{"version":3,"sources":["../src/adapters/ai/openai.ts","../src/adapters/store/pinecone.ts","../src/io/readers.ts","../src/util/chunker.ts","../src/util/hash.ts","../src/io/ingest.ts","../src/core/ContextWindow.ts","../src/core/registry.ts"],"names":["OpenAI","getClient","Pinecone","extname","readFile","pdf","createHash","path","stat","readdir","join","basename"],"mappings":"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","file":"index.cjs","sourcesContent":["import OpenAI from \"openai\";\nimport type { EmbedFn, ChatFn } from \"./types.js\";\n\n/**\n * Get OpenAI API key from environment\n * @throws Error if OPENAI_API_KEY is not set\n */\nfunction getOpenAIKey(): string {\n  const key = process.env.OPENAI_API_KEY;\n  if (!key) {\n    throw new Error(\n      \"OPENAI_API_KEY environment variable is required. Get your key from https://platform.openai.com/api-keys\"\n    );\n  }\n  return key;\n}\n\nlet openaiClient: OpenAI | null = null;\n\n/**\n * Get or create OpenAI client instance\n */\nfunction getClient(): OpenAI {\n  if (!openaiClient) {\n    openaiClient = new OpenAI({\n      apiKey: getOpenAIKey(),\n    });\n  }\n  return openaiClient;\n}\n\n/**\n * Create an embedding function using OpenAI's text-embedding-3-small model.\n * Returns 1536-dimensional vectors by default.\n *\n * @param model - The embedding model to use (default: \"text-embedding-3-small\")\n * @returns An embedding function\n *\n * @example\n * ```ts\n * const embed = createOpenAIEmbed();\n * const vectors = await embed([\"hello\", \"world\"]);\n * // vectors.length === 2, vectors[0].length === 1536\n * ```\n */\nexport function createOpenAIEmbed(\n  model = \"text-embedding-3-small\"\n): EmbedFn {\n  return async (texts: string[]): Promise<number[][]> => {\n    if (texts.length === 0) {\n      return [];\n    }\n\n    const client = getClient();\n\n    try {\n      const response = await client.embeddings.create({\n        model,\n        input: texts,\n      });\n\n      return response.data.map((item) => item.embedding);\n    } catch (error) {\n      throw new Error(`OpenAI embedding failed: ${error}`);\n    }\n  };\n}\n\n/**\n * Create a chat function using OpenAI's chat completion API.\n *\n * @returns A chat function\n *\n * @example\n * ```ts\n * const chat = createOpenAIChat();\n * const answer = await chat({\n *   model: \"gpt-4o-mini\",\n *   system: \"You are a helpful assistant.\",\n *   user: \"What is 2+2?\"\n * });\n * ```\n */\nexport function createOpenAIChat(): ChatFn {\n  return async ({ model, system, user }): Promise<string> => {\n    const client = getClient();\n\n    try {\n      const response = await client.chat.completions.create({\n        model,\n        messages: [\n          { role: \"system\", content: system },\n          { role: \"user\", content: user },\n        ],\n        temperature: 0.1, // Low temperature for more consistent, factual responses\n      });\n\n      return response.choices[0]?.message?.content || \"\";\n    } catch (error) {\n      throw new Error(`OpenAI chat completion failed: ${error}`);\n    }\n  };\n}\n\n","import { Pinecone } from \"@pinecone-database/pinecone\";\nimport type { UpsertFn, QueryFn, VectorRecord } from \"./types.js\";\n\n/**\n * Get Pinecone configuration from environment\n * @throws Error if required environment variables are not set\n */\nfunction getPineconeConfig(): {\n  apiKey: string;\n  indexName: string;\n  environment: string;\n} {\n  const apiKey = process.env.PINECONE_API_KEY;\n  const indexName = process.env.PINECONE_INDEX || \"context-window\";\n  const environment = process.env.PINECONE_ENVIRONMENT || \"us-east-1\";\n\n  if (!apiKey) {\n    throw new Error(\n      \"PINECONE_API_KEY environment variable is required. Get your key from https://app.pinecone.io/\"\n    );\n  }\n\n  return { apiKey, indexName, environment };\n}\n\nlet pineconeClient: Pinecone | null = null;\n\n/**\n * Get or create Pinecone client instance\n */\nfunction getClient(): Pinecone {\n  if (!pineconeClient) {\n    const { apiKey } = getPineconeConfig();\n    pineconeClient = new Pinecone({ apiKey });\n  }\n  return pineconeClient;\n}\n\n/**\n * Ensure a Pinecone index exists. Creates it if it doesn't exist.\n *\n * @param dimension - Vector dimension (default: 1536 for OpenAI embeddings)\n * @returns Promise that resolves when index is ready\n *\n * @example\n * ```ts\n * await ensurePineconeIndex(1536);\n * ```\n */\nexport async function ensurePineconeIndex(\n  dimension = 1536\n): Promise<void> {\n  const client = getClient();\n  const { indexName, environment } = getPineconeConfig();\n\n  try {\n    // Check if index exists\n    const indexes = await client.listIndexes();\n    const indexExists = indexes.indexes?.some(\n      (idx) => idx.name === indexName\n    );\n\n    if (!indexExists) {\n      // Create serverless index\n      await client.createIndex({\n        name: indexName,\n        dimension,\n        metric: \"cosine\",\n        spec: {\n          serverless: {\n            cloud: \"aws\",\n            region: environment,\n          },\n        },\n      });\n\n      // Wait for index to be ready\n      let ready = false;\n      let attempts = 0;\n      const maxAttempts = 30;\n\n      while (!ready && attempts < maxAttempts) {\n        const description = await client.describeIndex(indexName);\n        ready = description.status?.ready ?? false;\n\n        if (!ready) {\n          await new Promise((resolve) => setTimeout(resolve, 2000));\n          attempts++;\n        }\n      }\n\n      if (!ready) {\n        throw new Error(\n          `Index ${indexName} creation timed out after ${maxAttempts * 2} seconds`\n        );\n      }\n    }\n  } catch (error) {\n    throw new Error(`Failed to ensure Pinecone index: ${error}`);\n  }\n}\n\n/**\n * Create an upsert function for Pinecone.\n *\n * @returns An upsert function\n *\n * @example\n * ```ts\n * const upsert = createPineconeUpsert();\n * await upsert(records, \"my-namespace\");\n * ```\n */\nexport function createPineconeUpsert(): UpsertFn {\n  return async (records: VectorRecord[], namespace: string): Promise<void> => {\n    if (records.length === 0) {\n      return;\n    }\n\n    const client = getClient();\n    const { indexName } = getPineconeConfig();\n\n    try {\n      const index = client.index(indexName);\n\n      // Pinecone recommends batching upserts in chunks of 100\n      const batchSize = 100;\n      for (let i = 0; i < records.length; i += batchSize) {\n        const batch = records.slice(i, i + batchSize);\n        await index.namespace(namespace).upsert(batch);\n      }\n    } catch (error) {\n      throw new Error(`Pinecone upsert failed: ${error}`);\n    }\n  };\n}\n\n/**\n * Create a query function for Pinecone.\n *\n * @returns A query function\n *\n * @example\n * ```ts\n * const query = createPineconeQuery();\n * const matches = await query({\n *   vector: [0.1, 0.2, ...],\n *   topK: 5,\n *   namespace: \"my-namespace\",\n *   scoreThreshold: 0.7\n * });\n * ```\n */\nexport function createPineconeQuery(): QueryFn {\n  return async ({ vector, topK, namespace, scoreThreshold }) => {\n    const client = getClient();\n    const { indexName } = getPineconeConfig();\n\n    try {\n      const index = client.index(indexName);\n\n      const response = await index.namespace(namespace).query({\n        vector,\n        topK,\n        includeMetadata: true,\n      });\n\n      // Filter by score threshold and ensure metadata exists\n      const matches = (response.matches || [])\n        .filter((match) => match.score !== undefined && match.score >= scoreThreshold)\n        .map((match) => ({\n          id: match.id,\n          score: match.score!,\n          metadata: {\n            text: (match.metadata?.text as string) || \"\",\n            source: (match.metadata?.source as string) || \"\",\n          },\n        }));\n\n      return matches;\n    } catch (error) {\n      throw new Error(`Pinecone query failed: ${error}`);\n    }\n  };\n}\n\n","import { readFile } from \"fs/promises\";\nimport { extname } from \"path\";\nimport pdf from \"pdf-parse\";\n\n/**\n * Read a file and extract its text content based on file type.\n *\n * Supported formats:\n * - .txt: Plain text\n * - .md: Markdown\n * - .pdf: PDF documents\n *\n * @param filepath - Path to the file to read\n * @returns Promise resolving to the extracted text\n * @throws Error if file type is unsupported or file cannot be read\n *\n * @example\n * ```ts\n * const text = await readAsText(\"./document.pdf\");\n * console.log(text);\n * ```\n */\nexport async function readAsText(filepath: string): Promise<string> {\n  const ext = extname(filepath).toLowerCase();\n\n  try {\n    switch (ext) {\n      case \".txt\":\n      case \".md\": {\n        const content = await readFile(filepath, \"utf-8\");\n        return content;\n      }\n\n      case \".pdf\": {\n        const dataBuffer = await readFile(filepath);\n        const pdfData = await pdf(dataBuffer);\n        return pdfData.text;\n      }\n\n      default:\n        throw new Error(\n          `Unsupported file type: ${ext}. Supported types: .txt, .md, .pdf`\n        );\n    }\n  } catch (error) {\n    if (error instanceof Error && error.message.includes(\"Unsupported\")) {\n      throw error;\n    }\n    throw new Error(`Failed to read file ${filepath}: ${error}`);\n  }\n}\n\n/**\n * Check if a file is supported based on its extension.\n *\n * @param filepath - Path to check\n * @returns True if the file type is supported\n *\n * @example\n * ```ts\n * if (isSupportedFile(\"doc.pdf\")) {\n *   // Process file\n * }\n * ```\n */\nexport function isSupportedFile(filepath: string): boolean {\n  const ext = extname(filepath).toLowerCase();\n  return [\".txt\", \".md\", \".pdf\"].includes(ext);\n}\n\n","/**\n * Chunk configuration\n */\nexport interface ChunkOptions {\n  size: number;\n  overlap: number;\n}\n\n/**\n * Split text into overlapping chunks using a sliding window approach.\n *\n * @param text - The text to chunk\n * @param options - Chunking options (size and overlap)\n * @returns Array of text chunks\n *\n * @example\n * ```ts\n * const chunks = chunkText(\"Long document text...\", { size: 1000, overlap: 150 });\n * // Returns array of overlapping text chunks\n * ```\n */\nexport function chunkText(\n  text: string,\n  options: ChunkOptions = { size: 1000, overlap: 150 }\n): string[] {\n  const { size, overlap } = options;\n\n  // Handle empty or very short text\n  if (!text || text.length === 0) {\n    return [];\n  }\n\n  if (text.length <= size) {\n    return [text];\n  }\n\n  const chunks: string[] = [];\n  let start = 0;\n\n  while (start < text.length) {\n    const end = start + size;\n    const chunk = text.slice(start, end);\n    chunks.push(chunk);\n\n    // If we've reached the end, break\n    if (end >= text.length) {\n      break;\n    }\n\n    // Move forward by (size - overlap) to create overlapping chunks\n    start += size - overlap;\n  }\n\n  return chunks;\n}\n\n","import { createHash } from \"crypto\";\n\n/**\n * Generate a stable SHA-1 hash for a given string.\n * Used for creating idempotent chunk IDs.\n *\n * @param input - The string to hash\n * @returns The hexadecimal hash string\n *\n * @example\n * ```ts\n * const id = stableHash(\"my-file.txt#0:first 64 chars...\");\n * // => \"a1b2c3d4e5f6...\"\n * ```\n */\nexport function stableHash(input: string): string {\n  return createHash(\"sha1\").update(input, \"utf8\").digest(\"hex\");\n}\n\n","import { stat, readdir } from \"fs/promises\";\nimport { join, basename } from \"path\";\nimport { readAsText, isSupportedFile } from \"./readers.js\";\nimport { chunkText } from \"../util/chunker.js\";\nimport { stableHash } from \"../util/hash.js\";\nimport type { EmbedFn } from \"../adapters/ai/types.js\";\nimport type { UpsertFn, VectorRecord } from \"../adapters/store/types.js\";\n\n/**\n * Options for ingestion\n */\nexport interface IngestOptions {\n  /** Input paths (files or directories) */\n  inputs: string[];\n  /** Vector store namespace */\n  namespace: string;\n  /** Chunk size */\n  chunkSize: number;\n  /** Chunk overlap */\n  chunkOverlap: number;\n  /** Embedding function */\n  embed: EmbedFn;\n  /** Upsert function */\n  upsert: UpsertFn;\n}\n\n/**\n * Recursively collect all supported files from input paths.\n *\n * @param paths - Array of file or directory paths\n * @returns Array of file paths\n */\nasync function collectFiles(paths: string[]): Promise<string[]> {\n  const files: string[] = [];\n\n  for (const path of paths) {\n    const stats = await stat(path);\n\n    if (stats.isFile()) {\n      if (isSupportedFile(path)) {\n        files.push(path);\n      }\n    } else if (stats.isDirectory()) {\n      const entries = await readdir(path, { withFileTypes: true });\n\n      for (const entry of entries) {\n        const fullPath = join(path, entry.name);\n\n        if (entry.isDirectory()) {\n          // Recursively process subdirectories\n          const subFiles = await collectFiles([fullPath]);\n          files.push(...subFiles);\n        } else if (entry.isFile() && isSupportedFile(fullPath)) {\n          files.push(fullPath);\n        }\n      }\n    }\n  }\n\n  return files;\n}\n\n/**\n * Ingest files into the vector store.\n *\n * This function:\n * 1. Recursively collects all supported files from input paths\n * 2. Reads and chunks each file\n * 3. Generates stable IDs for idempotent ingestion\n * 4. Embeds chunks in batches\n * 5. Upserts to the vector store\n *\n * @param options - Ingestion options\n * @returns Promise that resolves when ingestion is complete\n *\n * @example\n * ```ts\n * await ingestPaths({\n *   inputs: [\"./docs\"],\n *   namespace: \"my-project\",\n *   chunkSize: 1000,\n *   chunkOverlap: 150,\n *   embed: embedFn,\n *   upsert: upsertFn\n * });\n * ```\n */\nexport async function ingestPaths(options: IngestOptions): Promise<void> {\n  const { inputs, namespace, chunkSize, chunkOverlap, embed, upsert } = options;\n\n  // Collect all files\n  const files = await collectFiles(inputs);\n\n  if (files.length === 0) {\n    console.warn(\"No supported files found to ingest\");\n    return;\n  }\n\n  console.log(`Ingesting ${files.length} file(s)...`);\n\n  // Process each file\n  const allRecords: VectorRecord[] = [];\n\n  for (const filepath of files) {\n    try {\n      // Read file content\n      const text = await readAsText(filepath);\n\n      if (!text || text.trim().length === 0) {\n        console.warn(`Skipping empty file: ${filepath}`);\n        continue;\n      }\n\n      // Chunk the text\n      const chunks = chunkText(text, { size: chunkSize, overlap: chunkOverlap });\n\n      // Create records with stable IDs\n      const source = basename(filepath);\n\n      for (let i = 0; i < chunks.length; i++) {\n        const chunk = chunks[i];\n        // Use first 64 chars for ID stability\n        const preview = chunk.slice(0, 64).replace(/\\s+/g, \" \");\n        const id = stableHash(`${filepath}#${i}:${preview}`);\n\n        // Note: embeddings will be added in batch below\n        allRecords.push({\n          id,\n          values: [], // Placeholder, will be filled after embedding\n          metadata: {\n            text: chunk,\n            source,\n          },\n        });\n      }\n    } catch (error) {\n      console.error(`Failed to process ${filepath}:`, error);\n      // Continue with other files\n    }\n  }\n\n  if (allRecords.length === 0) {\n    console.warn(\"No chunks generated from files\");\n    return;\n  }\n\n  console.log(`Generated ${allRecords.length} chunk(s), embedding...`);\n\n  // Embed in batches of 100 (to manage rate limits)\n  const batchSize = 100;\n  for (let i = 0; i < allRecords.length; i += batchSize) {\n    const batch = allRecords.slice(i, i + batchSize);\n    const texts = batch.map((r) => r.metadata.text);\n\n    try {\n      const embeddings = await embed(texts);\n\n      // Assign embeddings to records\n      for (let j = 0; j < batch.length; j++) {\n        batch[j].values = embeddings[j];\n      }\n    } catch (error) {\n      throw new Error(`Embedding batch failed: ${error}`);\n    }\n  }\n\n  console.log(`Upserting ${allRecords.length} chunk(s) to vector store...`);\n\n  // Upsert to vector store (the upsert function handles batching internally)\n  await upsert(allRecords, namespace);\n\n  console.log(\"Ingestion complete!\");\n}\n\n","import type {\n  CreateContextWindowOptions,\n  ContextWindow,\n  AskResult,\n  NormalizedOptions,\n} from \"../types.js\";\nimport { createOpenAIEmbed, createOpenAIChat } from \"../adapters/ai/openai.js\";\nimport {\n  ensurePineconeIndex,\n  createPineconeUpsert,\n  createPineconeQuery,\n} from \"../adapters/store/pinecone.js\";\nimport { ingestPaths } from \"../io/ingest.js\";\n\n/**\n * Normalize and validate options with defaults\n */\nfunction normalizeOptions(opts: CreateContextWindowOptions): NormalizedOptions {\n  const dataPaths = Array.isArray(opts.data) ? opts.data : [opts.data];\n  const aiModel = opts.ai?.model || \"gpt-4o-mini\";\n  const namespace = opts.vectorStore?.namespace || opts.namespace;\n  const chunkSize = opts.chunk?.size || 1000;\n  const chunkOverlap = opts.chunk?.overlap || 150;\n  const topK = opts.limits?.topK || 8;\n  const maxContextChars = opts.limits?.maxContextChars || 8000;\n  const scoreThreshold = opts.limits?.scoreThreshold || 0;\n\n  if (!namespace) {\n    throw new Error(\"namespace is required\");\n  }\n\n  if (dataPaths.length === 0) {\n    throw new Error(\"at least one data path is required\");\n  }\n\n  return {\n    namespace,\n    dataPaths,\n    aiModel,\n    chunkSize,\n    chunkOverlap,\n    topK,\n    maxContextChars,\n    scoreThreshold,\n  };\n}\n\n/**\n * Pack context from query matches, respecting maxContextChars limit.\n * Returns the packed context text and unique source filenames.\n */\nfunction packContext(\n  matches: Array<{ metadata: { text: string; source: string } }>,\n  maxContextChars: number\n): { context: string; sources: string[] } {\n  const chunks: string[] = [];\n  const sources: string[] = [];\n  const seenSources = new Set<string>();\n  let totalChars = 0;\n\n  for (const match of matches) {\n    const chunk = match.metadata.text;\n    const source = match.metadata.source;\n\n    // Check if adding this chunk would exceed the limit\n    if (totalChars + chunk.length > maxContextChars) {\n      break;\n    }\n\n    chunks.push(chunk);\n    totalChars += chunk.length;\n\n    // Track unique sources in order of appearance\n    if (!seenSources.has(source)) {\n      sources.push(source);\n      seenSources.add(source);\n    }\n  }\n\n  return {\n    context: chunks.join(\"\\n\\n---\\n\\n\"),\n    sources,\n  };\n}\n\n/**\n * Build the system prompt for strict RAG\n */\nfunction buildSystemPrompt(context: string): string {\n  return `You are a strict RAG assistant.\n\nAnswer ONLY using the provided context. If not fully supported,\nsay: \"I don't know based on the uploaded files.\"\nCite sources like [filename]. Keep answers concise.\n\nContext:\n${context}`;\n}\n\n/**\n * Create a context window instance without ingesting data.\n * This is useful for connecting to an existing Pinecone namespace.\n *\n * @param namespace - The namespace name\n * @param options - Optional configuration overrides\n * @returns A ContextWindow instance\n *\n * @internal\n */\nexport function createContextWindowWithoutIngestion(\n  namespace: string,\n  options?: {\n    aiModel?: string;\n    namespace?: string;\n    topK?: number;\n    maxContextChars?: number;\n    scoreThreshold?: number;\n  }\n): ContextWindow {\n  const config = {\n    aiModel: options?.aiModel || \"gpt-4o-mini\",\n    namespace: options?.namespace || namespace,\n    topK: options?.topK || 8,\n    maxContextChars: options?.maxContextChars || 8000,\n    scoreThreshold: options?.scoreThreshold || 0,\n  };\n\n  // Create adapter functions\n  const embed = createOpenAIEmbed();\n  const chat = createOpenAIChat();\n  const query = createPineconeQuery();\n\n  // Return ContextWindow instance\n  return {\n    async ask(question: string): Promise<AskResult> {\n      // Embed the question\n      const [questionVector] = await embed([question]);\n\n      // Query the vector store\n      const matches = await query({\n        vector: questionVector,\n        topK: config.topK,\n        namespace: config.namespace,\n        scoreThreshold: config.scoreThreshold,\n      });\n\n      // Pack context and extract sources\n      const { context, sources } = packContext(matches, config.maxContextChars);\n\n      // If no context found, return \"I don't know\"\n      if (!context || context.trim().length === 0) {\n        return {\n          text: \"I don't know based on the uploaded files.\",\n          sources: [],\n        };\n      }\n\n      // Build system prompt\n      const systemPrompt = buildSystemPrompt(context);\n\n      // Get answer from AI\n      const answer = await chat({\n        model: config.aiModel,\n        system: systemPrompt,\n        user: question,\n      });\n\n      return {\n        text: answer,\n        sources,\n      };\n    },\n  };\n}\n\n/**\n * Create a context window instance.\n *\n * This is the main entry point for the library. It:\n * 1. Validates and normalizes options\n * 2. Ensures the Pinecone index exists\n * 3. Ingests the provided data files\n * 4. Returns an object with an ask() method for querying\n *\n * @param opts - Configuration options\n * @returns Promise resolving to a ContextWindow instance\n *\n * @example\n * ```ts\n * const cw = await createContextWindow({\n *   namespace: \"my-book\",\n *   data: [\"./my-book.pdf\"],\n *   ai: { provider: \"openai\", model: \"gpt-4o-mini\" },\n *   vectorStore: { provider: \"pinecone\" }\n * });\n *\n * const { text, sources } = await cw.ask(\"When was America founded?\");\n * console.log(text, sources);\n * ```\n */\nexport async function createContextWindow(\n  opts: CreateContextWindowOptions\n): Promise<ContextWindow> {\n  // Normalize options with defaults\n  const config = normalizeOptions(opts);\n\n  // Create adapter functions\n  const embed = createOpenAIEmbed();\n  const chat = createOpenAIChat();\n  const upsert = createPineconeUpsert();\n  const query = createPineconeQuery();\n\n  // Ensure Pinecone index exists (1536 dims for OpenAI embeddings)\n  await ensurePineconeIndex(1536);\n\n  // Ingest data\n  await ingestPaths({\n    inputs: config.dataPaths,\n    namespace: config.namespace,\n    chunkSize: config.chunkSize,\n    chunkOverlap: config.chunkOverlap,\n    embed,\n    upsert,\n  });\n\n  // Return ContextWindow instance\n  return {\n    async ask(question: string): Promise<AskResult> {\n      // Embed the question\n      const [questionVector] = await embed([question]);\n\n      // Query the vector store\n      const matches = await query({\n        vector: questionVector,\n        topK: config.topK,\n        namespace: config.namespace,\n        scoreThreshold: config.scoreThreshold,\n      });\n\n      // Pack context and extract sources\n      const { context, sources } = packContext(matches, config.maxContextChars);\n\n      // If no context found, return \"I don't know\"\n      if (!context || context.trim().length === 0) {\n        return {\n          text: \"I don't know based on the uploaded files.\",\n          sources: [],\n        };\n      }\n\n      // Build system prompt\n      const systemPrompt = buildSystemPrompt(context);\n\n      // Get answer from AI\n      const answer = await chat({\n        model: config.aiModel,\n        system: systemPrompt,\n        user: question,\n      });\n\n      return {\n        text: answer,\n        sources,\n      };\n    },\n  };\n}\n","import type { ContextWindow, CreateContextWindowOptions } from \"../types.js\";\nimport {\n  createContextWindow,\n  createContextWindowWithoutIngestion,\n} from \"./ContextWindow.js\";\n\n/**\n * Global registry to store context windows by namespace\n */\nconst registry = new Map<string, ContextWindow>();\n\n/**\n * Default options for getCtxWindow when connecting to existing namespace\n */\nexport interface GetContextWindowOptions {\n  aiModel?: string;\n  namespace?: string;\n  topK?: number;\n  maxContextChars?: number;\n  scoreThreshold?: number;\n}\n\n/**\n * Create a context window and register it with the given namespace.\n * The context window can later be retrieved using getCtxWindow.\n *\n * @param opts - Configuration options including namespace\n * @returns Promise resolving to the created ContextWindow instance\n *\n * @example\n * ```ts\n * await createCtxWindow({\n *   namespace: \"american-history\",\n *   data: [\"./examples/sample/README.md\"],\n *   ai: { provider: \"openai\", model: \"gpt-4o-mini\" },\n *   vectorStore: { provider: \"pinecone\" }\n * });\n *\n * // Later, retrieve and use it\n * const cw = getCtxWindow(\"american-history\");\n * const result = await cw.ask(\"When was America founded?\");\n * ```\n */\nexport async function createCtxWindow(\n  opts: CreateContextWindowOptions\n): Promise<ContextWindow> {\n  const cw = await createContextWindow(opts);\n  registry.set(opts.namespace, cw);\n  return cw;\n}\n\n/**\n * Retrieve or create a context window by its namespace.\n *\n * If the context window is already in the registry, returns it immediately.\n * Otherwise, creates a new connection to the Pinecone namespace with the given name.\n * This allows you to reconnect to existing data without calling createCtxWindow.\n *\n * @param namespace - The namespace of the context window to retrieve\n * @param options - Optional configuration overrides\n * @returns The ContextWindow instance\n *\n * @example\n * ```ts\n * // Connect to existing Pinecone namespace\n * const cw = getCtxWindow(\"american-history\");\n * const result = await cw.ask(\"When was America founded?\");\n *\n * // With custom options\n * const cw2 = getCtxWindow(\"my-docs\", { topK: 10, aiModel: \"gpt-4\" });\n * ```\n */\nexport function getCtxWindow(\n  namespace: string,\n  options?: GetContextWindowOptions\n): ContextWindow {\n  // Check if already in registry\n  let cw = registry.get(namespace);\n\n  if (!cw) {\n    // Create a new connection to the existing Pinecone namespace\n    cw = createContextWindowWithoutIngestion(namespace, options);\n    registry.set(namespace, cw);\n  }\n\n  return cw;\n}\n\n/**\n * Check if a context window with the given namespace exists in the registry.\n *\n * @param namespace - The namespace to check\n * @returns true if the context window exists, false otherwise\n */\nexport function hasCtxWindow(namespace: string): boolean {\n  return registry.has(namespace);\n}\n\n/**\n * Remove a context window from the registry.\n *\n * @param namespace - The namespace of the context window to remove\n * @returns true if removed, false if it didn't exist\n */\nexport function deleteCtxWindow(namespace: string): boolean {\n  return registry.delete(namespace);\n}\n\n/**\n * Clear all context windows from the registry.\n */\nexport function clearCtxWindows(): void {\n  registry.clear();\n}\n\n/**\n * Get all registered context window namespaces.\n *\n * @returns Array of namespace names\n */\nexport function listCtxWindows(): string[] {\n  return Array.from(registry.keys());\n}\n\n"]}