bunnyquery 1.8.0 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bunnyquery.js +455 -43
- package/dist/engine.cjs +489 -33
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.mts +232 -3
- package/dist/engine.d.ts +232 -3
- package/dist/engine.mjs +462 -34
- package/dist/engine.mjs.map +1 -1
- package/package.json +1 -1
- package/src/engine/ai_agent.ts +80 -0
- package/src/engine/budget.ts +113 -7
- package/src/engine/download_encoding.ts +281 -0
- package/src/engine/errors.ts +34 -0
- package/src/engine/history.ts +48 -18
- package/src/engine/index.ts +11 -0
- package/src/engine/requests.ts +15 -3
- package/src/engine/session.ts +227 -6
package/dist/engine.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine/attachment_parsers.ts","../src/engine/config.ts","../src/engine/office.ts","../src/engine/attachments.ts","../src/engine/prompts/chat_system_prompt.ts","../src/engine/prompts/indexing_system_prompt.ts","../src/engine/prompts/indexing_user_message.ts","../src/engine/errors.ts","../src/engine/links.ts","../src/engine/budget.ts","../src/engine/time.ts","../src/engine/requests.ts","../src/engine/history.ts","../src/engine/viewport_fill.ts","../src/engine/session.ts","../src/engine/indexing_groups.ts"],"names":["remotePath","i","resolvedModel"],"mappings":"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","file":"engine.mjs","sourcesContent":["/**\n * Client-side attachment-parser plugins.\n *\n * Some attachment formats can't be read by the model's web_fetch (binary) and\n * have no server-side extractor either — e.g. legacy Hancom .hwp. A parser\n * plugin runs IN THE BROWSER, turns the uploaded File into indexable text (or an\n * HTML string), and the engine sends that content INLINE in the background\n * indexing request — so the model indexes the parsed content directly, with no\n * upload-side server extraction and no web_fetch for that file.\n *\n * Register a parser with `registerAttachmentParser()`, or via\n * `configureChatEngine({ attachmentParsers: [...] })`. The BunnyQuery widget also\n * exposes `BunnyQuery.registerAttachmentParser()` and an `attachmentParsers`\n * init option. First matching parser wins.\n */\n\nexport interface AttachmentParser {\n\t/** Human-readable label — used only in logs. */\n\tname?: string;\n\t/**\n\t * Return true if this parser handles the file. Receives the file name and\n\t * (when known) its MIME type. Keep it cheap — it runs for every upload.\n\t */\n\tmatch: (file: { name: string; mime?: string }) => boolean;\n\t/**\n\t * Parse the File into indexable plain text OR an HTML string (the model reads\n\t * either). Runs in the browser; may be async. Return a falsy/empty value to\n\t * skip (the file then falls back to web_fetch / server extraction).\n\t */\n\tparse: (\n\t\tfile: File,\n\t) => string | null | undefined | Promise<string | null | undefined>;\n}\n\n// Hard ceiling on inlined parsed content (characters), mirroring the worker's\n// server-side MAX_EXTRACTED_CHARS, so a huge document can't blow the model's\n// context window or the request size.\nexport const MAX_PARSED_CONTENT_CHARS = 200_000;\n\nconst _parsers: AttachmentParser[] = [];\n\n/** Register an attachment parser. Ignores duplicates (by reference) and invalid plugins. */\nexport function registerAttachmentParser(parser: AttachmentParser): void {\n\tif (\n\t\tparser &&\n\t\ttypeof parser.match === 'function' &&\n\t\ttypeof parser.parse === 'function' &&\n\t\t_parsers.indexOf(parser) === -1\n\t) {\n\t\t_parsers.push(parser);\n\t}\n}\n\n/** Remove all registered parsers (mainly for tests / re-init). */\nexport function clearAttachmentParsers(): void {\n\t_parsers.length = 0;\n}\n\n/** Snapshot of the registered parsers. */\nexport function getAttachmentParsers(): AttachmentParser[] {\n\treturn _parsers.slice();\n}\n\n/** First parser whose `match` returns true for the given file, if any. */\nexport function findAttachmentParser(\n\tname: string,\n\tmime?: string,\n): AttachmentParser | undefined {\n\tfor (let i = 0; i < _parsers.length; i++) {\n\t\ttry {\n\t\t\tif (_parsers[i].match({ name: name, mime: mime })) return _parsers[i];\n\t\t} catch {\n\t\t\t/* a throwing matcher must not break uploads */\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Run the matching parser (if any) and return capped, trimmed content — or null\n * when there is no parser, the parser throws, or it yields nothing. Never throws:\n * a parser failure degrades to null so the upload still completes (the file then\n * resolves via its normal path).\n */\nexport async function parseAttachmentContent(\n\tfile: File,\n\tname: string,\n\tmime?: string,\n): Promise<string | null> {\n\tconst parser = findAttachmentParser(name, mime);\n\tif (!parser) return null;\n\n\tlet raw: string | null | undefined;\n\ttry {\n\t\traw = await parser.parse(file);\n\t} catch (err) {\n\t\tconsole.error(\n\t\t\t`[chat-engine] attachment parser ${parser.name || '(unnamed)'} failed for ${name}:`,\n\t\t\terr,\n\t\t);\n\t\treturn null;\n\t}\n\n\tlet text = (raw == null ? '' : String(raw)).trim();\n\tif (!text) return null;\n\tif (text.length > MAX_PARSED_CONTENT_CHARS) {\n\t\ttext =\n\t\t\ttext.slice(0, MAX_PARSED_CONTENT_CHARS) +\n\t\t\t`\\n...[truncated for length; original ${text.length} characters]`;\n\t}\n\treturn text;\n}\n","/**\n * Engine configuration / dependency injection.\n *\n * The engine is framework- and transport-agnostic: it never imports a skapi\n * instance or `import.meta.env`. Each consumer calls `configureChatEngine()`\n * once at startup to inject the skapi transport functions, the MCP base URL,\n * and (optionally) the `poll` value to attach to clientSecretRequest.\n *\n * Why `poll` is configurable: agent.vue uses the npm-bundled skapi-js and OMITS\n * `poll` (its clientSecretRequest auto-resolves with the final body), whereas\n * the BunnyQuery widget uses the deployed skapi-js@latest and must pass\n * `poll: 0` to get the early ack + a manual `.poll()` handle (needed for queued-\n * send cancel). So the request builders include `poll` only when it is set.\n */\n\nimport { type AttachmentParser, registerAttachmentParser } from './attachment_parsers';\n\nexport interface ChatEngineConfig {\n /** skapi.clientSecretRequest, bound to the consumer's skapi instance. */\n clientSecretRequest: (opts: any) => Promise<any>;\n /** skapi.clientSecretRequestHistory, bound to the consumer's skapi instance. */\n clientSecretRequestHistory: (params: any, fetchOptions: any) => Promise<any>;\n /** MCP server base URL (prod vs dev resolved by the consumer). */\n mcpBaseUrl: string;\n /**\n * Value to attach as `poll` on every clientSecretRequest. When `undefined`\n * the `poll` key is omitted entirely (agent.vue). BunnyQuery sets `0`.\n */\n poll?: number;\n /**\n * Optional client-side attachment parsers (e.g. an .hwp parser). Each is\n * registered at configure time; more can be added later via\n * `registerAttachmentParser()`. See attachment_parsers.ts.\n */\n attachmentParsers?: AttachmentParser[];\n /**\n * Opt in to SERVER-DRIVEN windowed indexing for text/grid files.\n *\n * Off by default, and deliberately so. When on, the client emits a\n * `_skapi_window` directive and the WORKER reads the file one window at a time,\n * continuing until the reader says it is exhausted. When off, the agent pages the\n * file itself with readFileContent, exactly as before.\n *\n * The flag exists because the backend must ship FIRST: a client emitting the\n * directive against a worker that does not strip it leaves an unknown field in the\n * request body, and the provider rejects the whole call with no retry. Keep it off\n * until the worker is deployed, then flip it per environment.\n */\n windowedIndexing?: boolean;\n}\n\nlet _config: ChatEngineConfig | null = null;\n\nexport function configureChatEngine(config: ChatEngineConfig): void {\n _config = config;\n if (config.attachmentParsers) {\n for (const parser of config.attachmentParsers) registerAttachmentParser(parser);\n }\n}\n\nexport function chatEngineConfig(): ChatEngineConfig {\n if (!_config) {\n throw new Error(\n '[chat-engine] configureChatEngine() must be called before using the engine.',\n );\n }\n return _config;\n}\n\n/** True when the consumer has opted in to server-driven windowed indexing. */\nexport function windowedIndexingEnabled(): boolean {\n return _config?.windowedIndexing === true;\n}\n\n/** Spread helper: `{ ...pollOpt() }` adds `poll` only when configured. */\nexport function pollOpt(): { poll?: number } {\n const p = _config?.poll;\n return p === undefined ? {} : { poll: p };\n}\n","/**\n * Office-file server-side extraction helpers.\n *\n * Office documents (Microsoft .docx/.xlsx/.pptx, Hancom .hwpx, etc.) can't be\n * read by web_fetch (binary/zip). The proxy worker downloads them from db\n * storage, extracts their text server-side, and substitutes that text for a\n * placeholder token in the request body (carried under the reserved\n * `_skapi_extract` key, which the producer strips before the upstream call).\n */\n\n// A directive telling the proxy worker which office file to download + extract\n// and which placeholder token in the request body to substitute.\nexport type ExtractDirective = {\n\t/** db storage path of the file, e.g. \"folder/report.docx\" (also the src:: value). */\n\tpath: string;\n\t/** The exact token in the request body to replace with the extracted text. */\n\tplaceholder: string;\n\t/** Original filename — informational (server logs only). */\n\tname?: string;\n\t/** MIME type — informational (server logs only). */\n\tmime?: string;\n};\n\n// A directive telling the proxy worker to re-mint a fresh, short-lived URL for a\n// file the model fetches by url (PDFs, images — anything NOT server-extractable)\n// right before the upstream call, so a queued request never hands the model a\n// stale link. The worker mints from `path` and swaps `url` (the exact baked url\n// string) everywhere it appears in the request body.\nexport type FileUrlDirective = {\n\t/** db storage path of the file, e.g. \"folder/report.pdf\" (also the src:: value). */\n\tpath: string;\n\t/** The exact baked url string in the request body to replace with a fresh one. */\n\turl: string;\n};\n\n// Files whose text the worker extracts SERVER-SIDE and inlines for indexing,\n// instead of handing the agent a URL to fetch. Two groups:\n// (1) BINARY document formats the model can't read at all (OOXML, Hancom\n// HWP/HWPX, OpenDocument, EPUB) — the worker parses them.\n// (2) TEXT/data/markup/code formats. These ARE readable via web_fetch, BUT\n// some providers (OpenAI's Responses API) have no working file-fetch tool,\n// so the agent can't retrieve the URL at all. Extracting them server-side\n// (the worker just decodes the bytes) makes indexing provider-independent.\nconst OFFICE_FILE_EXTENSIONS = new Set([\n\t'doc', 'docx', 'docm',\n\t'xls', 'xlsx', 'xlsm',\n\t'ppt', 'pptx', 'pptm',\n\t'hwp', 'hwpx',\n\t'ods', 'odt', 'odp',\n\t'epub',\n]);\n\nconst TEXT_FILE_EXTENSIONS = new Set([\n\t'csv', 'tsv', 'tab', 'txt', 'text', 'log', 'md', 'markdown', 'rst',\n\t'json', 'ndjson', 'jsonl', 'geojson', 'xml', 'yaml', 'yml', 'toml',\n\t'ini', 'conf', 'cfg', 'properties', 'env', 'rtf', 'html', 'htm',\n\t'js', 'mjs', 'cjs', 'ts', 'tsx', 'jsx', 'py', 'rb', 'go', 'rs', 'java',\n\t'kt', 'c', 'h', 'cpp', 'cc', 'hpp', 'cs', 'php', 'swift', 'sh', 'bash',\n\t'zsh', 'sql', 'css', 'scss', 'less', 'vue', 'svelte', 'tex', 'srt', 'vtt',\n]);\n\n// MIME types that indicate decodable text even when the extension is unknown\n// (the worker has the same fallback, so any text/* file is extracted server-side).\nfunction isTextMime(m: string): boolean {\n\treturn (\n\t\tm.startsWith('text/') ||\n\t\tm.endsWith('+json') || m.endsWith('+xml') || m.endsWith('+yaml') ||\n\t\tm === 'application/json' || m === 'application/ld+json' ||\n\t\tm === 'application/xml' || m === 'application/yaml' || m === 'application/x-yaml' ||\n\t\tm === 'application/javascript' || m === 'application/x-javascript' ||\n\t\tm === 'application/x-sh' || m === 'application/x-ndjson' ||\n\t\tm === 'application/csv' || m === 'application/rtf' ||\n\t\tm === 'application/sql' || m === 'application/toml'\n\t);\n}\n\n/**\n * True when a file should be EXTRACTED SERVER-SIDE (text inlined for indexing)\n * rather than handed to the agent as a URL to fetch — i.e. binary office\n * documents AND all text/data/code files. Detection is extension-first (so a\n * .csv reported as an Office MIME is still treated as text), with a text-MIME\n * fallback for unlisted extensions.\n */\nexport function isServerExtractable(name?: string, mime?: string): boolean {\n\tconst ext = (name || '').split('.').pop()?.toLowerCase() || '';\n\tif (OFFICE_FILE_EXTENSIONS.has(ext)) return true;\n\tif (TEXT_FILE_EXTENSIONS.has(ext)) return true;\n\tconst m = (mime || '').toLowerCase();\n\tif (isTextMime(m)) return true;\n\treturn (\n\t\tm.includes('officedocument') ||\n\t\tm.includes('opendocument') ||\n\t\tm.includes('hwp') ||\n\t\tm.includes('epub') ||\n\t\tm === 'application/msword' ||\n\t\tm === 'application/vnd.ms-excel' ||\n\t\tm === 'application/vnd.ms-powerpoint'\n\t);\n}\n\n/** @deprecated renamed to {@link isServerExtractable} (now also covers text files). */\nexport const isOfficeFile = isServerExtractable;\n\n// Extensions read WINDOW-BY-WINDOW via the readFileContent tool instead of inlined once.\n//\n// Anything NOT in this set falls back to one-shot server extraction, which is capped at\n// MAX_EXTRACTED_CHARS (200k). Measured against real files, that cap was discarding the\n// overwhelming majority of every large non-spreadsheet upload:\n// 5MB .txt -> 4.0% indexed (4.8M characters silently dropped)\n// 4.8MB .json-> 4.2%\n// 1.9M-char Korean .txt -> 10.5%\n// .docx -> 70.6%\n// The truncation was invisible: the agent received a plausible-looking document and had\n// no way to know most of it was missing. Windowing these types is what makes \"index the\n// whole file\" true rather than aspirational.\n//\n// CSV/TSV specifically must be here rather than in the inline path: the layer now gives\n// them ROW-bounded windows with absolute row numbers, where the character windower used\n// to split rows across boundaries and emit no row numbers at all.\nconst PAGED_READ_EXTENSIONS = new Set([\n\t// grids\n\t'xls', 'xlsx', 'xlsm', 'ods',\n\t// delimited text (row-windowed by the layer)\n\t'csv', 'tsv', 'tab',\n\t// documents\n\t'pdf', 'docx', 'pptx',\n\t// plain text / data / markup\n\t'txt', 'md', 'markdown', 'log', 'json', 'jsonl', 'ndjson', 'xml', 'yaml', 'yml',\n]);\n\n/**\n * True when a file should be indexed by PAGING through readFileContent (spreadsheets and\n * PDFs), rather than inline extraction or a web_fetch URL. This is what lets a huge sheet\n * be read row-window by row-window and a scanned PDF be read page-image by page-image,\n * with embedded photos delivered to the vision model.\n */\nexport function isPagedReadFile(name?: string, mime?: string): boolean {\n\tconst ext = (name || '').split('.').pop()?.toLowerCase() || '';\n\tif (PAGED_READ_EXTENSIONS.has(ext)) return true;\n\tconst m = (mime || '').toLowerCase();\n\treturn (\n\t\tm === 'application/pdf' ||\n\t\tm === 'application/vnd.ms-excel' ||\n\t\tm.includes('spreadsheetml') ||\n\t\tm.includes('opendocument.spreadsheet')\n\t);\n}\n\n/**\n * True for files whose content is VISUAL and must be delivered to the model as IMAGE\n * BLOCKS in the message (rendered pages), because tool-result images render on neither\n * provider. The worker renders a page window to image URLs and injects them (`_skapi_render`\n * directive). Currently PDFs (scanned or not); indexed page-window by page-window with\n * resume advancing the window.\n */\nexport function isImageVisionFile(name?: string, mime?: string): boolean {\n\tconst ext = (name || '').split('.').pop()?.toLowerCase() || '';\n\treturn ext === 'pdf' || (mime || '').toLowerCase() === 'application/pdf';\n}\n\n// Monotonic counter so placeholders are unique even for same-named files in one\n// request. Token shape must match the worker's _EXTRACT_PLACEHOLDER_RE:\n// {{SKAPI_FILE_CONTENT::<id>}}.\nlet _extractPlaceholderSeq = 0;\nexport function makeExtractPlaceholder(seed: string): string {\n\t_extractPlaceholderSeq += 1;\n\tconst slug = (seed || 'file').replace(/[^a-zA-Z0-9]+/g, '_').slice(-48);\n\treturn `{{SKAPI_FILE_CONTENT::${slug}-${_extractPlaceholderSeq}}}`;\n}\n\n// Placeholder marking WHERE the worker injects a window of rendered page/photo IMAGE blocks\n// (the `_skapi_render` directive). Distinct token from the text-extraction placeholder.\nlet _renderPlaceholderSeq = 0;\nexport function makeRenderPlaceholder(seed: string): string {\n\t_renderPlaceholderSeq += 1;\n\tconst slug = (seed || 'file').replace(/[^a-zA-Z0-9]+/g, '_').slice(-48);\n\treturn `{{SKAPI_RENDER::${slug}-${_renderPlaceholderSeq}}}`;\n}\n\n// Page/photo images per render window. Must match the server default so the client's\n// resume window (from = pass * PAGES) lines up with what the worker renders.\nexport const RENDER_PAGES_PER_WINDOW = 5;\n\n// Token the WORKER substitutes with a human description of the next window's position.\n// Shared with the render loop so one substitution path serves both.\nexport const WINDOW_CURSOR_TOKEN = '{{RENDER_FROM}}';\n\nlet _windowPlaceholderSeq = 0;\n\n/**\n * Placeholder the worker replaces with ONE window of a file's text/grid content.\n * Distinct token from the render (page-image) and extract (whole-file) placeholders so\n * a stale token from either can never be mistaken for this one.\n */\nexport function makeWindowPlaceholder(seed: string): string {\n\t_windowPlaceholderSeq += 1;\n\tconst slug = (seed || 'file').replace(/[^a-zA-Z0-9]+/g, '_').slice(-48);\n\treturn `{{SKAPI_WINDOW::${slug}-${_windowPlaceholderSeq}}}`;\n}\n\n/**\n * True when a file should be read server-side, one window at a time, by the worker.\n * PDFs are excluded: they go through the VISION path, where pages are rendered to\n * images because their text layer is often absent or unreliable.\n */\nexport function isWindowedReadFile(name?: string, mime?: string): boolean {\n\tif (isImageVisionFile(name, mime)) return false;\n\treturn isPagedReadFile(name, mime);\n}\n\nexport interface ComposedUserMessage {\n\t/** Clean display/history copy (attachment links, NO extraction placeholders). */\n\tcomposed: string;\n\t/** LLM-bound copy — `composed` plus inline office-extraction placeholders. */\n\tcomposedForLlm: string;\n\t/** Office-extraction directives for the proxy worker (undefined if no office files). */\n\textractContent?: ExtractDirective[];\n\t/** JIT url re-mint directives for the worker (non-extractable files: PDFs, images). */\n\tfileUrls?: FileUrlDirective[];\n}\n\n// Compose the user's chat message from the typed text + uploaded attachment URLs.\n// Identical for every consumer (agent.vue + the BunnyQuery widget): appends a\n// markdown \"Attached files\" link block, and for office files\n// (.docx/.xlsx/.pptx/.hwpx) adds inline extraction placeholders to the LLM copy\n// ONLY (the proxy worker substitutes their text server-side; the display/history\n// copy stays clean so stale tokens never accumulate across replayed turns).\n// The directive `path` is the db storage path (uid-prefixed where applicable),\n// NOT the link label — it falls back to the label when no storagePath is given\n// (agent.vue uploads FLAT, so storagePath === name there).\nexport function composeUserMessage(\n\ttext: string,\n\tattachmentUrls: Array<{ name: string; url: string; storagePath?: string }>,\n): ComposedUserMessage {\n\tlet composed = text;\n\tif (attachmentUrls.length > 0) {\n\t\tconst lines = attachmentUrls.map((u) => `- [${u.name}](${u.url})`);\n\t\tcomposed = `${text}\\n\\nAttached files:\\n${lines.join('\\n')}`;\n\t}\n\tlet composedForLlm = composed;\n\tlet extractContent: ExtractDirective[] | undefined;\n\tlet fileUrls: FileUrlDirective[] | undefined;\n\tif (attachmentUrls.length > 0) {\n\t\tconst extractFiles = attachmentUrls.filter((u) => isServerExtractable(u.name));\n\t\tif (extractFiles.length > 0) {\n\t\t\tconst directives: ExtractDirective[] = [];\n\t\t\tconst sections = extractFiles.map((u) => {\n\t\t\t\tconst storagePath = u.storagePath || u.name;\n\t\t\t\tconst placeholder = makeExtractPlaceholder(storagePath);\n\t\t\t\tdirectives.push({ path: storagePath, placeholder, name: u.name });\n\t\t\t\treturn `===== ${u.name} =====\\n----- BEGIN FILE CONTENT -----\\n${placeholder}\\n----- END FILE CONTENT -----`;\n\t\t\t});\n\t\t\textractContent = directives;\n\t\t\tcomposedForLlm =\n\t\t\t\t`${composed}\\n\\nExtracted content of attached office files ` +\n\t\t\t\t`(read inline below; do NOT fetch their URLs):\\n\\n` +\n\t\t\t\tsections.join('\\n\\n');\n\t\t}\n\t\t// Files the model fetches by url (NOT server-extractable: PDFs, images) get\n\t\t// a re-mint directive so the worker swaps the baked long-lived CDN url for a\n\t\t// fresh short-lived one at send time. Extractable files are inlined as text,\n\t\t// so their url is never fetched — no directive needed. A blank url (nothing\n\t\t// to match/replace) is skipped.\n\t\tconst urlFiles = attachmentUrls.filter((u) => u.url && !isServerExtractable(u.name));\n\t\tif (urlFiles.length > 0) {\n\t\t\tfileUrls = urlFiles.map((u) => ({ path: u.storagePath || u.name, url: u.url }));\n\t\t}\n\t}\n\treturn { composed, composedForLlm, extractContent, fileUrls };\n}\n","/**\n * Attachment helpers shared by every consumer's view layer.\n *\n * The upload ORCHESTRATION is per-consumer (agent.vue does admin storage\n * accounting; the widget uses get-signed-url), but the failure-reporting shape\n * is identical, so it lives here. When an upload or its indexing request fails,\n * the orchestrator records the original `error.code` / `error.message` on the\n * attachment (`att.errorCode` / `att.errorDetail`); this groups those failed\n * attachments by (code, description) so a single report dialog can list each\n * distinct error once with all the files it affected.\n */\n\nexport interface AttachmentFailureGroup {\n\t/** The failing `error.code` (empty string when the error carried none). */\n\tcode: string;\n\t/** The failing `error.message` / human description. */\n\tmessage: string;\n\t/** Display names of the attachments that hit this exact (code, message). */\n\tfiles: string[];\n}\n\n// Group failed attachments by (code, message). A status of 'error' means the\n// upload itself failed; 'indexError' means the file uploaded but its indexing\n// request failed — both are surfaced. Order of first appearance is preserved.\nexport function groupAttachmentFailures(attachments: any[]): AttachmentFailureGroup[] {\n\tconst groups: Record<string, AttachmentFailureGroup> = {};\n\tconst order: string[] = [];\n\t(attachments || []).forEach(function (att: any) {\n\t\tif (!att || (att.status !== 'error' && att.status !== 'indexError')) return;\n\t\tconst code = String(att.errorCode || '');\n\t\tconst message = String(\n\t\t\tatt.errorDetail ||\n\t\t\tatt.errorMessage ||\n\t\t\t(att.status === 'indexError' ? 'File indexing failed' : 'File upload has failed'),\n\t\t);\n\t\tconst key = code + '\u0000' + message;\n\t\tif (!groups[key]) {\n\t\t\tgroups[key] = { code: code, message: message, files: [] };\n\t\t\torder.push(key);\n\t\t}\n\t\tgroups[key].files.push(String(att.name || '(unnamed file)'));\n\t});\n\treturn order.map(function (k) { return groups[k]; });\n}\n","/**\n * BASE PROMPT — Chat assistant\n * ============================================================================\n * System prompt sent on every chat turn. Rebuilt fresh on every send because\n * the project name/description can change at any time.\n *\n * The `${...}` placeholders are filled from the live project (service):\n * formattedServiceId -> the project ID the assistant is scoped to\n * serviceName -> project display name (only added if a description exists)\n * serviceDescription -> project description (only added if present)\n */\n\nexport type ChatSystemPromptParams = {\n\t/** The project/service ID this assistant is scoped to (formatted form). */\n\tformattedServiceId: string;\n\t/** Project display name. Only appended when a description is also present. */\n\tserviceName?: string;\n\t/** Project description. When present, name + description are appended. */\n\tserviceDescription?: string;\n};\n\nexport function buildChatSystemPrompt(params: ChatSystemPromptParams): string {\n\tconst { formattedServiceId, serviceName, serviceDescription } = params;\n\n\tlet systemPrompt = `\nYou are a dedicated assistant for the project ID: \"${formattedServiceId}\".\nScope: Only answer questions about this project and its data. Do not answer questions about other projects or topics unrelated to this project. When the user refers to \"my database\", \"my data\", or \"my files\", treat those as references to this project's database and file storage.\nKnowledge lookup: Before saying you don't know or that something isn't in the chat history, ALWAYS query this project's database through the available MCP tools to look for the answer. The user's data is the source of truth - the chat transcript is not. Only respond with \"I don't know\" or \"I couldn't find that\" after you have actually searched the project's data and come back empty.\nComplete answers over stored data: The database holds one record per spreadsheet row, and each uploaded file becomes many records that usually share a table. So a question about the data almost always spans many records across several files. For any request that counts, sums, totals, lists every match, compares across records, finds which one, or asks whether something is present or ABSENT (for example \"how many\", \"total spent\", \"which card\", \"is there any\", \"없어?\", \"하나도 없나?\"), you MUST read the COMPLETE matching set before answering. Query with fetch_all set to true, or page through getToolResponsePage until pagination.complete is true, across EVERY relevant table and EVERY relevant file. A single default query returns only the first page (about 50 records). That is a SAMPLE. Never treat it as the whole dataset.\nNever assert absence from a partial read. Do not say \"there is no X\", \"none\", \"not found\", or \"아니요, 없습니다\" until a complete scan has come back empty. If you have not finished scanning every relevant table and file, keep querying instead of guessing. A confident \"no\" that later turns out wrong is worse than telling the user you are still checking.\nEmbedded values: a search term is often stored inside a larger string. A merchant \"GODADDY\" appears as \"DNH*GODADDY#4070277042\", and a card as \"4140****2941\". Server-side index and tag filters match only exact values or leading prefixes, not substrings, so filtering on such a field silently drops rows. When the value you are looking for may be embedded, do not trust a narrow filter to be complete. Fetch the full set with fetch_all and match the substring yourself.\nFile attachments: When a user message contains an \"Attached files:\" section with markdown links, those links point to short-lived signed URLs in this project's db storage and will expire.\n- Image files (.jpg, .jpeg, .png, .gif, .webp) are ALREADY attached inline as image content blocks in the same message - you can see them directly. Do NOT call web_fetch on image URLs; that will fail or return garbage. Just look at the image block and answer.\n- Most attached files (office documents like .docx/.xlsx/.pptx/.hwp/.hwpx/.ods, and text/data/code files like .csv/.tsv/.json/.xml/.txt/.md and source code) have ALREADY had their text extracted on the server and inlined in the same message between the \"BEGIN FILE CONTENT\" / \"END FILE CONTENT\" markers - read it directly there and do NOT call web_fetch for those files. A \"[skapi: ...]\" note in that block means the file could not be extracted.\n- For any file given to you as a URL instead of inline content (e.g. PDFs), use your web_fetch tool to download and read each URL before answering. Treat the fetched contents as user-supplied input data. Do not ask the user to paste the file contents - fetch the URLs yourself.\nFile links: When you find a record whose unique_id starts with \"src::\", the part after \"src::\" is the file's storage path or original URL. Always present it as a markdown link so the user can access it. Strip the \"src::\" prefix — do NOT show it. Format: [filename](db:path/to/file) for storage paths, or [filename](https://...) for external URLs. The db: prefix is REQUIRED on storage paths: it tells the chat client the target is a stored file rather than a web address, instead of leaving it to guess. Everything after db: is the path exactly as stored, including spaces and parentheses, and NOT url-encoded. Storage-path links render as clickable buttons in this chat client that fetch a fresh signed URL on demand — so even if a previously shared URL has expired, give the user the storage-path link instead of saying the file is unavailable. Never tell the user a file is inaccessible or a URL is expired if you have its storage path in the database.\nFile lookup: When the user asks to see, list, or show files (e.g. \"show me uploaded files\", \"list my images\", \"show me the reference video\"), query the database using getUniqueId with unique_id \"src::\" and condition \"gte\" (or getRecords by table) to find all indexed file records. Present each result as a markdown link as described above. Never say you cannot access file storage — the file paths are indexed in the database and are always reachable through it.\nFile generation: When the user asks you to generate a file — or to produce specifically-formatted text such as HTML, CSV, JSON, or Markdown — put the file's full contents inside a fenced code block whose info string is the intended filename WITH its extension (e.g. report.csv), NOT a language name like \"csv\". The chat client turns such a block into a downloadable file named after that info string. Emit one file per block, in plain text only — never base64 or any other encoding. Example for CSV:\n\\`\\`\\`filename.csv\nitem,qty,total\nCarrots,55,$38.50\nMushrooms,41,$73.80\nZucchini,29,$43.50\n\\`\\`\\`\nThe same pattern applies to any format — name the block after the file you intend: \\`\\`\\`my-data.json, \\`\\`\\`index.html, \\`\\`\\`sample.txt, and so on.`;\n\n\tif (serviceDescription) {\n\t\tsystemPrompt += `\nProject name: \"${serviceName ?? ''}\"\nProject description: \"\"\"${serviceDescription}\"\"\"`;\n\t}\n\n\treturn systemPrompt;\n}\n","/**\n * BASE PROMPT — Background file-indexing agent (system prompt)\n * ============================================================================\n * System prompt for the BACKGROUND indexing agent (notifyAgentSaveAttachment).\n * Its only job is to read the freshly uploaded file and persist what it learns\n * into the project's knowledge base via the MCP tools. Pairs with the\n * user-message template in ./indexing_user_message.ts.\n */\n\nexport type IndexingSystemPromptParams = {\n\t/** The project/service ID being indexed into. */\n\tservice: string;\n\t/** Project display name. Only appended when a description is also present. */\n\tserviceName?: string;\n\t/** Project description. When present, name + description are appended. */\n\tserviceDescription?: string;\n};\n\nexport function buildIndexingSystemPrompt(params: IndexingSystemPromptParams): string {\n\tconst { service, serviceName, serviceDescription } = params;\n\n\tlet systemPrompt =\n`You are a background indexing agent for project ${service}.\n- Image files (.jpg, .jpeg, .png, .gif, .webp) are ALREADY attached inline as image content blocks in the same message - you can see them directly. Do NOT call web_fetch on image URLs; that will fail or return garbage. Just look at the image block and answer.\n- Most files (office documents like .docx/.xlsx/.pptx/.hwp/.hwpx/.ods, and text/data/code files like .csv/.tsv/.json/.xml/.txt/.md and source code) have ALREADY been extracted on the server and included inline in the user message between the \"BEGIN FILE CONTENT\" / \"END FILE CONTENT\" markers - read that directly. If the inline content is a \"[skapi: ...]\" note, the file could not be extracted - index it from its metadata only.\n- BIG SPREADSHEETS / TEXT: the inline content may be only the FIRST part of a large file (it can end with a truncation or \"more remains\" note). For big spreadsheets and big text/data files READ THE FILE WITH THE readFileContent TOOL: it returns the file ONE WINDOW at a time (spreadsheets as coordinate-tagged grid rows, text as a range of characters). Pass the file's storage path. After each window: datafy it into records and SAVE them, THEN if the window says MORE REMAINS call readFileContent again with the cursor it gives you. Repeat until it says END OF FILE, so the WHOLE file is indexed - never stop after the first window. (Do NOT call readFileContent on a PDF - see the next line.)\n- PDFs (scanned or not): you do NOT read a PDF with a tool or a URL. Its pages are RENDERED and embedded directly in the user message as IMAGE blocks, a WINDOW of pages at a time. LOOK at the embedded page images and datafy every one. The note beside them tells you whether MORE pages remain: if so, save this window's records and stop (a follow-up pass shows the next window automatically); only when the note says it was the LAST window is the PDF fully seen. Do NOT call readFileContent or web_fetch for a PDF.\n- VISION: when the message (a readFileContent window, an embedded PDF page, or an inline attachment) includes IMAGES - scanned/rendered PDF pages, or photos embedded in a spreadsheet next to a row/block - LOOK at them and capture what they show as record data (the reading/values in a scanned table, the part/defect/condition visible in a photo). The image IS part of the data; correlate each photo with its labelled block (\"PHOTO A3\" markers tie a photo to that grid row).\n- Whatever the file type, use the file's storage path (the \"storage path\" metadata line) as the \"src::\" unique_id - never the inline content or a temporary URL.\n- TABULAR data (any spreadsheet - .csv/.tsv/.xlsx/.xls/.ods, or sheet-like rows): you MUST save EVERY data row as its own record (ONE record per row) with that row's actual column values in the record's \"data\", keyed by the header names, in a dedicated table (e.g. \"spreadsheet_rows\"). Do NOT summarize, sample only a few rows, or save just file metadata - index the whole sheet, paging through it with readFileContent when it is large. Make MULTIPLE postRecords calls in batches (e.g. 30-50 rows per call) rather than one oversized call. This per-row completeness OVERRIDES brevity. ALSO save one file-level summary record (file name, sheet name(s), column headers, total row count, overall summary) - this is the record that carries the file's \"src::\" unique_id - and link EVERY per-row record to it via reference (set each row record's reference to that src:: file record; the row records themselves do NOT carry a src:: unique_id). The per-row records AND this reference linkage are BOTH mandatory: the linkage is what lets the whole sheet be found and cleaned up together when the file is re-indexed.\n- EPUB / e-books / long-form books (.epub or any book-length prose, provided inline in reading order with chapter headings preserved): you MUST save ONE record per CHAPTER (or, when chapters are unclear, per major section/topic) in a dedicated table (e.g. \"book_chapters\") - never collapse the whole book into a single record. Each chapter record's \"data\" must capture the chapter title plus its order/number AND a substantive summary of that chapter's content (key events, arguments, characters, places, concepts, terms, notable quotes). Apply AS MANY relevant tags as possible to EVERY chapter record (characters, locations, themes, topics, key concepts, key terms, dates, named entities) so the book is easy to SEARCH and cross-reference later - this is the whole point. ALSO save one book-level record (title, author, language, overall summary, chapter list / table of contents, genre/subjects) and link each chapter record to it via reference. This per-chapter completeness OVERRIDES brevity; human-readable summaries only, never raw/binary bytes.\n- This is a background indexing task: do ALL the MCP saving FIRST, never reply mid-task, and never ask the user questions. Always use the MCP tools to save what you learn - be exhaustive about meaning (and, for tabular data, about every row). SAVE AS YOU GO: persist each window's records before reading the next, so progress is never lost. If the file is so large you cannot finish in one turn, still save everything you have read so far; a follow-up pass will automatically continue from where you stopped. Never store raw or binary bytes (base64, blobs); describe them in human-readable text instead.\n- COMPLETION SIGNAL: only when you have fully read and saved the ENTIRE file (for readFileContent files: reached \"END OF FILE\"; for PDFs: the embedded page-image note said it was the LAST window - with all rows/pages/items saved), end your final message with the token INDEXING_COMPLETE on its own line. If you did NOT finish the whole file (more rows/pages remain), do NOT write that token - leaving it out is how the system knows to run another pass to continue.\n- Only AFTER every save is done, send exactly ONE final message summarizing what you indexed - never just \"Indexing complete\", and never a raw/base64/binary value or a large pasted dump. Keep it to a few factual sentences or a short markdown bullet list covering: the file name, its content type, each table you wrote to with its record/row count and the key columns/fields or topics captured, and anything that could not be extracted. Follow this shape - Indexed <file name> (<content type>): saved <N> records to <table(s)> capturing <key columns/fields or topics>; could not extract: <gaps, or none>.`;\n\n\tif (serviceDescription) {\n\t\tsystemPrompt += `\nProject name: \"${serviceName ?? ''}\"\nProject description: \"\"\"${serviceDescription}\"\"\"`;\n\t}\n\n\treturn systemPrompt;\n}\n","/**\n * BASE PROMPT — Background file-indexing agent (user message)\n * ============================================================================\n * USER-role message paired with the indexing system prompt. Sent by\n * notifyAgentSaveAttachment() each time a file is uploaded or re-indexed.\n *\n * NOTE: the leading line \"A new file has just been uploaded. Index it now.\" and\n * the \"- name: ...\" line are also what the chat client parses to build the\n * \"Indexing: <name>\" history bubble — keep those fields on their own lines.\n */\n\nexport type IndexingAttachmentInfo = {\n\t/** Original file name. */\n\tname: string;\n\t/** Storage path within the project's db storage. */\n\tstoragePath: string;\n\t/** MIME type, if detected. Omitted from the message when unknown. */\n\tmime?: string;\n\t/** File size in bytes, if known. Omitted from the message when unknown. */\n\tsize?: number;\n\t/** Temporary signed URL the agent/MCP fetches to read the file contents. */\n\turl: string;\n};\n\nexport type BuildIndexingUserMessageOptions = {\n\t/**\n\t * For office files (.docx/.xlsx/.pptx) the model can't read the binary via\n\t * web_fetch, so the proxy worker extracts the text server-side and replaces\n\t * this exact token with it. When provided, the message embeds the token (and\n\t * drops the temporary-URL line — there is nothing for the model to fetch).\n\t */\n\tinlineContentPlaceholder?: string;\n\t/**\n\t * Actual file content parsed CLIENT-SIDE by an attachment-parser plugin (e.g.\n\t * an .hwp parser). Embedded inline verbatim — no server extraction and no\n\t * web_fetch for this file. Takes precedence over `inlineContentPlaceholder`.\n\t */\n\tinlineContent?: string;\n\t/**\n\t * Spreadsheet or PDF: read by PAGING through the readFileContent tool (grid rows +\n\t * embedded photos / rendered scanned pages), not inline and not by web_fetch. The\n\t * message instructs the agent to page through EVERY window and datafy each.\n\t */\n\tpagedRead?: boolean;\n};\n\nexport function buildIndexingUserMessage(\n\tattachment: IndexingAttachmentInfo,\n\toptions?: BuildIndexingUserMessageOptions,\n): string {\n\tconst head =\n\t\t`A new file has just been uploaded. Index it now.\\n\\n` +\n\t\t`File metadata:\\n` +\n\t\t`- name: ${attachment.name}\\n` +\n\t\t`- storage path: ${attachment.storagePath}\\n` +\n\t\t(attachment.mime ? `- mime type: ${attachment.mime}\\n` : '') +\n\t\t(typeof attachment.size === 'number' ? `- size (bytes): ${attachment.size}\\n` : '');\n\n\tif (options?.inlineContent) {\n\t\t// Parsed client-side (an attachment-parser plugin). The content is already\n\t\t// inlined below — no server extraction, no URL to fetch.\n\t\treturn (\n\t\t\thead +\n\t\t\t`\\nThe file's content was parsed by the client and is provided inline below. ` +\n\t\t\t`Read it directly — do NOT fetch any URL for this file. ` +\n\t\t\t`Use the storage path above (not this content) for the \"src::\" unique_id.\\n\\n` +\n\t\t\t`----- BEGIN FILE CONTENT -----\\n` +\n\t\t\t`${options.inlineContent}\\n` +\n\t\t\t`----- END FILE CONTENT -----`\n\t\t);\n\t}\n\n\tif (options?.inlineContentPlaceholder) {\n\t\t// Office file: text was extracted on the server and is inlined below\n\t\t// between the markers. Do NOT fetch any URL for this file.\n\t\treturn (\n\t\t\thead +\n\t\t\t`\\nThe file's text content was extracted on the server and is provided inline below. ` +\n\t\t\t`Read it directly — do NOT fetch any URL for this file. ` +\n\t\t\t`Use the storage path above (not this content) for the \"src::\" unique_id.\\n\\n` +\n\t\t\t`----- BEGIN FILE CONTENT -----\\n` +\n\t\t\t`${options.inlineContentPlaceholder}\\n` +\n\t\t\t`----- END FILE CONTENT -----`\n\t\t);\n\t}\n\n\tif (options?.pagedRead) {\n\t\t// Spreadsheet / PDF: force the paging path. The agent MUST read this with the\n\t\t// readFileContent tool (which returns the file window by window, with grid rows,\n\t\t// embedded photos, and rendered scanned pages), NOT by fetching the URL.\n\t\treturn (\n\t\t\thead +\n\t\t\t`\\nRead this file with the readFileContent tool, using the storage path above - do NOT fetch a URL and do NOT rely on a single sample. ` +\n\t\t\t`readFileContent returns the file ONE WINDOW at a time: spreadsheets as coordinate-tagged grid rows (e.g. 'R4 A:E&I NUMBER | B:E1007'), scanned/large PDFs as rendered PAGE IMAGES, and windows may include embedded photos - LOOK at any images and datafy what they show. ` +\n\t\t\t`Page through EVERY window: for each window SAVE records for its rows/items/pages (postRecords, one record per row/item), THEN if the window says MORE REMAINS call readFileContent again with the cursor it gives you. Repeat until it says END OF FILE, so the WHOLE file is indexed. ` +\n\t\t\t`Do NOT stop after the first window and do NOT just write a summary. Use the storage path above for the \"src::\" unique_id.` +\n\t\t\t(attachment.url ? `\\n(A temporary URL is provided ONLY as a fallback if readFileContent fails: ${attachment.url})` : '')\n\t\t);\n\t}\n\n\treturn head + `- temporary URL (fetch this to read the file contents): ${attachment.url}`;\n}\n\n/**\n * Token the WORKER substitutes with the 1-based first page of the window it is about to\n * render, when it builds the next pass of a document from `RENDER_CONTINUE_TEMPLATE`.\n * Must match the worker's RENDER_FROM_TOKEN.\n */\nexport const RENDER_FROM_TOKEN = '{{RENDER_FROM}}';\nconst WINDOW_CURSOR_TOKEN = RENDER_FROM_TOKEN;\n\n/**\n * User message for a VISION file (PDF): its pages are delivered as RENDERED PAGE IMAGES that\n * the proxy worker injects into THIS message at the `placeholder` token (tool-result images\n * render on neither provider, so the pages must be image blocks in the message itself). Each\n * pass shows one WINDOW of pages starting at `renderFrom` (0-based).\n *\n * The WORKER advances the window: when its renderer reports pages remaining it enqueues the\n * next pass itself, off the true page count, so a document indexes end-to-end with no browser\n * involved. This message therefore only ever describes ONE window, and the model is never\n * asked to decide whether the document is finished.\n *\n * renderFrom === 0 is the FIRST pass (leads with \"A new file has just been uploaded.\" so the\n * client builds the \"Indexing: <name>\" bubble); a continue pass (built by the worker from\n * buildIndexingRenderContinueTemplate) leads with \"CONTINUE indexing\" so it is not a duplicate\n * primary bubble.\n */\nexport function buildIndexingRenderMessage(\n\tattachment: IndexingAttachmentInfo,\n\tplaceholder: string,\n\trenderFrom: number,\n): string {\n\tconst from = Math.max(0, renderFrom || 0);\n\tif (from > 0) return buildIndexingRenderContinueTemplate(attachment, placeholder, String(from + 1));\n\n\treturn (\n\t\t`A new file has just been uploaded. Index it now.\\n\\n` +\n\t\tbuildRenderMeta(attachment) +\n\t\t`\\nThis is a PDF. Its pages are delivered to you as RENDERED PAGE IMAGES embedded directly in this ` +\n\t\t`message (you do NOT need any tool, URL, or web_fetch to see them). You are shown a WINDOW of pages ` +\n\t\t`at a time, starting at page ${from + 1}.\\n` +\n\t\tbuildRenderDatafy(placeholder)\n\t);\n}\n\n/**\n * The CONTINUE pass, as a template the worker fills in. `pageLabel` defaults to the\n * RENDER_FROM_TOKEN placeholder, which the worker replaces with the real 1-based start page\n * of the window it is rendering; passing an explicit label produces a ready-to-send message.\n */\nexport function buildIndexingRenderContinueTemplate(\n\tattachment: IndexingAttachmentInfo,\n\tplaceholder: string,\n\tpageLabel: string = RENDER_FROM_TOKEN,\n): string {\n\tconst src = `src::${attachment.storagePath}`;\n\treturn (\n\t\t`CONTINUE indexing a PDF whose previous pass did not finish.\\n\\n` +\n\t\tbuildRenderMeta(attachment) +\n\t\t`\\nRecords for the earlier pages are ALREADY saved (they reference \"${src}\"). The NEXT window of ` +\n\t\t`rendered page images (starting at page ${pageLabel}) is embedded in this message. Datafy each page as ` +\n\t\t`before and do NOT re-save pages that are already saved.\\n` +\n\t\tbuildRenderDatafy(placeholder)\n\t);\n}\n\nfunction buildRenderMeta(attachment: IndexingAttachmentInfo): string {\n\treturn (\n\t\t`File metadata:\\n` +\n\t\t`- name: ${attachment.name}\\n` +\n\t\t`- storage path: ${attachment.storagePath}\\n` +\n\t\t(attachment.mime ? `- mime type: ${attachment.mime}\\n` : '')\n\t);\n}\n\n// Shared datafy guidance. The placeholder is where the worker splices the note + rendered\n// page images; instructions reference \"the page images in this message\" so they read\n// correctly whether the images land before or after this text.\n//\n// Deliberately says nothing about INDEXING_COMPLETE or about whether the document is\n// finished: the worker decides that from the renderer's page count. Asking the model was\n// what used to end an 88-page file at page 15.\nfunction buildRenderDatafy(placeholder: string): string {\n\treturn (\n\t\t`\\n${placeholder}\\n\\n` +\n\t\t`LOOK at each rendered page image in this message and DATAFY what it shows: for EVERY page ` +\n\t\t`call postRecords and save records - one record per row / table entry / line item visible on the page ` +\n\t\t`(or one record for the page if it is prose), capturing every value you can read (OCR the text, read tables ` +\n\t\t`cell by cell, describe any photos/diagrams). Use the storage path above for the \"src::\" unique_id.\\n\\n` +\n\t\t`Save records for THIS window of pages only, then stop and report what you saved. Do NOT try to read ` +\n\t\t`the rest of the file and do NOT worry about the pages after this window: if any remain, the next window ` +\n\t\t`is rendered and sent to you automatically. Report only the pages you were actually shown - never imply ` +\n\t\t`you have seen the whole document.`\n\t);\n}\n\n/**\n * User message for a WINDOWED file: the worker splices ONE window of the file's rows or\n * text into this message at `placeholder`, then continues from the reader's own cursor\n * until the file is exhausted.\n *\n * The agent is deliberately NOT asked to page the file itself, and is NOT asked to judge\n * whether it is finished. Both used to be its job, and both failed the same way: the\n * traversal lived inside a single turn's budget, so a large file simply stopped partway\n * with a confident summary of the part it had seen.\n */\nexport function buildIndexingWindowMessage(\n\tattachment: IndexingAttachmentInfo,\n\tplaceholder: string,\n\tisContinuation: boolean,\n\tpositionLabel?: string,\n): string {\n\tconst src = `src::${attachment.storagePath}`;\n\tconst head = isContinuation\n\t\t? `CONTINUE indexing a file whose previous pass did not finish.\\n\\n`\n\t\t: `A new file has just been uploaded. Index it now.\\n\\n`;\n\tconst where = isContinuation\n\t\t? `\\nRecords for the earlier windows are ALREADY saved (they reference \"${src}\"). The NEXT window ` +\n\t\t `(starting at ${positionLabel || WINDOW_CURSOR_TOKEN}) is embedded below. Do NOT re-save windows that are already saved.\\n`\n\t\t: `\\nThis file is delivered to you ONE WINDOW at a time, embedded directly in this message. ` +\n\t\t `You do NOT need any tool, URL, or web_fetch to read it.\\n`;\n\n\treturn (\n\t\thead +\n\t\tbuildRenderMeta(attachment) +\n\t\twhere +\n\t\t`\\n${placeholder}\\n\\n` +\n\t\t`DATAFY this window: call postRecords and save records for everything in it - ONE RECORD PER ROW ` +\n\t\t`for tabular data (keyed by the column headers), or one record per section for prose. Capture every ` +\n\t\t`value you can read. Use the storage path above for the \"src::\" unique_id on the file-level record, ` +\n\t\t`and link every row/section record to it by reference.\\n\\n` +\n\t\t`If this window has PHOTOS attached as images, LOOK at each one and datafy what it actually shows ` +\n\t\t`into the record for the row it is anchored to (a «PHOTO A88» marker in the grid text only says WHERE ` +\n\t\t`a picture sits - the picture itself is attached to this message). Never report that photo contents ` +\n\t\t`could not be extracted when images are attached here.\\n\\n` +\n\t\t`Save records for THIS window only, then stop and report what you saved. Do NOT try to read the rest ` +\n\t\t`of the file, and do NOT call readFileContent - if more remains, the next window is read and sent to ` +\n\t\t`you automatically. Report only what you were actually shown, and never imply you have seen the whole ` +\n\t\t`file when the note beside the window says more remains.`\n\t);\n}\n\n/**\n * User message for a RESUME pass: a previous indexing pass could not finish this large\n * file, so continue it from where the already-saved records leave off (never restart).\n */\nexport function buildIndexingContinueMessage(attachment: IndexingAttachmentInfo): string {\n\tconst src = `src::${attachment.storagePath}`;\n\treturn (\n\t\t`CONTINUE indexing a file whose previous pass did not finish.\\n\\n` +\n\t\t`File metadata:\\n` +\n\t\t`- name: ${attachment.name}\\n` +\n\t\t`- storage path: ${attachment.storagePath}\\n` +\n\t\t(attachment.mime ? `- mime type: ${attachment.mime}\\n` : '') +\n\t\t`\\nRecords for the earlier windows/pages of this file are ALREADY saved (they reference \"${src}\"). ` +\n\t\t`First call getRecords with reference \"${src}\" to see how far the previous pass got (the furthest page/row/window already saved). ` +\n\t\t`Then call readFileContent with the storage path above and a CURSOR that RESUMES just after that point - do NOT start at the beginning. The cursor is derivable from what you already saved:\\n` +\n\t\t` - PDF: the cursor is the NUMBER OF PAGES already read (0-based next page). If you saved up to page N, call readFileContent with cursor=\"N\" to get page N+1 onward.\\n` +\n\t\t` - Spreadsheet: the cursor is \"<sheetIndex>:<nextRow>\" (0-based sheet index, 1-based row). If you saved up to row R of sheet S, use cursor=\"S:R+1\".\\n` +\n\t\t` - Text: the cursor is the character offset already read.\\n` +\n\t\t`Index the REMAINING windows - one record per row/item, looking at any page images or embedded photos - saving as you go until readFileContent reports END OF FILE. ` +\n\t\t`Do NOT re-save windows that are already saved. ` +\n\t\t`Use the storage path above for the \"src::\" unique_id. When the ENTIRE file is finally indexed, end your message with the token INDEXING_COMPLETE.`\n\t);\n}\n","/**\n * Error detection + message extraction (pure). Moved verbatim from the\n * agent.vue / bunnyquery chatbox so both consumers share one implementation.\n */\n\nexport function getErrorMessage(input: any): string {\n\tif (!input) return 'Something went wrong.';\n\tif (typeof input === 'string') return input;\n\tif (input.error && input.error.message) return input.error.message;\n\tif (input.body && input.body.error && input.body.error.message) return input.body.error.message;\n\tif (input.body && typeof input.body.message === 'string') return input.body.message;\n\tif (input.message) return input.message;\n\treturn 'Something went wrong.';\n}\n\nexport function isErrorResponseBody(response: any): boolean {\n\tif (!response || typeof response !== 'object') return false;\n\tif (typeof response.status_code === 'number' && response.status_code >= 400) return true;\n\tif (response.type === 'error') return true;\n\tif (response.error && (response.error.message || response.error.type)) return true;\n\tvar body = response.body;\n\tif (body && typeof body === 'object') {\n\t\tif (body.type === 'error') return true;\n\t\tif (body.error && (body.error.message || body.error.type)) return true;\n\t}\n\tif (typeof response.message === 'string' && response.message.length) {\n\t\tvar hasClaude = Array.isArray(response.content);\n\t\tvar hasOpenAI =\n\t\t\ttypeof response.output_text === 'string' ||\n\t\t\tArray.isArray(response.output) ||\n\t\t\tArray.isArray(response.choices);\n\t\tif (!hasClaude && !hasOpenAI) return true;\n\t}\n\treturn false;\n}\n\n// A request that failed because the REQUEST ITSELF is malformed — an unknown or\n// rejected parameter on a 400/422 — will deterministically re-fail if resent\n// unchanged; no session refresh or retry can fix it. Detecting it lets the retry\n// gates refuse to auto-resend (otherwise a 400 whose param name merely contains\n// \"token\", e.g. `max_output_tokens`, trips the `invalid_request + token` branch\n// of isAuthExpiredError below and loops refresh->resend forever, burning tokens).\n// This is the `_skapi_extract` 400 class. Distinct from auth-expiry, which IS\n// retryable after a token refresh — so 401 (auth) and 429/5xx (transient) are\n// intentionally NOT treated as non-retryable here.\nexport function isNonRetryableRequestError(input: any): boolean {\n\tif (!input || typeof input !== 'object') return false;\n\n\tvar status = typeof input.status_code === 'number' ? input.status_code\n\t\t: typeof input.status === 'number' ? input.status : undefined;\n\n\t// Collect the error envelope wherever it lives (response, response.body, or a\n\t// thrown error), mirroring isErrorResponseBody / isAuthExpiredError.\n\tvar param: any = undefined;\n\tvar blobs: string[] = [];\n\tvar sources = [input.error, input.body && input.body.error, input.body, input];\n\tfor (var i = 0; i < sources.length; i++) {\n\t\tvar e = sources[i];\n\t\tif (!e) continue;\n\t\tif (typeof e === 'string') { blobs.push(e); continue; }\n\t\tif (typeof e !== 'object') continue;\n\t\tif (param === undefined && e.param != null) param = e.param;\n\t\tif (typeof e.code === 'string') blobs.push(e.code);\n\t\tif (typeof e.type === 'string') blobs.push(e.type);\n\t\tif (typeof e.message === 'string') blobs.push(e.message);\n\t}\n\tvar hay = blobs.join(' | ').toLowerCase();\n\n\t// Explicit \"unknown / unsupported parameter\" is always a malformed request.\n\tif (hay.indexOf('unknown_parameter') !== -1 || hay.indexOf('unknown parameter') !== -1 ||\n\t\thay.indexOf('unsupported_parameter') !== -1 || hay.indexOf('unsupported parameter') !== -1) {\n\t\treturn true;\n\t}\n\n\t// A 400/422 invalid_request that points at a specific rejected field: resending\n\t// the identical body re-fails. (401 -> isAuthExpiredError; 429/5xx -> transient.)\n\tvar isClientReqStatus = status === 400 || status === 422;\n\tif (isClientReqStatus && param != null && param !== '') return true;\n\tif (isClientReqStatus && hay.indexOf('invalid_request') !== -1 &&\n\t\t(hay.indexOf('parameter') !== -1 || hay.indexOf('param') !== -1)) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nexport function isAuthExpiredError(input: any): boolean {\n\tif (!input) return false;\n\tvar blobs: string[] = [];\n\tvar push = function (v: any) { if (typeof v === 'string' && v) blobs.push(v); };\n\tif (typeof input === 'string') push(input);\n\telse {\n\t\tpush(input.message); push(input.code);\n\t\tif (input.error) { push(input.error.message); push(input.error.code); push(input.error.type); }\n\t\tif (input.body) {\n\t\t\tpush(input.body.message);\n\t\t\tif (input.body.error) { push(input.body.error.message); push(input.body.error.code); push(input.body.error.type); }\n\t\t}\n\t\tif (typeof input.status === 'number' && input.status === 401) return true;\n\t\tif (typeof input.status_code === 'number' && input.status_code === 401) return true;\n\t}\n\tvar hay = blobs.join(' | ').toLowerCase();\n\tif (!hay) return false;\n\treturn hay.indexOf('token has expired') !== -1 || hay.indexOf('token is expired') !== -1 ||\n\t\thay.indexOf('expired_token') !== -1 || hay.indexOf('invalid_token') !== -1 ||\n\t\thay.indexOf('unauthorized') !== -1 || hay.indexOf('not authorized') !== -1 ||\n\t\t(hay.indexOf('invalid_request') !== -1 && hay.indexOf('token') !== -1);\n}\n","/**\n * Pure link/path helpers (no DOM, no marked). Moved verbatim from the chatbox.\n * `serviceId` is passed as a PARAMETER (the original read it from a global) so\n * the engine stays consumer-agnostic. The HTML-emitting helpers\n * (buildLinkPartFromGroups, linkToAnchorHtml, fileToAnchorHtml, parseMsgParts*)\n * stay in each VIEW — only these pure pieces move here.\n */\n\nexport var EXPIRED_ATTACHMENT_URL_HOST = '_expired_.url';\nexport var EXPIRED_ATTACHMENT_URL_ORIGIN = 'https://' + EXPIRED_ATTACHMENT_URL_HOST;\nexport var LINK_LABEL_MAX_DISPLAY_CHARS = 32;\n\n/**\n * Lifetime of the url minted when a user clicks an expired attachment chip.\n *\n * Mint it as a PLAIN get-db presign, never with generate_temporary_cdn_url: the\n * cdn branch ignores `expires` entirely and hands back a url good for the rest of\n * the current UTC day plus the next one, so a \"20 minute\" link would in fact live\n * 24 to 48 hours. The dashboard has always done this correctly and the widget did\n * not, which is precisely the kind of divergence a shared constant exists to stop.\n */\nexport var EXPIRED_LINK_REFRESH_EXPIRES_SECONDS = 20 * 60;\n\n/**\n * How long a client may keep serving an href it already minted before dropping\n * back to the placeholder and re-minting.\n *\n * DERIVED from the TTL above, with five minutes of headroom, because the\n * invariant \"the cache must expire before the url does\" used to be a comment\n * next to two independent literals. If it is ever violated a client serves a\n * dead url with no way to notice; deriving it makes that unrepresentable.\n */\nexport var LINK_REFRESH_WINDOW_MS = (EXPIRED_LINK_REFRESH_EXPIRES_SECONDS - 5 * 60) * 1000;\n\n// The two \"balanced parens\" groups match ONE CHARACTER per step, never a `+`\n// run, so each position has exactly one way to be matched: `[^()\\n]` cannot\n// start with `(`, and the nested-paren alternative always does. That disjointness\n// is load-bearing, not style.\n//\n// The obvious spelling — `(?:[^()\\n]+|\\([^()\\n]*\\))+` — is a nested quantifier:\n// a run of N plain characters can be split across the outer `+` in 2^N ways, and\n// the engine tries EVERY one before it can conclude the branch failed. A branch\n// fails on ordinary input: a link whose url contains a space (the url branch\n// forbids spaces), a link broken across a newline, or a reply truncated\n// mid-link. Measured on the unfixed pattern: `[label](` plus 30 characters with\n// no closing paren took 62 SECONDS, 45 characters never finished. Since this\n// regex is scanned over the whole reply by the typewriter (session.ts) and by\n// every message render (parseMsgParts), that is a permanently frozen tab the\n// moment such a message arrives. Same matches either way, linear time.\nexport function createInlineLinkRegex(): RegExp {\n\treturn /src::(\\S+)|\\[([^\\]\\n]+)\\]\\((https?:\\/\\/(?:[^\\s()]|\\([^\\s()]*\\))+)\\)|\\[([^\\]\\n]+)\\]\\(((?:[^()\\n]|\\([^()\\n]*\\))+)\\)|(https?:\\/\\/[^\\s<>\"']+)/g;\n}\n\nexport function safeDecodeURIComponent(v: string): string {\n\ttry { return decodeURIComponent(v); } catch (e) { return v; }\n}\n\nexport function encodePathSegments(path: string): string {\n\treturn path.split('/').filter(Boolean).map(function (s) { return encodeURIComponent(s); }).join('/');\n}\n\nexport function normalizeAttachmentPathCandidate(value: string): string {\n\treturn safeDecodeURIComponent((value || '').trim()).replace(/\\\\/g, '/').replace(/^\\/+/, '').replace(/\\/+/g, '/');\n}\n\nexport function extractRemotePathFromAttachmentHref(href: string, serviceId: string): string | null {\n\ttry {\n\t\tvar parsed = new URL(href);\n\t\tif (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return null;\n\t\tvar path = normalizeAttachmentPathCandidate(parsed.pathname || '');\n\t\tvar segs = path.split('/').filter(Boolean);\n\t\tif (!segs.length) return null;\n\t\tvar HEX = /^[a-f0-9]{32,}$/i;\n\t\tvar sid = serviceId || '';\n\t\tvar start = 0;\n\t\twhile (start < segs.length) {\n\t\t\tvar seg = segs[start];\n\t\t\tif (seg === sid || HEX.test(seg)) { start++; continue; }\n\t\t\tbreak;\n\t\t}\n\t\tvar real = segs.slice(start).join('/');\n\t\treturn real || null;\n\t} catch (e) { return null; }\n}\n\nexport function getExpiredAttachmentVisiblePath(remotePath: string, fallback?: string): string {\n\tvar n = normalizeAttachmentPathCandidate(remotePath);\n\tif (n) return n;\n\treturn normalizeAttachmentPathCandidate(fallback || 'file') || 'file';\n}\n\nexport function buildDisplayExpiredAttachmentHref(remotePath: string, fallback?: string): string {\n\treturn EXPIRED_ATTACHMENT_URL_ORIGIN + '/' + encodePathSegments(getExpiredAttachmentVisiblePath(remotePath, fallback));\n}\n\n// Does `href` point at THIS service's db attachment storage? A db attachment URL's\n// path always begins with the serviceId segment (…/<serviceId>/<hash>/<path>). Used\n// to SAFELY sanitize assistant messages — where an arbitrary external citation URL\n// must never be rewritten, only the service's own volatile db links.\nexport function isServiceDbAttachmentHref(href: string, serviceId: string): boolean {\n\tif (!serviceId) return false;\n\ttry {\n\t\tvar parsed = new URL(href);\n\t\tif (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return false;\n\t\tvar segs = normalizeAttachmentPathCandidate(parsed.pathname || '').split('/').filter(Boolean);\n\t\treturn segs.length > 0 && segs[0] === serviceId;\n\t} catch (e) { return false; }\n}\n\n/**\n * Read the storage path back out of an `_expired_.url` placeholder.\n *\n * The placeholder is not a display detail: sanitizeAttachmentLinksForHistory\n * writes it into PERSISTED history, and buildBoundedChatMessages replays it into\n * the model's context. So it round-trips constantly and MUST be recognised on the\n * way back in. Returns null for anything that is not the carrier.\n */\nexport function readExpiredAttachmentHref(href: string): string | null {\n\tif (!href) return null;\n\ttry {\n\t\tvar parsed = new URL(href);\n\t\tif (parsed.hostname !== EXPIRED_ATTACHMENT_URL_HOST) return null;\n\t\treturn normalizeAttachmentPathCandidate(parsed.pathname || '') || null;\n\t} catch (e) { return null; }\n}\n\n// Replace volatile attachment URLs with their durable `_expired_.url/<path>`\n// placeholder so a stored/replayed copy re-mints on demand instead of going stale.\n//\n// Only THIS service's db urls are rewritten, whichever role wrote them. The user\n// branch used to rewrite every url in any message that carried an \"Attached\n// files:\" block, which quietly destroyed a third-party link the user happened to\n// paste in the same message: it became a placeholder for a storage path that\n// never existed. We can only re-mint what we host, so we only rewrite what we\n// host.\nexport function sanitizeAttachmentLinksForHistory(content: string, serviceId: string, forAssistant?: boolean): string {\n\tif (!content) return content;\n\tif (!forAssistant && content.indexOf('Attached files:') === -1) return content;\n\treturn content.replace(/\\[([^\\]\\n]+)\\]\\((https?:\\/\\/[^\\s)]+)\\)/g, function (_m: string, label: string, href: string) {\n\t\tif (!isServiceDbAttachmentHref(href, serviceId)) return _m;\n\t\tvar remotePath = extractRemotePathFromAttachmentHref(href, serviceId);\n\t\tvar fullPath = remotePath || normalizeAttachmentPathCandidate(label);\n\t\tif (!fullPath) return _m;\n\t\treturn '[' + label + '](' + buildDisplayExpiredAttachmentHref(fullPath, label) + ')';\n\t});\n}\n\n/**\n * Is this markdown link target a URL rather than a db storage path?\n *\n * The inline-link regex decides that by whether the target contains whitespace:\n * its url branch forbids it, its bare-path branch allows it (a db path really can\n * contain spaces). So a url that picked up a stray space anywhere in transit\n * falls out of the url branch and is claimed by the path branch, and the view\n * renders it as an `_expired_.url/https%3A/…` attachment chip that resolves to\n * nothing. The view asks this FIRST, so what a link IS never depends on damage.\n */\nexport function isHttpUrlLike(target: string): boolean {\n\treturn /^https?:\\/\\//i.test((target || '').trim());\n}\n\n/**\n * Repair whitespace inside a url. RFC 3986 has no legal whitespace anywhere in a\n * URI, so a space in an href is always damage, never content.\n *\n * Two repairs, because the right one differs:\n * - Our own `/download/<id>` capability links (skapi-mcp file-download.js) are\n * base64url, optionally with a single `.` separating the payload and hmac of\n * the older self-describing token. That alphabet cannot contain whitespace,\n * so the spaces are purely damage and REMOVING them restores the exact link,\n * which is what makes an already-sent message clickable again. A model\n * reproducing one of these into its reply is exactly where the spaces come\n * from, which is also why the id is now short.\n * - Anything else keeps every character and only has the whitespace encoded,\n * the same thing a browser does with a space in an href. Stripping would be\n * wrong there: `…/exports/my report.csv` is a real file whose name has a\n * space in it, and deleting it points at a file that does not exist.\n */\nexport function repairUrlWhitespace(href: string): string {\n\tif (!href || !/\\s/.test(href)) return href;\n\tvar stripped = href.replace(/\\s+/g, '');\n\tif (/^https?:\\/\\/[^/\\s]+\\/download\\/[A-Za-z0-9_-]+(\\.[A-Za-z0-9_-]+)?$/i.test(stripped)) return stripped;\n\treturn href.trim().replace(/\\s/g, '%20');\n}\n\n/**\n * A model reproducing a URL sometimes HTML-escapes its `&` query separators as\n * `&` (or the numeric `&` / `&`). Left in the href that escaping\n * survives the client's own escapeAttr -> v-html/innerHTML decode round-trip and\n * reaches the browser LITERALLY, so a presigned S3 URL is navigated with its\n * parameters named `amp;Signature`, `amp;Expires`, `amp;response-content-type`,\n * ... — the real params vanish, the signature can't be located, and S3 rejects\n * it (the \"링크가 안되\" dead export link). Undo just that entity escaping.\n *\n * This is a no-op on a clean URL: a valid link carries a raw `&` between params\n * and percent-encodes (`%26`) any literal ampersand that is data, so a real URL\n * never contains `&` to begin with. Mirrors repairUrlWhitespace: it repairs\n * model damage, not the URL. The loop collapses a doubly-escaped `&amp;` too.\n */\nexport function repairUrlEntities(href: string): string {\n\tif (!href || href.indexOf('&') === -1) return href;\n\tvar out = href, prev = '';\n\twhile (out !== prev) {\n\t\tprev = out;\n\t\tout = out\n\t\t\t.replace(/&/gi, '&')\n\t\t\t.replace(/�*38;/g, '&')\n\t\t\t.replace(/�*26;/gi, '&');\n\t}\n\treturn out;\n}\n\n/**\n * Trim punctuation and unmatched wrappers that cling to a token in prose.\n * `src::a/b.pdf).` -> `src::a/b.pdf`, while a balanced `file (v2).pdf` is kept.\n */\nexport function normalizeTrailingInlineToken(value: string): string {\n\tif (!value) return value;\n\tvar out = value.replace(/[.,;:!?]+$/, '');\n\tvar trimUnmatched = function (openCh: string, closeCh: string) {\n\t\twhile (out.charAt(out.length - 1) === closeCh) {\n\t\t\tvar openCount = (out.match(new RegExp('\\\\' + openCh, 'g')) || []).length;\n\t\t\tvar closeCount = (out.match(new RegExp('\\\\' + closeCh, 'g')) || []).length;\n\t\t\tif (closeCount > openCount) out = out.slice(0, -1); else break;\n\t\t}\n\t};\n\ttrimUnmatched('(', ')');\n\ttrimUnmatched('[', ']');\n\ttrimUnmatched('{', '}');\n\tout = out.replace(/[`'\"*>]+$/, '');\n\treturn out;\n}\n\n/** A link the view renders. `expired` means the href is the `_expired_.url`\n * placeholder and a click must mint a fresh one from `remotePath`. */\nexport interface InlineLinkPart {\n\ttype: 'link';\n\tlabel: string;\n\tfullLabel: string;\n\thref: string;\n\texpired: boolean;\n\texpiredHref?: string;\n\tremotePath?: string;\n}\n\nexport interface InlineLinkContext {\n\t/** Current project id: the leading segment to strip off a db url. */\n\tserviceId: string;\n\t/** `https://db.<hostDomain>` for this deployment. */\n\tdbHostPrefix: string;\n\t/** A fresh url already minted for this placeholder, if the view cached one. */\n\tresolveFreshHref?: (expiredHref: string) => string | undefined;\n}\n\n/**\n * Decide what ONE inline-link regex match actually is, and how to render it.\n *\n * This is the single place that answers \"is this an external url, this project's\n * db file, or a bare storage path\", for every consumer. It used to live twice,\n * once in agent.vue and once in the widget, and both copies had to be found and\n * corrected for each of the link bugs this file's history records. A view now\n * supplies its own context (project id, db host, cached-href lookup) and does\n * nothing but turn the returned part into markup.\n *\n * `groups` is [g1..g6] from createInlineLinkRegex, in that order:\n * g1 src::<token> g2/g3 [label](url) g4/g5 [label](path) g6 bare url\n */\nexport function classifyInlineLink(\n\tfull: string,\n\tgroups: Array<string | undefined>,\n\tctx: InlineLinkContext,\n): { part: InlineLinkPart; tail?: string } | null {\n\tvar g1 = groups[0], g2 = groups[1], g3 = groups[2], g4 = groups[3], g5 = groups[4], g6 = groups[5];\n\tvar dbHostPrefix = (ctx.dbHostPrefix || '').toLowerCase();\n\tvar fresh = function (expiredHref: string): string | undefined {\n\t\treturn ctx.resolveFreshHref ? ctx.resolveFreshHref(expiredHref) : undefined;\n\t};\n\tvar isDbHost = function (url: string): boolean {\n\t\treturn !!dbHostPrefix && url.toLowerCase().indexOf(dbHostPrefix) === 0;\n\t};\n\t// A db path rendered as the placeholder the click handler resolves.\n\tvar asStoredFile = function (remotePath: string, label: string): { part: InlineLinkPart } | null {\n\t\tif (!remotePath) return null;\n\t\tvar expiredHref = buildDisplayExpiredAttachmentHref(remotePath, label);\n\t\tvar cached = fresh(expiredHref);\n\t\treturn {\n\t\t\tpart: {\n\t\t\t\ttype: 'link',\n\t\t\t\tlabel: truncateLabelForDisplay(label),\n\t\t\t\tfullLabel: label,\n\t\t\t\thref: cached || expiredHref,\n\t\t\t\texpired: !cached,\n\t\t\t\texpiredHref: expiredHref,\n\t\t\t\tremotePath: remotePath,\n\t\t\t},\n\t\t};\n\t};\n\n\t// src::<token> — a path, or a url the model copied out of a record.\n\tif (g1) {\n\t\tvar rawPath = normalizeTrailingInlineToken(g1);\n\t\tvar tail = full.slice(('src::' + rawPath).length);\n\t\tvar srcIsUrl = isHttpUrlLike(rawPath);\n\t\t// `src::` values come straight out of a record's unique_id, and the prompt\n\t\t// says that may be \"the file's storage path or original URL\". http:// is as\n\t\t// much a url as https://; testing only for https sent every plain-http\n\t\t// source into the storage-path branch, where it became a chip pointing at\n\t\t// this project for someone else's file.\n\t\tif (srcIsUrl && !isDbHost(rawPath) && !readExpiredAttachmentHref(rawPath)) {\n\t\t\t// decode any model-introduced `&` in the URL (tail stays keyed on\n\t\t\t// the raw match length, so it is left untouched)\n\t\t\tvar srcUrl = repairUrlEntities(rawPath);\n\t\t\treturn {\n\t\t\t\tpart: { type: 'link', label: truncateLabelForDisplay(srcUrl), fullLabel: srcUrl, href: srcUrl, expired: false },\n\t\t\t\ttail: tail,\n\t\t\t};\n\t\t}\n\t\tvar srcPath = readExpiredAttachmentHref(rawPath)\n\t\t\t|| (srcIsUrl\n\t\t\t\t? (extractRemotePathFromAttachmentHref(rawPath, ctx.serviceId) || normalizeAttachmentPathCandidate(rawPath))\n\t\t\t\t: normalizeAttachmentPathCandidate(rawPath));\n\t\tvar srcBuilt = asStoredFile(srcPath, srcPath);\n\t\treturn srcBuilt ? { part: srcBuilt.part, tail: tail } : null;\n\t}\n\n\t// [label](target) where target is NOT a url by the regex's reckoning.\n\tif (g4 && g5) {\n\t\t// An EXPLICIT db target, `[label](db:folder/file.csv)`, says what it is\n\t\t// instead of leaving us to infer it from the absence of \"http\". That is the\n\t\t// only form here that cannot be confused with anything else, and it matches\n\t\t// the scheme the backend already uses internally (db:<service>/<key>).\n\t\t// Accepted now so the clients tolerate it everywhere before anything starts\n\t\t// EMITTING it; until then this branch simply never fires.\n\t\tvar dbTarget = /^db:(.+)$/i.exec(g5.trim());\n\t\tif (dbTarget) {\n\t\t\tvar declared = asStoredFile(normalizeAttachmentPathCandidate(dbTarget[1]), g4);\n\t\t\tif (!declared) return null;\n\t\t\tdeclared.part.label = truncateLabelForDisplay(g4);\n\t\t\tdeclared.part.fullLabel = g4;\n\t\t\treturn declared;\n\t\t}\n\t\t// ...except when it is one. It only lands here because it contains\n\t\t// whitespace, which the url branch forbids and this one allows, and\n\t\t// reading a damaged url as a storage path is how a download link became a\n\t\t// dead chip. Repair it and classify it as what it is.\n\t\tif (isHttpUrlLike(g5)) {\n\t\t\treturn classifyInlineLink(full, [undefined, g4, repairUrlWhitespace(g5), undefined, undefined, undefined], ctx);\n\t\t}\n\t\t// Any OTHER scheme, or a fragment, is a link the user wrote and not a file\n\t\t// we host. `mailto:`, `tel:` and `#section` were all being turned into\n\t\t// download chips for storage paths of that literal text, so clicking one\n\t\t// asked this project for a file called \"mailto:a@b.com\".\n\t\tvar trimmedTarget = g5.trim();\n\t\tif (/^[a-z][a-z0-9+.-]*:/i.test(trimmedTarget) || trimmedTarget.charAt(0) === '#') {\n\t\t\treturn {\n\t\t\t\tpart: { type: 'link', label: truncateLabelForDisplay(g4), fullLabel: g4, href: trimmedTarget, expired: false },\n\t\t\t};\n\t\t}\n\t\tvar built = asStoredFile(normalizeAttachmentPathCandidate(g5), g4);\n\t\tif (!built) return null;\n\t\t// The label is the model's, not the path: keep it verbatim.\n\t\tbuilt.part.label = truncateLabelForDisplay(g4);\n\t\tbuilt.part.fullLabel = g4;\n\t\treturn built;\n\t}\n\n\t// [label](url) and bare urls.\n\tvar originalHref = g3 || g6 || '';\n\tif (!originalHref) return null;\n\t// A model that reproduces the URL may have HTML-escaped its `&` separators;\n\t// decode them now so every downstream check and the final href see a clean\n\t// URL (otherwise a presigned link navigates with `&` and 403s).\n\toriginalHref = repairUrlEntities(originalHref);\n\t// A bare url swallows the punctuation that ends the sentence it sits in, so\n\t// `see https://host/a.pdf.` linked to `a.pdf.` and 404'd. Trim it and hand the\n\t// trimmed text back as `tail`, exactly as the src:: branch does.\n\tvar urlTail: string | undefined;\n\tif (!g3 && g6) {\n\t\tvar trimmedUrl = normalizeTrailingInlineToken(originalHref);\n\t\tif (trimmedUrl !== originalHref) urlTail = originalHref.slice(trimmedUrl.length);\n\t\toriginalHref = trimmedUrl;\n\t}\n\tvar withTail = function (r: { part: InlineLinkPart }): { part: InlineLinkPart; tail?: string } {\n\t\treturn urlTail ? { part: r.part, tail: urlTail } : r;\n\t};\n\tvar urlLabel = g2 || originalHref;\n\n\t// THE PLACEHOLDER, read back. sanitizeAttachmentLinksForHistory writes this\n\t// form into stored history and buildBoundedChatMessages replays it to the\n\t// model, so it arrives here constantly: as a rebuilt bubble on every reload,\n\t// and as text the model copied out of its own context. It has to be checked\n\t// BEFORE the generic https branch, because it IS https and it is NOT the db\n\t// host, so that branch claimed it and rendered `expired: false` — a link to a\n\t// hostname that does not resolve, with no way to ever refresh it. Every stored\n\t// attachment link went dead on reload for exactly that reason.\n\tvar carried = readExpiredAttachmentHref(originalHref);\n\tif (carried) {\n\t\tvar carriedBuilt = asStoredFile(carried, g2 || carried);\n\t\tif (carriedBuilt) {\n\t\t\tif (g2) { carriedBuilt.part.label = truncateLabelForDisplay(g2); carriedBuilt.part.fullLabel = g2; }\n\t\t\treturn withTail(carriedBuilt);\n\t\t}\n\t}\n\n\t// This project's own db url: volatile, so render it re-mintable. A db url for\n\t// a DIFFERENT project is not ours to mint, so it stays an ordinary link rather\n\t// than a chip that would query this project for someone else's key.\n\tif (isServiceDbAttachmentHref(originalHref, ctx.serviceId)) {\n\t\tvar remotePath = extractRemotePathFromAttachmentHref(originalHref, ctx.serviceId);\n\t\tif (remotePath) {\n\t\t\tvar dbBuilt = asStoredFile(remotePath, getExpiredAttachmentVisiblePath(remotePath, urlLabel));\n\t\t\tif (dbBuilt) return withTail(dbBuilt);\n\t\t}\n\t}\n\n\t// Everything else is a link, not a path. The old rule tested for `https://`\n\t// specifically and treated ANY other target as db storage, so a plain\n\t// `http://` citation, a `mailto:`, a `#anchor` and a `/relative` link all\n\t// rendered as download chips for storage paths that never existed, and\n\t// clicking one raised \"failed to refresh\" on a file the user never had.\n\treturn withTail({\n\t\tpart: { type: 'link', label: truncateLabelForDisplay(urlLabel), fullLabel: urlLabel, href: originalHref, expired: false },\n\t});\n}\n\nexport function truncateLabelForDisplay(label: string): string {\n\tif (!label) return label;\n\tif (label.length <= LINK_LABEL_MAX_DISPLAY_CHARS) return label;\n\treturn '…' + label.slice(label.length - (LINK_LABEL_MAX_DISPLAY_CHARS - 1));\n}\n","/**\n * Token-budgeting (pure). Moved verbatim from the chatbox. Constants are shared\n * module-level values (identical in both consumers); a config knob is premature.\n * buildBoundedChatMessages now takes `serviceId` in its options so it can pass it\n * to sanitizeAttachmentLinksForHistory (which used to read a global).\n */\nimport { sanitizeAttachmentLinksForHistory } from './links';\n\nexport var CONTEXT_WINDOW_DEFAULT: Record<string, number> = { claude: 200000, openai: 128000 };\nexport var CONTEXT_WINDOW_BY_MODEL: Record<string, number> = {\n\t'claude-opus-4-7': 200000, 'claude-sonnet-4': 200000, 'gpt-5.4': 128000,\n};\nexport var OUTPUT_TOKEN_RESERVE = 22000;\nexport var TOOL_AND_RESPONSE_BUFFER = 4000;\nexport var MIN_INPUT_TOKEN_BUDGET = 8000;\nexport var CLAUDE_PER_REQUEST_INPUT_CAP = 28000;\nexport var MAX_HISTORY_MESSAGES = 20;\nexport var HISTORY_TOKEN_BUDGET = 8000;\n\nexport function estimateTextTokens(text: string): number {\n\treturn Math.ceil((text || '').length / 3);\n}\n\nexport function estimateMessageTokens(msg: { role: string; content: string }): number {\n\treturn estimateTextTokens(msg.content) + estimateTextTokens(msg.role) + 6;\n}\n\nexport function getContextWindow(platform: string, model?: string): number {\n\tvar normalized = (model || '').trim().toLowerCase();\n\tif (normalized && CONTEXT_WINDOW_BY_MODEL[normalized]) return CONTEXT_WINDOW_BY_MODEL[normalized];\n\treturn CONTEXT_WINDOW_DEFAULT[platform];\n}\n\nexport function stripFileBlocksFromHistory(content: string): string {\n\tif (!content) return content;\n\treturn content.replace(/```([^\\n`]+?\\.[^\\s.`]+)\\n[\\s\\S]*?```/g, '[file previously attached: $1]');\n}\n\nexport type BoundedChatOptions = {\n\tplatform: string;\n\tmodel?: string;\n\tsystemPrompt: string;\n\thistory: Array<{ role: string; content: string }>;\n\t/** Used to strip/rewrite expired attachment links in older user turns. */\n\tserviceId: string;\n};\n\nexport function buildBoundedChatMessages(options: BoundedChatOptions) {\n\tvar contextWindow = getContextWindow(options.platform, options.model);\n\tvar contextBasedBudget = Math.max(MIN_INPUT_TOKEN_BUDGET,\n\t\tcontextWindow - OUTPUT_TOKEN_RESERVE - TOOL_AND_RESPONSE_BUFFER);\n\tvar availableInputBudget = options.platform === 'claude'\n\t\t? Math.min(contextBasedBudget, CLAUDE_PER_REQUEST_INPUT_CAP) : contextBasedBudget;\n\tvar systemCost = estimateTextTokens(options.systemPrompt) + 12;\n\tvar budgetForHistory = Math.max(1000, Math.min(HISTORY_TOKEN_BUDGET, availableInputBudget - systemCost));\n\tvar windowed = options.history.slice(-MAX_HISTORY_MESSAGES);\n\tvar latestIndex = windowed.length - 1;\n\tvar trimmed = windowed.map(function (m, i) {\n\t\tif (i === latestIndex) return m;\n\t\tvar stripped = stripFileBlocksFromHistory(m.content);\n\t\t// Sanitize BOTH roles: user turns via the \"Attached files:\" block, assistant\n\t\t// turns via the safe db-only path (forAssistant=true) so a volatile db url the\n\t\t// model emitted doesn't get replayed into the LLM context as a dead link.\n\t\tvar sanitized = sanitizeAttachmentLinksForHistory(stripped, options.serviceId, m.role !== 'user');\n\t\treturn Object.assign({}, m, { content: sanitized });\n\t});\n\tvar bounded: Array<{ role: string; content: string }> = [], used = 0;\n\tfor (var i = trimmed.length - 1; i >= 0; i--) {\n\t\tvar cost = estimateMessageTokens(trimmed[i]);\n\t\tif (used + cost > budgetForHistory && bounded.length > 0) break;\n\t\tbounded.unshift(trimmed[i]); used += cost;\n\t}\n\treturn {\n\t\tmessages: bounded.map(function (m) { return { role: m.role, content: m.content }; }),\n\t\tdroppedCount: Math.max(0, options.history.length - bounded.length),\n\t\testimatedInputTokens: used + systemCost,\n\t\testimatedBudget: availableInputBudget,\n\t};\n}\n","/**\n * Chat timestamp formatting, shared so agent.vue and the widget render an\n * identical \"small text under the bubble\". Pure and locale-aware: it formats a\n * given epoch-ms value, it never reads the current time, so it stays testable and\n * DOM-free.\n */\n\n/** Wall-clock epoch ms. Separate from the engine's monotonic nowMs() (which is\n * performance.now() when available and therefore NOT epoch): a displayed\n * timestamp must be wall time. */\nexport function wallClockNow(): number {\n\treturn Date.now();\n}\n\n/**\n * \"Jul 24, 2026, 3:42:07 PM\" (locale-formatted). Empty string for a missing or\n * non-finite value, so a caller can gate rendering on the result being truthy and\n * a pending bubble (no timestamp yet) simply shows nothing.\n */\nexport function formatChatTimestamp(ms?: number): string {\n\tif (typeof ms !== 'number' || !isFinite(ms) || ms <= 0) return '';\n\ttry {\n\t\treturn new Date(ms).toLocaleString(undefined, {\n\t\t\tyear: 'numeric',\n\t\t\tmonth: 'short',\n\t\t\tday: 'numeric',\n\t\t\thour: 'numeric',\n\t\t\tminute: '2-digit',\n\t\t\tsecond: '2-digit',\n\t\t});\n\t} catch (e) {\n\t\treturn '';\n\t}\n}\n","/**\n * AI request builders + dispatch transport (framework-agnostic).\n *\n * Ported from www.skapi.com/src/code/ai_agent.ts. The only changes vs the\n * original are dependency-injection seams:\n * - `skapi.clientSecretRequest*` -> chatEngineConfig().clientSecretRequest*\n * - MCP endpoint URL -> chatEngineConfig().mcpBaseUrl\n * - `poll` on each request -> pollOpt() (set per consumer; see config.ts)\n * - Vue `reactive`/`ref` removed (bgTaskQueue/agentViewMounted are app-level\n * state that stays in the consumer, not here;\n * only the BgTaskEntry TYPE lives here)\n */\nimport { buildIndexingSystemPrompt, buildIndexingUserMessage, buildIndexingContinueMessage, buildIndexingRenderMessage, buildIndexingRenderContinueTemplate, buildIndexingWindowMessage } from './prompts';\nimport { isServerExtractable, isPagedReadFile, isImageVisionFile, isWindowedReadFile, makeExtractPlaceholder, makeRenderPlaceholder, makeWindowPlaceholder, RENDER_PAGES_PER_WINDOW, type ExtractDirective, type FileUrlDirective } from './office';\nimport { chatEngineConfig, pollOpt, windowedIndexingEnabled } from './config';\n\nexport const ANTHROPIC_MESSAGES_API_URL = 'https://api.anthropic.com/v1/messages';\nconst ANTHROPIC_MODELS_API_URL = 'https://api.anthropic.com/v1/models';\nconst ANTHROPIC_VERSION = '2023-06-01';\nconst ANTHROPIC_MCP_BETA = 'mcp-client-2025-11-20';\nconst ANTHROPIC_WEB_FETCH_BETA = 'web-fetch-2025-09-10';\nconst ANTHROPIC_PROMPT_CACHING_BETA = 'prompt-caching-2024-07-31';\nconst ANTHROPIC_BETA_HEADER = `${ANTHROPIC_MCP_BETA},${ANTHROPIC_WEB_FETCH_BETA},${ANTHROPIC_PROMPT_CACHING_BETA}`;\nconst WEB_FETCH_MAX_USES = 40;\nconst WEB_FETCH_MAX_CONTENT_TOKENS = 200000;\n\nexport const OPENAI_RESPONSES_API_URL = 'https://api.openai.com/v1/responses';\nconst OPENAI_MODELS_API_URL = 'https://api.openai.com/v1/models';\nconst MAX_TOKENS = 25000;\nconst DEFAULT_OPENAI_IMAGE_DETAIL = 'auto';\nconst OPENAI_WEB_SEARCH_ENABLED = true;\nconst OPENAI_WEB_SEARCH_EXTERNAL_WEB_ACCESS = true;\nexport const MCP_NAME = 'BunnyQuery';\n\nexport const DEFAULT_CLAUDE_MODEL = 'claude-sonnet-4-6';\nexport const DEFAULT_OPENAI_MODEL = 'gpt-5.6-luna';\n\nconst mcpUrl = () => chatEngineConfig().mcpBaseUrl;\nconst clientSecretRequest = (opts: any) => chatEngineConfig().clientSecretRequest(opts);\n\n// Resolve the per-image `detail` for OpenAI. The version match tolerates a\n// trailing variant/date suffix (`gpt-5.4-nano`, `-mini`, `-2026-01-01`, …):\n// previously the pattern was anchored with no suffix allowed, so EVERY suffixed\n// model silently fell through to 'auto' — i.e. the cheap tiers that most need\n// resolution were the ones getting downsampled images.\n//\n// Base models keep their exact previous behavior ('original'). A suffixed\n// variant resolves to 'high' rather than 'original': 'high' is the universally\n// supported value, and we have no way to confirm a given variant accepts\n// 'original' — sending an unsupported value would fail the whole request, which\n// is far worse than a slightly less detailed image.\nconst getOpenAIImageDetail = (model?: string) => {\n\tconst normalized = (model || DEFAULT_OPENAI_MODEL).trim().toLowerCase();\n\tconst match = normalized.match(/^gpt-(\\d+)(?:\\.(\\d+))?(-[a-z0-9.\\-]+)?$/);\n\tif (!match) {\n\t\treturn DEFAULT_OPENAI_IMAGE_DETAIL;\n\t}\n\n\tconst major = Number(match[1]);\n\tconst minor = match[2] === undefined ? null : Number(match[2]);\n\tconst isVariant = !!match[3];\n\n\tconst supportsOriginal = major > 5 || (major === 5 && minor !== null && minor >= 4);\n\tif (!supportsOriginal) {\n\t\treturn DEFAULT_OPENAI_IMAGE_DETAIL;\n\t}\n\n\treturn isVariant ? 'high' : 'original';\n};\n\n// Per-image `detail` for WORKER-RENDERED document pages (the `_skapi_render`\n// path). Same resolution as above with one difference: these are dense scans\n// whose entire purpose is to be read, so 'auto' is never acceptable — it lets\n// the API downsample exactly the pixels the model needs to OCR. Floor it at\n// 'high'; models that support full-resolution 'original' still get it.\n//\n// Without this the worker falls back to its own model-blind default ('high'),\n// which silently denies the strongest models the 'original' detail they support.\nconst getRenderImageDetail = (model?: string) => {\n\tconst detail = getOpenAIImageDetail(model);\n\treturn detail === DEFAULT_OPENAI_IMAGE_DETAIL ? 'high' : detail;\n};\n\nexport type ClaudeRole = 'user' | 'assistant';\n\nexport type ClaudeMessage = {\n\trole: ClaudeRole;\n\tcontent: string;\n};\n\nexport type OpenAIMessage = {\n\trole: ClaudeRole;\n\tcontent: string;\n};\n\nexport type ClaudeMcpToolConfig = {\n\tenabled?: boolean;\n\tdefer_loading?: boolean;\n};\n\nexport type ClaudeMcpServerRequest = {\n\tname: string;\n\turl: string;\n\tauthorizationToken?: string;\n\tdefaultConfig?: ClaudeMcpToolConfig;\n\tconfigs?: Record<string, ClaudeMcpToolConfig>;\n};\n\nconst IMAGE_URL_REGEX =\n\t/\\bhttps?:\\/\\/[^\\s<>\"'()\\[\\]]+?\\.(?:jpg|jpeg|png|gif|webp)(?:\\?[^\\s<>\"'()\\[\\]]*)?/gi;\n\nexport function transformContentWithImages(\n\tcontent: string,\n): string | Array<Record<string, any>> {\n\tif (typeof content !== 'string' || !content) {\n\t\treturn content;\n\t}\n\n\tconst matches = content.match(IMAGE_URL_REGEX);\n\n\tif (!matches || !matches.length) {\n\t\treturn content;\n\t}\n\n\tconst seen = new Set<string>();\n\tconst imageBlocks: Array<Record<string, any>> = [];\n\n\tfor (const url of matches) {\n\t\tif (seen.has(url)) continue;\n\t\tseen.add(url);\n\t\timageBlocks.push({\n\t\t\ttype: 'image',\n\t\t\tsource: { type: 'url', url },\n\t\t});\n\t}\n\n\treturn [...imageBlocks, { type: 'text', text: content }];\n}\n\nfunction prepareClaudeMessages(messages: ClaudeMessage[]) {\n\tif (!messages.length) return messages;\n\t// Only transform the most recent user message. Historical user messages\n\t// may reference image URLs that are now stale (deleted, moved, expired).\n\tconst lastIndex = messages.length - 1;\n\tconst last = messages[lastIndex];\n\tif (last.role !== 'user') return messages;\n\tconst content = transformContentWithImages(last.content);\n\tif (content === last.content) return messages;\n\tconst next = messages.slice();\n\tnext[lastIndex] = { role: last.role, content } as unknown as ClaudeMessage;\n\treturn next;\n}\n\nexport function transformContentWithOpenAIImages(\n\tcontent: string,\n\tdetail = DEFAULT_OPENAI_IMAGE_DETAIL,\n): string | Array<Record<string, any>> {\n\tif (typeof content !== 'string' || !content) {\n\t\treturn content;\n\t}\n\n\tconst matches = content.match(IMAGE_URL_REGEX);\n\n\tif (!matches || !matches.length) {\n\t\treturn content;\n\t}\n\n\tconst seen = new Set<string>();\n\tconst imageBlocks: Array<Record<string, any>> = [];\n\n\tfor (const url of matches) {\n\t\tif (seen.has(url)) continue;\n\t\tseen.add(url);\n\t\timageBlocks.push({\n\t\t\ttype: 'input_image',\n\t\t\timage_url: url,\n\t\t\tdetail,\n\t\t});\n\t}\n\n\treturn [{ type: 'input_text', text: content }, ...imageBlocks];\n}\n\nfunction prepareOpenAIMessages(\n\tmessages: OpenAIMessage[],\n\tdetail = DEFAULT_OPENAI_IMAGE_DETAIL,\n) {\n\tif (!messages.length) return messages;\n\tconst lastIndex = messages.length - 1;\n\tconst last = messages[lastIndex];\n\tif (last.role !== 'user') return messages;\n\tconst content = transformContentWithOpenAIImages(last.content, detail);\n\tif (content === last.content) return messages;\n\tconst next = messages.slice();\n\tnext[lastIndex] = { role: last.role, content } as unknown as OpenAIMessage;\n\treturn next;\n}\n\n// Attach a cache_control breakpoint to the last message of the stable history\n// prefix (everything except the final user turn) so Anthropic re-uses it at\n// ~10% input-token billing.\nfunction applyHistoryCacheBreakpoint(messages: any[]): any[] {\n\tif (messages.length < 2) return messages;\n\tconst breakpointIndex = messages.length - 2;\n\treturn messages.map((m, i) => {\n\t\tif (i !== breakpointIndex) return m;\n\t\tconst blocks = Array.isArray(m.content)\n\t\t\t? m.content.slice()\n\t\t\t: [{ type: 'text', text: m.content }];\n\t\tif (!blocks.length) return m;\n\t\tconst lastBlockIndex = blocks.length - 1;\n\t\tblocks[lastBlockIndex] = {\n\t\t\t...blocks[lastBlockIndex],\n\t\t\tcache_control: { type: 'ephemeral' },\n\t\t};\n\t\treturn { ...m, content: blocks };\n\t});\n}\n\nexport type CallClaudeWithMcpParams = {\n\tprompt: string;\n\tmessages?: ClaudeMessage[];\n\tservice: string;\n\towner: string;\n\tuserId?: string;\n\tmodel?: string;\n\tmaxTokens?: number;\n\tsystem?: string;\n\tmcpServer: ClaudeMcpServerRequest;\n\textractContent?: ExtractDirective[];\n\tfileUrls?: FileUrlDirective[];\n\tonResponse?: (res: any) => void;\n\tonError?: (err: any) => void;\n};\nexport const POLL_INTERVAL = 1500;\nexport async function callClaudeWithMcp({\n\tprompt,\n\tmessages,\n\tservice,\n\towner,\n\tuserId,\n\tmodel = DEFAULT_CLAUDE_MODEL,\n\tmaxTokens = 1000,\n\tsystem,\n\tmcpServer,\n\textractContent,\n\tfileUrls,\n}: CallClaudeWithMcpParams) {\n\tconst mcpServerDefinition: Record<string, any> = {\n\t\ttype: 'url',\n\t\tname: mcpServer.name,\n\t\turl: mcpServer.url,\n\t};\n\n\tif (mcpServer.authorizationToken) {\n\t\tmcpServerDefinition.authorization_token = mcpServer.authorizationToken;\n\t}\n\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'claude',\n\t\tqueue: userId || service,\n\t\tservice,\n\t\towner,\n\t\t...pollOpt(),\n\t\turl: ANTHROPIC_MESSAGES_API_URL,\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'content-type': 'application/json',\n\t\t\t'x-api-key': '$CLIENT_SECRET',\n\t\t\t'anthropic-version': ANTHROPIC_VERSION,\n\t\t\t'anthropic-beta': ANTHROPIC_BETA_HEADER,\n\t\t},\n\t\tdata: {\n\t\t\tmodel,\n\t\t\tmax_tokens: maxTokens,\n\t\t\t...(extractContent && extractContent.length\n\t\t\t\t? { _skapi_extract: extractContent }\n\t\t\t\t: {}),\n\t\t\t...(fileUrls && fileUrls.length\n\t\t\t\t? { _skapi_file_urls: fileUrls }\n\t\t\t\t: {}),\n\t\t\t...(system\n\t\t\t\t? {\n\t\t\t\t\t\tsystem: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\ttext: system,\n\t\t\t\t\t\t\t\tcache_control: { type: 'ephemeral' },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\tmessages: (() => {\n\t\t\t\tconst prepared =\n\t\t\t\t\tmessages && messages.length\n\t\t\t\t\t\t? prepareClaudeMessages(messages)\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\trole: 'user',\n\t\t\t\t\t\t\t\t\tcontent: transformContentWithImages(prompt),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t];\n\t\t\t\treturn applyHistoryCacheBreakpoint(prepared as any[]);\n\t\t\t})(),\n\t\t\tmcp_servers: [mcpServerDefinition],\n\t\t\ttools: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'mcp_toolset',\n\t\t\t\t\tmcp_server_name: mcpServer.name,\n\t\t\t\t\t...(mcpServer.defaultConfig\n\t\t\t\t\t\t? { default_config: mcpServer.defaultConfig }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...(mcpServer.configs ? { configs: mcpServer.configs } : {}),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'web_fetch_20250910',\n\t\t\t\t\tname: 'web_fetch',\n\t\t\t\t\tmax_uses: WEB_FETCH_MAX_USES,\n\t\t\t\t\tcitations: { enabled: true },\n\t\t\t\t\tmax_content_tokens: WEB_FETCH_MAX_CONTENT_TOKENS,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t});\n}\n\nexport async function callClaudeWithPublicMcp(\n\tprompt: string,\n\tservice: string,\n\towner: string,\n\tmessages?: ClaudeMessage[],\n\tsystem?: string,\n\tmodel?: string,\n\tuserId?: string,\n\textractContent?: ExtractDirective[],\n\tfileUrls?: FileUrlDirective[],\n\tonResponse?: (res: any) => void,\n\tonError?: (err: any) => void,\n) {\n\treturn callClaudeWithMcp({\n\t\tprompt,\n\t\tmessages,\n\t\tservice,\n\t\towner,\n\t\tuserId,\n\t\tmodel: model || DEFAULT_CLAUDE_MODEL,\n\t\tmaxTokens: MAX_TOKENS,\n\t\tsystem,\n\t\textractContent,\n\t\tfileUrls,\n\t\tmcpServer: {\n\t\t\tname: MCP_NAME,\n\t\t\turl: mcpUrl(),\n\t\t\tauthorizationToken: '$ACCESS_TOKEN',\n\t\t},\n\t\tonResponse,\n\t\tonError,\n\t});\n}\n\nexport async function callOpenAIWithPublicMcp(\n\tprompt: string,\n\tservice: string,\n\towner: string,\n\tmessages?: OpenAIMessage[],\n\tsystem?: string,\n\tmodel?: string,\n\tuserId?: string,\n\textractContent?: ExtractDirective[],\n\tfileUrls?: FileUrlDirective[],\n\tonResponse?: (res: any) => void,\n\tonError?: (err: any) => void,\n) {\n\tconst resolvedModel = model || DEFAULT_OPENAI_MODEL;\n\tconst imageDetail = getOpenAIImageDetail(resolvedModel);\n\tconst messageList =\n\t\tmessages && messages.length\n\t\t\t? prepareOpenAIMessages(messages, imageDetail)\n\t\t\t: [\n\t\t\t\t{\n\t\t\t\t\trole: 'user' as const,\n\t\t\t\t\tcontent: transformContentWithOpenAIImages(prompt, imageDetail),\n\t\t\t\t},\n\t\t\t];\n\n\tconst responseInput = [\n\t\t...(system\n\t\t\t? [\n\t\t\t\t{\n\t\t\t\t\trole: 'system',\n\t\t\t\t\tcontent: system,\n\t\t\t\t},\n\t\t\t]\n\t\t\t: []),\n\t\t...messageList.map((m) => ({\n\t\t\trole: m.role,\n\t\t\tcontent: m.content,\n\t\t})),\n\t];\n\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'openai',\n\t\tqueue: userId || service,\n\t\tservice,\n\t\towner,\n\t\t...pollOpt(),\n\t\turl: OPENAI_RESPONSES_API_URL,\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'content-type': 'application/json',\n\t\t\tAuthorization: 'Bearer $CLIENT_SECRET',\n\t\t},\n\t\tdata: {\n\t\t\tmodel: resolvedModel,\n\t\t\tmax_output_tokens: MAX_TOKENS,\n\t\t\t...(extractContent && extractContent.length\n\t\t\t\t? { _skapi_extract: extractContent }\n\t\t\t\t: {}),\n\t\t\t...(fileUrls && fileUrls.length\n\t\t\t\t? { _skapi_file_urls: fileUrls }\n\t\t\t\t: {}),\n\t\t\tinput: responseInput,\n\t\t\ttools: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'mcp',\n\t\t\t\t\tserver_label: MCP_NAME,\n\t\t\t\t\tserver_url: mcpUrl(),\n\t\t\t\t\trequire_approval: 'never',\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: 'Bearer $ACCESS_TOKEN',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t...(OPENAI_WEB_SEARCH_ENABLED\n\t\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'web_search',\n\t\t\t\t\t\t\texternal_web_access: OPENAI_WEB_SEARCH_EXTERNAL_WEB_ACCESS,\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t\t: []),\n\t\t\t],\n\t\t},\n\t});\n}\n\nexport type AttachmentSaveInfo = {\n\tplatform: 'claude' | 'openai';\n\tmodel?: string;\n\tservice: string;\n\towner: string;\n\tuserId?: string;\n\tserviceName?: string;\n\tserviceDescription?: string;\n\tattachment: {\n\t\tname: string;\n\t\tstoragePath: string;\n\t\tmime?: string;\n\t\tsize?: number;\n\t\turl: string;\n\t};\n\t/**\n\t * Content parsed CLIENT-SIDE by an attachment-parser plugin (e.g. an .hwp\n\t * parser). When set, it is inlined into the indexing message verbatim and\n\t * takes precedence over server-side office extraction / web_fetch.\n\t */\n\tparsedContent?: string;\n\t/**\n\t * True for a RESUME pass: a previous indexing pass could not finish this (large)\n\t * file, so continue it - always via readFileContent paging, with a \"continue\"\n\t * message telling the agent to resume from where the saved records leave off.\n\t */\n\tcontinueIndexing?: boolean;\n\t/**\n\t * For an image-vision file (PDF), the 0-based PAGE the render window should start at.\n\t * The worker renders [renderFrom, renderFrom+RENDER_PAGES_PER_WINDOW) and injects them\n\t * as image blocks; the resume loop advances this by a window each pass.\n\t */\n\trenderFrom?: number;\n};\n\n// RESUME pass: continue indexing a large file a previous pass could not finish. Same\n// dispatch as notifyAgentSaveAttachment, but forced onto the paging path with a\n// \"continue from where the saved records leave off\" message.\nexport async function notifyAgentContinueIndexing(info: AttachmentSaveInfo) {\n\treturn notifyAgentSaveAttachment({ ...info, continueIndexing: true });\n}\n\n// Background \"save into knowledge\" call (not a chat turn). A client-parsed file\n// (parser plugin) is inlined directly; otherwise office files get the\n// _skapi_extract directive + a placeholder, and everything else gets a URL.\nexport async function notifyAgentSaveAttachment(info: AttachmentSaveInfo) {\n\tconst { platform, service, owner, attachment, parsedContent } = info;\n\n\t// A CONTINUE pass resumes a large file that a previous pass could not finish.\n\tconst continuing = !!info.continueIndexing;\n\n\t// VISION files (PDFs) are delivered as rendered page IMAGES injected into the message by\n\t// the worker (`_skapi_render`), because tool-result images render on neither provider.\n\t// Both the first pass and every resume pass use this; renderFrom advances the page window.\n\tconst visionFile = !parsedContent && isImageVisionFile(attachment.name, attachment.mime);\n\tconst renderFrom = Math.max(0, info.renderFrom || 0);\n\tconst renderPlaceholder = visionFile ? makeRenderPlaceholder(attachment.storagePath) : undefined;\n\t// Tell the worker what image `detail` to stamp on the injected page blocks.\n\t// The worker is model-blind, so without this it applies a one-size default and\n\t// the strongest models never get the 'original' detail they support. Only\n\t// meaningful for OpenAI — Claude has no per-image detail knob and the worker\n\t// ignores the field for it.\n\tconst renderDetail = platform === 'openai'\n\t\t? getRenderImageDetail(info.model || DEFAULT_OPENAI_MODEL)\n\t\t: undefined;\n\t// `auto_continue` + `continue_text` hand the page loop to the WORKER: when its renderer\n\t// reports pages left after this window, it builds the next pass from this template\n\t// (substituting the window's 1-based start page for RENDER_FROM_TOKEN) and enqueues it\n\t// itself. That is what makes a 500-page document index end-to-end — the loop no longer\n\t// depends on the tab staying open, nor on the model correctly declaring itself unfinished.\n\tconst skapiRender = visionFile && renderPlaceholder\n\t\t? {\n\t\t\t_skapi_render: [\n\t\t\t\t{\n\t\t\t\t\tpath: attachment.storagePath, from: renderFrom, count: RENDER_PAGES_PER_WINDOW,\n\t\t\t\t\tplaceholder: renderPlaceholder, name: attachment.name, mime: attachment.mime, detail: renderDetail,\n\t\t\t\t\tauto_continue: true,\n\t\t\t\t\tcontinue_text: buildIndexingRenderContinueTemplate(attachment, renderPlaceholder),\n\t\t\t\t},\n\t\t\t],\n\t\t}\n\t\t: {};\n\n\t// SERVER-DRIVEN windowed read. When enabled, the worker reads one window of the file\n\t// per request and continues from the reader's own cursor until the file is exhausted,\n\t// so the traversal no longer lives inside the model's turn budget.\n\t//\n\t// Flag-gated because the BACKEND MUST SHIP FIRST: against a worker that does not strip\n\t// `_skapi_window`, the directive reaches the provider as an unknown body field and the\n\t// call fails terminally with no retry.\n\tconst windowedRead =\n\t\t!visionFile && !parsedContent && windowedIndexingEnabled() &&\n\t\tisWindowedReadFile(attachment.name, attachment.mime);\n\tconst windowPlaceholder = windowedRead ? makeWindowPlaceholder(attachment.storagePath) : undefined;\n\tconst skapiWindow = windowedRead && windowPlaceholder\n\t\t? {\n\t\t\t_skapi_window: [\n\t\t\t\t{\n\t\t\t\t\tpath: attachment.storagePath,\n\t\t\t\t\tcursor: null,\n\t\t\t\t\tplaceholder: windowPlaceholder,\n\t\t\t\t\tname: attachment.name,\n\t\t\t\t\tmime: attachment.mime,\n\t\t\t\t\tkind: 'window',\n\t\t\t\t\tauto_continue: true,\n\t\t\t\t\tcontinue_text: buildIndexingWindowMessage(attachment, windowPlaceholder, true),\n\t\t\t\t},\n\t\t\t],\n\t\t}\n\t\t: {};\n\n\t// Spreadsheets are read by PAGING through readFileContent (grid rows), NOT inlined - so\n\t// they skip the inline server-extract and the agent is told to page the whole file.\n\tconst pagedRead = !visionFile && !windowedRead && (continuing || (!parsedContent && isPagedReadFile(attachment.name, attachment.mime)));\n\n\t// Client-parsed content wins over server-side extraction.\n\tconst serverExtract = !visionFile && !windowedRead && !continuing && !parsedContent && !pagedRead && isServerExtractable(attachment.name, attachment.mime);\n\tconst placeholder = serverExtract ? makeExtractPlaceholder(attachment.storagePath) : undefined;\n\tconst extractContent: ExtractDirective[] | undefined =\n\t\tserverExtract && placeholder\n\t\t\t? [{ path: attachment.storagePath, placeholder, name: attachment.name, mime: attachment.mime }]\n\t\t\t: undefined;\n\tconst skapiExtract =\n\t\textractContent && extractContent.length ? { _skapi_extract: extractContent } : {};\n\n\tconst userMessage = (visionFile && renderPlaceholder)\n\t\t? buildIndexingRenderMessage(attachment, renderPlaceholder, renderFrom)\n\t\t: (windowedRead && windowPlaceholder)\n\t\t? buildIndexingWindowMessage(attachment, windowPlaceholder, false)\n\t\t: continuing\n\t\t\t? buildIndexingContinueMessage(attachment)\n\t\t\t: buildIndexingUserMessage(\n\t\t\t\tattachment,\n\t\t\t\tparsedContent\n\t\t\t\t\t? { inlineContent: parsedContent }\n\t\t\t\t\t: placeholder\n\t\t\t\t\t\t? { inlineContentPlaceholder: placeholder }\n\t\t\t\t\t\t: pagedRead\n\t\t\t\t\t\t\t? { pagedRead: true }\n\t\t\t\t\t\t\t: undefined,\n\t\t\t);\n\n\tconst systemPrompt = buildIndexingSystemPrompt({\n\t\tservice,\n\t\tserviceName: info.serviceName,\n\t\tserviceDescription: info.serviceDescription,\n\t});\n\n\tif (platform === 'openai') {\n\t\tconst resolvedModel = info.model || DEFAULT_OPENAI_MODEL;\n\t\tconst imageDetail = getOpenAIImageDetail(resolvedModel);\n\t\treturn clientSecretRequest({\n\t\t\tclientSecretName: 'openai',\n\t\t\tqueue: (info.userId || service) + BG_INDEXING_QUEUE_SUFFIX,\n\t\t\tservice,\n\t\t\towner,\n\t\t\t...pollOpt(),\n\t\t\turl: OPENAI_RESPONSES_API_URL,\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'content-type': 'application/json',\n\t\t\t\tAuthorization: 'Bearer $CLIENT_SECRET',\n\t\t\t},\n\t\t\tdata: {\n\t\t\t\tmodel: resolvedModel,\n\t\t\t\tmax_output_tokens: MAX_TOKENS,\n\t\t\t\t...skapiExtract,\n\t\t\t\t...skapiRender,\n\t\t\t\t...skapiWindow,\n\t\t\t\tinput: [\n\t\t\t\t\t{ role: 'system', content: systemPrompt },\n\t\t\t\t\t{\n\t\t\t\t\t\trole: 'user',\n\t\t\t\t\t\tcontent: transformContentWithOpenAIImages(userMessage, imageDetail),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\ttools: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'mcp',\n\t\t\t\t\t\tserver_label: MCP_NAME,\n\t\t\t\t\t\tserver_url: mcpUrl(),\n\t\t\t\t\t\trequire_approval: 'never',\n\t\t\t\t\t\theaders: { Authorization: 'Bearer $ACCESS_TOKEN' },\n\t\t\t\t\t},\n\t\t\t\t\t...(OPENAI_WEB_SEARCH_ENABLED\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: 'web_search',\n\t\t\t\t\t\t\t\t\texternal_web_access: OPENAI_WEB_SEARCH_EXTERNAL_WEB_ACCESS,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: []),\n\t\t\t\t],\n\t\t\t},\n\t\t});\n\t}\n\n\tconst resolvedModel = info.model || DEFAULT_CLAUDE_MODEL;\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'claude',\n\t\tqueue: (info.userId || service) + BG_INDEXING_QUEUE_SUFFIX,\n\t\tservice,\n\t\towner,\n\t\t...pollOpt(),\n\t\turl: ANTHROPIC_MESSAGES_API_URL,\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'content-type': 'application/json',\n\t\t\t'x-api-key': '$CLIENT_SECRET',\n\t\t\t'anthropic-version': ANTHROPIC_VERSION,\n\t\t\t'anthropic-beta': ANTHROPIC_BETA_HEADER,\n\t\t},\n\t\tdata: {\n\t\t\tmodel: resolvedModel,\n\t\t\tmax_tokens: MAX_TOKENS,\n\t\t\t...skapiExtract,\n\t\t\t...skapiRender,\n\t\t\t...skapiWindow,\n\t\t\tsystem: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\ttext: systemPrompt,\n\t\t\t\t\tcache_control: { type: 'ephemeral' },\n\t\t\t\t},\n\t\t\t],\n\t\t\tmessages: [\n\t\t\t\t{\n\t\t\t\t\trole: 'user',\n\t\t\t\t\tcontent: transformContentWithImages(userMessage),\n\t\t\t\t},\n\t\t\t],\n\t\t\tmcp_servers: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'url',\n\t\t\t\t\tname: MCP_NAME,\n\t\t\t\t\turl: mcpUrl(),\n\t\t\t\t\tauthorization_token: '$ACCESS_TOKEN',\n\t\t\t\t},\n\t\t\t],\n\t\t\ttools: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'mcp_toolset',\n\t\t\t\t\tmcp_server_name: MCP_NAME,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'web_fetch_20250910',\n\t\t\t\t\tname: 'web_fetch',\n\t\t\t\t\tmax_uses: WEB_FETCH_MAX_USES,\n\t\t\t\t\tcitations: { enabled: true },\n\t\t\t\t\tmax_content_tokens: WEB_FETCH_MAX_CONTENT_TOKENS,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t});\n}\n\nexport function extractClaudeText(response: any) {\n\tif (!Array.isArray(response?.content)) {\n\t\treturn '';\n\t}\n\n\treturn response.content\n\t\t.filter((block: any) => block?.type === 'text')\n\t\t.map((block: any) => block.text)\n\t\t.join('\\n');\n}\n\nexport function extractOpenAIText(response: any) {\n\tif (\n\t\ttypeof response?.output_text === 'string' &&\n\t\tresponse.output_text.length\n\t) {\n\t\treturn response.output_text;\n\t}\n\n\tif (Array.isArray(response?.output)) {\n\t\tconst text = response.output\n\t\t\t.flatMap((item: any) => item?.content || [])\n\t\t\t.filter((part: any) => part?.type === 'output_text')\n\t\t\t.map((part: any) => part.text || '')\n\t\t\t.join('\\n')\n\t\t\t.trim();\n\n\t\tif (text) {\n\t\t\treturn text;\n\t\t}\n\t}\n\n\tconst content = response?.choices?.[0]?.message?.content;\n\n\tif (typeof content === 'string') {\n\t\treturn content;\n\t}\n\n\tif (Array.isArray(content)) {\n\t\treturn content\n\t\t\t.map((part: any) => {\n\t\t\t\tif (typeof part === 'string') {\n\t\t\t\t\treturn part;\n\t\t\t\t}\n\t\t\t\tif (part?.type === 'text') {\n\t\t\t\t\treturn part.text || '';\n\t\t\t\t}\n\t\t\t\treturn '';\n\t\t\t})\n\t\t\t.join('\\n');\n\t}\n\n\treturn '';\n}\n\nexport async function listClaudeModels(service: string, owner: string) {\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'claude',\n\t\tservice,\n\t\towner,\n\t\turl: ANTHROPIC_MODELS_API_URL,\n\t\tmethod: 'GET',\n\t\theaders: {\n\t\t\t'x-api-key': '$CLIENT_SECRET',\n\t\t\t'anthropic-version': ANTHROPIC_VERSION,\n\t\t},\n\t});\n}\n\nexport async function listOpenAIModels(service: string, owner: string) {\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'openai',\n\t\tservice,\n\t\towner,\n\t\turl: OPENAI_MODELS_API_URL,\n\t\tmethod: 'GET',\n\t\theaders: {\n\t\t\tAuthorization: 'Bearer $CLIENT_SECRET',\n\t\t},\n\t});\n}\n\n// Suffix for the background-indexing queue. Must sort *before* ':' (ASCII 58)\n// so the chat-history BETWEEN query never includes bg-queue items. '-' (45) works.\nexport const BG_INDEXING_QUEUE_SUFFIX = '-bg';\n\n/**\n * True when a request belongs to the background-indexing queue.\n *\n * Accepts BOTH shapes this value arrives in: the bare queue name the client sends\n * (\"<userId>-bg\"), and the server qid that comes back on history/poll responses\n * (\"<service>:<queue>|<seq>\"). Testing the tail of the raw value only works for the\n * first: a qid ends in \"|<seq>\", so `endsWith('-bg')` is always false for it — which\n * silently meant history items were NEVER recognised as background tasks.\n */\nexport function isBgIndexingQueue(queueName?: string): boolean {\n\tif (typeof queueName !== 'string' || !queueName) return false;\n\tconst prefix = queueName.split('|')[0];\n\tconst idx = prefix.lastIndexOf(':');\n\tconst name = idx === -1 ? prefix : prefix.slice(idx + 1);\n\treturn name.slice(-BG_INDEXING_QUEUE_SUFFIX.length) === BG_INDEXING_QUEUE_SUFFIX;\n}\n\n// Pending background-indexing task descriptor. NOTE: the live mutable queue\n// (a Vue `reactive([])` in agent.vue, a plain array in bunnyquery) is app-level\n// state owned by the consumer — only the TYPE lives in the engine.\nexport type BgTaskEntry = {\n\tserviceId: string;\n\tplatform: 'claude' | 'openai';\n\tid: string;\n\tfilename: string;\n\tstoragePath?: string;\n\tisReindex?: boolean;\n\tmime?: string;\n\tsize?: number;\n\tstatus: 'running' | 'pending';\n\tpoll: ((opts: { latency: number }) => Promise<any>) | undefined;\n\t/** How many CONTINUE passes have already run for this file (resume-across-passes). */\n\tresumePass?: number;\n};\n\n// Token the indexing agent appends to its final message ONLY when it has fully read and\n// saved the whole file. Its ABSENCE is what tells the client to run another CONTINUE pass.\n//\n// Applies to the TEXT/GRID paging path only. The vision path (rendered PDF pages) no longer\n// asks the model whether it is finished — the worker advances that loop off the renderer's\n// page count — so this marker has no say in whether a PDF keeps going.\nexport const INDEXING_COMPLETE_MARKER = 'INDEXING_COMPLETE';\n// Cap on CONTINUE passes per file, so a file the agent can never mark complete (or a\n// pathological loop) stops instead of re-dispatching forever. The text/grid paging path\n// reads MANY windows within a single pass (the agent loops readFileContent in one turn), so\n// a small cap suffices.\nexport const MAX_INDEXING_RESUME_PASSES = 6;\n\nexport async function getChatHistory(\n\tparams: { service?: string; owner?: string; platform: 'claude' | 'openai'; queue?: string },\n\tfetchOptions: Record<string, any>,\n) {\n\tconst url =\n\t\tparams.platform === 'claude'\n\t\t\t? ANTHROPIC_MESSAGES_API_URL\n\t\t\t: OPENAI_RESPONSES_API_URL;\n\tconst p = Object.assign(\n\t\t{\n\t\t\turl,\n\t\t\tmethod: 'POST',\n\t\t},\n\t\t{ service: params.service, owner: params.owner },\n\t\tparams.queue ? { queue: params.queue } : {},\n\t);\n\n\treturn chatEngineConfig().clientSecretRequestHistory(\n\t\tp as { url: string; method: 'POST'; queue?: string },\n\t\tObject.assign({ ascending: false }, fetchOptions),\n\t);\n}\n","/**\n * History mapping (pure). Moved verbatim from the chatbox. The clear-horizon\n * timestamp and the \"Indexing: …\" display label are INJECTED (clearedAt param,\n * formatIndexingLabel callback) so the engine touches neither localStorage nor\n * view-specific display formatting. serviceId is passed for link sanitization.\n */\nimport { extractClaudeText, extractOpenAIText } from './requests';\nimport { isErrorResponseBody, getErrorMessage } from './errors';\nimport { sanitizeAttachmentLinksForHistory } from './links';\n\nexport function filterListByClearHorizon(list: any[], clearedAt: number): any[] {\n\tif (!clearedAt) return list;\n\treturn list.filter(function (item) {\n\t\tvar updated = Number(item && item.updated);\n\t\treturn isFinite(updated) && updated > clearedAt;\n\t});\n}\n\nexport function normalizeTextContent(content: any): string {\n\tif (typeof content === 'string') return content;\n\tif (Array.isArray(content)) {\n\t\treturn content.map(function (part: any) {\n\t\t\tif (typeof part === 'string') return part;\n\t\t\tif (part && (part.type === 'text' || part.type === 'input_text' || part.type === 'output_text')) return part.text || '';\n\t\t\treturn '';\n\t\t}).join('\\n').trim();\n\t}\n\treturn '';\n}\n\nexport function extractLastUserTextFromRequest(requestBody: any): string {\n\tvar arr = requestBody && Array.isArray(requestBody.messages) ? requestBody.messages\n\t\t: (requestBody && Array.isArray(requestBody.input) ? requestBody.input : []);\n\tfor (var i = arr.length - 1; i >= 0; i--) {\n\t\tif (arr[i] && arr[i].role === 'user') {\n\t\t\tvar t = normalizeTextContent(arr[i].content);\n\t\t\tif (t) return t;\n\t\t}\n\t}\n\treturn '';\n}\n\nexport type MapHistoryOptions = {\n\tclearedAt: number;\n\tserviceId: string;\n\t/** View-side display formatter for \"Indexing:/Reindexing: …\" bubbles. */\n\tformatIndexingLabel: (name: string, mime?: string, size?: number | null, storagePath?: string, reindex?: boolean, continued?: boolean) => string;\n};\n\nexport function mapHistoryListToMessages(list: any[], platform: 'claude' | 'openai', opts: MapHistoryOptions) {\n\tvar mapped: any[] = [], runningItemIds: string[] = [];\n\tvar extractAssistantText = platform === 'openai' ? extractOpenAIText : extractClaudeText;\n\tvar filtered = filterListByClearHorizon(list, opts.clearedAt);\n\tfiltered.slice().reverse().forEach(function (item) {\n\t\tvar requestBody = item && item.request_body;\n\t\tvar isInProcess = item && item.status === 'running';\n\t\tvar isQueued = item && item.status === 'pending';\n\t\tvar isCancelledItem = item && item.status === 'cancelled';\n\t\tvar isPending = isInProcess || isQueued;\n\t\tvar isFailed = item && item.status === 'failed';\n\t\tvar response = isFailed ? (item.error != null ? item.error : item.response_body)\n\t\t\t: (item && item.response_body != null ? item.response_body : item && item.error);\n\t\tvar userText = extractLastUserTextFromRequest(requestBody);\n\t\tvar assistantText = isPending ? '' : ((extractAssistantText(response) || '').trim() || '');\n\t\tvar isErrorResponse = !isPending && (isFailed || isErrorResponseBody(response));\n\t\tvar serverItemId = item && typeof item.id === 'string' && item.id ? item.id : undefined;\n\t\t// A USER bubble shows when the request was made (`created`); an ASSISTANT\n\t\t// bubble shows when its response landed (`updated`). Fall back to the other\n\t\t// if one is missing (older records only carried `updated`).\n\t\tvar createdTs = Number(item && item.created);\n\t\tvar updatedTs = Number(item && item.updated);\n\t\tvar userTs = isFinite(createdTs) && createdTs > 0 ? createdTs : (isFinite(updatedTs) && updatedTs > 0 ? updatedTs : undefined);\n\t\tvar replyTs = isFinite(updatedTs) && updatedTs > 0 ? updatedTs : (isFinite(createdTs) && createdTs > 0 ? createdTs : undefined);\n\n\t\tif (userText) {\n\t\t\tvar displayContent;\n\t\t\t// Structured file ref for the display layer's per-file collapsing, kept\n\t\t\t// alongside the formatted label so grouping never has to parse it back.\n\t\t\tvar indexFile: any = undefined;\n\t\t\tif (item._isBgTask) {\n\t\t\t\tvar nameMatch = userText.match(/^- name: (.+)$/m);\n\t\t\t\tif (nameMatch) {\n\t\t\t\t\tvar mimeMatch = userText.match(/^- mime type: (.+)$/m);\n\t\t\t\t\tvar sizeMatch = userText.match(/^- size \\(bytes\\): (\\d+)$/m);\n\t\t\t\t\tvar pathMatch = userText.match(/^- storage path: (.+)$/m);\n\t\t\t\t\t// A CONTINUE pass (\"CONTINUE indexing …\") gets the compact\n\t\t\t\t\t// continuation label; a first pass (\"A new file …\") gets the full\n\t\t\t\t\t// one. Mirrors agent.vue's mapHistoryListToMessages so a big file's\n\t\t\t\t\t// windows read as progress, not the same task repeating.\n\t\t\t\t\tvar isContinuePass = userText.indexOf('CONTINUE indexing') === 0;\n\t\t\t\t\tdisplayContent = opts.formatIndexingLabel(\n\t\t\t\t\t\tnameMatch[1].trim(),\n\t\t\t\t\t\tmimeMatch ? mimeMatch[1].trim() : '',\n\t\t\t\t\t\tsizeMatch ? Number(sizeMatch[1]) : null,\n\t\t\t\t\t\tpathMatch ? pathMatch[1].trim() : undefined,\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t\tisContinuePass\n\t\t\t\t\t);\n\t\t\t\t\tindexFile = {\n\t\t\t\t\t\tname: nameMatch[1].trim(),\n\t\t\t\t\t\tpath: pathMatch ? pathMatch[1].trim() : undefined,\n\t\t\t\t\t\tmime: mimeMatch ? mimeMatch[1].trim() : undefined,\n\t\t\t\t\t\tsize: sizeMatch ? Number(sizeMatch[1]) : undefined,\n\t\t\t\t\t\tcontinued: isContinuePass,\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tdisplayContent = userText;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdisplayContent = sanitizeAttachmentLinksForHistory(userText, opts.serviceId);\n\t\t\t}\n\t\t\tvar userMsg: any = { role: 'user', content: displayContent };\n\t\t\tif (isInProcess) userMsg.isPendingInProcess = true;\n\t\t\tif (isQueued) userMsg.isPendingQueued = true;\n\t\t\tif (isCancelledItem) userMsg.isCancelled = true;\n\t\t\tif (item._isBgTask) userMsg.isBackgroundTask = true;\n\t\t\tif (indexFile) userMsg._indexFile = indexFile;\n\t\t\tif (item._isOnBgQueue) userMsg._useBgQueue = true;\n\t\t\tif (serverItemId !== undefined) userMsg._serverItemId = serverItemId;\n\t\t\tif (userTs !== undefined) userMsg._ts = userTs;\n\t\t\tmapped.push(userMsg);\n\t\t}\n\t\tif (isCancelledItem) { /* no assistant bubble */ }\n\t\telse if (isInProcess) {\n\t\t\tvar ph: any = { role: 'assistant', content: '', isPending: true, isPendingInProcess: true };\n\t\t\tif (item._isBgTask) ph.isBackgroundTask = true;\n\t\t\tif (serverItemId !== undefined) { ph._serverItemId = serverItemId; runningItemIds.push(serverItemId); }\n\t\t\tmapped.push(ph);\n\t\t} else if (isQueued) { /* no assistant placeholder */ }\n\t\telse if (isErrorResponse) {\n\t\t\tvar em: any = { role: 'assistant', content: getErrorMessage(response), isError: true };\n\t\t\tif (item._isBgTask) em.isBackgroundTask = true;\n\t\t\tif (serverItemId !== undefined) em._serverItemId = serverItemId;\n\t\t\tif (replyTs !== undefined) em._ts = replyTs;\n\t\t\tmapped.push(em);\n\t\t} else if (assistantText) {\n\t\t\t// Safe db-only sanitize (forAssistant) so a volatile db url the model\n\t\t\t// emitted renders as a re-mintable `_expired_.url` link, not a dead one.\n\t\t\tvar okm: any = { role: 'assistant', content: sanitizeAttachmentLinksForHistory(assistantText, opts.serviceId, true) };\n\t\t\tif (item._isBgTask) okm.isBackgroundTask = true;\n\t\t\tif (serverItemId !== undefined) okm._serverItemId = serverItemId;\n\t\t\tif (replyTs !== undefined) okm._ts = replyTs;\n\t\t\tmapped.push(okm);\n\t\t}\n\t});\n\treturn { messages: mapped, runningItemIds: runningItemIds };\n}\n","/**\n * Keep older history REACHABLE by paging until the message box actually gains\n * something to scroll to.\n *\n * Older history is paged in by one trigger only: the user scrolling to the top\n * of the message box. That trigger has two ways to die, and collapsed indexing\n * rows cause both:\n *\n * 1. The box never scrolls. A file's every indexing pass (the first plus every\n * CONTINUE pass, request AND response bubble each) folds into ONE row, so a\n * full history page — twenty-plus messages — can render as a single line.\n * Content shorter than the viewport fires no scroll event, so page 2 is\n * never requested and any conversation the user had before that upload is\n * permanently out of reach.\n * 2. The fetched page adds no height. A page that is entirely the same file's\n * earlier passes joins the collapsed row already on screen and renders\n * nothing new. The user, sitting at scrollTop 0, scrolls up again — and\n * because the position never changed, no further scroll event fires.\n *\n * Both are the same shape: fetch, re-measure, and keep going until the user\n * genuinely gained reachable content, history ran out, or the pager stopped\n * advancing. `isSatisfied` is what differs between the two (can the box scroll\n * at all / did it grow), so the loop below takes it as a predicate.\n *\n * DOM-free like the rest of the engine — the caller supplies the measurement and\n * awaits its own render before measuring, so agent.vue and the widget run the\n * identical loop over their own pagers.\n */\n\n/** Overflow (px) that counts as \"the user can scroll here\". Comfortably more\n * than the 60px top threshold that triggers the next page, so a filled box has\n * real room to scroll rather than sitting one pixel from the trigger. */\nexport const HISTORY_FILL_SLACK_PX = 64;\n\n/** Pages one fill pass will request before giving up. Reached only by a chat\n * whose history really is dozens of pages of one file's indexing passes; the\n * cap exists so a pager that stops advancing can never spin forever. */\nexport const MAX_HISTORY_FILL_PAGES = 24;\n\nexport type FillHistoryViewportOptions = {\n\t/** The user has reachable content and paging can stop. Called AFTER the\n\t * caller's own render has settled (nextTick / rAF), since only the caller\n\t * knows when its view has painted — hence the allowance for a promise. */\n\tisSatisfied: () => boolean | Promise<boolean>;\n\t/** All history is loaded — nothing left to page in. */\n\tisEndOfList: () => boolean;\n\t/** A history request is already in flight. Waited out, not treated as a stop\n\t * condition: a background first-page refresh (the queue-detect tick fires one\n\t * every couple of seconds while a file is indexing) would otherwise swallow\n\t * the user's scroll-up entirely, and scrolling up again from scrollTop 0\n\t * produces no second event to retry with. */\n\tisLoading: () => boolean;\n\t/** Messages currently loaded. Used to detect a page that added nothing, which\n\t * means the pager is not advancing and looping would never terminate. */\n\tmessageCount: () => number;\n\t/** Fetch ONE older page (the caller's own fetchMore path, scroll-restore and\n\t * all). Return `false` when the request was NOT issued (the caller's own\n\t * single-flight guard swallowed it) so the loop retries instead of reading\n\t * the unchanged message count as an exhausted pager. Anything else, including\n\t * undefined, means it was attempted. */\n\tfetchOlder: () => Promise<boolean | void | any>;\n\t/** The chat this fill was started for is gone (project switched, view\n\t * unmounted, gate token bumped). Checked between pages so a stale fill can\n\t * never keep paging another chat's history. */\n\tisStale?: () => boolean;\n\tmaxPages?: number;\n};\n\n/** How long to wait out an in-flight history request before giving up on it. */\nconst IDLE_WAIT_STEP_MS = 120;\nconst IDLE_WAIT_MAX_MS = 15000;\n\n/** Resolve once no history request is in flight. False if the wait timed out or\n * the chat went stale, in which case the caller should stop. */\nasync function waitForIdle(\n\topts: FillHistoryViewportOptions,\n\tstale: () => boolean,\n): Promise<boolean> {\n\tvar waited = 0;\n\twhile (opts.isLoading()) {\n\t\tif (stale() || waited >= IDLE_WAIT_MAX_MS) return false;\n\t\tawait new Promise(function (r) { setTimeout(r, IDLE_WAIT_STEP_MS); });\n\t\twaited += IDLE_WAIT_STEP_MS;\n\t}\n\treturn !stale();\n}\n\n/**\n * Page older history until `isSatisfied`, until history runs out, or until the\n * pager stops advancing. Never throws: a failed page ends the fill, and the\n * user's own scrolling remains the fallback trigger.\n */\nexport async function fillHistoryViewport(opts: FillHistoryViewportOptions): Promise<void> {\n\tvar maxPages = typeof opts.maxPages === 'number' ? opts.maxPages : MAX_HISTORY_FILL_PAGES;\n\tvar stale = function () { return !!(opts.isStale && opts.isStale()); };\n\tvar swallowed = 0;\n\n\tfor (var page = 0; page < maxPages; page++) {\n\t\tif (stale() || opts.isEndOfList()) return;\n\t\tif (!(await waitForIdle(opts, stale))) return;\n\t\tvar satisfied = false;\n\t\ttry {\n\t\t\tsatisfied = !!(await opts.isSatisfied());\n\t\t} catch {\n\t\t\treturn; // cannot measure (view torn down mid-fill) — stop.\n\t\t}\n\t\tif (satisfied || stale()) return;\n\n\t\t// Re-check immediately before dispatching: measuring above yields for a\n\t\t// frame, and a background first-page refresh landing in that gap would make\n\t\t// the caller's own single-flight guard swallow this request. A swallowed\n\t\t// page adds no messages, which used to read as \"the pager is exhausted\" and\n\t\t// abandoned the fill for good.\n\t\tif (!(await waitForIdle(opts, stale))) return;\n\t\tvar before = opts.messageCount();\n\t\tvar attempted: boolean | void;\n\t\ttry {\n\t\t\tattempted = await opts.fetchOlder();\n\t\t} catch {\n\t\t\treturn; // history is optional; the scroll trigger stays as the fallback.\n\t\t}\n\t\tif (stale()) return;\n\t\tif (attempted === false) {\n\t\t\t// The caller reported it never issued the request. Retry it rather than\n\t\t\t// mistaking it for an exhausted pager, but not forever.\n\t\t\tif (++swallowed > 3) return;\n\t\t\tpage--;\n\t\t\tcontinue;\n\t\t}\n\t\t// The page came back with nothing new. Either the pager is exhausted (and\n\t\t// endOfList simply has not been set) or it is stuck; either way another\n\t\t// round would request the same page again.\n\t\tif (opts.messageCount() <= before) return;\n\t}\n}\n\n/**\n * One fill loop per view, with predicates COMBINED rather than dropped.\n *\n * Fills come from several places at once — a first page finishing, a window\n * resize, a row being collapsed, and the user's own scroll to the top — and a\n * plain \"one at a time, drop the rest\" guard picks the wrong winner: a resize\n * fill (satisfied the moment the box can scroll at all) would swallow the user's\n * scroll-up (which needs content specifically ABOVE them), and the scroll-up\n * cannot be retried, because a reader parked at scrollTop 0 produces no further\n * scroll event. Dropping the guard entirely is no better: every frame of a\n * window drag would start its own 24-page loop.\n *\n * So a request that arrives mid-loop ANDs its predicate into the running one:\n * the loop then keeps paging until EVERY caller is satisfied. Predicates that\n * come true are dropped as it goes, so the cost stays flat.\n */\nexport function createHistoryFiller(\n\tbase: Omit<FillHistoryViewportOptions, 'isSatisfied'>,\n): { fill: (isSatisfied: () => boolean | Promise<boolean>) => Promise<void>; isRunning: () => boolean } {\n\tvar pending: Array<() => boolean | Promise<boolean>> = [];\n\tvar running = false;\n\n\tasync function allSatisfied(): Promise<boolean> {\n\t\tvar next: Array<() => boolean | Promise<boolean>> = [];\n\t\tfor (var i = 0; i < pending.length; i++) {\n\t\t\tif (!(await pending[i]())) next.push(pending[i]);\n\t\t}\n\t\tpending = next;\n\t\treturn pending.length === 0;\n\t}\n\n\treturn {\n\t\tisRunning: function () { return running; },\n\t\tfill: function (isSatisfied) {\n\t\t\tpending.push(isSatisfied);\n\t\t\tif (running) return Promise.resolve();\n\t\t\trunning = true;\n\t\t\tvar done = function () { running = false; pending = []; };\n\t\t\treturn fillHistoryViewport({\n\t\t\t\tisSatisfied: allSatisfied,\n\t\t\t\tisEndOfList: base.isEndOfList,\n\t\t\t\tisLoading: base.isLoading,\n\t\t\t\tmessageCount: base.messageCount,\n\t\t\t\tfetchOlder: base.fetchOlder,\n\t\t\t\tisStale: base.isStale,\n\t\t\t\tmaxPages: base.maxPages,\n\t\t\t}).then(done, done);\n\t\t},\n\t};\n}\n","/**\n * ChatSession — framework-agnostic stateful chat orchestration.\n *\n * Ported verbatim from the bunnyquery widget's in-place state machine (which was\n * itself ported from agent.vue), with three mechanical substitutions:\n * CS.<field> -> this.state.<field>\n * renderMessages() -> this.host.notify()\n * S.<x> / skapi -> this.host.getIdentity().<x> / this.host.cancelRequest / refreshSession\n * scroll/refresh -> this.host.scrollToBottom(IfSticky) / refreshMessageBubble\n * Module-level singletons (bgTaskQueue, aiChatHistoryCache, pendingAgentRequests,\n * cancelledServerIds, historyItemPolls) become instance fields. The provider\n * request builders are reached through the engine (which already has the skapi\n * transport + poll injected via configureChatEngine), so cancel/poll behavior is\n * preserved.\n *\n * The view (per consumer) keeps: rendering, markdown PARSE, DOM refs + scroll\n * measurement, attachment chips, and the auth/account shell. It drives the\n * session via the public methods and re-renders in host.notify().\n */\nimport {\n\tcallClaudeWithPublicMcp,\n\tcallOpenAIWithPublicMcp,\n\tnotifyAgentSaveAttachment,\n\tnotifyAgentContinueIndexing,\n\tINDEXING_COMPLETE_MARKER,\n\tMAX_INDEXING_RESUME_PASSES,\n\textractClaudeText,\n\textractOpenAIText,\n\tgetChatHistory,\n\tPOLL_INTERVAL,\n\tBG_INDEXING_QUEUE_SUFFIX,\n\tisBgIndexingQueue,\n\tANTHROPIC_MESSAGES_API_URL,\n\tOPENAI_RESPONSES_API_URL,\n\ttype BgTaskEntry,\n} from './requests';\nimport { isPagedReadFile, isImageVisionFile, isWindowedReadFile } from './office';\nimport { windowedIndexingEnabled } from './config';\nimport { isErrorResponseBody, isAuthExpiredError, isNonRetryableRequestError, getErrorMessage } from './errors';\nimport { buildBoundedChatMessages } from './budget';\nimport { createInlineLinkRegex } from './links';\nimport { mapHistoryListToMessages, extractLastUserTextFromRequest } from './history';\nimport { wallClockNow } from './time';\nimport { parseAttachmentContent } from './attachment_parsers';\nimport type { ChatHost, ChatState, ChatMessage, PinnedDispatchContext } from './host';\nimport type { IndexingGroup } from './indexing_groups';\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise(function (r) { setTimeout(r, ms); });\n}\n\n// requestAnimationFrame / high-res clock, reached through globalThis so the\n// engine stays DOM-free at the type level (and degrades gracefully in non-DOM\n// / test environments where these globals are absent).\nvar _g: any = typeof globalThis !== 'undefined' ? globalThis : {};\nfunction nowMs(): number {\n\treturn (_g.performance && typeof _g.performance.now === 'function') ? _g.performance.now() : Date.now();\n}\nfunction nextFrame(cb: (t: number) => void): void {\n\tif (typeof _g.requestAnimationFrame === 'function') { _g.requestAnimationFrame(cb); return; }\n\tsetTimeout(function () { cb(nowMs()); }, 16);\n}\n\n/** A live poll registered in ChatSession.historyItemPolls. */\nexport type PollHandle = {\n\t/** 'bg' = background indexing, pausable. 'fg' = a reply the user is waiting on. */\n\tkind: 'fg' | 'bg';\n\t/** Absent on an older skapi-js that cannot stop an attached poll. */\n\tstop?: () => void;\n};\n\n/**\n * True when a poll result came from stopPolling rather than the server. Duck-typed on\n * purpose — see the note above about not importing skapi-js here.\n */\nfunction isPollStopped(res: any): boolean {\n\treturn !!res && typeof res === 'object' && res.status === 'stopped';\n}\n\nexport class ChatSession {\n\thost: ChatHost;\n\tstate: ChatState;\n\tbgTaskQueue: BgTaskEntry[];\n\tcancelledServerIds: Set<string>;\n\t/** Files whose indexing the user stopped, keyed exactly as buildChatDisplayList\n\t * keys a group (storage path, else filename). Cancelling one pass is not\n\t * enough on its own: the client dispatches CONTINUE passes for paged files, so\n\t * without this the next pass is enqueued the moment the cancelled one settles.\n\t * Cleared when a FIRST pass for the same file is queued again (a re-upload or a\n\t * Reindex from the file manager), so stopping a file never poisons it. */\n\tcancelledIndexKeys: Set<string>;\n\tpendingAgentRequests: Record<string, Promise<any>>;\n\taiChatHistoryCache: Record<string, { messages: ChatMessage[]; endOfList: boolean; startKeyHistory: string[] }>;\n\thistoryItemPolls: Map<string, PollHandle>;\n\t/** Non-empty while polling is paused; keyed by reason so overlapping causes\n\t * (view detached AND tab hidden) do not resume each other prematurely. */\n\tprivate _pauseReasons: Set<string>;\n\tprivate _resuming: boolean;\n\tprivate _lidSeq: number;\n\n\tconstructor(host: ChatHost) {\n\t\tthis.host = host;\n\t\tthis.state = {\n\t\t\tmessages: [],\n\t\t\tattachments: [],\n\t\t\tuploadingAttachments: false,\n\t\t\tsending: false,\n\t\t\ttyping: false,\n\t\t\ttypingAbort: false,\n\t\t\tloadingHistory: false,\n\t\t\tloadingOlderHistory: false,\n\t\t\thistoryEndOfList: false,\n\t\t\thistoryStartKeyHistory: [],\n\t\t\thistoryRequestToken: 0,\n\t\t\tgateRefreshToken: 0,\n\t\t};\n\t\tthis.bgTaskQueue = [];\n\t\tthis.cancelledServerIds = new Set();\n\t\tthis.cancelledIndexKeys = new Set();\n\t\tthis.pendingAgentRequests = {};\n\t\tthis.aiChatHistoryCache = {};\n\t\tthis.historyItemPolls = new Map();\n\t\tthis._pauseReasons = new Set();\n\t\tthis._resuming = false;\n\t\tthis._lidSeq = 0;\n\t}\n\n\t/**\n\t * Register a live poll so (a) a remount dedupes against it instead of stacking a\n\t * SECOND poll on the same item, and (b) pausePolling can stop it.\n\t *\n\t * `stop` comes from the SDK and may be absent on an older skapi-js, in which case the\n\t * poll simply cannot be stopped and is left running — see pausePolling.\n\t */\n\tprivate _trackPoll(id: string, kind: 'fg' | 'bg', p: any): any {\n\t\tvar stop = p && typeof p.stop === 'function' ? p.stop.bind(p) : undefined;\n\t\tif (!stop) {\n\t\t\t// The SDK could not give us a handle. Almost always means an older skapi-js\n\t\t\t// is loaded (or a stale bundler dep cache) — the poll will be unstoppable.\n\t\t\tconsole.debug('[chat-engine] poll has no stop handle', { id: id, kind: kind });\n\t\t}\n\t\tthis.historyItemPolls.set(id, { kind: kind, stop: stop });\n\t\treturn p;\n\t}\n\n\t/**\n\t * Stop and forget one item's poll. Used after a cancel: the row is either gone\n\t * (cancelled while queued) or flagged cancelled (cancelled while running), so\n\t * asking about it again only burns requests. Safe when no poll is attached, and\n\t * safe on an older skapi-js with no stop handle (the entry is then LEFT in the\n\t * map so a later drain cannot stack a second, unstoppable poll on the id).\n\t */\n\tprivate _stopPoll(id: string): void {\n\t\tvar handle = this.historyItemPolls.get(id);\n\t\tif (!handle) return;\n\t\tif (typeof handle.stop !== 'function') return;\n\t\ttry { handle.stop(); } catch (e) { /* best effort */ }\n\t\tthis.historyItemPolls.delete(id);\n\t}\n\n\t/** True while any pause reason is active. */\n\tisPollingPaused(): boolean {\n\t\treturn this._pauseReasons.size > 0;\n\t}\n\n\t/**\n\t * Stop BACKGROUND polling until resumePolling. Foreground polls (a reply the user is\n\t * waiting on) keep running deliberately: their results must still land in the history\n\t * cache so resumePendingRequest can render them on return, otherwise a user who sends\n\t * a message then navigates away comes back to a permanently stuck \"Thinking...\".\n\t *\n\t * Server-side work is untouched; this only stops asking about it. That is safe for\n\t * document indexing because the worker drives that loop itself.\n\t */\n\tpausePolling(reason: string): void {\n\t\tthis._pauseReasons.add(reason || 'paused');\n\t\tvar self = this;\n\t\tvar stopped: string[] = [];\n\t\tthis.historyItemPolls.forEach(function (handle, id) {\n\t\t\tif (!handle || handle.kind !== 'bg') return;\n\t\t\t// No stop available (older SDK): LEAVE the entry in place. Deleting it would\n\t\t\t// let a later drain attach a second, uncancellable poll on the same item.\n\t\t\tif (typeof handle.stop !== 'function') return;\n\t\t\ttry { handle.stop(); } catch (e) { /* best effort */ }\n\t\t\tstopped.push(id);\n\t\t});\n\t\t// Delete only what we actually stopped, one at a time. NEVER clear() the map:\n\t\t// wholesale clearing is what previously let loadHistory attach a duplicate poll\n\t\t// on a live item, producing duplicate replies and stranded \"Thinking\" bubbles.\n\t\tstopped.forEach(function (id) { self.historyItemPolls.delete(id); });\n\n\t}\n\n\t/**\n\t * Lift a pause reason WITHOUT running the reconcile. For a caller that is about to\n\t * reload history anyway (a view remounting), letting resumePolling also reconcile\n\t * would race that load and can double-attach.\n\t */\n\tclearPauseReason(reason: string): void {\n\t\tthis._pauseReasons.delete(reason || 'paused');\n\t}\n\n\t/**\n\t * Clear a pause reason and, once none remain, re-attach polling and reconcile.\n\t * Deliberately does NOT touch gateRefreshToken: bumping it would silently discard\n\t * the results of anything still in flight across the pause.\n\t */\n\tresumePolling(reason: string): Promise<void> {\n\t\tthis._pauseReasons.delete(reason || 'paused');\n\t\tif (this._pauseReasons.size > 0 || this._resuming) return Promise.resolve();\n\t\tif (!this.host.isViewMounted || !this.host.isViewMounted()) return Promise.resolve();\n\t\tvar self = this;\n\t\tthis._resuming = true;\n\t\treturn Promise.resolve()\n\t\t\t.then(function () {\n\t\t\t\tself.drainBgTaskQueue();\n\t\t\t\treturn self.loadHistory(false, self.state.gateRefreshToken);\n\t\t\t})\n\t\t\t.catch(function (e: any) { console.error('[chat-engine] resume polling failed', e); })\n\t\t\t.then(function () { self._resuming = false; });\n\t}\n\n\tprivate _newLocalId(): string {\n\t\tthis._lidSeq += 1;\n\t\treturn 'lid_' + this._lidSeq;\n\t}\n\n\tgetHistoryCacheKey(): string {\n\t\tvar id = this.host.getIdentity();\n\t\tif (!id.serviceId || id.platform === 'none') return '';\n\t\treturn id.serviceId + '#' + id.platform;\n\t}\n\n\tupdateHistoryCache(): void {\n\t\tvar key = this.getHistoryCacheKey();\n\t\tif (!key) return;\n\t\t// Never persist another chat's in-flight bubbles under THIS key. The\n\t\t// dashboard shares one ChatSession across projects, so a turn dispatched\n\t\t// in project A can still be sitting in state.messages while the identity\n\t\t// (and therefore `key`) already points at project B — without this filter\n\t\t// A's user + \"Thinking...\" bubbles get written into B's cache entry and\n\t\t// replay on every later visit to B. Bubbles with no _ownerKey (server\n\t\t// history, bg tasks) are always kept. Single pass: this runs on the\n\t\t// typewriter hot path.\n\t\tthis.aiChatHistoryCache[key] = {\n\t\t\tmessages: this.state.messages.filter(function (m) {\n\t\t\t\treturn m._ownerKey === undefined || m._ownerKey === key;\n\t\t\t}),\n\t\t\tendOfList: this.state.historyEndOfList,\n\t\t\tstartKeyHistory: this.state.historyStartKeyHistory.slice(),\n\t\t};\n\t}\n\n\t/**\n\t * Land a resolved reply in the history cache of a chat that is NOT currently\n\t * visible, without touching state.messages. Mirrors the cache-only path in\n\t * dispatchAgentRequest: REPLACE the trailing pending \"Thinking...\" bubble\n\t * (append only when there is none), and settle the matching pending user\n\t * bubble, so the cached copy never keeps a stuck \"Thinking...\" that a later\n\t * cache-first load would re-render forever.\n\t */\n\tprivate _applyReplyToCache(key: string, reply: ChatMessage, serverId?: string): void {\n\t\tif (!key) return;\n\t\tvar existing = this.aiChatHistoryCache[key] || { messages: [], endOfList: false, startKeyHistory: [] };\n\t\tvar msgs = existing.messages.slice();\n\n\t\tvar thIdx = -1;\n\t\tfor (var i = msgs.length - 1; i >= 0; i--) {\n\t\t\tvar m = msgs[i];\n\t\t\tif (!m || !m.isPending || m.role !== 'assistant' || m.isBackgroundTask) continue;\n\t\t\tif (serverId && m._serverItemId && m._serverItemId !== serverId) continue;\n\t\t\tthIdx = i; break;\n\t\t}\n\t\tif (thIdx !== -1) {\n\t\t\tif (reply._serverItemId === undefined && msgs[thIdx]._serverItemId !== undefined) reply._serverItemId = msgs[thIdx]._serverItemId;\n\t\t\tmsgs[thIdx] = reply;\n\t\t} else {\n\t\t\t// No pending placeholder left to replace. Before appending, check whether\n\t\t\t// this turn is ALREADY in the cache — a history fetch may have mapped the\n\t\t\t// resolved turn in while the reply was in flight. Appending blindly is how\n\t\t\t// one turn ended up rendered twice (the duplicated question+answer): the\n\t\t\t// cache is restored verbatim on the next mount, so a duplicate written\n\t\t\t// here survives every later visit.\n\t\t\tvar dupIdx = -1;\n\t\t\tif (serverId) {\n\t\t\t\tfor (var d = msgs.length - 1; d >= 0; d--) {\n\t\t\t\t\tvar dm = msgs[d];\n\t\t\t\t\tif (dm && dm.role === 'assistant' && dm._serverItemId === serverId) { dupIdx = d; break; }\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (dupIdx !== -1) msgs[dupIdx] = reply;\n\t\t\telse msgs.push(reply);\n\t\t}\n\n\t\t// Settle the user bubble this turn belongs to (first pending one, or the\n\t\t// one carrying serverId) so it stops rendering as still in flight.\n\t\tfor (var j = 0; j < msgs.length; j++) {\n\t\t\tvar u = msgs[j];\n\t\t\tif (!u || u.role !== 'user' || u.isBackgroundTask) continue;\n\t\t\tif (!(u.isPendingQueued || u.isPendingInProcess || u.isSendingToServer)) continue;\n\t\t\tif (serverId && u._serverItemId && u._serverItemId !== serverId) continue;\n\t\t\tvar settled: ChatMessage = { role: 'user', content: u.content };\n\t\t\tif (u._serverItemId !== undefined) settled._serverItemId = u._serverItemId;\n\t\t\tif (u._ownerKey !== undefined) settled._ownerKey = u._ownerKey;\n\t\t\tmsgs[j] = settled;\n\t\t\tbreak;\n\t\t}\n\n\t\tthis.aiChatHistoryCache[key] = {\n\t\t\tmessages: msgs,\n\t\t\tendOfList: existing.endOfList,\n\t\t\tstartKeyHistory: existing.startKeyHistory,\n\t\t};\n\t}\n\n\t/**\n\t * serviceId/owner are passed explicitly by every caller: a request can be\n\t * dispatched after the user moved to another project, and re-reading the live\n\t * identity here would silently send the turn to THAT project instead of the\n\t * one it was composed for. Falls back to the live read only when a caller\n\t * omits them.\n\t */\n\tprivate _callProviderFor(platform: string, prompt: string, messages: any, system: string, model: string | undefined, userId: string, extractContent: any, fileUrls?: any, serviceId?: string, owner?: string) {\n\t\tif (serviceId === undefined || owner === undefined) {\n\t\t\tvar id = this.host.getIdentity();\n\t\t\tif (serviceId === undefined) serviceId = id.serviceId;\n\t\t\tif (owner === undefined) owner = id.owner;\n\t\t}\n\t\treturn platform === 'openai'\n\t\t\t? callOpenAIWithPublicMcp(prompt, serviceId, owner, messages, system, model, userId, extractContent, fileUrls)\n\t\t\t: callClaudeWithPublicMcp(prompt, serviceId, owner, messages, system, model, userId, extractContent, fileUrls);\n\t}\n\n\tdispatchAgentRequest(params: any) {\n\t\tvar self = this;\n\t\t// Id of the in-flight item this dispatch polls. Recorded in\n\t\t// historyItemPolls (set below, deleted when the dispatch settles) so a\n\t\t// remount / history refetch dedups against THIS poll instead of stacking\n\t\t// a duplicate history poll on the same item. (The cacheKey guard alone\n\t\t// stops covering an item once pendingAgentRequests clears — e.g. a queued\n\t\t// message still in flight after the immediate one resolved.)\n\t\tvar dispatchItemId: string | undefined;\n\t\tvar sendAndPoll = function () {\n\t\t\treturn Promise.resolve(\n\t\t\t\tself._callProviderFor(params.aiPlatform, params.text, params.boundedMessages, params.systemPrompt, params.aiModel, params.userId, params.extractContent, params.fileUrls, params.serviceId, params.owner)\n\t\t\t).then(function (initial: any) {\n\t\t\t\tif (initial && initial.poll && (initial.status === 'pending' || initial.status === 'running')) {\n\t\t\t\t\tif (initial.id) {\n\t\t\t\t\t\tif (dispatchItemId && dispatchItemId !== initial.id) self.historyItemPolls.delete(dispatchItemId);\n\t\t\t\t\t\tdispatchItemId = initial.id;\n\t\t\t\t\t}\n\t\t\t\t\tvar dp = initial.poll({ latency: POLL_INTERVAL });\n\t\t\t\t\tif (initial.id) self._trackPoll(initial.id, 'fg', dp);\n\t\t\t\t\treturn dp;\n\t\t\t\t}\n\t\t\t\treturn initial;\n\t\t\t});\n\t\t};\n\t\tvar run = sendAndPoll()\n\t\t\t.catch(function (err: any) {\n\t\t\t\t// Only auth-expiry is worth a refresh+resend; a malformed-request 400\n\t\t\t\t// (e.g. the `_skapi_extract`/unknown-parameter class) re-fails identically,\n\t\t\t\t// so never loop on it — guard against isAuthExpiredError's heuristic\n\t\t\t\t// misfiring on a param name that merely contains \"token\".\n\t\t\t\tif (isAuthExpiredError(err) && !isNonRetryableRequestError(err)) return self.host.refreshSession().then(sendAndPoll);\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.then(function (response: any) {\n\t\t\t\tif (isErrorResponseBody(response) && isAuthExpiredError(response) && !isNonRetryableRequestError(response)) {\n\t\t\t\t\treturn self.host.refreshSession().then(sendAndPoll);\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t})\n\t\t\t.then(function (response: any) {\n\t\t\t\tif (isErrorResponseBody(response)) return { content: getErrorMessage(response), isError: true };\n\t\t\t\tvar answer = (params.aiPlatform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response));\n\t\t\t\tanswer = (answer || '').trim();\n\t\t\t\treturn { content: answer || 'No text response received from AI provider.', isError: false };\n\t\t\t})\n\t\t\t.catch(function (err: any) { return { content: getErrorMessage(err), isError: true }; })\n\t\t\t.then(function (result: any) {\n\t\t\t\t// Land the resolved reply in the shared history cache. This runs\n\t\t\t\t// independently of the view lifecycle, so a reply is captured even\n\t\t\t\t// if the chatbox unmounted mid-request.\n\t\t\t\tdelete self.pendingAgentRequests[params.key];\n\t\t\t\tif (dispatchItemId) self.historyItemPolls.delete(dispatchItemId);\n\t\t\t\tvar existing = self.aiChatHistoryCache[params.key] || { messages: [], endOfList: false, startKeyHistory: [] };\n\t\t\t\tvar reply: ChatMessage = { role: 'assistant', content: result.content, isError: result.isError };\n\n\t\t\t\t// REPLACE the trailing pending \"Thinking...\" bubble in the cache with\n\t\t\t\t// the answer (falling back to append when none is present), regardless\n\t\t\t\t// of whether this chat is the currently-visible view. The cache must\n\t\t\t\t// NEVER retain a pending \"Thinking...\" bubble: even when the chatbox is\n\t\t\t\t// showing this chat, typewriteLatestReply swaps the bubble only in\n\t\t\t\t// state.messages and NEVER re-snapshots the cache — so appending a\n\t\t\t\t// duplicate here would leave the cached copy stuck pending, and a later\n\t\t\t\t// cache-first remount (agent.vue's loadChatHistory) would re-render that\n\t\t\t\t// \"Thinking...\" forever. typewriteLatestReply still finds this reply (it\n\t\t\t\t// reads the latest non-pending assistant from the cache), so replacing is\n\t\t\t\t// correct for the visible case too. The next fresh history fetch\n\t\t\t\t// reconciles it either way.\n\t\t\t\tvar msgs = existing.messages.slice();\n\t\t\t\tvar idx = -1;\n\t\t\t\tfor (var i = msgs.length - 1; i >= 0; i--) {\n\t\t\t\t\tvar m = msgs[i];\n\t\t\t\t\tif (m && m.isPending && m.role === 'assistant' && !m.isBackgroundTask) { idx = i; break; }\n\t\t\t\t}\n\t\t\t\tif (idx !== -1) {\n\t\t\t\t\treply._serverItemId = msgs[idx]._serverItemId;\n\t\t\t\t\tmsgs[idx] = reply;\n\t\t\t\t} else {\n\t\t\t\t\tmsgs.push(reply);\n\t\t\t\t}\n\t\t\t\tself.aiChatHistoryCache[params.key] = {\n\t\t\t\t\tmessages: msgs,\n\t\t\t\t\tendOfList: existing.endOfList,\n\t\t\t\t\tstartKeyHistory: existing.startKeyHistory,\n\t\t\t\t};\n\t\t\t\treturn result;\n\t\t\t});\n\t\tthis.pendingAgentRequests[params.key] = run;\n\t\treturn run;\n\t}\n\n\t// composed = clean display text; composedForLlm carries office-extraction\n\t// placeholders for the provider only. useBgQueue routes a post-attachment turn\n\t// onto the \"-bg\" queue so it runs after indexing.\n\tdispatchComposedMessage(composed: string, useBgQueue?: boolean, composedForLlm?: string, extractContent?: any, fileUrls?: any, pinned?: PinnedDispatchContext): void {\n\t\tvar self = this;\n\t\tif (!composed) return;\n\t\t// A send can be dispatched LONG after the user hit Send (attachment\n\t\t// uploads are awaited first), by which time the live identity may have\n\t\t// moved to another project. The caller pins the identity + system prompt\n\t\t// it captured at Send time so the request still goes to the project the\n\t\t// question was actually asked of. Falls back to the live read when the\n\t\t// caller doesn't pin (the widget, which has only one project anyway).\n\t\tvar id = pinned ? pinned.identity : this.host.getIdentity();\n\t\tif (id.platform === 'none') return;\n\n\t\tvar llmComposed = composedForLlm || composed;\n\n\t\t// Cache key of the chat this turn belongs to. Every locally-created\n\t\t// bubble is stamped with it so a project switch (which flips\n\t\t// getIdentity()/getHistoryCacheKey() to the new project) can't\n\t\t// misattribute this turn's bubbles to that project.\n\t\t// (platform === 'none' already returned above, so serviceId is the only gate)\n\t\tvar key = !id.serviceId ? '' : id.serviceId + '#' + id.platform;\n\t\t// True when the pinned chat is NOT the one currently on screen. Then\n\t\t// state.messages belongs to a different project and MUST NOT be touched:\n\t\t// the turn is staged in the pinned chat's cache instead and shows up when\n\t\t// the user navigates back to it.\n\t\tvar offChat = !!key && key !== this.getHistoryCacheKey();\n\n\t\tvar isQueuedSend = !offChat && (useBgQueue || this.state.sending || this.state.messages.some(function (m) {\n\t\t\treturn (m.isPending || m.isPendingQueued) && !m.isBackgroundTask && !m._useBgQueue;\n\t\t}));\n\n\t\tvar aiPlatform = id.platform;\n\t\tvar aiModel = id.model || undefined;\n\t\tvar systemPrompt = pinned ? pinned.systemPrompt : this.host.buildSystemPrompt();\n\t\tvar userId = id.userId || id.serviceId;\n\t\tvar chatQueue = useBgQueue ? userId + BG_INDEXING_QUEUE_SUFFIX : userId;\n\n\t\tif (offChat) {\n\t\t\t// Stage the turn in the pinned chat's cache and dispatch. The\n\t\t\t// client-side queue can't be consulted (its state is the other\n\t\t\t// project's), but the SERVER serializes per queue name, so ordering\n\t\t\t// within the pinned chat still holds. dispatchAgentRequest replaces\n\t\t\t// the pending bubble in this same cache entry when the reply lands.\n\t\t\tvar offHistory = (this.aiChatHistoryCache[key] ? this.aiChatHistoryCache[key].messages : []).filter(function (m) {\n\t\t\t\treturn !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder &&\n\t\t\t\t\t!m.isCancelled && !m.isBackgroundTask;\n\t\t\t});\n\t\t\tvar offBounded = buildBoundedChatMessages({\n\t\t\t\tplatform: aiPlatform, model: aiModel, systemPrompt: systemPrompt, serviceId: id.serviceId,\n\t\t\t\thistory: offHistory.concat([{ role: 'user', content: llmComposed }]),\n\t\t\t});\n\t\t\tvar offExisting = this.aiChatHistoryCache[key] || { messages: [], endOfList: false, startKeyHistory: [] };\n\t\t\tthis.aiChatHistoryCache[key] = {\n\t\t\t\tmessages: offExisting.messages.concat([\n\t\t\t\t\t{ role: 'user', content: composed, _ownerKey: key, _ts: wallClockNow() },\n\t\t\t\t\t{ role: 'assistant', content: '', isPending: true, isPendingInProcess: true, _ownerKey: key },\n\t\t\t\t]),\n\t\t\t\tendOfList: offExisting.endOfList,\n\t\t\t\tstartKeyHistory: offExisting.startKeyHistory,\n\t\t\t};\n\t\t\tthis.dispatchAgentRequest({\n\t\t\t\tkey: key, serviceId: id.serviceId, owner: id.owner, aiPlatform: aiPlatform, aiModel: aiModel,\n\t\t\t\tsystemPrompt: systemPrompt, text: composed, boundedMessages: offBounded.messages, userId: chatQueue,\n\t\t\t\textractContent: extractContent, fileUrls: fileUrls,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (isQueuedSend) {\n\t\t\tvar resolvedHistory = this.state.messages.filter(function (m) {\n\t\t\t\treturn !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder &&\n\t\t\t\t\t!m.isCancelled && !m.isBackgroundTask;\n\t\t\t});\n\t\t\tvar boundedQ = buildBoundedChatMessages({\n\t\t\t\tplatform: aiPlatform, model: aiModel, systemPrompt: systemPrompt, serviceId: id.serviceId,\n\t\t\t\thistory: resolvedHistory.concat([{ role: 'user', content: llmComposed }]),\n\t\t\t});\n\t\t\tvar queuedBubble: ChatMessage = { role: 'user', content: composed, isPendingQueued: true, isSendingToServer: true, _ts: wallClockNow() };\n\t\t\tif (key) queuedBubble._ownerKey = key;\n\t\t\tif (useBgQueue) queuedBubble._useBgQueue = true;\n\t\t\tthis.state.messages.push(queuedBubble);\n\t\t\tthis.host.notify(); this.updateHistoryCache(); this.host.scrollToBottom(true);\n\n\t\t\tvar capturedComposed = composed, capturedPlatform = aiPlatform, capturedKey = key;\n\t\t\tPromise.resolve(this._callProviderFor(aiPlatform, composed, boundedQ.messages, systemPrompt, aiModel, chatQueue, extractContent, fileUrls, id.serviceId, id.owner))\n\t\t\t\t.then(function (result: any) {\n\t\t\t\t\t// Only ack a bubble that belongs to THIS chat — the search is\n\t\t\t\t\t// positional, so on another project it would stamp this turn's\n\t\t\t\t\t// _serverItemId onto that project's unrelated in-flight bubble.\n\t\t\t\t\tvar sendingIdx = self.getHistoryCacheKey() !== capturedKey ? -1 : self.state.messages.findIndex(function (m) {\n\t\t\t\t\t\treturn m.isSendingToServer && (m.isPendingQueued || m.isPendingInProcess) && m.role === 'user' &&\n\t\t\t\t\t\t\t(m._ownerKey === undefined || m._ownerKey === capturedKey);\n\t\t\t\t\t});\n\t\t\t\t\tvar serverId = result && typeof result.id === 'string' ? result.id : undefined;\n\t\t\t\t\tif (sendingIdx >= 0) {\n\t\t\t\t\t\tvar upd = Object.assign({}, self.state.messages[sendingIdx], { isSendingToServer: false });\n\t\t\t\t\t\tif (serverId) upd._serverItemId = serverId;\n\t\t\t\t\t\tself.state.messages[sendingIdx] = upd; self.host.notify();\n\t\t\t\t\t}\n\t\t\t\t\tif (result && result.poll && (result.status === 'pending' || result.status === 'running')) {\n\t\t\t\t\t\t// Track this queued item's poll so a remount/refetch dedups\n\t\t\t\t\t\t// against it instead of attaching a duplicate history poll.\n\t\t\t\t\t\tvar qp = result.poll({ latency: POLL_INTERVAL });\n\t\t\t\t\t\tif (serverId) self._trackPoll(serverId, 'fg', qp);\n\t\t\t\t\t\treturn qp\n\t\t\t\t\t\t\t.then(function (res: any) { if (isPollStopped(res)) return; return self.onQueuedSendResponse(capturedComposed, res, capturedPlatform, serverId, capturedKey); })\n\t\t\t\t\t\t\t.catch(function (err: any) { return self.onQueuedSendError(capturedComposed, err, serverId, capturedKey); });\n\t\t\t\t\t}\n\t\t\t\t\treturn self.onQueuedSendResponse(capturedComposed, result, capturedPlatform, serverId, capturedKey);\n\t\t\t\t})\n\t\t\t\t.catch(function (err: any) { return self.onQueuedSendError(capturedComposed, err, undefined, capturedKey); });\n\t\t\treturn;\n\t\t}\n\n\t\t// immediate send — cache+resume model (mirrors agent.vue). The reply is\n\t\t// appended to aiChatHistoryCache by dispatchAgentRequest (so it survives a\n\t\t// view unmount), then rendered from the cache via typewriteLatestReply. A\n\t\t// later resumePendingRequest() re-renders it if the view remounted while the\n\t\t// request was still in flight.\n\t\tthis.state.messages.push({ role: 'user', content: composed, _ts: wallClockNow(), ...(key ? { _ownerKey: key } : {}) });\n\t\tthis.state.messages.push({ role: 'assistant', content: '', isPending: true, isPendingInProcess: true, ...(key ? { _ownerKey: key } : {}) });\n\t\tthis.host.notify(); this.updateHistoryCache(); this.state.sending = true; this.host.scrollToBottom(true);\n\n\t\tvar historyForLlm = this.state.messages.filter(function (m) { return !m.isCancelled && !m.isBackgroundTask; });\n\t\tif (llmComposed !== composed) {\n\t\t\tfor (var li = historyForLlm.length - 1; li >= 0; li--) {\n\t\t\t\tif (historyForLlm[li].role === 'user' && historyForLlm[li].content === composed) {\n\t\t\t\t\thistoryForLlm[li] = Object.assign({}, historyForLlm[li], { content: llmComposed });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tvar bounded = buildBoundedChatMessages({\n\t\t\tplatform: aiPlatform, model: aiModel, systemPrompt: systemPrompt, serviceId: id.serviceId,\n\t\t\thistory: historyForLlm,\n\t\t});\n\t\tvar run = this.dispatchAgentRequest({\n\t\t\tkey: key, serviceId: id.serviceId, owner: id.owner, aiPlatform: aiPlatform, aiModel: aiModel,\n\t\t\tsystemPrompt: systemPrompt, text: composed, boundedMessages: bounded.messages, userId: chatQueue,\n\t\t\textractContent: extractContent, fileUrls: fileUrls,\n\t\t});\n\t\t// Render the reply into the \"Thinking...\" bubble whenever the chatbox is\n\t\t// CURRENTLY showing this chat — even after an unmount/remount. The old\n\t\t// guard bailed on `requestToken !== gateRefreshToken`, but EVERY remount\n\t\t// bumps gateRefreshToken (refreshGate), so a request that finished after\n\t\t// the user navigated away and back left a stuck \"Thinking...\" (no view\n\t\t// typewriter ever ran, and resumePendingRequest bails when a pending\n\t\t// bubble is already present). Gate on \"is this the visible chat\" instead.\n\t\t// When it ISN'T (unmounted / another project), dispatchAgentRequest has\n\t\t// already replaced the pending bubble with the answer IN THE CACHE, so a\n\t\t// later loadChatHistory renders it.\n\t\tPromise.resolve(run).catch(function () { }).then(function () {\n\t\t\t// Clear `sending` UNCONDITIONALLY. It is session-global (it gates\n\t\t\t// isQueuedSend above, plus the platform/model pickers in the view), so\n\t\t\t// leaving it set when the user navigated to another project wedged\n\t\t\t// every subsequent send in EVERY project onto the queued path and kept\n\t\t\t// the view's user-bubble rescue arm armed forever. Only the RENDER of\n\t\t\t// the reply stays gated on still showing this chat — when it isn't,\n\t\t\t// dispatchAgentRequest has already written the answer into the cache\n\t\t\t// under `key`, so a later loadChatHistory renders it.\n\t\t\tself.state.sending = false;\n\t\t\tif (!(self.host.isViewMounted() && self.getHistoryCacheKey() === key)) return;\n\t\t\treturn Promise.resolve(self.typewriteLatestReply(key)).then(function () { self.host.scrollToBottomIfSticky(true); });\n\t\t});\n\t}\n\n\tpromoteNextBgQueuedToRunning(): void {\n\t\tif (this.state.messages.some(function (m) { return m.isPending && m.role === 'assistant' && m.isBackgroundTask; })) return;\n\t\tvar nextIdx = this.state.messages.findIndex(function (m) {\n\t\t\treturn m.isPendingQueued && m.role === 'user' && m.isBackgroundTask;\n\t\t});\n\t\tif (nextIdx === -1) return;\n\t\tvar existing = this.state.messages[nextIdx];\n\t\tvar promoted: ChatMessage = { role: 'user', content: existing.content, isPendingInProcess: true, isBackgroundTask: true };\n\t\tif (existing._indexFile) promoted._indexFile = existing._indexFile;\n\t\tif (existing._ts !== undefined) promoted._ts = existing._ts;\n\t\tif (existing._serverItemId !== undefined) promoted._serverItemId = existing._serverItemId;\n\t\tif (existing._ownerKey !== undefined) promoted._ownerKey = existing._ownerKey;\n\t\tthis.state.messages[nextIdx] = promoted;\n\t\tvar placeholder: ChatMessage = { role: 'assistant', content: '', isPending: true, isPendingInProcess: true, isBackgroundTask: true };\n\t\tif (existing._serverItemId !== undefined) placeholder._serverItemId = existing._serverItemId;\n\t\tif (existing._ownerKey !== undefined) placeholder._ownerKey = existing._ownerKey;\n\t\tthis.state.messages.splice(nextIdx + 1, 0, placeholder);\n\t\tthis.host.notify();\n\t}\n\n\tpromoteNextQueuedToRunning(): void {\n\t\tif (this.state.messages.some(function (m) { return m.isPending && m.role === 'assistant' && !m.isBackgroundTask; })) return;\n\t\tvar nextIdx = this.state.messages.findIndex(function (m) {\n\t\t\treturn m.isPendingQueued && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue;\n\t\t});\n\t\tif (nextIdx === -1) return;\n\t\tvar existing = this.state.messages[nextIdx];\n\t\tvar promoted: ChatMessage = { role: 'user', content: existing.content, isPendingInProcess: true };\n\t\tif (existing.isBackgroundTask) promoted.isBackgroundTask = true;\n\t\tif (existing._indexFile) promoted._indexFile = existing._indexFile;\n\t\tif (existing._ts !== undefined) promoted._ts = existing._ts;\n\t\tif (existing._serverItemId !== undefined) promoted._serverItemId = existing._serverItemId;\n\t\tif (existing._ownerKey !== undefined) promoted._ownerKey = existing._ownerKey;\n\t\tif (existing.isSendingToServer) promoted.isSendingToServer = true;\n\t\tthis.state.messages[nextIdx] = promoted;\n\t\t// Carry the promoted turn's _serverItemId onto the \"Thinking...\" placeholder\n\t\t// (mirrors promoteNextBgQueuedToRunning). Without it, when this promoted turn\n\t\t// is resolved via the history-poll path — applyHistoryItemResolution, which\n\t\t// matches the pending assistant by _serverItemId — the placeholder is not\n\t\t// found, so the reply is spliced in BESIDE it and the \"Thinking...\" is\n\t\t// stranded forever (e.g. after a reload, or when a cancel advances the queue).\n\t\t// onQueuedSendResponse still finds it by position, so the queued-send path is\n\t\t// unaffected.\n\t\tvar placeholder: ChatMessage = { role: 'assistant', content: '', isPending: true };\n\t\tif (existing._serverItemId !== undefined) placeholder._serverItemId = existing._serverItemId;\n\t\tif (existing._ownerKey !== undefined) placeholder._ownerKey = existing._ownerKey;\n\t\tthis.state.messages.splice(nextIdx + 1, 0, placeholder);\n\t\tthis.host.notify();\n\t}\n\n\tresolveQueuedUserBubble(serverId?: string): number | undefined {\n\t\t// The two fallbacks below match by POSITION, not identity, so they must\n\t\t// never consider a bubble stamped for a different chat.\n\t\tvar liveKey = this.getHistoryCacheKey();\n\t\tvar isLocal = function (m: ChatMessage) { return m._ownerKey === undefined || m._ownerKey === liveKey; };\n\t\tvar userIdx = -1;\n\t\tif (serverId) {\n\t\t\tuserIdx = this.state.messages.findIndex(function (m) {\n\t\t\t\treturn m._serverItemId === serverId && (m.isPendingInProcess || m.isPendingQueued) &&\n\t\t\t\t\tm.role === 'user' && !m.isBackgroundTask;\n\t\t\t});\n\t\t}\n\t\tif (userIdx === -1) {\n\t\t\tuserIdx = this.state.messages.findIndex(function (m) {\n\t\t\t\treturn m.isPendingInProcess && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue && isLocal(m);\n\t\t\t});\n\t\t}\n\t\tif (userIdx === -1) {\n\t\t\tuserIdx = this.state.messages.findIndex(function (m) {\n\t\t\t\treturn m.isPendingQueued && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue && isLocal(m);\n\t\t\t});\n\t\t}\n\t\tif (serverId && this.cancelledServerIds.has(serverId)) {\n\t\t\tthis.cancelledServerIds.delete(serverId);\n\t\t\tif (userIdx >= 0) {\n\t\t\t\tvar ex = this.state.messages[userIdx];\n\t\t\t\tthis.state.messages[userIdx] = { role: 'user', content: ex.content, isCancelled: true, _serverItemId: ex._serverItemId, ...(ex._ownerKey !== undefined ? { _ownerKey: ex._ownerKey } : {}) };\n\t\t\t\tvar thIdx = this.state.messages.findIndex(function (m, i) {\n\t\t\t\t\treturn i > userIdx && m.isPending && m.role === 'assistant' && !m.isBackgroundTask;\n\t\t\t\t});\n\t\t\t\tif (thIdx !== -1) this.state.messages.splice(thIdx, 1);\n\t\t\t}\n\t\t\tthis.promoteNextQueuedToRunning();\n\t\t\treturn undefined;\n\t\t}\n\t\tif (userIdx >= 0) {\n\t\t\tvar exist = this.state.messages[userIdx];\n\t\t\tvar repl: ChatMessage = { role: 'user', content: exist.content };\n\t\t\tif (exist._serverItemId !== undefined) repl._serverItemId = exist._serverItemId;\n\t\t\tif (exist._ownerKey !== undefined) repl._ownerKey = exist._ownerKey;\n\t\t\tif (exist._ts !== undefined) repl._ts = exist._ts;\n\t\t\tthis.state.messages[userIdx] = repl;\n\t\t}\n\t\tvar thinkingIdx = userIdx >= 0\n\t\t\t? this.state.messages.findIndex(function (m, i) { return i > userIdx && m.isPending && m.role === 'assistant' && !m.isBackgroundTask; })\n\t\t\t: -1;\n\t\treturn thinkingIdx !== -1 ? thinkingIdx : (userIdx >= 0 ? userIdx + 1 : -1);\n\t}\n\n\tinsertAtTarget(msg: ChatMessage, targetIdx: number): void {\n\t\t// Error/direct replies land here rather than through the typewriter, so this\n\t\t// is where they pick up their display time.\n\t\tif (msg && msg.role === 'assistant' && msg._ts === undefined) msg._ts = wallClockNow();\n\t\tif (targetIdx >= 0 && this.state.messages[targetIdx] && this.state.messages[targetIdx].isPending) this.state.messages[targetIdx] = msg;\n\t\telse if (targetIdx >= 0) this.state.messages.splice(targetIdx, 0, msg);\n\t\telse this.state.messages.push(msg);\n\t}\n\n\tonQueuedSendResponse(_composed: string, response: any, platform: string, serverId?: string, ownerKey?: string): void {\n\t\tif (serverId) this.historyItemPolls.delete(serverId);\n\t\t// This turn resolved while a DIFFERENT chat is on screen (the user moved to\n\t\t// another project mid-flight). state.messages now belongs to that chat, and\n\t\t// resolveQueuedUserBubble's positional fallbacks would happily hijack ITS\n\t\t// pending bubble — or, finding nothing, push this answer onto its list.\n\t\t// Settle in the owning chat's cache instead and leave the view untouched.\n\t\tif (ownerKey && this.getHistoryCacheKey() !== ownerKey) {\n\t\t\tvar offReply: ChatMessage = isErrorResponseBody(response)\n\t\t\t\t? { role: 'assistant', content: getErrorMessage(response), isError: true }\n\t\t\t\t: { role: 'assistant', content: ((platform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response)) || '').trim() || 'No text response received from AI provider.' };\n\t\t\tthis._applyReplyToCache(ownerKey, offReply, serverId);\n\t\t\tif (serverId) this.cancelledServerIds.delete(serverId);\n\t\t\treturn;\n\t\t}\n\t\tvar targetIdx = this.resolveQueuedUserBubble(serverId);\n\t\tif (targetIdx === undefined) { this.host.notify(); this.updateHistoryCache(); return; }\n\t\tif (isErrorResponseBody(response)) {\n\t\t\tthis.insertAtTarget({ role: 'assistant', content: getErrorMessage(response), isError: true }, targetIdx);\n\t\t} else {\n\t\t\tvar answer = (platform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response));\n\t\t\tanswer = (answer || '').trim() || 'No text response received from AI provider.';\n\t\t\tvar lid = this._newLocalId();\n\t\t\tif (targetIdx >= 0 && this.state.messages[targetIdx] && this.state.messages[targetIdx].isPending) {\n\t\t\t\tthis.state.messages[targetIdx] = { role: 'assistant', content: '', _localId: lid };\n\t\t\t\tthis.host.notify(); this.enqueueTypewrite(targetIdx, answer, lid);\n\t\t\t} else if (targetIdx >= 0) {\n\t\t\t\tthis.state.messages.splice(targetIdx, 0, { role: 'assistant', content: '', _localId: lid });\n\t\t\t\tthis.host.notify(); this.enqueueTypewrite(targetIdx, answer, lid);\n\t\t\t} else {\n\t\t\t\tvar aiIdx = this.state.messages.length;\n\t\t\t\tthis.state.messages.push({ role: 'assistant', content: '', _localId: lid });\n\t\t\t\tthis.host.notify(); this.enqueueTypewrite(aiIdx, answer, lid);\n\t\t\t}\n\t\t}\n\t\tthis._removeStrayPendingAssistants();\n\t\tthis.promoteNextQueuedToRunning();\n\t\tthis.updateHistoryCache();\n\t\tthis.host.notify();\n\t\t// ARRIVAL, not a user action: only follow if the user is still pinned to\n\t\t// the bottom. Scrolled-up readers keep their position.\n\t\tthis.host.scrollToBottomIfSticky(true);\n\t}\n\n\tonQueuedSendError(_composed: string, err: any, serverId?: string, ownerKey?: string): void {\n\t\tvar self = this;\n\t\tif (serverId) this.historyItemPolls.delete(serverId);\n\t\t// Off-chat resolution — see onQueuedSendResponse. Settle in the owning\n\t\t// chat's cache rather than mutating whatever chat is on screen now.\n\t\tif (ownerKey && this.getHistoryCacheKey() !== ownerKey) {\n\t\t\tvar isGone = err && (err.code === 'NOT_EXISTS' || (err.body && err.body.code === 'NOT_EXISTS'));\n\t\t\tthis._applyReplyToCache(ownerKey, isGone\n\t\t\t\t? { role: 'assistant', content: 'Request was cancelled.', isError: true }\n\t\t\t\t: { role: 'assistant', content: getErrorMessage(err), isError: true }, serverId);\n\t\t\tif (serverId) this.cancelledServerIds.delete(serverId);\n\t\t\treturn;\n\t\t}\n\t\tvar isNotExists = err && (err.code === 'NOT_EXISTS' || (err.body && err.body.code === 'NOT_EXISTS'));\n\t\tif (isNotExists) {\n\t\t\tvar userIdx = serverId\n\t\t\t\t? this.state.messages.findIndex(function (m) { return m._serverItemId === serverId && (m.isPendingInProcess || m.isPendingQueued) && m.role === 'user' && !m.isBackgroundTask; })\n\t\t\t\t: this.state.messages.findIndex(function (m) { return m.isPendingInProcess && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue; });\n\t\t\tif (!serverId && userIdx === -1) {\n\t\t\t\tuserIdx = this.state.messages.findIndex(function (m) { return m.isPendingQueued && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue; });\n\t\t\t}\n\t\t\tif (userIdx >= 0) {\n\t\t\t\tvar ex = this.state.messages[userIdx];\n\t\t\t\tvar repl: ChatMessage = { role: 'user', content: ex.content, isCancelled: true };\n\t\t\t\tif (ex._serverItemId !== undefined) repl._serverItemId = ex._serverItemId;\n\t\t\t\tthis.state.messages[userIdx] = repl;\n\t\t\t}\n\t\t\tif (serverId) {\n\t\t\t\tvar thById = this.state.messages.findIndex(function (m) { return m._serverItemId === serverId && m.isPending && m.role === 'assistant' && !m.isBackgroundTask; });\n\t\t\t\tif (thById !== -1) this.state.messages.splice(thById, 1);\n\t\t\t\telse if (userIdx >= 0) {\n\t\t\t\t\tvar thPos = this.state.messages.findIndex(function (m, i) { return i > userIdx && m.isPending && m.role === 'assistant' && !m.isBackgroundTask; });\n\t\t\t\t\tif (thPos !== -1) this.state.messages.splice(thPos, 1);\n\t\t\t\t}\n\t\t\t} else if (userIdx >= 0) {\n\t\t\t\tvar thPos2 = this.state.messages.findIndex(function (m, i) { return i > userIdx && m.isPending && m.role === 'assistant' && !m.isBackgroundTask; });\n\t\t\t\tif (thPos2 !== -1) this.state.messages.splice(thPos2, 1);\n\t\t\t}\n\t\t\tif (serverId) this.cancelledServerIds.delete(serverId);\n\t\t\tthis._removeStrayPendingAssistants();\n\t\t\tthis.promoteNextQueuedToRunning(); this.updateHistoryCache(); this.host.notify(); this.host.scrollToBottomIfSticky(true);\n\t\t\treturn;\n\t\t}\n\t\tvar targetIdx = this.resolveQueuedUserBubble(serverId);\n\t\tif (targetIdx === undefined) { this.host.notify(); this.updateHistoryCache(); return; }\n\t\tthis.insertAtTarget({ role: 'assistant', content: getErrorMessage(err), isError: true }, targetIdx);\n\t\tthis._removeStrayPendingAssistants();\n\t\tthis.promoteNextQueuedToRunning(); this.updateHistoryCache(); this.host.notify(); this.host.scrollToBottomIfSticky(true);\n\t}\n\n\tcancelQueuedMessage(msg: ChatMessage, idx: number): void {\n\t\tvar self = this;\n\t\tvar id = this.host.getIdentity();\n\t\tvar serverId = msg._serverItemId;\n\t\tif (!serverId || msg._cancelling) return;\n\t\tvar platform = id.platform;\n\t\tif (platform !== 'claude' && platform !== 'openai') return;\n\t\tvar url = platform === 'claude' ? ANTHROPIC_MESSAGES_API_URL : OPENAI_RESPONSES_API_URL;\n\t\tvar queueBase = id.userId || id.serviceId;\n\t\tvar queue = (msg.isBackgroundTask || msg._useBgQueue) ? queueBase + BG_INDEXING_QUEUE_SUFFIX : queueBase;\n\t\tthis.state.messages[idx] = Object.assign({}, msg, { _cancelling: true, _cancelError: undefined });\n\t\tthis.host.notify();\n\t\tPromise.resolve(this.host.cancelRequest({\n\t\t\turl: url, method: 'POST', id: serverId, queue: queue, service: id.serviceId, owner: id.owner,\n\t\t})).then(function (result: any) {\n\t\t\tif (result && result.removed) {\n\t\t\t\tself.cancelledServerIds.add(serverId as string);\n\t\t\t\tself._stopPoll(serverId as string);\n\t\t\t\tvar qi = self.bgTaskQueue.findIndex(function (e) { return e.id === serverId; });\n\t\t\t\tif (qi !== -1) self.bgTaskQueue.splice(qi, 1);\n\t\t\t\tvar removeIdx = self.state.messages.findIndex(function (m) {\n\t\t\t\t\treturn m._serverItemId === serverId && (m.isPendingQueued || m.isPendingInProcess) && m.role === 'user';\n\t\t\t\t});\n\t\t\t\tif (removeIdx !== -1) {\n\t\t\t\t\t// Carry the background/file markers onto the rebuild. Dropping them\n\t\t\t\t\t// took a cancelled INDEXING pass out of its file's collapsed row\n\t\t\t\t\t// (buildChatDisplayList only groups isBackgroundTask bubbles), so the\n\t\t\t\t\t// row stayed \"Indexing…\" forever while a bare \"Indexing: file\" bubble\n\t\t\t\t\t// appeared beside it.\n\t\t\t\t\tvar wasMsg = self.state.messages[removeIdx];\n\t\t\t\t\tvar cancelledMsg: ChatMessage = { role: 'user', content: wasMsg.content, isCancelled: true, _serverItemId: serverId };\n\t\t\t\t\tif (wasMsg.isBackgroundTask) cancelledMsg.isBackgroundTask = true;\n\t\t\t\t\tif (wasMsg._indexFile) cancelledMsg._indexFile = wasMsg._indexFile;\n\t\t\t\t\tif (wasMsg._useBgQueue) cancelledMsg._useBgQueue = true;\n\t\t\t\t\tif (wasMsg._ownerKey !== undefined) cancelledMsg._ownerKey = wasMsg._ownerKey;\n\t\t\t\t\tself.state.messages[removeIdx] = cancelledMsg;\n\t\t\t\t\tvar thById = self.state.messages.findIndex(function (m) { return m._serverItemId === serverId && m.isPending && m.role === 'assistant'; });\n\t\t\t\t\tif (thById !== -1) self.state.messages.splice(thById, 1);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar thPos = self.state.messages.findIndex(function (m, i) {\n\t\t\t\t\t\t\treturn i > removeIdx && m.isPending && m.role === 'assistant' &&\n\t\t\t\t\t\t\t\t(msg.isBackgroundTask ? !!m.isBackgroundTask : !m.isBackgroundTask);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (thPos !== -1) self.state.messages.splice(thPos, 1);\n\t\t\t\t\t}\n\t\t\t\t\tif (msg.isBackgroundTask) self.promoteNextBgQueuedToRunning(); else self.promoteNextQueuedToRunning();\n\t\t\t\t\tself.updateHistoryCache();\n\t\t\t\t}\n\t\t\t\tself.host.notify();\n\t\t\t} else {\n\t\t\t\tvar errMsg = result && typeof result.message === 'string' && result.message ? result.message : 'Could not remove from queue.';\n\t\t\t\tvar ci = self.state.messages.findIndex(function (m) { return m._serverItemId === serverId && m.role === 'user'; });\n\t\t\t\tif (ci !== -1) { self.state.messages[ci] = Object.assign({}, self.state.messages[ci], { _cancelling: false, _cancelError: errMsg }); self.host.notify(); }\n\t\t\t}\n\t\t}).catch(function (err: any) {\n\t\t\tvar errMsg = err && typeof err.message === 'string' && err.message ? err.message : 'Could not remove from queue.';\n\t\t\tvar ci = self.state.messages.findIndex(function (m) { return m._serverItemId === serverId && m.role === 'user'; });\n\t\t\tif (ci !== -1) { self.state.messages[ci] = Object.assign({}, self.state.messages[ci], { _cancelling: false, _cancelError: errMsg }); self.host.notify(); }\n\t\t});\n\t}\n\n\t/**\n\t * Stop indexing a file, from its collapsed row — every pass at once, not just\n\t * the bubble the user happens to see.\n\t *\n\t * A big file is indexed as a CHAIN of passes, so cancelling only the live one\n\t * accomplishes nothing: the next pass is dispatched as soon as it settles.\n\t * Three things end the chain:\n\t * 1. every queued/running pass of this file is cancelled server-side\n\t * (csr-cancel deletes a queued row and flags a running one \"cancelled\",\n\t * which is also the worker's gate for NOT enqueueing the next window);\n\t * 2. the file is remembered in cancelledIndexKeys, so the client-driven\n\t * resume (maybeResumeIndexing) stops dispatching CONTINUE passes; and\n\t * 3. any of its passes still sitting in bgTaskQueue is dropped by the next\n\t * drain rather than surfacing a fresh \"Indexing…\" bubble.\n\t *\n\t * Records already written by the passes that DID run are kept — this stops the\n\t * work, it does not undo it.\n\t */\n\tcancelIndexingGroup(group: IndexingGroup): void {\n\t\tvar self = this;\n\t\tif (!group || !group.key) return;\n\t\t// The group belongs to the chat on screen, so scope its key the same way\n\t\t// _indexKeyOf scopes a queued task's.\n\t\tvar scoped = this.getHistoryCacheKey() + '|' + group.key;\n\t\tthis.cancelledIndexKeys.add(scoped);\n\t\tvar ids = group.cancellableIds || [];\n\t\tif (!ids.length) { this.host.notify(); return; }\n\t\tids.forEach(function (serverId) {\n\t\t\t// Address the message by IDENTITY, not by the index captured when the\n\t\t\t// display list was built: an earlier cancel in this same loop may already\n\t\t\t// have spliced the array (a group can have more than one live pass), and a\n\t\t\t// stale index would mark the WRONG bubble as cancelling.\n\t\t\tvar idx = self.state.messages.findIndex(function (m) {\n\t\t\t\treturn m._serverItemId === serverId && m.role === 'user' &&\n\t\t\t\t\t(m.isPendingQueued || m.isPendingInProcess);\n\t\t\t});\n\t\t\tif (idx === -1) return;\n\t\t\tself.cancelQueuedMessage(self.state.messages[idx], idx);\n\t\t});\n\t}\n\n\t// --- typewriter -------------------------------------------------------\n\t// Reveal `fullText` into a message bubble at a constant wall-clock RATE\n\t// (chars/second) driven by requestAnimationFrame, rather than a fixed number\n\t// of characters per fixed-delay tick. This is what keeps typing smooth and\n\t// cheap on slow machines:\n\t//\n\t// * Each frame reveals `elapsed_ms * CHARS_PER_SEC` characters, so the\n\t// visual speed is the same regardless of how long a frame actually took.\n\t// * As the bubble's markdown grows, each re-render gets more expensive, so\n\t// frames get longer — which makes each frame reveal MORE characters and\n\t// therefore do FEWER, larger renders. That converts the old O(n^2)\n\t// \"re-render the whole growing string once per 3 characters\" (which got\n\t// slower and slower and pegged the CPU) into roughly O(n): the number of\n\t// renders self-throttles to what the machine can actually paint.\n\t// * rAF paces us to the browser's paint cycle and pauses in background\n\t// tabs, so we never queue work faster than it can be drawn.\n\ttypewriteIntoIndex(idx: number, fullText: string, localId?: string): Promise<void> {\n\t\tvar self = this;\n\t\tif (!fullText) return Promise.resolve();\n\n\t\tvar CHARS_PER_SEC = 300; // reveal rate (was ~188 = 3 chars / 16ms) — a bit faster\n\t\tvar MIN_STEP = 1; // always make progress, even on a sub-ms frame\n\t\tvar MAX_FRAME_MS = 1000; // cap catch-up after a long stall / backgrounded tab\n\n\t\t// Atomic regions that must never be left half-revealed: file fences\n\t\t// (shown as a download chip / hidden as \"[generating …]\" while unclosed —\n\t\t// and potentially huge, so revealed in one jump) and inline links\n\t\t// (a partial link is broken markdown). If a frame's reveal boundary lands\n\t\t// inside one, snap it to the region end so the chip/link appears whole.\n\t\tvar regions: Array<{ start: number; end: number }> = [], m;\n\t\tvar fenceRegex = /```[^\\n`]+?\\.[^\\s.`]+\\n[\\s\\S]*?```/g;\n\t\twhile ((m = fenceRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });\n\t\tvar linkRegex = createInlineLinkRegex();\n\t\twhile ((m = linkRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });\n\t\tregions.sort(function (a, b) { return a.start - b.start; });\n\n\t\tthis.state.typing = true; this.state.typingAbort = false;\n\t\tvar i = 0;\n\t\tvar last = nowMs();\n\n\t\treturn new Promise<void>(function (resolve) {\n\t\t\tvar done = false;\n\t\t\tvar doc: any = _g.document;\n\t\t\tfunction isHidden(): boolean { return !!(doc && doc.hidden); }\n\t\t\tfunction cleanup(): void {\n\t\t\t\tif (doc && doc.removeEventListener) doc.removeEventListener('visibilitychange', onVisibility);\n\t\t\t}\n\t\t\tfunction finish(): void {\n\t\t\t\tif (done) return;\n\t\t\t\tdone = true;\n\t\t\t\tcleanup();\n\t\t\t\tif (!self.state.typingAbort) {\n\t\t\t\t\t// Re-find the bubble by localId and, if it's gone, bail WITHOUT\n\t\t\t\t\t// writing — never fall back to the numeric idx, which a concurrent\n\t\t\t\t\t// array mutation may have repurposed for an unrelated message\n\t\t\t\t\t// (mirrors frame()'s currentIdx===-1 bail below).\n\t\t\t\t\tvar fi = localId ? self.state.messages.findIndex(function (mm) { return mm._localId === localId; }) : idx;\n\t\t\t\t\tif (fi !== -1) {\n\t\t\t\t\t\tvar t = self.state.messages[fi];\n\t\t\t\t\t\tif (t) { t.content = fullText; self.host.refreshMessageBubble(fi); }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tself.state.typing = false;\n\t\t\t\tresolve();\n\t\t\t}\n\t\t\t// requestAnimationFrame is PAUSED in a backgrounded tab (setTimeout only\n\t\t\t// throttles), so an rAF-driven reveal would freeze there — leaving a blank\n\t\t\t// bubble and stalling the sequential enqueueTypewrite queue until refocus.\n\t\t\t// When the page is (or becomes) hidden, skip the animation and show the\n\t\t\t// full text immediately so the queue keeps draining.\n\t\t\tfunction onVisibility(): void { if (isHidden()) finish(); }\n\t\t\tif (doc && doc.addEventListener) doc.addEventListener('visibilitychange', onVisibility);\n\t\t\tfunction frame(t: number): void {\n\t\t\t\tif (done) return;\n\t\t\t\tif (self.state.typingAbort || i >= fullText.length || isHidden()) { finish(); return; }\n\n\t\t\t\tvar dt = t - last; last = t;\n\t\t\t\tif (!(dt > 0)) dt = 16; // first frame / clock glitch\n\t\t\t\tif (dt > MAX_FRAME_MS) dt = MAX_FRAME_MS;\n\t\t\t\tvar step = Math.round(dt * CHARS_PER_SEC / 1000);\n\t\t\t\tif (step < MIN_STEP) step = MIN_STEP;\n\t\t\t\tvar next = Math.min(fullText.length, i + step);\n\n\t\t\t\t// Extend past any atomic region the newly-revealed span (i, next]\n\t\t\t\t// cuts into. Iterate to convergence so back-to-back regions (e.g. a\n\t\t\t\t// link right after a fence) are all revealed whole in one frame.\n\t\t\t\tfor (var changed = true; changed;) {\n\t\t\t\t\tchanged = false;\n\t\t\t\t\tfor (var k = 0; k < regions.length; k++) {\n\t\t\t\t\t\tvar r = regions[k];\n\t\t\t\t\t\tif (next > r.start && i < r.end && r.end > next) { next = r.end; changed = true; }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (next > fullText.length) next = fullText.length;\n\t\t\t\ti = next;\n\n\t\t\t\tvar currentIdx = localId ? self.state.messages.findIndex(function (mm) { return mm._localId === localId; }) : idx;\n\t\t\t\tif (currentIdx === -1) { finish(); return; }\n\t\t\t\tvar target = self.state.messages[currentIdx];\n\t\t\t\tif (!target) { finish(); return; }\n\t\t\t\ttarget.content = fullText.slice(0, i);\n\t\t\t\tself.host.refreshMessageBubble(currentIdx);\n\t\t\t\tself.host.scrollToBottomIfSticky();\n\t\t\t\tnextFrame(frame);\n\t\t\t}\n\t\t\tif (isHidden()) { finish(); return; }\n\t\t\tnextFrame(frame);\n\t\t});\n\t}\n\n\tprivate typewriterQueue: Promise<any> = Promise.resolve();\n\tenqueueTypewrite(idx: number, fullText: string, localId?: string): Promise<any> {\n\t\tvar self = this;\n\t\t// Stamp the reply bubble's display time as it starts revealing. This is the\n\t\t// single chokepoint every typed reply (immediate, queued, and bg-resolution)\n\t\t// passes through, so it is where a live reply gets its \"when it arrived\"\n\t\t// timestamp; a history reload later replaces it with the server `updated`.\n\t\tvar target = this.state.messages[idx];\n\t\tif (target && target._ts === undefined) target._ts = wallClockNow();\n\t\tthis.typewriterQueue = this.typewriterQueue.then(function () { return self.typewriteIntoIndex(idx, fullText, localId); });\n\t\treturn this.typewriterQueue;\n\t}\n\n\t// --- cache+resume immediate-send rendering -----------------------------\n\t// Render the just-resolved reply (read from aiChatHistoryCache) into the\n\t// pending assistant bubble, character-by-character. Runs AFTER the reply is\n\t// already in the cache (dispatchAgentRequest appended it); errors are shown\n\t// instantly (no typing). Promotes the next queued message immediately so its\n\t// \"Thinking…\" bubble appears without waiting for this typewriter to finish.\n\ttypewriteLatestReply(key: string): Promise<any> {\n\t\tvar cached = this.aiChatHistoryCache[key];\n\t\tif (!cached || !cached.messages.length) return Promise.resolve();\n\t\tvar latest: ChatMessage | undefined;\n\t\tfor (var i = cached.messages.length - 1; i >= 0; i--) {\n\t\t\tvar m = cached.messages[i];\n\t\t\tif (m.role === 'assistant' && !m.isPending) { latest = m; break; }\n\t\t}\n\t\tif (!latest) return Promise.resolve();\n\t\tvar pendingIdx = this.state.messages.findIndex(function (mm) {\n\t\t\treturn mm.isPending && mm.role === 'assistant' && !mm.isBackgroundTask;\n\t\t});\n\t\tif (pendingIdx === -1) return Promise.resolve();\n\t\tif (latest.isError || !latest.content) {\n\t\t\tthis.state.messages[pendingIdx] = { role: 'assistant', content: latest.content || '', isError: !!latest.isError };\n\t\t\tthis._removeStrayPendingAssistants();\n\t\t\tthis.host.notify();\n\t\t\tthis.promoteNextQueuedToRunning();\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tvar lid = this._newLocalId();\n\t\tthis.state.messages[pendingIdx] = { role: 'assistant', content: '', isPending: false, _localId: lid };\n\t\tthis._removeStrayPendingAssistants();\n\t\tthis.host.notify();\n\t\tthis.promoteNextQueuedToRunning();\n\t\treturn this.enqueueTypewrite(pendingIdx, latest.content, lid);\n\t}\n\n\t// Remove any leftover non-background pending (\"Thinking…\") assistant bubbles.\n\t// There is normally at most ONE such bubble at a time (promoteNext* refuses to\n\t// add a second), so any extra is a duplicate — it appears when a concurrent\n\t// history refetch re-maps the still-\"running\" turn into a pending placeholder\n\t// (with a real _serverItemId) while the local pending bubble (no _serverItemId)\n\t// is rescued and re-appended (see loadHistory rescue below). Each resolve path\n\t// only replaces the FIRST pending bubble, so without this a stray \"Thinking…\"\n\t// survives next to the reply/error. MUST run AFTER the resolved bubble has been\n\t// made non-pending and BEFORE promoteNext*() (so a freshly-promoted Thinking,\n\t// which is added only once no pending assistant remains, is preserved).\n\t_removeStrayPendingAssistants(): void {\n\t\tfor (var k = this.state.messages.length - 1; k >= 0; k--) {\n\t\t\tvar m = this.state.messages[k];\n\t\t\tif (m.isPending && m.role === 'assistant' && !m.isBackgroundTask) this.state.messages.splice(k, 1);\n\t\t}\n\t}\n\n\t// Drop the pending flags on the resolved turn's USER bubble (preserving its\n\t// content + background-task marker). Needed because a bg \"Indexing:\" turn's user\n\t// bubble carries isPendingInProcess; leaving it set keeps the bubble visually\n\t// stuck and keeps its bgTaskQueue entry alive forever.\n\t_clearPendingUserBubble(itemId: string): void {\n\t\tvar uIdx = this.state.messages.findIndex(function (m) {\n\t\t\treturn m.role === 'user' && m._serverItemId === itemId &&\n\t\t\t\t(m.isPendingInProcess || m.isPendingQueued || m.isSendingToServer);\n\t\t});\n\t\tif (uIdx === -1) return;\n\t\tvar u = this.state.messages[uIdx];\n\t\tvar cleaned: ChatMessage = { role: 'user', content: u.content, _serverItemId: itemId };\n\t\tif (u.isBackgroundTask) cleaned.isBackgroundTask = true;\n\t\tif (u._ts !== undefined) cleaned._ts = u._ts;\n\t\t// Carry the file ref: it is what keeps this pass in its file's collapsed\n\t\t// row (the label parser is only a fallback for older cached bubbles).\n\t\tif (u._indexFile) cleaned._indexFile = u._indexFile;\n\t\tthis.state.messages[uIdx] = cleaned;\n\t}\n\n\t// If an immediate-send request for the current cache key is still in flight\n\t// (e.g. the view unmounted then remounted mid-request), show the sending\n\t// state, await it, then render the reply from the cache. Skipped when the\n\t// list already has its own pending/queued bubbles (those resolve via their\n\t// own polls). The displayed reply also lands via dispatchComposedMessage's\n\t// own finally if the view never unmounted — this is the remount recovery.\n\tresumePendingRequest(token: number): Promise<void> {\n\t\tvar self = this;\n\t\tvar key = this.getHistoryCacheKey();\n\t\tvar pending = key ? this.pendingAgentRequests[key] : undefined;\n\t\tif (!pending) return Promise.resolve();\n\t\tif (this.state.messages.some(function (m) { return (m.isPending || m.isPendingQueued) && !m.isBackgroundTask && !m._useBgQueue; })) return Promise.resolve();\n\t\tthis.state.sending = true;\n\t\tthis.host.scrollToBottomIfSticky(true);\n\t\treturn Promise.resolve(pending).catch(function () { }).then(function () {\n\t\t\tif (token !== self.state.gateRefreshToken) return;\n\t\t\tself.state.sending = false;\n\t\t\treturn Promise.resolve(self.typewriteLatestReply(key)).then(function () { self.host.scrollToBottomIfSticky(true); });\n\t\t});\n\t}\n\n\t// --- background-task resolution + drain -------------------------------\n\thandleHistoryItemResolution(itemId: string, response: any, platform: string): void {\n\t\tthis.applyHistoryItemResolution(itemId, response, platform);\n\t\tthis.promoteNextBgQueuedToRunning();\n\t}\n\n\tapplyHistoryItemResolution(itemId: string, response: any, platform: string): void {\n\t\tthis.historyItemPolls.delete(itemId);\n\t\tvar isErr = isErrorResponseBody(response);\n\t\tvar answer = isErr ? getErrorMessage(response)\n\t\t\t: ((platform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response)) || '').trim();\n\t\t// Hide the internal indexing-completion marker from the displayed summary.\n\t\tif (!isErr && answer) answer = answer.split(INDEXING_COMPLETE_MARKER).join('').trim();\n\t\tvar idx = this.state.messages.findIndex(function (m) { return m.isPending && m._serverItemId === itemId; });\n\t\tif (idx !== -1) {\n\t\t\t// A bg \"Indexing:\" turn pushes a user bubble (isPendingInProcess) ALONGSIDE\n\t\t\t// the assistant Thinking; replacing only the assistant leaves that user\n\t\t\t// bubble stuck pending — and drainBgTaskQueue then never clears its queue\n\t\t\t// entry (its stillPending check stays true). Un-pend it here too.\n\t\t\tthis._clearPendingUserBubble(itemId);\n\t\t\t// Carry isBackgroundTask onto the REPLACEMENT. These rebuilds are fresh\n\t\t\t// object literals, so anything not copied is lost — and dropping this flag\n\t\t\t// made a pass that resolved LIVE fall out of its file's collapsed row\n\t\t\t// (buildChatDisplayList only considers isBackgroundTask messages), while\n\t\t\t// the same pass rebuilt from history stayed grouped. That mismatch is the\n\t\t\t// \"new indexing response renders outside the group\" bug.\n\t\t\tvar wasBgTask = !!this.state.messages[idx].isBackgroundTask;\n\t\t\tif (isErr) {\n\t\t\t\tthis.state.messages[idx] = { role: 'assistant', content: answer, isError: true, _serverItemId: itemId };\n\t\t\t\tif (wasBgTask) this.state.messages[idx].isBackgroundTask = true;\n\t\t\t\tthis.host.notify(); this.updateHistoryCache(); return;\n\t\t\t}\n\t\t\tvar text = answer || 'No text response received from AI provider.';\n\t\t\t// A background-indexing reply is INSIDE a collapsed row: nothing of it is\n\t\t\t// on screen. Typewriting it anyway put it on the one shared, serial\n\t\t\t// typewriter queue, so the user's own next reply — which IS on screen —\n\t\t\t// lost its \"Thinking...\" spinner and sat as an EMPTY bubble for however\n\t\t\t// long the invisible indexing summary took to reveal (seconds per pass,\n\t\t\t// additive across files). It also held state.typing true for the whole\n\t\t\t// time, which disables the platform/model pickers and no-ops Clear\n\t\t\t// history, and ran a per-frame scroll for content nobody can see.\n\t\t\t// Write it straight in; expanding the row then shows it complete.\n\t\t\tif (wasBgTask) {\n\t\t\t\tthis.state.messages[idx] = { role: 'assistant', content: text, isBackgroundTask: true, _serverItemId: itemId };\n\t\t\t\tthis.host.notify(); this.updateHistoryCache(); return;\n\t\t\t}\n\t\t\tvar lid = this._newLocalId();\n\t\t\tthis.state.messages[idx] = { role: 'assistant', content: '', _localId: lid, _serverItemId: itemId };\n\t\t\tthis.host.notify(); this.enqueueTypewrite(idx, text, lid);\n\t\t\tthis.updateHistoryCache(); return;\n\t\t}\n\t\tvar userIdx = this.state.messages.findIndex(function (m) {\n\t\t\treturn m.role === 'user' && m._serverItemId === itemId && (m.isPendingQueued || m.isPendingInProcess);\n\t\t});\n\t\tif (userIdx === -1) return;\n\t\tvar ex = this.state.messages[userIdx];\n\t\t// Same carry-over as above, plus _indexFile / _useBgQueue: this rebuild is\n\t\t// what keeps an indexing REQUEST bubble in its file's collapsed row (and a\n\t\t// bg-queued chat cancelling against the right queue) once the pass settles.\n\t\tvar settledUser: ChatMessage = { role: 'user', content: ex.content, _serverItemId: itemId };\n\t\tif (ex.isBackgroundTask) settledUser.isBackgroundTask = true;\n\t\tif (ex._ts !== undefined) settledUser._ts = ex._ts;\n\t\tif (ex._indexFile) settledUser._indexFile = ex._indexFile;\n\t\tif (ex._useBgQueue) settledUser._useBgQueue = true;\n\t\tthis.state.messages[userIdx] = settledUser;\n\t\tif (isErr) {\n\t\t\tvar errReply: ChatMessage = { role: 'assistant', content: answer, isError: true, _serverItemId: itemId };\n\t\t\tif (ex.isBackgroundTask) errReply.isBackgroundTask = true;\n\t\t\tthis.state.messages.splice(userIdx + 1, 0, errReply);\n\t\t\tthis.host.notify(); this.updateHistoryCache(); return;\n\t\t}\n\t\tvar text2 = answer || 'No text response received from AI provider.';\n\t\t// Same as above: a collapsed row's reply is not on screen, so revealing it\n\t\t// character by character only blocks the queue the visible reply needs.\n\t\tif (ex.isBackgroundTask) {\n\t\t\tthis.state.messages.splice(userIdx + 1, 0, { role: 'assistant', content: text2, isBackgroundTask: true, _serverItemId: itemId });\n\t\t\tthis.host.notify(); this.updateHistoryCache(); return;\n\t\t}\n\t\tvar lid2 = this._newLocalId();\n\t\tvar reply: ChatMessage = { role: 'assistant', content: '', _localId: lid2, _serverItemId: itemId };\n\t\tthis.state.messages.splice(userIdx + 1, 0, reply);\n\t\tthis.host.notify(); this.enqueueTypewrite(userIdx + 1, text2, lid2);\n\t\tthis.updateHistoryCache();\n\t}\n\n\t/** How a bg task maps onto a collapsed row: the row's own key (storage path\n\t * when known, else the filename), scoped to the chat it belongs to. A storage\n\t * path is project-relative (\"report.xlsx\"), and ONE ChatSession serves every\n\t * project — unscoped, stopping a file in one project would silently suppress\n\t * the same filename's continuations in another. */\n\tprivate _indexKeyOf(entry: BgTaskEntry): string {\n\t\tif (!entry) return '';\n\t\tvar file = entry.storagePath || entry.filename;\n\t\tif (!file) return '';\n\t\treturn entry.serviceId + '#' + entry.platform + '|' + file;\n\t}\n\n\t/**\n\t * Reconcile the bg queue with the files the user has stopped.\n\t *\n\t * A FIRST pass (no resumePass) is a fresh indexing request — a re-upload, or a\n\t * Reindex from the file manager — so it LIFTS the stop: the key is a storage\n\t * path, and without this an earlier cancel would silently kill every future\n\t * index of the same path. A continuation of a stopped file is dropped instead,\n\t * covering the pass that was dispatched in the moment before the cancel landed.\n\t */\n\tprivate _applyIndexCancellations(): void {\n\t\tif (!this.cancelledIndexKeys.size) return;\n\t\tfor (var i = this.bgTaskQueue.length - 1; i >= 0; i--) {\n\t\t\tvar entry = this.bgTaskQueue[i];\n\t\t\tvar key = this._indexKeyOf(entry);\n\t\t\tif (!key || !this.cancelledIndexKeys.has(key)) continue;\n\t\t\tif (!entry.resumePass) { this.cancelledIndexKeys.delete(key); continue; }\n\t\t\tthis.bgTaskQueue.splice(i, 1);\n\t\t\tthis._stopPoll(entry.id);\n\t\t\tthis._cancelServerItem(entry.id);\n\t\t}\n\t}\n\n\t/**\n\t * Cancel any live pass of a stopped file that turned up on its own.\n\t *\n\t * The client is not the only thing that continues a file: for PDFs and (when\n\t * windowed indexing is on) text/grid files the WORKER enqueues the next window\n\t * itself, and that pass reaches the chat through the history poll, never\n\t * through bgTaskQueue. The worker's own gate stops the chain when the running\n\t * row is cancelled — but if the row had already finished when the user hit\n\t * stop, the next window was queued a moment earlier and still arrives. Stop it\n\t * here rather than making the user hit stop again.\n\t *\n\t * Runs from drainBgTaskQueue, which both clients call after a history load.\n\t */\n\tprivate _sweepCancelledIndexing(): void {\n\t\tif (!this.cancelledIndexKeys.size) return;\n\t\tvar self = this;\n\t\tvar chatKey = this.getHistoryCacheKey();\n\t\tvar targets: { msg: ChatMessage; idx: number }[] = [];\n\t\tthis.state.messages.forEach(function (m, i) {\n\t\t\tif (!m.isBackgroundTask || m.role !== 'user' || !m._serverItemId) return;\n\t\t\tif (m._cancelling || m.isSendingToServer) return;\n\t\t\tif (!(m.isPendingQueued || m.isPendingInProcess)) return;\n\t\t\tvar ref = m._indexFile;\n\t\t\tvar file = ref && (ref.path || ref.name);\n\t\t\tif (!file || !self.cancelledIndexKeys.has(chatKey + '|' + file)) return;\n\t\t\ttargets.push({ msg: m, idx: i });\n\t\t});\n\t\ttargets.forEach(function (t) {\n\t\t\tvar idx = self.state.messages.indexOf(t.msg);\n\t\t\tself.cancelQueuedMessage(t.msg, idx === -1 ? t.idx : idx);\n\t\t});\n\t}\n\n\t/** Best-effort server-side cancel of a bg-queue item that has no bubble (so\n\t * cancelQueuedMessage, which drives one, has nothing to act on). */\n\tprivate _cancelServerItem(serverId: string): void {\n\t\tvar id = this.host.getIdentity();\n\t\tif (!serverId || (id.platform !== 'claude' && id.platform !== 'openai')) return;\n\t\tvar url = id.platform === 'claude' ? ANTHROPIC_MESSAGES_API_URL : OPENAI_RESPONSES_API_URL;\n\t\tPromise.resolve(this.host.cancelRequest({\n\t\t\turl: url, method: 'POST', id: serverId,\n\t\t\tqueue: (id.userId || id.serviceId) + BG_INDEXING_QUEUE_SUFFIX,\n\t\t\tservice: id.serviceId, owner: id.owner,\n\t\t})).catch(function () { /* the pass may already have finished; nothing to do */ });\n\t}\n\n\t// Inject \"Indexing: <file>\" bubbles for queued bg tasks + attach their polls.\n\tdrainBgTaskQueue(): void {\n\t\tvar self = this;\n\t\tvar id = this.host.getIdentity();\n\t\tvar svcId = id.serviceId, plat = id.platform;\n\t\tif (!svcId || plat === 'none' || !this.host.isViewMounted()) return;\n\t\t// Before anything is surfaced: drop continuations of files the user stopped\n\t\t// (and let a fresh first pass lift the stop), then cancel any worker-queued\n\t\t// pass of a stopped file that reached the chat through history.\n\t\tthis._applyIndexCancellations();\n\t\tthis._sweepCancelledIndexing();\n\t\t// Index messages by _serverItemId ONCE, so the per-entry presence/pending\n\t\t// checks below are O(1) instead of a full messages.some() scan each. With a\n\t\t// large bg queue (bulk uploads) the old nested scan was O(queue x messages)\n\t\t// per drain, and the drain runs once per uploaded file (O(n^3) overall).\n\t\tvar presentIds: { [id: string]: boolean } = {};\n\t\tvar pendingIds: { [id: string]: boolean } = {};\n\t\tthis.state.messages.forEach(function (m) {\n\t\t\tvar sid = m._serverItemId;\n\t\t\tif (sid == null) return;\n\t\t\tpresentIds[sid] = true;\n\t\t\tif (m.isPending || m.isPendingInProcess || m.isPendingQueued) pendingIds[sid] = true;\n\t\t});\n\t\tfor (var i = this.bgTaskQueue.length - 1; i >= 0; i--) {\n\t\t\tvar e = this.bgTaskQueue[i];\n\t\t\tif (e.serviceId !== svcId || e.platform !== plat) continue;\n\t\t\tif (presentIds[e.id] && !pendingIds[e.id]) this.bgTaskQueue.splice(i, 1);\n\t\t}\n\t\tthis.bgTaskQueue.forEach(function (entry) {\n\t\t\tif (entry.serviceId !== svcId || entry.platform !== plat) return;\n\t\t\t// Bubble injection and poll attachment are INDEPENDENT. An entry whose bubble\n\t\t\t// already exists may still need a poll — that is exactly the state a paused\n\t\t\t// drain leaves behind, and returning early here stranded it as a permanent\n\t\t\t// \"Thinking...\" once polling resumed.\n\t\t\tif (!presentIds[entry.id]) {\n\t\t\tvar isRunning = entry.status === 'running';\n\t\t\tvar userBubble: ChatMessage = {\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: self.host.formatIndexingLabel(entry.filename, entry.mime, entry.size, entry.storagePath, entry.isReindex, !!entry.resumePass),\n\t\t\t\tisBackgroundTask: true,\n\t\t\t\t_serverItemId: entry.id,\n\t\t\t\t// Structured ref so this live pass groups with the same file's passes\n\t\t\t\t// rebuilt from history (see indexing_groups.buildChatDisplayList).\n\t\t\t\t_indexFile: {\n\t\t\t\t\tname: entry.filename,\n\t\t\t\t\tpath: entry.storagePath,\n\t\t\t\t\tmime: entry.mime,\n\t\t\t\t\tsize: entry.size,\n\t\t\t\t\tisReindex: !!entry.isReindex,\n\t\t\t\t\tcontinued: !!entry.resumePass,\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (isRunning) userBubble.isPendingInProcess = true; else userBubble.isPendingQueued = true;\n\t\t\tself.state.messages.push(userBubble);\n\t\t\tif (isRunning) {\n\t\t\t\tself.state.messages.push({ role: 'assistant', content: '', isPending: true, isPendingInProcess: true, isBackgroundTask: true, _serverItemId: entry.id });\n\t\t\t}\n\t\t\tpresentIds[entry.id] = true; // keep the index consistent with the pushed bubbles\n\t\t\tself.host.notify(); self.updateHistoryCache(); self.host.scrollToBottomIfSticky(false);\n\t\t\t}\n\t\t\tif (!self.isPollingPaused() && !self.historyItemPolls.has(entry.id) && typeof entry.poll === 'function') {\n\t\t\t\tvar capturedId = entry.id, capturedPlat = plat;\n\t\t\t\tvar capturedEntry = entry;\n\t\t\t\tvar wasStopped = false;\n\t\t\t\tvar bp = entry.poll({ latency: POLL_INTERVAL });\n\t\t\t\tself._trackPoll(entry.id, 'bg', bp);\n\t\t\t\tbp.then(function (response: any) {\n\t\t\t\t\t// A stopped poll is not a result: leave the bubble and the queue entry\n\t\t\t\t\t// exactly as they were so resumePolling can re-attach.\n\t\t\t\t\tif (isPollStopped(response)) { wasStopped = true; return; }\n\t\t\t\t\tself.handleHistoryItemResolution(capturedId, response, capturedPlat);\n\t\t\t\t\tself.maybeResumeIndexing(capturedEntry, response, capturedPlat);\n\t\t\t\t}).catch(function (err: any) {\n\t\t\t\t\tself.historyItemPolls.delete(capturedId);\n\t\t\t\t\tvar isNotExists = err && (err.code === 'NOT_EXISTS' || (err.body && err.body.code === 'NOT_EXISTS'));\n\t\t\t\t\t// Settle the REQUEST bubble first, unconditionally. Only a RUNNING\n\t\t\t\t\t// pass gets an assistant placeholder, so for a queued one the lookup\n\t\t\t\t\t// below finds nothing and every branch was skipped — leaving the\n\t\t\t\t\t// request bubble isPendingQueued with its queue entry about to be\n\t\t\t\t\t// spliced away, i.e. no poll left to ever clear it. One such bubble\n\t\t\t\t\t// pins the whole collapsed row to \"active\": a spinner and a Stop\n\t\t\t\t\t// button against a dead id, until the page is reloaded.\n\t\t\t\t\tself._clearPendingUserBubble(capturedId);\n\t\t\t\t\tvar bi = self.state.messages.findIndex(function (m) { return m.isPending && m._serverItemId === capturedId; });\n\t\t\t\t\tif (bi !== -1) {\n\t\t\t\t\t\tif (isNotExists) self.state.messages.splice(bi, 1);\n\t\t\t\t\t\telse self.state.messages[bi] = { role: 'assistant', content: getErrorMessage(err), isError: true, isBackgroundTask: true, _serverItemId: capturedId };\n\t\t\t\t\t} else if (!isNotExists) {\n\t\t\t\t\t\t// No placeholder to turn into the error (a queued pass). Put one\n\t\t\t\t\t\t// after the request bubble so the row reports the failure instead\n\t\t\t\t\t\t// of quietly settling to \"Indexed\".\n\t\t\t\t\t\tvar ui = self.state.messages.findIndex(function (m) { return m.role === 'user' && m._serverItemId === capturedId; });\n\t\t\t\t\t\tif (ui !== -1) {\n\t\t\t\t\t\t\tself.state.messages.splice(ui + 1, 0, { role: 'assistant', content: getErrorMessage(err), isError: true, isBackgroundTask: true, _serverItemId: capturedId });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tself.host.notify(); self.updateHistoryCache();\n\t\t\t\t}).then(function () {\n\t\t\t\t\t// Keep the queue entry when the poll was merely stopped, or resuming\n\t\t\t\t\t// would have nothing left to re-attach to.\n\t\t\t\t\tif (wasStopped) return;\n\t\t\t\t\tvar qi = self.bgTaskQueue.findIndex(function (q) { return q.id === capturedId; });\n\t\t\t\t\tif (qi !== -1) self.bgTaskQueue.splice(qi, 1);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tthis.promoteNextBgQueuedToRunning();\n\t}\n\n\t// Resume-across-passes: if a background INDEXING task for a paged file (spreadsheet or\n\t// text) finished WITHOUT the completion marker, the agent ran out of room before reading\n\t// the whole file - dispatch a CONTINUE pass (up to a cap) that resumes from where the\n\t// already-saved records leave off. Additive + guarded so it never loops forever and\n\t// never breaks the resolution path.\n\t//\n\t// VISION files (PDFs rendered to page images) are NOT resumed here: the proxy worker\n\t// advances their page window itself, off the renderer's true page count. Driving them\n\t// from the browser is what used to lose pages on long documents - the chain lived in tab\n\t// memory (a reload or a closed tab ended it), and it stopped whenever the model claimed\n\t// completion, which on an 88-page file happened at page 15. Continuing to dispatch here\n\t// as well would now double-index every window.\n\tmaybeResumeIndexing(entry: BgTaskEntry, response: any, platform: string): void {\n\t\tvar self = this;\n\t\ttry {\n\t\t\tif (!entry || !entry.storagePath) return;\n\t\t\t// The user stopped this file from its collapsed row. Dispatching the next\n\t\t\t// pass here is exactly what \"stop\" has to prevent — the cancelled pass\n\t\t\t// settles, and without this the chain simply carries on.\n\t\t\tif (this.cancelledIndexKeys.has(this._indexKeyOf(entry))) return;\n\t\t\tif (!isPagedReadFile(entry.filename, entry.mime)) return;\n\t\t\tif (isImageVisionFile(entry.filename, entry.mime)) return; // worker owns this loop (PDF vision)\n\t\t\t// When windowed indexing is on, the WORKER drives the text/grid loop too. The\n\t\t\t// client MUST NOT also resume, or two drivers each enqueue a continuation per\n\t\t\t// pass and the chain FORKS - duplicate records, runaway passes. Same reason\n\t\t\t// PDFs early-return above. Gated on the flag so the old client-driven path is\n\t\t\t// untouched when windowing is off.\n\t\t\tif (windowedIndexingEnabled() && isWindowedReadFile(entry.filename, entry.mime)) return;\n\t\t\tif (isErrorResponseBody(response)) return; // a failed pass is not \"incomplete\"\n\t\t\tvar answer = (platform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response)) || '';\n\t\t\tif (answer.indexOf(INDEXING_COMPLETE_MARKER) !== -1) return; // fully indexed\n\t\t\tvar pass = (entry.resumePass || 0) + 1;\n\t\t\tif (pass > MAX_INDEXING_RESUME_PASSES) return; // give up after the cap\n\t\t\tvar id = this.host.getIdentity();\n\t\t\tif (!id || id.platform === 'none' || id.serviceId !== entry.serviceId) return;\n\t\t\tnotifyAgentContinueIndexing({\n\t\t\t\tplatform: id.platform as 'claude' | 'openai',\n\t\t\t\tmodel: id.model,\n\t\t\t\tservice: id.serviceId,\n\t\t\t\towner: id.owner,\n\t\t\t\tuserId: id.userId || id.serviceId,\n\t\t\t\tserviceName: id.serviceName,\n\t\t\t\tserviceDescription: id.serviceDescription,\n\t\t\t\tattachment: {\n\t\t\t\t\tname: entry.filename,\n\t\t\t\t\tstoragePath: entry.storagePath,\n\t\t\t\t\tmime: entry.mime,\n\t\t\t\t\tsize: entry.size,\n\t\t\t\t\turl: '',\n\t\t\t\t},\n\t\t\t}).then(function (ack: any) {\n\t\t\t\tif (ack && typeof ack.id === 'string') {\n\t\t\t\t\tself.bgTaskQueue.push({\n\t\t\t\t\t\tserviceId: id.serviceId, platform: id.platform as 'claude' | 'openai', id: ack.id,\n\t\t\t\t\t\tfilename: entry.filename, storagePath: entry.storagePath,\n\t\t\t\t\t\tisReindex: entry.isReindex, mime: entry.mime, size: entry.size,\n\t\t\t\t\t\tstatus: ack.status === 'running' ? 'running' : 'pending',\n\t\t\t\t\t\tpoll: ack.poll, resumePass: pass,\n\t\t\t\t\t});\n\t\t\t\t\tself.drainBgTaskQueue();\n\t\t\t\t}\n\t\t\t}, function (e: any) { console.error('[chat-engine] resume-indexing dispatch failed', e); });\n\t\t} catch (e) { /* best-effort: resume must never break bg-task resolution */ }\n\t}\n\n\t// --- history fetch + pagination --------------------------------------\n\t// Initial load (fetchMore=false) replaces the list (with in-flight rescue +\n\t// cancelled-merge) and attaches polls to running/pending items; pagination\n\t// (fetchMore=true) prepends older messages. The DOM scroll-restore for the\n\t// older-prepend is the VIEW's job (it captures the pre-prepend scroll position\n\t// and restores after this resolves) — the engine never measures the DOM.\n\tloadHistory(fetchMore?: boolean, token?: number): Promise<void> {\n\t\tvar self = this;\n\t\tvar id = this.host.getIdentity();\n\t\t// Key this fetch is FOR, snapshotted from the same identity read the\n\t\t// request is built from. The rescue below compares against this rather\n\t\t// than a live getHistoryCacheKey(), so a project switch mid-fetch can't\n\t\t// make another chat's in-flight bubbles look local.\n\t\tvar loadKey = (!id.serviceId || id.platform === 'none') ? '' : id.serviceId + '#' + id.platform;\n\t\tif (token === undefined) token = this.state.gateRefreshToken;\n\t\tif ((this.state.loadingHistory && this.state.historyRequestToken === token) || id.platform === 'none' || !id.serviceId) {\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tthis.state.historyRequestToken = token;\n\t\tthis.state.loadingHistory = true;\n\t\tif (fetchMore) this.state.loadingOlderHistory = true;\n\t\tthis.host.notify(); // surface \"Fetching history...\" while it loads\n\t\tvar platform = id.platform as 'claude' | 'openai';\n\t\tvar serviceId = id.serviceId, owner = id.owner;\n\t\tvar options: any = { fetchMore: fetchMore };\n\t\tif (fetchMore && this.state.historyStartKeyHistory.length) options.startKeyHistory = this.state.historyStartKeyHistory.slice();\n\n\t\tvar fetchHistory = function () { return getChatHistory({ service: serviceId, owner: owner, platform: platform }, options); };\n\n\t\treturn Promise.resolve().then(fetchHistory).catch(function (err: any) {\n\t\t\tif (isAuthExpiredError(err) && !isNonRetryableRequestError(err)) return self.host.refreshSession().then(fetchHistory);\n\t\t\tthrow err;\n\t\t}).then(function (history: any) {\n\t\t\tif (token !== self.state.gateRefreshToken) return;\n\t\t\tvar chatList = history && Array.isArray(history.list) ? history.list : [];\n\t\t\tchatList.forEach(function (item: any) {\n\t\t\t\tif (isBgIndexingQueue(item.queue_name)) {\n\t\t\t\t\tvar userText = extractLastUserTextFromRequest(item.request_body);\n\t\t\t\t\tif (typeof userText === 'string' && (userText.indexOf('A new file has just been uploaded') === 0 || userText.indexOf('CONTINUE indexing') === 0)) item._isBgTask = true;\n\t\t\t\t\telse item._isOnBgQueue = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\tvar list = chatList.sort(function (a: any, b: any) {\n\t\t\t\tvar ai = typeof a.id === 'string' ? a.id : '', bi = typeof b.id === 'string' ? b.id : '';\n\t\t\t\treturn ai > bi ? -1 : (ai < bi ? 1 : 0);\n\t\t\t});\n\t\t\tvar mapped = mapHistoryListToMessages(list, platform, {\n\t\t\t\tclearedAt: self.host.getClearedAt(),\n\t\t\t\tserviceId: id.serviceId,\n\t\t\t\tformatIndexingLabel: self.host.formatIndexingLabel,\n\t\t\t}).messages;\n\n\t\t\t// Set when a first-page refresh re-prepended already-loaded older pages,\n\t\t\t// so the cursor reset below knows not to rewind to page 1's boundary.\n\t\t\tvar keptOlderPages = false;\n\n\t\t\tif (fetchMore) {\n\t\t\t\tself.state.messages = mapped.concat(self.state.messages);\n\t\t\t} else {\n\t\t\t\tif (self.state.typing) self.state.typingAbort = true;\n\t\t\t\tvar serverIds: any = {};\n\t\t\t\tmapped.forEach(function (m: any) { if (m._serverItemId) serverIds[m._serverItemId] = 1; });\n\t\t\t\tvar locallyCancelled: any = {};\n\t\t\t\tself.state.messages.forEach(function (m) { if (m.isCancelled && m._serverItemId) locallyCancelled[m._serverItemId] = m; });\n\t\t\t\t// A cancel the server has not acknowledged yet. Without carrying these\n\t\t\t\t// across the replace, a collapsed row mid-cancel drops its \"Stopping...\"\n\t\t\t\t// state and re-offers Stop; the second click cancels an id that is\n\t\t\t\t// already gone and writes a bogus \"Could not remove from queue.\" onto a\n\t\t\t\t// run that WAS stopped successfully.\n\t\t\t\tvar inFlightCancel: any = {};\n\t\t\t\tself.state.messages.forEach(function (m) {\n\t\t\t\t\tif (!m._serverItemId) return;\n\t\t\t\t\tif (m._cancelling || m._cancelError) inFlightCancel[m._serverItemId] = m;\n\t\t\t\t});\n\t\t\t\t// If the freshly-mapped server list ALREADY shows this in-flight turn\n\t\t\t\t// as a pending placeholder (a non-bg pending assistant, which carries\n\t\t\t\t// a real _serverItemId), re-pushing the local no-_serverItemId\n\t\t\t\t// user+Thinking would DUPLICATE it. Each resolve path only clears the\n\t\t\t\t// first pending bubble, so the duplicate strands a \"Thinking…\" beside\n\t\t\t\t// the reply/error. There is at most one in-flight regular turn, so a\n\t\t\t\t// mapped pending assistant IS this turn — skip the redundant local copy.\n\t\t\t\tvar mappedHasPendingAssistant = mapped.some(function (m: any) {\n\t\t\t\t\treturn m.isPending && m.role === 'assistant' && !m.isBackgroundTask;\n\t\t\t\t});\n\t\t\t\tvar rescued: ChatMessage[] = [];\n\t\t\t\tfor (var ri = 0; ri < self.state.messages.length; ri++) {\n\t\t\t\t\tvar mm = self.state.messages[ri];\n\t\t\t\t\tif (mm.isBackgroundTask) continue;\n\t\t\t\t\t// Belongs to a different chat (another project, or another\n\t\t\t\t\t// platform on this one) — it must not be carried onto THIS\n\t\t\t\t\t// chat's freshly-fetched history.\n\t\t\t\t\tif (mm._ownerKey !== undefined && mm._ownerKey !== loadKey) continue;\n\t\t\t\t\tif (mm._serverItemId && serverIds[mm._serverItemId]) continue;\n\t\t\t\t\tif (!mm._serverItemId) {\n\t\t\t\t\t\tif (mappedHasPendingAssistant) continue;\n\t\t\t\t\t\tif (mm.isSendingToServer || mm.isPendingQueued || mm.isPendingInProcess || mm.isPending) rescued.push(mm);\n\t\t\t\t\t\telse if (self.state.sending && mm.role === 'user') {\n\t\t\t\t\t\t\tvar next = self.state.messages[ri + 1];\n\t\t\t\t\t\t\tif (next && !next.isBackgroundTask && next.isPending && !next._serverItemId) rescued.push(mm);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// PRESERVE already-loaded older pages. `mapped` is only page 1, so a\n\t\t\t\t// blind replace threw away every page the user had scrolled in. This\n\t\t\t\t// path runs from resumePolling (visibilitychange), so merely leaving\n\t\t\t\t// the tab and coming back wiped the whole scrolled-in history.\n\t\t\t\t//\n\t\t\t\t// The list is oldest-first (fetchMore PREPENDS), and ids sort with\n\t\t\t\t// newest largest, so anything already in the list whose _serverItemId\n\t\t\t\t// sorts BELOW page 1's oldest id is an older page. Those are disjoint\n\t\t\t\t// from `mapped` (strict <), so re-prepending cannot duplicate.\n\t\t\t\tvar oldestInPage1: string | undefined = undefined;\n\t\t\t\tmapped.forEach(function (m: any) {\n\t\t\t\t\tvar sid = m._serverItemId;\n\t\t\t\t\tif (typeof sid !== 'string') return;\n\t\t\t\t\tif (oldestInPage1 === undefined || sid < (oldestInPage1 as string)) oldestInPage1 = sid;\n\t\t\t\t});\n\t\t\t\t// Only merge when the current list is genuinely a continuation of THIS\n\t\t\t\t// page 1 (shares at least one id with it). A project switch, a cleared\n\t\t\t\t// horizon, or a wholly-new page means the head is unrelated history and\n\t\t\t\t// must be replaced, not spliced.\n\t\t\t\tvar sharesPage1 = self.state.messages.some(function (m) {\n\t\t\t\t\treturn typeof m._serverItemId === 'string' && !!serverIds[m._serverItemId as string];\n\t\t\t\t});\n\t\t\t\tvar retainedOlder: ChatMessage[] = (!sharesPage1 || oldestInPage1 === undefined) ? [] : self.state.messages.filter(function (m) {\n\t\t\t\t\t// Settled server history only; in-flight bubbles are the rescue\n\t\t\t\t\t// loop's job below and would otherwise be kept twice.\n\t\t\t\t\tif (typeof m._serverItemId !== 'string') return false;\n\t\t\t\t\t// Same ownership predicate as the rescue loop: never carry another\n\t\t\t\t\t// project's bubbles onto this chat (the cross-project leak fix).\n\t\t\t\t\t// Compare against the snapshotted loadKey, never a live read.\n\t\t\t\t\tif (m._ownerKey !== undefined && m._ownerKey !== loadKey) return false;\n\t\t\t\t\treturn (m._serverItemId as string) < (oldestInPage1 as string);\n\t\t\t\t});\n\t\t\t\tkeptOlderPages = retainedOlder.length > 0;\n\t\t\t\tself.state.messages = keptOlderPages ? retainedOlder.concat(mapped) : mapped;\n\t\t\t\trescued.forEach(function (m) { self.state.messages.push(m); });\n\t\t\t\tif (Object.keys(locallyCancelled).length) {\n\t\t\t\t\tfor (var ci = 0; ci < self.state.messages.length; ci++) {\n\t\t\t\t\t\tvar c = self.state.messages[ci];\n\t\t\t\t\t\tif (!c._serverItemId || !locallyCancelled[c._serverItemId] || c.isCancelled) continue;\n\t\t\t\t\t\t// Rebuild FROM the mapped bubble rather than as a bare literal:\n\t\t\t\t\t\t// dropping isBackgroundTask / _indexFile here ejected a stopped\n\t\t\t\t\t\t// indexing pass from its file's collapsed row, where it then rendered\n\t\t\t\t\t\t// as a standalone \"Indexing: <file>\" chat bubble and left the row\n\t\t\t\t\t\t// recomputing its passes as if that one had never happened.\n\t\t\t\t\t\tself.state.messages[ci] = {\n\t\t\t\t\t\t\trole: 'user', content: c.content, isCancelled: true, _serverItemId: c._serverItemId,\n\t\t\t\t\t\t\tisBackgroundTask: c.isBackgroundTask, _indexFile: c._indexFile,\n\t\t\t\t\t\t\t_useBgQueue: c._useBgQueue, _ownerKey: c._ownerKey,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (ci + 1 < self.state.messages.length && self.state.messages[ci + 1].isPending && self.state.messages[ci + 1]._serverItemId === c._serverItemId) {\n\t\t\t\t\t\t\tself.state.messages.splice(ci + 1, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Re-stamp a cancel that is still in flight (see inFlightCancel above).\n\t\t\t\t// Only onto a bubble the server still reports as pending — once it has\n\t\t\t\t// settled the flags describe nothing the user can act on.\n\t\t\t\tfor (var fi = 0; fi < self.state.messages.length; fi++) {\n\t\t\t\t\tvar fm = self.state.messages[fi];\n\t\t\t\t\tvar was = fm._serverItemId && inFlightCancel[fm._serverItemId];\n\t\t\t\t\tif (!was || fm.isCancelled) continue;\n\t\t\t\t\tif (!(fm.isPendingQueued || fm.isPendingInProcess || fm.isPending)) continue;\n\t\t\t\t\tif (was._cancelling) fm._cancelling = true;\n\t\t\t\t\tif (was._cancelError) fm._cancelError = was._cancelError;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Only adopt page 1's cursor when page 1 IS the whole list. If older pages\n\t\t\t// survived the merge, rewinding here would make the next scroll-up\n\t\t\t// re-fetch page 2 (already on screen) and duplicate it.\n\t\t\tif (!keptOlderPages) {\n\t\t\t\tself.state.historyEndOfList = !!(history && history.endOfList);\n\t\t\t\tself.state.historyStartKeyHistory = history && Array.isArray(history.startKeyHistory) ? history.startKeyHistory : [];\n\t\t\t\tvar clearedAt = self.host.getClearedAt();\n\t\t\t\tif (clearedAt && chatList.length > 0) {\n\t\t\t\t\tvar oldestUpdated = Number(chatList[chatList.length - 1] && chatList[chatList.length - 1].updated);\n\t\t\t\t\tif (isFinite(oldestUpdated) && oldestUpdated <= clearedAt) self.state.historyEndOfList = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Clear loading flags BEFORE this render so the final paint is\n\t\t\t// indicator-free (and the view's scroll-restore math sees matching heights).\n\t\t\tif (self.state.historyRequestToken === token) { self.state.loadingHistory = false; self.state.loadingOlderHistory = false; }\n\t\t\tself.updateHistoryCache();\n\t\t\tself.host.notify();\n\n\t\t\tif (!fetchMore) {\n\t\t\t\tchatList.forEach(function (item: any) {\n\t\t\t\t\tif (item.status !== 'running' && item.status !== 'pending') return;\n\t\t\t\t\tif (!item.poll || !item.id) return;\n\t\t\t\t\t// Every live poll registers its item id in historyItemPolls — an\n\t\t\t\t\t// immediate dispatch (dispatchAgentRequest ~123), a queued send\n\t\t\t\t\t// (~253), a bg task (drain), or an earlier history poll — so the\n\t\t\t\t\t// has() check below already skips exactly the items a live poll\n\t\t\t\t\t// covers (including the one the current dispatch is polling). Do NOT\n\t\t\t\t\t// additionally skip every OTHER running/pending item just because\n\t\t\t\t\t// some immediate dispatch is in flight: that dispatch polls only ITS\n\t\t\t\t\t// item, so blanket-skipping stranded a concurrent \"-bg\" indexing item\n\t\t\t\t\t// (a separate server queue runs in parallel) — or any item whose own\n\t\t\t\t\t// poll had since died — with no live poller, leaving a \"Thinking...\"\n\t\t\t\t\t// that never clears even after the server settled everything.\n\t\t\t\t\tif (self.historyItemPolls.has(item.id)) return;\n\t\t\t\t\t// An in-flight immediate dispatch polls its own MAIN-QUEUE item but\n\t\t\t\t\t// registers that id in historyItemPolls only AFTER its provider POST\n\t\t\t\t\t// returns; in the sliver before that, a remount can surface the item\n\t\t\t\t\t// here still unregistered. Skip re-polling MAIN-QUEUE items while a\n\t\t\t\t\t// dispatch is in flight so we don't stack a 2nd poll on the item the\n\t\t\t\t\t// dispatch is about to poll. Bg-queue items (_isBgTask indexing tasks\n\t\t\t\t\t// and _isOnBgQueue chats) run on a SEPARATE queue the immediate\n\t\t\t\t\t// dispatch never polls, so they MUST still get their poll — skipping\n\t\t\t\t\t// them was the stranded-\"Thinking\" bug this guard must not revive.\n\t\t\t\t\tif (self.pendingAgentRequests[self.getHistoryCacheKey()] && !item._isBgTask && !item._isOnBgQueue) return;\n\t\t\t\t\t// Background indexing polls are suppressed while paused; foreground\n\t\t\t\t\t// replies the user is waiting on are not.\n\t\t\t\t\tif ((item._isBgTask || item._isOnBgQueue) && self.isPollingPaused()) return;\n\t\t\t\t\tvar capturedId = item.id;\n\t\t\t\t\tvar pp = item.poll({\n\t\t\t\t\t\tlatency: POLL_INTERVAL,\n\t\t\t\t\t\tonResponse: function (response: any) { if (isPollStopped(response)) return; self.handleHistoryItemResolution(capturedId, response, platform); },\n\t\t\t\t\t\tonError: function (err: any) {\n\t\t\t\t\t\t\tself.historyItemPolls.delete(capturedId);\n\t\t\t\t\t\t\tvar isNotExists = err && (err.code === 'NOT_EXISTS' || (err.body && err.body.code === 'NOT_EXISTS'));\n\t\t\t\t\t\t\tvar aIdx = self.state.messages.findIndex(function (m) { return m.isPending && m._serverItemId === capturedId; });\n\t\t\t\t\t\t\tif (isNotExists) {\n\t\t\t\t\t\t\t\tvar uIdx = self.state.messages.findIndex(function (m) { return m.role === 'user' && m._serverItemId === capturedId && !m.isCancelled; });\n\t\t\t\t\t\t\t\t// Decide bg-ness from whichever bubble actually exists. A\n\t\t\t\t\t\t\t\t// QUEUED pass has no assistant placeholder (history.ts emits\n\t\t\t\t\t\t\t\t// none), so reading it off the placeholder alone classified\n\t\t\t\t\t\t\t\t// every queued indexing pass as foreground: the rebuild below\n\t\t\t\t\t\t\t\t// then dropped isBackgroundTask/_indexFile, ejecting the pass\n\t\t\t\t\t\t\t\t// from its collapsed row as a raw \"Indexing: <file>\" chat\n\t\t\t\t\t\t\t\t// bubble, and promoteNextQueuedToRunning span up a \"Thinking...\"\n\t\t\t\t\t\t\t\t// on an unrelated queued FOREGROUND message.\n\t\t\t\t\t\t\t\tvar isBg = (aIdx !== -1 && !!self.state.messages[aIdx].isBackgroundTask)\n\t\t\t\t\t\t\t\t\t|| (uIdx !== -1 && !!self.state.messages[uIdx].isBackgroundTask);\n\t\t\t\t\t\t\t\tif (aIdx !== -1) self.state.messages.splice(aIdx, 1);\n\t\t\t\t\t\t\t\tif (!isBg) {\n\t\t\t\t\t\t\t\t\tif (uIdx !== -1) { var ex = self.state.messages[uIdx]; self.state.messages[uIdx] = { role: 'user', content: ex.content, isCancelled: true, _serverItemId: ex._serverItemId }; }\n\t\t\t\t\t\t\t\t\tself.cancelledServerIds.delete(capturedId); self.promoteNextQueuedToRunning();\n\t\t\t\t\t\t\t\t} else if (uIdx !== -1) {\n\t\t\t\t\t\t\t\t\t// Same carry-over every other rebuild does, so the pass stays\n\t\t\t\t\t\t\t\t\t// a member of its file's row while reading as cancelled.\n\t\t\t\t\t\t\t\t\tvar bex = self.state.messages[uIdx];\n\t\t\t\t\t\t\t\t\tvar bcancelled: ChatMessage = { role: 'user', content: bex.content, isCancelled: true, isBackgroundTask: true, _serverItemId: bex._serverItemId };\n\t\t\t\t\t\t\t\t\tif (bex._indexFile) bcancelled._indexFile = bex._indexFile;\n\t\t\t\t\t\t\t\t\tif (bex._useBgQueue) bcancelled._useBgQueue = true;\n\t\t\t\t\t\t\t\t\tself.state.messages[uIdx] = bcancelled;\n\t\t\t\t\t\t\t\t\tself.promoteNextBgQueuedToRunning();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tself.host.notify(); self.updateHistoryCache(); return;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (aIdx !== -1) {\n\t\t\t\t\t\t\t\tvar wasBg = self.state.messages[aIdx].isBackgroundTask;\n\t\t\t\t\t\t\t\tself.state.messages[aIdx] = { role: 'assistant', content: getErrorMessage(err), isError: true };\n\t\t\t\t\t\t\t\tif (wasBg) self.state.messages[aIdx].isBackgroundTask = true;\n\t\t\t\t\t\t\t\tself.host.notify(); self.updateHistoryCache();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\t// Anything on the BACKGROUND queue is pausable, not just items whose\n\t\t\t\t\t// prompt text we recognise as an indexing task. _isBgTask vs\n\t\t\t\t\t// _isOnBgQueue is a DISPLAY distinction (\"Indexing: file\" vs a normal\n\t\t\t\t\t// chat bubble); keying the pause off _isBgTask alone left every\n\t\t\t\t\t// bg-queue item we could not text-match polling forever.\n\t\t\t\t\tself._trackPoll(capturedId, (item._isBgTask || item._isOnBgQueue) ? 'bg' : 'fg', pp);\n\t\t\t\t\tif (pp && pp.catch) pp.catch(function () { });\n\t\t\t\t});\n\t\t\t\tself.drainBgTaskQueue();\n\t\t\t}\n\n\t\t\t// Sticky, NOT forcing: this runs after every first-page load, including\n\t\t\t// the one resumePolling fires on visibilitychange. Forcing yanked a\n\t\t\t// reader who had scrolled up back to the bottom. On a genuine mount the\n\t\t\t// user is still pinned, so this behaves identically there.\n\t\t\tif (!fetchMore) return self.host.scrollToBottomIfSticky();\n\t\t}).catch(function (err: any) {\n\t\t\tconsole.warn('[chat-engine] getChatHistory failed', err);\n\t\t}).then(function () {\n\t\t\tif (self.state.historyRequestToken === token) {\n\t\t\t\tvar wasLoading = self.state.loadingHistory || self.state.loadingOlderHistory;\n\t\t\t\tself.state.loadingHistory = false; self.state.loadingOlderHistory = false;\n\t\t\t\tif (wasLoading) self.host.notify();\n\t\t\t}\n\t\t\t// Every first-page load ends here — mount, resumePolling, a cache-restore\n\t\t\t// refresh — and every one of them can leave a box too short to scroll,\n\t\t\t// which is the only trigger there is for reaching page 2. The view (which\n\t\t\t// alone can measure) pages its way out of it. Fired after the flags are\n\t\t\t// cleared so the fill loop does not see a request still in flight.\n\t\t\tif (self.host.onHistoryLoaded) self.host.onHistoryLoaded(!!fetchMore, token as number);\n\t\t});\n\t}\n\n\t// --- attachment upload orchestration ---------------------------------\n\t// Upload one attachment (a file = 1 member, a folder = N) to db storage and\n\t// queue indexing per member. The bytes I/O + chip rendering go through host\n\t// hooks; the overwrite/reindex flow, status lifecycle, and indexing live here.\n\tuploadSingleAttachment(att: any): Promise<Array<{ name: string; url: string; storagePath: string }>> {\n\t\tvar self = this;\n\t\tvar id = this.host.getIdentity();\n\t\tatt.status = 'uploading'; att.progress = 0; att.errorMessage = '';\n\t\tatt.errorCode = ''; att.errorDetail = ''; // clear any prior failure (retry)\n\t\tthis.host.renderAttachmentChips();\n\t\tvar members = (att.kind === 'folder')\n\t\t\t? (att.files || []).map(function (f: any) { return { file: f.file, relPath: f.path, storagePath: self.host.storagePathFor(f.path) }; })\n\t\t\t: [{ file: att.file, relPath: att.name, storagePath: this.host.storagePathFor(att.name) }];\n\t\tvar total = members.length;\n\t\tif (!total) return Promise.reject(new Error('Empty attachment'));\n\t\tvar urls: Array<{ name: string; url: string; storagePath: string }> = [];\n\t\tvar anyIndexFailed = false;\n\t\tvar chain: Promise<any> = Promise.resolve();\n\t\tmembers.forEach(function (member: any, idx: number) {\n\t\t\tchain = chain.then(function () {\n\t\t\t\tvar hadExists = false;\n\t\t\t\tvar skipped = false;\n\t\t\t\t// True when the file already existed and we are re-indexing over it\n\t\t\t\t// (user chose Reindex, OR Overwrite replaced the bytes). Drives the\n\t\t\t\t// delete-then-repost of the stale \"src::\" record below. Kept separate\n\t\t\t\t// from hadExists, which must keep driving ONLY the Reindexing/Indexing\n\t\t\t\t// label (isReindex) — overwrite still labels as \"Indexing:\".\n\t\t\t\tvar existedBefore = false;\n\t\t\t\tvar onProg = function (p: any) {\n\t\t\t\t\tif (p && p.total) {\n\t\t\t\t\t\tatt.progress = Math.floor(((idx + p.loaded / p.total) / total) * 100);\n\t\t\t\t\t\tself.host.renderAttachmentChips();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tvar doMemberUpload = function (checkExistence: boolean) {\n\t\t\t\t\treturn self.host.uploadFile({\n\t\t\t\t\t\tfile: member.file, storagePath: member.storagePath, checkExistence: checkExistence,\n\t\t\t\t\t\tonProgress: onProg, setAbort: function (abort) { att._abort = abort; },\n\t\t\t\t\t});\n\t\t\t\t};\n\t\t\t\treturn doMemberUpload(true).catch(function (err: any) {\n\t\t\t\t\tvar code = err && (err.code || (err.body && err.body.code));\n\t\t\t\t\tvar msg = err && (err.message || (err.body && err.body.message) || (typeof err === 'string' ? err : ''));\n\t\t\t\t\tvar isExists = code === 'EXISTS' || (msg && /exist/i.test(msg));\n\t\t\t\t\tif (!isExists) throw err; // a member upload failed → whole attachment fails (red)\n\t\t\t\t\treturn self.host.promptOverwrite(member.file.name).then(function (choice) {\n\t\t\t\t\t\tif (choice === 'overwrite') { existedBefore = true; return doMemberUpload(false); } // replace the existing file\n\t\t\t\t\t\tif (choice === 'skip') { skipped = true; return; } // leave it untouched; no upload/index\n\t\t\t\t\t\thadExists = true; existedBefore = true; // keep it; Reindex\n\t\t\t\t\t});\n\t\t\t\t}).then(function () {\n\t\t\t\t\tif (skipped) return; // user skipped this member — no url, no index request\n\t\t\t\t\treturn self.host.getTemporaryUrl(member.storagePath);\n\t\t\t\t}).then(function (url: string) {\n\t\t\t\t\tif (skipped) return; // guard the indexing branch for a skipped member\n\t\t\t\t\turls.push({ name: member.relPath, url: url, storagePath: member.storagePath });\n\t\t\t\t\tif (att.kind !== 'folder') { att.uploadedUrl = url; att.storagePath = member.storagePath; }\n\t\t\t\t\tvar mime = member.file.type || self.host.getMimeType(member.file.name);\n\t\t\t\t\t// Delete-then-repost: when the file already existed (Reindex or\n\t\t\t\t\t// Overwrite), delete the stale \"src::<storagePath>\" index record\n\t\t\t\t\t// first — the skapi backend cascades the delete to its\n\t\t\t\t\t// reference-linked children — so re-indexing REPLACES rather than\n\t\t\t\t\t// colliding/duplicating. Awaited before the index request is\n\t\t\t\t\t// enqueued. Best-effort + optional-hook guarded: a missing record,\n\t\t\t\t\t// a permission error, or a host without the hook must not block\n\t\t\t\t\t// indexing.\n\t\t\t\t\tvar preIndex = (existedBefore && typeof self.host.deleteExistingFileRecord === 'function')\n\t\t\t\t\t\t? Promise.resolve(self.host.deleteExistingFileRecord(member.storagePath)).catch(function () { })\n\t\t\t\t\t\t: Promise.resolve();\n\t\t\t\t\t// Run a client-side attachment parser (e.g. .hwp) if one matches; its\n\t\t\t\t\t// output is inlined into the indexing request (falls back to office\n\t\t\t\t\t// extraction / web_fetch when no parser matches or it yields nothing).\n\t\t\t\t\treturn preIndex.then(function () {\n\t\t\t\t\t\treturn parseAttachmentContent(member.file, member.file.name, mime || undefined);\n\t\t\t\t\t}).then(function (parsedContent: string | null) {\n\t\t\t\t\treturn notifyAgentSaveAttachment({\n\t\t\t\t\t\tplatform: id.platform as 'claude' | 'openai',\n\t\t\t\t\t\tmodel: id.model,\n\t\t\t\t\t\tservice: id.serviceId,\n\t\t\t\t\t\towner: id.owner,\n\t\t\t\t\t\tuserId: id.userId || id.serviceId,\n\t\t\t\t\t\tserviceName: id.serviceName,\n\t\t\t\t\t\tserviceDescription: id.serviceDescription,\n\t\t\t\t\t\tattachment: {\n\t\t\t\t\t\t\tname: member.file.name, storagePath: member.storagePath,\n\t\t\t\t\t\t\tmime: mime || undefined, size: member.file.size, url: url,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tparsedContent: parsedContent || undefined,\n\t\t\t\t\t}).then(function (ack: any) {\n\t\t\t\t\t\tif (ack && typeof ack.id === 'string') {\n\t\t\t\t\t\t\tself.bgTaskQueue.push({\n\t\t\t\t\t\t\t\tserviceId: id.serviceId, platform: id.platform as 'claude' | 'openai', id: ack.id,\n\t\t\t\t\t\t\t\tfilename: member.file.name,\n\t\t\t\t\t\t\t\tstoragePath: member.storagePath,\n\t\t\t\t\t\t\t\tisReindex: hadExists,\n\t\t\t\t\t\t\t\tmime: mime || undefined,\n\t\t\t\t\t\t\t\tsize: member.file.size,\n\t\t\t\t\t\t\t\tstatus: ack.status === 'running' ? 'running' : 'pending',\n\t\t\t\t\t\t\t\tpoll: ack.poll,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tself.drainBgTaskQueue(); // surface \"Indexing: <file>\" as soon as THIS file uploads\n\t\t\t\t\t\t}\n\t\t\t\t\t}, function (e: any) {\n\t\t\t\t\t\tconsole.error('[chat-engine] indexing request failed', e);\n\t\t\t\t\t\tanyIndexFailed = true; // uploaded but not indexed → yellow\n\t\t\t\t\t\t// Record the first index error's code/message for the report dialog.\n\t\t\t\t\t\tif (!att.errorCode && !att.errorDetail) {\n\t\t\t\t\t\t\tatt.errorCode = (e && (e.code || (e.body && e.body.code))) || '';\n\t\t\t\t\t\t\tatt.errorDetail = (e && (e.message || (e.body && e.body.message))) || (typeof e === 'string' ? e : '');\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn chain.then(function () {\n\t\t\tatt._abort = null; att.progress = 100;\n\t\t\tif (att.kind === 'folder') att.uploadedUrls = urls.map(function (u) { return { path: u.name, url: u.url, storagePath: u.storagePath }; });\n\t\t\tatt.status = anyIndexFailed ? 'indexError' : 'done';\n\t\t\tif (att.status === 'indexError') att.errorMessage = 'File indexing failed';\n\t\t\tself.host.renderAttachmentChips();\n\t\t\treturn urls;\n\t\t});\n\t}\n\n\t// Upload all not-yet-done attachments sequentially. Resolves to the full\n\t// list of { name, url, storagePath } for composing the chat message.\n\tuploadPendingAttachments(): Promise<Array<{ name: string; url: string; storagePath?: string }>> {\n\t\tvar self = this;\n\t\tthis.host.resetOverwriteBatch();\n\t\tthis.state.uploadingAttachments = true;\n\t\tthis.host.updateComposerControls();\n\t\tthis.host.renderAttachmentChips();\n\t\tvar collected: Array<{ name: string; url: string; storagePath?: string }> = [];\n\t\tvar snapshot = this.state.attachments.slice();\n\t\tvar chain: Promise<any> = Promise.resolve();\n\t\tsnapshot.forEach(function (att: any) {\n\t\t\tchain = chain.then(function () {\n\t\t\t\tif (!self.state.attachments.some(function (a: any) { return a.id === att.id; })) return; // removed\n\t\t\t\tif (att.status === 'done' || att.status === 'indexError') {\n\t\t\t\t\tif (att.kind === 'folder' && att.uploadedUrls) {\n\t\t\t\t\t\tatt.uploadedUrls.forEach(function (u: any) { collected.push({ name: u.path, url: u.url, storagePath: u.storagePath }); });\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (att.uploadedUrl) { collected.push({ name: att.name, url: att.uploadedUrl, storagePath: att.storagePath }); return; }\n\t\t\t\t}\n\t\t\t\treturn self.uploadSingleAttachment(att).then(function (us) {\n\t\t\t\t\tcollected.push.apply(collected, us);\n\t\t\t\t}).catch(function (err: any) {\n\t\t\t\t\tvar removed = !self.state.attachments.some(function (a: any) { return a.id === att.id; });\n\t\t\t\t\tvar aborted = err && (err.message === 'Aborted' || err === 'Aborted');\n\t\t\t\t\tif (removed || aborted) return;\n\t\t\t\t\tatt.status = 'error';\n\t\t\t\t\tatt.errorMessage = 'File upload has failed';\n\t\t\t\t\t// Preserve the original error code/message for the report dialog.\n\t\t\t\t\tatt.errorCode = (err && (err.code || (err.body && err.body.code))) || '';\n\t\t\t\t\tatt.errorDetail = (err && (err.message || (err.body && err.body.message))) || (typeof err === 'string' ? err : '');\n\t\t\t\t\tself.host.renderAttachmentChips();\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\tvar done = function () {\n\t\t\tself.state.uploadingAttachments = false; self.host.updateComposerControls(); self.host.renderAttachmentChips();\n\t\t\treturn collected;\n\t\t};\n\t\treturn chain.then(done, done);\n\t}\n\n\t// Stop timers / abort the typewriter (view teardown).\n\tstop(): void {\n\t\tthis.state.typingAbort = true;\n\t}\n\n\t// Bump the gate token so any in-flight immediate-send result is dropped\n\t// (called by the view on a service/platform switch or history clear).\n\tbumpGate(): void {\n\t\tthis.state.gateRefreshToken += 1;\n\t}\n}\n","/**\n * Background file-indexing turns, collapsed into ONE row per file.\n *\n * A single upload can produce many chat turns: the first \"Indexing: <file>\" pass\n * plus up to MAX_INDEXING_RESUME_PASSES CONTINUE passes, each with its own\n * request AND response bubble. Rendered flat, that reads as the same task\n * repeating forever, and any real question the user asks in between gets buried.\n *\n * buildChatDisplayList turns the flat message array into a DISPLAY list in which\n * every message belonging to one run of one file (however far apart the passes\n * sit, and whatever else is interleaved between them) is represented by a single\n * group entry, rendered at the position of that run's FIRST loaded pass.\n *\n * First, not newest. The message array is ordered by request CREATION time, and\n * a run's later passes are created one at a time as the previous one resolves —\n * by the client for the paged text path, and by the WORKER itself for the\n * rendered-page (PDF) path, which the client only learns about on its next\n * first-page history fetch. So a pass is routinely created minutes after the\n * upload, on a queue that runs in parallel with the foreground chat. Anchoring\n * at the newest pass meant one such late pass dragged the whole run — every\n * earlier pass with it — below any question the user had asked in the meantime,\n * and made a run that had visibly finished before the question render after it.\n * Anchoring at the first pass puts the row where the run actually began, which\n * is a position no later pass can change:\n * - a new pass never relocates the row, so nothing under the reader shifts;\n * - a question asked after the upload always renders below the row, which is\n * the order it happened in.\n * The cost is that a long-running index does not follow the conversation to the\n * bottom: once the user has chatted past the upload, the spinner and the Stop\n * button sit above their newest turns. That is a scroll away, and the row no\n * longer lies about when the work started.\n *\n * Paging older history is the one thing that CAN move the row: an older page\n * carrying earlier passes of a run already on screen moves it up into that page.\n * That happens at most once per run, only for a run whose start was never\n * loaded (`mayHaveOlder`), and it is the same event that already re-derives\n * `runKey` — so the view treats it as a new row either way.\n *\n * The group deliberately reports no authoritative pass TOTAL. History is paged\n * newest-first, so any total computed from loaded messages is a lower bound that\n * a later scroll-up would contradict. It reports STATE (indexing / indexed /\n * failed), how many passes are currently loaded, and `mayHaveOlder` when the\n * file's first pass is not among them.\n *\n * Pure and view-agnostic: agent.vue and the BunnyQuery widget both render from\n * this, so the two stay identical.\n */\nimport type { ChatMessage, IndexingFileRef } from './host';\n\nexport type IndexingGroupStatus = 'active' | 'done' | 'error' | 'cancelled';\n\nexport type IndexingGroup = {\n\t/** The FILE this row is about: storage path when known (a file can be\n\t * re-uploaded under a name that already exists elsewhere), else name. Shared\n\t * by every run of that file, and what ChatSession.cancelIndexingGroup and\n\t * _indexKeyOf match on — never use it as a render key. */\n\tkey: string;\n\t/** Identity of this ROW: one indexing RUN of that file. A file indexed on\n\t * Monday and re-indexed on Wednesday is two runs, and collapsing them into\n\t * one row erased Monday's from Monday's place in the conversation, claimed\n\t * its passes for Wednesday, and let Monday's failure be overwritten by\n\t * Wednesday's success. Named after the run's FIRST loaded pass (see where it\n\t * is assigned below), so passes appended to the run and other runs appearing\n\t * on either side of it never rename a row already on screen. This is the\n\t * render key and the expansion key. */\n\trunKey: string;\n\tname: string;\n\tpath?: string;\n\tmime?: string;\n\tsize?: number;\n\t/** True when any loaded pass was a re-index of an already-stored file. */\n\tisReindex: boolean;\n\t/** Every message of this file, in chat order, with its index in the source\n\t * array (so cancel/typewriter paths keep addressing the real message). */\n\tmembers: { msg: ChatMessage; index: number }[];\n\t/** Indexing passes LOADED (request bubbles), never a server-side total. */\n\tpassCount: number;\n\tstatus: IndexingGroupStatus;\n\t/** Server item ids of the passes that are still queued/running, so the row can\n\t * offer a stop button (ChatSession.cancelIndexingGroup cancels each). Empty\n\t * when nothing is cancellable — a finished file, or a live pass whose server\n\t * id has not come back yet. */\n\tcancellableIds: string[];\n\t/** A cancel request is in flight for one of the passes. */\n\tcancelling: boolean;\n\t/** Why the last cancel attempt failed (e.g. the pass had already finished). */\n\tcancelError?: string;\n\t/** The file's first pass is not among the loaded messages, so earlier passes\n\t * exist in history that has not been paged in yet. */\n\tmayHaveOlder: boolean;\n\t/** Position in the source array this collapsed row renders at: the index of\n\t * the run's FIRST loaded pass (see the file docstring for why not the last). */\n\tanchorIndex: number;\n\t/** Identity of the turn at `anchorIndex` — its server item id, or its local id\n\t * while it has none, or `''` when it has neither. The views stamp this on the\n\t * row (`data-row-pos`) so the scroll anchor can tell a row that RELOCATED (an\n\t * older page moved the run's start) from one that merely gained a pass. They\n\t * must not re-derive it from `members`: which member the row renders at is\n\t * this module's decision, and the two silently disagreed once already. */\n\tanchorId: string;\n};\n\nexport type DisplayEntry =\n\t| { kind: 'message'; msg: ChatMessage; index: number }\n\t| { kind: 'indexing'; group: IndexingGroup; index: number };\n\nexport type BuildDisplayListOptions = {\n\t/** True while older history remains unpaged, which is what makes a group\n\t * with no first pass genuinely incomplete rather than merely odd. */\n\thasMoreHistory?: boolean;\n};\n\n// The indexing label is view-formatted (formatIndexingLabel), so parsing it is\n// the FALLBACK path only: it exists for bubbles restored from a history cache\n// written before `_indexFile` was stamped. Live and freshly-mapped bubbles carry\n// the structured ref and never reach this.\n//\n// Shapes produced by formatIndexingLabel:\n// \"Indexing: [name](path) · mime · 1.2 MB\"\n// \"Reindexing: name · mime\"\n// \"Indexing (continuing) [name](path)\"\nconst INDEXING_LABEL_RE = /^(Re)?[Ii]ndexing(\\s*\\(continuing\\))?\\s*:?\\s+(.+)$/;\nconst LEADING_MD_LINK_RE = /^\\[([^\\]]+)\\]\\(([^)]+)\\)/;\n\nexport function parseIndexingLabel(\n\tcontent: string,\n): { name: string; path?: string; continued: boolean; isReindex: boolean } | null {\n\tif (typeof content !== 'string' || !content) return null;\n\tvar firstLine = content.split('\\n')[0].trim();\n\tvar m = firstLine.match(INDEXING_LABEL_RE);\n\tif (!m) return null;\n\t// Only the first \" · \" segment is the file; the rest is mime/size trivia.\n\tvar head = m[3].split(' · ')[0].trim();\n\tvar link = head.match(LEADING_MD_LINK_RE);\n\tvar name = link ? link[1].trim() : head;\n\tif (!name) return null;\n\treturn {\n\t\tname: name,\n\t\tpath: link ? link[2].trim() : undefined,\n\t\tcontinued: !!m[2],\n\t\tisReindex: !!m[1],\n\t};\n}\n\n/** The file a background-indexing bubble belongs to, structured ref preferred. */\nfunction readFileRef(msg: ChatMessage): (IndexingFileRef & { continued: boolean }) | null {\n\tvar ref = msg && msg._indexFile;\n\tif (ref && (ref.path || ref.name)) {\n\t\treturn {\n\t\t\tname: ref.name || ref.path || '',\n\t\t\tpath: ref.path,\n\t\t\tmime: ref.mime,\n\t\t\tsize: ref.size,\n\t\t\tisReindex: ref.isReindex,\n\t\t\tcontinued: !!ref.continued,\n\t\t};\n\t}\n\tvar parsed = parseIndexingLabel(msg && msg.content);\n\tif (!parsed) return null;\n\treturn {\n\t\tname: parsed.name,\n\t\tpath: parsed.path,\n\t\tisReindex: parsed.isReindex,\n\t\tcontinued: parsed.continued,\n\t};\n}\n\nfunction isPendingMsg(m: ChatMessage): boolean {\n\treturn !!(m.isPending || m.isPendingInProcess || m.isPendingQueued || m.isSendingToServer);\n}\n\n/**\n * Collapse background-indexing turns into per-file groups.\n *\n * Messages that are not background-indexing pass through untouched, at their\n * original positions and with their original indices.\n */\nexport function buildChatDisplayList(\n\tmessages: ChatMessage[],\n\topts?: BuildDisplayListOptions,\n): DisplayEntry[] {\n\tvar list = Array.isArray(messages) ? messages : [];\n\tvar hasMoreHistory = !!(opts && opts.hasMoreHistory);\n\n\t// One entry per RUN (see IndexingGroup.runKey), addressed by an internal id\n\t// while the list is being walked; runKey is assigned at the end, once the\n\t// number of runs per file is known.\n\tvar groups: { [runId: string]: IndexingGroup } = {};\n\tvar order: string[] = [];\n\tvar runOfIndex: (string | undefined)[] = new Array(list.length);\n\t// A response bubble carries no file metadata of its own; it is tied to its\n\t// request by the server item id, with the immediately preceding request as\n\t// the fallback for locally-pushed bubbles that have no id yet.\n\tvar runByItemId: { [itemId: string]: string } = {};\n\t// Row already opened for a file NAME, so a pass that reports no storage path\n\t// joins it instead of opening a second row for the same file.\n\tvar keyByName: { [name: string]: string } = {};\n\t// The run currently being accumulated for each file, every run of it, and the\n\t// file each run belongs to (a run id is opaque — a file key can contain any\n\t// character, so it must never be parsed back out of one).\n\tvar openRunOfKey: { [key: string]: string } = {};\n\tvar runsOfKey: { [key: string]: string[] } = {};\n\tvar keyOfRun: { [runId: string]: string } = {};\n\tvar runSeq = 0;\n\n\tfor (var i = 0; i < list.length; i++) {\n\t\tvar msg = list[i];\n\t\tif (!msg || !msg.isBackgroundTask) continue;\n\n\t\tvar runId: string | undefined;\n\t\tvar ref = msg.role === 'user' ? readFileRef(msg) : null;\n\t\tif (ref) {\n\t\t\t// Path first — a file can be re-uploaded under a name that already\n\t\t\t// exists elsewhere. But a pass that supplied no path (a compact\n\t\t\t// continuation label recovered from an old history cache) is still the\n\t\t\t// same file as the path-bearing passes above it, so let it join them\n\t\t\t// rather than splitting one file across two collapsed rows.\n\t\t\tvar key = ref.path || keyByName[ref.name] || ref.name;\n\t\t\t// A FIRST pass (\"A new file has just been uploaded\") when this file\n\t\t\t// already has a run open starts a new one: it is a re-index, or a\n\t\t\t// re-upload over the same storage path. Continuations join the run.\n\t\t\tif (!ref.continued && openRunOfKey[key]) delete openRunOfKey[key];\n\t\t\trunId = openRunOfKey[key];\n\t\t\tif (!runId) {\n\t\t\t\trunId = 'run' + (runSeq++);\n\t\t\t\topenRunOfKey[key] = runId;\n\t\t\t\tkeyOfRun[runId] = key;\n\t\t\t\t(runsOfKey[key] || (runsOfKey[key] = [])).push(runId);\n\t\t\t}\n\t\t} else if (msg._serverItemId && runByItemId[msg._serverItemId]) {\n\t\t\trunId = runByItemId[msg._serverItemId];\n\t\t} else if (msg.role !== 'user') {\n\t\t\t// ADJACENT only. Both paths that create a pass emit its request and\n\t\t\t// response bubbles together, so an id-less response belongs to the\n\t\t\t// message right before it. Falling back to the last file seen ANYWHERE\n\t\t\t// above swallowed stray background bubbles — an indexing prompt whose\n\t\t\t// shape we could not parse, a response whose request is not loaded —\n\t\t\t// into whichever file happened to be indexed most recently, however\n\t\t\t// much unrelated conversation sat in between.\n\t\t\trunId = runOfIndex[i - 1];\n\t\t}\n\t\t// A background bubble we cannot attribute to a file (an unrecognised label,\n\t\t// or a response whose request is not loaded) stays an ordinary message\n\t\t// rather than being folded into whichever group happens to be nearest.\n\t\tif (!runId) continue;\n\n\t\tvar g = groups[runId];\n\t\tif (!g) {\n\t\t\tvar fileKey = keyOfRun[runId];\n\t\t\tg = groups[runId] = {\n\t\t\t\tkey: fileKey,\n\t\t\t\trunKey: runId, // provisional; renumbered newest-first below\n\t\t\t\tname: ref ? ref.name : fileKey,\n\t\t\t\tpath: ref ? ref.path : undefined,\n\t\t\t\tmime: ref ? ref.mime : undefined,\n\t\t\t\tsize: ref ? ref.size : undefined,\n\t\t\t\tisReindex: !!(ref && ref.isReindex),\n\t\t\t\tmembers: [],\n\t\t\t\tpassCount: 0,\n\t\t\t\tstatus: 'done',\n\t\t\t\tcancellableIds: [],\n\t\t\t\tcancelling: false,\n\t\t\t\tmayHaveOlder: false,\n\t\t\t\t// The run's first loaded pass, and never re-stamped: see the file\n\t\t\t\t// docstring. `anchorId` is filled in once every member is known.\n\t\t\t\tanchorIndex: i,\n\t\t\t\tanchorId: '',\n\t\t\t};\n\t\t\torder.push(runId);\n\t\t}\n\t\tif (ref) {\n\t\t\t// Later passes carry the compact continuation label with no mime/size,\n\t\t\t// so keep the richest values any pass supplied.\n\t\t\tif (ref.name) g.name = ref.name;\n\t\t\tif (ref.path) g.path = ref.path;\n\t\t\tif (ref.mime) g.mime = ref.mime;\n\t\t\tif (typeof ref.size === 'number') g.size = ref.size;\n\t\t\tif (ref.isReindex) g.isReindex = true;\n\t\t\tif (!ref.continued) g.mayHaveOlder = false;\n\t\t\tg.passCount++;\n\t\t}\n\t\tg.members.push({ msg: msg, index: i });\n\t\trunOfIndex[i] = runId;\n\t\tif (msg._serverItemId) runByItemId[msg._serverItemId] = runId;\n\t\tif (ref && ref.name) keyByName[ref.name] = g.key;\n\t}\n\n\t// Name each run after its FIRST loaded pass. That id survives everything the\n\t// list does around it: passes appended to this run, other runs of the same\n\t// file appearing before OR after it, and an older page prepending. (An\n\t// ordinal would not — numbering from either end renames existing rows as soon\n\t// as a run appears at that end, which silently moves the user's expansion to\n\t// a row they never opened.) The one thing that changes it is the run's own\n\t// true first pass finally paging in, which happens at most once per run.\n\tfor (var rk in runsOfKey) {\n\t\tvar runIds = runsOfKey[rk];\n\t\tfor (var ri = 0; ri < runIds.length; ri++) {\n\t\t\tvar grpR = groups[runIds[ri]];\n\t\t\tif (!grpR) continue;\n\t\t\tvar first = grpR.members[0];\n\t\t\tvar firstId = first && first.msg && (first.msg._serverItemId || first.msg._localId);\n\t\t\t// A run whose passes are all still local (no server id yet) falls back to\n\t\t\t// its position, which is all there is to go on.\n\t\t\tgrpR.runKey = rk + '#' + (firstId || 'n' + ri);\n\t\t}\n\t}\n\n\t// Status + completeness, once every member is known.\n\tfor (var oi = 0; oi < order.length; oi++) {\n\t\tvar grp = groups[order[oi]];\n\t\t// A file's passes run strictly one after another, so a pass still marked\n\t\t// queued/running with a SETTLED pass after it is stale history, not live\n\t\t// work — the server's row for it simply never left \"running\". Ignoring\n\t\t// those matters most for pages reached by scrolling up (or by the viewport\n\t\t// fill), which get no poll attached to resolve them: one stale row would\n\t\t// otherwise flip a long-finished file back to a spinner with a \"Stop\"\n\t\t// button aimed at a dead item id, permanently.\n\t\tvar lastSettled = -1;\n\t\tfor (var si = 0; si < grp.members.length; si++) {\n\t\t\tif (!isPendingMsg(grp.members[si].msg)) lastSettled = si;\n\t\t}\n\t\tvar active = false;\n\t\tfor (var mi = lastSettled + 1; mi < grp.members.length; mi++) {\n\t\t\tif (isPendingMsg(grp.members[mi].msg)) { active = true; break; }\n\t\t}\n\t\t// What a stop button would act on: the REQUEST bubble of every pass that is\n\t\t// still queued or running server-side. The assistant placeholder shares its\n\t\t// pass's server id, so ids are de-duplicated. A pass mid-cancel is left out\n\t\t// (its request is already on its way) but keeps the row in a cancelling\n\t\t// state so the button does not flicker back to \"stop\".\n\t\tfor (var xi = 0; xi < grp.members.length; xi++) {\n\t\t\tif (grp.members[xi].msg._cancelling) { grp.cancelling = true; break; }\n\t\t}\n\t\tvar seenIds: { [id: string]: boolean } = {};\n\t\tfor (var ci = 0; ci < grp.members.length; ci++) {\n\t\t\tvar cm = grp.members[ci].msg;\n\t\t\t// Report a failed Stop only while the stop is still something the user\n\t\t\t// can act on. \"Could not remove from queue\" (the pass had just started)\n\t\t\t// stays on that bubble, so reporting it from ANY member meant a row that\n\t\t\t// went on to finish normally kept describing a one-off transient failure\n\t\t\t// as a permanent property of the file, until a full history refresh\n\t\t\t// rebuilt the bubbles.\n\t\t\tif (cm._cancelError && (active || grp.cancelling)) grp.cancelError = cm._cancelError;\n\t\t\tif (cm.role !== 'user' || !cm._serverItemId || cm._cancelling || cm.isSendingToServer) continue;\n\t\t\tif (!(cm.isPendingQueued || cm.isPendingInProcess)) continue;\n\t\t\t// Same staleness rule: never offer to stop a pass a later one outlived.\n\t\t\tif (ci < lastSettled) continue;\n\t\t\tif (seenIds[cm._serverItemId]) continue;\n\t\t\tseenIds[cm._serverItemId] = true;\n\t\t\tgrp.cancellableIds.push(cm._serverItemId);\n\t\t}\n\t\tif (active) {\n\t\t\tgrp.status = 'active';\n\t\t} else {\n\t\t\t// The newest loaded outcome is the file's state: an early pass may have\n\t\t\t// errored and a later one succeeded.\n\t\t\tvar last = grp.members[grp.members.length - 1].msg;\n\t\t\tgrp.status = last.isError ? 'error' : last.isCancelled ? 'cancelled' : 'done';\n\t\t}\n\t\t// A group whose passes are ALL continuations began before the loaded\n\t\t// window; its earlier passes arrive when older history is paged in.\n\t\tvar sawFirstPass = false;\n\t\tfor (var pi = 0; pi < grp.members.length; pi++) {\n\t\t\tvar pm = grp.members[pi].msg;\n\t\t\tif (pm.role !== 'user') continue;\n\t\t\tvar pref = readFileRef(pm);\n\t\t\tif (pref && !pref.continued) { sawFirstPass = true; break; }\n\t\t}\n\t\tgrp.mayHaveOlder = !sawFirstPass && hasMoreHistory;\n\t\t// Where the row renders, and WHICH turn that is. Derived from the same\n\t\t// member so the two can never drift apart; a group always has a member\n\t\t// (it is created by the first one).\n\t\tvar anchor = grp.members[0];\n\t\tgrp.anchorIndex = anchor.index;\n\t\tgrp.anchorId = anchor.msg._serverItemId || anchor.msg._localId || '';\n\t}\n\n\tvar out: DisplayEntry[] = [];\n\tfor (var j = 0; j < list.length; j++) {\n\t\tvar r = runOfIndex[j];\n\t\tif (r === undefined) {\n\t\t\tout.push({ kind: 'message', msg: list[j], index: j });\n\t\t\tcontinue;\n\t\t}\n\t\t// Every other member of the run is represented by the row at the anchor.\n\t\tif (groups[r].anchorIndex === j) out.push({ kind: 'indexing', group: groups[r], index: j });\n\t}\n\treturn out;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/engine/attachment_parsers.ts","../src/engine/config.ts","../src/engine/office.ts","../src/engine/attachments.ts","../src/engine/prompts/chat_system_prompt.ts","../src/engine/prompts/indexing_system_prompt.ts","../src/engine/prompts/indexing_user_message.ts","../src/engine/errors.ts","../src/engine/links.ts","../src/engine/budget.ts","../src/engine/download_encoding.ts","../src/engine/time.ts","../src/engine/ai_agent.ts","../src/engine/requests.ts","../src/engine/history.ts","../src/engine/viewport_fill.ts","../src/engine/session.ts","../src/engine/indexing_groups.ts"],"names":["remotePath","i","resolvedModel"],"mappings":"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","file":"engine.mjs","sourcesContent":["/**\n * Client-side attachment-parser plugins.\n *\n * Some attachment formats can't be read by the model's web_fetch (binary) and\n * have no server-side extractor either — e.g. legacy Hancom .hwp. A parser\n * plugin runs IN THE BROWSER, turns the uploaded File into indexable text (or an\n * HTML string), and the engine sends that content INLINE in the background\n * indexing request — so the model indexes the parsed content directly, with no\n * upload-side server extraction and no web_fetch for that file.\n *\n * Register a parser with `registerAttachmentParser()`, or via\n * `configureChatEngine({ attachmentParsers: [...] })`. The BunnyQuery widget also\n * exposes `BunnyQuery.registerAttachmentParser()` and an `attachmentParsers`\n * init option. First matching parser wins.\n */\n\nexport interface AttachmentParser {\n\t/** Human-readable label — used only in logs. */\n\tname?: string;\n\t/**\n\t * Return true if this parser handles the file. Receives the file name and\n\t * (when known) its MIME type. Keep it cheap — it runs for every upload.\n\t */\n\tmatch: (file: { name: string; mime?: string }) => boolean;\n\t/**\n\t * Parse the File into indexable plain text OR an HTML string (the model reads\n\t * either). Runs in the browser; may be async. Return a falsy/empty value to\n\t * skip (the file then falls back to web_fetch / server extraction).\n\t */\n\tparse: (\n\t\tfile: File,\n\t) => string | null | undefined | Promise<string | null | undefined>;\n}\n\n// Hard ceiling on inlined parsed content (characters), mirroring the worker's\n// server-side MAX_EXTRACTED_CHARS, so a huge document can't blow the model's\n// context window or the request size.\nexport const MAX_PARSED_CONTENT_CHARS = 200_000;\n\nconst _parsers: AttachmentParser[] = [];\n\n/** Register an attachment parser. Ignores duplicates (by reference) and invalid plugins. */\nexport function registerAttachmentParser(parser: AttachmentParser): void {\n\tif (\n\t\tparser &&\n\t\ttypeof parser.match === 'function' &&\n\t\ttypeof parser.parse === 'function' &&\n\t\t_parsers.indexOf(parser) === -1\n\t) {\n\t\t_parsers.push(parser);\n\t}\n}\n\n/** Remove all registered parsers (mainly for tests / re-init). */\nexport function clearAttachmentParsers(): void {\n\t_parsers.length = 0;\n}\n\n/** Snapshot of the registered parsers. */\nexport function getAttachmentParsers(): AttachmentParser[] {\n\treturn _parsers.slice();\n}\n\n/** First parser whose `match` returns true for the given file, if any. */\nexport function findAttachmentParser(\n\tname: string,\n\tmime?: string,\n): AttachmentParser | undefined {\n\tfor (let i = 0; i < _parsers.length; i++) {\n\t\ttry {\n\t\t\tif (_parsers[i].match({ name: name, mime: mime })) return _parsers[i];\n\t\t} catch {\n\t\t\t/* a throwing matcher must not break uploads */\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Run the matching parser (if any) and return capped, trimmed content — or null\n * when there is no parser, the parser throws, or it yields nothing. Never throws:\n * a parser failure degrades to null so the upload still completes (the file then\n * resolves via its normal path).\n */\nexport async function parseAttachmentContent(\n\tfile: File,\n\tname: string,\n\tmime?: string,\n): Promise<string | null> {\n\tconst parser = findAttachmentParser(name, mime);\n\tif (!parser) return null;\n\n\tlet raw: string | null | undefined;\n\ttry {\n\t\traw = await parser.parse(file);\n\t} catch (err) {\n\t\tconsole.error(\n\t\t\t`[chat-engine] attachment parser ${parser.name || '(unnamed)'} failed for ${name}:`,\n\t\t\terr,\n\t\t);\n\t\treturn null;\n\t}\n\n\tlet text = (raw == null ? '' : String(raw)).trim();\n\tif (!text) return null;\n\tif (text.length > MAX_PARSED_CONTENT_CHARS) {\n\t\ttext =\n\t\t\ttext.slice(0, MAX_PARSED_CONTENT_CHARS) +\n\t\t\t`\\n...[truncated for length; original ${text.length} characters]`;\n\t}\n\treturn text;\n}\n","/**\n * Engine configuration / dependency injection.\n *\n * The engine is framework- and transport-agnostic: it never imports a skapi\n * instance or `import.meta.env`. Each consumer calls `configureChatEngine()`\n * once at startup to inject the skapi transport functions, the MCP base URL,\n * and (optionally) the `poll` value to attach to clientSecretRequest.\n *\n * Why `poll` is configurable: agent.vue uses the npm-bundled skapi-js and OMITS\n * `poll` (its clientSecretRequest auto-resolves with the final body), whereas\n * the BunnyQuery widget uses the deployed skapi-js@latest and must pass\n * `poll: 0` to get the early ack + a manual `.poll()` handle (needed for queued-\n * send cancel). So the request builders include `poll` only when it is set.\n */\n\nimport { type AttachmentParser, registerAttachmentParser } from './attachment_parsers';\n\nexport interface ChatEngineConfig {\n /** skapi.clientSecretRequest, bound to the consumer's skapi instance. */\n clientSecretRequest: (opts: any) => Promise<any>;\n /** skapi.clientSecretRequestHistory, bound to the consumer's skapi instance. */\n clientSecretRequestHistory: (params: any, fetchOptions: any) => Promise<any>;\n /** MCP server base URL (prod vs dev resolved by the consumer). */\n mcpBaseUrl: string;\n /**\n * Value to attach as `poll` on every clientSecretRequest. When `undefined`\n * the `poll` key is omitted entirely (agent.vue). BunnyQuery sets `0`.\n */\n poll?: number;\n /**\n * Optional client-side attachment parsers (e.g. an .hwp parser). Each is\n * registered at configure time; more can be added later via\n * `registerAttachmentParser()`. See attachment_parsers.ts.\n */\n attachmentParsers?: AttachmentParser[];\n /**\n * Opt in to SERVER-DRIVEN windowed indexing for text/grid files.\n *\n * Off by default, and deliberately so. When on, the client emits a\n * `_skapi_window` directive and the WORKER reads the file one window at a time,\n * continuing until the reader says it is exhausted. When off, the agent pages the\n * file itself with readFileContent, exactly as before.\n *\n * The flag exists because the backend must ship FIRST: a client emitting the\n * directive against a worker that does not strip it leaves an unknown field in the\n * request body, and the provider rejects the whole call with no retry. Keep it off\n * until the worker is deployed, then flip it per environment.\n */\n windowedIndexing?: boolean;\n}\n\nlet _config: ChatEngineConfig | null = null;\n\nexport function configureChatEngine(config: ChatEngineConfig): void {\n _config = config;\n if (config.attachmentParsers) {\n for (const parser of config.attachmentParsers) registerAttachmentParser(parser);\n }\n}\n\nexport function chatEngineConfig(): ChatEngineConfig {\n if (!_config) {\n throw new Error(\n '[chat-engine] configureChatEngine() must be called before using the engine.',\n );\n }\n return _config;\n}\n\n/** True when the consumer has opted in to server-driven windowed indexing. */\nexport function windowedIndexingEnabled(): boolean {\n return _config?.windowedIndexing === true;\n}\n\n/** Spread helper: `{ ...pollOpt() }` adds `poll` only when configured. */\nexport function pollOpt(): { poll?: number } {\n const p = _config?.poll;\n return p === undefined ? {} : { poll: p };\n}\n","/**\n * Office-file server-side extraction helpers.\n *\n * Office documents (Microsoft .docx/.xlsx/.pptx, Hancom .hwpx, etc.) can't be\n * read by web_fetch (binary/zip). The proxy worker downloads them from db\n * storage, extracts their text server-side, and substitutes that text for a\n * placeholder token in the request body (carried under the reserved\n * `_skapi_extract` key, which the producer strips before the upstream call).\n */\n\n// A directive telling the proxy worker which office file to download + extract\n// and which placeholder token in the request body to substitute.\nexport type ExtractDirective = {\n\t/** db storage path of the file, e.g. \"folder/report.docx\" (also the src:: value). */\n\tpath: string;\n\t/** The exact token in the request body to replace with the extracted text. */\n\tplaceholder: string;\n\t/** Original filename — informational (server logs only). */\n\tname?: string;\n\t/** MIME type — informational (server logs only). */\n\tmime?: string;\n};\n\n// A directive telling the proxy worker to re-mint a fresh, short-lived URL for a\n// file the model fetches by url (PDFs, images — anything NOT server-extractable)\n// right before the upstream call, so a queued request never hands the model a\n// stale link. The worker mints from `path` and swaps `url` (the exact baked url\n// string) everywhere it appears in the request body.\nexport type FileUrlDirective = {\n\t/** db storage path of the file, e.g. \"folder/report.pdf\" (also the src:: value). */\n\tpath: string;\n\t/** The exact baked url string in the request body to replace with a fresh one. */\n\turl: string;\n};\n\n// Files whose text the worker extracts SERVER-SIDE and inlines for indexing,\n// instead of handing the agent a URL to fetch. Two groups:\n// (1) BINARY document formats the model can't read at all (OOXML, Hancom\n// HWP/HWPX, OpenDocument, EPUB) — the worker parses them.\n// (2) TEXT/data/markup/code formats. These ARE readable via web_fetch, BUT\n// some providers (OpenAI's Responses API) have no working file-fetch tool,\n// so the agent can't retrieve the URL at all. Extracting them server-side\n// (the worker just decodes the bytes) makes indexing provider-independent.\nconst OFFICE_FILE_EXTENSIONS = new Set([\n\t'doc', 'docx', 'docm',\n\t'xls', 'xlsx', 'xlsm',\n\t'ppt', 'pptx', 'pptm',\n\t'hwp', 'hwpx',\n\t'ods', 'odt', 'odp',\n\t'epub',\n]);\n\nconst TEXT_FILE_EXTENSIONS = new Set([\n\t'csv', 'tsv', 'tab', 'txt', 'text', 'log', 'md', 'markdown', 'rst',\n\t'json', 'ndjson', 'jsonl', 'geojson', 'xml', 'yaml', 'yml', 'toml',\n\t'ini', 'conf', 'cfg', 'properties', 'env', 'rtf', 'html', 'htm',\n\t'js', 'mjs', 'cjs', 'ts', 'tsx', 'jsx', 'py', 'rb', 'go', 'rs', 'java',\n\t'kt', 'c', 'h', 'cpp', 'cc', 'hpp', 'cs', 'php', 'swift', 'sh', 'bash',\n\t'zsh', 'sql', 'css', 'scss', 'less', 'vue', 'svelte', 'tex', 'srt', 'vtt',\n]);\n\n// MIME types that indicate decodable text even when the extension is unknown\n// (the worker has the same fallback, so any text/* file is extracted server-side).\nfunction isTextMime(m: string): boolean {\n\treturn (\n\t\tm.startsWith('text/') ||\n\t\tm.endsWith('+json') || m.endsWith('+xml') || m.endsWith('+yaml') ||\n\t\tm === 'application/json' || m === 'application/ld+json' ||\n\t\tm === 'application/xml' || m === 'application/yaml' || m === 'application/x-yaml' ||\n\t\tm === 'application/javascript' || m === 'application/x-javascript' ||\n\t\tm === 'application/x-sh' || m === 'application/x-ndjson' ||\n\t\tm === 'application/csv' || m === 'application/rtf' ||\n\t\tm === 'application/sql' || m === 'application/toml'\n\t);\n}\n\n/**\n * True when a file should be EXTRACTED SERVER-SIDE (text inlined for indexing)\n * rather than handed to the agent as a URL to fetch — i.e. binary office\n * documents AND all text/data/code files. Detection is extension-first (so a\n * .csv reported as an Office MIME is still treated as text), with a text-MIME\n * fallback for unlisted extensions.\n */\nexport function isServerExtractable(name?: string, mime?: string): boolean {\n\tconst ext = (name || '').split('.').pop()?.toLowerCase() || '';\n\tif (OFFICE_FILE_EXTENSIONS.has(ext)) return true;\n\tif (TEXT_FILE_EXTENSIONS.has(ext)) return true;\n\tconst m = (mime || '').toLowerCase();\n\tif (isTextMime(m)) return true;\n\treturn (\n\t\tm.includes('officedocument') ||\n\t\tm.includes('opendocument') ||\n\t\tm.includes('hwp') ||\n\t\tm.includes('epub') ||\n\t\tm === 'application/msword' ||\n\t\tm === 'application/vnd.ms-excel' ||\n\t\tm === 'application/vnd.ms-powerpoint'\n\t);\n}\n\n/** @deprecated renamed to {@link isServerExtractable} (now also covers text files). */\nexport const isOfficeFile = isServerExtractable;\n\n// Extensions read WINDOW-BY-WINDOW via the readFileContent tool instead of inlined once.\n//\n// Anything NOT in this set falls back to one-shot server extraction, which is capped at\n// MAX_EXTRACTED_CHARS (200k). Measured against real files, that cap was discarding the\n// overwhelming majority of every large non-spreadsheet upload:\n// 5MB .txt -> 4.0% indexed (4.8M characters silently dropped)\n// 4.8MB .json-> 4.2%\n// 1.9M-char Korean .txt -> 10.5%\n// .docx -> 70.6%\n// The truncation was invisible: the agent received a plausible-looking document and had\n// no way to know most of it was missing. Windowing these types is what makes \"index the\n// whole file\" true rather than aspirational.\n//\n// CSV/TSV specifically must be here rather than in the inline path: the layer now gives\n// them ROW-bounded windows with absolute row numbers, where the character windower used\n// to split rows across boundaries and emit no row numbers at all.\nconst PAGED_READ_EXTENSIONS = new Set([\n\t// grids\n\t'xls', 'xlsx', 'xlsm', 'ods',\n\t// delimited text (row-windowed by the layer)\n\t'csv', 'tsv', 'tab',\n\t// documents\n\t'pdf', 'docx', 'pptx',\n\t// plain text / data / markup\n\t'txt', 'md', 'markdown', 'log', 'json', 'jsonl', 'ndjson', 'xml', 'yaml', 'yml',\n]);\n\n/**\n * True when a file should be indexed by PAGING through readFileContent (spreadsheets and\n * PDFs), rather than inline extraction or a web_fetch URL. This is what lets a huge sheet\n * be read row-window by row-window and a scanned PDF be read page-image by page-image,\n * with embedded photos delivered to the vision model.\n */\nexport function isPagedReadFile(name?: string, mime?: string): boolean {\n\tconst ext = (name || '').split('.').pop()?.toLowerCase() || '';\n\tif (PAGED_READ_EXTENSIONS.has(ext)) return true;\n\tconst m = (mime || '').toLowerCase();\n\treturn (\n\t\tm === 'application/pdf' ||\n\t\tm === 'application/vnd.ms-excel' ||\n\t\tm.includes('spreadsheetml') ||\n\t\tm.includes('opendocument.spreadsheet')\n\t);\n}\n\n/**\n * True for files whose content is VISUAL and must be delivered to the model as IMAGE\n * BLOCKS in the message (rendered pages), because tool-result images render on neither\n * provider. The worker renders a page window to image URLs and injects them (`_skapi_render`\n * directive). Currently PDFs (scanned or not); indexed page-window by page-window with\n * resume advancing the window.\n */\nexport function isImageVisionFile(name?: string, mime?: string): boolean {\n\tconst ext = (name || '').split('.').pop()?.toLowerCase() || '';\n\treturn ext === 'pdf' || (mime || '').toLowerCase() === 'application/pdf';\n}\n\n// Monotonic counter so placeholders are unique even for same-named files in one\n// request. Token shape must match the worker's _EXTRACT_PLACEHOLDER_RE:\n// {{SKAPI_FILE_CONTENT::<id>}}.\nlet _extractPlaceholderSeq = 0;\nexport function makeExtractPlaceholder(seed: string): string {\n\t_extractPlaceholderSeq += 1;\n\tconst slug = (seed || 'file').replace(/[^a-zA-Z0-9]+/g, '_').slice(-48);\n\treturn `{{SKAPI_FILE_CONTENT::${slug}-${_extractPlaceholderSeq}}}`;\n}\n\n// Placeholder marking WHERE the worker injects a window of rendered page/photo IMAGE blocks\n// (the `_skapi_render` directive). Distinct token from the text-extraction placeholder.\nlet _renderPlaceholderSeq = 0;\nexport function makeRenderPlaceholder(seed: string): string {\n\t_renderPlaceholderSeq += 1;\n\tconst slug = (seed || 'file').replace(/[^a-zA-Z0-9]+/g, '_').slice(-48);\n\treturn `{{SKAPI_RENDER::${slug}-${_renderPlaceholderSeq}}}`;\n}\n\n// Page/photo images per render window. Must match the server default so the client's\n// resume window (from = pass * PAGES) lines up with what the worker renders.\nexport const RENDER_PAGES_PER_WINDOW = 5;\n\n// Token the WORKER substitutes with a human description of the next window's position.\n// Shared with the render loop so one substitution path serves both.\nexport const WINDOW_CURSOR_TOKEN = '{{RENDER_FROM}}';\n\nlet _windowPlaceholderSeq = 0;\n\n/**\n * Placeholder the worker replaces with ONE window of a file's text/grid content.\n * Distinct token from the render (page-image) and extract (whole-file) placeholders so\n * a stale token from either can never be mistaken for this one.\n */\nexport function makeWindowPlaceholder(seed: string): string {\n\t_windowPlaceholderSeq += 1;\n\tconst slug = (seed || 'file').replace(/[^a-zA-Z0-9]+/g, '_').slice(-48);\n\treturn `{{SKAPI_WINDOW::${slug}-${_windowPlaceholderSeq}}}`;\n}\n\n/**\n * True when a file should be read server-side, one window at a time, by the worker.\n * PDFs are excluded: they go through the VISION path, where pages are rendered to\n * images because their text layer is often absent or unreliable.\n */\nexport function isWindowedReadFile(name?: string, mime?: string): boolean {\n\tif (isImageVisionFile(name, mime)) return false;\n\treturn isPagedReadFile(name, mime);\n}\n\nexport interface ComposedUserMessage {\n\t/** Clean display/history copy (attachment links, NO extraction placeholders). */\n\tcomposed: string;\n\t/** LLM-bound copy — `composed` plus inline office-extraction placeholders. */\n\tcomposedForLlm: string;\n\t/** Office-extraction directives for the proxy worker (undefined if no office files). */\n\textractContent?: ExtractDirective[];\n\t/** JIT url re-mint directives for the worker (non-extractable files: PDFs, images). */\n\tfileUrls?: FileUrlDirective[];\n}\n\n// Compose the user's chat message from the typed text + uploaded attachment URLs.\n// Identical for every consumer (agent.vue + the BunnyQuery widget): appends a\n// markdown \"Attached files\" link block, and for office files\n// (.docx/.xlsx/.pptx/.hwpx) adds inline extraction placeholders to the LLM copy\n// ONLY (the proxy worker substitutes their text server-side; the display/history\n// copy stays clean so stale tokens never accumulate across replayed turns).\n// The directive `path` is the db storage path (uid-prefixed where applicable),\n// NOT the link label — it falls back to the label when no storagePath is given\n// (agent.vue uploads FLAT, so storagePath === name there).\nexport function composeUserMessage(\n\ttext: string,\n\tattachmentUrls: Array<{ name: string; url: string; storagePath?: string }>,\n): ComposedUserMessage {\n\tlet composed = text;\n\tif (attachmentUrls.length > 0) {\n\t\tconst lines = attachmentUrls.map((u) => `- [${u.name}](${u.url})`);\n\t\tcomposed = `${text}\\n\\nAttached files:\\n${lines.join('\\n')}`;\n\t}\n\tlet composedForLlm = composed;\n\tlet extractContent: ExtractDirective[] | undefined;\n\tlet fileUrls: FileUrlDirective[] | undefined;\n\tif (attachmentUrls.length > 0) {\n\t\tconst extractFiles = attachmentUrls.filter((u) => isServerExtractable(u.name));\n\t\tif (extractFiles.length > 0) {\n\t\t\tconst directives: ExtractDirective[] = [];\n\t\t\tconst sections = extractFiles.map((u) => {\n\t\t\t\tconst storagePath = u.storagePath || u.name;\n\t\t\t\tconst placeholder = makeExtractPlaceholder(storagePath);\n\t\t\t\tdirectives.push({ path: storagePath, placeholder, name: u.name });\n\t\t\t\treturn `===== ${u.name} =====\\n----- BEGIN FILE CONTENT -----\\n${placeholder}\\n----- END FILE CONTENT -----`;\n\t\t\t});\n\t\t\textractContent = directives;\n\t\t\tcomposedForLlm =\n\t\t\t\t`${composed}\\n\\nExtracted content of attached office files ` +\n\t\t\t\t`(read inline below; do NOT fetch their URLs):\\n\\n` +\n\t\t\t\tsections.join('\\n\\n');\n\t\t}\n\t\t// Files the model fetches by url (NOT server-extractable: PDFs, images) get\n\t\t// a re-mint directive so the worker swaps the baked long-lived CDN url for a\n\t\t// fresh short-lived one at send time. Extractable files are inlined as text,\n\t\t// so their url is never fetched — no directive needed. A blank url (nothing\n\t\t// to match/replace) is skipped.\n\t\tconst urlFiles = attachmentUrls.filter((u) => u.url && !isServerExtractable(u.name));\n\t\tif (urlFiles.length > 0) {\n\t\t\tfileUrls = urlFiles.map((u) => ({ path: u.storagePath || u.name, url: u.url }));\n\t\t}\n\t}\n\treturn { composed, composedForLlm, extractContent, fileUrls };\n}\n","/**\n * Attachment helpers shared by every consumer's view layer.\n *\n * The upload ORCHESTRATION is per-consumer (agent.vue does admin storage\n * accounting; the widget uses get-signed-url), but the failure-reporting shape\n * is identical, so it lives here. When an upload or its indexing request fails,\n * the orchestrator records the original `error.code` / `error.message` on the\n * attachment (`att.errorCode` / `att.errorDetail`); this groups those failed\n * attachments by (code, description) so a single report dialog can list each\n * distinct error once with all the files it affected.\n */\n\nexport interface AttachmentFailureGroup {\n\t/** The failing `error.code` (empty string when the error carried none). */\n\tcode: string;\n\t/** The failing `error.message` / human description. */\n\tmessage: string;\n\t/** Display names of the attachments that hit this exact (code, message). */\n\tfiles: string[];\n}\n\n// Group failed attachments by (code, message). A status of 'error' means the\n// upload itself failed; 'indexError' means the file uploaded but its indexing\n// request failed — both are surfaced. Order of first appearance is preserved.\nexport function groupAttachmentFailures(attachments: any[]): AttachmentFailureGroup[] {\n\tconst groups: Record<string, AttachmentFailureGroup> = {};\n\tconst order: string[] = [];\n\t(attachments || []).forEach(function (att: any) {\n\t\tif (!att || (att.status !== 'error' && att.status !== 'indexError')) return;\n\t\tconst code = String(att.errorCode || '');\n\t\tconst message = String(\n\t\t\tatt.errorDetail ||\n\t\t\tatt.errorMessage ||\n\t\t\t(att.status === 'indexError' ? 'File indexing failed' : 'File upload has failed'),\n\t\t);\n\t\tconst key = code + '\u0000' + message;\n\t\tif (!groups[key]) {\n\t\t\tgroups[key] = { code: code, message: message, files: [] };\n\t\t\torder.push(key);\n\t\t}\n\t\tgroups[key].files.push(String(att.name || '(unnamed file)'));\n\t});\n\treturn order.map(function (k) { return groups[k]; });\n}\n","/**\n * BASE PROMPT — Chat assistant\n * ============================================================================\n * System prompt sent on every chat turn. Rebuilt fresh on every send because\n * the project name/description can change at any time.\n *\n * The `${...}` placeholders are filled from the live project (service):\n * formattedServiceId -> the project ID the assistant is scoped to\n * serviceName -> project display name (only added if a description exists)\n * serviceDescription -> project description (only added if present)\n */\n\nexport type ChatSystemPromptParams = {\n\t/** The project/service ID this assistant is scoped to (formatted form). */\n\tformattedServiceId: string;\n\t/** Project display name. Only appended when a description is also present. */\n\tserviceName?: string;\n\t/** Project description. When present, name + description are appended. */\n\tserviceDescription?: string;\n};\n\nexport function buildChatSystemPrompt(params: ChatSystemPromptParams): string {\n\tconst { formattedServiceId, serviceName, serviceDescription } = params;\n\n\tlet systemPrompt = `\nYou are a dedicated assistant for the project ID: \"${formattedServiceId}\".\nScope: Only answer questions about this project and its data. Do not answer questions about other projects or topics unrelated to this project. When the user refers to \"my database\", \"my data\", or \"my files\", treat those as references to this project's database and file storage.\nKnowledge lookup: Before saying you don't know or that something isn't in the chat history, ALWAYS query this project's database through the available MCP tools to look for the answer. The user's data is the source of truth - the chat transcript is not. Only respond with \"I don't know\" or \"I couldn't find that\" after you have actually searched the project's data and come back empty.\nComplete answers over stored data: The database holds one record per spreadsheet row, and each uploaded file becomes many records that usually share a table. So a question about the data almost always spans many records across several files. For any request that counts, sums, totals, lists every match, compares across records, finds which one, or asks whether something is present or ABSENT (for example \"how many\", \"total spent\", \"which card\", \"is there any\", \"없어?\", \"하나도 없나?\"), you MUST read the COMPLETE matching set before answering. Query with fetch_all set to true, or page through getToolResponsePage until pagination.complete is true, across EVERY relevant table and EVERY relevant file. A single default query returns only the first page (about 50 records). That is a SAMPLE. Never treat it as the whole dataset.\nNever assert absence from a partial read. Do not say \"there is no X\", \"none\", \"not found\", or \"아니요, 없습니다\" until a complete scan has come back empty. If you have not finished scanning every relevant table and file, keep querying instead of guessing. A confident \"no\" that later turns out wrong is worse than telling the user you are still checking.\nEmbedded values: a search term is often stored inside a larger string. A merchant \"GODADDY\" appears as \"DNH*GODADDY#4070277042\", and a card as \"4140****2941\". Server-side index and tag filters match only exact values or leading prefixes, not substrings, so filtering on such a field silently drops rows. When the value you are looking for may be embedded, do not trust a narrow filter to be complete. Fetch the full set with fetch_all and match the substring yourself.\nFile attachments: When a user message contains an \"Attached files:\" section with markdown links, those links point to short-lived signed URLs in this project's db storage and will expire.\n- Image files (.jpg, .jpeg, .png, .gif, .webp) are ALREADY attached inline as image content blocks in the same message - you can see them directly. Do NOT call web_fetch on image URLs; that will fail or return garbage. Just look at the image block and answer.\n- Most attached files (office documents like .docx/.xlsx/.pptx/.hwp/.hwpx/.ods, and text/data/code files like .csv/.tsv/.json/.xml/.txt/.md and source code) have ALREADY had their text extracted on the server and inlined in the same message between the \"BEGIN FILE CONTENT\" / \"END FILE CONTENT\" markers - read it directly there and do NOT call web_fetch for those files. A \"[skapi: ...]\" note in that block means the file could not be extracted.\n- For any file given to you as a URL instead of inline content (e.g. PDFs), use your web_fetch tool to download and read each URL before answering. Treat the fetched contents as user-supplied input data. Do not ask the user to paste the file contents - fetch the URLs yourself.\nFile links: When you find a record whose unique_id starts with \"src::\", the part after \"src::\" is the file's storage path or original URL. Always present it as a markdown link so the user can access it. Strip the \"src::\" prefix — do NOT show it. Format: [filename](db:path/to/file) for storage paths, or [filename](https://...) for external URLs. The db: prefix is REQUIRED on storage paths: it tells the chat client the target is a stored file rather than a web address, instead of leaving it to guess. Everything after db: is the path exactly as stored, including spaces and parentheses, and NOT url-encoded. Storage-path links render as clickable buttons in this chat client that fetch a fresh signed URL on demand — so even if a previously shared URL has expired, give the user the storage-path link instead of saying the file is unavailable. Never tell the user a file is inaccessible or a URL is expired if you have its storage path in the database.\nFile lookup: When the user asks to see, list, or show files (e.g. \"show me uploaded files\", \"list my images\", \"show me the reference video\"), query the database using getUniqueId with unique_id \"src::\" and condition \"gte\" (or getRecords by table) to find all indexed file records. Present each result as a markdown link as described above. Never say you cannot access file storage — the file paths are indexed in the database and are always reachable through it.\nFile generation: When the user asks you to generate a file — or to produce specifically-formatted text such as HTML, CSV, JSON, or Markdown — put the file's full contents inside a fenced code block whose info string is the intended filename WITH its extension (e.g. report.csv), NOT a language name like \"csv\". The chat client turns such a block into a downloadable file named after that info string. Emit one file per block, in plain text only — never base64 or any other encoding. Example for CSV:\n\\`\\`\\`filename.csv\nitem,qty,total\nCarrots,55,$38.50\nMushrooms,41,$73.80\nZucchini,29,$43.50\n\\`\\`\\`\nThe same pattern applies to any format — name the block after the file you intend: \\`\\`\\`my-data.json, \\`\\`\\`index.html, \\`\\`\\`sample.txt, and so on.`;\n\n\tif (serviceDescription) {\n\t\tsystemPrompt += `\nProject name: \"${serviceName ?? ''}\"\nProject description: \"\"\"${serviceDescription}\"\"\"`;\n\t}\n\n\treturn systemPrompt;\n}\n","/**\n * BASE PROMPT — Background file-indexing agent (system prompt)\n * ============================================================================\n * System prompt for the BACKGROUND indexing agent (notifyAgentSaveAttachment).\n * Its only job is to read the freshly uploaded file and persist what it learns\n * into the project's knowledge base via the MCP tools. Pairs with the\n * user-message template in ./indexing_user_message.ts.\n */\n\nexport type IndexingSystemPromptParams = {\n\t/** The project/service ID being indexed into. */\n\tservice: string;\n\t/** Project display name. Only appended when a description is also present. */\n\tserviceName?: string;\n\t/** Project description. When present, name + description are appended. */\n\tserviceDescription?: string;\n};\n\nexport function buildIndexingSystemPrompt(params: IndexingSystemPromptParams): string {\n\tconst { service, serviceName, serviceDescription } = params;\n\n\tlet systemPrompt =\n`You are a background indexing agent for project ${service}.\n- Image files (.jpg, .jpeg, .png, .gif, .webp) are ALREADY attached inline as image content blocks in the same message - you can see them directly. Do NOT call web_fetch on image URLs; that will fail or return garbage. Just look at the image block and answer.\n- Most files (office documents like .docx/.xlsx/.pptx/.hwp/.hwpx/.ods, and text/data/code files like .csv/.tsv/.json/.xml/.txt/.md and source code) have ALREADY been extracted on the server and included inline in the user message between the \"BEGIN FILE CONTENT\" / \"END FILE CONTENT\" markers - read that directly. If the inline content is a \"[skapi: ...]\" note, the file could not be extracted - index it from its metadata only.\n- BIG SPREADSHEETS / TEXT: the inline content may be only the FIRST part of a large file (it can end with a truncation or \"more remains\" note). For big spreadsheets and big text/data files READ THE FILE WITH THE readFileContent TOOL: it returns the file ONE WINDOW at a time (spreadsheets as coordinate-tagged grid rows, text as a range of characters). Pass the file's storage path. After each window: datafy it into records and SAVE them, THEN if the window says MORE REMAINS call readFileContent again with the cursor it gives you. Repeat until it says END OF FILE, so the WHOLE file is indexed - never stop after the first window. (Do NOT call readFileContent on a PDF - see the next line.)\n- PDFs (scanned or not): you do NOT read a PDF with a tool or a URL. Its pages are RENDERED and embedded directly in the user message as IMAGE blocks, a WINDOW of pages at a time. LOOK at the embedded page images and datafy every one. The note beside them tells you whether MORE pages remain: if so, save this window's records and stop (a follow-up pass shows the next window automatically); only when the note says it was the LAST window is the PDF fully seen. Do NOT call readFileContent or web_fetch for a PDF.\n- VISION: when the message (a readFileContent window, an embedded PDF page, or an inline attachment) includes IMAGES - scanned/rendered PDF pages, or photos embedded in a spreadsheet next to a row/block - LOOK at them and capture what they show as record data (the reading/values in a scanned table, the part/defect/condition visible in a photo). The image IS part of the data; correlate each photo with its labelled block (\"PHOTO A3\" markers tie a photo to that grid row).\n- Whatever the file type, use the file's storage path (the \"storage path\" metadata line) as the \"src::\" unique_id - never the inline content or a temporary URL.\n- TABULAR data (any spreadsheet - .csv/.tsv/.xlsx/.xls/.ods, or sheet-like rows): you MUST save EVERY data row as its own record (ONE record per row) with that row's actual column values in the record's \"data\", keyed by the header names, in a dedicated table (e.g. \"spreadsheet_rows\"). Do NOT summarize, sample only a few rows, or save just file metadata - index the whole sheet, paging through it with readFileContent when it is large. Make MULTIPLE postRecords calls in batches (e.g. 30-50 rows per call) rather than one oversized call. This per-row completeness OVERRIDES brevity. ALSO save one file-level summary record (file name, sheet name(s), column headers, total row count, overall summary) - this is the record that carries the file's \"src::\" unique_id - and link EVERY per-row record to it via reference (set each row record's reference to that src:: file record; the row records themselves do NOT carry a src:: unique_id). The per-row records AND this reference linkage are BOTH mandatory: the linkage is what lets the whole sheet be found and cleaned up together when the file is re-indexed.\n- EPUB / e-books / long-form books (.epub or any book-length prose, provided inline in reading order with chapter headings preserved): you MUST save ONE record per CHAPTER (or, when chapters are unclear, per major section/topic) in a dedicated table (e.g. \"book_chapters\") - never collapse the whole book into a single record. Each chapter record's \"data\" must capture the chapter title plus its order/number AND a substantive summary of that chapter's content (key events, arguments, characters, places, concepts, terms, notable quotes). Apply AS MANY relevant tags as possible to EVERY chapter record (characters, locations, themes, topics, key concepts, key terms, dates, named entities) so the book is easy to SEARCH and cross-reference later - this is the whole point. ALSO save one book-level record (title, author, language, overall summary, chapter list / table of contents, genre/subjects) and link each chapter record to it via reference. This per-chapter completeness OVERRIDES brevity; human-readable summaries only, never raw/binary bytes.\n- This is a background indexing task: do ALL the MCP saving FIRST, never reply mid-task, and never ask the user questions. Always use the MCP tools to save what you learn - be exhaustive about meaning (and, for tabular data, about every row). SAVE AS YOU GO: persist each window's records before reading the next, so progress is never lost. If the file is so large you cannot finish in one turn, still save everything you have read so far; a follow-up pass will automatically continue from where you stopped. Never store raw or binary bytes (base64, blobs); describe them in human-readable text instead.\n- COMPLETION SIGNAL: only when you have fully read and saved the ENTIRE file (for readFileContent files: reached \"END OF FILE\"; for PDFs: the embedded page-image note said it was the LAST window - with all rows/pages/items saved), end your final message with the token INDEXING_COMPLETE on its own line. If you did NOT finish the whole file (more rows/pages remain), do NOT write that token - leaving it out is how the system knows to run another pass to continue.\n- Only AFTER every save is done, send exactly ONE final message summarizing what you indexed - never just \"Indexing complete\", and never a raw/base64/binary value or a large pasted dump. Keep it to a few factual sentences or a short markdown bullet list covering: the file name, its content type, each table you wrote to with its record/row count and the key columns/fields or topics captured, and anything that could not be extracted. Follow this shape - Indexed <file name> (<content type>): saved <N> records to <table(s)> capturing <key columns/fields or topics>; could not extract: <gaps, or none>.`;\n\n\tif (serviceDescription) {\n\t\tsystemPrompt += `\nProject name: \"${serviceName ?? ''}\"\nProject description: \"\"\"${serviceDescription}\"\"\"`;\n\t}\n\n\treturn systemPrompt;\n}\n","/**\n * BASE PROMPT — Background file-indexing agent (user message)\n * ============================================================================\n * USER-role message paired with the indexing system prompt. Sent by\n * notifyAgentSaveAttachment() each time a file is uploaded or re-indexed.\n *\n * NOTE: the leading line \"A new file has just been uploaded. Index it now.\" and\n * the \"- name: ...\" line are also what the chat client parses to build the\n * \"Indexing: <name>\" history bubble — keep those fields on their own lines.\n */\n\nexport type IndexingAttachmentInfo = {\n\t/** Original file name. */\n\tname: string;\n\t/** Storage path within the project's db storage. */\n\tstoragePath: string;\n\t/** MIME type, if detected. Omitted from the message when unknown. */\n\tmime?: string;\n\t/** File size in bytes, if known. Omitted from the message when unknown. */\n\tsize?: number;\n\t/** Temporary signed URL the agent/MCP fetches to read the file contents. */\n\turl: string;\n};\n\nexport type BuildIndexingUserMessageOptions = {\n\t/**\n\t * For office files (.docx/.xlsx/.pptx) the model can't read the binary via\n\t * web_fetch, so the proxy worker extracts the text server-side and replaces\n\t * this exact token with it. When provided, the message embeds the token (and\n\t * drops the temporary-URL line — there is nothing for the model to fetch).\n\t */\n\tinlineContentPlaceholder?: string;\n\t/**\n\t * Actual file content parsed CLIENT-SIDE by an attachment-parser plugin (e.g.\n\t * an .hwp parser). Embedded inline verbatim — no server extraction and no\n\t * web_fetch for this file. Takes precedence over `inlineContentPlaceholder`.\n\t */\n\tinlineContent?: string;\n\t/**\n\t * Spreadsheet or PDF: read by PAGING through the readFileContent tool (grid rows +\n\t * embedded photos / rendered scanned pages), not inline and not by web_fetch. The\n\t * message instructs the agent to page through EVERY window and datafy each.\n\t */\n\tpagedRead?: boolean;\n};\n\nexport function buildIndexingUserMessage(\n\tattachment: IndexingAttachmentInfo,\n\toptions?: BuildIndexingUserMessageOptions,\n): string {\n\tconst head =\n\t\t`A new file has just been uploaded. Index it now.\\n\\n` +\n\t\t`File metadata:\\n` +\n\t\t`- name: ${attachment.name}\\n` +\n\t\t`- storage path: ${attachment.storagePath}\\n` +\n\t\t(attachment.mime ? `- mime type: ${attachment.mime}\\n` : '') +\n\t\t(typeof attachment.size === 'number' ? `- size (bytes): ${attachment.size}\\n` : '');\n\n\tif (options?.inlineContent) {\n\t\t// Parsed client-side (an attachment-parser plugin). The content is already\n\t\t// inlined below — no server extraction, no URL to fetch.\n\t\treturn (\n\t\t\thead +\n\t\t\t`\\nThe file's content was parsed by the client and is provided inline below. ` +\n\t\t\t`Read it directly — do NOT fetch any URL for this file. ` +\n\t\t\t`Use the storage path above (not this content) for the \"src::\" unique_id.\\n\\n` +\n\t\t\t`----- BEGIN FILE CONTENT -----\\n` +\n\t\t\t`${options.inlineContent}\\n` +\n\t\t\t`----- END FILE CONTENT -----`\n\t\t);\n\t}\n\n\tif (options?.inlineContentPlaceholder) {\n\t\t// Office file: text was extracted on the server and is inlined below\n\t\t// between the markers. Do NOT fetch any URL for this file.\n\t\treturn (\n\t\t\thead +\n\t\t\t`\\nThe file's text content was extracted on the server and is provided inline below. ` +\n\t\t\t`Read it directly — do NOT fetch any URL for this file. ` +\n\t\t\t`Use the storage path above (not this content) for the \"src::\" unique_id.\\n\\n` +\n\t\t\t`----- BEGIN FILE CONTENT -----\\n` +\n\t\t\t`${options.inlineContentPlaceholder}\\n` +\n\t\t\t`----- END FILE CONTENT -----`\n\t\t);\n\t}\n\n\tif (options?.pagedRead) {\n\t\t// Spreadsheet / PDF: force the paging path. The agent MUST read this with the\n\t\t// readFileContent tool (which returns the file window by window, with grid rows,\n\t\t// embedded photos, and rendered scanned pages), NOT by fetching the URL.\n\t\treturn (\n\t\t\thead +\n\t\t\t`\\nRead this file with the readFileContent tool, using the storage path above - do NOT fetch a URL and do NOT rely on a single sample. ` +\n\t\t\t`readFileContent returns the file ONE WINDOW at a time: spreadsheets as coordinate-tagged grid rows (e.g. 'R4 A:E&I NUMBER | B:E1007'), scanned/large PDFs as rendered PAGE IMAGES, and windows may include embedded photos - LOOK at any images and datafy what they show. ` +\n\t\t\t`Page through EVERY window: for each window SAVE records for its rows/items/pages (postRecords, one record per row/item), THEN if the window says MORE REMAINS call readFileContent again with the cursor it gives you. Repeat until it says END OF FILE, so the WHOLE file is indexed. ` +\n\t\t\t`Do NOT stop after the first window and do NOT just write a summary. Use the storage path above for the \"src::\" unique_id.` +\n\t\t\t(attachment.url ? `\\n(A temporary URL is provided ONLY as a fallback if readFileContent fails: ${attachment.url})` : '')\n\t\t);\n\t}\n\n\treturn head + `- temporary URL (fetch this to read the file contents): ${attachment.url}`;\n}\n\n/**\n * Token the WORKER substitutes with the 1-based first page of the window it is about to\n * render, when it builds the next pass of a document from `RENDER_CONTINUE_TEMPLATE`.\n * Must match the worker's RENDER_FROM_TOKEN.\n */\nexport const RENDER_FROM_TOKEN = '{{RENDER_FROM}}';\nconst WINDOW_CURSOR_TOKEN = RENDER_FROM_TOKEN;\n\n/**\n * User message for a VISION file (PDF): its pages are delivered as RENDERED PAGE IMAGES that\n * the proxy worker injects into THIS message at the `placeholder` token (tool-result images\n * render on neither provider, so the pages must be image blocks in the message itself). Each\n * pass shows one WINDOW of pages starting at `renderFrom` (0-based).\n *\n * The WORKER advances the window: when its renderer reports pages remaining it enqueues the\n * next pass itself, off the true page count, so a document indexes end-to-end with no browser\n * involved. This message therefore only ever describes ONE window, and the model is never\n * asked to decide whether the document is finished.\n *\n * renderFrom === 0 is the FIRST pass (leads with \"A new file has just been uploaded.\" so the\n * client builds the \"Indexing: <name>\" bubble); a continue pass (built by the worker from\n * buildIndexingRenderContinueTemplate) leads with \"CONTINUE indexing\" so it is not a duplicate\n * primary bubble.\n */\nexport function buildIndexingRenderMessage(\n\tattachment: IndexingAttachmentInfo,\n\tplaceholder: string,\n\trenderFrom: number,\n): string {\n\tconst from = Math.max(0, renderFrom || 0);\n\tif (from > 0) return buildIndexingRenderContinueTemplate(attachment, placeholder, String(from + 1));\n\n\treturn (\n\t\t`A new file has just been uploaded. Index it now.\\n\\n` +\n\t\tbuildRenderMeta(attachment) +\n\t\t`\\nThis is a PDF. Its pages are delivered to you as RENDERED PAGE IMAGES embedded directly in this ` +\n\t\t`message (you do NOT need any tool, URL, or web_fetch to see them). You are shown a WINDOW of pages ` +\n\t\t`at a time, starting at page ${from + 1}.\\n` +\n\t\tbuildRenderDatafy(placeholder)\n\t);\n}\n\n/**\n * The CONTINUE pass, as a template the worker fills in. `pageLabel` defaults to the\n * RENDER_FROM_TOKEN placeholder, which the worker replaces with the real 1-based start page\n * of the window it is rendering; passing an explicit label produces a ready-to-send message.\n */\nexport function buildIndexingRenderContinueTemplate(\n\tattachment: IndexingAttachmentInfo,\n\tplaceholder: string,\n\tpageLabel: string = RENDER_FROM_TOKEN,\n): string {\n\tconst src = `src::${attachment.storagePath}`;\n\treturn (\n\t\t`CONTINUE indexing a PDF whose previous pass did not finish.\\n\\n` +\n\t\tbuildRenderMeta(attachment) +\n\t\t`\\nRecords for the earlier pages are ALREADY saved (they reference \"${src}\"). The NEXT window of ` +\n\t\t`rendered page images (starting at page ${pageLabel}) is embedded in this message. Datafy each page as ` +\n\t\t`before and do NOT re-save pages that are already saved.\\n` +\n\t\tbuildRenderDatafy(placeholder)\n\t);\n}\n\nfunction buildRenderMeta(attachment: IndexingAttachmentInfo): string {\n\treturn (\n\t\t`File metadata:\\n` +\n\t\t`- name: ${attachment.name}\\n` +\n\t\t`- storage path: ${attachment.storagePath}\\n` +\n\t\t(attachment.mime ? `- mime type: ${attachment.mime}\\n` : '')\n\t);\n}\n\n// Shared datafy guidance. The placeholder is where the worker splices the note + rendered\n// page images; instructions reference \"the page images in this message\" so they read\n// correctly whether the images land before or after this text.\n//\n// Deliberately says nothing about INDEXING_COMPLETE or about whether the document is\n// finished: the worker decides that from the renderer's page count. Asking the model was\n// what used to end an 88-page file at page 15.\nfunction buildRenderDatafy(placeholder: string): string {\n\treturn (\n\t\t`\\n${placeholder}\\n\\n` +\n\t\t`LOOK at each rendered page image in this message and DATAFY what it shows: for EVERY page ` +\n\t\t`call postRecords and save records - one record per row / table entry / line item visible on the page ` +\n\t\t`(or one record for the page if it is prose), capturing every value you can read (OCR the text, read tables ` +\n\t\t`cell by cell, describe any photos/diagrams). Use the storage path above for the \"src::\" unique_id.\\n\\n` +\n\t\t`Save records for THIS window of pages only, then stop and report what you saved. Do NOT try to read ` +\n\t\t`the rest of the file and do NOT worry about the pages after this window: if any remain, the next window ` +\n\t\t`is rendered and sent to you automatically. Report only the pages you were actually shown - never imply ` +\n\t\t`you have seen the whole document.`\n\t);\n}\n\n/**\n * User message for a WINDOWED file: the worker splices ONE window of the file's rows or\n * text into this message at `placeholder`, then continues from the reader's own cursor\n * until the file is exhausted.\n *\n * The agent is deliberately NOT asked to page the file itself, and is NOT asked to judge\n * whether it is finished. Both used to be its job, and both failed the same way: the\n * traversal lived inside a single turn's budget, so a large file simply stopped partway\n * with a confident summary of the part it had seen.\n */\nexport function buildIndexingWindowMessage(\n\tattachment: IndexingAttachmentInfo,\n\tplaceholder: string,\n\tisContinuation: boolean,\n\tpositionLabel?: string,\n): string {\n\tconst src = `src::${attachment.storagePath}`;\n\tconst head = isContinuation\n\t\t? `CONTINUE indexing a file whose previous pass did not finish.\\n\\n`\n\t\t: `A new file has just been uploaded. Index it now.\\n\\n`;\n\tconst where = isContinuation\n\t\t? `\\nRecords for the earlier windows are ALREADY saved (they reference \"${src}\"). The NEXT window ` +\n\t\t `(starting at ${positionLabel || WINDOW_CURSOR_TOKEN}) is embedded below. Do NOT re-save windows that are already saved.\\n`\n\t\t: `\\nThis file is delivered to you ONE WINDOW at a time, embedded directly in this message. ` +\n\t\t `You do NOT need any tool, URL, or web_fetch to read it.\\n`;\n\n\treturn (\n\t\thead +\n\t\tbuildRenderMeta(attachment) +\n\t\twhere +\n\t\t`\\n${placeholder}\\n\\n` +\n\t\t`DATAFY this window: call postRecords and save records for everything in it - ONE RECORD PER ROW ` +\n\t\t`for tabular data (keyed by the column headers), or one record per section for prose. Capture every ` +\n\t\t`value you can read. Use the storage path above for the \"src::\" unique_id on the file-level record, ` +\n\t\t`and link every row/section record to it by reference.\\n\\n` +\n\t\t`If this window has PHOTOS attached as images, LOOK at each one and datafy what it actually shows ` +\n\t\t`into the record for the row it is anchored to (a «PHOTO A88» marker in the grid text only says WHERE ` +\n\t\t`a picture sits - the picture itself is attached to this message). Never report that photo contents ` +\n\t\t`could not be extracted when images are attached here.\\n\\n` +\n\t\t`Save records for THIS window only, then stop and report what you saved. Do NOT try to read the rest ` +\n\t\t`of the file, and do NOT call readFileContent - if more remains, the next window is read and sent to ` +\n\t\t`you automatically. Report only what you were actually shown, and never imply you have seen the whole ` +\n\t\t`file when the note beside the window says more remains.`\n\t);\n}\n\n/**\n * User message for a RESUME pass: a previous indexing pass could not finish this large\n * file, so continue it from where the already-saved records leave off (never restart).\n */\nexport function buildIndexingContinueMessage(attachment: IndexingAttachmentInfo): string {\n\tconst src = `src::${attachment.storagePath}`;\n\treturn (\n\t\t`CONTINUE indexing a file whose previous pass did not finish.\\n\\n` +\n\t\t`File metadata:\\n` +\n\t\t`- name: ${attachment.name}\\n` +\n\t\t`- storage path: ${attachment.storagePath}\\n` +\n\t\t(attachment.mime ? `- mime type: ${attachment.mime}\\n` : '') +\n\t\t`\\nRecords for the earlier windows/pages of this file are ALREADY saved (they reference \"${src}\"). ` +\n\t\t`First call getRecords with reference \"${src}\" to see how far the previous pass got (the furthest page/row/window already saved). ` +\n\t\t`Then call readFileContent with the storage path above and a CURSOR that RESUMES just after that point - do NOT start at the beginning. The cursor is derivable from what you already saved:\\n` +\n\t\t` - PDF: the cursor is the NUMBER OF PAGES already read (0-based next page). If you saved up to page N, call readFileContent with cursor=\"N\" to get page N+1 onward.\\n` +\n\t\t` - Spreadsheet: the cursor is \"<sheetIndex>:<nextRow>\" (0-based sheet index, 1-based row). If you saved up to row R of sheet S, use cursor=\"S:R+1\".\\n` +\n\t\t` - Text: the cursor is the character offset already read.\\n` +\n\t\t`Index the REMAINING windows - one record per row/item, looking at any page images or embedded photos - saving as you go until readFileContent reports END OF FILE. ` +\n\t\t`Do NOT re-save windows that are already saved. ` +\n\t\t`Use the storage path above for the \"src::\" unique_id. When the ENTIRE file is finally indexed, end your message with the token INDEXING_COMPLETE.`\n\t);\n}\n","/**\n * Error detection + message extraction (pure). Moved verbatim from the\n * agent.vue / bunnyquery chatbox so both consumers share one implementation.\n */\n\n// Plain-language text per upstream status, for the case below where the provider\n// gave us no readable message of its own.\nvar STATUS_MESSAGE: { [code: string]: string } = {\n\t'408': 'The AI provider timed out before it started.',\n\t'409': 'The AI provider rejected the request as conflicting.',\n\t'413': 'The request was too large for the AI provider.',\n\t'429': 'The AI provider is rate limiting requests right now.',\n\t'500': 'The AI provider hit an internal error.',\n\t'502': 'The AI provider is temporarily unreachable.',\n\t'503': 'The AI provider is temporarily unavailable.',\n\t'504': 'The AI provider timed out.',\n};\n\nfunction isTransientStatus(status: number): boolean {\n\treturn status === 408 || status === 425 || status === 429 || status >= 500;\n}\n\nexport function getErrorMessage(input: any): string {\n\tif (!input) return 'Something went wrong.';\n\tif (typeof input === 'string') return input;\n\tif (input.error && input.error.message) return input.error.message;\n\tif (input.body && input.body.error && input.body.error.message) return input.body.error.message;\n\tif (input.body && typeof input.body.message === 'string') return input.body.message;\n\tif (input.message) return input.message;\n\n\t// Every branch above assumes the provider answered with JSON. It does not\n\t// always: a gateway failure in front of the model API (Cloudflare's \"502 Bad\n\t// gateway\" page, an ALB error page) arrives as an HTML STRING in `body`, so\n\t// `body.error` / `body.message` are undefined on it and the user used to get a\n\t// bare 'Something went wrong.' with no way to tell a provider outage from a\n\t// bug in their own data. The status code is the one thing we always have, so\n\t// say what it means and whether retrying is worth it.\n\tvar status = typeof input.status_code === 'number' ? input.status_code\n\t\t: typeof input.status === 'number' ? input.status : 0;\n\tif (status) {\n\t\tvar text = STATUS_MESSAGE[String(status)]\n\t\t\t|| (status >= 500 ? 'The AI provider returned a server error.'\n\t\t\t\t: 'The AI provider rejected the request.');\n\t\treturn text + ' (error ' + status + ')'\n\t\t\t+ (isTransientStatus(status) ? ' This is usually temporary, please try again.' : '');\n\t}\n\treturn 'Something went wrong.';\n}\n\nexport function isErrorResponseBody(response: any): boolean {\n\tif (!response || typeof response !== 'object') return false;\n\tif (typeof response.status_code === 'number' && response.status_code >= 400) return true;\n\tif (response.type === 'error') return true;\n\tif (response.error && (response.error.message || response.error.type)) return true;\n\tvar body = response.body;\n\tif (body && typeof body === 'object') {\n\t\tif (body.type === 'error') return true;\n\t\tif (body.error && (body.error.message || body.error.type)) return true;\n\t}\n\tif (typeof response.message === 'string' && response.message.length) {\n\t\tvar hasClaude = Array.isArray(response.content);\n\t\tvar hasOpenAI =\n\t\t\ttypeof response.output_text === 'string' ||\n\t\t\tArray.isArray(response.output) ||\n\t\t\tArray.isArray(response.choices);\n\t\tif (!hasClaude && !hasOpenAI) return true;\n\t}\n\treturn false;\n}\n\n// A request that failed because the REQUEST ITSELF is malformed — an unknown or\n// rejected parameter on a 400/422 — will deterministically re-fail if resent\n// unchanged; no session refresh or retry can fix it. Detecting it lets the retry\n// gates refuse to auto-resend (otherwise a 400 whose param name merely contains\n// \"token\", e.g. `max_output_tokens`, trips the `invalid_request + token` branch\n// of isAuthExpiredError below and loops refresh->resend forever, burning tokens).\n// This is the `_skapi_extract` 400 class. Distinct from auth-expiry, which IS\n// retryable after a token refresh — so 401 (auth) and 429/5xx (transient) are\n// intentionally NOT treated as non-retryable here.\nexport function isNonRetryableRequestError(input: any): boolean {\n\tif (!input || typeof input !== 'object') return false;\n\n\tvar status = typeof input.status_code === 'number' ? input.status_code\n\t\t: typeof input.status === 'number' ? input.status : undefined;\n\n\t// Collect the error envelope wherever it lives (response, response.body, or a\n\t// thrown error), mirroring isErrorResponseBody / isAuthExpiredError.\n\tvar param: any = undefined;\n\tvar blobs: string[] = [];\n\tvar sources = [input.error, input.body && input.body.error, input.body, input];\n\tfor (var i = 0; i < sources.length; i++) {\n\t\tvar e = sources[i];\n\t\tif (!e) continue;\n\t\tif (typeof e === 'string') { blobs.push(e); continue; }\n\t\tif (typeof e !== 'object') continue;\n\t\tif (param === undefined && e.param != null) param = e.param;\n\t\tif (typeof e.code === 'string') blobs.push(e.code);\n\t\tif (typeof e.type === 'string') blobs.push(e.type);\n\t\tif (typeof e.message === 'string') blobs.push(e.message);\n\t}\n\tvar hay = blobs.join(' | ').toLowerCase();\n\n\t// Explicit \"unknown / unsupported parameter\" is always a malformed request.\n\tif (hay.indexOf('unknown_parameter') !== -1 || hay.indexOf('unknown parameter') !== -1 ||\n\t\thay.indexOf('unsupported_parameter') !== -1 || hay.indexOf('unsupported parameter') !== -1) {\n\t\treturn true;\n\t}\n\n\t// A 400/422 invalid_request that points at a specific rejected field: resending\n\t// the identical body re-fails. (401 -> isAuthExpiredError; 429/5xx -> transient.)\n\tvar isClientReqStatus = status === 400 || status === 422;\n\tif (isClientReqStatus && param != null && param !== '') return true;\n\tif (isClientReqStatus && hay.indexOf('invalid_request') !== -1 &&\n\t\t(hay.indexOf('parameter') !== -1 || hay.indexOf('param') !== -1)) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nexport function isAuthExpiredError(input: any): boolean {\n\tif (!input) return false;\n\tvar blobs: string[] = [];\n\tvar push = function (v: any) { if (typeof v === 'string' && v) blobs.push(v); };\n\tif (typeof input === 'string') push(input);\n\telse {\n\t\tpush(input.message); push(input.code);\n\t\tif (input.error) { push(input.error.message); push(input.error.code); push(input.error.type); }\n\t\tif (input.body) {\n\t\t\tpush(input.body.message);\n\t\t\tif (input.body.error) { push(input.body.error.message); push(input.body.error.code); push(input.body.error.type); }\n\t\t}\n\t\tif (typeof input.status === 'number' && input.status === 401) return true;\n\t\tif (typeof input.status_code === 'number' && input.status_code === 401) return true;\n\t}\n\tvar hay = blobs.join(' | ').toLowerCase();\n\tif (!hay) return false;\n\treturn hay.indexOf('token has expired') !== -1 || hay.indexOf('token is expired') !== -1 ||\n\t\thay.indexOf('expired_token') !== -1 || hay.indexOf('invalid_token') !== -1 ||\n\t\thay.indexOf('unauthorized') !== -1 || hay.indexOf('not authorized') !== -1 ||\n\t\t(hay.indexOf('invalid_request') !== -1 && hay.indexOf('token') !== -1);\n}\n","/**\n * Pure link/path helpers (no DOM, no marked). Moved verbatim from the chatbox.\n * `serviceId` is passed as a PARAMETER (the original read it from a global) so\n * the engine stays consumer-agnostic. The HTML-emitting helpers\n * (buildLinkPartFromGroups, linkToAnchorHtml, fileToAnchorHtml, parseMsgParts*)\n * stay in each VIEW — only these pure pieces move here.\n */\n\nexport var EXPIRED_ATTACHMENT_URL_HOST = '_expired_.url';\nexport var EXPIRED_ATTACHMENT_URL_ORIGIN = 'https://' + EXPIRED_ATTACHMENT_URL_HOST;\nexport var LINK_LABEL_MAX_DISPLAY_CHARS = 32;\n\n/**\n * Lifetime of the url minted when a user clicks an expired attachment chip.\n *\n * Mint it as a PLAIN get-db presign, never with generate_temporary_cdn_url: the\n * cdn branch ignores `expires` entirely and hands back a url good for the rest of\n * the current UTC day plus the next one, so a \"20 minute\" link would in fact live\n * 24 to 48 hours. The dashboard has always done this correctly and the widget did\n * not, which is precisely the kind of divergence a shared constant exists to stop.\n */\nexport var EXPIRED_LINK_REFRESH_EXPIRES_SECONDS = 20 * 60;\n\n/**\n * How long a client may keep serving an href it already minted before dropping\n * back to the placeholder and re-minting.\n *\n * DERIVED from the TTL above, with five minutes of headroom, because the\n * invariant \"the cache must expire before the url does\" used to be a comment\n * next to two independent literals. If it is ever violated a client serves a\n * dead url with no way to notice; deriving it makes that unrepresentable.\n */\nexport var LINK_REFRESH_WINDOW_MS = (EXPIRED_LINK_REFRESH_EXPIRES_SECONDS - 5 * 60) * 1000;\n\n// The two \"balanced parens\" groups match ONE CHARACTER per step, never a `+`\n// run, so each position has exactly one way to be matched: `[^()\\n]` cannot\n// start with `(`, and the nested-paren alternative always does. That disjointness\n// is load-bearing, not style.\n//\n// The obvious spelling — `(?:[^()\\n]+|\\([^()\\n]*\\))+` — is a nested quantifier:\n// a run of N plain characters can be split across the outer `+` in 2^N ways, and\n// the engine tries EVERY one before it can conclude the branch failed. A branch\n// fails on ordinary input: a link whose url contains a space (the url branch\n// forbids spaces), a link broken across a newline, or a reply truncated\n// mid-link. Measured on the unfixed pattern: `[label](` plus 30 characters with\n// no closing paren took 62 SECONDS, 45 characters never finished. Since this\n// regex is scanned over the whole reply by the typewriter (session.ts) and by\n// every message render (parseMsgParts), that is a permanently frozen tab the\n// moment such a message arrives. Same matches either way, linear time.\nexport function createInlineLinkRegex(): RegExp {\n\treturn /src::(\\S+)|\\[([^\\]\\n]+)\\]\\((https?:\\/\\/(?:[^\\s()]|\\([^\\s()]*\\))+)\\)|\\[([^\\]\\n]+)\\]\\(((?:[^()\\n]|\\([^()\\n]*\\))+)\\)|(https?:\\/\\/[^\\s<>\"']+)/g;\n}\n\nexport function safeDecodeURIComponent(v: string): string {\n\ttry { return decodeURIComponent(v); } catch (e) { return v; }\n}\n\nexport function encodePathSegments(path: string): string {\n\treturn path.split('/').filter(Boolean).map(function (s) { return encodeURIComponent(s); }).join('/');\n}\n\nexport function normalizeAttachmentPathCandidate(value: string): string {\n\treturn safeDecodeURIComponent((value || '').trim()).replace(/\\\\/g, '/').replace(/^\\/+/, '').replace(/\\/+/g, '/');\n}\n\nexport function extractRemotePathFromAttachmentHref(href: string, serviceId: string): string | null {\n\ttry {\n\t\tvar parsed = new URL(href);\n\t\tif (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return null;\n\t\tvar path = normalizeAttachmentPathCandidate(parsed.pathname || '');\n\t\tvar segs = path.split('/').filter(Boolean);\n\t\tif (!segs.length) return null;\n\t\tvar HEX = /^[a-f0-9]{32,}$/i;\n\t\tvar sid = serviceId || '';\n\t\tvar start = 0;\n\t\twhile (start < segs.length) {\n\t\t\tvar seg = segs[start];\n\t\t\tif (seg === sid || HEX.test(seg)) { start++; continue; }\n\t\t\tbreak;\n\t\t}\n\t\tvar real = segs.slice(start).join('/');\n\t\treturn real || null;\n\t} catch (e) { return null; }\n}\n\nexport function getExpiredAttachmentVisiblePath(remotePath: string, fallback?: string): string {\n\tvar n = normalizeAttachmentPathCandidate(remotePath);\n\tif (n) return n;\n\treturn normalizeAttachmentPathCandidate(fallback || 'file') || 'file';\n}\n\nexport function buildDisplayExpiredAttachmentHref(remotePath: string, fallback?: string): string {\n\treturn EXPIRED_ATTACHMENT_URL_ORIGIN + '/' + encodePathSegments(getExpiredAttachmentVisiblePath(remotePath, fallback));\n}\n\n// Does `href` point at THIS service's db attachment storage? A db attachment URL's\n// path always begins with the serviceId segment (…/<serviceId>/<hash>/<path>). Used\n// to SAFELY sanitize assistant messages — where an arbitrary external citation URL\n// must never be rewritten, only the service's own volatile db links.\nexport function isServiceDbAttachmentHref(href: string, serviceId: string): boolean {\n\tif (!serviceId) return false;\n\ttry {\n\t\tvar parsed = new URL(href);\n\t\tif (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return false;\n\t\tvar segs = normalizeAttachmentPathCandidate(parsed.pathname || '').split('/').filter(Boolean);\n\t\treturn segs.length > 0 && segs[0] === serviceId;\n\t} catch (e) { return false; }\n}\n\n/**\n * Read the storage path back out of an `_expired_.url` placeholder.\n *\n * The placeholder is not a display detail: sanitizeAttachmentLinksForHistory\n * writes it into PERSISTED history, and buildBoundedChatMessages replays it into\n * the model's context. So it round-trips constantly and MUST be recognised on the\n * way back in. Returns null for anything that is not the carrier.\n */\nexport function readExpiredAttachmentHref(href: string): string | null {\n\tif (!href) return null;\n\ttry {\n\t\tvar parsed = new URL(href);\n\t\tif (parsed.hostname !== EXPIRED_ATTACHMENT_URL_HOST) return null;\n\t\treturn normalizeAttachmentPathCandidate(parsed.pathname || '') || null;\n\t} catch (e) { return null; }\n}\n\n// Replace volatile attachment URLs with their durable `_expired_.url/<path>`\n// placeholder so a stored/replayed copy re-mints on demand instead of going stale.\n//\n// Only THIS service's db urls are rewritten, whichever role wrote them. The user\n// branch used to rewrite every url in any message that carried an \"Attached\n// files:\" block, which quietly destroyed a third-party link the user happened to\n// paste in the same message: it became a placeholder for a storage path that\n// never existed. We can only re-mint what we host, so we only rewrite what we\n// host.\nexport function sanitizeAttachmentLinksForHistory(content: string, serviceId: string, forAssistant?: boolean): string {\n\tif (!content) return content;\n\tif (!forAssistant && content.indexOf('Attached files:') === -1) return content;\n\treturn content.replace(/\\[([^\\]\\n]+)\\]\\((https?:\\/\\/[^\\s)]+)\\)/g, function (_m: string, label: string, href: string) {\n\t\tif (!isServiceDbAttachmentHref(href, serviceId)) return _m;\n\t\tvar remotePath = extractRemotePathFromAttachmentHref(href, serviceId);\n\t\tvar fullPath = remotePath || normalizeAttachmentPathCandidate(label);\n\t\tif (!fullPath) return _m;\n\t\treturn '[' + label + '](' + buildDisplayExpiredAttachmentHref(fullPath, label) + ')';\n\t});\n}\n\n/**\n * Is this markdown link target a URL rather than a db storage path?\n *\n * The inline-link regex decides that by whether the target contains whitespace:\n * its url branch forbids it, its bare-path branch allows it (a db path really can\n * contain spaces). So a url that picked up a stray space anywhere in transit\n * falls out of the url branch and is claimed by the path branch, and the view\n * renders it as an `_expired_.url/https%3A/…` attachment chip that resolves to\n * nothing. The view asks this FIRST, so what a link IS never depends on damage.\n */\nexport function isHttpUrlLike(target: string): boolean {\n\treturn /^https?:\\/\\//i.test((target || '').trim());\n}\n\n/**\n * Repair whitespace inside a url. RFC 3986 has no legal whitespace anywhere in a\n * URI, so a space in an href is always damage, never content.\n *\n * Two repairs, because the right one differs:\n * - Our own `/download/<id>` capability links (skapi-mcp file-download.js) are\n * base64url, optionally with a single `.` separating the payload and hmac of\n * the older self-describing token. That alphabet cannot contain whitespace,\n * so the spaces are purely damage and REMOVING them restores the exact link,\n * which is what makes an already-sent message clickable again. A model\n * reproducing one of these into its reply is exactly where the spaces come\n * from, which is also why the id is now short.\n * - Anything else keeps every character and only has the whitespace encoded,\n * the same thing a browser does with a space in an href. Stripping would be\n * wrong there: `…/exports/my report.csv` is a real file whose name has a\n * space in it, and deleting it points at a file that does not exist.\n */\nexport function repairUrlWhitespace(href: string): string {\n\tif (!href || !/\\s/.test(href)) return href;\n\tvar stripped = href.replace(/\\s+/g, '');\n\tif (/^https?:\\/\\/[^/\\s]+\\/download\\/[A-Za-z0-9_-]+(\\.[A-Za-z0-9_-]+)?$/i.test(stripped)) return stripped;\n\treturn href.trim().replace(/\\s/g, '%20');\n}\n\n/**\n * A model reproducing a URL sometimes HTML-escapes its `&` query separators as\n * `&` (or the numeric `&` / `&`). Left in the href that escaping\n * survives the client's own escapeAttr -> v-html/innerHTML decode round-trip and\n * reaches the browser LITERALLY, so a presigned S3 URL is navigated with its\n * parameters named `amp;Signature`, `amp;Expires`, `amp;response-content-type`,\n * ... — the real params vanish, the signature can't be located, and S3 rejects\n * it (the \"링크가 안되\" dead export link). Undo just that entity escaping.\n *\n * This is a no-op on a clean URL: a valid link carries a raw `&` between params\n * and percent-encodes (`%26`) any literal ampersand that is data, so a real URL\n * never contains `&` to begin with. Mirrors repairUrlWhitespace: it repairs\n * model damage, not the URL. The loop collapses a doubly-escaped `&amp;` too.\n */\nexport function repairUrlEntities(href: string): string {\n\tif (!href || href.indexOf('&') === -1) return href;\n\tvar out = href, prev = '';\n\twhile (out !== prev) {\n\t\tprev = out;\n\t\tout = out\n\t\t\t.replace(/&/gi, '&')\n\t\t\t.replace(/�*38;/g, '&')\n\t\t\t.replace(/�*26;/gi, '&');\n\t}\n\treturn out;\n}\n\n/**\n * Trim punctuation and unmatched wrappers that cling to a token in prose.\n * `src::a/b.pdf).` -> `src::a/b.pdf`, while a balanced `file (v2).pdf` is kept.\n */\nexport function normalizeTrailingInlineToken(value: string): string {\n\tif (!value) return value;\n\tvar out = value.replace(/[.,;:!?]+$/, '');\n\tvar trimUnmatched = function (openCh: string, closeCh: string) {\n\t\twhile (out.charAt(out.length - 1) === closeCh) {\n\t\t\tvar openCount = (out.match(new RegExp('\\\\' + openCh, 'g')) || []).length;\n\t\t\tvar closeCount = (out.match(new RegExp('\\\\' + closeCh, 'g')) || []).length;\n\t\t\tif (closeCount > openCount) out = out.slice(0, -1); else break;\n\t\t}\n\t};\n\ttrimUnmatched('(', ')');\n\ttrimUnmatched('[', ']');\n\ttrimUnmatched('{', '}');\n\tout = out.replace(/[`'\"*>]+$/, '');\n\treturn out;\n}\n\n/** A link the view renders. `expired` means the href is the `_expired_.url`\n * placeholder and a click must mint a fresh one from `remotePath`. */\nexport interface InlineLinkPart {\n\ttype: 'link';\n\tlabel: string;\n\tfullLabel: string;\n\thref: string;\n\texpired: boolean;\n\texpiredHref?: string;\n\tremotePath?: string;\n}\n\nexport interface InlineLinkContext {\n\t/** Current project id: the leading segment to strip off a db url. */\n\tserviceId: string;\n\t/** `https://db.<hostDomain>` for this deployment. */\n\tdbHostPrefix: string;\n\t/** A fresh url already minted for this placeholder, if the view cached one. */\n\tresolveFreshHref?: (expiredHref: string) => string | undefined;\n}\n\n/**\n * Decide what ONE inline-link regex match actually is, and how to render it.\n *\n * This is the single place that answers \"is this an external url, this project's\n * db file, or a bare storage path\", for every consumer. It used to live twice,\n * once in agent.vue and once in the widget, and both copies had to be found and\n * corrected for each of the link bugs this file's history records. A view now\n * supplies its own context (project id, db host, cached-href lookup) and does\n * nothing but turn the returned part into markup.\n *\n * `groups` is [g1..g6] from createInlineLinkRegex, in that order:\n * g1 src::<token> g2/g3 [label](url) g4/g5 [label](path) g6 bare url\n */\nexport function classifyInlineLink(\n\tfull: string,\n\tgroups: Array<string | undefined>,\n\tctx: InlineLinkContext,\n): { part: InlineLinkPart; tail?: string } | null {\n\tvar g1 = groups[0], g2 = groups[1], g3 = groups[2], g4 = groups[3], g5 = groups[4], g6 = groups[5];\n\tvar dbHostPrefix = (ctx.dbHostPrefix || '').toLowerCase();\n\tvar fresh = function (expiredHref: string): string | undefined {\n\t\treturn ctx.resolveFreshHref ? ctx.resolveFreshHref(expiredHref) : undefined;\n\t};\n\tvar isDbHost = function (url: string): boolean {\n\t\treturn !!dbHostPrefix && url.toLowerCase().indexOf(dbHostPrefix) === 0;\n\t};\n\t// A db path rendered as the placeholder the click handler resolves.\n\tvar asStoredFile = function (remotePath: string, label: string): { part: InlineLinkPart } | null {\n\t\tif (!remotePath) return null;\n\t\tvar expiredHref = buildDisplayExpiredAttachmentHref(remotePath, label);\n\t\tvar cached = fresh(expiredHref);\n\t\treturn {\n\t\t\tpart: {\n\t\t\t\ttype: 'link',\n\t\t\t\tlabel: truncateLabelForDisplay(label),\n\t\t\t\tfullLabel: label,\n\t\t\t\thref: cached || expiredHref,\n\t\t\t\texpired: !cached,\n\t\t\t\texpiredHref: expiredHref,\n\t\t\t\tremotePath: remotePath,\n\t\t\t},\n\t\t};\n\t};\n\n\t// src::<token> — a path, or a url the model copied out of a record.\n\tif (g1) {\n\t\tvar rawPath = normalizeTrailingInlineToken(g1);\n\t\tvar tail = full.slice(('src::' + rawPath).length);\n\t\tvar srcIsUrl = isHttpUrlLike(rawPath);\n\t\t// `src::` values come straight out of a record's unique_id, and the prompt\n\t\t// says that may be \"the file's storage path or original URL\". http:// is as\n\t\t// much a url as https://; testing only for https sent every plain-http\n\t\t// source into the storage-path branch, where it became a chip pointing at\n\t\t// this project for someone else's file.\n\t\tif (srcIsUrl && !isDbHost(rawPath) && !readExpiredAttachmentHref(rawPath)) {\n\t\t\t// decode any model-introduced `&` in the URL (tail stays keyed on\n\t\t\t// the raw match length, so it is left untouched)\n\t\t\tvar srcUrl = repairUrlEntities(rawPath);\n\t\t\treturn {\n\t\t\t\tpart: { type: 'link', label: truncateLabelForDisplay(srcUrl), fullLabel: srcUrl, href: srcUrl, expired: false },\n\t\t\t\ttail: tail,\n\t\t\t};\n\t\t}\n\t\tvar srcPath = readExpiredAttachmentHref(rawPath)\n\t\t\t|| (srcIsUrl\n\t\t\t\t? (extractRemotePathFromAttachmentHref(rawPath, ctx.serviceId) || normalizeAttachmentPathCandidate(rawPath))\n\t\t\t\t: normalizeAttachmentPathCandidate(rawPath));\n\t\tvar srcBuilt = asStoredFile(srcPath, srcPath);\n\t\treturn srcBuilt ? { part: srcBuilt.part, tail: tail } : null;\n\t}\n\n\t// [label](target) where target is NOT a url by the regex's reckoning.\n\tif (g4 && g5) {\n\t\t// An EXPLICIT db target, `[label](db:folder/file.csv)`, says what it is\n\t\t// instead of leaving us to infer it from the absence of \"http\". That is the\n\t\t// only form here that cannot be confused with anything else, and it matches\n\t\t// the scheme the backend already uses internally (db:<service>/<key>).\n\t\t// Accepted now so the clients tolerate it everywhere before anything starts\n\t\t// EMITTING it; until then this branch simply never fires.\n\t\tvar dbTarget = /^db:(.+)$/i.exec(g5.trim());\n\t\tif (dbTarget) {\n\t\t\tvar declared = asStoredFile(normalizeAttachmentPathCandidate(dbTarget[1]), g4);\n\t\t\tif (!declared) return null;\n\t\t\tdeclared.part.label = truncateLabelForDisplay(g4);\n\t\t\tdeclared.part.fullLabel = g4;\n\t\t\treturn declared;\n\t\t}\n\t\t// ...except when it is one. It only lands here because it contains\n\t\t// whitespace, which the url branch forbids and this one allows, and\n\t\t// reading a damaged url as a storage path is how a download link became a\n\t\t// dead chip. Repair it and classify it as what it is.\n\t\tif (isHttpUrlLike(g5)) {\n\t\t\treturn classifyInlineLink(full, [undefined, g4, repairUrlWhitespace(g5), undefined, undefined, undefined], ctx);\n\t\t}\n\t\t// Any OTHER scheme, or a fragment, is a link the user wrote and not a file\n\t\t// we host. `mailto:`, `tel:` and `#section` were all being turned into\n\t\t// download chips for storage paths of that literal text, so clicking one\n\t\t// asked this project for a file called \"mailto:a@b.com\".\n\t\tvar trimmedTarget = g5.trim();\n\t\tif (/^[a-z][a-z0-9+.-]*:/i.test(trimmedTarget) || trimmedTarget.charAt(0) === '#') {\n\t\t\treturn {\n\t\t\t\tpart: { type: 'link', label: truncateLabelForDisplay(g4), fullLabel: g4, href: trimmedTarget, expired: false },\n\t\t\t};\n\t\t}\n\t\tvar built = asStoredFile(normalizeAttachmentPathCandidate(g5), g4);\n\t\tif (!built) return null;\n\t\t// The label is the model's, not the path: keep it verbatim.\n\t\tbuilt.part.label = truncateLabelForDisplay(g4);\n\t\tbuilt.part.fullLabel = g4;\n\t\treturn built;\n\t}\n\n\t// [label](url) and bare urls.\n\tvar originalHref = g3 || g6 || '';\n\tif (!originalHref) return null;\n\t// A model that reproduces the URL may have HTML-escaped its `&` separators;\n\t// decode them now so every downstream check and the final href see a clean\n\t// URL (otherwise a presigned link navigates with `&` and 403s).\n\toriginalHref = repairUrlEntities(originalHref);\n\t// A bare url swallows the punctuation that ends the sentence it sits in, so\n\t// `see https://host/a.pdf.` linked to `a.pdf.` and 404'd. Trim it and hand the\n\t// trimmed text back as `tail`, exactly as the src:: branch does.\n\tvar urlTail: string | undefined;\n\tif (!g3 && g6) {\n\t\tvar trimmedUrl = normalizeTrailingInlineToken(originalHref);\n\t\tif (trimmedUrl !== originalHref) urlTail = originalHref.slice(trimmedUrl.length);\n\t\toriginalHref = trimmedUrl;\n\t}\n\tvar withTail = function (r: { part: InlineLinkPart }): { part: InlineLinkPart; tail?: string } {\n\t\treturn urlTail ? { part: r.part, tail: urlTail } : r;\n\t};\n\tvar urlLabel = g2 || originalHref;\n\n\t// THE PLACEHOLDER, read back. sanitizeAttachmentLinksForHistory writes this\n\t// form into stored history and buildBoundedChatMessages replays it to the\n\t// model, so it arrives here constantly: as a rebuilt bubble on every reload,\n\t// and as text the model copied out of its own context. It has to be checked\n\t// BEFORE the generic https branch, because it IS https and it is NOT the db\n\t// host, so that branch claimed it and rendered `expired: false` — a link to a\n\t// hostname that does not resolve, with no way to ever refresh it. Every stored\n\t// attachment link went dead on reload for exactly that reason.\n\tvar carried = readExpiredAttachmentHref(originalHref);\n\tif (carried) {\n\t\tvar carriedBuilt = asStoredFile(carried, g2 || carried);\n\t\tif (carriedBuilt) {\n\t\t\tif (g2) { carriedBuilt.part.label = truncateLabelForDisplay(g2); carriedBuilt.part.fullLabel = g2; }\n\t\t\treturn withTail(carriedBuilt);\n\t\t}\n\t}\n\n\t// This project's own db url: volatile, so render it re-mintable. A db url for\n\t// a DIFFERENT project is not ours to mint, so it stays an ordinary link rather\n\t// than a chip that would query this project for someone else's key.\n\tif (isServiceDbAttachmentHref(originalHref, ctx.serviceId)) {\n\t\tvar remotePath = extractRemotePathFromAttachmentHref(originalHref, ctx.serviceId);\n\t\tif (remotePath) {\n\t\t\tvar dbBuilt = asStoredFile(remotePath, getExpiredAttachmentVisiblePath(remotePath, urlLabel));\n\t\t\tif (dbBuilt) return withTail(dbBuilt);\n\t\t}\n\t}\n\n\t// Everything else is a link, not a path. The old rule tested for `https://`\n\t// specifically and treated ANY other target as db storage, so a plain\n\t// `http://` citation, a `mailto:`, a `#anchor` and a `/relative` link all\n\t// rendered as download chips for storage paths that never existed, and\n\t// clicking one raised \"failed to refresh\" on a file the user never had.\n\treturn withTail({\n\t\tpart: { type: 'link', label: truncateLabelForDisplay(urlLabel), fullLabel: urlLabel, href: originalHref, expired: false },\n\t});\n}\n\nexport function truncateLabelForDisplay(label: string): string {\n\tif (!label) return label;\n\tif (label.length <= LINK_LABEL_MAX_DISPLAY_CHARS) return label;\n\treturn '…' + label.slice(label.length - (LINK_LABEL_MAX_DISPLAY_CHARS - 1));\n}\n","/**\n * Token-budgeting (pure). Moved verbatim from the chatbox. Constants are shared\n * module-level values (identical in both consumers); a config knob is premature.\n * buildBoundedChatMessages now takes `serviceId` in its options so it can pass it\n * to sanitizeAttachmentLinksForHistory (which used to read a global).\n */\nimport { sanitizeAttachmentLinksForHistory } from './links';\n\nexport var CONTEXT_WINDOW_DEFAULT: Record<string, number> = { claude: 200000, openai: 128000 };\n// Exact model ids first, then family keys (see getContextWindow: a suffixed id\n// falls back to its family rather than to the platform default). Claude figures\n// come from Anthropic's published model table; `max_input_tokens` from\n// /v1/models overrides all of this at runtime when a listing has been seen.\n// 'claude-opus-4-7' read 200000 here, which was wrong by 5x, and the default\n// Claude model 'claude-sonnet-4-6' was absent entirely so it fell through to\n// CONTEXT_WINDOW_DEFAULT.claude. Neither was observable, because the history\n// budget and the Claude per-request cap below bind long before the window does.\nexport var CONTEXT_WINDOW_BY_MODEL: Record<string, number> = {\n\t// exact ids\n\t'claude-opus-5': 1000000, 'claude-opus-4-8': 1000000, 'claude-opus-4-7': 1000000,\n\t'claude-sonnet-5': 1000000, 'claude-sonnet-4-6': 1000000, 'claude-sonnet-4': 200000,\n\t'claude-haiku-4-5': 200000, 'gpt-5.4': 128000, 'gpt-5.6-luna': 128000,\n\t// family keys\n\t'claude-opus': 1000000, 'claude-sonnet': 1000000, 'claude-haiku': 200000,\n\t'gpt-5.6': 128000, 'gpt-5': 128000,\n};\n\n// Context windows reported by a provider's own models listing, keyed by model id.\n// Anthropic's GET /v1/models returns `max_input_tokens` per model, which is the\n// authoritative context window; OpenAI's listing carries no equivalent field, so\n// OpenAI models resolve from the table above. Populated by\n// registerModelContextWindows() when a client fetches its model list.\nvar apiReportedContextWindows: Record<string, number> = {};\n\n/**\n * Record context windows from a provider models listing. Accepts the raw list\n * items and reads `max_input_tokens` (Anthropic); items without it are skipped,\n * so passing an OpenAI listing is a no-op rather than an error.\n */\nexport function registerModelContextWindows(models: Array<{ id?: string; max_input_tokens?: number }> | null | undefined): void {\n\tif (!Array.isArray(models)) return;\n\tfor (var i = 0; i < models.length; i++) {\n\t\tvar m = models[i];\n\t\tvar id = (m && m.id ? String(m.id) : '').trim().toLowerCase();\n\t\tvar reported = m ? Number(m.max_input_tokens) : NaN;\n\t\tif (id && Number.isFinite(reported) && reported > 0) {\n\t\t\tapiReportedContextWindows[id] = Math.floor(reported);\n\t\t}\n\t}\n}\n\n/** Per-project override, keyed by service id. Set from the project settings. */\nvar projectContextWindows: Record<string, number> = {};\n\nexport function setProjectContextWindow(serviceId: string, tokens: number | null | undefined): void {\n\tvar key = (serviceId || '').trim();\n\tif (!key) return;\n\tvar n = Number(tokens);\n\tif (Number.isFinite(n) && n > 0) projectContextWindows[key] = Math.floor(n);\n\telse delete projectContextWindows[key];\n}\n\nexport function getProjectContextWindow(serviceId: string): number | null {\n\tvar key = (serviceId || '').trim();\n\treturn key && projectContextWindows[key] ? projectContextWindows[key] : null;\n}\nexport var OUTPUT_TOKEN_RESERVE = 22000;\nexport var TOOL_AND_RESPONSE_BUFFER = 4000;\nexport var MIN_INPUT_TOKEN_BUDGET = 8000;\nexport var CLAUDE_PER_REQUEST_INPUT_CAP = 28000;\nexport var MAX_HISTORY_MESSAGES = 20;\nexport var HISTORY_TOKEN_BUDGET = 8000;\n// Ratios that scale the two ceilings above off the resolved context window.\n// Calibrated to reproduce the previous fixed values at the default windows:\n// claude 200000 -> cap 27840 (was 28000, so the 28000 floor holds), and\n// openai 128000 -> history 8160 (~the previous 8000). Both are floored at the\n// old constants, so these can only ever raise a budget, never lower one.\nexport var CLAUDE_INPUT_CAP_RATIO = 0.16;\nexport var HISTORY_BUDGET_RATIO = 0.08;\n\nexport function estimateTextTokens(text: string): number {\n\treturn Math.ceil((text || '').length / 3);\n}\n\nexport function estimateMessageTokens(msg: { role: string; content: string }): number {\n\treturn estimateTextTokens(msg.content) + estimateTextTokens(msg.role) + 6;\n}\n\n/**\n * Resolve a model's context window, most specific source first:\n * 1. per-project override (project settings)\n * 2. the provider's own models listing (Anthropic `max_input_tokens`)\n * 3. an exact entry in CONTEXT_WINDOW_BY_MODEL\n * 4. a family entry, by dropping trailing '-' segments off the id\n * 5. the platform default\n *\n * Step 4 is why a new or suffixed id no longer drops straight to the platform\n * default: 'gpt-5.6-luna' resolves via 'gpt-5.6', and a dated Claude snapshot\n * such as 'claude-opus-4-7-20260101' resolves via 'claude-opus-4-7'. The walk\n * stops at the first hit, so a more specific entry always wins over its family.\n */\nexport function getContextWindow(platform: string, model?: string, serviceId?: string): number {\n\tvar override = serviceId ? getProjectContextWindow(serviceId) : null;\n\tif (override) return override;\n\n\tvar normalized = (model || '').trim().toLowerCase();\n\tif (normalized) {\n\t\tif (apiReportedContextWindows[normalized]) return apiReportedContextWindows[normalized];\n\t\tif (CONTEXT_WINDOW_BY_MODEL[normalized]) return CONTEXT_WINDOW_BY_MODEL[normalized];\n\n\t\tvar parts = normalized.split('-');\n\t\tfor (var end = parts.length - 1; end > 0; end--) {\n\t\t\tvar family = parts.slice(0, end).join('-');\n\t\t\tif (CONTEXT_WINDOW_BY_MODEL[family]) return CONTEXT_WINDOW_BY_MODEL[family];\n\t\t}\n\t}\n\treturn CONTEXT_WINDOW_DEFAULT[platform];\n}\n\nexport function stripFileBlocksFromHistory(content: string): string {\n\tif (!content) return content;\n\treturn content.replace(/```([^\\n`]+?\\.[^\\s.`]+)\\n[\\s\\S]*?```/g, '[file previously attached: $1]');\n}\n\nexport type BoundedChatOptions = {\n\tplatform: string;\n\tmodel?: string;\n\tsystemPrompt: string;\n\thistory: Array<{ role: string; content: string }>;\n\t/** Used to strip/rewrite expired attachment links in older user turns. */\n\tserviceId: string;\n};\n\nexport function buildBoundedChatMessages(options: BoundedChatOptions) {\n\tvar contextWindow = getContextWindow(options.platform, options.model, options.serviceId);\n\tvar contextBasedBudget = Math.max(MIN_INPUT_TOKEN_BUDGET,\n\t\tcontextWindow - OUTPUT_TOKEN_RESERVE - TOOL_AND_RESPONSE_BUFFER);\n\t// Scaling is gated on an EXPLICIT per-project window set from project\n\t// settings. Without one, the fixed ceilings apply exactly as before, so every\n\t// existing project keeps byte-identical behavior and nobody's token spend\n\t// moves because a table value was corrected. With one, the Claude per-request\n\t// cap and the history budget scale off the window, so raising it genuinely\n\t// sends more history instead of being absorbed by a hardcoded ceiling.\n\t// Both derive from contextBasedBudget (pre-Claude-cap) so the two platforms\n\t// scale symmetrically rather than the Claude cap compounding the ratio down.\n\tvar scaled = !!(options.serviceId && getProjectContextWindow(options.serviceId));\n\tvar claudeInputCap = scaled\n\t\t? Math.max(CLAUDE_PER_REQUEST_INPUT_CAP, Math.round(contextBasedBudget * CLAUDE_INPUT_CAP_RATIO))\n\t\t: CLAUDE_PER_REQUEST_INPUT_CAP;\n\tvar availableInputBudget = options.platform === 'claude'\n\t\t? Math.min(contextBasedBudget, claudeInputCap) : contextBasedBudget;\n\tvar systemCost = estimateTextTokens(options.systemPrompt) + 12;\n\tvar historyAllowance = scaled\n\t\t? Math.max(HISTORY_TOKEN_BUDGET, Math.round(contextBasedBudget * HISTORY_BUDGET_RATIO))\n\t\t: HISTORY_TOKEN_BUDGET;\n\tvar budgetForHistory = Math.max(1000, Math.min(historyAllowance, availableInputBudget - systemCost));\n\t// The message count scales alongside the token budget; otherwise 20 messages\n\t// is a second ceiling that swallows the extra budget on a raised window.\n\tvar maxHistoryMessages = scaled\n\t\t? Math.max(MAX_HISTORY_MESSAGES, Math.round(MAX_HISTORY_MESSAGES * (budgetForHistory / HISTORY_TOKEN_BUDGET)))\n\t\t: MAX_HISTORY_MESSAGES;\n\tvar windowed = options.history.slice(-maxHistoryMessages);\n\tvar latestIndex = windowed.length - 1;\n\tvar trimmed = windowed.map(function (m, i) {\n\t\tif (i === latestIndex) return m;\n\t\tvar stripped = stripFileBlocksFromHistory(m.content);\n\t\t// Sanitize BOTH roles: user turns via the \"Attached files:\" block, assistant\n\t\t// turns via the safe db-only path (forAssistant=true) so a volatile db url the\n\t\t// model emitted doesn't get replayed into the LLM context as a dead link.\n\t\tvar sanitized = sanitizeAttachmentLinksForHistory(stripped, options.serviceId, m.role !== 'user');\n\t\treturn Object.assign({}, m, { content: sanitized });\n\t});\n\tvar bounded: Array<{ role: string; content: string }> = [], used = 0;\n\tfor (var i = trimmed.length - 1; i >= 0; i--) {\n\t\tvar cost = estimateMessageTokens(trimmed[i]);\n\t\tif (used + cost > budgetForHistory && bounded.length > 0) break;\n\t\tbounded.unshift(trimmed[i]); used += cost;\n\t}\n\treturn {\n\t\tmessages: bounded.map(function (m) { return { role: m.role, content: m.content }; }),\n\t\tdroppedCount: Math.max(0, options.history.length - bounded.length),\n\t\testimatedInputTokens: used + systemCost,\n\t\testimatedBudget: availableInputBudget,\n\t};\n}\n","/**\n * How a text file the chat offers as a download is encoded and labelled, so that\n * whatever opens it reads the characters correctly, in any language.\n *\n * When the model answers with a fenced ```name.ext block, the client turns that\n * block into a Blob and an <a download>. We always write UTF-8, but several very\n * common consumers do not assume UTF-8 when nothing in the file says so, and fall\n * back to the reader's local ANSI codepage: CP949 in Korea, CP932 in Japan,\n * CP936/CP950 in China and Taiwan, CP1251 for Cyrillic. The file is valid and\n * every non-ASCII character still opens as mojibake.\n *\n * There is no single fix, because the way a file declares \"this is UTF-8\" is a\n * property of the FORMAT:\n *\n * - a spreadsheet (csv/tsv) and a Windows text editor read a BOM;\n * - HTML is opened from disk with no HTTP headers, so only an in-document\n * <meta charset> survives;\n * - XML carries its encoding in its declaration, and a WRONG declaration makes\n * a conforming parser fail outright;\n * - RTF is 7-bit, so non-ASCII has to be escaped into \\uNNNN?;\n * - JSON, JSONL and YAML are UTF-8 by specification, and a BOM BREAKS them.\n *\n * Anything unrecognised is left byte-for-byte alone: an unknown extension is far\n * more likely to be machine-parsed, where an uninvited BOM is a new bug, than to\n * be opened by a legacy editor.\n *\n * MIRROR of skapi-mcp/download-encoding.js, which does the same job for files the\n * server publishes (writeReport / exportRecordsToFile). A file the user gets from\n * a fenced block and the same file published as a download must behave\n * identically, so the two have to change together.\n */\n\nexport const BOM = '';\n\n/** Files a spreadsheet or a Windows text editor opens directly. */\nexport const BOM_EXTS = new Set(['csv', 'tsv', 'tab', 'txt', 'text', 'log']);\n\n/** Read from disk with no HTTP headers, so the declaration must be in the file. */\nexport const HTML_EXTS = new Set(['html', 'htm', 'xhtml']);\nexport const XML_EXTS = new Set(['xml', 'svg', 'rss', 'atom', 'xsl', 'xslt', 'plist', 'kml']);\nexport const RTF_EXTS = new Set(['rtf']);\n\n/** Content types by extension. Every text family carries an explicit charset. */\nexport const EXT_CONTENT_TYPES: Record<string, string> = {\n\tcsv: 'text/csv; charset=utf-8',\n\ttsv: 'text/tab-separated-values; charset=utf-8',\n\ttab: 'text/tab-separated-values; charset=utf-8',\n\ttxt: 'text/plain; charset=utf-8',\n\ttext: 'text/plain; charset=utf-8',\n\tlog: 'text/plain; charset=utf-8',\n\tmd: 'text/markdown; charset=utf-8',\n\tmarkdown: 'text/markdown; charset=utf-8',\n\tjson: 'application/json; charset=utf-8',\n\tjsonl: 'application/x-ndjson; charset=utf-8',\n\tndjson: 'application/x-ndjson; charset=utf-8',\n\tgeojson: 'application/geo+json; charset=utf-8',\n\tyaml: 'text/yaml; charset=utf-8',\n\tyml: 'text/yaml; charset=utf-8',\n\ttoml: 'text/plain; charset=utf-8',\n\tini: 'text/plain; charset=utf-8',\n\tsql: 'text/plain; charset=utf-8',\n\thtml: 'text/html; charset=utf-8',\n\thtm: 'text/html; charset=utf-8',\n\txhtml: 'application/xhtml+xml; charset=utf-8',\n\txml: 'application/xml; charset=utf-8',\n\tsvg: 'image/svg+xml; charset=utf-8',\n\tcss: 'text/css; charset=utf-8',\n\tjs: 'text/javascript; charset=utf-8',\n\tts: 'text/plain; charset=utf-8',\n\tpy: 'text/x-python; charset=utf-8',\n\tsh: 'text/x-shellscript; charset=utf-8',\n\tsrt: 'application/x-subrip; charset=utf-8',\n\tvtt: 'text/vtt; charset=utf-8',\n\tics: 'text/calendar; charset=utf-8',\n\tvcf: 'text/vcard; charset=utf-8',\n\t// RTF is 7-bit ASCII by specification, so it takes no charset parameter.\n\trtf: 'application/rtf',\n\t// Binary types the model can only ever REFERENCE, never author in a fence, but\n\t// which keep the type sensible if one ever shows up.\n\tpdf: 'application/pdf',\n\tpng: 'image/png',\n\tjpg: 'image/jpeg',\n\tjpeg: 'image/jpeg',\n\tgif: 'image/gif',\n\twebp: 'image/webp',\n};\n\nexport type EncodingClass = 'bom' | 'html' | 'xml' | 'rtf' | 'none';\n\nexport function normalizeExt(ext: string | null | undefined): string {\n\treturn String(ext || '').trim().replace(/^\\./, '').toLowerCase();\n}\n\n/** Extension of a filename, '' when it has none. */\nexport function extOf(filename: string | null | undefined): string {\n\tconst name = String(filename || '');\n\tconst dot = name.lastIndexOf('.');\n\treturn dot > 0 ? normalizeExt(name.slice(dot + 1)) : '';\n}\n\n/** Which encoding declaration this format understands. */\nexport function encodingClassForExt(ext: string | null | undefined): EncodingClass {\n\tconst e = normalizeExt(ext);\n\tif (BOM_EXTS.has(e)) return 'bom';\n\tif (HTML_EXTS.has(e)) return 'html';\n\tif (XML_EXTS.has(e)) return 'xml';\n\tif (RTF_EXTS.has(e)) return 'rtf';\n\treturn 'none';\n}\n\n/** True when a file with this extension must be written BOM-first. */\nexport function needsBomForExt(ext: string | null | undefined): boolean {\n\treturn encodingClassForExt(ext) === 'bom';\n}\n\n/**\n * Content type to declare. Everything textual carries an explicit charset:\n * without one the receiving end guesses, and it guesses the local codepage.\n */\nexport function contentTypeForExt(\n\text: string | null | undefined,\n\tfallback = 'text/plain; charset=utf-8',\n): string {\n\treturn EXT_CONTENT_TYPES[normalizeExt(ext)] || fallback;\n}\n\nexport function hasBom(text: string): boolean {\n\treturn typeof text === 'string' && text.charCodeAt(0) === 0xfeff;\n}\n\n// --- HTML -------------------------------------------------------------------\n// Only the document head is inspected. A charset written further down is not one\n// a browser would act on anyway (the spec only honours a declaration in the first\n// 1024 bytes), and scanning the whole body would start matching <meta> tags that\n// a document about HTML is merely quoting.\nexport const HTML_HEAD_WINDOW = 4096;\nconst META_CHARSET_RE = /<meta[^>]+charset\\s*=\\s*[\"']?\\s*([a-z0-9_-]+)/i;\nconst META_HTTP_EQUIV_RE = /<meta[^>]+http-equiv\\s*=\\s*[\"']?content-type[\"']?[^>]*>/i;\n\n/**\n * Make an HTML document state its own encoding. Downloaded HTML is opened from\n * disk, where the Content-Type we set no longer exists, so a document with no\n * <meta charset> is decoded with the browser's locale default.\n */\nexport function ensureHtmlCharset(text: string): string {\n\tconst src = String(text == null ? '' : text);\n\tconst head = src.slice(0, HTML_HEAD_WINDOW);\n\n\tconst declared = META_CHARSET_RE.exec(head);\n\tif (declared) {\n\t\t// A declaration naming anything other than UTF-8 is actively wrong: the\n\t\t// bytes underneath it are always UTF-8. Correct it in place rather than\n\t\t// adding a second, contradictory one.\n\t\tif (declared[1].toLowerCase().replace(/[^a-z0-9]/g, '') === 'utf8') return src;\n\t\tconst start = declared.index + declared[0].length - declared[1].length;\n\t\treturn src.slice(0, start) + 'utf-8' + src.slice(start + declared[1].length);\n\t}\n\t// An http-equiv Content-Type with no charset= is still a declaration the\n\t// browser will use; replace the whole tag with the modern short form.\n\tconst httpEquiv = META_HTTP_EQUIV_RE.exec(head);\n\tif (httpEquiv) {\n\t\treturn src.slice(0, httpEquiv.index)\n\t\t\t+ '<meta charset=\"utf-8\">'\n\t\t\t+ src.slice(httpEquiv.index + httpEquiv[0].length);\n\t}\n\n\tconst tag = '<meta charset=\"utf-8\">';\n\t// As early as the document allows: inside <head> if there is one, else right\n\t// after <html>, else at the very top (a fragment is still parsed head-first).\n\tconst headOpen = /<head[^>]*>/i.exec(head);\n\tif (headOpen) {\n\t\tconst at = headOpen.index + headOpen[0].length;\n\t\treturn src.slice(0, at) + '\\n' + tag + src.slice(at);\n\t}\n\tconst htmlOpen = /<html[^>]*>/i.exec(head);\n\tif (htmlOpen) {\n\t\tconst at = htmlOpen.index + htmlOpen[0].length;\n\t\treturn src.slice(0, at) + '\\n<head>' + tag + '</head>' + src.slice(at);\n\t}\n\tconst doctype = /<!doctype[^>]*>/i.exec(head);\n\tif (doctype) {\n\t\tconst at = doctype.index + doctype[0].length;\n\t\treturn src.slice(0, at) + '\\n' + tag + src.slice(at);\n\t}\n\treturn tag + '\\n' + src;\n}\n\n// --- XML ---------------------------------------------------------------------\nconst XML_DECL_RE = /^\\s*<\\?xml\\s[^?]*\\?>/i;\n\n/**\n * Correct an XML declaration that names the wrong encoding.\n *\n * A MISSING declaration is left alone on purpose: XML with none is UTF-8 by\n * specification, so every conforming parser already gets it right. A declaration\n * naming EUC-KR over UTF-8 bytes, on the other hand, makes a parser fail outright.\n */\nexport function ensureXmlEncoding(text: string): string {\n\tconst src = String(text == null ? '' : text);\n\tconst decl = XML_DECL_RE.exec(src);\n\tif (!decl) return src;\n\n\tconst found = /encoding\\s*=\\s*[\"']([^\"']*)[\"']/i.exec(decl[0]);\n\tif (!found) return src; // declaration without an encoding is UTF-8 by spec\n\tif (found[1].toLowerCase().replace(/[^a-z0-9]/g, '') === 'utf8') return src;\n\n\tconst fixedDecl = decl[0].slice(0, found.index)\n\t\t+ found[0].replace(found[1], 'UTF-8')\n\t\t+ decl[0].slice(found.index + found[0].length);\n\treturn fixedDecl + src.slice(decl[0].length);\n}\n\n// --- RTF ----------------------------------------------------------------------\nconst RTF_SIGNATURE_RE = /^[\\s]*\\{\\\\rtf/i;\n\n/** True when the body really is RTF rather than text merely named .rtf. */\nexport function looksLikeRtf(text: string): boolean {\n\treturn RTF_SIGNATURE_RE.test(String(text == null ? '' : text));\n}\n\n/**\n * Escape every non-ASCII character into RTF's \\uNNNN? form.\n *\n * RTF is 7-bit: a literal UTF-8 byte in the body is read through the codepage the\n * header declares, which is how Korean, Japanese and Cyrillic RTF turns to\n * mojibake in Word. \\uNNNN? is codepage-independent.\n *\n * ASCII is never touched, which matters: backslashes and braces in an RTF body\n * are control syntax, and \"escaping\" them would destroy the document. \\u takes a\n * SIGNED 16-bit value, so anything above 0x7FFF is emitted negative, and astral\n * characters are emitted as their two surrogates.\n */\nexport function escapeRtfNonAscii(text: string): string {\n\tconst src = String(text == null ? '' : text);\n\tlet out = '';\n\tlet plainFrom = 0;\n\tfor (let i = 0; i < src.length; i++) {\n\t\tconst code = src.charCodeAt(i); // UTF-16 unit: surrogates arrive separately\n\t\tif (code < 0x80) continue;\n\t\tout += src.slice(plainFrom, i);\n\t\tout += `\\\\u${code > 32767 ? code - 65536 : code}?`;\n\t\tplainFrom = i + 1;\n\t}\n\treturn plainFrom === 0 ? src : out + src.slice(plainFrom);\n}\n\n/** Apply the format's encoding declaration to a whole document. */\nexport function applyEncodingDeclaration(text: string, ext: string | null | undefined): string {\n\tconst src = String(text == null ? '' : text);\n\tswitch (encodingClassForExt(ext)) {\n\t\tcase 'bom':\n\t\t\t// Never a second BOM: two U+FEFF show as a visible in the first cell.\n\t\t\treturn hasBom(src) ? src : BOM + src;\n\t\tcase 'html':\n\t\t\treturn ensureHtmlCharset(src);\n\t\tcase 'xml':\n\t\t\treturn ensureXmlEncoding(src);\n\t\tcase 'rtf':\n\t\t\t// Text merely NAMED .rtf is opened by Word as plain text, where a BOM is\n\t\t\t// what makes it read UTF-8. Escaping it would show literal \\u escapes.\n\t\t\treturn looksLikeRtf(src) ? escapeRtfNonAscii(src) : (hasBom(src) ? src : BOM + src);\n\t\tdefault:\n\t\t\treturn src;\n\t}\n}\n\n/**\n * Everything a client needs to turn a fenced ```name.ext block into a download:\n * the exact text to put in the Blob and the type to give it.\n */\nexport function prepareDownloadText(\n\tfilename: string,\n\tbody: string,\n): { ext: string; text: string; contentType: string } {\n\tconst ext = extOf(filename);\n\treturn {\n\t\text,\n\t\ttext: applyEncodingDeclaration(body, ext),\n\t\tcontentType: contentTypeForExt(ext),\n\t};\n}\n","/**\n * Chat timestamp formatting, shared so agent.vue and the widget render an\n * identical \"small text under the bubble\". Pure and locale-aware: it formats a\n * given epoch-ms value, it never reads the current time, so it stays testable and\n * DOM-free.\n */\n\n/** Wall-clock epoch ms. Separate from the engine's monotonic nowMs() (which is\n * performance.now() when available and therefore NOT epoch): a displayed\n * timestamp must be wall time. */\nexport function wallClockNow(): number {\n\treturn Date.now();\n}\n\n/**\n * \"Jul 24, 2026, 3:42:07 PM\" (locale-formatted). Empty string for a missing or\n * non-finite value, so a caller can gate rendering on the result being truthy and\n * a pending bubble (no timestamp yet) simply shows nothing.\n */\nexport function formatChatTimestamp(ms?: number): string {\n\tif (typeof ms !== 'number' || !isFinite(ms) || ms <= 0) return '';\n\ttry {\n\t\treturn new Date(ms).toLocaleString(undefined, {\n\t\t\tyear: 'numeric',\n\t\t\tmonth: 'short',\n\t\t\tday: 'numeric',\n\t\t\thour: 'numeric',\n\t\t\tminute: '2-digit',\n\t\t\tsecond: '2-digit',\n\t\t});\n\t} catch (e) {\n\t\treturn '';\n\t}\n}\n","/**\n * The `ai_agent` service option, parsed and serialized in ONE place.\n *\n * Stored on the skapi service record as up to three '#'-delimited segments:\n *\n * none AI chat disabled\n * claude platform chosen, no model saved yet\n * claude#claude-sonnet-4-6 platform + model\n * claude#claude-sonnet-4-6#400000 platform + model + context-window override\n *\n * The third segment is new and optional, so every value written before it\n * existed parses unchanged with `contextWindow: null`. Nothing writes a third\n * segment without a model, because the window is meaningless without one.\n *\n * This lived as four separate copies (agent.vue, dbfile.vue, service.vue, and\n * the widget's index.js), which is how the format drifts. New callers should\n * import from here rather than re-deriving the split.\n */\n\nexport type AiAgentPlatform = 'claude' | 'openai' | null;\n\nexport type ParsedAiAgent = {\n\t/** null when unset or explicitly 'none'. */\n\tplatform: AiAgentPlatform;\n\t/** '' when no model has been saved. */\n\tmodel: string;\n\t/** Per-project context-window override in tokens, or null to use the model's. */\n\tcontextWindow: number | null;\n\t/** True when a real platform is configured (i.e. not unset and not 'none'). */\n\thasPlatform: boolean;\n};\n\nfunction normalizePlatform(raw: string): AiAgentPlatform {\n\tvar p = (raw || '').trim().toLowerCase();\n\treturn p === 'claude' || p === 'openai' ? p : null;\n}\n\nexport function parseAiAgentValue(value: string | null | undefined): ParsedAiAgent {\n\tvar raw = (value || '').trim();\n\tif (!raw || raw.toLowerCase() === 'none') {\n\t\treturn { platform: null, model: '', contextWindow: null, hasPlatform: false };\n\t}\n\n\t// Split into at most three parts so a '#' inside a model id (none today, but\n\t// the delimiter should not be load-bearing on the tail) cannot shift fields.\n\tvar firstHash = raw.indexOf('#');\n\tif (firstHash === -1) {\n\t\tvar only = normalizePlatform(raw);\n\t\treturn { platform: only, model: '', contextWindow: null, hasPlatform: !!only };\n\t}\n\n\tvar platform = normalizePlatform(raw.slice(0, firstHash));\n\tvar rest = raw.slice(firstHash + 1);\n\tvar secondHash = rest.indexOf('#');\n\tvar model = (secondHash === -1 ? rest : rest.slice(0, secondHash)).trim();\n\tvar windowRaw = secondHash === -1 ? '' : rest.slice(secondHash + 1).trim();\n\n\tvar parsedWindow = windowRaw ? Number(windowRaw) : NaN;\n\tvar contextWindow = Number.isFinite(parsedWindow) && parsedWindow > 0\n\t\t? Math.floor(parsedWindow)\n\t\t: null;\n\n\treturn { platform: platform, model: model, contextWindow: contextWindow, hasPlatform: !!platform };\n}\n\nexport function buildAiAgentValue(\n\tplatform: string | null | undefined,\n\tmodel?: string | null,\n\tcontextWindow?: number | null,\n): string {\n\tvar p = (platform || '').trim().toLowerCase();\n\tif (!p || p === 'none') return 'none';\n\n\tvar m = (model || '').trim();\n\tif (!m) return p;\n\n\tvar n = Number(contextWindow);\n\tif (!Number.isFinite(n) || n <= 0) return p + '#' + m;\n\treturn p + '#' + m + '#' + Math.floor(n);\n}\n","/**\n * AI request builders + dispatch transport (framework-agnostic).\n *\n * Ported from www.skapi.com/src/code/ai_agent.ts. The only changes vs the\n * original are dependency-injection seams:\n * - `skapi.clientSecretRequest*` -> chatEngineConfig().clientSecretRequest*\n * - MCP endpoint URL -> chatEngineConfig().mcpBaseUrl\n * - `poll` on each request -> pollOpt() (set per consumer; see config.ts)\n * - Vue `reactive`/`ref` removed (bgTaskQueue/agentViewMounted are app-level\n * state that stays in the consumer, not here;\n * only the BgTaskEntry TYPE lives here)\n */\nimport { buildIndexingSystemPrompt, buildIndexingUserMessage, buildIndexingContinueMessage, buildIndexingRenderMessage, buildIndexingRenderContinueTemplate, buildIndexingWindowMessage } from './prompts';\nimport { isServerExtractable, isPagedReadFile, isImageVisionFile, isWindowedReadFile, makeExtractPlaceholder, makeRenderPlaceholder, makeWindowPlaceholder, RENDER_PAGES_PER_WINDOW, type ExtractDirective, type FileUrlDirective } from './office';\nimport { chatEngineConfig, pollOpt, windowedIndexingEnabled } from './config';\n\nexport const ANTHROPIC_MESSAGES_API_URL = 'https://api.anthropic.com/v1/messages';\nconst ANTHROPIC_MODELS_API_URL = 'https://api.anthropic.com/v1/models';\nconst ANTHROPIC_VERSION = '2023-06-01';\nconst ANTHROPIC_MCP_BETA = 'mcp-client-2025-11-20';\nconst ANTHROPIC_WEB_FETCH_BETA = 'web-fetch-2025-09-10';\nconst ANTHROPIC_PROMPT_CACHING_BETA = 'prompt-caching-2024-07-31';\nconst ANTHROPIC_BETA_HEADER = `${ANTHROPIC_MCP_BETA},${ANTHROPIC_WEB_FETCH_BETA},${ANTHROPIC_PROMPT_CACHING_BETA}`;\nconst WEB_FETCH_MAX_USES = 40;\nconst WEB_FETCH_MAX_CONTENT_TOKENS = 200000;\n\nexport const OPENAI_RESPONSES_API_URL = 'https://api.openai.com/v1/responses';\nconst OPENAI_MODELS_API_URL = 'https://api.openai.com/v1/models';\nconst MAX_TOKENS = 25000;\nconst DEFAULT_OPENAI_IMAGE_DETAIL = 'auto';\nconst OPENAI_WEB_SEARCH_ENABLED = true;\nconst OPENAI_WEB_SEARCH_EXTERNAL_WEB_ACCESS = true;\nexport const MCP_NAME = 'BunnyQuery';\n\nexport const DEFAULT_CLAUDE_MODEL = 'claude-sonnet-4-6';\nexport const DEFAULT_OPENAI_MODEL = 'gpt-5.6-luna';\n\nconst mcpUrl = () => chatEngineConfig().mcpBaseUrl;\nconst clientSecretRequest = (opts: any) => chatEngineConfig().clientSecretRequest(opts);\n\n// Resolve the per-image `detail` for OpenAI. The version match tolerates a\n// trailing variant/date suffix (`gpt-5.4-nano`, `-mini`, `-2026-01-01`, …):\n// previously the pattern was anchored with no suffix allowed, so EVERY suffixed\n// model silently fell through to 'auto' — i.e. the cheap tiers that most need\n// resolution were the ones getting downsampled images.\n//\n// Base models keep their exact previous behavior ('original'). A suffixed\n// variant resolves to 'high' rather than 'original': 'high' is the universally\n// supported value, and we have no way to confirm a given variant accepts\n// 'original' — sending an unsupported value would fail the whole request, which\n// is far worse than a slightly less detailed image.\nconst getOpenAIImageDetail = (model?: string) => {\n\tconst normalized = (model || DEFAULT_OPENAI_MODEL).trim().toLowerCase();\n\tconst match = normalized.match(/^gpt-(\\d+)(?:\\.(\\d+))?(-[a-z0-9.\\-]+)?$/);\n\tif (!match) {\n\t\treturn DEFAULT_OPENAI_IMAGE_DETAIL;\n\t}\n\n\tconst major = Number(match[1]);\n\tconst minor = match[2] === undefined ? null : Number(match[2]);\n\tconst isVariant = !!match[3];\n\n\tconst supportsOriginal = major > 5 || (major === 5 && minor !== null && minor >= 4);\n\tif (!supportsOriginal) {\n\t\treturn DEFAULT_OPENAI_IMAGE_DETAIL;\n\t}\n\n\treturn isVariant ? 'high' : 'original';\n};\n\n// Per-image `detail` for WORKER-RENDERED document pages (the `_skapi_render`\n// path). Same resolution as above with one difference: these are dense scans\n// whose entire purpose is to be read, so 'auto' is never acceptable — it lets\n// the API downsample exactly the pixels the model needs to OCR. Floor it at\n// 'high'; models that support full-resolution 'original' still get it.\n//\n// Without this the worker falls back to its own model-blind default ('high'),\n// which silently denies the strongest models the 'original' detail they support.\nconst getRenderImageDetail = (model?: string) => {\n\tconst detail = getOpenAIImageDetail(model);\n\treturn detail === DEFAULT_OPENAI_IMAGE_DETAIL ? 'high' : detail;\n};\n\nexport type ClaudeRole = 'user' | 'assistant';\n\nexport type ClaudeMessage = {\n\trole: ClaudeRole;\n\tcontent: string;\n};\n\nexport type OpenAIMessage = {\n\trole: ClaudeRole;\n\tcontent: string;\n};\n\nexport type ClaudeMcpToolConfig = {\n\tenabled?: boolean;\n\tdefer_loading?: boolean;\n};\n\nexport type ClaudeMcpServerRequest = {\n\tname: string;\n\turl: string;\n\tauthorizationToken?: string;\n\tdefaultConfig?: ClaudeMcpToolConfig;\n\tconfigs?: Record<string, ClaudeMcpToolConfig>;\n};\n\nconst IMAGE_URL_REGEX =\n\t/\\bhttps?:\\/\\/[^\\s<>\"'()\\[\\]]+?\\.(?:jpg|jpeg|png|gif|webp)(?:\\?[^\\s<>\"'()\\[\\]]*)?/gi;\n\nexport function transformContentWithImages(\n\tcontent: string,\n): string | Array<Record<string, any>> {\n\tif (typeof content !== 'string' || !content) {\n\t\treturn content;\n\t}\n\n\tconst matches = content.match(IMAGE_URL_REGEX);\n\n\tif (!matches || !matches.length) {\n\t\treturn content;\n\t}\n\n\tconst seen = new Set<string>();\n\tconst imageBlocks: Array<Record<string, any>> = [];\n\n\tfor (const url of matches) {\n\t\tif (seen.has(url)) continue;\n\t\tseen.add(url);\n\t\timageBlocks.push({\n\t\t\ttype: 'image',\n\t\t\tsource: { type: 'url', url },\n\t\t});\n\t}\n\n\treturn [...imageBlocks, { type: 'text', text: content }];\n}\n\nfunction prepareClaudeMessages(messages: ClaudeMessage[]) {\n\tif (!messages.length) return messages;\n\t// Only transform the most recent user message. Historical user messages\n\t// may reference image URLs that are now stale (deleted, moved, expired).\n\tconst lastIndex = messages.length - 1;\n\tconst last = messages[lastIndex];\n\tif (last.role !== 'user') return messages;\n\tconst content = transformContentWithImages(last.content);\n\tif (content === last.content) return messages;\n\tconst next = messages.slice();\n\tnext[lastIndex] = { role: last.role, content } as unknown as ClaudeMessage;\n\treturn next;\n}\n\nexport function transformContentWithOpenAIImages(\n\tcontent: string,\n\tdetail = DEFAULT_OPENAI_IMAGE_DETAIL,\n): string | Array<Record<string, any>> {\n\tif (typeof content !== 'string' || !content) {\n\t\treturn content;\n\t}\n\n\tconst matches = content.match(IMAGE_URL_REGEX);\n\n\tif (!matches || !matches.length) {\n\t\treturn content;\n\t}\n\n\tconst seen = new Set<string>();\n\tconst imageBlocks: Array<Record<string, any>> = [];\n\n\tfor (const url of matches) {\n\t\tif (seen.has(url)) continue;\n\t\tseen.add(url);\n\t\timageBlocks.push({\n\t\t\ttype: 'input_image',\n\t\t\timage_url: url,\n\t\t\tdetail,\n\t\t});\n\t}\n\n\treturn [{ type: 'input_text', text: content }, ...imageBlocks];\n}\n\nfunction prepareOpenAIMessages(\n\tmessages: OpenAIMessage[],\n\tdetail = DEFAULT_OPENAI_IMAGE_DETAIL,\n) {\n\tif (!messages.length) return messages;\n\tconst lastIndex = messages.length - 1;\n\tconst last = messages[lastIndex];\n\tif (last.role !== 'user') return messages;\n\tconst content = transformContentWithOpenAIImages(last.content, detail);\n\tif (content === last.content) return messages;\n\tconst next = messages.slice();\n\tnext[lastIndex] = { role: last.role, content } as unknown as OpenAIMessage;\n\treturn next;\n}\n\n// Attach a cache_control breakpoint to the last message of the stable history\n// prefix (everything except the final user turn) so Anthropic re-uses it at\n// ~10% input-token billing.\nfunction applyHistoryCacheBreakpoint(messages: any[]): any[] {\n\tif (messages.length < 2) return messages;\n\tconst breakpointIndex = messages.length - 2;\n\treturn messages.map((m, i) => {\n\t\tif (i !== breakpointIndex) return m;\n\t\tconst blocks = Array.isArray(m.content)\n\t\t\t? m.content.slice()\n\t\t\t: [{ type: 'text', text: m.content }];\n\t\tif (!blocks.length) return m;\n\t\tconst lastBlockIndex = blocks.length - 1;\n\t\tblocks[lastBlockIndex] = {\n\t\t\t...blocks[lastBlockIndex],\n\t\t\tcache_control: { type: 'ephemeral' },\n\t\t};\n\t\treturn { ...m, content: blocks };\n\t});\n}\n\nexport type CallClaudeWithMcpParams = {\n\tprompt: string;\n\tmessages?: ClaudeMessage[];\n\tservice: string;\n\towner: string;\n\tuserId?: string;\n\tmodel?: string;\n\tmaxTokens?: number;\n\tsystem?: string;\n\tmcpServer: ClaudeMcpServerRequest;\n\textractContent?: ExtractDirective[];\n\tfileUrls?: FileUrlDirective[];\n\tonResponse?: (res: any) => void;\n\tonError?: (err: any) => void;\n};\n// Poll cadence for every client-secret request the chat waits on. Shared by the\n// engine's own poll sites and imported by agent.vue; the widget carries its own\n// copy in src/index.js that must be kept in step.\nexport const POLL_INTERVAL = 3000;\nexport async function callClaudeWithMcp({\n\tprompt,\n\tmessages,\n\tservice,\n\towner,\n\tuserId,\n\tmodel = DEFAULT_CLAUDE_MODEL,\n\tmaxTokens = 1000,\n\tsystem,\n\tmcpServer,\n\textractContent,\n\tfileUrls,\n}: CallClaudeWithMcpParams) {\n\tconst mcpServerDefinition: Record<string, any> = {\n\t\ttype: 'url',\n\t\tname: mcpServer.name,\n\t\turl: mcpServer.url,\n\t};\n\n\tif (mcpServer.authorizationToken) {\n\t\tmcpServerDefinition.authorization_token = mcpServer.authorizationToken;\n\t}\n\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'claude',\n\t\tqueue: userId || service,\n\t\tservice,\n\t\towner,\n\t\t...pollOpt(),\n\t\turl: ANTHROPIC_MESSAGES_API_URL,\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'content-type': 'application/json',\n\t\t\t'x-api-key': '$CLIENT_SECRET',\n\t\t\t'anthropic-version': ANTHROPIC_VERSION,\n\t\t\t'anthropic-beta': ANTHROPIC_BETA_HEADER,\n\t\t},\n\t\tdata: {\n\t\t\tmodel,\n\t\t\tmax_tokens: maxTokens,\n\t\t\t...(extractContent && extractContent.length\n\t\t\t\t? { _skapi_extract: extractContent }\n\t\t\t\t: {}),\n\t\t\t...(fileUrls && fileUrls.length\n\t\t\t\t? { _skapi_file_urls: fileUrls }\n\t\t\t\t: {}),\n\t\t\t...(system\n\t\t\t\t? {\n\t\t\t\t\t\tsystem: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\ttext: system,\n\t\t\t\t\t\t\t\tcache_control: { type: 'ephemeral' },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\tmessages: (() => {\n\t\t\t\tconst prepared =\n\t\t\t\t\tmessages && messages.length\n\t\t\t\t\t\t? prepareClaudeMessages(messages)\n\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\trole: 'user',\n\t\t\t\t\t\t\t\t\tcontent: transformContentWithImages(prompt),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t];\n\t\t\t\treturn applyHistoryCacheBreakpoint(prepared as any[]);\n\t\t\t})(),\n\t\t\tmcp_servers: [mcpServerDefinition],\n\t\t\ttools: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'mcp_toolset',\n\t\t\t\t\tmcp_server_name: mcpServer.name,\n\t\t\t\t\t...(mcpServer.defaultConfig\n\t\t\t\t\t\t? { default_config: mcpServer.defaultConfig }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...(mcpServer.configs ? { configs: mcpServer.configs } : {}),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'web_fetch_20250910',\n\t\t\t\t\tname: 'web_fetch',\n\t\t\t\t\tmax_uses: WEB_FETCH_MAX_USES,\n\t\t\t\t\tcitations: { enabled: true },\n\t\t\t\t\tmax_content_tokens: WEB_FETCH_MAX_CONTENT_TOKENS,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t});\n}\n\nexport async function callClaudeWithPublicMcp(\n\tprompt: string,\n\tservice: string,\n\towner: string,\n\tmessages?: ClaudeMessage[],\n\tsystem?: string,\n\tmodel?: string,\n\tuserId?: string,\n\textractContent?: ExtractDirective[],\n\tfileUrls?: FileUrlDirective[],\n\tonResponse?: (res: any) => void,\n\tonError?: (err: any) => void,\n) {\n\treturn callClaudeWithMcp({\n\t\tprompt,\n\t\tmessages,\n\t\tservice,\n\t\towner,\n\t\tuserId,\n\t\tmodel: model || DEFAULT_CLAUDE_MODEL,\n\t\tmaxTokens: MAX_TOKENS,\n\t\tsystem,\n\t\textractContent,\n\t\tfileUrls,\n\t\tmcpServer: {\n\t\t\tname: MCP_NAME,\n\t\t\turl: mcpUrl(),\n\t\t\tauthorizationToken: '$ACCESS_TOKEN',\n\t\t},\n\t\tonResponse,\n\t\tonError,\n\t});\n}\n\nexport async function callOpenAIWithPublicMcp(\n\tprompt: string,\n\tservice: string,\n\towner: string,\n\tmessages?: OpenAIMessage[],\n\tsystem?: string,\n\tmodel?: string,\n\tuserId?: string,\n\textractContent?: ExtractDirective[],\n\tfileUrls?: FileUrlDirective[],\n\tonResponse?: (res: any) => void,\n\tonError?: (err: any) => void,\n) {\n\tconst resolvedModel = model || DEFAULT_OPENAI_MODEL;\n\tconst imageDetail = getOpenAIImageDetail(resolvedModel);\n\tconst messageList =\n\t\tmessages && messages.length\n\t\t\t? prepareOpenAIMessages(messages, imageDetail)\n\t\t\t: [\n\t\t\t\t{\n\t\t\t\t\trole: 'user' as const,\n\t\t\t\t\tcontent: transformContentWithOpenAIImages(prompt, imageDetail),\n\t\t\t\t},\n\t\t\t];\n\n\tconst responseInput = [\n\t\t...(system\n\t\t\t? [\n\t\t\t\t{\n\t\t\t\t\trole: 'system',\n\t\t\t\t\tcontent: system,\n\t\t\t\t},\n\t\t\t]\n\t\t\t: []),\n\t\t...messageList.map((m) => ({\n\t\t\trole: m.role,\n\t\t\tcontent: m.content,\n\t\t})),\n\t];\n\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'openai',\n\t\tqueue: userId || service,\n\t\tservice,\n\t\towner,\n\t\t...pollOpt(),\n\t\turl: OPENAI_RESPONSES_API_URL,\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'content-type': 'application/json',\n\t\t\tAuthorization: 'Bearer $CLIENT_SECRET',\n\t\t},\n\t\tdata: {\n\t\t\tmodel: resolvedModel,\n\t\t\tmax_output_tokens: MAX_TOKENS,\n\t\t\t...(extractContent && extractContent.length\n\t\t\t\t? { _skapi_extract: extractContent }\n\t\t\t\t: {}),\n\t\t\t...(fileUrls && fileUrls.length\n\t\t\t\t? { _skapi_file_urls: fileUrls }\n\t\t\t\t: {}),\n\t\t\tinput: responseInput,\n\t\t\ttools: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'mcp',\n\t\t\t\t\tserver_label: MCP_NAME,\n\t\t\t\t\tserver_url: mcpUrl(),\n\t\t\t\t\trequire_approval: 'never',\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: 'Bearer $ACCESS_TOKEN',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t...(OPENAI_WEB_SEARCH_ENABLED\n\t\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'web_search',\n\t\t\t\t\t\t\texternal_web_access: OPENAI_WEB_SEARCH_EXTERNAL_WEB_ACCESS,\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t\t: []),\n\t\t\t],\n\t\t},\n\t});\n}\n\nexport type AttachmentSaveInfo = {\n\tplatform: 'claude' | 'openai';\n\tmodel?: string;\n\tservice: string;\n\towner: string;\n\tuserId?: string;\n\tserviceName?: string;\n\tserviceDescription?: string;\n\tattachment: {\n\t\tname: string;\n\t\tstoragePath: string;\n\t\tmime?: string;\n\t\tsize?: number;\n\t\turl: string;\n\t};\n\t/**\n\t * Content parsed CLIENT-SIDE by an attachment-parser plugin (e.g. an .hwp\n\t * parser). When set, it is inlined into the indexing message verbatim and\n\t * takes precedence over server-side office extraction / web_fetch.\n\t */\n\tparsedContent?: string;\n\t/**\n\t * True for a RESUME pass: a previous indexing pass could not finish this (large)\n\t * file, so continue it - always via readFileContent paging, with a \"continue\"\n\t * message telling the agent to resume from where the saved records leave off.\n\t */\n\tcontinueIndexing?: boolean;\n\t/**\n\t * For an image-vision file (PDF), the 0-based PAGE the render window should start at.\n\t * The worker renders [renderFrom, renderFrom+RENDER_PAGES_PER_WINDOW) and injects them\n\t * as image blocks; the resume loop advances this by a window each pass.\n\t */\n\trenderFrom?: number;\n};\n\n// RESUME pass: continue indexing a large file a previous pass could not finish. Same\n// dispatch as notifyAgentSaveAttachment, but forced onto the paging path with a\n// \"continue from where the saved records leave off\" message.\nexport async function notifyAgentContinueIndexing(info: AttachmentSaveInfo) {\n\treturn notifyAgentSaveAttachment({ ...info, continueIndexing: true });\n}\n\n// Background \"save into knowledge\" call (not a chat turn). A client-parsed file\n// (parser plugin) is inlined directly; otherwise office files get the\n// _skapi_extract directive + a placeholder, and everything else gets a URL.\nexport async function notifyAgentSaveAttachment(info: AttachmentSaveInfo) {\n\tconst { platform, service, owner, attachment, parsedContent } = info;\n\n\t// A CONTINUE pass resumes a large file that a previous pass could not finish.\n\tconst continuing = !!info.continueIndexing;\n\n\t// VISION files (PDFs) are delivered as rendered page IMAGES injected into the message by\n\t// the worker (`_skapi_render`), because tool-result images render on neither provider.\n\t// Both the first pass and every resume pass use this; renderFrom advances the page window.\n\tconst visionFile = !parsedContent && isImageVisionFile(attachment.name, attachment.mime);\n\tconst renderFrom = Math.max(0, info.renderFrom || 0);\n\tconst renderPlaceholder = visionFile ? makeRenderPlaceholder(attachment.storagePath) : undefined;\n\t// Tell the worker what image `detail` to stamp on the injected page blocks.\n\t// The worker is model-blind, so without this it applies a one-size default and\n\t// the strongest models never get the 'original' detail they support. Only\n\t// meaningful for OpenAI — Claude has no per-image detail knob and the worker\n\t// ignores the field for it.\n\tconst renderDetail = platform === 'openai'\n\t\t? getRenderImageDetail(info.model || DEFAULT_OPENAI_MODEL)\n\t\t: undefined;\n\t// `auto_continue` + `continue_text` hand the page loop to the WORKER: when its renderer\n\t// reports pages left after this window, it builds the next pass from this template\n\t// (substituting the window's 1-based start page for RENDER_FROM_TOKEN) and enqueues it\n\t// itself. That is what makes a 500-page document index end-to-end — the loop no longer\n\t// depends on the tab staying open, nor on the model correctly declaring itself unfinished.\n\tconst skapiRender = visionFile && renderPlaceholder\n\t\t? {\n\t\t\t_skapi_render: [\n\t\t\t\t{\n\t\t\t\t\tpath: attachment.storagePath, from: renderFrom, count: RENDER_PAGES_PER_WINDOW,\n\t\t\t\t\tplaceholder: renderPlaceholder, name: attachment.name, mime: attachment.mime, detail: renderDetail,\n\t\t\t\t\tauto_continue: true,\n\t\t\t\t\tcontinue_text: buildIndexingRenderContinueTemplate(attachment, renderPlaceholder),\n\t\t\t\t},\n\t\t\t],\n\t\t}\n\t\t: {};\n\n\t// SERVER-DRIVEN windowed read. When enabled, the worker reads one window of the file\n\t// per request and continues from the reader's own cursor until the file is exhausted,\n\t// so the traversal no longer lives inside the model's turn budget.\n\t//\n\t// Flag-gated because the BACKEND MUST SHIP FIRST: against a worker that does not strip\n\t// `_skapi_window`, the directive reaches the provider as an unknown body field and the\n\t// call fails terminally with no retry.\n\tconst windowedRead =\n\t\t!visionFile && !parsedContent && windowedIndexingEnabled() &&\n\t\tisWindowedReadFile(attachment.name, attachment.mime);\n\tconst windowPlaceholder = windowedRead ? makeWindowPlaceholder(attachment.storagePath) : undefined;\n\tconst skapiWindow = windowedRead && windowPlaceholder\n\t\t? {\n\t\t\t_skapi_window: [\n\t\t\t\t{\n\t\t\t\t\tpath: attachment.storagePath,\n\t\t\t\t\tcursor: null,\n\t\t\t\t\tplaceholder: windowPlaceholder,\n\t\t\t\t\tname: attachment.name,\n\t\t\t\t\tmime: attachment.mime,\n\t\t\t\t\tkind: 'window',\n\t\t\t\t\tauto_continue: true,\n\t\t\t\t\tcontinue_text: buildIndexingWindowMessage(attachment, windowPlaceholder, true),\n\t\t\t\t},\n\t\t\t],\n\t\t}\n\t\t: {};\n\n\t// Spreadsheets are read by PAGING through readFileContent (grid rows), NOT inlined - so\n\t// they skip the inline server-extract and the agent is told to page the whole file.\n\tconst pagedRead = !visionFile && !windowedRead && (continuing || (!parsedContent && isPagedReadFile(attachment.name, attachment.mime)));\n\n\t// Client-parsed content wins over server-side extraction.\n\tconst serverExtract = !visionFile && !windowedRead && !continuing && !parsedContent && !pagedRead && isServerExtractable(attachment.name, attachment.mime);\n\tconst placeholder = serverExtract ? makeExtractPlaceholder(attachment.storagePath) : undefined;\n\tconst extractContent: ExtractDirective[] | undefined =\n\t\tserverExtract && placeholder\n\t\t\t? [{ path: attachment.storagePath, placeholder, name: attachment.name, mime: attachment.mime }]\n\t\t\t: undefined;\n\tconst skapiExtract =\n\t\textractContent && extractContent.length ? { _skapi_extract: extractContent } : {};\n\n\tconst userMessage = (visionFile && renderPlaceholder)\n\t\t? buildIndexingRenderMessage(attachment, renderPlaceholder, renderFrom)\n\t\t: (windowedRead && windowPlaceholder)\n\t\t? buildIndexingWindowMessage(attachment, windowPlaceholder, false)\n\t\t: continuing\n\t\t\t? buildIndexingContinueMessage(attachment)\n\t\t\t: buildIndexingUserMessage(\n\t\t\t\tattachment,\n\t\t\t\tparsedContent\n\t\t\t\t\t? { inlineContent: parsedContent }\n\t\t\t\t\t: placeholder\n\t\t\t\t\t\t? { inlineContentPlaceholder: placeholder }\n\t\t\t\t\t\t: pagedRead\n\t\t\t\t\t\t\t? { pagedRead: true }\n\t\t\t\t\t\t\t: undefined,\n\t\t\t);\n\n\tconst systemPrompt = buildIndexingSystemPrompt({\n\t\tservice,\n\t\tserviceName: info.serviceName,\n\t\tserviceDescription: info.serviceDescription,\n\t});\n\n\tif (platform === 'openai') {\n\t\tconst resolvedModel = info.model || DEFAULT_OPENAI_MODEL;\n\t\tconst imageDetail = getOpenAIImageDetail(resolvedModel);\n\t\treturn clientSecretRequest({\n\t\t\tclientSecretName: 'openai',\n\t\t\tqueue: (info.userId || service) + BG_INDEXING_QUEUE_SUFFIX,\n\t\t\tservice,\n\t\t\towner,\n\t\t\t...pollOpt(),\n\t\t\turl: OPENAI_RESPONSES_API_URL,\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'content-type': 'application/json',\n\t\t\t\tAuthorization: 'Bearer $CLIENT_SECRET',\n\t\t\t},\n\t\t\tdata: {\n\t\t\t\tmodel: resolvedModel,\n\t\t\t\tmax_output_tokens: MAX_TOKENS,\n\t\t\t\t...skapiExtract,\n\t\t\t\t...skapiRender,\n\t\t\t\t...skapiWindow,\n\t\t\t\tinput: [\n\t\t\t\t\t{ role: 'system', content: systemPrompt },\n\t\t\t\t\t{\n\t\t\t\t\t\trole: 'user',\n\t\t\t\t\t\tcontent: transformContentWithOpenAIImages(userMessage, imageDetail),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\ttools: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'mcp',\n\t\t\t\t\t\tserver_label: MCP_NAME,\n\t\t\t\t\t\tserver_url: mcpUrl(),\n\t\t\t\t\t\trequire_approval: 'never',\n\t\t\t\t\t\theaders: { Authorization: 'Bearer $ACCESS_TOKEN' },\n\t\t\t\t\t},\n\t\t\t\t\t...(OPENAI_WEB_SEARCH_ENABLED\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: 'web_search',\n\t\t\t\t\t\t\t\t\texternal_web_access: OPENAI_WEB_SEARCH_EXTERNAL_WEB_ACCESS,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: []),\n\t\t\t\t],\n\t\t\t},\n\t\t});\n\t}\n\n\tconst resolvedModel = info.model || DEFAULT_CLAUDE_MODEL;\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'claude',\n\t\tqueue: (info.userId || service) + BG_INDEXING_QUEUE_SUFFIX,\n\t\tservice,\n\t\towner,\n\t\t...pollOpt(),\n\t\turl: ANTHROPIC_MESSAGES_API_URL,\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'content-type': 'application/json',\n\t\t\t'x-api-key': '$CLIENT_SECRET',\n\t\t\t'anthropic-version': ANTHROPIC_VERSION,\n\t\t\t'anthropic-beta': ANTHROPIC_BETA_HEADER,\n\t\t},\n\t\tdata: {\n\t\t\tmodel: resolvedModel,\n\t\t\tmax_tokens: MAX_TOKENS,\n\t\t\t...skapiExtract,\n\t\t\t...skapiRender,\n\t\t\t...skapiWindow,\n\t\t\tsystem: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\ttext: systemPrompt,\n\t\t\t\t\tcache_control: { type: 'ephemeral' },\n\t\t\t\t},\n\t\t\t],\n\t\t\tmessages: [\n\t\t\t\t{\n\t\t\t\t\trole: 'user',\n\t\t\t\t\tcontent: transformContentWithImages(userMessage),\n\t\t\t\t},\n\t\t\t],\n\t\t\tmcp_servers: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'url',\n\t\t\t\t\tname: MCP_NAME,\n\t\t\t\t\turl: mcpUrl(),\n\t\t\t\t\tauthorization_token: '$ACCESS_TOKEN',\n\t\t\t\t},\n\t\t\t],\n\t\t\ttools: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'mcp_toolset',\n\t\t\t\t\tmcp_server_name: MCP_NAME,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'web_fetch_20250910',\n\t\t\t\t\tname: 'web_fetch',\n\t\t\t\t\tmax_uses: WEB_FETCH_MAX_USES,\n\t\t\t\t\tcitations: { enabled: true },\n\t\t\t\t\tmax_content_tokens: WEB_FETCH_MAX_CONTENT_TOKENS,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t});\n}\n\nexport function extractClaudeText(response: any) {\n\tif (!Array.isArray(response?.content)) {\n\t\treturn '';\n\t}\n\n\treturn response.content\n\t\t.filter((block: any) => block?.type === 'text')\n\t\t.map((block: any) => block.text)\n\t\t.join('\\n');\n}\n\nexport function extractOpenAIText(response: any) {\n\tif (\n\t\ttypeof response?.output_text === 'string' &&\n\t\tresponse.output_text.length\n\t) {\n\t\treturn response.output_text;\n\t}\n\n\tif (Array.isArray(response?.output)) {\n\t\tconst text = response.output\n\t\t\t.flatMap((item: any) => item?.content || [])\n\t\t\t.filter((part: any) => part?.type === 'output_text')\n\t\t\t.map((part: any) => part.text || '')\n\t\t\t.join('\\n')\n\t\t\t.trim();\n\n\t\tif (text) {\n\t\t\treturn text;\n\t\t}\n\t}\n\n\tconst content = response?.choices?.[0]?.message?.content;\n\n\tif (typeof content === 'string') {\n\t\treturn content;\n\t}\n\n\tif (Array.isArray(content)) {\n\t\treturn content\n\t\t\t.map((part: any) => {\n\t\t\t\tif (typeof part === 'string') {\n\t\t\t\t\treturn part;\n\t\t\t\t}\n\t\t\t\tif (part?.type === 'text') {\n\t\t\t\t\treturn part.text || '';\n\t\t\t\t}\n\t\t\t\treturn '';\n\t\t\t})\n\t\t\t.join('\\n');\n\t}\n\n\treturn '';\n}\n\nexport async function listClaudeModels(service: string, owner: string) {\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'claude',\n\t\tservice,\n\t\towner,\n\t\turl: ANTHROPIC_MODELS_API_URL,\n\t\tmethod: 'GET',\n\t\theaders: {\n\t\t\t'x-api-key': '$CLIENT_SECRET',\n\t\t\t'anthropic-version': ANTHROPIC_VERSION,\n\t\t},\n\t});\n}\n\nexport async function listOpenAIModels(service: string, owner: string) {\n\treturn clientSecretRequest({\n\t\tclientSecretName: 'openai',\n\t\tservice,\n\t\towner,\n\t\turl: OPENAI_MODELS_API_URL,\n\t\tmethod: 'GET',\n\t\theaders: {\n\t\t\tAuthorization: 'Bearer $CLIENT_SECRET',\n\t\t},\n\t});\n}\n\n// Suffix for the background-indexing queue. Must sort *before* ':' (ASCII 58)\n// so the chat-history BETWEEN query never includes bg-queue items. '-' (45) works.\nexport const BG_INDEXING_QUEUE_SUFFIX = '-bg';\n\n/**\n * True when a request belongs to the background-indexing queue.\n *\n * Accepts BOTH shapes this value arrives in: the bare queue name the client sends\n * (\"<userId>-bg\"), and the server qid that comes back on history/poll responses\n * (\"<service>:<queue>|<seq>\"). Testing the tail of the raw value only works for the\n * first: a qid ends in \"|<seq>\", so `endsWith('-bg')` is always false for it — which\n * silently meant history items were NEVER recognised as background tasks.\n */\nexport function isBgIndexingQueue(queueName?: string): boolean {\n\tif (typeof queueName !== 'string' || !queueName) return false;\n\tconst prefix = queueName.split('|')[0];\n\tconst idx = prefix.lastIndexOf(':');\n\tconst name = idx === -1 ? prefix : prefix.slice(idx + 1);\n\treturn name.slice(-BG_INDEXING_QUEUE_SUFFIX.length) === BG_INDEXING_QUEUE_SUFFIX;\n}\n\n// Pending background-indexing task descriptor. NOTE: the live mutable queue\n// (a Vue `reactive([])` in agent.vue, a plain array in bunnyquery) is app-level\n// state owned by the consumer — only the TYPE lives in the engine.\nexport type BgTaskEntry = {\n\tserviceId: string;\n\tplatform: 'claude' | 'openai';\n\tid: string;\n\tfilename: string;\n\tstoragePath?: string;\n\tisReindex?: boolean;\n\tmime?: string;\n\tsize?: number;\n\tstatus: 'running' | 'pending';\n\tpoll: ((opts: { latency: number }) => Promise<any>) | undefined;\n\t/** How many CONTINUE passes have already run for this file (resume-across-passes). */\n\tresumePass?: number;\n};\n\n// Token the indexing agent appends to its final message ONLY when it has fully read and\n// saved the whole file. Its ABSENCE is what tells the client to run another CONTINUE pass.\n//\n// Applies to the TEXT/GRID paging path only. The vision path (rendered PDF pages) no longer\n// asks the model whether it is finished — the worker advances that loop off the renderer's\n// page count — so this marker has no say in whether a PDF keeps going.\nexport const INDEXING_COMPLETE_MARKER = 'INDEXING_COMPLETE';\n// Cap on CONTINUE passes per file, so a file the agent can never mark complete (or a\n// pathological loop) stops instead of re-dispatching forever. The text/grid paging path\n// reads MANY windows within a single pass (the agent loops readFileContent in one turn), so\n// a small cap suffices.\nexport const MAX_INDEXING_RESUME_PASSES = 6;\n\n/**\n * `queue` narrows the fetch to one processing chain; `status` narrows it to items\n * in one state. Passing both is how the client asks \"is there still unresolved\n * work on the background-indexing queue?\" without pulling a page of chat history\n * (see ChatSession._adoptWorkerIndexingPasses) — the server answers that from a\n * status-keyed index, so the reply carries only the live items, not the bodies of\n * everything already finished.\n */\nexport async function getChatHistory(\n\tparams: { service?: string; owner?: string; platform: 'claude' | 'openai'; queue?: string; status?: 'pending' | 'running' | 'resolved' | 'failed' },\n\tfetchOptions: Record<string, any>,\n) {\n\tconst url =\n\t\tparams.platform === 'claude'\n\t\t\t? ANTHROPIC_MESSAGES_API_URL\n\t\t\t: OPENAI_RESPONSES_API_URL;\n\tconst p = Object.assign(\n\t\t{\n\t\t\turl,\n\t\t\tmethod: 'POST',\n\t\t},\n\t\t{ service: params.service, owner: params.owner },\n\t\tparams.queue ? { queue: params.queue } : {},\n\t\tparams.status ? { status: params.status } : {},\n\t);\n\n\treturn chatEngineConfig().clientSecretRequestHistory(\n\t\tp as { url: string; method: 'POST'; queue?: string; status?: string },\n\t\tObject.assign({ ascending: false }, fetchOptions),\n\t);\n}\n","/**\n * History mapping (pure). Moved verbatim from the chatbox. The clear-horizon\n * timestamp and the \"Indexing: …\" display label are INJECTED (clearedAt param,\n * formatIndexingLabel callback) so the engine touches neither localStorage nor\n * view-specific display formatting. serviceId is passed for link sanitization.\n */\nimport { extractClaudeText, extractOpenAIText } from './requests';\nimport { isErrorResponseBody, getErrorMessage } from './errors';\nimport { sanitizeAttachmentLinksForHistory } from './links';\n\nexport function filterListByClearHorizon(list: any[], clearedAt: number): any[] {\n\tif (!clearedAt) return list;\n\treturn list.filter(function (item) {\n\t\tvar updated = Number(item && item.updated);\n\t\treturn isFinite(updated) && updated > clearedAt;\n\t});\n}\n\nexport function normalizeTextContent(content: any): string {\n\tif (typeof content === 'string') return content;\n\tif (Array.isArray(content)) {\n\t\treturn content.map(function (part: any) {\n\t\t\tif (typeof part === 'string') return part;\n\t\t\tif (part && (part.type === 'text' || part.type === 'input_text' || part.type === 'output_text')) return part.text || '';\n\t\t\treturn '';\n\t\t}).join('\\n').trim();\n\t}\n\treturn '';\n}\n\nexport function extractLastUserTextFromRequest(requestBody: any): string {\n\tvar arr = requestBody && Array.isArray(requestBody.messages) ? requestBody.messages\n\t\t: (requestBody && Array.isArray(requestBody.input) ? requestBody.input : []);\n\tfor (var i = arr.length - 1; i >= 0; i--) {\n\t\tif (arr[i] && arr[i].role === 'user') {\n\t\t\tvar t = normalizeTextContent(arr[i].content);\n\t\t\tif (t) return t;\n\t\t}\n\t}\n\treturn '';\n}\n\n/** The two openings an indexing prompt can have. A bg-queue item that starts with\n * neither is an ordinary chat that happened to be routed onto that queue. */\nexport function isIndexingRequestText(userText: any): boolean {\n\tif (typeof userText !== 'string') return false;\n\treturn userText.indexOf('A new file has just been uploaded') === 0 || userText.indexOf('CONTINUE indexing') === 0;\n}\n\nexport type IndexingRequestRef = {\n\tname: string;\n\tpath?: string;\n\tmime?: string;\n\tsize?: number;\n\t/** A CONTINUE pass rather than the run's first. */\n\tcontinued: boolean;\n};\n\n/**\n * The file an indexing prompt is about, read back out of the prompt itself.\n *\n * The prompt is the only description of the pass that survives on the server, so\n * this is how BOTH a history rebuild and a worker-minted pass the client never\n * dispatched (ChatSession._adoptWorkerIndexingPasses) recover the file. Shared so\n * the two produce the same `_indexFile`, which is what makes them group together.\n */\nexport function parseIndexingRequestText(userText: any): IndexingRequestRef | null {\n\tif (typeof userText !== 'string' || !userText) return null;\n\tvar nameMatch = userText.match(/^- name: (.+)$/m);\n\tif (!nameMatch) return null;\n\tvar mimeMatch = userText.match(/^- mime type: (.+)$/m);\n\tvar sizeMatch = userText.match(/^- size \\(bytes\\): (\\d+)$/m);\n\tvar pathMatch = userText.match(/^- storage path: (.+)$/m);\n\treturn {\n\t\tname: nameMatch[1].trim(),\n\t\tpath: pathMatch ? pathMatch[1].trim() : undefined,\n\t\tmime: mimeMatch ? mimeMatch[1].trim() : undefined,\n\t\tsize: sizeMatch ? Number(sizeMatch[1]) : undefined,\n\t\tcontinued: userText.indexOf('CONTINUE indexing') === 0,\n\t};\n}\n\nexport type MapHistoryOptions = {\n\tclearedAt: number;\n\tserviceId: string;\n\t/** View-side display formatter for \"Indexing:/Reindexing: …\" bubbles. */\n\tformatIndexingLabel: (name: string, mime?: string, size?: number | null, storagePath?: string, reindex?: boolean, continued?: boolean) => string;\n};\n\nexport function mapHistoryListToMessages(list: any[], platform: 'claude' | 'openai', opts: MapHistoryOptions) {\n\tvar mapped: any[] = [], runningItemIds: string[] = [];\n\tvar extractAssistantText = platform === 'openai' ? extractOpenAIText : extractClaudeText;\n\tvar filtered = filterListByClearHorizon(list, opts.clearedAt);\n\tfiltered.slice().reverse().forEach(function (item) {\n\t\tvar requestBody = item && item.request_body;\n\t\tvar isInProcess = item && item.status === 'running';\n\t\tvar isQueued = item && item.status === 'pending';\n\t\tvar isCancelledItem = item && item.status === 'cancelled';\n\t\tvar isPending = isInProcess || isQueued;\n\t\tvar isFailed = item && item.status === 'failed';\n\t\tvar response = isFailed ? (item.error != null ? item.error : item.response_body)\n\t\t\t: (item && item.response_body != null ? item.response_body : item && item.error);\n\t\tvar userText = extractLastUserTextFromRequest(requestBody);\n\t\tvar assistantText = isPending ? '' : ((extractAssistantText(response) || '').trim() || '');\n\t\tvar isErrorResponse = !isPending && (isFailed || isErrorResponseBody(response));\n\t\tvar serverItemId = item && typeof item.id === 'string' && item.id ? item.id : undefined;\n\t\t// A USER bubble shows when the request was made (`created`); an ASSISTANT\n\t\t// bubble shows when its response landed (`updated`). Fall back to the other\n\t\t// if one is missing (older records only carried `updated`).\n\t\tvar createdTs = Number(item && item.created);\n\t\tvar updatedTs = Number(item && item.updated);\n\t\tvar userTs = isFinite(createdTs) && createdTs > 0 ? createdTs : (isFinite(updatedTs) && updatedTs > 0 ? updatedTs : undefined);\n\t\tvar replyTs = isFinite(updatedTs) && updatedTs > 0 ? updatedTs : (isFinite(createdTs) && createdTs > 0 ? createdTs : undefined);\n\n\t\tif (userText) {\n\t\t\tvar displayContent;\n\t\t\t// Structured file ref for the display layer's per-file collapsing, kept\n\t\t\t// alongside the formatted label so grouping never has to parse it back.\n\t\t\tvar indexFile: any = undefined;\n\t\t\tif (item._isBgTask) {\n\t\t\t\tvar ref = parseIndexingRequestText(userText);\n\t\t\t\tif (ref) {\n\t\t\t\t\t// A CONTINUE pass (\"CONTINUE indexing …\") gets the compact\n\t\t\t\t\t// continuation label; a first pass (\"A new file …\") gets the full\n\t\t\t\t\t// one. Mirrors agent.vue's mapHistoryListToMessages so a big file's\n\t\t\t\t\t// windows read as progress, not the same task repeating.\n\t\t\t\t\tdisplayContent = opts.formatIndexingLabel(\n\t\t\t\t\t\tref.name,\n\t\t\t\t\t\tref.mime || '',\n\t\t\t\t\t\ttypeof ref.size === 'number' ? ref.size : null,\n\t\t\t\t\t\tref.path,\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t\tref.continued\n\t\t\t\t\t);\n\t\t\t\t\tindexFile = ref;\n\t\t\t\t} else {\n\t\t\t\t\tdisplayContent = userText;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdisplayContent = sanitizeAttachmentLinksForHistory(userText, opts.serviceId);\n\t\t\t}\n\t\t\tvar userMsg: any = { role: 'user', content: displayContent };\n\t\t\tif (isInProcess) userMsg.isPendingInProcess = true;\n\t\t\tif (isQueued) userMsg.isPendingQueued = true;\n\t\t\tif (isCancelledItem) userMsg.isCancelled = true;\n\t\t\tif (item._isBgTask) userMsg.isBackgroundTask = true;\n\t\t\tif (indexFile) userMsg._indexFile = indexFile;\n\t\t\tif (item._isOnBgQueue) userMsg._useBgQueue = true;\n\t\t\tif (serverItemId !== undefined) userMsg._serverItemId = serverItemId;\n\t\t\tif (userTs !== undefined) userMsg._ts = userTs;\n\t\t\tmapped.push(userMsg);\n\t\t}\n\t\tif (isCancelledItem) { /* no assistant bubble */ }\n\t\telse if (isInProcess) {\n\t\t\tvar ph: any = { role: 'assistant', content: '', isPending: true, isPendingInProcess: true };\n\t\t\tif (item._isBgTask) ph.isBackgroundTask = true;\n\t\t\tif (serverItemId !== undefined) { ph._serverItemId = serverItemId; runningItemIds.push(serverItemId); }\n\t\t\tmapped.push(ph);\n\t\t} else if (isQueued) { /* no assistant placeholder */ }\n\t\telse if (isErrorResponse) {\n\t\t\tvar em: any = { role: 'assistant', content: getErrorMessage(response), isError: true };\n\t\t\tif (item._isBgTask) em.isBackgroundTask = true;\n\t\t\tif (serverItemId !== undefined) em._serverItemId = serverItemId;\n\t\t\tif (replyTs !== undefined) em._ts = replyTs;\n\t\t\tmapped.push(em);\n\t\t} else if (assistantText) {\n\t\t\t// Safe db-only sanitize (forAssistant) so a volatile db url the model\n\t\t\t// emitted renders as a re-mintable `_expired_.url` link, not a dead one.\n\t\t\tvar okm: any = { role: 'assistant', content: sanitizeAttachmentLinksForHistory(assistantText, opts.serviceId, true) };\n\t\t\tif (item._isBgTask) okm.isBackgroundTask = true;\n\t\t\tif (serverItemId !== undefined) okm._serverItemId = serverItemId;\n\t\t\tif (replyTs !== undefined) okm._ts = replyTs;\n\t\t\tmapped.push(okm);\n\t\t}\n\t});\n\treturn { messages: mapped, runningItemIds: runningItemIds };\n}\n","/**\n * Keep older history REACHABLE by paging until the message box actually gains\n * something to scroll to.\n *\n * Older history is paged in by one trigger only: the user scrolling to the top\n * of the message box. That trigger has two ways to die, and collapsed indexing\n * rows cause both:\n *\n * 1. The box never scrolls. A file's every indexing pass (the first plus every\n * CONTINUE pass, request AND response bubble each) folds into ONE row, so a\n * full history page — twenty-plus messages — can render as a single line.\n * Content shorter than the viewport fires no scroll event, so page 2 is\n * never requested and any conversation the user had before that upload is\n * permanently out of reach.\n * 2. The fetched page adds no height. A page that is entirely the same file's\n * earlier passes joins the collapsed row already on screen and renders\n * nothing new. The user, sitting at scrollTop 0, scrolls up again — and\n * because the position never changed, no further scroll event fires.\n *\n * Both are the same shape: fetch, re-measure, and keep going until the user\n * genuinely gained reachable content, history ran out, or the pager stopped\n * advancing. `isSatisfied` is what differs between the two (can the box scroll\n * at all / did it grow), so the loop below takes it as a predicate.\n *\n * DOM-free like the rest of the engine — the caller supplies the measurement and\n * awaits its own render before measuring, so agent.vue and the widget run the\n * identical loop over their own pagers.\n */\n\n/** Overflow (px) that counts as \"the user can scroll here\". Comfortably more\n * than the 60px top threshold that triggers the next page, so a filled box has\n * real room to scroll rather than sitting one pixel from the trigger. */\nexport const HISTORY_FILL_SLACK_PX = 64;\n\n/** Pages one fill pass will request before giving up. Reached only by a chat\n * whose history really is dozens of pages of one file's indexing passes; the\n * cap exists so a pager that stops advancing can never spin forever. */\nexport const MAX_HISTORY_FILL_PAGES = 24;\n\nexport type FillHistoryViewportOptions = {\n\t/** The user has reachable content and paging can stop. Called AFTER the\n\t * caller's own render has settled (nextTick / rAF), since only the caller\n\t * knows when its view has painted — hence the allowance for a promise. */\n\tisSatisfied: () => boolean | Promise<boolean>;\n\t/** All history is loaded — nothing left to page in. */\n\tisEndOfList: () => boolean;\n\t/** A history request is already in flight. Waited out, not treated as a stop\n\t * condition: a background first-page refresh (the queue-detect tick fires one\n\t * every couple of seconds while a file is indexing) would otherwise swallow\n\t * the user's scroll-up entirely, and scrolling up again from scrollTop 0\n\t * produces no second event to retry with. */\n\tisLoading: () => boolean;\n\t/** Messages currently loaded. Used to detect a page that added nothing, which\n\t * means the pager is not advancing and looping would never terminate. */\n\tmessageCount: () => number;\n\t/** Fetch ONE older page (the caller's own fetchMore path, scroll-restore and\n\t * all). Return `false` when the request was NOT issued (the caller's own\n\t * single-flight guard swallowed it) so the loop retries instead of reading\n\t * the unchanged message count as an exhausted pager. Anything else, including\n\t * undefined, means it was attempted. */\n\tfetchOlder: () => Promise<boolean | void | any>;\n\t/** The chat this fill was started for is gone (project switched, view\n\t * unmounted, gate token bumped). Checked between pages so a stale fill can\n\t * never keep paging another chat's history. */\n\tisStale?: () => boolean;\n\tmaxPages?: number;\n};\n\n/** How long to wait out an in-flight history request before giving up on it. */\nconst IDLE_WAIT_STEP_MS = 120;\nconst IDLE_WAIT_MAX_MS = 15000;\n\n/** Resolve once no history request is in flight. False if the wait timed out or\n * the chat went stale, in which case the caller should stop. */\nasync function waitForIdle(\n\topts: FillHistoryViewportOptions,\n\tstale: () => boolean,\n): Promise<boolean> {\n\tvar waited = 0;\n\twhile (opts.isLoading()) {\n\t\tif (stale() || waited >= IDLE_WAIT_MAX_MS) return false;\n\t\tawait new Promise(function (r) { setTimeout(r, IDLE_WAIT_STEP_MS); });\n\t\twaited += IDLE_WAIT_STEP_MS;\n\t}\n\treturn !stale();\n}\n\n/**\n * Page older history until `isSatisfied`, until history runs out, or until the\n * pager stops advancing. Never throws: a failed page ends the fill, and the\n * user's own scrolling remains the fallback trigger.\n */\nexport async function fillHistoryViewport(opts: FillHistoryViewportOptions): Promise<void> {\n\tvar maxPages = typeof opts.maxPages === 'number' ? opts.maxPages : MAX_HISTORY_FILL_PAGES;\n\tvar stale = function () { return !!(opts.isStale && opts.isStale()); };\n\tvar swallowed = 0;\n\n\tfor (var page = 0; page < maxPages; page++) {\n\t\tif (stale() || opts.isEndOfList()) return;\n\t\tif (!(await waitForIdle(opts, stale))) return;\n\t\tvar satisfied = false;\n\t\ttry {\n\t\t\tsatisfied = !!(await opts.isSatisfied());\n\t\t} catch {\n\t\t\treturn; // cannot measure (view torn down mid-fill) — stop.\n\t\t}\n\t\tif (satisfied || stale()) return;\n\n\t\t// Re-check immediately before dispatching: measuring above yields for a\n\t\t// frame, and a background first-page refresh landing in that gap would make\n\t\t// the caller's own single-flight guard swallow this request. A swallowed\n\t\t// page adds no messages, which used to read as \"the pager is exhausted\" and\n\t\t// abandoned the fill for good.\n\t\tif (!(await waitForIdle(opts, stale))) return;\n\t\tvar before = opts.messageCount();\n\t\tvar attempted: boolean | void;\n\t\ttry {\n\t\t\tattempted = await opts.fetchOlder();\n\t\t} catch {\n\t\t\treturn; // history is optional; the scroll trigger stays as the fallback.\n\t\t}\n\t\tif (stale()) return;\n\t\tif (attempted === false) {\n\t\t\t// The caller reported it never issued the request. Retry it rather than\n\t\t\t// mistaking it for an exhausted pager, but not forever.\n\t\t\tif (++swallowed > 3) return;\n\t\t\tpage--;\n\t\t\tcontinue;\n\t\t}\n\t\t// The page came back with nothing new. Either the pager is exhausted (and\n\t\t// endOfList simply has not been set) or it is stuck; either way another\n\t\t// round would request the same page again.\n\t\tif (opts.messageCount() <= before) return;\n\t}\n}\n\n/**\n * One fill loop per view, with predicates COMBINED rather than dropped.\n *\n * Fills come from several places at once — a first page finishing, a window\n * resize, a row being collapsed, and the user's own scroll to the top — and a\n * plain \"one at a time, drop the rest\" guard picks the wrong winner: a resize\n * fill (satisfied the moment the box can scroll at all) would swallow the user's\n * scroll-up (which needs content specifically ABOVE them), and the scroll-up\n * cannot be retried, because a reader parked at scrollTop 0 produces no further\n * scroll event. Dropping the guard entirely is no better: every frame of a\n * window drag would start its own 24-page loop.\n *\n * So a request that arrives mid-loop ANDs its predicate into the running one:\n * the loop then keeps paging until EVERY caller is satisfied. Predicates that\n * come true are dropped as it goes, so the cost stays flat.\n */\nexport function createHistoryFiller(\n\tbase: Omit<FillHistoryViewportOptions, 'isSatisfied'>,\n): { fill: (isSatisfied: () => boolean | Promise<boolean>) => Promise<void>; isRunning: () => boolean } {\n\tvar pending: Array<() => boolean | Promise<boolean>> = [];\n\tvar running = false;\n\n\tasync function allSatisfied(): Promise<boolean> {\n\t\tvar next: Array<() => boolean | Promise<boolean>> = [];\n\t\tfor (var i = 0; i < pending.length; i++) {\n\t\t\tif (!(await pending[i]())) next.push(pending[i]);\n\t\t}\n\t\tpending = next;\n\t\treturn pending.length === 0;\n\t}\n\n\treturn {\n\t\tisRunning: function () { return running; },\n\t\tfill: function (isSatisfied) {\n\t\t\tpending.push(isSatisfied);\n\t\t\tif (running) return Promise.resolve();\n\t\t\trunning = true;\n\t\t\tvar done = function () { running = false; pending = []; };\n\t\t\treturn fillHistoryViewport({\n\t\t\t\tisSatisfied: allSatisfied,\n\t\t\t\tisEndOfList: base.isEndOfList,\n\t\t\t\tisLoading: base.isLoading,\n\t\t\t\tmessageCount: base.messageCount,\n\t\t\t\tfetchOlder: base.fetchOlder,\n\t\t\t\tisStale: base.isStale,\n\t\t\t\tmaxPages: base.maxPages,\n\t\t\t}).then(done, done);\n\t\t},\n\t};\n}\n","/**\n * ChatSession — framework-agnostic stateful chat orchestration.\n *\n * Ported verbatim from the bunnyquery widget's in-place state machine (which was\n * itself ported from agent.vue), with three mechanical substitutions:\n * CS.<field> -> this.state.<field>\n * renderMessages() -> this.host.notify()\n * S.<x> / skapi -> this.host.getIdentity().<x> / this.host.cancelRequest / refreshSession\n * scroll/refresh -> this.host.scrollToBottom(IfSticky) / refreshMessageBubble\n * Module-level singletons (bgTaskQueue, aiChatHistoryCache, pendingAgentRequests,\n * cancelledServerIds, historyItemPolls) become instance fields. The provider\n * request builders are reached through the engine (which already has the skapi\n * transport + poll injected via configureChatEngine), so cancel/poll behavior is\n * preserved.\n *\n * The view (per consumer) keeps: rendering, markdown PARSE, DOM refs + scroll\n * measurement, attachment chips, and the auth/account shell. It drives the\n * session via the public methods and re-renders in host.notify().\n */\nimport {\n\tcallClaudeWithPublicMcp,\n\tcallOpenAIWithPublicMcp,\n\tnotifyAgentSaveAttachment,\n\tnotifyAgentContinueIndexing,\n\tINDEXING_COMPLETE_MARKER,\n\tMAX_INDEXING_RESUME_PASSES,\n\textractClaudeText,\n\textractOpenAIText,\n\tgetChatHistory,\n\tPOLL_INTERVAL,\n\tBG_INDEXING_QUEUE_SUFFIX,\n\tisBgIndexingQueue,\n\tANTHROPIC_MESSAGES_API_URL,\n\tOPENAI_RESPONSES_API_URL,\n\ttype BgTaskEntry,\n} from './requests';\nimport { isPagedReadFile, isImageVisionFile, isWindowedReadFile } from './office';\nimport { windowedIndexingEnabled } from './config';\nimport { isErrorResponseBody, isAuthExpiredError, isNonRetryableRequestError, getErrorMessage } from './errors';\nimport { buildBoundedChatMessages } from './budget';\nimport { createInlineLinkRegex } from './links';\nimport { mapHistoryListToMessages, extractLastUserTextFromRequest, isIndexingRequestText, parseIndexingRequestText } from './history';\nimport { wallClockNow } from './time';\nimport { parseAttachmentContent } from './attachment_parsers';\nimport type { ChatHost, ChatState, ChatMessage, PinnedDispatchContext } from './host';\nimport type { IndexingGroup } from './indexing_groups';\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise(function (r) { setTimeout(r, ms); });\n}\n\n// How many live items one look at the background-indexing queue asks for. The\n// queue is FIFO per user, so a healthy chain has one running plus at most a\n// couple queued; the cap only bounds a pathological backlog.\nconst WORKER_PASS_ADOPT_LIMIT = 20;\n// Delays before each look (the first is immediate). More than one because the\n// worker writes the next pass's row a few milliseconds AFTER it resolves the\n// current one, so a look that wins that race sees an empty queue for a chain\n// that is still alive. Fixed and finite: this must never become a poll.\nconst WORKER_PASS_ADOPT_ATTEMPTS = [0, 2000, 6000];\n\n// requestAnimationFrame / high-res clock, reached through globalThis so the\n// engine stays DOM-free at the type level (and degrades gracefully in non-DOM\n// / test environments where these globals are absent).\nvar _g: any = typeof globalThis !== 'undefined' ? globalThis : {};\nfunction nowMs(): number {\n\treturn (_g.performance && typeof _g.performance.now === 'function') ? _g.performance.now() : Date.now();\n}\nfunction nextFrame(cb: (t: number) => void): void {\n\tif (typeof _g.requestAnimationFrame === 'function') { _g.requestAnimationFrame(cb); return; }\n\tsetTimeout(function () { cb(nowMs()); }, 16);\n}\n\n/** A live poll registered in ChatSession.historyItemPolls. */\nexport type PollHandle = {\n\t/** 'bg' = background indexing, pausable. 'fg' = a reply the user is waiting on. */\n\tkind: 'fg' | 'bg';\n\t/** Absent on an older skapi-js that cannot stop an attached poll. */\n\tstop?: () => void;\n};\n\n/**\n * True when a poll result came from stopPolling rather than the server. Duck-typed on\n * purpose — see the note above about not importing skapi-js here.\n */\nfunction isPollStopped(res: any): boolean {\n\treturn !!res && typeof res === 'object' && res.status === 'stopped';\n}\n\nexport class ChatSession {\n\thost: ChatHost;\n\tstate: ChatState;\n\tbgTaskQueue: BgTaskEntry[];\n\tcancelledServerIds: Set<string>;\n\t/** Files whose indexing the user stopped, keyed exactly as buildChatDisplayList\n\t * keys a group (storage path, else filename). Cancelling one pass is not\n\t * enough on its own: the client dispatches CONTINUE passes for paged files, so\n\t * without this the next pass is enqueued the moment the cancelled one settles.\n\t * Cleared when a FIRST pass for the same file is queued again (a re-upload or a\n\t * Reindex from the file manager), so stopping a file never poisons it. */\n\tcancelledIndexKeys: Set<string>;\n\tpendingAgentRequests: Record<string, Promise<any>>;\n\taiChatHistoryCache: Record<string, { messages: ChatMessage[]; endOfList: boolean; startKeyHistory: string[] }>;\n\thistoryItemPolls: Map<string, PollHandle>;\n\t/** Non-empty while polling is paused; keyed by reason so overlapping causes\n\t * (view detached AND tab hidden) do not resume each other prematurely. */\n\tprivate _pauseReasons: Set<string>;\n\tprivate _resuming: boolean;\n\tprivate _lidSeq: number;\n\n\tconstructor(host: ChatHost) {\n\t\tthis.host = host;\n\t\tthis.state = {\n\t\t\tmessages: [],\n\t\t\tattachments: [],\n\t\t\tuploadingAttachments: false,\n\t\t\tsending: false,\n\t\t\ttyping: false,\n\t\t\ttypingAbort: false,\n\t\t\tloadingHistory: false,\n\t\t\tloadingOlderHistory: false,\n\t\t\thistoryEndOfList: false,\n\t\t\thistoryStartKeyHistory: [],\n\t\t\thistoryRequestToken: 0,\n\t\t\tgateRefreshToken: 0,\n\t\t};\n\t\tthis.bgTaskQueue = [];\n\t\tthis.cancelledServerIds = new Set();\n\t\tthis.cancelledIndexKeys = new Set();\n\t\tthis.pendingAgentRequests = {};\n\t\tthis.aiChatHistoryCache = {};\n\t\tthis.historyItemPolls = new Map();\n\t\tthis._pauseReasons = new Set();\n\t\tthis._resuming = false;\n\t\tthis._lidSeq = 0;\n\t}\n\n\t/**\n\t * Register a live poll so (a) a remount dedupes against it instead of stacking a\n\t * SECOND poll on the same item, and (b) pausePolling can stop it.\n\t *\n\t * `stop` comes from the SDK and may be absent on an older skapi-js, in which case the\n\t * poll simply cannot be stopped and is left running — see pausePolling.\n\t */\n\tprivate _trackPoll(id: string, kind: 'fg' | 'bg', p: any): any {\n\t\tvar stop = p && typeof p.stop === 'function' ? p.stop.bind(p) : undefined;\n\t\tif (!stop) {\n\t\t\t// The SDK could not give us a handle. Almost always means an older skapi-js\n\t\t\t// is loaded (or a stale bundler dep cache) — the poll will be unstoppable.\n\t\t\tconsole.debug('[chat-engine] poll has no stop handle', { id: id, kind: kind });\n\t\t}\n\t\tthis.historyItemPolls.set(id, { kind: kind, stop: stop });\n\t\treturn p;\n\t}\n\n\t/**\n\t * Stop and forget one item's poll. Used after a cancel: the row is either gone\n\t * (cancelled while queued) or flagged cancelled (cancelled while running), so\n\t * asking about it again only burns requests. Safe when no poll is attached, and\n\t * safe on an older skapi-js with no stop handle (the entry is then LEFT in the\n\t * map so a later drain cannot stack a second, unstoppable poll on the id).\n\t */\n\tprivate _stopPoll(id: string): void {\n\t\tvar handle = this.historyItemPolls.get(id);\n\t\tif (!handle) return;\n\t\tif (typeof handle.stop !== 'function') return;\n\t\ttry { handle.stop(); } catch (e) { /* best effort */ }\n\t\tthis.historyItemPolls.delete(id);\n\t}\n\n\t/** True while any pause reason is active. */\n\tisPollingPaused(): boolean {\n\t\treturn this._pauseReasons.size > 0;\n\t}\n\n\t/**\n\t * Stop BACKGROUND polling until resumePolling. Foreground polls (a reply the user is\n\t * waiting on) keep running deliberately: their results must still land in the history\n\t * cache so resumePendingRequest can render them on return, otherwise a user who sends\n\t * a message then navigates away comes back to a permanently stuck \"Thinking...\".\n\t *\n\t * Server-side work is untouched; this only stops asking about it. That is safe for\n\t * document indexing because the worker drives that loop itself.\n\t */\n\tpausePolling(reason: string): void {\n\t\tthis._pauseReasons.add(reason || 'paused');\n\t\tvar self = this;\n\t\tvar stopped: string[] = [];\n\t\tthis.historyItemPolls.forEach(function (handle, id) {\n\t\t\tif (!handle || handle.kind !== 'bg') return;\n\t\t\t// No stop available (older SDK): LEAVE the entry in place. Deleting it would\n\t\t\t// let a later drain attach a second, uncancellable poll on the same item.\n\t\t\tif (typeof handle.stop !== 'function') return;\n\t\t\ttry { handle.stop(); } catch (e) { /* best effort */ }\n\t\t\tstopped.push(id);\n\t\t});\n\t\t// Delete only what we actually stopped, one at a time. NEVER clear() the map:\n\t\t// wholesale clearing is what previously let loadHistory attach a duplicate poll\n\t\t// on a live item, producing duplicate replies and stranded \"Thinking\" bubbles.\n\t\tstopped.forEach(function (id) { self.historyItemPolls.delete(id); });\n\n\t}\n\n\t/**\n\t * Lift a pause reason WITHOUT running the reconcile. For a caller that is about to\n\t * reload history anyway (a view remounting), letting resumePolling also reconcile\n\t * would race that load and can double-attach.\n\t */\n\tclearPauseReason(reason: string): void {\n\t\tthis._pauseReasons.delete(reason || 'paused');\n\t}\n\n\t/**\n\t * Clear a pause reason and, once none remain, re-attach polling and reconcile.\n\t * Deliberately does NOT touch gateRefreshToken: bumping it would silently discard\n\t * the results of anything still in flight across the pause.\n\t */\n\tresumePolling(reason: string): Promise<void> {\n\t\tthis._pauseReasons.delete(reason || 'paused');\n\t\tif (this._pauseReasons.size > 0 || this._resuming) return Promise.resolve();\n\t\tif (!this.host.isViewMounted || !this.host.isViewMounted()) return Promise.resolve();\n\t\tvar self = this;\n\t\tthis._resuming = true;\n\t\treturn Promise.resolve()\n\t\t\t.then(function () {\n\t\t\t\tself.drainBgTaskQueue();\n\t\t\t\treturn self.loadHistory(false, self.state.gateRefreshToken);\n\t\t\t})\n\t\t\t.catch(function (e: any) { console.error('[chat-engine] resume polling failed', e); })\n\t\t\t.then(function () { self._resuming = false; });\n\t}\n\n\tprivate _newLocalId(): string {\n\t\tthis._lidSeq += 1;\n\t\treturn 'lid_' + this._lidSeq;\n\t}\n\n\tgetHistoryCacheKey(): string {\n\t\tvar id = this.host.getIdentity();\n\t\tif (!id.serviceId || id.platform === 'none') return '';\n\t\treturn id.serviceId + '#' + id.platform;\n\t}\n\n\tupdateHistoryCache(): void {\n\t\tvar key = this.getHistoryCacheKey();\n\t\tif (!key) return;\n\t\t// Never persist another chat's in-flight bubbles under THIS key. The\n\t\t// dashboard shares one ChatSession across projects, so a turn dispatched\n\t\t// in project A can still be sitting in state.messages while the identity\n\t\t// (and therefore `key`) already points at project B — without this filter\n\t\t// A's user + \"Thinking...\" bubbles get written into B's cache entry and\n\t\t// replay on every later visit to B. Bubbles with no _ownerKey (server\n\t\t// history, bg tasks) are always kept. Single pass: this runs on the\n\t\t// typewriter hot path.\n\t\tthis.aiChatHistoryCache[key] = {\n\t\t\tmessages: this.state.messages.filter(function (m) {\n\t\t\t\treturn m._ownerKey === undefined || m._ownerKey === key;\n\t\t\t}),\n\t\t\tendOfList: this.state.historyEndOfList,\n\t\t\tstartKeyHistory: this.state.historyStartKeyHistory.slice(),\n\t\t};\n\t}\n\n\t/**\n\t * Land a resolved reply in the history cache of a chat that is NOT currently\n\t * visible, without touching state.messages. Mirrors the cache-only path in\n\t * dispatchAgentRequest: REPLACE the trailing pending \"Thinking...\" bubble\n\t * (append only when there is none), and settle the matching pending user\n\t * bubble, so the cached copy never keeps a stuck \"Thinking...\" that a later\n\t * cache-first load would re-render forever.\n\t */\n\tprivate _applyReplyToCache(key: string, reply: ChatMessage, serverId?: string): void {\n\t\tif (!key) return;\n\t\tvar existing = this.aiChatHistoryCache[key] || { messages: [], endOfList: false, startKeyHistory: [] };\n\t\tvar msgs = existing.messages.slice();\n\n\t\tvar thIdx = -1;\n\t\tfor (var i = msgs.length - 1; i >= 0; i--) {\n\t\t\tvar m = msgs[i];\n\t\t\tif (!m || !m.isPending || m.role !== 'assistant' || m.isBackgroundTask) continue;\n\t\t\tif (serverId && m._serverItemId && m._serverItemId !== serverId) continue;\n\t\t\tthIdx = i; break;\n\t\t}\n\t\tif (thIdx !== -1) {\n\t\t\tif (reply._serverItemId === undefined && msgs[thIdx]._serverItemId !== undefined) reply._serverItemId = msgs[thIdx]._serverItemId;\n\t\t\tmsgs[thIdx] = reply;\n\t\t} else {\n\t\t\t// No pending placeholder left to replace. Before appending, check whether\n\t\t\t// this turn is ALREADY in the cache — a history fetch may have mapped the\n\t\t\t// resolved turn in while the reply was in flight. Appending blindly is how\n\t\t\t// one turn ended up rendered twice (the duplicated question+answer): the\n\t\t\t// cache is restored verbatim on the next mount, so a duplicate written\n\t\t\t// here survives every later visit.\n\t\t\tvar dupIdx = -1;\n\t\t\tif (serverId) {\n\t\t\t\tfor (var d = msgs.length - 1; d >= 0; d--) {\n\t\t\t\t\tvar dm = msgs[d];\n\t\t\t\t\tif (dm && dm.role === 'assistant' && dm._serverItemId === serverId) { dupIdx = d; break; }\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (dupIdx !== -1) msgs[dupIdx] = reply;\n\t\t\telse msgs.push(reply);\n\t\t}\n\n\t\t// Settle the user bubble this turn belongs to (first pending one, or the\n\t\t// one carrying serverId) so it stops rendering as still in flight.\n\t\tfor (var j = 0; j < msgs.length; j++) {\n\t\t\tvar u = msgs[j];\n\t\t\tif (!u || u.role !== 'user' || u.isBackgroundTask) continue;\n\t\t\tif (!(u.isPendingQueued || u.isPendingInProcess || u.isSendingToServer)) continue;\n\t\t\tif (serverId && u._serverItemId && u._serverItemId !== serverId) continue;\n\t\t\tvar settled: ChatMessage = { role: 'user', content: u.content };\n\t\t\tif (u._serverItemId !== undefined) settled._serverItemId = u._serverItemId;\n\t\t\tif (u._ownerKey !== undefined) settled._ownerKey = u._ownerKey;\n\t\t\tmsgs[j] = settled;\n\t\t\tbreak;\n\t\t}\n\n\t\tthis.aiChatHistoryCache[key] = {\n\t\t\tmessages: msgs,\n\t\t\tendOfList: existing.endOfList,\n\t\t\tstartKeyHistory: existing.startKeyHistory,\n\t\t};\n\t}\n\n\t/**\n\t * serviceId/owner are passed explicitly by every caller: a request can be\n\t * dispatched after the user moved to another project, and re-reading the live\n\t * identity here would silently send the turn to THAT project instead of the\n\t * one it was composed for. Falls back to the live read only when a caller\n\t * omits them.\n\t */\n\tprivate _callProviderFor(platform: string, prompt: string, messages: any, system: string, model: string | undefined, userId: string, extractContent: any, fileUrls?: any, serviceId?: string, owner?: string) {\n\t\tif (serviceId === undefined || owner === undefined) {\n\t\t\tvar id = this.host.getIdentity();\n\t\t\tif (serviceId === undefined) serviceId = id.serviceId;\n\t\t\tif (owner === undefined) owner = id.owner;\n\t\t}\n\t\treturn platform === 'openai'\n\t\t\t? callOpenAIWithPublicMcp(prompt, serviceId, owner, messages, system, model, userId, extractContent, fileUrls)\n\t\t\t: callClaudeWithPublicMcp(prompt, serviceId, owner, messages, system, model, userId, extractContent, fileUrls);\n\t}\n\n\tdispatchAgentRequest(params: any) {\n\t\tvar self = this;\n\t\t// Id of the in-flight item this dispatch polls. Recorded in\n\t\t// historyItemPolls (set below, deleted when the dispatch settles) so a\n\t\t// remount / history refetch dedups against THIS poll instead of stacking\n\t\t// a duplicate history poll on the same item. (The cacheKey guard alone\n\t\t// stops covering an item once pendingAgentRequests clears — e.g. a queued\n\t\t// message still in flight after the immediate one resolved.)\n\t\tvar dispatchItemId: string | undefined;\n\t\tvar sendAndPoll = function () {\n\t\t\treturn Promise.resolve(\n\t\t\t\tself._callProviderFor(params.aiPlatform, params.text, params.boundedMessages, params.systemPrompt, params.aiModel, params.userId, params.extractContent, params.fileUrls, params.serviceId, params.owner)\n\t\t\t).then(function (initial: any) {\n\t\t\t\tif (initial && initial.poll && (initial.status === 'pending' || initial.status === 'running')) {\n\t\t\t\t\tif (initial.id) {\n\t\t\t\t\t\tif (dispatchItemId && dispatchItemId !== initial.id) self.historyItemPolls.delete(dispatchItemId);\n\t\t\t\t\t\tdispatchItemId = initial.id;\n\t\t\t\t\t}\n\t\t\t\t\tvar dp = initial.poll({ latency: POLL_INTERVAL });\n\t\t\t\t\tif (initial.id) self._trackPoll(initial.id, 'fg', dp);\n\t\t\t\t\treturn dp;\n\t\t\t\t}\n\t\t\t\treturn initial;\n\t\t\t});\n\t\t};\n\t\tvar run = sendAndPoll()\n\t\t\t.catch(function (err: any) {\n\t\t\t\t// Only auth-expiry is worth a refresh+resend; a malformed-request 400\n\t\t\t\t// (e.g. the `_skapi_extract`/unknown-parameter class) re-fails identically,\n\t\t\t\t// so never loop on it — guard against isAuthExpiredError's heuristic\n\t\t\t\t// misfiring on a param name that merely contains \"token\".\n\t\t\t\tif (isAuthExpiredError(err) && !isNonRetryableRequestError(err)) return self.host.refreshSession().then(sendAndPoll);\n\t\t\t\tthrow err;\n\t\t\t})\n\t\t\t.then(function (response: any) {\n\t\t\t\tif (isErrorResponseBody(response) && isAuthExpiredError(response) && !isNonRetryableRequestError(response)) {\n\t\t\t\t\treturn self.host.refreshSession().then(sendAndPoll);\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t})\n\t\t\t.then(function (response: any) {\n\t\t\t\tif (isErrorResponseBody(response)) return { content: getErrorMessage(response), isError: true };\n\t\t\t\tvar answer = (params.aiPlatform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response));\n\t\t\t\tanswer = (answer || '').trim();\n\t\t\t\treturn { content: answer || 'No text response received from AI provider.', isError: false };\n\t\t\t})\n\t\t\t.catch(function (err: any) { return { content: getErrorMessage(err), isError: true }; })\n\t\t\t.then(function (result: any) {\n\t\t\t\t// Land the resolved reply in the shared history cache. This runs\n\t\t\t\t// independently of the view lifecycle, so a reply is captured even\n\t\t\t\t// if the chatbox unmounted mid-request.\n\t\t\t\tdelete self.pendingAgentRequests[params.key];\n\t\t\t\tif (dispatchItemId) self.historyItemPolls.delete(dispatchItemId);\n\t\t\t\tvar existing = self.aiChatHistoryCache[params.key] || { messages: [], endOfList: false, startKeyHistory: [] };\n\t\t\t\tvar reply: ChatMessage = { role: 'assistant', content: result.content, isError: result.isError };\n\n\t\t\t\t// REPLACE the trailing pending \"Thinking...\" bubble in the cache with\n\t\t\t\t// the answer (falling back to append when none is present), regardless\n\t\t\t\t// of whether this chat is the currently-visible view. The cache must\n\t\t\t\t// NEVER retain a pending \"Thinking...\" bubble: even when the chatbox is\n\t\t\t\t// showing this chat, typewriteLatestReply swaps the bubble only in\n\t\t\t\t// state.messages and NEVER re-snapshots the cache — so appending a\n\t\t\t\t// duplicate here would leave the cached copy stuck pending, and a later\n\t\t\t\t// cache-first remount (agent.vue's loadChatHistory) would re-render that\n\t\t\t\t// \"Thinking...\" forever. typewriteLatestReply still finds this reply (it\n\t\t\t\t// reads the latest non-pending assistant from the cache), so replacing is\n\t\t\t\t// correct for the visible case too. The next fresh history fetch\n\t\t\t\t// reconciles it either way.\n\t\t\t\tvar msgs = existing.messages.slice();\n\t\t\t\tvar idx = -1;\n\t\t\t\tfor (var i = msgs.length - 1; i >= 0; i--) {\n\t\t\t\t\tvar m = msgs[i];\n\t\t\t\t\tif (m && m.isPending && m.role === 'assistant' && !m.isBackgroundTask) { idx = i; break; }\n\t\t\t\t}\n\t\t\t\tif (idx !== -1) {\n\t\t\t\t\treply._serverItemId = msgs[idx]._serverItemId;\n\t\t\t\t\tmsgs[idx] = reply;\n\t\t\t\t} else {\n\t\t\t\t\tmsgs.push(reply);\n\t\t\t\t}\n\t\t\t\tself.aiChatHistoryCache[params.key] = {\n\t\t\t\t\tmessages: msgs,\n\t\t\t\t\tendOfList: existing.endOfList,\n\t\t\t\t\tstartKeyHistory: existing.startKeyHistory,\n\t\t\t\t};\n\t\t\t\treturn result;\n\t\t\t});\n\t\tthis.pendingAgentRequests[params.key] = run;\n\t\treturn run;\n\t}\n\n\t// composed = clean display text; composedForLlm carries office-extraction\n\t// placeholders for the provider only. useBgQueue routes a post-attachment turn\n\t// onto the \"-bg\" queue so it runs after indexing.\n\tdispatchComposedMessage(composed: string, useBgQueue?: boolean, composedForLlm?: string, extractContent?: any, fileUrls?: any, pinned?: PinnedDispatchContext): void {\n\t\tvar self = this;\n\t\tif (!composed) return;\n\t\t// A send can be dispatched LONG after the user hit Send (attachment\n\t\t// uploads are awaited first), by which time the live identity may have\n\t\t// moved to another project. The caller pins the identity + system prompt\n\t\t// it captured at Send time so the request still goes to the project the\n\t\t// question was actually asked of. Falls back to the live read when the\n\t\t// caller doesn't pin (the widget, which has only one project anyway).\n\t\tvar id = pinned ? pinned.identity : this.host.getIdentity();\n\t\tif (id.platform === 'none') return;\n\n\t\tvar llmComposed = composedForLlm || composed;\n\n\t\t// Cache key of the chat this turn belongs to. Every locally-created\n\t\t// bubble is stamped with it so a project switch (which flips\n\t\t// getIdentity()/getHistoryCacheKey() to the new project) can't\n\t\t// misattribute this turn's bubbles to that project.\n\t\t// (platform === 'none' already returned above, so serviceId is the only gate)\n\t\tvar key = !id.serviceId ? '' : id.serviceId + '#' + id.platform;\n\t\t// True when the pinned chat is NOT the one currently on screen. Then\n\t\t// state.messages belongs to a different project and MUST NOT be touched:\n\t\t// the turn is staged in the pinned chat's cache instead and shows up when\n\t\t// the user navigates back to it.\n\t\tvar offChat = !!key && key !== this.getHistoryCacheKey();\n\n\t\tvar isQueuedSend = !offChat && (useBgQueue || this.state.sending || this.state.messages.some(function (m) {\n\t\t\treturn (m.isPending || m.isPendingQueued) && !m.isBackgroundTask && !m._useBgQueue;\n\t\t}));\n\n\t\tvar aiPlatform = id.platform;\n\t\tvar aiModel = id.model || undefined;\n\t\tvar systemPrompt = pinned ? pinned.systemPrompt : this.host.buildSystemPrompt();\n\t\tvar userId = id.userId || id.serviceId;\n\t\tvar chatQueue = useBgQueue ? userId + BG_INDEXING_QUEUE_SUFFIX : userId;\n\n\t\tif (offChat) {\n\t\t\t// Stage the turn in the pinned chat's cache and dispatch. The\n\t\t\t// client-side queue can't be consulted (its state is the other\n\t\t\t// project's), but the SERVER serializes per queue name, so ordering\n\t\t\t// within the pinned chat still holds. dispatchAgentRequest replaces\n\t\t\t// the pending bubble in this same cache entry when the reply lands.\n\t\t\tvar offHistory = (this.aiChatHistoryCache[key] ? this.aiChatHistoryCache[key].messages : []).filter(function (m) {\n\t\t\t\treturn !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder &&\n\t\t\t\t\t!m.isCancelled && !m.isBackgroundTask && !m.isError;\n\t\t\t});\n\t\t\tvar offBounded = buildBoundedChatMessages({\n\t\t\t\tplatform: aiPlatform, model: aiModel, systemPrompt: systemPrompt, serviceId: id.serviceId,\n\t\t\t\thistory: offHistory.concat([{ role: 'user', content: llmComposed }]),\n\t\t\t});\n\t\t\tvar offExisting = this.aiChatHistoryCache[key] || { messages: [], endOfList: false, startKeyHistory: [] };\n\t\t\tthis.aiChatHistoryCache[key] = {\n\t\t\t\tmessages: offExisting.messages.concat([\n\t\t\t\t\t{ role: 'user', content: composed, _ownerKey: key, _ts: wallClockNow() },\n\t\t\t\t\t{ role: 'assistant', content: '', isPending: true, isPendingInProcess: true, _ownerKey: key },\n\t\t\t\t]),\n\t\t\t\tendOfList: offExisting.endOfList,\n\t\t\t\tstartKeyHistory: offExisting.startKeyHistory,\n\t\t\t};\n\t\t\tthis.dispatchAgentRequest({\n\t\t\t\tkey: key, serviceId: id.serviceId, owner: id.owner, aiPlatform: aiPlatform, aiModel: aiModel,\n\t\t\t\tsystemPrompt: systemPrompt, text: composed, boundedMessages: offBounded.messages, userId: chatQueue,\n\t\t\t\textractContent: extractContent, fileUrls: fileUrls,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (isQueuedSend) {\n\t\t\tvar resolvedHistory = this.state.messages.filter(function (m) {\n\t\t\t\treturn !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder &&\n\t\t\t\t\t!m.isCancelled && !m.isBackgroundTask && !m.isError;\n\t\t\t});\n\t\t\tvar boundedQ = buildBoundedChatMessages({\n\t\t\t\tplatform: aiPlatform, model: aiModel, systemPrompt: systemPrompt, serviceId: id.serviceId,\n\t\t\t\thistory: resolvedHistory.concat([{ role: 'user', content: llmComposed }]),\n\t\t\t});\n\t\t\tvar queuedBubble: ChatMessage = { role: 'user', content: composed, isPendingQueued: true, isSendingToServer: true, _ts: wallClockNow() };\n\t\t\tif (key) queuedBubble._ownerKey = key;\n\t\t\tif (useBgQueue) queuedBubble._useBgQueue = true;\n\t\t\tthis.state.messages.push(queuedBubble);\n\t\t\tthis.host.notify(); this.updateHistoryCache(); this.host.scrollToBottom(true);\n\n\t\t\tvar capturedComposed = composed, capturedPlatform = aiPlatform, capturedKey = key;\n\t\t\tPromise.resolve(this._callProviderFor(aiPlatform, composed, boundedQ.messages, systemPrompt, aiModel, chatQueue, extractContent, fileUrls, id.serviceId, id.owner))\n\t\t\t\t.then(function (result: any) {\n\t\t\t\t\t// Only ack a bubble that belongs to THIS chat — the search is\n\t\t\t\t\t// positional, so on another project it would stamp this turn's\n\t\t\t\t\t// _serverItemId onto that project's unrelated in-flight bubble.\n\t\t\t\t\tvar sendingIdx = self.getHistoryCacheKey() !== capturedKey ? -1 : self.state.messages.findIndex(function (m) {\n\t\t\t\t\t\treturn m.isSendingToServer && (m.isPendingQueued || m.isPendingInProcess) && m.role === 'user' &&\n\t\t\t\t\t\t\t(m._ownerKey === undefined || m._ownerKey === capturedKey);\n\t\t\t\t\t});\n\t\t\t\t\tvar serverId = result && typeof result.id === 'string' ? result.id : undefined;\n\t\t\t\t\tif (sendingIdx >= 0) {\n\t\t\t\t\t\tvar upd = Object.assign({}, self.state.messages[sendingIdx], { isSendingToServer: false });\n\t\t\t\t\t\tif (serverId) upd._serverItemId = serverId;\n\t\t\t\t\t\tself.state.messages[sendingIdx] = upd; self.host.notify();\n\t\t\t\t\t}\n\t\t\t\t\tif (result && result.poll && (result.status === 'pending' || result.status === 'running')) {\n\t\t\t\t\t\t// Track this queued item's poll so a remount/refetch dedups\n\t\t\t\t\t\t// against it instead of attaching a duplicate history poll.\n\t\t\t\t\t\tvar qp = result.poll({ latency: POLL_INTERVAL });\n\t\t\t\t\t\tif (serverId) self._trackPoll(serverId, 'fg', qp);\n\t\t\t\t\t\treturn qp\n\t\t\t\t\t\t\t.then(function (res: any) { if (isPollStopped(res)) return; return self.onQueuedSendResponse(capturedComposed, res, capturedPlatform, serverId, capturedKey); })\n\t\t\t\t\t\t\t.catch(function (err: any) { return self.onQueuedSendError(capturedComposed, err, serverId, capturedKey); });\n\t\t\t\t\t}\n\t\t\t\t\treturn self.onQueuedSendResponse(capturedComposed, result, capturedPlatform, serverId, capturedKey);\n\t\t\t\t})\n\t\t\t\t.catch(function (err: any) { return self.onQueuedSendError(capturedComposed, err, undefined, capturedKey); });\n\t\t\treturn;\n\t\t}\n\n\t\t// immediate send — cache+resume model (mirrors agent.vue). The reply is\n\t\t// appended to aiChatHistoryCache by dispatchAgentRequest (so it survives a\n\t\t// view unmount), then rendered from the cache via typewriteLatestReply. A\n\t\t// later resumePendingRequest() re-renders it if the view remounted while the\n\t\t// request was still in flight.\n\t\tthis.state.messages.push({ role: 'user', content: composed, _ts: wallClockNow(), ...(key ? { _ownerKey: key } : {}) });\n\t\tthis.state.messages.push({ role: 'assistant', content: '', isPending: true, isPendingInProcess: true, ...(key ? { _ownerKey: key } : {}) });\n\t\tthis.host.notify(); this.updateHistoryCache(); this.state.sending = true; this.host.scrollToBottom(true);\n\n\t\t// Same filter as the offChat and isQueuedSend paths above. It must drop the\n\t\t// pending flags too: the `isPending` placeholder pushed two lines up is the\n\t\t// in-flight \"Thinking...\" bubble, and leaving it in sent a trailing\n\t\t// `{role:'assistant', content:''}` upstream on EVERY immediate send. That is\n\t\t// a last-assistant-turn prefill, which the Claude platform rejects outright,\n\t\t// and on both platforms it made the history end on an assistant turn, so\n\t\t// prepareOpenAIMessages / prepareClaudeMessages bailed at their\n\t\t// `last.role !== 'user'` guard and silently stopped converting attached\n\t\t// images into image blocks.\n\t\t//\n\t\t// `isError` is dropped in all three paths for a different reason: those\n\t\t// bubbles are written by THIS client, never by the model. Every site that\n\t\t// sets `isError: true` fills content from getErrorMessage() or the literal\n\t\t// 'Request was cancelled.', so filtering them discards no model-authored\n\t\t// text. Keeping them handed the model a turn it never produced (\"The AI\n\t\t// provider is temporarily unreachable...\"), attributed to itself, because the\n\t\t// flag is stripped when buildBoundedChatMessages maps down to {role,content}.\n\t\t// The cost is that a retry now follows an unanswered question with no stated\n\t\t// reason, which is a true account of what happened rather than a false one.\n\t\tvar historyForLlm = this.state.messages.filter(function (m) {\n\t\t\treturn !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder &&\n\t\t\t\t!m.isCancelled && !m.isBackgroundTask && !m.isError;\n\t\t});\n\t\tif (llmComposed !== composed) {\n\t\t\tfor (var li = historyForLlm.length - 1; li >= 0; li--) {\n\t\t\t\tif (historyForLlm[li].role === 'user' && historyForLlm[li].content === composed) {\n\t\t\t\t\thistoryForLlm[li] = Object.assign({}, historyForLlm[li], { content: llmComposed });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tvar bounded = buildBoundedChatMessages({\n\t\t\tplatform: aiPlatform, model: aiModel, systemPrompt: systemPrompt, serviceId: id.serviceId,\n\t\t\thistory: historyForLlm,\n\t\t});\n\t\tvar run = this.dispatchAgentRequest({\n\t\t\tkey: key, serviceId: id.serviceId, owner: id.owner, aiPlatform: aiPlatform, aiModel: aiModel,\n\t\t\tsystemPrompt: systemPrompt, text: composed, boundedMessages: bounded.messages, userId: chatQueue,\n\t\t\textractContent: extractContent, fileUrls: fileUrls,\n\t\t});\n\t\t// Render the reply into the \"Thinking...\" bubble whenever the chatbox is\n\t\t// CURRENTLY showing this chat — even after an unmount/remount. The old\n\t\t// guard bailed on `requestToken !== gateRefreshToken`, but EVERY remount\n\t\t// bumps gateRefreshToken (refreshGate), so a request that finished after\n\t\t// the user navigated away and back left a stuck \"Thinking...\" (no view\n\t\t// typewriter ever ran, and resumePendingRequest bails when a pending\n\t\t// bubble is already present). Gate on \"is this the visible chat\" instead.\n\t\t// When it ISN'T (unmounted / another project), dispatchAgentRequest has\n\t\t// already replaced the pending bubble with the answer IN THE CACHE, so a\n\t\t// later loadChatHistory renders it.\n\t\tPromise.resolve(run).catch(function () { }).then(function () {\n\t\t\t// Clear `sending` UNCONDITIONALLY. It is session-global (it gates\n\t\t\t// isQueuedSend above, plus the platform/model pickers in the view), so\n\t\t\t// leaving it set when the user navigated to another project wedged\n\t\t\t// every subsequent send in EVERY project onto the queued path and kept\n\t\t\t// the view's user-bubble rescue arm armed forever. Only the RENDER of\n\t\t\t// the reply stays gated on still showing this chat — when it isn't,\n\t\t\t// dispatchAgentRequest has already written the answer into the cache\n\t\t\t// under `key`, so a later loadChatHistory renders it.\n\t\t\tself.state.sending = false;\n\t\t\tif (!(self.host.isViewMounted() && self.getHistoryCacheKey() === key)) return;\n\t\t\treturn Promise.resolve(self.typewriteLatestReply(key)).then(function () { self.host.scrollToBottomIfSticky(true); });\n\t\t});\n\t}\n\n\tpromoteNextBgQueuedToRunning(): void {\n\t\tif (this.state.messages.some(function (m) { return m.isPending && m.role === 'assistant' && m.isBackgroundTask; })) return;\n\t\tvar nextIdx = this.state.messages.findIndex(function (m) {\n\t\t\treturn m.isPendingQueued && m.role === 'user' && m.isBackgroundTask;\n\t\t});\n\t\tif (nextIdx === -1) return;\n\t\tvar existing = this.state.messages[nextIdx];\n\t\tvar promoted: ChatMessage = { role: 'user', content: existing.content, isPendingInProcess: true, isBackgroundTask: true };\n\t\tif (existing._indexFile) promoted._indexFile = existing._indexFile;\n\t\tif (existing._ts !== undefined) promoted._ts = existing._ts;\n\t\tif (existing._serverItemId !== undefined) promoted._serverItemId = existing._serverItemId;\n\t\tif (existing._ownerKey !== undefined) promoted._ownerKey = existing._ownerKey;\n\t\tthis.state.messages[nextIdx] = promoted;\n\t\tvar placeholder: ChatMessage = { role: 'assistant', content: '', isPending: true, isPendingInProcess: true, isBackgroundTask: true };\n\t\tif (existing._serverItemId !== undefined) placeholder._serverItemId = existing._serverItemId;\n\t\tif (existing._ownerKey !== undefined) placeholder._ownerKey = existing._ownerKey;\n\t\tthis.state.messages.splice(nextIdx + 1, 0, placeholder);\n\t\tthis.host.notify();\n\t}\n\n\tpromoteNextQueuedToRunning(): void {\n\t\tif (this.state.messages.some(function (m) { return m.isPending && m.role === 'assistant' && !m.isBackgroundTask; })) return;\n\t\tvar nextIdx = this.state.messages.findIndex(function (m) {\n\t\t\treturn m.isPendingQueued && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue;\n\t\t});\n\t\tif (nextIdx === -1) return;\n\t\tvar existing = this.state.messages[nextIdx];\n\t\tvar promoted: ChatMessage = { role: 'user', content: existing.content, isPendingInProcess: true };\n\t\tif (existing.isBackgroundTask) promoted.isBackgroundTask = true;\n\t\tif (existing._indexFile) promoted._indexFile = existing._indexFile;\n\t\tif (existing._ts !== undefined) promoted._ts = existing._ts;\n\t\tif (existing._serverItemId !== undefined) promoted._serverItemId = existing._serverItemId;\n\t\tif (existing._ownerKey !== undefined) promoted._ownerKey = existing._ownerKey;\n\t\tif (existing.isSendingToServer) promoted.isSendingToServer = true;\n\t\tthis.state.messages[nextIdx] = promoted;\n\t\t// Carry the promoted turn's _serverItemId onto the \"Thinking...\" placeholder\n\t\t// (mirrors promoteNextBgQueuedToRunning). Without it, when this promoted turn\n\t\t// is resolved via the history-poll path — applyHistoryItemResolution, which\n\t\t// matches the pending assistant by _serverItemId — the placeholder is not\n\t\t// found, so the reply is spliced in BESIDE it and the \"Thinking...\" is\n\t\t// stranded forever (e.g. after a reload, or when a cancel advances the queue).\n\t\t// onQueuedSendResponse still finds it by position, so the queued-send path is\n\t\t// unaffected.\n\t\tvar placeholder: ChatMessage = { role: 'assistant', content: '', isPending: true };\n\t\tif (existing._serverItemId !== undefined) placeholder._serverItemId = existing._serverItemId;\n\t\tif (existing._ownerKey !== undefined) placeholder._ownerKey = existing._ownerKey;\n\t\tthis.state.messages.splice(nextIdx + 1, 0, placeholder);\n\t\tthis.host.notify();\n\t}\n\n\tresolveQueuedUserBubble(serverId?: string): number | undefined {\n\t\t// The two fallbacks below match by POSITION, not identity, so they must\n\t\t// never consider a bubble stamped for a different chat.\n\t\tvar liveKey = this.getHistoryCacheKey();\n\t\tvar isLocal = function (m: ChatMessage) { return m._ownerKey === undefined || m._ownerKey === liveKey; };\n\t\tvar userIdx = -1;\n\t\tif (serverId) {\n\t\t\tuserIdx = this.state.messages.findIndex(function (m) {\n\t\t\t\treturn m._serverItemId === serverId && (m.isPendingInProcess || m.isPendingQueued) &&\n\t\t\t\t\tm.role === 'user' && !m.isBackgroundTask;\n\t\t\t});\n\t\t}\n\t\tif (userIdx === -1) {\n\t\t\tuserIdx = this.state.messages.findIndex(function (m) {\n\t\t\t\treturn m.isPendingInProcess && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue && isLocal(m);\n\t\t\t});\n\t\t}\n\t\tif (userIdx === -1) {\n\t\t\tuserIdx = this.state.messages.findIndex(function (m) {\n\t\t\t\treturn m.isPendingQueued && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue && isLocal(m);\n\t\t\t});\n\t\t}\n\t\tif (serverId && this.cancelledServerIds.has(serverId)) {\n\t\t\tthis.cancelledServerIds.delete(serverId);\n\t\t\tif (userIdx >= 0) {\n\t\t\t\tvar ex = this.state.messages[userIdx];\n\t\t\t\tthis.state.messages[userIdx] = { role: 'user', content: ex.content, isCancelled: true, _serverItemId: ex._serverItemId, ...(ex._ownerKey !== undefined ? { _ownerKey: ex._ownerKey } : {}) };\n\t\t\t\tvar thIdx = this.state.messages.findIndex(function (m, i) {\n\t\t\t\t\treturn i > userIdx && m.isPending && m.role === 'assistant' && !m.isBackgroundTask;\n\t\t\t\t});\n\t\t\t\tif (thIdx !== -1) this.state.messages.splice(thIdx, 1);\n\t\t\t}\n\t\t\tthis.promoteNextQueuedToRunning();\n\t\t\treturn undefined;\n\t\t}\n\t\tif (userIdx >= 0) {\n\t\t\tvar exist = this.state.messages[userIdx];\n\t\t\tvar repl: ChatMessage = { role: 'user', content: exist.content };\n\t\t\tif (exist._serverItemId !== undefined) repl._serverItemId = exist._serverItemId;\n\t\t\tif (exist._ownerKey !== undefined) repl._ownerKey = exist._ownerKey;\n\t\t\tif (exist._ts !== undefined) repl._ts = exist._ts;\n\t\t\tthis.state.messages[userIdx] = repl;\n\t\t}\n\t\tvar thinkingIdx = userIdx >= 0\n\t\t\t? this.state.messages.findIndex(function (m, i) { return i > userIdx && m.isPending && m.role === 'assistant' && !m.isBackgroundTask; })\n\t\t\t: -1;\n\t\treturn thinkingIdx !== -1 ? thinkingIdx : (userIdx >= 0 ? userIdx + 1 : -1);\n\t}\n\n\tinsertAtTarget(msg: ChatMessage, targetIdx: number): void {\n\t\t// Error/direct replies land here rather than through the typewriter, so this\n\t\t// is where they pick up their display time.\n\t\tif (msg && msg.role === 'assistant' && msg._ts === undefined) msg._ts = wallClockNow();\n\t\tif (targetIdx >= 0 && this.state.messages[targetIdx] && this.state.messages[targetIdx].isPending) this.state.messages[targetIdx] = msg;\n\t\telse if (targetIdx >= 0) this.state.messages.splice(targetIdx, 0, msg);\n\t\telse this.state.messages.push(msg);\n\t}\n\n\tonQueuedSendResponse(_composed: string, response: any, platform: string, serverId?: string, ownerKey?: string): void {\n\t\tif (serverId) this.historyItemPolls.delete(serverId);\n\t\t// This turn resolved while a DIFFERENT chat is on screen (the user moved to\n\t\t// another project mid-flight). state.messages now belongs to that chat, and\n\t\t// resolveQueuedUserBubble's positional fallbacks would happily hijack ITS\n\t\t// pending bubble — or, finding nothing, push this answer onto its list.\n\t\t// Settle in the owning chat's cache instead and leave the view untouched.\n\t\tif (ownerKey && this.getHistoryCacheKey() !== ownerKey) {\n\t\t\tvar offReply: ChatMessage = isErrorResponseBody(response)\n\t\t\t\t? { role: 'assistant', content: getErrorMessage(response), isError: true }\n\t\t\t\t: { role: 'assistant', content: ((platform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response)) || '').trim() || 'No text response received from AI provider.' };\n\t\t\tthis._applyReplyToCache(ownerKey, offReply, serverId);\n\t\t\tif (serverId) this.cancelledServerIds.delete(serverId);\n\t\t\treturn;\n\t\t}\n\t\tvar targetIdx = this.resolveQueuedUserBubble(serverId);\n\t\tif (targetIdx === undefined) { this.host.notify(); this.updateHistoryCache(); return; }\n\t\tif (isErrorResponseBody(response)) {\n\t\t\tthis.insertAtTarget({ role: 'assistant', content: getErrorMessage(response), isError: true }, targetIdx);\n\t\t} else {\n\t\t\tvar answer = (platform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response));\n\t\t\tanswer = (answer || '').trim() || 'No text response received from AI provider.';\n\t\t\tvar lid = this._newLocalId();\n\t\t\tif (targetIdx >= 0 && this.state.messages[targetIdx] && this.state.messages[targetIdx].isPending) {\n\t\t\t\tthis.state.messages[targetIdx] = { role: 'assistant', content: '', _localId: lid };\n\t\t\t\tthis.host.notify(); this.enqueueTypewrite(targetIdx, answer, lid);\n\t\t\t} else if (targetIdx >= 0) {\n\t\t\t\tthis.state.messages.splice(targetIdx, 0, { role: 'assistant', content: '', _localId: lid });\n\t\t\t\tthis.host.notify(); this.enqueueTypewrite(targetIdx, answer, lid);\n\t\t\t} else {\n\t\t\t\tvar aiIdx = this.state.messages.length;\n\t\t\t\tthis.state.messages.push({ role: 'assistant', content: '', _localId: lid });\n\t\t\t\tthis.host.notify(); this.enqueueTypewrite(aiIdx, answer, lid);\n\t\t\t}\n\t\t}\n\t\tthis._removeStrayPendingAssistants();\n\t\tthis.promoteNextQueuedToRunning();\n\t\tthis.updateHistoryCache();\n\t\tthis.host.notify();\n\t\t// ARRIVAL, not a user action: only follow if the user is still pinned to\n\t\t// the bottom. Scrolled-up readers keep their position.\n\t\tthis.host.scrollToBottomIfSticky(true);\n\t}\n\n\tonQueuedSendError(_composed: string, err: any, serverId?: string, ownerKey?: string): void {\n\t\tvar self = this;\n\t\tif (serverId) this.historyItemPolls.delete(serverId);\n\t\t// Off-chat resolution — see onQueuedSendResponse. Settle in the owning\n\t\t// chat's cache rather than mutating whatever chat is on screen now.\n\t\tif (ownerKey && this.getHistoryCacheKey() !== ownerKey) {\n\t\t\tvar isGone = err && (err.code === 'NOT_EXISTS' || (err.body && err.body.code === 'NOT_EXISTS'));\n\t\t\tthis._applyReplyToCache(ownerKey, isGone\n\t\t\t\t? { role: 'assistant', content: 'Request was cancelled.', isError: true }\n\t\t\t\t: { role: 'assistant', content: getErrorMessage(err), isError: true }, serverId);\n\t\t\tif (serverId) this.cancelledServerIds.delete(serverId);\n\t\t\treturn;\n\t\t}\n\t\tvar isNotExists = err && (err.code === 'NOT_EXISTS' || (err.body && err.body.code === 'NOT_EXISTS'));\n\t\tif (isNotExists) {\n\t\t\tvar userIdx = serverId\n\t\t\t\t? this.state.messages.findIndex(function (m) { return m._serverItemId === serverId && (m.isPendingInProcess || m.isPendingQueued) && m.role === 'user' && !m.isBackgroundTask; })\n\t\t\t\t: this.state.messages.findIndex(function (m) { return m.isPendingInProcess && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue; });\n\t\t\tif (!serverId && userIdx === -1) {\n\t\t\t\tuserIdx = this.state.messages.findIndex(function (m) { return m.isPendingQueued && m.role === 'user' && !m.isBackgroundTask && !m._useBgQueue; });\n\t\t\t}\n\t\t\tif (userIdx >= 0) {\n\t\t\t\tvar ex = this.state.messages[userIdx];\n\t\t\t\tvar repl: ChatMessage = { role: 'user', content: ex.content, isCancelled: true };\n\t\t\t\tif (ex._serverItemId !== undefined) repl._serverItemId = ex._serverItemId;\n\t\t\t\tthis.state.messages[userIdx] = repl;\n\t\t\t}\n\t\t\tif (serverId) {\n\t\t\t\tvar thById = this.state.messages.findIndex(function (m) { return m._serverItemId === serverId && m.isPending && m.role === 'assistant' && !m.isBackgroundTask; });\n\t\t\t\tif (thById !== -1) this.state.messages.splice(thById, 1);\n\t\t\t\telse if (userIdx >= 0) {\n\t\t\t\t\tvar thPos = this.state.messages.findIndex(function (m, i) { return i > userIdx && m.isPending && m.role === 'assistant' && !m.isBackgroundTask; });\n\t\t\t\t\tif (thPos !== -1) this.state.messages.splice(thPos, 1);\n\t\t\t\t}\n\t\t\t} else if (userIdx >= 0) {\n\t\t\t\tvar thPos2 = this.state.messages.findIndex(function (m, i) { return i > userIdx && m.isPending && m.role === 'assistant' && !m.isBackgroundTask; });\n\t\t\t\tif (thPos2 !== -1) this.state.messages.splice(thPos2, 1);\n\t\t\t}\n\t\t\tif (serverId) this.cancelledServerIds.delete(serverId);\n\t\t\tthis._removeStrayPendingAssistants();\n\t\t\tthis.promoteNextQueuedToRunning(); this.updateHistoryCache(); this.host.notify(); this.host.scrollToBottomIfSticky(true);\n\t\t\treturn;\n\t\t}\n\t\tvar targetIdx = this.resolveQueuedUserBubble(serverId);\n\t\tif (targetIdx === undefined) { this.host.notify(); this.updateHistoryCache(); return; }\n\t\tthis.insertAtTarget({ role: 'assistant', content: getErrorMessage(err), isError: true }, targetIdx);\n\t\tthis._removeStrayPendingAssistants();\n\t\tthis.promoteNextQueuedToRunning(); this.updateHistoryCache(); this.host.notify(); this.host.scrollToBottomIfSticky(true);\n\t}\n\n\tcancelQueuedMessage(msg: ChatMessage, idx: number): void {\n\t\tvar self = this;\n\t\tvar id = this.host.getIdentity();\n\t\tvar serverId = msg._serverItemId;\n\t\tif (!serverId || msg._cancelling) return;\n\t\tvar platform = id.platform;\n\t\tif (platform !== 'claude' && platform !== 'openai') return;\n\t\tvar url = platform === 'claude' ? ANTHROPIC_MESSAGES_API_URL : OPENAI_RESPONSES_API_URL;\n\t\tvar queueBase = id.userId || id.serviceId;\n\t\tvar queue = (msg.isBackgroundTask || msg._useBgQueue) ? queueBase + BG_INDEXING_QUEUE_SUFFIX : queueBase;\n\t\tthis.state.messages[idx] = Object.assign({}, msg, { _cancelling: true, _cancelError: undefined });\n\t\tthis.host.notify();\n\t\tPromise.resolve(this.host.cancelRequest({\n\t\t\turl: url, method: 'POST', id: serverId, queue: queue, service: id.serviceId, owner: id.owner,\n\t\t})).then(function (result: any) {\n\t\t\tif (result && result.removed) {\n\t\t\t\tself.cancelledServerIds.add(serverId as string);\n\t\t\t\tself._stopPoll(serverId as string);\n\t\t\t\tvar qi = self.bgTaskQueue.findIndex(function (e) { return e.id === serverId; });\n\t\t\t\tif (qi !== -1) self.bgTaskQueue.splice(qi, 1);\n\t\t\t\tvar removeIdx = self.state.messages.findIndex(function (m) {\n\t\t\t\t\treturn m._serverItemId === serverId && (m.isPendingQueued || m.isPendingInProcess) && m.role === 'user';\n\t\t\t\t});\n\t\t\t\tif (removeIdx !== -1) {\n\t\t\t\t\t// Carry the background/file markers onto the rebuild. Dropping them\n\t\t\t\t\t// took a cancelled INDEXING pass out of its file's collapsed row\n\t\t\t\t\t// (buildChatDisplayList only groups isBackgroundTask bubbles), so the\n\t\t\t\t\t// row stayed \"Indexing…\" forever while a bare \"Indexing: file\" bubble\n\t\t\t\t\t// appeared beside it.\n\t\t\t\t\tvar wasMsg = self.state.messages[removeIdx];\n\t\t\t\t\tvar cancelledMsg: ChatMessage = { role: 'user', content: wasMsg.content, isCancelled: true, _serverItemId: serverId };\n\t\t\t\t\tif (wasMsg.isBackgroundTask) cancelledMsg.isBackgroundTask = true;\n\t\t\t\t\tif (wasMsg._indexFile) cancelledMsg._indexFile = wasMsg._indexFile;\n\t\t\t\t\tif (wasMsg._useBgQueue) cancelledMsg._useBgQueue = true;\n\t\t\t\t\tif (wasMsg._ownerKey !== undefined) cancelledMsg._ownerKey = wasMsg._ownerKey;\n\t\t\t\t\tself.state.messages[removeIdx] = cancelledMsg;\n\t\t\t\t\tvar thById = self.state.messages.findIndex(function (m) { return m._serverItemId === serverId && m.isPending && m.role === 'assistant'; });\n\t\t\t\t\tif (thById !== -1) self.state.messages.splice(thById, 1);\n\t\t\t\t\telse {\n\t\t\t\t\t\tvar thPos = self.state.messages.findIndex(function (m, i) {\n\t\t\t\t\t\t\treturn i > removeIdx && m.isPending && m.role === 'assistant' &&\n\t\t\t\t\t\t\t\t(msg.isBackgroundTask ? !!m.isBackgroundTask : !m.isBackgroundTask);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (thPos !== -1) self.state.messages.splice(thPos, 1);\n\t\t\t\t\t}\n\t\t\t\t\tif (msg.isBackgroundTask) self.promoteNextBgQueuedToRunning(); else self.promoteNextQueuedToRunning();\n\t\t\t\t\tself.updateHistoryCache();\n\t\t\t\t}\n\t\t\t\tself.host.notify();\n\t\t\t} else {\n\t\t\t\tvar errMsg = result && typeof result.message === 'string' && result.message ? result.message : 'Could not remove from queue.';\n\t\t\t\tvar ci = self.state.messages.findIndex(function (m) { return m._serverItemId === serverId && m.role === 'user'; });\n\t\t\t\tif (ci !== -1) { self.state.messages[ci] = Object.assign({}, self.state.messages[ci], { _cancelling: false, _cancelError: errMsg }); self.host.notify(); }\n\t\t\t}\n\t\t}).catch(function (err: any) {\n\t\t\tvar errMsg = err && typeof err.message === 'string' && err.message ? err.message : 'Could not remove from queue.';\n\t\t\tvar ci = self.state.messages.findIndex(function (m) { return m._serverItemId === serverId && m.role === 'user'; });\n\t\t\tif (ci !== -1) { self.state.messages[ci] = Object.assign({}, self.state.messages[ci], { _cancelling: false, _cancelError: errMsg }); self.host.notify(); }\n\t\t});\n\t}\n\n\t/**\n\t * Stop indexing a file, from its collapsed row — every pass at once, not just\n\t * the bubble the user happens to see.\n\t *\n\t * A big file is indexed as a CHAIN of passes, so cancelling only the live one\n\t * accomplishes nothing: the next pass is dispatched as soon as it settles.\n\t * Three things end the chain:\n\t * 1. every queued/running pass of this file is cancelled server-side\n\t * (csr-cancel deletes a queued row and flags a running one \"cancelled\",\n\t * which is also the worker's gate for NOT enqueueing the next window);\n\t * 2. the file is remembered in cancelledIndexKeys, so the client-driven\n\t * resume (maybeResumeIndexing) stops dispatching CONTINUE passes; and\n\t * 3. any of its passes still sitting in bgTaskQueue is dropped by the next\n\t * drain rather than surfacing a fresh \"Indexing…\" bubble.\n\t *\n\t * Records already written by the passes that DID run are kept — this stops the\n\t * work, it does not undo it.\n\t */\n\tcancelIndexingGroup(group: IndexingGroup): void {\n\t\tvar self = this;\n\t\tif (!group || !group.key) return;\n\t\t// The group belongs to the chat on screen, so scope its key the same way\n\t\t// _indexKeyOf scopes a queued task's.\n\t\tvar scoped = this.getHistoryCacheKey() + '|' + group.key;\n\t\tthis.cancelledIndexKeys.add(scoped);\n\t\tvar ids = group.cancellableIds || [];\n\t\tif (!ids.length) { this.host.notify(); return; }\n\t\tids.forEach(function (serverId) {\n\t\t\t// Address the message by IDENTITY, not by the index captured when the\n\t\t\t// display list was built: an earlier cancel in this same loop may already\n\t\t\t// have spliced the array (a group can have more than one live pass), and a\n\t\t\t// stale index would mark the WRONG bubble as cancelling.\n\t\t\tvar idx = self.state.messages.findIndex(function (m) {\n\t\t\t\treturn m._serverItemId === serverId && m.role === 'user' &&\n\t\t\t\t\t(m.isPendingQueued || m.isPendingInProcess);\n\t\t\t});\n\t\t\tif (idx === -1) return;\n\t\t\tself.cancelQueuedMessage(self.state.messages[idx], idx);\n\t\t});\n\t}\n\n\t// --- typewriter -------------------------------------------------------\n\t// Reveal `fullText` into a message bubble at a constant wall-clock RATE\n\t// (chars/second) driven by requestAnimationFrame, rather than a fixed number\n\t// of characters per fixed-delay tick. This is what keeps typing smooth and\n\t// cheap on slow machines:\n\t//\n\t// * Each frame reveals `elapsed_ms * CHARS_PER_SEC` characters, so the\n\t// visual speed is the same regardless of how long a frame actually took.\n\t// * As the bubble's markdown grows, each re-render gets more expensive, so\n\t// frames get longer — which makes each frame reveal MORE characters and\n\t// therefore do FEWER, larger renders. That converts the old O(n^2)\n\t// \"re-render the whole growing string once per 3 characters\" (which got\n\t// slower and slower and pegged the CPU) into roughly O(n): the number of\n\t// renders self-throttles to what the machine can actually paint.\n\t// * rAF paces us to the browser's paint cycle and pauses in background\n\t// tabs, so we never queue work faster than it can be drawn.\n\ttypewriteIntoIndex(idx: number, fullText: string, localId?: string): Promise<void> {\n\t\tvar self = this;\n\t\tif (!fullText) return Promise.resolve();\n\n\t\tvar CHARS_PER_SEC = 300; // reveal rate (was ~188 = 3 chars / 16ms) — a bit faster\n\t\tvar MIN_STEP = 1; // always make progress, even on a sub-ms frame\n\t\tvar MAX_FRAME_MS = 1000; // cap catch-up after a long stall / backgrounded tab\n\n\t\t// Atomic regions that must never be left half-revealed: file fences\n\t\t// (shown as a download chip / hidden as \"[generating …]\" while unclosed —\n\t\t// and potentially huge, so revealed in one jump) and inline links\n\t\t// (a partial link is broken markdown). If a frame's reveal boundary lands\n\t\t// inside one, snap it to the region end so the chip/link appears whole.\n\t\tvar regions: Array<{ start: number; end: number }> = [], m;\n\t\tvar fenceRegex = /```[^\\n`]+?\\.[^\\s.`]+\\n[\\s\\S]*?```/g;\n\t\twhile ((m = fenceRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });\n\t\tvar linkRegex = createInlineLinkRegex();\n\t\twhile ((m = linkRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });\n\t\tregions.sort(function (a, b) { return a.start - b.start; });\n\n\t\tthis.state.typing = true; this.state.typingAbort = false;\n\t\tvar i = 0;\n\t\tvar last = nowMs();\n\n\t\treturn new Promise<void>(function (resolve) {\n\t\t\tvar done = false;\n\t\t\tvar doc: any = _g.document;\n\t\t\tfunction isHidden(): boolean { return !!(doc && doc.hidden); }\n\t\t\tfunction cleanup(): void {\n\t\t\t\tif (doc && doc.removeEventListener) doc.removeEventListener('visibilitychange', onVisibility);\n\t\t\t}\n\t\t\tfunction finish(): void {\n\t\t\t\tif (done) return;\n\t\t\t\tdone = true;\n\t\t\t\tcleanup();\n\t\t\t\tif (!self.state.typingAbort) {\n\t\t\t\t\t// Re-find the bubble by localId and, if it's gone, bail WITHOUT\n\t\t\t\t\t// writing — never fall back to the numeric idx, which a concurrent\n\t\t\t\t\t// array mutation may have repurposed for an unrelated message\n\t\t\t\t\t// (mirrors frame()'s currentIdx===-1 bail below).\n\t\t\t\t\tvar fi = localId ? self.state.messages.findIndex(function (mm) { return mm._localId === localId; }) : idx;\n\t\t\t\t\tif (fi !== -1) {\n\t\t\t\t\t\tvar t = self.state.messages[fi];\n\t\t\t\t\t\tif (t) { t.content = fullText; self.host.refreshMessageBubble(fi); }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tself.state.typing = false;\n\t\t\t\tresolve();\n\t\t\t}\n\t\t\t// requestAnimationFrame is PAUSED in a backgrounded tab (setTimeout only\n\t\t\t// throttles), so an rAF-driven reveal would freeze there — leaving a blank\n\t\t\t// bubble and stalling the sequential enqueueTypewrite queue until refocus.\n\t\t\t// When the page is (or becomes) hidden, skip the animation and show the\n\t\t\t// full text immediately so the queue keeps draining.\n\t\t\tfunction onVisibility(): void { if (isHidden()) finish(); }\n\t\t\tif (doc && doc.addEventListener) doc.addEventListener('visibilitychange', onVisibility);\n\t\t\tfunction frame(t: number): void {\n\t\t\t\tif (done) return;\n\t\t\t\tif (self.state.typingAbort || i >= fullText.length || isHidden()) { finish(); return; }\n\n\t\t\t\tvar dt = t - last; last = t;\n\t\t\t\tif (!(dt > 0)) dt = 16; // first frame / clock glitch\n\t\t\t\tif (dt > MAX_FRAME_MS) dt = MAX_FRAME_MS;\n\t\t\t\tvar step = Math.round(dt * CHARS_PER_SEC / 1000);\n\t\t\t\tif (step < MIN_STEP) step = MIN_STEP;\n\t\t\t\tvar next = Math.min(fullText.length, i + step);\n\n\t\t\t\t// Extend past any atomic region the newly-revealed span (i, next]\n\t\t\t\t// cuts into. Iterate to convergence so back-to-back regions (e.g. a\n\t\t\t\t// link right after a fence) are all revealed whole in one frame.\n\t\t\t\tfor (var changed = true; changed;) {\n\t\t\t\t\tchanged = false;\n\t\t\t\t\tfor (var k = 0; k < regions.length; k++) {\n\t\t\t\t\t\tvar r = regions[k];\n\t\t\t\t\t\tif (next > r.start && i < r.end && r.end > next) { next = r.end; changed = true; }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (next > fullText.length) next = fullText.length;\n\t\t\t\ti = next;\n\n\t\t\t\tvar currentIdx = localId ? self.state.messages.findIndex(function (mm) { return mm._localId === localId; }) : idx;\n\t\t\t\tif (currentIdx === -1) { finish(); return; }\n\t\t\t\tvar target = self.state.messages[currentIdx];\n\t\t\t\tif (!target) { finish(); return; }\n\t\t\t\ttarget.content = fullText.slice(0, i);\n\t\t\t\tself.host.refreshMessageBubble(currentIdx);\n\t\t\t\tself.host.scrollToBottomIfSticky();\n\t\t\t\tnextFrame(frame);\n\t\t\t}\n\t\t\tif (isHidden()) { finish(); return; }\n\t\t\tnextFrame(frame);\n\t\t});\n\t}\n\n\tprivate typewriterQueue: Promise<any> = Promise.resolve();\n\tenqueueTypewrite(idx: number, fullText: string, localId?: string): Promise<any> {\n\t\tvar self = this;\n\t\t// Stamp the reply bubble's display time as it starts revealing. This is the\n\t\t// single chokepoint every typed reply (immediate, queued, and bg-resolution)\n\t\t// passes through, so it is where a live reply gets its \"when it arrived\"\n\t\t// timestamp; a history reload later replaces it with the server `updated`.\n\t\tvar target = this.state.messages[idx];\n\t\tif (target && target._ts === undefined) target._ts = wallClockNow();\n\t\tthis.typewriterQueue = this.typewriterQueue.then(function () { return self.typewriteIntoIndex(idx, fullText, localId); });\n\t\treturn this.typewriterQueue;\n\t}\n\n\t// --- cache+resume immediate-send rendering -----------------------------\n\t// Render the just-resolved reply (read from aiChatHistoryCache) into the\n\t// pending assistant bubble, character-by-character. Runs AFTER the reply is\n\t// already in the cache (dispatchAgentRequest appended it); errors are shown\n\t// instantly (no typing). Promotes the next queued message immediately so its\n\t// \"Thinking…\" bubble appears without waiting for this typewriter to finish.\n\ttypewriteLatestReply(key: string): Promise<any> {\n\t\tvar cached = this.aiChatHistoryCache[key];\n\t\tif (!cached || !cached.messages.length) return Promise.resolve();\n\t\tvar latest: ChatMessage | undefined;\n\t\tfor (var i = cached.messages.length - 1; i >= 0; i--) {\n\t\t\tvar m = cached.messages[i];\n\t\t\tif (m.role === 'assistant' && !m.isPending) { latest = m; break; }\n\t\t}\n\t\tif (!latest) return Promise.resolve();\n\t\tvar pendingIdx = this.state.messages.findIndex(function (mm) {\n\t\t\treturn mm.isPending && mm.role === 'assistant' && !mm.isBackgroundTask;\n\t\t});\n\t\tif (pendingIdx === -1) return Promise.resolve();\n\t\tif (latest.isError || !latest.content) {\n\t\t\tthis.state.messages[pendingIdx] = { role: 'assistant', content: latest.content || '', isError: !!latest.isError };\n\t\t\tthis._removeStrayPendingAssistants();\n\t\t\tthis.host.notify();\n\t\t\tthis.promoteNextQueuedToRunning();\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tvar lid = this._newLocalId();\n\t\tthis.state.messages[pendingIdx] = { role: 'assistant', content: '', isPending: false, _localId: lid };\n\t\tthis._removeStrayPendingAssistants();\n\t\tthis.host.notify();\n\t\tthis.promoteNextQueuedToRunning();\n\t\treturn this.enqueueTypewrite(pendingIdx, latest.content, lid);\n\t}\n\n\t// Remove any leftover non-background pending (\"Thinking…\") assistant bubbles.\n\t// There is normally at most ONE such bubble at a time (promoteNext* refuses to\n\t// add a second), so any extra is a duplicate — it appears when a concurrent\n\t// history refetch re-maps the still-\"running\" turn into a pending placeholder\n\t// (with a real _serverItemId) while the local pending bubble (no _serverItemId)\n\t// is rescued and re-appended (see loadHistory rescue below). Each resolve path\n\t// only replaces the FIRST pending bubble, so without this a stray \"Thinking…\"\n\t// survives next to the reply/error. MUST run AFTER the resolved bubble has been\n\t// made non-pending and BEFORE promoteNext*() (so a freshly-promoted Thinking,\n\t// which is added only once no pending assistant remains, is preserved).\n\t_removeStrayPendingAssistants(): void {\n\t\tfor (var k = this.state.messages.length - 1; k >= 0; k--) {\n\t\t\tvar m = this.state.messages[k];\n\t\t\tif (m.isPending && m.role === 'assistant' && !m.isBackgroundTask) this.state.messages.splice(k, 1);\n\t\t}\n\t}\n\n\t// Drop the pending flags on the resolved turn's USER bubble (preserving its\n\t// content + background-task marker). Needed because a bg \"Indexing:\" turn's user\n\t// bubble carries isPendingInProcess; leaving it set keeps the bubble visually\n\t// stuck and keeps its bgTaskQueue entry alive forever.\n\t_clearPendingUserBubble(itemId: string): void {\n\t\tvar uIdx = this.state.messages.findIndex(function (m) {\n\t\t\treturn m.role === 'user' && m._serverItemId === itemId &&\n\t\t\t\t(m.isPendingInProcess || m.isPendingQueued || m.isSendingToServer);\n\t\t});\n\t\tif (uIdx === -1) return;\n\t\tvar u = this.state.messages[uIdx];\n\t\tvar cleaned: ChatMessage = { role: 'user', content: u.content, _serverItemId: itemId };\n\t\tif (u.isBackgroundTask) cleaned.isBackgroundTask = true;\n\t\tif (u._ts !== undefined) cleaned._ts = u._ts;\n\t\t// Carry the file ref: it is what keeps this pass in its file's collapsed\n\t\t// row (the label parser is only a fallback for older cached bubbles).\n\t\tif (u._indexFile) cleaned._indexFile = u._indexFile;\n\t\tthis.state.messages[uIdx] = cleaned;\n\t}\n\n\t// If an immediate-send request for the current cache key is still in flight\n\t// (e.g. the view unmounted then remounted mid-request), show the sending\n\t// state, await it, then render the reply from the cache. Skipped when the\n\t// list already has its own pending/queued bubbles (those resolve via their\n\t// own polls). The displayed reply also lands via dispatchComposedMessage's\n\t// own finally if the view never unmounted — this is the remount recovery.\n\tresumePendingRequest(token: number): Promise<void> {\n\t\tvar self = this;\n\t\tvar key = this.getHistoryCacheKey();\n\t\tvar pending = key ? this.pendingAgentRequests[key] : undefined;\n\t\tif (!pending) return Promise.resolve();\n\t\tif (this.state.messages.some(function (m) { return (m.isPending || m.isPendingQueued) && !m.isBackgroundTask && !m._useBgQueue; })) return Promise.resolve();\n\t\tthis.state.sending = true;\n\t\tthis.host.scrollToBottomIfSticky(true);\n\t\treturn Promise.resolve(pending).catch(function () { }).then(function () {\n\t\t\tif (token !== self.state.gateRefreshToken) return;\n\t\t\tself.state.sending = false;\n\t\t\treturn Promise.resolve(self.typewriteLatestReply(key)).then(function () { self.host.scrollToBottomIfSticky(true); });\n\t\t});\n\t}\n\n\t// --- background-task resolution + drain -------------------------------\n\thandleHistoryItemResolution(itemId: string, response: any, platform: string): void {\n\t\t// Which file this turn was indexing, read BEFORE the resolution rewrites the\n\t\t// bubbles. Every settling turn funnels through here — the bg drain's own\n\t\t// poll, the history poll, and agent.vue's forked history poll, which calls\n\t\t// straight into this method — so hooking the chain follow-up here is what\n\t\t// makes it work in both clients without either of them forking a call site.\n\t\tvar indexRef = this._indexRefOfItem(itemId);\n\t\tthis.applyHistoryItemResolution(itemId, response, platform);\n\t\tthis.promoteNextBgQueuedToRunning();\n\t\t// A worker-driven chain has no client-side record of its next pass, so a\n\t\t// settling pass is the only moment there is to go looking for one.\n\t\tif (indexRef) this._followWorkerIndexingChain(indexRef.name, indexRef.mime);\n\t}\n\n\t/** The file an already-rendered background pass is about, off its request\n\t * bubble. Null for an ordinary turn, which is most of them. */\n\tprivate _indexRefOfItem(itemId: string): { name?: string; mime?: string } | null {\n\t\tif (!itemId) return null;\n\t\tfor (var i = 0; i < this.state.messages.length; i++) {\n\t\t\tvar m = this.state.messages[i];\n\t\t\tif (m._serverItemId !== itemId || m.role !== 'user' || !m.isBackgroundTask) continue;\n\t\t\treturn m._indexFile || null;\n\t\t}\n\t\treturn null;\n\t}\n\n\tapplyHistoryItemResolution(itemId: string, response: any, platform: string): void {\n\t\tthis.historyItemPolls.delete(itemId);\n\t\tvar isErr = isErrorResponseBody(response);\n\t\tvar answer = isErr ? getErrorMessage(response)\n\t\t\t: ((platform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response)) || '').trim();\n\t\t// Hide the internal indexing-completion marker from the displayed summary.\n\t\tif (!isErr && answer) answer = answer.split(INDEXING_COMPLETE_MARKER).join('').trim();\n\t\tvar idx = this.state.messages.findIndex(function (m) { return m.isPending && m._serverItemId === itemId; });\n\t\tif (idx !== -1) {\n\t\t\t// A bg \"Indexing:\" turn pushes a user bubble (isPendingInProcess) ALONGSIDE\n\t\t\t// the assistant Thinking; replacing only the assistant leaves that user\n\t\t\t// bubble stuck pending — and drainBgTaskQueue then never clears its queue\n\t\t\t// entry (its stillPending check stays true). Un-pend it here too.\n\t\t\tthis._clearPendingUserBubble(itemId);\n\t\t\t// Carry isBackgroundTask onto the REPLACEMENT. These rebuilds are fresh\n\t\t\t// object literals, so anything not copied is lost — and dropping this flag\n\t\t\t// made a pass that resolved LIVE fall out of its file's collapsed row\n\t\t\t// (buildChatDisplayList only considers isBackgroundTask messages), while\n\t\t\t// the same pass rebuilt from history stayed grouped. That mismatch is the\n\t\t\t// \"new indexing response renders outside the group\" bug.\n\t\t\tvar wasBgTask = !!this.state.messages[idx].isBackgroundTask;\n\t\t\tif (isErr) {\n\t\t\t\tthis.state.messages[idx] = { role: 'assistant', content: answer, isError: true, _serverItemId: itemId };\n\t\t\t\tif (wasBgTask) this.state.messages[idx].isBackgroundTask = true;\n\t\t\t\tthis.host.notify(); this.updateHistoryCache(); return;\n\t\t\t}\n\t\t\tvar text = answer || 'No text response received from AI provider.';\n\t\t\t// A background-indexing reply is INSIDE a collapsed row: nothing of it is\n\t\t\t// on screen. Typewriting it anyway put it on the one shared, serial\n\t\t\t// typewriter queue, so the user's own next reply — which IS on screen —\n\t\t\t// lost its \"Thinking...\" spinner and sat as an EMPTY bubble for however\n\t\t\t// long the invisible indexing summary took to reveal (seconds per pass,\n\t\t\t// additive across files). It also held state.typing true for the whole\n\t\t\t// time, which disables the platform/model pickers and no-ops Clear\n\t\t\t// history, and ran a per-frame scroll for content nobody can see.\n\t\t\t// Write it straight in; expanding the row then shows it complete.\n\t\t\tif (wasBgTask) {\n\t\t\t\tthis.state.messages[idx] = { role: 'assistant', content: text, isBackgroundTask: true, _serverItemId: itemId };\n\t\t\t\tthis.host.notify(); this.updateHistoryCache(); return;\n\t\t\t}\n\t\t\tvar lid = this._newLocalId();\n\t\t\tthis.state.messages[idx] = { role: 'assistant', content: '', _localId: lid, _serverItemId: itemId };\n\t\t\tthis.host.notify(); this.enqueueTypewrite(idx, text, lid);\n\t\t\tthis.updateHistoryCache(); return;\n\t\t}\n\t\tvar userIdx = this.state.messages.findIndex(function (m) {\n\t\t\treturn m.role === 'user' && m._serverItemId === itemId && (m.isPendingQueued || m.isPendingInProcess);\n\t\t});\n\t\tif (userIdx === -1) return;\n\t\tvar ex = this.state.messages[userIdx];\n\t\t// Same carry-over as above, plus _indexFile / _useBgQueue: this rebuild is\n\t\t// what keeps an indexing REQUEST bubble in its file's collapsed row (and a\n\t\t// bg-queued chat cancelling against the right queue) once the pass settles.\n\t\tvar settledUser: ChatMessage = { role: 'user', content: ex.content, _serverItemId: itemId };\n\t\tif (ex.isBackgroundTask) settledUser.isBackgroundTask = true;\n\t\tif (ex._ts !== undefined) settledUser._ts = ex._ts;\n\t\tif (ex._indexFile) settledUser._indexFile = ex._indexFile;\n\t\tif (ex._useBgQueue) settledUser._useBgQueue = true;\n\t\tthis.state.messages[userIdx] = settledUser;\n\t\tif (isErr) {\n\t\t\tvar errReply: ChatMessage = { role: 'assistant', content: answer, isError: true, _serverItemId: itemId };\n\t\t\tif (ex.isBackgroundTask) errReply.isBackgroundTask = true;\n\t\t\tthis.state.messages.splice(userIdx + 1, 0, errReply);\n\t\t\tthis.host.notify(); this.updateHistoryCache(); return;\n\t\t}\n\t\tvar text2 = answer || 'No text response received from AI provider.';\n\t\t// Same as above: a collapsed row's reply is not on screen, so revealing it\n\t\t// character by character only blocks the queue the visible reply needs.\n\t\tif (ex.isBackgroundTask) {\n\t\t\tthis.state.messages.splice(userIdx + 1, 0, { role: 'assistant', content: text2, isBackgroundTask: true, _serverItemId: itemId });\n\t\t\tthis.host.notify(); this.updateHistoryCache(); return;\n\t\t}\n\t\tvar lid2 = this._newLocalId();\n\t\tvar reply: ChatMessage = { role: 'assistant', content: '', _localId: lid2, _serverItemId: itemId };\n\t\tthis.state.messages.splice(userIdx + 1, 0, reply);\n\t\tthis.host.notify(); this.enqueueTypewrite(userIdx + 1, text2, lid2);\n\t\tthis.updateHistoryCache();\n\t}\n\n\t/** How a bg task maps onto a collapsed row: the row's own key (storage path\n\t * when known, else the filename), scoped to the chat it belongs to. A storage\n\t * path is project-relative (\"report.xlsx\"), and ONE ChatSession serves every\n\t * project — unscoped, stopping a file in one project would silently suppress\n\t * the same filename's continuations in another. */\n\tprivate _indexKeyOf(entry: BgTaskEntry): string {\n\t\tif (!entry) return '';\n\t\tvar file = entry.storagePath || entry.filename;\n\t\tif (!file) return '';\n\t\treturn entry.serviceId + '#' + entry.platform + '|' + file;\n\t}\n\n\t/**\n\t * Reconcile the bg queue with the files the user has stopped.\n\t *\n\t * A FIRST pass (no resumePass) is a fresh indexing request — a re-upload, or a\n\t * Reindex from the file manager — so it LIFTS the stop: the key is a storage\n\t * path, and without this an earlier cancel would silently kill every future\n\t * index of the same path. A continuation of a stopped file is dropped instead,\n\t * covering the pass that was dispatched in the moment before the cancel landed.\n\t */\n\tprivate _applyIndexCancellations(): void {\n\t\tif (!this.cancelledIndexKeys.size) return;\n\t\tfor (var i = this.bgTaskQueue.length - 1; i >= 0; i--) {\n\t\t\tvar entry = this.bgTaskQueue[i];\n\t\t\tvar key = this._indexKeyOf(entry);\n\t\t\tif (!key || !this.cancelledIndexKeys.has(key)) continue;\n\t\t\tif (!entry.resumePass) { this.cancelledIndexKeys.delete(key); continue; }\n\t\t\tthis.bgTaskQueue.splice(i, 1);\n\t\t\tthis._stopPoll(entry.id);\n\t\t\tthis._cancelServerItem(entry.id);\n\t\t}\n\t}\n\n\t/**\n\t * Cancel any live pass of a stopped file that turned up on its own.\n\t *\n\t * The client is not the only thing that continues a file: for PDFs and (when\n\t * windowed indexing is on) text/grid files the WORKER enqueues the next window\n\t * itself, and that pass reaches the chat through the history poll, never\n\t * through bgTaskQueue. The worker's own gate stops the chain when the running\n\t * row is cancelled — but if the row had already finished when the user hit\n\t * stop, the next window was queued a moment earlier and still arrives. Stop it\n\t * here rather than making the user hit stop again.\n\t *\n\t * Runs from drainBgTaskQueue, which both clients call after a history load.\n\t */\n\tprivate _sweepCancelledIndexing(): void {\n\t\tif (!this.cancelledIndexKeys.size) return;\n\t\tvar self = this;\n\t\tvar chatKey = this.getHistoryCacheKey();\n\t\tvar targets: { msg: ChatMessage; idx: number }[] = [];\n\t\tthis.state.messages.forEach(function (m, i) {\n\t\t\tif (!m.isBackgroundTask || m.role !== 'user' || !m._serverItemId) return;\n\t\t\tif (m._cancelling || m.isSendingToServer) return;\n\t\t\tif (!(m.isPendingQueued || m.isPendingInProcess)) return;\n\t\t\tvar ref = m._indexFile;\n\t\t\tvar file = ref && (ref.path || ref.name);\n\t\t\tif (!file || !self.cancelledIndexKeys.has(chatKey + '|' + file)) return;\n\t\t\ttargets.push({ msg: m, idx: i });\n\t\t});\n\t\ttargets.forEach(function (t) {\n\t\t\tvar idx = self.state.messages.indexOf(t.msg);\n\t\t\tself.cancelQueuedMessage(t.msg, idx === -1 ? t.idx : idx);\n\t\t});\n\t}\n\n\t/**\n\t * True when the WORKER, not this client, drives the rest of this file's chain.\n\t * The mirror image of the early returns in maybeResumeIndexing: whatever that\n\t * refuses to continue is exactly what nothing client-side is tracking.\n\t */\n\tprivate _isWorkerDrivenIndexing(filename?: string, mime?: string): boolean {\n\t\tif (!isPagedReadFile(filename, mime)) return false;\n\t\tif (isImageVisionFile(filename, mime)) return true;\n\t\treturn windowedIndexingEnabled() && isWindowedReadFile(filename, mime);\n\t}\n\n\t/**\n\t * Pick up indexing passes the WORKER minted, which no client ever dispatched.\n\t *\n\t * For a PDF (and for text/grid when windowed indexing is on) the worker writes\n\t * pass N+1's row itself, inside pass N's invocation, right after saving pass\n\t * N's result. That row reaches this client through nothing at all: it is not in\n\t * bgTaskQueue (the client never asked for it) and it is not in state.messages\n\t * (only a first-page history load maps it in, which happens on mount, project\n\t * switch or tab return). So between two worker passes every pass the client\n\t * knows about is settled, and the collapsed row renders \"Indexed N passes\"\n\t * with no spinner and no Stop, for a file that is still being read. A user who\n\t * believes that then asks questions against a half-indexed file — which is what\n\t * this exists to prevent.\n\t *\n\t * So when a background indexing pass settles, ask the bg queue what is still\n\t * unresolved on it and adopt anything unknown as an ordinary BgTaskEntry.\n\t * drainBgTaskQueue then treats it exactly like a pass this client dispatched:\n\t * same bubble, same `_indexFile` (so it joins the file's collapsed row), same\n\t * poll — and that poll settling runs this again, so the chain is followed to\n\t * its end. `status`-scoped so the reply carries the live items only, never a\n\t * page of finished ones with their bodies.\n\t *\n\t * Termination: the only trigger is a pass SETTLING, which happens once per\n\t * pass. An adopted item that is still running is not re-adopted (its id is\n\t * already polled), and when the queue holds nothing unknown the chain stops on\n\t * its own. Nothing here is periodic — a timer that re-reads history is the\n\t * shape that previously looped fetchHistoryPage after an already-DONE index.\n\t */\n\tprivate _adoptingWorkerPasses = false;\n\tprivate _adoptWorkerIndexingPasses(attempt: number): void {\n\t\tvar self = this;\n\t\t// One in flight at a time. The query is queue-WIDE, so a second file's pass\n\t\t// settling in the same moment is covered by the query already running.\n\t\tif (this._adoptingWorkerPasses) return;\n\t\tvar id = this.host.getIdentity();\n\t\tvar platform = id.platform;\n\t\tif (!id.serviceId || (platform !== 'claude' && platform !== 'openai')) return;\n\t\tif (this.isPollingPaused() || !this.host.isViewMounted()) return;\n\t\tvar svcId = id.serviceId, owner = id.owner;\n\t\tvar queue = (id.userId || id.serviceId) + BG_INDEXING_QUEUE_SUFFIX;\n\t\tvar ask = function (status: 'pending' | 'running') {\n\t\t\treturn Promise.resolve(getChatHistory(\n\t\t\t\t{ service: svcId, owner: owner, platform: platform as 'claude' | 'openai', queue: queue, status: status },\n\t\t\t\t{ limit: WORKER_PASS_ADOPT_LIMIT },\n\t\t\t)).catch(function () { return null; });\n\t\t};\n\t\tthis._adoptingWorkerPasses = true;\n\t\tPromise.all([ask('running'), ask('pending')]).then(function (results: any[]) {\n\t\t\tself._adoptingWorkerPasses = false;\n\t\t\t// The chat may have changed under the query; adopting into another\n\t\t\t// project's session is the cross-project bubble leak all over again.\n\t\t\tvar now = self.host.getIdentity();\n\t\t\tif (now.serviceId !== svcId || now.platform !== platform) return;\n\t\t\tif (!self.host.isViewMounted()) return;\n\t\t\tvar adoptedIds: string[] = [];\n\t\t\tfor (var ri = 0; ri < results.length; ri++) {\n\t\t\t\tvar list = results[ri] && Array.isArray(results[ri].list) ? results[ri].list : [];\n\t\t\t\tfor (var i = 0; i < list.length; i++) {\n\t\t\t\t\tif (self._adoptWorkerIndexingItem(list[i], svcId, platform as 'claude' | 'openai')) adoptedIds.push(list[i].id);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (adoptedIds.length) {\n\t\t\t\tself.drainBgTaskQueue();\n\t\t\t\t// Only an item the drain KEPT means the chain is still going. One it\n\t\t\t\t// threw straight back out is not progress and must not end the ladder:\n\t\t\t\t// the status index is eventually consistent, so a look taken the\n\t\t\t\t// instant a pass settles can still report that pass as running, and a\n\t\t\t\t// pass belonging to a file the user stopped is dropped on sight. Both\n\t\t\t\t// used to read as \"found the next pass\", which ended the search for a\n\t\t\t\t// pass that had not been written yet.\n\t\t\t\tif (self._isTrackingAny(adoptedIds)) return;\n\t\t\t}\n\t\t\t// Nothing yet. The worker writes pass N+1 a few milliseconds AFTER it\n\t\t\t// flips pass N to resolved, so a poll that lands in that gap sees an\n\t\t\t// empty queue for a chain that is very much alive — and with no pass\n\t\t\t// left to settle, nothing would ever ask again. Look once or twice more\n\t\t\t// before believing the file is finished.\n\t\t\tif (attempt + 1 >= WORKER_PASS_ADOPT_ATTEMPTS.length) return;\n\t\t\tsetTimeout(function () {\n\t\t\t\tvar later = self.host.getIdentity();\n\t\t\t\tif (later.serviceId !== svcId || later.platform !== platform) return;\n\t\t\t\tif (self.isPollingPaused() || !self.host.isViewMounted()) return;\n\t\t\t\tself._adoptWorkerIndexingPasses(attempt + 1);\n\t\t\t}, WORKER_PASS_ADOPT_ATTEMPTS[attempt + 1]);\n\t\t}, function () { self._adoptingWorkerPasses = false; });\n\t}\n\n\t/** Any of these ids still queued or still polled, i.e. surviving work. */\n\tprivate _isTrackingAny(ids: string[]): boolean {\n\t\tfor (var i = 0; i < ids.length; i++) {\n\t\t\tif (this.historyItemPolls.has(ids[i])) return true;\n\t\t\tfor (var q = 0; q < this.bgTaskQueue.length; q++) {\n\t\t\t\tif (this.bgTaskQueue[q].id === ids[i]) return true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/** One live bg-queue item -> a BgTaskEntry, if it is an indexing pass this\n\t * client is not already tracking. Returns whether it was adopted. */\n\tprivate _adoptWorkerIndexingItem(item: any, svcId: string, platform: 'claude' | 'openai'): boolean {\n\t\tif (!item || typeof item.id !== 'string' || !item.id) return false;\n\t\tif (item.status !== 'pending' && item.status !== 'running') return false;\n\t\tif (typeof item.poll !== 'function') return false;\n\t\t// Already known: a pass this client dispatched, or one adopted earlier that\n\t\t// has not settled yet. Adopting twice would stack a second poll on one item.\n\t\tif (this.historyItemPolls.has(item.id)) return false;\n\t\tfor (var q = 0; q < this.bgTaskQueue.length; q++) {\n\t\t\tif (this.bgTaskQueue[q].id === item.id) return false;\n\t\t}\n\t\t// Already SETTLED here. The status index is eventually consistent, so the\n\t\t// pass that just finished can still come back as running; re-adopting it\n\t\t// would re-poll a dead item and, worse, read as the chain continuing.\n\t\tfor (var m = 0; m < this.state.messages.length; m++) {\n\t\t\tvar msg = this.state.messages[m];\n\t\t\tif (msg._serverItemId !== item.id) continue;\n\t\t\tif (!(msg.isPending || msg.isPendingInProcess || msg.isPendingQueued)) return false;\n\t\t}\n\t\t// The bg queue also carries ordinary chats routed onto it (_isOnBgQueue), and\n\t\t// both platforms share one queue name, so check the shape as well: a claude\n\t\t// request body has `messages`, an openai one has `input`. Adopting the other\n\t\t// platform's item would poll it against this platform's url.\n\t\tvar body = item.request_body;\n\t\tif (!body || typeof body !== 'object') return false;\n\t\tif (platform === 'claude' ? !Array.isArray((body as any).messages) : !Array.isArray((body as any).input)) return false;\n\t\tvar userText = extractLastUserTextFromRequest(body);\n\t\tif (!isIndexingRequestText(userText)) return false;\n\t\tvar ref = parseIndexingRequestText(userText);\n\t\tif (!ref || !ref.name) return false;\n\t\t// Only chains the worker drives. A client-driven file is already tracked by\n\t\t// the entry that dispatched it, and adopting a copy of it would hand\n\t\t// maybeResumeIndexing an entry whose resumePass no longer counts that\n\t\t// chain's passes — which is the cap that stops it running forever.\n\t\tif (!this._isWorkerDrivenIndexing(ref.name, ref.mime)) return false;\n\t\tthis.bgTaskQueue.push({\n\t\t\tserviceId: svcId,\n\t\t\tplatform: platform,\n\t\t\tid: item.id,\n\t\t\tfilename: ref.name,\n\t\t\tstoragePath: ref.path,\n\t\t\tmime: ref.mime,\n\t\t\tsize: ref.size,\n\t\t\tstatus: item.status === 'running' ? 'running' : 'pending',\n\t\t\tpoll: item.poll,\n\t\t\t// Drives the \"(continuing)\" label and marks this as a continuation for\n\t\t\t// _applyIndexCancellations, which must not read a CONTINUE pass as the\n\t\t\t// fresh first pass that lifts a stop.\n\t\t\tresumePass: ref.continued ? 1 : 0,\n\t\t});\n\t\treturn true;\n\t}\n\n\t/** Follow the chain on from a background indexing pass that just settled. */\n\tprivate _followWorkerIndexingChain(filename?: string, mime?: string): void {\n\t\tif (!this._isWorkerDrivenIndexing(filename, mime)) return;\n\t\tthis._adoptWorkerIndexingPasses(0);\n\t}\n\n\t/** Best-effort server-side cancel of a bg-queue item that has no bubble (so\n\t * cancelQueuedMessage, which drives one, has nothing to act on). */\n\tprivate _cancelServerItem(serverId: string): void {\n\t\tvar id = this.host.getIdentity();\n\t\tif (!serverId || (id.platform !== 'claude' && id.platform !== 'openai')) return;\n\t\tvar url = id.platform === 'claude' ? ANTHROPIC_MESSAGES_API_URL : OPENAI_RESPONSES_API_URL;\n\t\tPromise.resolve(this.host.cancelRequest({\n\t\t\turl: url, method: 'POST', id: serverId,\n\t\t\tqueue: (id.userId || id.serviceId) + BG_INDEXING_QUEUE_SUFFIX,\n\t\t\tservice: id.serviceId, owner: id.owner,\n\t\t})).catch(function () { /* the pass may already have finished; nothing to do */ });\n\t}\n\n\t// Inject \"Indexing: <file>\" bubbles for queued bg tasks + attach their polls.\n\tdrainBgTaskQueue(): void {\n\t\tvar self = this;\n\t\tvar id = this.host.getIdentity();\n\t\tvar svcId = id.serviceId, plat = id.platform;\n\t\tif (!svcId || plat === 'none' || !this.host.isViewMounted()) return;\n\t\t// Before anything is surfaced: drop continuations of files the user stopped\n\t\t// (and let a fresh first pass lift the stop), then cancel any worker-queued\n\t\t// pass of a stopped file that reached the chat through history.\n\t\tthis._applyIndexCancellations();\n\t\tthis._sweepCancelledIndexing();\n\t\t// Index messages by _serverItemId ONCE, so the per-entry presence/pending\n\t\t// checks below are O(1) instead of a full messages.some() scan each. With a\n\t\t// large bg queue (bulk uploads) the old nested scan was O(queue x messages)\n\t\t// per drain, and the drain runs once per uploaded file (O(n^3) overall).\n\t\tvar presentIds: { [id: string]: boolean } = {};\n\t\tvar pendingIds: { [id: string]: boolean } = {};\n\t\tthis.state.messages.forEach(function (m) {\n\t\t\tvar sid = m._serverItemId;\n\t\t\tif (sid == null) return;\n\t\t\tpresentIds[sid] = true;\n\t\t\tif (m.isPending || m.isPendingInProcess || m.isPendingQueued) pendingIds[sid] = true;\n\t\t});\n\t\tfor (var i = this.bgTaskQueue.length - 1; i >= 0; i--) {\n\t\t\tvar e = this.bgTaskQueue[i];\n\t\t\tif (e.serviceId !== svcId || e.platform !== plat) continue;\n\t\t\tif (presentIds[e.id] && !pendingIds[e.id]) this.bgTaskQueue.splice(i, 1);\n\t\t}\n\t\tthis.bgTaskQueue.forEach(function (entry) {\n\t\t\tif (entry.serviceId !== svcId || entry.platform !== plat) return;\n\t\t\t// Bubble injection and poll attachment are INDEPENDENT. An entry whose bubble\n\t\t\t// already exists may still need a poll — that is exactly the state a paused\n\t\t\t// drain leaves behind, and returning early here stranded it as a permanent\n\t\t\t// \"Thinking...\" once polling resumed.\n\t\t\tif (!presentIds[entry.id]) {\n\t\t\tvar isRunning = entry.status === 'running';\n\t\t\tvar userBubble: ChatMessage = {\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: self.host.formatIndexingLabel(entry.filename, entry.mime, entry.size, entry.storagePath, entry.isReindex, !!entry.resumePass),\n\t\t\t\tisBackgroundTask: true,\n\t\t\t\t_serverItemId: entry.id,\n\t\t\t\t// Structured ref so this live pass groups with the same file's passes\n\t\t\t\t// rebuilt from history (see indexing_groups.buildChatDisplayList).\n\t\t\t\t_indexFile: {\n\t\t\t\t\tname: entry.filename,\n\t\t\t\t\tpath: entry.storagePath,\n\t\t\t\t\tmime: entry.mime,\n\t\t\t\t\tsize: entry.size,\n\t\t\t\t\tisReindex: !!entry.isReindex,\n\t\t\t\t\tcontinued: !!entry.resumePass,\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (isRunning) userBubble.isPendingInProcess = true; else userBubble.isPendingQueued = true;\n\t\t\tself.state.messages.push(userBubble);\n\t\t\tif (isRunning) {\n\t\t\t\tself.state.messages.push({ role: 'assistant', content: '', isPending: true, isPendingInProcess: true, isBackgroundTask: true, _serverItemId: entry.id });\n\t\t\t}\n\t\t\tpresentIds[entry.id] = true; // keep the index consistent with the pushed bubbles\n\t\t\tself.host.notify(); self.updateHistoryCache(); self.host.scrollToBottomIfSticky(false);\n\t\t\t}\n\t\t\tif (!self.isPollingPaused() && !self.historyItemPolls.has(entry.id) && typeof entry.poll === 'function') {\n\t\t\t\tvar capturedId = entry.id, capturedPlat = plat;\n\t\t\t\tvar capturedEntry = entry;\n\t\t\t\tvar wasStopped = false;\n\t\t\t\tvar bp = entry.poll({ latency: POLL_INTERVAL });\n\t\t\t\tself._trackPoll(entry.id, 'bg', bp);\n\t\t\t\tbp.then(function (response: any) {\n\t\t\t\t\t// A stopped poll is not a result: leave the bubble and the queue entry\n\t\t\t\t\t// exactly as they were so resumePolling can re-attach.\n\t\t\t\t\tif (isPollStopped(response)) { wasStopped = true; return; }\n\t\t\t\t\tself.handleHistoryItemResolution(capturedId, response, capturedPlat);\n\t\t\t\t\tself.maybeResumeIndexing(capturedEntry, response, capturedPlat);\n\t\t\t\t}).catch(function (err: any) {\n\t\t\t\t\tself.historyItemPolls.delete(capturedId);\n\t\t\t\t\tvar isNotExists = err && (err.code === 'NOT_EXISTS' || (err.body && err.body.code === 'NOT_EXISTS'));\n\t\t\t\t\t// Settle the REQUEST bubble first, unconditionally. Only a RUNNING\n\t\t\t\t\t// pass gets an assistant placeholder, so for a queued one the lookup\n\t\t\t\t\t// below finds nothing and every branch was skipped — leaving the\n\t\t\t\t\t// request bubble isPendingQueued with its queue entry about to be\n\t\t\t\t\t// spliced away, i.e. no poll left to ever clear it. One such bubble\n\t\t\t\t\t// pins the whole collapsed row to \"active\": a spinner and a Stop\n\t\t\t\t\t// button against a dead id, until the page is reloaded.\n\t\t\t\t\tself._clearPendingUserBubble(capturedId);\n\t\t\t\t\tvar bi = self.state.messages.findIndex(function (m) { return m.isPending && m._serverItemId === capturedId; });\n\t\t\t\t\tif (bi !== -1) {\n\t\t\t\t\t\tif (isNotExists) self.state.messages.splice(bi, 1);\n\t\t\t\t\t\telse self.state.messages[bi] = { role: 'assistant', content: getErrorMessage(err), isError: true, isBackgroundTask: true, _serverItemId: capturedId };\n\t\t\t\t\t} else if (!isNotExists) {\n\t\t\t\t\t\t// No placeholder to turn into the error (a queued pass). Put one\n\t\t\t\t\t\t// after the request bubble so the row reports the failure instead\n\t\t\t\t\t\t// of quietly settling to \"Indexed\".\n\t\t\t\t\t\tvar ui = self.state.messages.findIndex(function (m) { return m.role === 'user' && m._serverItemId === capturedId; });\n\t\t\t\t\t\tif (ui !== -1) {\n\t\t\t\t\t\t\tself.state.messages.splice(ui + 1, 0, { role: 'assistant', content: getErrorMessage(err), isError: true, isBackgroundTask: true, _serverItemId: capturedId });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tself.host.notify(); self.updateHistoryCache();\n\t\t\t\t}).then(function () {\n\t\t\t\t\t// Keep the queue entry when the poll was merely stopped, or resuming\n\t\t\t\t\t// would have nothing left to re-attach to.\n\t\t\t\t\tif (wasStopped) return;\n\t\t\t\t\tvar qi = self.bgTaskQueue.findIndex(function (q) { return q.id === capturedId; });\n\t\t\t\t\tif (qi !== -1) self.bgTaskQueue.splice(qi, 1);\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tthis.promoteNextBgQueuedToRunning();\n\t}\n\n\t// Resume-across-passes: if a background INDEXING task for a paged file (spreadsheet or\n\t// text) finished WITHOUT the completion marker, the agent ran out of room before reading\n\t// the whole file - dispatch a CONTINUE pass (up to a cap) that resumes from where the\n\t// already-saved records leave off. Additive + guarded so it never loops forever and\n\t// never breaks the resolution path.\n\t//\n\t// VISION files (PDFs rendered to page images) are NOT resumed here: the proxy worker\n\t// advances their page window itself, off the renderer's true page count. Driving them\n\t// from the browser is what used to lose pages on long documents - the chain lived in tab\n\t// memory (a reload or a closed tab ended it), and it stopped whenever the model claimed\n\t// completion, which on an 88-page file happened at page 15. Continuing to dispatch here\n\t// as well would now double-index every window.\n\tmaybeResumeIndexing(entry: BgTaskEntry, response: any, platform: string): void {\n\t\tvar self = this;\n\t\ttry {\n\t\t\tif (!entry || !entry.storagePath) return;\n\t\t\t// The user stopped this file from its collapsed row. Dispatching the next\n\t\t\t// pass here is exactly what \"stop\" has to prevent — the cancelled pass\n\t\t\t// settles, and without this the chain simply carries on.\n\t\t\tif (this.cancelledIndexKeys.has(this._indexKeyOf(entry))) return;\n\t\t\tif (!isPagedReadFile(entry.filename, entry.mime)) return;\n\t\t\tif (isImageVisionFile(entry.filename, entry.mime)) return; // worker owns this loop (PDF vision)\n\t\t\t// When windowed indexing is on, the WORKER drives the text/grid loop too. The\n\t\t\t// client MUST NOT also resume, or two drivers each enqueue a continuation per\n\t\t\t// pass and the chain FORKS - duplicate records, runaway passes. Same reason\n\t\t\t// PDFs early-return above. Gated on the flag so the old client-driven path is\n\t\t\t// untouched when windowing is off.\n\t\t\tif (windowedIndexingEnabled() && isWindowedReadFile(entry.filename, entry.mime)) return;\n\t\t\tif (isErrorResponseBody(response)) return; // a failed pass is not \"incomplete\"\n\t\t\tvar answer = (platform === 'openai' ? extractOpenAIText(response) : extractClaudeText(response)) || '';\n\t\t\tif (answer.indexOf(INDEXING_COMPLETE_MARKER) !== -1) return; // fully indexed\n\t\t\tvar pass = (entry.resumePass || 0) + 1;\n\t\t\tif (pass > MAX_INDEXING_RESUME_PASSES) return; // give up after the cap\n\t\t\tvar id = this.host.getIdentity();\n\t\t\tif (!id || id.platform === 'none' || id.serviceId !== entry.serviceId) return;\n\t\t\tnotifyAgentContinueIndexing({\n\t\t\t\tplatform: id.platform as 'claude' | 'openai',\n\t\t\t\tmodel: id.model,\n\t\t\t\tservice: id.serviceId,\n\t\t\t\towner: id.owner,\n\t\t\t\tuserId: id.userId || id.serviceId,\n\t\t\t\tserviceName: id.serviceName,\n\t\t\t\tserviceDescription: id.serviceDescription,\n\t\t\t\tattachment: {\n\t\t\t\t\tname: entry.filename,\n\t\t\t\t\tstoragePath: entry.storagePath,\n\t\t\t\t\tmime: entry.mime,\n\t\t\t\t\tsize: entry.size,\n\t\t\t\t\turl: '',\n\t\t\t\t},\n\t\t\t}).then(function (ack: any) {\n\t\t\t\tif (ack && typeof ack.id === 'string') {\n\t\t\t\t\tself.bgTaskQueue.push({\n\t\t\t\t\t\tserviceId: id.serviceId, platform: id.platform as 'claude' | 'openai', id: ack.id,\n\t\t\t\t\t\tfilename: entry.filename, storagePath: entry.storagePath,\n\t\t\t\t\t\tisReindex: entry.isReindex, mime: entry.mime, size: entry.size,\n\t\t\t\t\t\tstatus: ack.status === 'running' ? 'running' : 'pending',\n\t\t\t\t\t\tpoll: ack.poll, resumePass: pass,\n\t\t\t\t\t});\n\t\t\t\t\tself.drainBgTaskQueue();\n\t\t\t\t}\n\t\t\t}, function (e: any) { console.error('[chat-engine] resume-indexing dispatch failed', e); });\n\t\t} catch (e) { /* best-effort: resume must never break bg-task resolution */ }\n\t}\n\n\t// --- history fetch + pagination --------------------------------------\n\t// Initial load (fetchMore=false) replaces the list (with in-flight rescue +\n\t// cancelled-merge) and attaches polls to running/pending items; pagination\n\t// (fetchMore=true) prepends older messages. The DOM scroll-restore for the\n\t// older-prepend is the VIEW's job (it captures the pre-prepend scroll position\n\t// and restores after this resolves) — the engine never measures the DOM.\n\tloadHistory(fetchMore?: boolean, token?: number): Promise<void> {\n\t\tvar self = this;\n\t\tvar id = this.host.getIdentity();\n\t\t// Key this fetch is FOR, snapshotted from the same identity read the\n\t\t// request is built from. The rescue below compares against this rather\n\t\t// than a live getHistoryCacheKey(), so a project switch mid-fetch can't\n\t\t// make another chat's in-flight bubbles look local.\n\t\tvar loadKey = (!id.serviceId || id.platform === 'none') ? '' : id.serviceId + '#' + id.platform;\n\t\tif (token === undefined) token = this.state.gateRefreshToken;\n\t\tif ((this.state.loadingHistory && this.state.historyRequestToken === token) || id.platform === 'none' || !id.serviceId) {\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tthis.state.historyRequestToken = token;\n\t\tthis.state.loadingHistory = true;\n\t\tif (fetchMore) this.state.loadingOlderHistory = true;\n\t\tthis.host.notify(); // surface \"Fetching history...\" while it loads\n\t\tvar platform = id.platform as 'claude' | 'openai';\n\t\tvar serviceId = id.serviceId, owner = id.owner;\n\t\tvar options: any = { fetchMore: fetchMore };\n\t\tif (fetchMore && this.state.historyStartKeyHistory.length) options.startKeyHistory = this.state.historyStartKeyHistory.slice();\n\n\t\tvar fetchHistory = function () { return getChatHistory({ service: serviceId, owner: owner, platform: platform }, options); };\n\n\t\treturn Promise.resolve().then(fetchHistory).catch(function (err: any) {\n\t\t\tif (isAuthExpiredError(err) && !isNonRetryableRequestError(err)) return self.host.refreshSession().then(fetchHistory);\n\t\t\tthrow err;\n\t\t}).then(function (history: any) {\n\t\t\tif (token !== self.state.gateRefreshToken) return;\n\t\t\tvar chatList = history && Array.isArray(history.list) ? history.list : [];\n\t\t\tchatList.forEach(function (item: any) {\n\t\t\t\tif (isBgIndexingQueue(item.queue_name)) {\n\t\t\t\t\tif (isIndexingRequestText(extractLastUserTextFromRequest(item.request_body))) item._isBgTask = true;\n\t\t\t\t\telse item._isOnBgQueue = true;\n\t\t\t\t}\n\t\t\t});\n\t\t\tvar list = chatList.sort(function (a: any, b: any) {\n\t\t\t\tvar ai = typeof a.id === 'string' ? a.id : '', bi = typeof b.id === 'string' ? b.id : '';\n\t\t\t\treturn ai > bi ? -1 : (ai < bi ? 1 : 0);\n\t\t\t});\n\t\t\tvar mapped = mapHistoryListToMessages(list, platform, {\n\t\t\t\tclearedAt: self.host.getClearedAt(),\n\t\t\t\tserviceId: id.serviceId,\n\t\t\t\tformatIndexingLabel: self.host.formatIndexingLabel,\n\t\t\t}).messages;\n\n\t\t\t// Set when a first-page refresh re-prepended already-loaded older pages,\n\t\t\t// so the cursor reset below knows not to rewind to page 1's boundary.\n\t\t\tvar keptOlderPages = false;\n\n\t\t\tif (fetchMore) {\n\t\t\t\tself.state.messages = mapped.concat(self.state.messages);\n\t\t\t} else {\n\t\t\t\tif (self.state.typing) self.state.typingAbort = true;\n\t\t\t\tvar serverIds: any = {};\n\t\t\t\tmapped.forEach(function (m: any) { if (m._serverItemId) serverIds[m._serverItemId] = 1; });\n\t\t\t\tvar locallyCancelled: any = {};\n\t\t\t\tself.state.messages.forEach(function (m) { if (m.isCancelled && m._serverItemId) locallyCancelled[m._serverItemId] = m; });\n\t\t\t\t// A cancel the server has not acknowledged yet. Without carrying these\n\t\t\t\t// across the replace, a collapsed row mid-cancel drops its \"Stopping...\"\n\t\t\t\t// state and re-offers Stop; the second click cancels an id that is\n\t\t\t\t// already gone and writes a bogus \"Could not remove from queue.\" onto a\n\t\t\t\t// run that WAS stopped successfully.\n\t\t\t\tvar inFlightCancel: any = {};\n\t\t\t\tself.state.messages.forEach(function (m) {\n\t\t\t\t\tif (!m._serverItemId) return;\n\t\t\t\t\tif (m._cancelling || m._cancelError) inFlightCancel[m._serverItemId] = m;\n\t\t\t\t});\n\t\t\t\t// If the freshly-mapped server list ALREADY shows this in-flight turn\n\t\t\t\t// as a pending placeholder (a non-bg pending assistant, which carries\n\t\t\t\t// a real _serverItemId), re-pushing the local no-_serverItemId\n\t\t\t\t// user+Thinking would DUPLICATE it. Each resolve path only clears the\n\t\t\t\t// first pending bubble, so the duplicate strands a \"Thinking…\" beside\n\t\t\t\t// the reply/error. There is at most one in-flight regular turn, so a\n\t\t\t\t// mapped pending assistant IS this turn — skip the redundant local copy.\n\t\t\t\tvar mappedHasPendingAssistant = mapped.some(function (m: any) {\n\t\t\t\t\treturn m.isPending && m.role === 'assistant' && !m.isBackgroundTask;\n\t\t\t\t});\n\t\t\t\tvar rescued: ChatMessage[] = [];\n\t\t\t\tfor (var ri = 0; ri < self.state.messages.length; ri++) {\n\t\t\t\t\tvar mm = self.state.messages[ri];\n\t\t\t\t\tif (mm.isBackgroundTask) continue;\n\t\t\t\t\t// Belongs to a different chat (another project, or another\n\t\t\t\t\t// platform on this one) — it must not be carried onto THIS\n\t\t\t\t\t// chat's freshly-fetched history.\n\t\t\t\t\tif (mm._ownerKey !== undefined && mm._ownerKey !== loadKey) continue;\n\t\t\t\t\tif (mm._serverItemId && serverIds[mm._serverItemId]) continue;\n\t\t\t\t\tif (!mm._serverItemId) {\n\t\t\t\t\t\tif (mappedHasPendingAssistant) continue;\n\t\t\t\t\t\tif (mm.isSendingToServer || mm.isPendingQueued || mm.isPendingInProcess || mm.isPending) rescued.push(mm);\n\t\t\t\t\t\telse if (self.state.sending && mm.role === 'user') {\n\t\t\t\t\t\t\tvar next = self.state.messages[ri + 1];\n\t\t\t\t\t\t\tif (next && !next.isBackgroundTask && next.isPending && !next._serverItemId) rescued.push(mm);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// PRESERVE already-loaded older pages. `mapped` is only page 1, so a\n\t\t\t\t// blind replace threw away every page the user had scrolled in. This\n\t\t\t\t// path runs from resumePolling (visibilitychange), so merely leaving\n\t\t\t\t// the tab and coming back wiped the whole scrolled-in history.\n\t\t\t\t//\n\t\t\t\t// The list is oldest-first (fetchMore PREPENDS), and ids sort with\n\t\t\t\t// newest largest, so anything already in the list whose _serverItemId\n\t\t\t\t// sorts BELOW page 1's oldest id is an older page. Those are disjoint\n\t\t\t\t// from `mapped` (strict <), so re-prepending cannot duplicate.\n\t\t\t\tvar oldestInPage1: string | undefined = undefined;\n\t\t\t\tmapped.forEach(function (m: any) {\n\t\t\t\t\tvar sid = m._serverItemId;\n\t\t\t\t\tif (typeof sid !== 'string') return;\n\t\t\t\t\tif (oldestInPage1 === undefined || sid < (oldestInPage1 as string)) oldestInPage1 = sid;\n\t\t\t\t});\n\t\t\t\t// Only merge when the current list is genuinely a continuation of THIS\n\t\t\t\t// page 1 (shares at least one id with it). A project switch, a cleared\n\t\t\t\t// horizon, or a wholly-new page means the head is unrelated history and\n\t\t\t\t// must be replaced, not spliced.\n\t\t\t\tvar sharesPage1 = self.state.messages.some(function (m) {\n\t\t\t\t\treturn typeof m._serverItemId === 'string' && !!serverIds[m._serverItemId as string];\n\t\t\t\t});\n\t\t\t\tvar retainedOlder: ChatMessage[] = (!sharesPage1 || oldestInPage1 === undefined) ? [] : self.state.messages.filter(function (m) {\n\t\t\t\t\t// Settled server history only; in-flight bubbles are the rescue\n\t\t\t\t\t// loop's job below and would otherwise be kept twice.\n\t\t\t\t\tif (typeof m._serverItemId !== 'string') return false;\n\t\t\t\t\t// Same ownership predicate as the rescue loop: never carry another\n\t\t\t\t\t// project's bubbles onto this chat (the cross-project leak fix).\n\t\t\t\t\t// Compare against the snapshotted loadKey, never a live read.\n\t\t\t\t\tif (m._ownerKey !== undefined && m._ownerKey !== loadKey) return false;\n\t\t\t\t\treturn (m._serverItemId as string) < (oldestInPage1 as string);\n\t\t\t\t});\n\t\t\t\tkeptOlderPages = retainedOlder.length > 0;\n\t\t\t\tself.state.messages = keptOlderPages ? retainedOlder.concat(mapped) : mapped;\n\t\t\t\trescued.forEach(function (m) { self.state.messages.push(m); });\n\t\t\t\tif (Object.keys(locallyCancelled).length) {\n\t\t\t\t\tfor (var ci = 0; ci < self.state.messages.length; ci++) {\n\t\t\t\t\t\tvar c = self.state.messages[ci];\n\t\t\t\t\t\tif (!c._serverItemId || !locallyCancelled[c._serverItemId] || c.isCancelled) continue;\n\t\t\t\t\t\t// Rebuild FROM the mapped bubble rather than as a bare literal:\n\t\t\t\t\t\t// dropping isBackgroundTask / _indexFile here ejected a stopped\n\t\t\t\t\t\t// indexing pass from its file's collapsed row, where it then rendered\n\t\t\t\t\t\t// as a standalone \"Indexing: <file>\" chat bubble and left the row\n\t\t\t\t\t\t// recomputing its passes as if that one had never happened.\n\t\t\t\t\t\tself.state.messages[ci] = {\n\t\t\t\t\t\t\trole: 'user', content: c.content, isCancelled: true, _serverItemId: c._serverItemId,\n\t\t\t\t\t\t\tisBackgroundTask: c.isBackgroundTask, _indexFile: c._indexFile,\n\t\t\t\t\t\t\t_useBgQueue: c._useBgQueue, _ownerKey: c._ownerKey,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (ci + 1 < self.state.messages.length && self.state.messages[ci + 1].isPending && self.state.messages[ci + 1]._serverItemId === c._serverItemId) {\n\t\t\t\t\t\t\tself.state.messages.splice(ci + 1, 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Re-stamp a cancel that is still in flight (see inFlightCancel above).\n\t\t\t\t// Only onto a bubble the server still reports as pending — once it has\n\t\t\t\t// settled the flags describe nothing the user can act on.\n\t\t\t\tfor (var fi = 0; fi < self.state.messages.length; fi++) {\n\t\t\t\t\tvar fm = self.state.messages[fi];\n\t\t\t\t\tvar was = fm._serverItemId && inFlightCancel[fm._serverItemId];\n\t\t\t\t\tif (!was || fm.isCancelled) continue;\n\t\t\t\t\tif (!(fm.isPendingQueued || fm.isPendingInProcess || fm.isPending)) continue;\n\t\t\t\t\tif (was._cancelling) fm._cancelling = true;\n\t\t\t\t\tif (was._cancelError) fm._cancelError = was._cancelError;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Only adopt page 1's cursor when page 1 IS the whole list. If older pages\n\t\t\t// survived the merge, rewinding here would make the next scroll-up\n\t\t\t// re-fetch page 2 (already on screen) and duplicate it.\n\t\t\tif (!keptOlderPages) {\n\t\t\t\tself.state.historyEndOfList = !!(history && history.endOfList);\n\t\t\t\tself.state.historyStartKeyHistory = history && Array.isArray(history.startKeyHistory) ? history.startKeyHistory : [];\n\t\t\t\tvar clearedAt = self.host.getClearedAt();\n\t\t\t\tif (clearedAt && chatList.length > 0) {\n\t\t\t\t\tvar oldestUpdated = Number(chatList[chatList.length - 1] && chatList[chatList.length - 1].updated);\n\t\t\t\t\tif (isFinite(oldestUpdated) && oldestUpdated <= clearedAt) self.state.historyEndOfList = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Clear loading flags BEFORE this render so the final paint is\n\t\t\t// indicator-free (and the view's scroll-restore math sees matching heights).\n\t\t\tif (self.state.historyRequestToken === token) { self.state.loadingHistory = false; self.state.loadingOlderHistory = false; }\n\t\t\tself.updateHistoryCache();\n\t\t\tself.host.notify();\n\n\t\t\tif (!fetchMore) {\n\t\t\t\tchatList.forEach(function (item: any) {\n\t\t\t\t\tif (item.status !== 'running' && item.status !== 'pending') return;\n\t\t\t\t\tif (!item.poll || !item.id) return;\n\t\t\t\t\t// Every live poll registers its item id in historyItemPolls — an\n\t\t\t\t\t// immediate dispatch (dispatchAgentRequest ~123), a queued send\n\t\t\t\t\t// (~253), a bg task (drain), or an earlier history poll — so the\n\t\t\t\t\t// has() check below already skips exactly the items a live poll\n\t\t\t\t\t// covers (including the one the current dispatch is polling). Do NOT\n\t\t\t\t\t// additionally skip every OTHER running/pending item just because\n\t\t\t\t\t// some immediate dispatch is in flight: that dispatch polls only ITS\n\t\t\t\t\t// item, so blanket-skipping stranded a concurrent \"-bg\" indexing item\n\t\t\t\t\t// (a separate server queue runs in parallel) — or any item whose own\n\t\t\t\t\t// poll had since died — with no live poller, leaving a \"Thinking...\"\n\t\t\t\t\t// that never clears even after the server settled everything.\n\t\t\t\t\tif (self.historyItemPolls.has(item.id)) return;\n\t\t\t\t\t// An in-flight immediate dispatch polls its own MAIN-QUEUE item but\n\t\t\t\t\t// registers that id in historyItemPolls only AFTER its provider POST\n\t\t\t\t\t// returns; in the sliver before that, a remount can surface the item\n\t\t\t\t\t// here still unregistered. Skip re-polling MAIN-QUEUE items while a\n\t\t\t\t\t// dispatch is in flight so we don't stack a 2nd poll on the item the\n\t\t\t\t\t// dispatch is about to poll. Bg-queue items (_isBgTask indexing tasks\n\t\t\t\t\t// and _isOnBgQueue chats) run on a SEPARATE queue the immediate\n\t\t\t\t\t// dispatch never polls, so they MUST still get their poll — skipping\n\t\t\t\t\t// them was the stranded-\"Thinking\" bug this guard must not revive.\n\t\t\t\t\tif (self.pendingAgentRequests[self.getHistoryCacheKey()] && !item._isBgTask && !item._isOnBgQueue) return;\n\t\t\t\t\t// Background indexing polls are suppressed while paused; foreground\n\t\t\t\t\t// replies the user is waiting on are not.\n\t\t\t\t\tif ((item._isBgTask || item._isOnBgQueue) && self.isPollingPaused()) return;\n\t\t\t\t\tvar capturedId = item.id;\n\t\t\t\t\tvar pp = item.poll({\n\t\t\t\t\t\tlatency: POLL_INTERVAL,\n\t\t\t\t\t\tonResponse: function (response: any) { if (isPollStopped(response)) return; self.handleHistoryItemResolution(capturedId, response, platform); },\n\t\t\t\t\t\tonError: function (err: any) {\n\t\t\t\t\t\t\tself.historyItemPolls.delete(capturedId);\n\t\t\t\t\t\t\tvar isNotExists = err && (err.code === 'NOT_EXISTS' || (err.body && err.body.code === 'NOT_EXISTS'));\n\t\t\t\t\t\t\tvar aIdx = self.state.messages.findIndex(function (m) { return m.isPending && m._serverItemId === capturedId; });\n\t\t\t\t\t\t\tif (isNotExists) {\n\t\t\t\t\t\t\t\tvar uIdx = self.state.messages.findIndex(function (m) { return m.role === 'user' && m._serverItemId === capturedId && !m.isCancelled; });\n\t\t\t\t\t\t\t\t// Decide bg-ness from whichever bubble actually exists. A\n\t\t\t\t\t\t\t\t// QUEUED pass has no assistant placeholder (history.ts emits\n\t\t\t\t\t\t\t\t// none), so reading it off the placeholder alone classified\n\t\t\t\t\t\t\t\t// every queued indexing pass as foreground: the rebuild below\n\t\t\t\t\t\t\t\t// then dropped isBackgroundTask/_indexFile, ejecting the pass\n\t\t\t\t\t\t\t\t// from its collapsed row as a raw \"Indexing: <file>\" chat\n\t\t\t\t\t\t\t\t// bubble, and promoteNextQueuedToRunning span up a \"Thinking...\"\n\t\t\t\t\t\t\t\t// on an unrelated queued FOREGROUND message.\n\t\t\t\t\t\t\t\tvar isBg = (aIdx !== -1 && !!self.state.messages[aIdx].isBackgroundTask)\n\t\t\t\t\t\t\t\t\t|| (uIdx !== -1 && !!self.state.messages[uIdx].isBackgroundTask);\n\t\t\t\t\t\t\t\tif (aIdx !== -1) self.state.messages.splice(aIdx, 1);\n\t\t\t\t\t\t\t\tif (!isBg) {\n\t\t\t\t\t\t\t\t\tif (uIdx !== -1) { var ex = self.state.messages[uIdx]; self.state.messages[uIdx] = { role: 'user', content: ex.content, isCancelled: true, _serverItemId: ex._serverItemId }; }\n\t\t\t\t\t\t\t\t\tself.cancelledServerIds.delete(capturedId); self.promoteNextQueuedToRunning();\n\t\t\t\t\t\t\t\t} else if (uIdx !== -1) {\n\t\t\t\t\t\t\t\t\t// Same carry-over every other rebuild does, so the pass stays\n\t\t\t\t\t\t\t\t\t// a member of its file's row while reading as cancelled.\n\t\t\t\t\t\t\t\t\tvar bex = self.state.messages[uIdx];\n\t\t\t\t\t\t\t\t\tvar bcancelled: ChatMessage = { role: 'user', content: bex.content, isCancelled: true, isBackgroundTask: true, _serverItemId: bex._serverItemId };\n\t\t\t\t\t\t\t\t\tif (bex._indexFile) bcancelled._indexFile = bex._indexFile;\n\t\t\t\t\t\t\t\t\tif (bex._useBgQueue) bcancelled._useBgQueue = true;\n\t\t\t\t\t\t\t\t\tself.state.messages[uIdx] = bcancelled;\n\t\t\t\t\t\t\t\t\tself.promoteNextBgQueuedToRunning();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tself.host.notify(); self.updateHistoryCache(); return;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (aIdx !== -1) {\n\t\t\t\t\t\t\t\tvar wasBg = self.state.messages[aIdx].isBackgroundTask;\n\t\t\t\t\t\t\t\tself.state.messages[aIdx] = { role: 'assistant', content: getErrorMessage(err), isError: true };\n\t\t\t\t\t\t\t\tif (wasBg) self.state.messages[aIdx].isBackgroundTask = true;\n\t\t\t\t\t\t\t\tself.host.notify(); self.updateHistoryCache();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\t// Anything on the BACKGROUND queue is pausable, not just items whose\n\t\t\t\t\t// prompt text we recognise as an indexing task. _isBgTask vs\n\t\t\t\t\t// _isOnBgQueue is a DISPLAY distinction (\"Indexing: file\" vs a normal\n\t\t\t\t\t// chat bubble); keying the pause off _isBgTask alone left every\n\t\t\t\t\t// bg-queue item we could not text-match polling forever.\n\t\t\t\t\tself._trackPoll(capturedId, (item._isBgTask || item._isOnBgQueue) ? 'bg' : 'fg', pp);\n\t\t\t\t\tif (pp && pp.catch) pp.catch(function () { });\n\t\t\t\t});\n\t\t\t\tself.drainBgTaskQueue();\n\t\t\t}\n\n\t\t\t// Sticky, NOT forcing: this runs after every first-page load, including\n\t\t\t// the one resumePolling fires on visibilitychange. Forcing yanked a\n\t\t\t// reader who had scrolled up back to the bottom. On a genuine mount the\n\t\t\t// user is still pinned, so this behaves identically there.\n\t\t\tif (!fetchMore) return self.host.scrollToBottomIfSticky();\n\t\t}).catch(function (err: any) {\n\t\t\tconsole.warn('[chat-engine] getChatHistory failed', err);\n\t\t}).then(function () {\n\t\t\tif (self.state.historyRequestToken === token) {\n\t\t\t\tvar wasLoading = self.state.loadingHistory || self.state.loadingOlderHistory;\n\t\t\t\tself.state.loadingHistory = false; self.state.loadingOlderHistory = false;\n\t\t\t\tif (wasLoading) self.host.notify();\n\t\t\t}\n\t\t\t// Every first-page load ends here — mount, resumePolling, a cache-restore\n\t\t\t// refresh — and every one of them can leave a box too short to scroll,\n\t\t\t// which is the only trigger there is for reaching page 2. The view (which\n\t\t\t// alone can measure) pages its way out of it. Fired after the flags are\n\t\t\t// cleared so the fill loop does not see a request still in flight.\n\t\t\tif (self.host.onHistoryLoaded) self.host.onHistoryLoaded(!!fetchMore, token as number);\n\t\t});\n\t}\n\n\t// --- attachment upload orchestration ---------------------------------\n\t// Upload one attachment (a file = 1 member, a folder = N) to db storage and\n\t// queue indexing per member. The bytes I/O + chip rendering go through host\n\t// hooks; the overwrite/reindex flow, status lifecycle, and indexing live here.\n\tuploadSingleAttachment(att: any): Promise<Array<{ name: string; url: string; storagePath: string }>> {\n\t\tvar self = this;\n\t\tvar id = this.host.getIdentity();\n\t\tatt.status = 'uploading'; att.progress = 0; att.errorMessage = '';\n\t\tatt.errorCode = ''; att.errorDetail = ''; // clear any prior failure (retry)\n\t\tthis.host.renderAttachmentChips();\n\t\tvar members = (att.kind === 'folder')\n\t\t\t? (att.files || []).map(function (f: any) { return { file: f.file, relPath: f.path, storagePath: self.host.storagePathFor(f.path) }; })\n\t\t\t: [{ file: att.file, relPath: att.name, storagePath: this.host.storagePathFor(att.name) }];\n\t\tvar total = members.length;\n\t\tif (!total) return Promise.reject(new Error('Empty attachment'));\n\t\tvar urls: Array<{ name: string; url: string; storagePath: string }> = [];\n\t\tvar anyIndexFailed = false;\n\t\tvar chain: Promise<any> = Promise.resolve();\n\t\tmembers.forEach(function (member: any, idx: number) {\n\t\t\tchain = chain.then(function () {\n\t\t\t\tvar hadExists = false;\n\t\t\t\tvar skipped = false;\n\t\t\t\t// True when the file already existed and we are re-indexing over it\n\t\t\t\t// (user chose Reindex, OR Overwrite replaced the bytes). Drives the\n\t\t\t\t// delete-then-repost of the stale \"src::\" record below. Kept separate\n\t\t\t\t// from hadExists, which must keep driving ONLY the Reindexing/Indexing\n\t\t\t\t// label (isReindex) — overwrite still labels as \"Indexing:\".\n\t\t\t\tvar existedBefore = false;\n\t\t\t\tvar onProg = function (p: any) {\n\t\t\t\t\tif (p && p.total) {\n\t\t\t\t\t\tatt.progress = Math.floor(((idx + p.loaded / p.total) / total) * 100);\n\t\t\t\t\t\tself.host.renderAttachmentChips();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tvar doMemberUpload = function (checkExistence: boolean) {\n\t\t\t\t\treturn self.host.uploadFile({\n\t\t\t\t\t\tfile: member.file, storagePath: member.storagePath, checkExistence: checkExistence,\n\t\t\t\t\t\tonProgress: onProg, setAbort: function (abort) { att._abort = abort; },\n\t\t\t\t\t});\n\t\t\t\t};\n\t\t\t\treturn doMemberUpload(true).catch(function (err: any) {\n\t\t\t\t\tvar code = err && (err.code || (err.body && err.body.code));\n\t\t\t\t\tvar msg = err && (err.message || (err.body && err.body.message) || (typeof err === 'string' ? err : ''));\n\t\t\t\t\tvar isExists = code === 'EXISTS' || (msg && /exist/i.test(msg));\n\t\t\t\t\tif (!isExists) throw err; // a member upload failed → whole attachment fails (red)\n\t\t\t\t\treturn self.host.promptOverwrite(member.file.name).then(function (choice) {\n\t\t\t\t\t\tif (choice === 'overwrite') { existedBefore = true; return doMemberUpload(false); } // replace the existing file\n\t\t\t\t\t\tif (choice === 'skip') { skipped = true; return; } // leave it untouched; no upload/index\n\t\t\t\t\t\thadExists = true; existedBefore = true; // keep it; Reindex\n\t\t\t\t\t});\n\t\t\t\t}).then(function () {\n\t\t\t\t\tif (skipped) return; // user skipped this member — no url, no index request\n\t\t\t\t\treturn self.host.getTemporaryUrl(member.storagePath);\n\t\t\t\t}).then(function (url: string) {\n\t\t\t\t\tif (skipped) return; // guard the indexing branch for a skipped member\n\t\t\t\t\turls.push({ name: member.relPath, url: url, storagePath: member.storagePath });\n\t\t\t\t\tif (att.kind !== 'folder') { att.uploadedUrl = url; att.storagePath = member.storagePath; }\n\t\t\t\t\tvar mime = member.file.type || self.host.getMimeType(member.file.name);\n\t\t\t\t\t// Delete-then-repost: when the file already existed (Reindex or\n\t\t\t\t\t// Overwrite), delete the stale \"src::<storagePath>\" index record\n\t\t\t\t\t// first — the skapi backend cascades the delete to its\n\t\t\t\t\t// reference-linked children — so re-indexing REPLACES rather than\n\t\t\t\t\t// colliding/duplicating. Awaited before the index request is\n\t\t\t\t\t// enqueued. Best-effort + optional-hook guarded: a missing record,\n\t\t\t\t\t// a permission error, or a host without the hook must not block\n\t\t\t\t\t// indexing.\n\t\t\t\t\tvar preIndex = (existedBefore && typeof self.host.deleteExistingFileRecord === 'function')\n\t\t\t\t\t\t? Promise.resolve(self.host.deleteExistingFileRecord(member.storagePath)).catch(function () { })\n\t\t\t\t\t\t: Promise.resolve();\n\t\t\t\t\t// Run a client-side attachment parser (e.g. .hwp) if one matches; its\n\t\t\t\t\t// output is inlined into the indexing request (falls back to office\n\t\t\t\t\t// extraction / web_fetch when no parser matches or it yields nothing).\n\t\t\t\t\treturn preIndex.then(function () {\n\t\t\t\t\t\treturn parseAttachmentContent(member.file, member.file.name, mime || undefined);\n\t\t\t\t\t}).then(function (parsedContent: string | null) {\n\t\t\t\t\treturn notifyAgentSaveAttachment({\n\t\t\t\t\t\tplatform: id.platform as 'claude' | 'openai',\n\t\t\t\t\t\tmodel: id.model,\n\t\t\t\t\t\tservice: id.serviceId,\n\t\t\t\t\t\towner: id.owner,\n\t\t\t\t\t\tuserId: id.userId || id.serviceId,\n\t\t\t\t\t\tserviceName: id.serviceName,\n\t\t\t\t\t\tserviceDescription: id.serviceDescription,\n\t\t\t\t\t\tattachment: {\n\t\t\t\t\t\t\tname: member.file.name, storagePath: member.storagePath,\n\t\t\t\t\t\t\tmime: mime || undefined, size: member.file.size, url: url,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tparsedContent: parsedContent || undefined,\n\t\t\t\t\t}).then(function (ack: any) {\n\t\t\t\t\t\tif (ack && typeof ack.id === 'string') {\n\t\t\t\t\t\t\tself.bgTaskQueue.push({\n\t\t\t\t\t\t\t\tserviceId: id.serviceId, platform: id.platform as 'claude' | 'openai', id: ack.id,\n\t\t\t\t\t\t\t\tfilename: member.file.name,\n\t\t\t\t\t\t\t\tstoragePath: member.storagePath,\n\t\t\t\t\t\t\t\tisReindex: hadExists,\n\t\t\t\t\t\t\t\tmime: mime || undefined,\n\t\t\t\t\t\t\t\tsize: member.file.size,\n\t\t\t\t\t\t\t\tstatus: ack.status === 'running' ? 'running' : 'pending',\n\t\t\t\t\t\t\t\tpoll: ack.poll,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tself.drainBgTaskQueue(); // surface \"Indexing: <file>\" as soon as THIS file uploads\n\t\t\t\t\t\t}\n\t\t\t\t\t}, function (e: any) {\n\t\t\t\t\t\tconsole.error('[chat-engine] indexing request failed', e);\n\t\t\t\t\t\tanyIndexFailed = true; // uploaded but not indexed → yellow\n\t\t\t\t\t\t// Record the first index error's code/message for the report dialog.\n\t\t\t\t\t\tif (!att.errorCode && !att.errorDetail) {\n\t\t\t\t\t\t\tatt.errorCode = (e && (e.code || (e.body && e.body.code))) || '';\n\t\t\t\t\t\t\tatt.errorDetail = (e && (e.message || (e.body && e.body.message))) || (typeof e === 'string' ? e : '');\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn chain.then(function () {\n\t\t\tatt._abort = null; att.progress = 100;\n\t\t\tif (att.kind === 'folder') att.uploadedUrls = urls.map(function (u) { return { path: u.name, url: u.url, storagePath: u.storagePath }; });\n\t\t\tatt.status = anyIndexFailed ? 'indexError' : 'done';\n\t\t\tif (att.status === 'indexError') att.errorMessage = 'File indexing failed';\n\t\t\tself.host.renderAttachmentChips();\n\t\t\treturn urls;\n\t\t});\n\t}\n\n\t// Upload all not-yet-done attachments sequentially. Resolves to the full\n\t// list of { name, url, storagePath } for composing the chat message.\n\tuploadPendingAttachments(): Promise<Array<{ name: string; url: string; storagePath?: string }>> {\n\t\tvar self = this;\n\t\tthis.host.resetOverwriteBatch();\n\t\tthis.state.uploadingAttachments = true;\n\t\tthis.host.updateComposerControls();\n\t\tthis.host.renderAttachmentChips();\n\t\tvar collected: Array<{ name: string; url: string; storagePath?: string }> = [];\n\t\tvar snapshot = this.state.attachments.slice();\n\t\tvar chain: Promise<any> = Promise.resolve();\n\t\tsnapshot.forEach(function (att: any) {\n\t\t\tchain = chain.then(function () {\n\t\t\t\tif (!self.state.attachments.some(function (a: any) { return a.id === att.id; })) return; // removed\n\t\t\t\tif (att.status === 'done' || att.status === 'indexError') {\n\t\t\t\t\tif (att.kind === 'folder' && att.uploadedUrls) {\n\t\t\t\t\t\tatt.uploadedUrls.forEach(function (u: any) { collected.push({ name: u.path, url: u.url, storagePath: u.storagePath }); });\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (att.uploadedUrl) { collected.push({ name: att.name, url: att.uploadedUrl, storagePath: att.storagePath }); return; }\n\t\t\t\t}\n\t\t\t\treturn self.uploadSingleAttachment(att).then(function (us) {\n\t\t\t\t\tcollected.push.apply(collected, us);\n\t\t\t\t}).catch(function (err: any) {\n\t\t\t\t\tvar removed = !self.state.attachments.some(function (a: any) { return a.id === att.id; });\n\t\t\t\t\tvar aborted = err && (err.message === 'Aborted' || err === 'Aborted');\n\t\t\t\t\tif (removed || aborted) return;\n\t\t\t\t\tatt.status = 'error';\n\t\t\t\t\tatt.errorMessage = 'File upload has failed';\n\t\t\t\t\t// Preserve the original error code/message for the report dialog.\n\t\t\t\t\tatt.errorCode = (err && (err.code || (err.body && err.body.code))) || '';\n\t\t\t\t\tatt.errorDetail = (err && (err.message || (err.body && err.body.message))) || (typeof err === 'string' ? err : '');\n\t\t\t\t\tself.host.renderAttachmentChips();\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\tvar done = function () {\n\t\t\tself.state.uploadingAttachments = false; self.host.updateComposerControls(); self.host.renderAttachmentChips();\n\t\t\treturn collected;\n\t\t};\n\t\treturn chain.then(done, done);\n\t}\n\n\t// Stop timers / abort the typewriter (view teardown).\n\tstop(): void {\n\t\tthis.state.typingAbort = true;\n\t}\n\n\t// Bump the gate token so any in-flight immediate-send result is dropped\n\t// (called by the view on a service/platform switch or history clear).\n\tbumpGate(): void {\n\t\tthis.state.gateRefreshToken += 1;\n\t}\n}\n","/**\n * Background file-indexing turns, collapsed into ONE row per file.\n *\n * A single upload can produce many chat turns: the first \"Indexing: <file>\" pass\n * plus up to MAX_INDEXING_RESUME_PASSES CONTINUE passes, each with its own\n * request AND response bubble. Rendered flat, that reads as the same task\n * repeating forever, and any real question the user asks in between gets buried.\n *\n * buildChatDisplayList turns the flat message array into a DISPLAY list in which\n * every message belonging to one run of one file (however far apart the passes\n * sit, and whatever else is interleaved between them) is represented by a single\n * group entry, rendered at the position of that run's FIRST loaded pass.\n *\n * First, not newest. The message array is ordered by request CREATION time, and\n * a run's later passes are created one at a time as the previous one resolves —\n * by the client for the paged text path, and by the WORKER itself for the\n * rendered-page (PDF) path, which the client only learns about on its next\n * first-page history fetch. So a pass is routinely created minutes after the\n * upload, on a queue that runs in parallel with the foreground chat. Anchoring\n * at the newest pass meant one such late pass dragged the whole run — every\n * earlier pass with it — below any question the user had asked in the meantime,\n * and made a run that had visibly finished before the question render after it.\n * Anchoring at the first pass puts the row where the run actually began, which\n * is a position no later pass can change:\n * - a new pass never relocates the row, so nothing under the reader shifts;\n * - a question asked after the upload always renders below the row, which is\n * the order it happened in.\n * The cost is that a long-running index does not follow the conversation to the\n * bottom: once the user has chatted past the upload, the spinner and the Stop\n * button sit above their newest turns. That is a scroll away, and the row no\n * longer lies about when the work started.\n *\n * Paging older history is the one thing that CAN move the row: an older page\n * carrying earlier passes of a run already on screen moves it up into that page.\n * That happens at most once per run, only for a run whose start was never\n * loaded (`mayHaveOlder`), and it is the same event that already re-derives\n * `runKey` — so the view treats it as a new row either way.\n *\n * The group deliberately reports no authoritative pass TOTAL. History is paged\n * newest-first, so any total computed from loaded messages is a lower bound that\n * a later scroll-up would contradict. It reports STATE (indexing / indexed /\n * failed), how many passes are currently loaded, and `mayHaveOlder` when the\n * file's first pass is not among them.\n *\n * Pure and view-agnostic: agent.vue and the BunnyQuery widget both render from\n * this, so the two stay identical.\n */\nimport type { ChatMessage, IndexingFileRef } from './host';\n\nexport type IndexingGroupStatus = 'active' | 'done' | 'error' | 'cancelled';\n\nexport type IndexingGroup = {\n\t/** The FILE this row is about: storage path when known (a file can be\n\t * re-uploaded under a name that already exists elsewhere), else name. Shared\n\t * by every run of that file, and what ChatSession.cancelIndexingGroup and\n\t * _indexKeyOf match on — never use it as a render key. */\n\tkey: string;\n\t/** Identity of this ROW: one indexing RUN of that file. A file indexed on\n\t * Monday and re-indexed on Wednesday is two runs, and collapsing them into\n\t * one row erased Monday's from Monday's place in the conversation, claimed\n\t * its passes for Wednesday, and let Monday's failure be overwritten by\n\t * Wednesday's success. Named after the run's FIRST loaded pass (see where it\n\t * is assigned below), so passes appended to the run and other runs appearing\n\t * on either side of it never rename a row already on screen. This is the\n\t * render key and the expansion key. */\n\trunKey: string;\n\tname: string;\n\tpath?: string;\n\tmime?: string;\n\tsize?: number;\n\t/** True when any loaded pass was a re-index of an already-stored file. */\n\tisReindex: boolean;\n\t/** Every message of this file, in chat order, with its index in the source\n\t * array (so cancel/typewriter paths keep addressing the real message). */\n\tmembers: { msg: ChatMessage; index: number }[];\n\t/** Indexing passes LOADED (request bubbles), never a server-side total. */\n\tpassCount: number;\n\tstatus: IndexingGroupStatus;\n\t/** Server item ids of the passes that are still queued/running, so the row can\n\t * offer a stop button (ChatSession.cancelIndexingGroup cancels each). Empty\n\t * when nothing is cancellable — a finished file, or a live pass whose server\n\t * id has not come back yet. */\n\tcancellableIds: string[];\n\t/** A cancel request is in flight for one of the passes. */\n\tcancelling: boolean;\n\t/** Why the last cancel attempt failed (e.g. the pass had already finished). */\n\tcancelError?: string;\n\t/** The file's first pass is not among the loaded messages, so earlier passes\n\t * exist in history that has not been paged in yet. */\n\tmayHaveOlder: boolean;\n\t/** Position in the source array this collapsed row renders at: the index of\n\t * the run's FIRST loaded pass (see the file docstring for why not the last). */\n\tanchorIndex: number;\n\t/** Identity of the turn at `anchorIndex` — its server item id, or its local id\n\t * while it has none, or `''` when it has neither. The views stamp this on the\n\t * row (`data-row-pos`) so the scroll anchor can tell a row that RELOCATED (an\n\t * older page moved the run's start) from one that merely gained a pass. They\n\t * must not re-derive it from `members`: which member the row renders at is\n\t * this module's decision, and the two silently disagreed once already. */\n\tanchorId: string;\n};\n\nexport type DisplayEntry =\n\t| { kind: 'message'; msg: ChatMessage; index: number }\n\t| { kind: 'indexing'; group: IndexingGroup; index: number };\n\nexport type BuildDisplayListOptions = {\n\t/** True while older history remains unpaged, which is what makes a group\n\t * with no first pass genuinely incomplete rather than merely odd. */\n\thasMoreHistory?: boolean;\n};\n\n// The indexing label is view-formatted (formatIndexingLabel), so parsing it is\n// the FALLBACK path only: it exists for bubbles restored from a history cache\n// written before `_indexFile` was stamped. Live and freshly-mapped bubbles carry\n// the structured ref and never reach this.\n//\n// Shapes produced by formatIndexingLabel:\n// \"Indexing: [name](path) · mime · 1.2 MB\"\n// \"Reindexing: name · mime\"\n// \"Indexing (continuing) [name](path)\"\nconst INDEXING_LABEL_RE = /^(Re)?[Ii]ndexing(\\s*\\(continuing\\))?\\s*:?\\s+(.+)$/;\nconst LEADING_MD_LINK_RE = /^\\[([^\\]]+)\\]\\(([^)]+)\\)/;\n\nexport function parseIndexingLabel(\n\tcontent: string,\n): { name: string; path?: string; continued: boolean; isReindex: boolean } | null {\n\tif (typeof content !== 'string' || !content) return null;\n\tvar firstLine = content.split('\\n')[0].trim();\n\tvar m = firstLine.match(INDEXING_LABEL_RE);\n\tif (!m) return null;\n\t// Only the first \" · \" segment is the file; the rest is mime/size trivia.\n\tvar head = m[3].split(' · ')[0].trim();\n\tvar link = head.match(LEADING_MD_LINK_RE);\n\tvar name = link ? link[1].trim() : head;\n\tif (!name) return null;\n\treturn {\n\t\tname: name,\n\t\tpath: link ? link[2].trim() : undefined,\n\t\tcontinued: !!m[2],\n\t\tisReindex: !!m[1],\n\t};\n}\n\n/** The file a background-indexing bubble belongs to, structured ref preferred. */\nfunction readFileRef(msg: ChatMessage): (IndexingFileRef & { continued: boolean }) | null {\n\tvar ref = msg && msg._indexFile;\n\tif (ref && (ref.path || ref.name)) {\n\t\treturn {\n\t\t\tname: ref.name || ref.path || '',\n\t\t\tpath: ref.path,\n\t\t\tmime: ref.mime,\n\t\t\tsize: ref.size,\n\t\t\tisReindex: ref.isReindex,\n\t\t\tcontinued: !!ref.continued,\n\t\t};\n\t}\n\tvar parsed = parseIndexingLabel(msg && msg.content);\n\tif (!parsed) return null;\n\treturn {\n\t\tname: parsed.name,\n\t\tpath: parsed.path,\n\t\tisReindex: parsed.isReindex,\n\t\tcontinued: parsed.continued,\n\t};\n}\n\nfunction isPendingMsg(m: ChatMessage): boolean {\n\treturn !!(m.isPending || m.isPendingInProcess || m.isPendingQueued || m.isSendingToServer);\n}\n\n/**\n * Collapse background-indexing turns into per-file groups.\n *\n * Messages that are not background-indexing pass through untouched, at their\n * original positions and with their original indices.\n */\nexport function buildChatDisplayList(\n\tmessages: ChatMessage[],\n\topts?: BuildDisplayListOptions,\n): DisplayEntry[] {\n\tvar list = Array.isArray(messages) ? messages : [];\n\tvar hasMoreHistory = !!(opts && opts.hasMoreHistory);\n\n\t// One entry per RUN (see IndexingGroup.runKey), addressed by an internal id\n\t// while the list is being walked; runKey is assigned at the end, once the\n\t// number of runs per file is known.\n\tvar groups: { [runId: string]: IndexingGroup } = {};\n\tvar order: string[] = [];\n\tvar runOfIndex: (string | undefined)[] = new Array(list.length);\n\t// A response bubble carries no file metadata of its own; it is tied to its\n\t// request by the server item id, with the immediately preceding request as\n\t// the fallback for locally-pushed bubbles that have no id yet.\n\tvar runByItemId: { [itemId: string]: string } = {};\n\t// Row already opened for a file NAME, so a pass that reports no storage path\n\t// joins it instead of opening a second row for the same file.\n\tvar keyByName: { [name: string]: string } = {};\n\t// The run currently being accumulated for each file, every run of it, and the\n\t// file each run belongs to (a run id is opaque — a file key can contain any\n\t// character, so it must never be parsed back out of one).\n\tvar openRunOfKey: { [key: string]: string } = {};\n\tvar runsOfKey: { [key: string]: string[] } = {};\n\tvar keyOfRun: { [runId: string]: string } = {};\n\tvar runSeq = 0;\n\n\tfor (var i = 0; i < list.length; i++) {\n\t\tvar msg = list[i];\n\t\tif (!msg || !msg.isBackgroundTask) continue;\n\n\t\tvar runId: string | undefined;\n\t\tvar ref = msg.role === 'user' ? readFileRef(msg) : null;\n\t\tif (ref) {\n\t\t\t// Path first — a file can be re-uploaded under a name that already\n\t\t\t// exists elsewhere. But a pass that supplied no path (a compact\n\t\t\t// continuation label recovered from an old history cache) is still the\n\t\t\t// same file as the path-bearing passes above it, so let it join them\n\t\t\t// rather than splitting one file across two collapsed rows.\n\t\t\tvar key = ref.path || keyByName[ref.name] || ref.name;\n\t\t\t// A FIRST pass (\"A new file has just been uploaded\") when this file\n\t\t\t// already has a run open starts a new one: it is a re-index, or a\n\t\t\t// re-upload over the same storage path. Continuations join the run.\n\t\t\tif (!ref.continued && openRunOfKey[key]) delete openRunOfKey[key];\n\t\t\trunId = openRunOfKey[key];\n\t\t\tif (!runId) {\n\t\t\t\trunId = 'run' + (runSeq++);\n\t\t\t\topenRunOfKey[key] = runId;\n\t\t\t\tkeyOfRun[runId] = key;\n\t\t\t\t(runsOfKey[key] || (runsOfKey[key] = [])).push(runId);\n\t\t\t}\n\t\t} else if (msg._serverItemId && runByItemId[msg._serverItemId]) {\n\t\t\trunId = runByItemId[msg._serverItemId];\n\t\t} else if (msg.role !== 'user') {\n\t\t\t// ADJACENT only. Both paths that create a pass emit its request and\n\t\t\t// response bubbles together, so an id-less response belongs to the\n\t\t\t// message right before it. Falling back to the last file seen ANYWHERE\n\t\t\t// above swallowed stray background bubbles — an indexing prompt whose\n\t\t\t// shape we could not parse, a response whose request is not loaded —\n\t\t\t// into whichever file happened to be indexed most recently, however\n\t\t\t// much unrelated conversation sat in between.\n\t\t\trunId = runOfIndex[i - 1];\n\t\t}\n\t\t// A background bubble we cannot attribute to a file (an unrecognised label,\n\t\t// or a response whose request is not loaded) stays an ordinary message\n\t\t// rather than being folded into whichever group happens to be nearest.\n\t\tif (!runId) continue;\n\n\t\tvar g = groups[runId];\n\t\tif (!g) {\n\t\t\tvar fileKey = keyOfRun[runId];\n\t\t\tg = groups[runId] = {\n\t\t\t\tkey: fileKey,\n\t\t\t\trunKey: runId, // provisional; renumbered newest-first below\n\t\t\t\tname: ref ? ref.name : fileKey,\n\t\t\t\tpath: ref ? ref.path : undefined,\n\t\t\t\tmime: ref ? ref.mime : undefined,\n\t\t\t\tsize: ref ? ref.size : undefined,\n\t\t\t\tisReindex: !!(ref && ref.isReindex),\n\t\t\t\tmembers: [],\n\t\t\t\tpassCount: 0,\n\t\t\t\tstatus: 'done',\n\t\t\t\tcancellableIds: [],\n\t\t\t\tcancelling: false,\n\t\t\t\tmayHaveOlder: false,\n\t\t\t\t// The run's first loaded pass, and never re-stamped: see the file\n\t\t\t\t// docstring. `anchorId` is filled in once every member is known.\n\t\t\t\tanchorIndex: i,\n\t\t\t\tanchorId: '',\n\t\t\t};\n\t\t\torder.push(runId);\n\t\t}\n\t\tif (ref) {\n\t\t\t// Later passes carry the compact continuation label with no mime/size,\n\t\t\t// so keep the richest values any pass supplied.\n\t\t\tif (ref.name) g.name = ref.name;\n\t\t\tif (ref.path) g.path = ref.path;\n\t\t\tif (ref.mime) g.mime = ref.mime;\n\t\t\tif (typeof ref.size === 'number') g.size = ref.size;\n\t\t\tif (ref.isReindex) g.isReindex = true;\n\t\t\tif (!ref.continued) g.mayHaveOlder = false;\n\t\t\tg.passCount++;\n\t\t}\n\t\tg.members.push({ msg: msg, index: i });\n\t\trunOfIndex[i] = runId;\n\t\tif (msg._serverItemId) runByItemId[msg._serverItemId] = runId;\n\t\tif (ref && ref.name) keyByName[ref.name] = g.key;\n\t}\n\n\t// Name each run after its FIRST loaded pass. That id survives everything the\n\t// list does around it: passes appended to this run, other runs of the same\n\t// file appearing before OR after it, and an older page prepending. (An\n\t// ordinal would not — numbering from either end renames existing rows as soon\n\t// as a run appears at that end, which silently moves the user's expansion to\n\t// a row they never opened.) The one thing that changes it is the run's own\n\t// true first pass finally paging in, which happens at most once per run.\n\tfor (var rk in runsOfKey) {\n\t\tvar runIds = runsOfKey[rk];\n\t\tfor (var ri = 0; ri < runIds.length; ri++) {\n\t\t\tvar grpR = groups[runIds[ri]];\n\t\t\tif (!grpR) continue;\n\t\t\tvar first = grpR.members[0];\n\t\t\tvar firstId = first && first.msg && (first.msg._serverItemId || first.msg._localId);\n\t\t\t// A run whose passes are all still local (no server id yet) falls back to\n\t\t\t// its position, which is all there is to go on.\n\t\t\tgrpR.runKey = rk + '#' + (firstId || 'n' + ri);\n\t\t}\n\t}\n\n\t// Status + completeness, once every member is known.\n\tfor (var oi = 0; oi < order.length; oi++) {\n\t\tvar grp = groups[order[oi]];\n\t\t// A file's passes run strictly one after another, so a pass still marked\n\t\t// queued/running with a SETTLED pass after it is stale history, not live\n\t\t// work — the server's row for it simply never left \"running\". Ignoring\n\t\t// those matters most for pages reached by scrolling up (or by the viewport\n\t\t// fill), which get no poll attached to resolve them: one stale row would\n\t\t// otherwise flip a long-finished file back to a spinner with a \"Stop\"\n\t\t// button aimed at a dead item id, permanently.\n\t\tvar lastSettled = -1;\n\t\tfor (var si = 0; si < grp.members.length; si++) {\n\t\t\tif (!isPendingMsg(grp.members[si].msg)) lastSettled = si;\n\t\t}\n\t\tvar active = false;\n\t\tfor (var mi = lastSettled + 1; mi < grp.members.length; mi++) {\n\t\t\tif (isPendingMsg(grp.members[mi].msg)) { active = true; break; }\n\t\t}\n\t\t// What a stop button would act on: the REQUEST bubble of every pass that is\n\t\t// still queued or running server-side. The assistant placeholder shares its\n\t\t// pass's server id, so ids are de-duplicated. A pass mid-cancel is left out\n\t\t// (its request is already on its way) but keeps the row in a cancelling\n\t\t// state so the button does not flicker back to \"stop\".\n\t\tfor (var xi = 0; xi < grp.members.length; xi++) {\n\t\t\tif (grp.members[xi].msg._cancelling) { grp.cancelling = true; break; }\n\t\t}\n\t\tvar seenIds: { [id: string]: boolean } = {};\n\t\tfor (var ci = 0; ci < grp.members.length; ci++) {\n\t\t\tvar cm = grp.members[ci].msg;\n\t\t\t// Report a failed Stop only while the stop is still something the user\n\t\t\t// can act on. \"Could not remove from queue\" (the pass had just started)\n\t\t\t// stays on that bubble, so reporting it from ANY member meant a row that\n\t\t\t// went on to finish normally kept describing a one-off transient failure\n\t\t\t// as a permanent property of the file, until a full history refresh\n\t\t\t// rebuilt the bubbles.\n\t\t\tif (cm._cancelError && (active || grp.cancelling)) grp.cancelError = cm._cancelError;\n\t\t\tif (cm.role !== 'user' || !cm._serverItemId || cm._cancelling || cm.isSendingToServer) continue;\n\t\t\tif (!(cm.isPendingQueued || cm.isPendingInProcess)) continue;\n\t\t\t// Same staleness rule: never offer to stop a pass a later one outlived.\n\t\t\tif (ci < lastSettled) continue;\n\t\t\tif (seenIds[cm._serverItemId]) continue;\n\t\t\tseenIds[cm._serverItemId] = true;\n\t\t\tgrp.cancellableIds.push(cm._serverItemId);\n\t\t}\n\t\tif (active) {\n\t\t\tgrp.status = 'active';\n\t\t} else {\n\t\t\t// The newest loaded outcome is the file's state: an early pass may have\n\t\t\t// errored and a later one succeeded.\n\t\t\tvar last = grp.members[grp.members.length - 1].msg;\n\t\t\tgrp.status = last.isError ? 'error' : last.isCancelled ? 'cancelled' : 'done';\n\t\t}\n\t\t// A group whose passes are ALL continuations began before the loaded\n\t\t// window; its earlier passes arrive when older history is paged in.\n\t\tvar sawFirstPass = false;\n\t\tfor (var pi = 0; pi < grp.members.length; pi++) {\n\t\t\tvar pm = grp.members[pi].msg;\n\t\t\tif (pm.role !== 'user') continue;\n\t\t\tvar pref = readFileRef(pm);\n\t\t\tif (pref && !pref.continued) { sawFirstPass = true; break; }\n\t\t}\n\t\tgrp.mayHaveOlder = !sawFirstPass && hasMoreHistory;\n\t\t// Where the row renders, and WHICH turn that is. Derived from the same\n\t\t// member so the two can never drift apart; a group always has a member\n\t\t// (it is created by the first one).\n\t\tvar anchor = grp.members[0];\n\t\tgrp.anchorIndex = anchor.index;\n\t\tgrp.anchorId = anchor.msg._serverItemId || anchor.msg._localId || '';\n\t}\n\n\tvar out: DisplayEntry[] = [];\n\tfor (var j = 0; j < list.length; j++) {\n\t\tvar r = runOfIndex[j];\n\t\tif (r === undefined) {\n\t\t\tout.push({ kind: 'message', msg: list[j], index: j });\n\t\t\tcontinue;\n\t\t}\n\t\t// Every other member of the run is represented by the row at the anchor.\n\t\tif (groups[r].anchorIndex === j) out.push({ kind: 'indexing', group: groups[r], index: j });\n\t}\n\treturn out;\n}\n"]}
|