bunnyquery 1.8.0 → 1.8.1

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/dist/engine.d.mts CHANGED
@@ -312,18 +312,44 @@ declare function isAuthExpiredError(input: any): boolean;
312
312
 
313
313
  declare var CONTEXT_WINDOW_DEFAULT: Record<string, number>;
314
314
  declare var CONTEXT_WINDOW_BY_MODEL: Record<string, number>;
315
+ /**
316
+ * Record context windows from a provider models listing. Accepts the raw list
317
+ * items and reads `max_input_tokens` (Anthropic); items without it are skipped,
318
+ * so passing an OpenAI listing is a no-op rather than an error.
319
+ */
320
+ declare function registerModelContextWindows(models: Array<{
321
+ id?: string;
322
+ max_input_tokens?: number;
323
+ }> | null | undefined): void;
324
+ declare function setProjectContextWindow(serviceId: string, tokens: number | null | undefined): void;
325
+ declare function getProjectContextWindow(serviceId: string): number | null;
315
326
  declare var OUTPUT_TOKEN_RESERVE: number;
316
327
  declare var TOOL_AND_RESPONSE_BUFFER: number;
317
328
  declare var MIN_INPUT_TOKEN_BUDGET: number;
318
329
  declare var CLAUDE_PER_REQUEST_INPUT_CAP: number;
319
330
  declare var MAX_HISTORY_MESSAGES: number;
320
331
  declare var HISTORY_TOKEN_BUDGET: number;
332
+ declare var CLAUDE_INPUT_CAP_RATIO: number;
333
+ declare var HISTORY_BUDGET_RATIO: number;
321
334
  declare function estimateTextTokens(text: string): number;
322
335
  declare function estimateMessageTokens(msg: {
323
336
  role: string;
324
337
  content: string;
325
338
  }): number;
326
- declare function getContextWindow(platform: string, model?: string): number;
339
+ /**
340
+ * Resolve a model's context window, most specific source first:
341
+ * 1. per-project override (project settings)
342
+ * 2. the provider's own models listing (Anthropic `max_input_tokens`)
343
+ * 3. an exact entry in CONTEXT_WINDOW_BY_MODEL
344
+ * 4. a family entry, by dropping trailing '-' segments off the id
345
+ * 5. the platform default
346
+ *
347
+ * Step 4 is why a new or suffixed id no longer drops straight to the platform
348
+ * default: 'gpt-5.6-luna' resolves via 'gpt-5.6', and a dated Claude snapshot
349
+ * such as 'claude-opus-4-7-20260101' resolves via 'claude-opus-4-7'. The walk
350
+ * stops at the first hit, so a more specific entry always wins over its family.
351
+ */
352
+ declare function getContextWindow(platform: string, model?: string, serviceId?: string): number;
327
353
  declare function stripFileBlocksFromHistory(content: string): string;
328
354
  type BoundedChatOptions = {
329
355
  platform: string;
@@ -498,9 +524,61 @@ declare function wallClockNow(): number;
498
524
  */
499
525
  declare function formatChatTimestamp(ms?: number): string;
500
526
 
527
+ /**
528
+ * The `ai_agent` service option, parsed and serialized in ONE place.
529
+ *
530
+ * Stored on the skapi service record as up to three '#'-delimited segments:
531
+ *
532
+ * none AI chat disabled
533
+ * claude platform chosen, no model saved yet
534
+ * claude#claude-sonnet-4-6 platform + model
535
+ * claude#claude-sonnet-4-6#400000 platform + model + context-window override
536
+ *
537
+ * The third segment is new and optional, so every value written before it
538
+ * existed parses unchanged with `contextWindow: null`. Nothing writes a third
539
+ * segment without a model, because the window is meaningless without one.
540
+ *
541
+ * This lived as four separate copies (agent.vue, dbfile.vue, service.vue, and
542
+ * the widget's index.js), which is how the format drifts. New callers should
543
+ * import from here rather than re-deriving the split.
544
+ */
545
+ type AiAgentPlatform = 'claude' | 'openai' | null;
546
+ type ParsedAiAgent = {
547
+ /** null when unset or explicitly 'none'. */
548
+ platform: AiAgentPlatform;
549
+ /** '' when no model has been saved. */
550
+ model: string;
551
+ /** Per-project context-window override in tokens, or null to use the model's. */
552
+ contextWindow: number | null;
553
+ /** True when a real platform is configured (i.e. not unset and not 'none'). */
554
+ hasPlatform: boolean;
555
+ };
556
+ declare function parseAiAgentValue(value: string | null | undefined): ParsedAiAgent;
557
+ declare function buildAiAgentValue(platform: string | null | undefined, model?: string | null, contextWindow?: number | null): string;
558
+
501
559
  declare function filterListByClearHorizon(list: any[], clearedAt: number): any[];
502
560
  declare function normalizeTextContent(content: any): string;
503
561
  declare function extractLastUserTextFromRequest(requestBody: any): string;
562
+ /** The two openings an indexing prompt can have. A bg-queue item that starts with
563
+ * neither is an ordinary chat that happened to be routed onto that queue. */
564
+ declare function isIndexingRequestText(userText: any): boolean;
565
+ type IndexingRequestRef = {
566
+ name: string;
567
+ path?: string;
568
+ mime?: string;
569
+ size?: number;
570
+ /** A CONTINUE pass rather than the run's first. */
571
+ continued: boolean;
572
+ };
573
+ /**
574
+ * The file an indexing prompt is about, read back out of the prompt itself.
575
+ *
576
+ * The prompt is the only description of the pass that survives on the server, so
577
+ * this is how BOTH a history rebuild and a worker-minted pass the client never
578
+ * dispatched (ChatSession._adoptWorkerIndexingPasses) recover the file. Shared so
579
+ * the two produce the same `_indexFile`, which is what makes them group together.
580
+ */
581
+ declare function parseIndexingRequestText(userText: any): IndexingRequestRef | null;
504
582
  type MapHistoryOptions = {
505
583
  clearedAt: number;
506
584
  serviceId: string;
@@ -713,11 +791,20 @@ type BgTaskEntry = {
713
791
  /** How many CONTINUE passes have already run for this file (resume-across-passes). */
714
792
  resumePass?: number;
715
793
  };
794
+ /**
795
+ * `queue` narrows the fetch to one processing chain; `status` narrows it to items
796
+ * in one state. Passing both is how the client asks "is there still unresolved
797
+ * work on the background-indexing queue?" without pulling a page of chat history
798
+ * (see ChatSession._adoptWorkerIndexingPasses) — the server answers that from a
799
+ * status-keyed index, so the reply carries only the live items, not the bodies of
800
+ * everything already finished.
801
+ */
716
802
  declare function getChatHistory(params: {
717
803
  service?: string;
718
804
  owner?: string;
719
805
  platform: 'claude' | 'openai';
720
806
  queue?: string;
807
+ status?: 'pending' | 'running' | 'resolved' | 'failed';
721
808
  }, fetchOptions: Record<string, any>): Promise<any>;
722
809
 
723
810
  /**
@@ -1152,6 +1239,9 @@ declare class ChatSession {
1152
1239
  _clearPendingUserBubble(itemId: string): void;
1153
1240
  resumePendingRequest(token: number): Promise<void>;
1154
1241
  handleHistoryItemResolution(itemId: string, response: any, platform: string): void;
1242
+ /** The file an already-rendered background pass is about, off its request
1243
+ * bubble. Null for an ordinary turn, which is most of them. */
1244
+ private _indexRefOfItem;
1155
1245
  applyHistoryItemResolution(itemId: string, response: any, platform: string): void;
1156
1246
  /** How a bg task maps onto a collapsed row: the row's own key (storage path
1157
1247
  * when known, else the filename), scoped to the chat it belongs to. A storage
@@ -1183,6 +1273,49 @@ declare class ChatSession {
1183
1273
  * Runs from drainBgTaskQueue, which both clients call after a history load.
1184
1274
  */
1185
1275
  private _sweepCancelledIndexing;
1276
+ /**
1277
+ * True when the WORKER, not this client, drives the rest of this file's chain.
1278
+ * The mirror image of the early returns in maybeResumeIndexing: whatever that
1279
+ * refuses to continue is exactly what nothing client-side is tracking.
1280
+ */
1281
+ private _isWorkerDrivenIndexing;
1282
+ /**
1283
+ * Pick up indexing passes the WORKER minted, which no client ever dispatched.
1284
+ *
1285
+ * For a PDF (and for text/grid when windowed indexing is on) the worker writes
1286
+ * pass N+1's row itself, inside pass N's invocation, right after saving pass
1287
+ * N's result. That row reaches this client through nothing at all: it is not in
1288
+ * bgTaskQueue (the client never asked for it) and it is not in state.messages
1289
+ * (only a first-page history load maps it in, which happens on mount, project
1290
+ * switch or tab return). So between two worker passes every pass the client
1291
+ * knows about is settled, and the collapsed row renders "Indexed N passes"
1292
+ * with no spinner and no Stop, for a file that is still being read. A user who
1293
+ * believes that then asks questions against a half-indexed file — which is what
1294
+ * this exists to prevent.
1295
+ *
1296
+ * So when a background indexing pass settles, ask the bg queue what is still
1297
+ * unresolved on it and adopt anything unknown as an ordinary BgTaskEntry.
1298
+ * drainBgTaskQueue then treats it exactly like a pass this client dispatched:
1299
+ * same bubble, same `_indexFile` (so it joins the file's collapsed row), same
1300
+ * poll — and that poll settling runs this again, so the chain is followed to
1301
+ * its end. `status`-scoped so the reply carries the live items only, never a
1302
+ * page of finished ones with their bodies.
1303
+ *
1304
+ * Termination: the only trigger is a pass SETTLING, which happens once per
1305
+ * pass. An adopted item that is still running is not re-adopted (its id is
1306
+ * already polled), and when the queue holds nothing unknown the chain stops on
1307
+ * its own. Nothing here is periodic — a timer that re-reads history is the
1308
+ * shape that previously looped fetchHistoryPage after an already-DONE index.
1309
+ */
1310
+ private _adoptingWorkerPasses;
1311
+ private _adoptWorkerIndexingPasses;
1312
+ /** Any of these ids still queued or still polled, i.e. surviving work. */
1313
+ private _isTrackingAny;
1314
+ /** One live bg-queue item -> a BgTaskEntry, if it is an indexing pass this
1315
+ * client is not already tracking. Returns whether it was adopted. */
1316
+ private _adoptWorkerIndexingItem;
1317
+ /** Follow the chain on from a background indexing pass that just settled. */
1318
+ private _followWorkerIndexingChain;
1186
1319
  /** Best-effort server-side cancel of a bg-queue item that has no bubble (so
1187
1320
  * cancelQueuedMessage, which drives one, has nothing to act on). */
1188
1321
  private _cancelServerItem;
@@ -1203,4 +1336,4 @@ declare class ChatSession {
1203
1336
  bumpGate(): void;
1204
1337
  }
1205
1338
 
1206
- export { type AttachmentFailureGroup, type AttachmentParser, type AttachmentSaveInfo, BG_INDEXING_QUEUE_SUFFIX, type BgTaskEntry, type BoundedChatOptions, type BuildDisplayListOptions, type BuildIndexingUserMessageOptions, CLAUDE_PER_REQUEST_INPUT_CAP, CONTEXT_WINDOW_BY_MODEL, CONTEXT_WINDOW_DEFAULT, type CallClaudeWithMcpParams, type ChatEngineConfig, type ChatHost, type ChatIdentity, type ChatMessage, ChatSession, type ChatState, type ChatSystemPromptParams, type ClaudeMcpServerRequest, type ClaudeMcpToolConfig, type ClaudeMessage, type ClaudeRole, type ComposedUserMessage, DEFAULT_CLAUDE_MODEL, DEFAULT_OPENAI_MODEL, type DisplayEntry, EXPIRED_ATTACHMENT_URL_HOST, EXPIRED_ATTACHMENT_URL_ORIGIN, EXPIRED_LINK_REFRESH_EXPIRES_SECONDS, type ExtractDirective, type FillHistoryViewportOptions, HISTORY_FILL_SLACK_PX, HISTORY_TOKEN_BUDGET, type IndexingAttachmentInfo, type IndexingFileRef, type IndexingGroup, type IndexingGroupStatus, type IndexingSystemPromptParams, type InlineLinkContext, type InlineLinkPart, LINK_LABEL_MAX_DISPLAY_CHARS, LINK_REFRESH_WINDOW_MS, MAX_HISTORY_FILL_PAGES, MAX_HISTORY_MESSAGES, MAX_PARSED_CONTENT_CHARS, MCP_NAME, MIN_INPUT_TOKEN_BUDGET, type MapHistoryOptions, OUTPUT_TOKEN_RESERVE, type OpenAIMessage, POLL_INTERVAL, type PinnedDispatchContext, RENDER_FROM_TOKEN, TOOL_AND_RESPONSE_BUFFER, buildBoundedChatMessages, buildChatDisplayList, buildChatSystemPrompt, buildDisplayExpiredAttachmentHref, buildIndexingContinueMessage, buildIndexingRenderContinueTemplate, buildIndexingRenderMessage, buildIndexingSystemPrompt, buildIndexingUserMessage, buildIndexingWindowMessage, callClaudeWithMcp, callClaudeWithPublicMcp, callOpenAIWithPublicMcp, chatEngineConfig, classifyInlineLink, clearAttachmentParsers, composeUserMessage, configureChatEngine, createHistoryFiller, createInlineLinkRegex, encodePathSegments, estimateMessageTokens, estimateTextTokens, extractClaudeText, extractLastUserTextFromRequest, extractOpenAIText, extractRemotePathFromAttachmentHref, fillHistoryViewport, filterListByClearHorizon, findAttachmentParser, formatChatTimestamp, getAttachmentParsers, getChatHistory, getContextWindow, getErrorMessage, getExpiredAttachmentVisiblePath, groupAttachmentFailures, isAuthExpiredError, isBgIndexingQueue, isErrorResponseBody, isHttpUrlLike, isNonRetryableRequestError, isOfficeFile, isServerExtractable, isServiceDbAttachmentHref, listClaudeModels, listOpenAIModels, makeExtractPlaceholder, mapHistoryListToMessages, normalizeAttachmentPathCandidate, normalizeTextContent, normalizeTrailingInlineToken, notifyAgentSaveAttachment, parseAttachmentContent, parseIndexingLabel, readExpiredAttachmentHref, registerAttachmentParser, repairUrlEntities, repairUrlWhitespace, safeDecodeURIComponent, sanitizeAttachmentLinksForHistory, stripFileBlocksFromHistory, transformContentWithImages, transformContentWithOpenAIImages, truncateLabelForDisplay, wallClockNow };
1339
+ export { type AiAgentPlatform, type AttachmentFailureGroup, type AttachmentParser, type AttachmentSaveInfo, BG_INDEXING_QUEUE_SUFFIX, type BgTaskEntry, type BoundedChatOptions, type BuildDisplayListOptions, type BuildIndexingUserMessageOptions, CLAUDE_INPUT_CAP_RATIO, CLAUDE_PER_REQUEST_INPUT_CAP, CONTEXT_WINDOW_BY_MODEL, CONTEXT_WINDOW_DEFAULT, type CallClaudeWithMcpParams, type ChatEngineConfig, type ChatHost, type ChatIdentity, type ChatMessage, ChatSession, type ChatState, type ChatSystemPromptParams, type ClaudeMcpServerRequest, type ClaudeMcpToolConfig, type ClaudeMessage, type ClaudeRole, type ComposedUserMessage, DEFAULT_CLAUDE_MODEL, DEFAULT_OPENAI_MODEL, type DisplayEntry, EXPIRED_ATTACHMENT_URL_HOST, EXPIRED_ATTACHMENT_URL_ORIGIN, EXPIRED_LINK_REFRESH_EXPIRES_SECONDS, type ExtractDirective, type FillHistoryViewportOptions, HISTORY_BUDGET_RATIO, HISTORY_FILL_SLACK_PX, HISTORY_TOKEN_BUDGET, type IndexingAttachmentInfo, type IndexingFileRef, type IndexingGroup, type IndexingGroupStatus, type IndexingRequestRef, type IndexingSystemPromptParams, type InlineLinkContext, type InlineLinkPart, LINK_LABEL_MAX_DISPLAY_CHARS, LINK_REFRESH_WINDOW_MS, MAX_HISTORY_FILL_PAGES, MAX_HISTORY_MESSAGES, MAX_PARSED_CONTENT_CHARS, MCP_NAME, MIN_INPUT_TOKEN_BUDGET, type MapHistoryOptions, OUTPUT_TOKEN_RESERVE, type OpenAIMessage, POLL_INTERVAL, type ParsedAiAgent, type PinnedDispatchContext, RENDER_FROM_TOKEN, TOOL_AND_RESPONSE_BUFFER, buildAiAgentValue, buildBoundedChatMessages, buildChatDisplayList, buildChatSystemPrompt, buildDisplayExpiredAttachmentHref, buildIndexingContinueMessage, buildIndexingRenderContinueTemplate, buildIndexingRenderMessage, buildIndexingSystemPrompt, buildIndexingUserMessage, buildIndexingWindowMessage, callClaudeWithMcp, callClaudeWithPublicMcp, callOpenAIWithPublicMcp, chatEngineConfig, classifyInlineLink, clearAttachmentParsers, composeUserMessage, configureChatEngine, createHistoryFiller, createInlineLinkRegex, encodePathSegments, estimateMessageTokens, estimateTextTokens, extractClaudeText, extractLastUserTextFromRequest, extractOpenAIText, extractRemotePathFromAttachmentHref, fillHistoryViewport, filterListByClearHorizon, findAttachmentParser, formatChatTimestamp, getAttachmentParsers, getChatHistory, getContextWindow, getErrorMessage, getExpiredAttachmentVisiblePath, getProjectContextWindow, groupAttachmentFailures, isAuthExpiredError, isBgIndexingQueue, isErrorResponseBody, isHttpUrlLike, isIndexingRequestText, isNonRetryableRequestError, isOfficeFile, isServerExtractable, isServiceDbAttachmentHref, listClaudeModels, listOpenAIModels, makeExtractPlaceholder, mapHistoryListToMessages, normalizeAttachmentPathCandidate, normalizeTextContent, normalizeTrailingInlineToken, notifyAgentSaveAttachment, parseAiAgentValue, parseAttachmentContent, parseIndexingLabel, parseIndexingRequestText, readExpiredAttachmentHref, registerAttachmentParser, registerModelContextWindows, repairUrlEntities, repairUrlWhitespace, safeDecodeURIComponent, sanitizeAttachmentLinksForHistory, setProjectContextWindow, stripFileBlocksFromHistory, transformContentWithImages, transformContentWithOpenAIImages, truncateLabelForDisplay, wallClockNow };
package/dist/engine.d.ts CHANGED
@@ -312,18 +312,44 @@ declare function isAuthExpiredError(input: any): boolean;
312
312
 
313
313
  declare var CONTEXT_WINDOW_DEFAULT: Record<string, number>;
314
314
  declare var CONTEXT_WINDOW_BY_MODEL: Record<string, number>;
315
+ /**
316
+ * Record context windows from a provider models listing. Accepts the raw list
317
+ * items and reads `max_input_tokens` (Anthropic); items without it are skipped,
318
+ * so passing an OpenAI listing is a no-op rather than an error.
319
+ */
320
+ declare function registerModelContextWindows(models: Array<{
321
+ id?: string;
322
+ max_input_tokens?: number;
323
+ }> | null | undefined): void;
324
+ declare function setProjectContextWindow(serviceId: string, tokens: number | null | undefined): void;
325
+ declare function getProjectContextWindow(serviceId: string): number | null;
315
326
  declare var OUTPUT_TOKEN_RESERVE: number;
316
327
  declare var TOOL_AND_RESPONSE_BUFFER: number;
317
328
  declare var MIN_INPUT_TOKEN_BUDGET: number;
318
329
  declare var CLAUDE_PER_REQUEST_INPUT_CAP: number;
319
330
  declare var MAX_HISTORY_MESSAGES: number;
320
331
  declare var HISTORY_TOKEN_BUDGET: number;
332
+ declare var CLAUDE_INPUT_CAP_RATIO: number;
333
+ declare var HISTORY_BUDGET_RATIO: number;
321
334
  declare function estimateTextTokens(text: string): number;
322
335
  declare function estimateMessageTokens(msg: {
323
336
  role: string;
324
337
  content: string;
325
338
  }): number;
326
- declare function getContextWindow(platform: string, model?: string): number;
339
+ /**
340
+ * Resolve a model's context window, most specific source first:
341
+ * 1. per-project override (project settings)
342
+ * 2. the provider's own models listing (Anthropic `max_input_tokens`)
343
+ * 3. an exact entry in CONTEXT_WINDOW_BY_MODEL
344
+ * 4. a family entry, by dropping trailing '-' segments off the id
345
+ * 5. the platform default
346
+ *
347
+ * Step 4 is why a new or suffixed id no longer drops straight to the platform
348
+ * default: 'gpt-5.6-luna' resolves via 'gpt-5.6', and a dated Claude snapshot
349
+ * such as 'claude-opus-4-7-20260101' resolves via 'claude-opus-4-7'. The walk
350
+ * stops at the first hit, so a more specific entry always wins over its family.
351
+ */
352
+ declare function getContextWindow(platform: string, model?: string, serviceId?: string): number;
327
353
  declare function stripFileBlocksFromHistory(content: string): string;
328
354
  type BoundedChatOptions = {
329
355
  platform: string;
@@ -498,9 +524,61 @@ declare function wallClockNow(): number;
498
524
  */
499
525
  declare function formatChatTimestamp(ms?: number): string;
500
526
 
527
+ /**
528
+ * The `ai_agent` service option, parsed and serialized in ONE place.
529
+ *
530
+ * Stored on the skapi service record as up to three '#'-delimited segments:
531
+ *
532
+ * none AI chat disabled
533
+ * claude platform chosen, no model saved yet
534
+ * claude#claude-sonnet-4-6 platform + model
535
+ * claude#claude-sonnet-4-6#400000 platform + model + context-window override
536
+ *
537
+ * The third segment is new and optional, so every value written before it
538
+ * existed parses unchanged with `contextWindow: null`. Nothing writes a third
539
+ * segment without a model, because the window is meaningless without one.
540
+ *
541
+ * This lived as four separate copies (agent.vue, dbfile.vue, service.vue, and
542
+ * the widget's index.js), which is how the format drifts. New callers should
543
+ * import from here rather than re-deriving the split.
544
+ */
545
+ type AiAgentPlatform = 'claude' | 'openai' | null;
546
+ type ParsedAiAgent = {
547
+ /** null when unset or explicitly 'none'. */
548
+ platform: AiAgentPlatform;
549
+ /** '' when no model has been saved. */
550
+ model: string;
551
+ /** Per-project context-window override in tokens, or null to use the model's. */
552
+ contextWindow: number | null;
553
+ /** True when a real platform is configured (i.e. not unset and not 'none'). */
554
+ hasPlatform: boolean;
555
+ };
556
+ declare function parseAiAgentValue(value: string | null | undefined): ParsedAiAgent;
557
+ declare function buildAiAgentValue(platform: string | null | undefined, model?: string | null, contextWindow?: number | null): string;
558
+
501
559
  declare function filterListByClearHorizon(list: any[], clearedAt: number): any[];
502
560
  declare function normalizeTextContent(content: any): string;
503
561
  declare function extractLastUserTextFromRequest(requestBody: any): string;
562
+ /** The two openings an indexing prompt can have. A bg-queue item that starts with
563
+ * neither is an ordinary chat that happened to be routed onto that queue. */
564
+ declare function isIndexingRequestText(userText: any): boolean;
565
+ type IndexingRequestRef = {
566
+ name: string;
567
+ path?: string;
568
+ mime?: string;
569
+ size?: number;
570
+ /** A CONTINUE pass rather than the run's first. */
571
+ continued: boolean;
572
+ };
573
+ /**
574
+ * The file an indexing prompt is about, read back out of the prompt itself.
575
+ *
576
+ * The prompt is the only description of the pass that survives on the server, so
577
+ * this is how BOTH a history rebuild and a worker-minted pass the client never
578
+ * dispatched (ChatSession._adoptWorkerIndexingPasses) recover the file. Shared so
579
+ * the two produce the same `_indexFile`, which is what makes them group together.
580
+ */
581
+ declare function parseIndexingRequestText(userText: any): IndexingRequestRef | null;
504
582
  type MapHistoryOptions = {
505
583
  clearedAt: number;
506
584
  serviceId: string;
@@ -713,11 +791,20 @@ type BgTaskEntry = {
713
791
  /** How many CONTINUE passes have already run for this file (resume-across-passes). */
714
792
  resumePass?: number;
715
793
  };
794
+ /**
795
+ * `queue` narrows the fetch to one processing chain; `status` narrows it to items
796
+ * in one state. Passing both is how the client asks "is there still unresolved
797
+ * work on the background-indexing queue?" without pulling a page of chat history
798
+ * (see ChatSession._adoptWorkerIndexingPasses) — the server answers that from a
799
+ * status-keyed index, so the reply carries only the live items, not the bodies of
800
+ * everything already finished.
801
+ */
716
802
  declare function getChatHistory(params: {
717
803
  service?: string;
718
804
  owner?: string;
719
805
  platform: 'claude' | 'openai';
720
806
  queue?: string;
807
+ status?: 'pending' | 'running' | 'resolved' | 'failed';
721
808
  }, fetchOptions: Record<string, any>): Promise<any>;
722
809
 
723
810
  /**
@@ -1152,6 +1239,9 @@ declare class ChatSession {
1152
1239
  _clearPendingUserBubble(itemId: string): void;
1153
1240
  resumePendingRequest(token: number): Promise<void>;
1154
1241
  handleHistoryItemResolution(itemId: string, response: any, platform: string): void;
1242
+ /** The file an already-rendered background pass is about, off its request
1243
+ * bubble. Null for an ordinary turn, which is most of them. */
1244
+ private _indexRefOfItem;
1155
1245
  applyHistoryItemResolution(itemId: string, response: any, platform: string): void;
1156
1246
  /** How a bg task maps onto a collapsed row: the row's own key (storage path
1157
1247
  * when known, else the filename), scoped to the chat it belongs to. A storage
@@ -1183,6 +1273,49 @@ declare class ChatSession {
1183
1273
  * Runs from drainBgTaskQueue, which both clients call after a history load.
1184
1274
  */
1185
1275
  private _sweepCancelledIndexing;
1276
+ /**
1277
+ * True when the WORKER, not this client, drives the rest of this file's chain.
1278
+ * The mirror image of the early returns in maybeResumeIndexing: whatever that
1279
+ * refuses to continue is exactly what nothing client-side is tracking.
1280
+ */
1281
+ private _isWorkerDrivenIndexing;
1282
+ /**
1283
+ * Pick up indexing passes the WORKER minted, which no client ever dispatched.
1284
+ *
1285
+ * For a PDF (and for text/grid when windowed indexing is on) the worker writes
1286
+ * pass N+1's row itself, inside pass N's invocation, right after saving pass
1287
+ * N's result. That row reaches this client through nothing at all: it is not in
1288
+ * bgTaskQueue (the client never asked for it) and it is not in state.messages
1289
+ * (only a first-page history load maps it in, which happens on mount, project
1290
+ * switch or tab return). So between two worker passes every pass the client
1291
+ * knows about is settled, and the collapsed row renders "Indexed N passes"
1292
+ * with no spinner and no Stop, for a file that is still being read. A user who
1293
+ * believes that then asks questions against a half-indexed file — which is what
1294
+ * this exists to prevent.
1295
+ *
1296
+ * So when a background indexing pass settles, ask the bg queue what is still
1297
+ * unresolved on it and adopt anything unknown as an ordinary BgTaskEntry.
1298
+ * drainBgTaskQueue then treats it exactly like a pass this client dispatched:
1299
+ * same bubble, same `_indexFile` (so it joins the file's collapsed row), same
1300
+ * poll — and that poll settling runs this again, so the chain is followed to
1301
+ * its end. `status`-scoped so the reply carries the live items only, never a
1302
+ * page of finished ones with their bodies.
1303
+ *
1304
+ * Termination: the only trigger is a pass SETTLING, which happens once per
1305
+ * pass. An adopted item that is still running is not re-adopted (its id is
1306
+ * already polled), and when the queue holds nothing unknown the chain stops on
1307
+ * its own. Nothing here is periodic — a timer that re-reads history is the
1308
+ * shape that previously looped fetchHistoryPage after an already-DONE index.
1309
+ */
1310
+ private _adoptingWorkerPasses;
1311
+ private _adoptWorkerIndexingPasses;
1312
+ /** Any of these ids still queued or still polled, i.e. surviving work. */
1313
+ private _isTrackingAny;
1314
+ /** One live bg-queue item -> a BgTaskEntry, if it is an indexing pass this
1315
+ * client is not already tracking. Returns whether it was adopted. */
1316
+ private _adoptWorkerIndexingItem;
1317
+ /** Follow the chain on from a background indexing pass that just settled. */
1318
+ private _followWorkerIndexingChain;
1186
1319
  /** Best-effort server-side cancel of a bg-queue item that has no bubble (so
1187
1320
  * cancelQueuedMessage, which drives one, has nothing to act on). */
1188
1321
  private _cancelServerItem;
@@ -1203,4 +1336,4 @@ declare class ChatSession {
1203
1336
  bumpGate(): void;
1204
1337
  }
1205
1338
 
1206
- export { type AttachmentFailureGroup, type AttachmentParser, type AttachmentSaveInfo, BG_INDEXING_QUEUE_SUFFIX, type BgTaskEntry, type BoundedChatOptions, type BuildDisplayListOptions, type BuildIndexingUserMessageOptions, CLAUDE_PER_REQUEST_INPUT_CAP, CONTEXT_WINDOW_BY_MODEL, CONTEXT_WINDOW_DEFAULT, type CallClaudeWithMcpParams, type ChatEngineConfig, type ChatHost, type ChatIdentity, type ChatMessage, ChatSession, type ChatState, type ChatSystemPromptParams, type ClaudeMcpServerRequest, type ClaudeMcpToolConfig, type ClaudeMessage, type ClaudeRole, type ComposedUserMessage, DEFAULT_CLAUDE_MODEL, DEFAULT_OPENAI_MODEL, type DisplayEntry, EXPIRED_ATTACHMENT_URL_HOST, EXPIRED_ATTACHMENT_URL_ORIGIN, EXPIRED_LINK_REFRESH_EXPIRES_SECONDS, type ExtractDirective, type FillHistoryViewportOptions, HISTORY_FILL_SLACK_PX, HISTORY_TOKEN_BUDGET, type IndexingAttachmentInfo, type IndexingFileRef, type IndexingGroup, type IndexingGroupStatus, type IndexingSystemPromptParams, type InlineLinkContext, type InlineLinkPart, LINK_LABEL_MAX_DISPLAY_CHARS, LINK_REFRESH_WINDOW_MS, MAX_HISTORY_FILL_PAGES, MAX_HISTORY_MESSAGES, MAX_PARSED_CONTENT_CHARS, MCP_NAME, MIN_INPUT_TOKEN_BUDGET, type MapHistoryOptions, OUTPUT_TOKEN_RESERVE, type OpenAIMessage, POLL_INTERVAL, type PinnedDispatchContext, RENDER_FROM_TOKEN, TOOL_AND_RESPONSE_BUFFER, buildBoundedChatMessages, buildChatDisplayList, buildChatSystemPrompt, buildDisplayExpiredAttachmentHref, buildIndexingContinueMessage, buildIndexingRenderContinueTemplate, buildIndexingRenderMessage, buildIndexingSystemPrompt, buildIndexingUserMessage, buildIndexingWindowMessage, callClaudeWithMcp, callClaudeWithPublicMcp, callOpenAIWithPublicMcp, chatEngineConfig, classifyInlineLink, clearAttachmentParsers, composeUserMessage, configureChatEngine, createHistoryFiller, createInlineLinkRegex, encodePathSegments, estimateMessageTokens, estimateTextTokens, extractClaudeText, extractLastUserTextFromRequest, extractOpenAIText, extractRemotePathFromAttachmentHref, fillHistoryViewport, filterListByClearHorizon, findAttachmentParser, formatChatTimestamp, getAttachmentParsers, getChatHistory, getContextWindow, getErrorMessage, getExpiredAttachmentVisiblePath, groupAttachmentFailures, isAuthExpiredError, isBgIndexingQueue, isErrorResponseBody, isHttpUrlLike, isNonRetryableRequestError, isOfficeFile, isServerExtractable, isServiceDbAttachmentHref, listClaudeModels, listOpenAIModels, makeExtractPlaceholder, mapHistoryListToMessages, normalizeAttachmentPathCandidate, normalizeTextContent, normalizeTrailingInlineToken, notifyAgentSaveAttachment, parseAttachmentContent, parseIndexingLabel, readExpiredAttachmentHref, registerAttachmentParser, repairUrlEntities, repairUrlWhitespace, safeDecodeURIComponent, sanitizeAttachmentLinksForHistory, stripFileBlocksFromHistory, transformContentWithImages, transformContentWithOpenAIImages, truncateLabelForDisplay, wallClockNow };
1339
+ export { type AiAgentPlatform, type AttachmentFailureGroup, type AttachmentParser, type AttachmentSaveInfo, BG_INDEXING_QUEUE_SUFFIX, type BgTaskEntry, type BoundedChatOptions, type BuildDisplayListOptions, type BuildIndexingUserMessageOptions, CLAUDE_INPUT_CAP_RATIO, CLAUDE_PER_REQUEST_INPUT_CAP, CONTEXT_WINDOW_BY_MODEL, CONTEXT_WINDOW_DEFAULT, type CallClaudeWithMcpParams, type ChatEngineConfig, type ChatHost, type ChatIdentity, type ChatMessage, ChatSession, type ChatState, type ChatSystemPromptParams, type ClaudeMcpServerRequest, type ClaudeMcpToolConfig, type ClaudeMessage, type ClaudeRole, type ComposedUserMessage, DEFAULT_CLAUDE_MODEL, DEFAULT_OPENAI_MODEL, type DisplayEntry, EXPIRED_ATTACHMENT_URL_HOST, EXPIRED_ATTACHMENT_URL_ORIGIN, EXPIRED_LINK_REFRESH_EXPIRES_SECONDS, type ExtractDirective, type FillHistoryViewportOptions, HISTORY_BUDGET_RATIO, HISTORY_FILL_SLACK_PX, HISTORY_TOKEN_BUDGET, type IndexingAttachmentInfo, type IndexingFileRef, type IndexingGroup, type IndexingGroupStatus, type IndexingRequestRef, type IndexingSystemPromptParams, type InlineLinkContext, type InlineLinkPart, LINK_LABEL_MAX_DISPLAY_CHARS, LINK_REFRESH_WINDOW_MS, MAX_HISTORY_FILL_PAGES, MAX_HISTORY_MESSAGES, MAX_PARSED_CONTENT_CHARS, MCP_NAME, MIN_INPUT_TOKEN_BUDGET, type MapHistoryOptions, OUTPUT_TOKEN_RESERVE, type OpenAIMessage, POLL_INTERVAL, type ParsedAiAgent, type PinnedDispatchContext, RENDER_FROM_TOKEN, TOOL_AND_RESPONSE_BUFFER, buildAiAgentValue, buildBoundedChatMessages, buildChatDisplayList, buildChatSystemPrompt, buildDisplayExpiredAttachmentHref, buildIndexingContinueMessage, buildIndexingRenderContinueTemplate, buildIndexingRenderMessage, buildIndexingSystemPrompt, buildIndexingUserMessage, buildIndexingWindowMessage, callClaudeWithMcp, callClaudeWithPublicMcp, callOpenAIWithPublicMcp, chatEngineConfig, classifyInlineLink, clearAttachmentParsers, composeUserMessage, configureChatEngine, createHistoryFiller, createInlineLinkRegex, encodePathSegments, estimateMessageTokens, estimateTextTokens, extractClaudeText, extractLastUserTextFromRequest, extractOpenAIText, extractRemotePathFromAttachmentHref, fillHistoryViewport, filterListByClearHorizon, findAttachmentParser, formatChatTimestamp, getAttachmentParsers, getChatHistory, getContextWindow, getErrorMessage, getExpiredAttachmentVisiblePath, getProjectContextWindow, groupAttachmentFailures, isAuthExpiredError, isBgIndexingQueue, isErrorResponseBody, isHttpUrlLike, isIndexingRequestText, isNonRetryableRequestError, isOfficeFile, isServerExtractable, isServiceDbAttachmentHref, listClaudeModels, listOpenAIModels, makeExtractPlaceholder, mapHistoryListToMessages, normalizeAttachmentPathCandidate, normalizeTextContent, normalizeTrailingInlineToken, notifyAgentSaveAttachment, parseAiAgentValue, parseAttachmentContent, parseIndexingLabel, parseIndexingRequestText, readExpiredAttachmentHref, registerAttachmentParser, registerModelContextWindows, repairUrlEntities, repairUrlWhitespace, safeDecodeURIComponent, sanitizeAttachmentLinksForHistory, setProjectContextWindow, stripFileBlocksFromHistory, transformContentWithImages, transformContentWithOpenAIImages, truncateLabelForDisplay, wallClockNow };