@tanstack/ai-client 0.26.0 → 0.29.0

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.
Files changed (56) hide show
  1. package/dist/esm/byok/client.d.ts +52 -0
  2. package/dist/esm/byok/client.js +300 -0
  3. package/dist/esm/byok/client.js.map +1 -0
  4. package/dist/esm/byok/passkey.d.ts +43 -0
  5. package/dist/esm/byok/passkey.js +251 -0
  6. package/dist/esm/byok/passkey.js.map +1 -0
  7. package/dist/esm/byok/resolve.d.ts +8 -0
  8. package/dist/esm/byok/resolve.js +20 -0
  9. package/dist/esm/byok/resolve.js.map +1 -0
  10. package/dist/esm/byok/storage.d.ts +15 -0
  11. package/dist/esm/byok/storage.js +16 -0
  12. package/dist/esm/byok/storage.js.map +1 -0
  13. package/dist/esm/byok.d.ts +8 -0
  14. package/dist/esm/byok.js +5 -0
  15. package/dist/esm/chat-client.d.ts +19 -3
  16. package/dist/esm/chat-client.js +82 -42
  17. package/dist/esm/chat-client.js.map +1 -1
  18. package/dist/esm/connection-adapters.d.ts +2 -0
  19. package/dist/esm/connection-adapters.js +35 -10
  20. package/dist/esm/connection-adapters.js.map +1 -1
  21. package/dist/esm/generation-client.d.ts +3 -1
  22. package/dist/esm/generation-client.js +23 -4
  23. package/dist/esm/generation-client.js.map +1 -1
  24. package/dist/esm/generation-types.d.ts +14 -0
  25. package/dist/esm/generation-types.js.map +1 -1
  26. package/dist/esm/interrupt-manager.d.ts +1 -0
  27. package/dist/esm/interrupt-manager.js +15 -6
  28. package/dist/esm/interrupt-manager.js.map +1 -1
  29. package/dist/esm/message-date-normalizer.d.ts +3 -0
  30. package/dist/esm/message-date-normalizer.js +35 -0
  31. package/dist/esm/message-date-normalizer.js.map +1 -0
  32. package/dist/esm/sse-parser.js +8 -1
  33. package/dist/esm/sse-parser.js.map +1 -1
  34. package/dist/esm/storage-adapters.js +13 -1
  35. package/dist/esm/storage-adapters.js.map +1 -1
  36. package/dist/esm/types.d.ts +34 -3
  37. package/dist/esm/types.js.map +1 -1
  38. package/dist/esm/video-generation-client.d.ts +3 -1
  39. package/dist/esm/video-generation-client.js +25 -6
  40. package/dist/esm/video-generation-client.js.map +1 -1
  41. package/package.json +7 -3
  42. package/src/byok/client.ts +360 -0
  43. package/src/byok/passkey.ts +399 -0
  44. package/src/byok/resolve.ts +30 -0
  45. package/src/byok/storage.ts +29 -0
  46. package/src/byok.ts +20 -0
  47. package/src/chat-client.ts +165 -72
  48. package/src/connection-adapters.ts +46 -14
  49. package/src/generation-client.ts +48 -4
  50. package/src/generation-types.ts +16 -0
  51. package/src/interrupt-manager.ts +20 -6
  52. package/src/message-date-normalizer.ts +29 -0
  53. package/src/sse-parser.ts +10 -0
  54. package/src/storage-adapters.ts +13 -2
  55. package/src/types.ts +36 -3
  56. package/src/video-generation-client.ts +45 -4
@@ -1 +1 @@
1
- {"version":3,"file":"interrupt-manager.js","names":[],"sources":["../../src/interrupt-manager.ts"],"sourcesContent":["import {\n INTERRUPT_BINDING_METADATA_KEY,\n INTERRUPT_BINDING_VERSION,\n canonicalInterruptJson,\n canonicalizeInterruptResolutions,\n cloneAndDeepFreezeJson,\n digestInterruptJson,\n genericInterruptContinuationFromDescriptor,\n hashInterruptDefinitionSchema,\n hashSchemaInput,\n isStandardSchema,\n normalizeApprovalSchema,\n readInterruptBinding,\n wrapGenericInterruptContinuation,\n} from '@tanstack/ai/client'\nimport type {\n AnyClientTool,\n BatchInterruptError,\n Interrupt,\n InterruptBinding,\n InterruptDefinition,\n InterruptSubmissionError,\n ItemInterruptError,\n RunAgentResumeItem,\n} from '@tanstack/ai/client'\nimport type {\n BoundInterruptBase,\n BoundInterrupts,\n ChatInterrupt,\n ChatInterruptState,\n GenericAGUIInterrupt,\n InterruptItemStatus,\n ResolvableChatInterrupt,\n UnboundInterrupt,\n} from './types'\n\nexport interface InterruptManagerHydration {\n threadId: string\n interruptedRunId: string\n generation: number\n interrupts: ReadonlyArray<Interrupt>\n}\n\nexport interface InterruptManagerSubmission {\n threadId: string\n interruptedRunId: string\n generation: number\n resolutions: ReadonlyArray<RunAgentResumeItem>\n canonicalResolutions: string\n fingerprint: string\n}\n\nexport type InterruptManagerChangeSource = 'hydrate' | 'live'\n\nexport interface InterruptManagerOptions<\n TTools extends ReadonlyArray<AnyClientTool>,\n TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>> =\n readonly [],\n> {\n tools?: TTools\n interrupts?: TInterrupts\n submit: (submission: InterruptManagerSubmission) => Promise<void>\n onChange?: (source: InterruptManagerChangeSource) => void\n}\n\ntype UnknownObject = { [key: string]: unknown }\n\ntype RuntimeKind =\n | 'generic'\n | 'tool-approval'\n | 'client-tool-execution'\n /** Carries no binding we understand — not ours to resume. */\n | 'unbound'\n\ninterface RuntimeInterrupt {\n descriptor: Interrupt\n /** `undefined` only for `unbound` items. */\n binding: InterruptBinding | undefined\n kind: RuntimeKind\n status: InterruptItemStatus\n canResolve: boolean\n error?: ItemInterruptError\n resolution?: RunAgentResumeItem\n tool?: AnyClientTool\n definition?: InterruptDefinition<any, any, any, any>\n /** Validated display payload for a registered first-party generic item. */\n payload?: unknown\n /** This binding is valid and can participate in this chat resume batch. */\n resumable: boolean\n validationGeneration: number\n}\n\ninterface ValidationFailure {\n code: ItemInterruptError['code']\n message: string\n path?: ReadonlyArray<string | number>\n}\n\ntype ValidationResult = { valid: true; payload: unknown } | ValidationFailure\n\ninterface TransactionToken {\n active: boolean\n}\n\ninterface RuntimeInterruptCheckpoint {\n status: InterruptItemStatus\n resolution?: RunAgentResumeItem\n error?: ItemInterruptError\n validationGeneration: number\n}\n\nfunction isClientOwnedInterrupt(item: RuntimeInterrupt): boolean {\n return item.resumable\n}\n\nfunction resolutionWithContinuation(\n item: RuntimeInterrupt,\n resolution: RunAgentResumeItem,\n): RunAgentResumeItem {\n const continuation = genericInterruptContinuationFromDescriptor(\n item.descriptor,\n )\n if (!continuation) return resolution\n return {\n ...resolution,\n metadata: wrapGenericInterruptContinuation(continuation),\n }\n}\n\nfunction isRootResolvableInterrupt<\n TTools extends ReadonlyArray<AnyClientTool>,\n TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>>,\n>(\n interrupt: ChatInterrupt<TTools, TInterrupts>,\n): interrupt is ResolvableChatInterrupt<TTools, TInterrupts> {\n return 'cancel' in interrupt && 'clearResolution' in interrupt\n}\n\nconst itemErrorCodes = new Set<ItemInterruptError['code']>([\n 'invalid-payload',\n 'invalid-edited-args',\n 'invalid-tool-output',\n 'invalid-response-schema',\n 'unknown-interrupt',\n 'expired',\n 'stale',\n 'conflict',\n 'legacy-unsupported',\n])\n\nconst batchErrorCodes = new Set<BatchInterruptError['code']>([\n 'incomplete-batch',\n 'item-validation-failed',\n 'unsupported-bulk-operation',\n 'async-resolver',\n 'inactive-transaction',\n 'mixed-provenance',\n 'transport',\n 'server',\n 'protocol',\n 'invalid-response-schema',\n 'expired',\n 'stale',\n 'conflict',\n 'legacy-submit-failed',\n])\n\nfunction isUnknownObject(value: unknown): value is UnknownObject {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isLegacyApprovalMetadata(value: unknown): boolean {\n return (\n isUnknownObject(value) &&\n value['kind'] === 'approval' &&\n typeof value['toolName'] === 'string' &&\n 'input' in value\n )\n}\n\nfunction isLegacyClientToolMetadata(value: unknown): boolean {\n return (\n isUnknownObject(value) &&\n value['kind'] === 'client_tool' &&\n typeof value['toolName'] === 'string' &&\n 'input' in value\n )\n}\n\n/**\n * Does this descriptor carry the pre-binding TanStack metadata marker?\n *\n * Descriptors emitted before the resume binding existed are still ours to\n * resume, so they must not be mistaken for another producer's interrupt.\n */\nfunction isLegacyInterruptMetadata(interrupt: Interrupt): boolean {\n return (\n isLegacyApprovalMetadata(interrupt.metadata) ||\n isLegacyClientToolMetadata(interrupt.metadata)\n )\n}\n\nfunction getDescriptorBinding(\n interrupt: Interrupt,\n): InterruptBinding | undefined {\n return readInterruptBinding(interrupt)\n}\n\nfunction hasReservedFirstPartyBindingMarker(interrupt: Interrupt): boolean {\n if (!isUnknownObject(interrupt.metadata)) return false\n const binding = interrupt.metadata[INTERRUPT_BINDING_METADATA_KEY]\n if (!isUnknownObject(binding)) return false\n if (\n binding['v'] !== undefined &&\n binding['v'] !== INTERRUPT_BINDING_VERSION\n ) {\n return false\n }\n return (\n binding['kind'] === 'generic' ||\n binding['kind'] === 'tool-approval' ||\n binding['kind'] === 'client-tool-execution' ||\n 'definitionId' in binding ||\n 'key' in binding ||\n 'batchIndex' in binding ||\n 'payloadSchemaHash' in binding\n )\n}\n\nfunction hasFirstPartyGenericMarker(interrupt: Interrupt): boolean {\n if (!isUnknownObject(interrupt.metadata)) return false\n const binding = interrupt.metadata[INTERRUPT_BINDING_METADATA_KEY]\n if (!isUnknownObject(binding) || binding['kind'] !== 'generic') return false\n return (\n 'definitionId' in binding ||\n 'key' in binding ||\n 'batchIndex' in binding ||\n 'payloadSchemaHash' in binding\n )\n}\n\nfunction getInterruptPayload(interrupt: Interrupt): unknown {\n return interrupt.metadata?.['tanstack:interruptPayload']\n}\n\n/**\n * Only used to route *legacy* (pre-binding) descriptors, which have no binding\n * to classify off. Current descriptors are classified by their binding alone.\n */\nfunction isClientToolExecutionReason(reason: string): boolean {\n return (\n reason === 'tanstack:client_tool_execution' ||\n reason === 'client_tool_input'\n )\n}\n\nfunction responseSchemaHash(interrupt: Interrupt): string | undefined {\n if (interrupt.responseSchema === undefined) return undefined\n try {\n return digestInterruptJson(canonicalInterruptJson(interrupt.responseSchema))\n } catch {\n return undefined\n }\n}\n\nfunction definitionSchemaHash(\n schema: InterruptDefinition<any, any, any, any>['responseSchema'] | undefined,\n): string | undefined {\n if (schema === undefined) return undefined\n try {\n return hashInterruptDefinitionSchema(schema)\n } catch {\n return undefined\n }\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n value !== null &&\n (typeof value === 'object' || typeof value === 'function') &&\n 'then' in value &&\n typeof value.then === 'function'\n )\n}\n\nfunction validateWithSchema(\n schema: unknown,\n value: unknown,\n code: ItemInterruptError['code'],\n): ValidationResult | Promise<ValidationResult> {\n if (schema === undefined) return { valid: true, payload: value }\n if (isStandardSchema(schema)) {\n const result = schema['~standard'].validate(value)\n const normalize = (\n validation: Awaited<typeof result>,\n ): ValidationResult => {\n if (!validation.issues) {\n return { valid: true, payload: validation.value }\n }\n return {\n code,\n message: validation.issues[0]?.message ?? 'Schema validation failed.',\n }\n }\n return isPromiseLike(result)\n ? Promise.resolve(result).then(normalize)\n : normalize(result)\n }\n // A non-Standard-Schema value (a raw JSON Schema arriving over the wire) is\n // not validated by the library. The application transforms the schema and\n // validates the value itself before resolving; whatever it passes flows\n // through as-is.\n return { valid: true, payload: value }\n}\n\nfunction isItemErrorCode(value: string): value is ItemInterruptError['code'] {\n for (const code of itemErrorCodes) if (code === value) return true\n return false\n}\n\nfunction isBatchErrorCode(value: string): value is BatchInterruptError['code'] {\n for (const code of batchErrorCodes) if (code === value) return true\n return false\n}\n\nfunction isSubmissionError(value: unknown): value is InterruptSubmissionError {\n if (!isUnknownObject(value)) return false\n const scope = value['scope']\n const code = value['code']\n const base =\n typeof code === 'string' &&\n typeof value['message'] === 'string' &&\n typeof value['retryable'] === 'boolean' &&\n typeof value['threadId'] === 'string' &&\n typeof value['interruptedRunId'] === 'string' &&\n typeof value['generation'] === 'number'\n if (!base) return false\n if (scope === 'item') {\n return (\n isItemErrorCode(code) &&\n typeof value['interruptId'] === 'string' &&\n (value['source'] === 'client' || value['source'] === 'server')\n )\n }\n return (\n scope === 'batch' &&\n isBatchErrorCode(code) &&\n Array.isArray(value['interruptIds']) &&\n value['interruptIds'].every((id) => typeof id === 'string') &&\n (value['source'] === 'client' ||\n value['source'] === 'server' ||\n value['source'] === 'transport')\n )\n}\n\nfunction readSubmissionErrors(\n error: unknown,\n): ReadonlyArray<InterruptSubmissionError> {\n if (isSubmissionError(error)) return [error]\n if (!isUnknownObject(error) || !Array.isArray(error['errors'])) return []\n return error['errors'].every(isSubmissionError) ? error['errors'] : []\n}\n\nfunction haveSameInterruptIds(\n left: ReadonlyArray<string>,\n right: ReadonlyArray<string>,\n): boolean {\n if (left.length !== right.length) return false\n const sortedLeft = [...left].sort()\n const sortedRight = [...right].sort()\n return sortedLeft.every((id, index) => id === sortedRight[index])\n}\n\nfunction haveSameBatchCorrelation(\n left: BatchInterruptError,\n right: BatchInterruptError,\n): boolean {\n return (\n left.threadId === right.threadId &&\n left.interruptedRunId === right.interruptedRunId &&\n left.generation === right.generation &&\n haveSameInterruptIds(left.interruptIds, right.interruptIds)\n )\n}\n\nfunction mergeSubmissionBatchErrors(\n current: ReadonlyArray<BatchInterruptError>,\n previousSubmission: ReadonlyArray<BatchInterruptError>,\n incoming: ReadonlyArray<BatchInterruptError>,\n): {\n rootErrors: ReadonlyArray<BatchInterruptError>\n submissionRootErrors: ReadonlyArray<BatchInterruptError>\n} {\n const replaceableIncoming = incoming.filter(\n (error) => error.source !== 'transport',\n )\n const isSuperseded = (candidate: BatchInterruptError): boolean =>\n previousSubmission.includes(candidate) &&\n replaceableIncoming.some((error) =>\n haveSameBatchCorrelation(candidate, error),\n )\n const retainedRootErrors = current.filter(\n (candidate) => !isSuperseded(candidate),\n )\n const retainedSubmissionRootErrors = previousSubmission.filter(\n (candidate) =>\n !replaceableIncoming.some((error) =>\n haveSameBatchCorrelation(candidate, error),\n ),\n )\n return Object.freeze({\n rootErrors: Object.freeze([...retainedRootErrors, ...incoming]),\n submissionRootErrors: Object.freeze([\n ...retainedSubmissionRootErrors,\n ...replaceableIncoming,\n ]),\n })\n}\n\nfunction submissionErrorMatchesActiveBatch(\n error: InterruptSubmissionError,\n submission: InterruptManagerSubmission,\n): boolean {\n if (\n error.threadId !== submission.threadId ||\n error.interruptedRunId !== submission.interruptedRunId ||\n error.generation !== submission.generation\n ) {\n return false\n }\n const interruptIds = submission.resolutions.map(\n (resolution) => resolution.interruptId,\n )\n return error.scope === 'item'\n ? interruptIds.includes(error.interruptId)\n : haveSameInterruptIds(error.interruptIds, interruptIds)\n}\n\nfunction genericBinding(\n interrupt: Interrupt,\n hydration: InterruptManagerHydration,\n candidate: InterruptBinding | undefined,\n): InterruptBinding {\n const schemaHash =\n responseSchemaHash(interrupt) ?? candidate?.responseSchemaHash\n return cloneAndDeepFreezeJson({\n v: INTERRUPT_BINDING_VERSION,\n kind: 'generic',\n interruptId: interrupt.id,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n ...(schemaHash !== undefined ? { responseSchemaHash: schemaHash } : {}),\n ...(interrupt.expiresAt !== undefined\n ? { expiresAt: interrupt.expiresAt }\n : {}),\n })\n}\n\nfunction baseSnapshot(\n item: RuntimeInterrupt,\n hydration: InterruptManagerHydration,\n): Omit<BoundInterruptBase, 'cancel' | 'clearResolution'> {\n const descriptor = cloneAndDeepFreezeJson(item.descriptor)\n const errors: ReadonlyArray<ItemInterruptError> =\n item.error === undefined\n ? Object.freeze([])\n : Object.freeze([cloneAndDeepFreezeJson(item.error)])\n const error = errors[0]\n return {\n id: descriptor.id,\n interruptId: descriptor.id,\n reason: descriptor.reason,\n ...(descriptor.message !== undefined\n ? { message: descriptor.message }\n : {}),\n ...(descriptor.responseSchema !== undefined\n ? { responseSchema: descriptor.responseSchema }\n : {}),\n ...(descriptor.expiresAt !== undefined\n ? { expiresAt: descriptor.expiresAt }\n : {}),\n ...(descriptor.metadata !== undefined\n ? { metadata: descriptor.metadata }\n : {}),\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n status: item.status,\n errors,\n ...(error !== undefined ? { error } : {}),\n canResolve: item.canResolve,\n }\n}\n\nexport class InterruptManager<\n TTools extends ReadonlyArray<AnyClientTool> = ReadonlyArray<AnyClientTool>,\n TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>> =\n readonly [],\n> {\n private hydration: InterruptManagerHydration | undefined\n private items: Array<RuntimeInterrupt> = []\n private snapshot: ReadonlyArray<ChatInterrupt<TTools, TInterrupts>> =\n Object.freeze([])\n private rootErrors: ReadonlyArray<BatchInterruptError> = Object.freeze([])\n private submissionRootErrors: ReadonlyArray<BatchInterruptError> =\n Object.freeze([])\n private state: ChatInterruptState<TTools, TInterrupts> = Object.freeze({\n interrupts: this.snapshot,\n pendingInterrupts: this.snapshot,\n interruptErrors: this.rootErrors,\n resuming: false,\n })\n private activeTransaction: TransactionToken | undefined\n private retrySubmission: InterruptManagerSubmission | undefined\n private resuming = false\n private tools: TTools | undefined\n private readonly interruptDefinitions: ReadonlyMap<\n string,\n InterruptDefinition<any, any, any, any>\n >\n\n constructor(\n private readonly options: InterruptManagerOptions<TTools, TInterrupts>,\n ) {\n this.tools = options.tools\n const definitions = new Map<\n string,\n InterruptDefinition<any, any, any, any>\n >()\n for (const definition of options.interrupts ?? []) {\n if (definitions.has(definition.id)) {\n throw new Error(`Duplicate interrupt definition id: ${definition.id}`)\n }\n definitions.set(definition.id, definition)\n }\n this.interruptDefinitions = definitions\n }\n\n updateTools(tools: TTools): void {\n this.tools = tools\n }\n\n hydrate(\n hydration: InterruptManagerHydration,\n source: InterruptManagerChangeSource = 'live',\n ): void {\n this.hydration = {\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n interrupts: cloneAndDeepFreezeJson(hydration.interrupts),\n }\n const firstPartyIndexes = new Map<number, number>()\n for (const interrupt of hydration.interrupts) {\n const binding = getDescriptorBinding(interrupt)\n if (\n binding?.kind === 'generic' &&\n binding.definitionId !== undefined &&\n binding.key !== undefined &&\n binding.batchIndex !== undefined\n ) {\n firstPartyIndexes.set(\n binding.batchIndex,\n (firstPartyIndexes.get(binding.batchIndex) ?? 0) + 1,\n )\n }\n }\n this.items = hydration.interrupts.map((interrupt) =>\n this.hydrateInterrupt(interrupt, hydration, firstPartyIndexes),\n )\n this.rootErrors = Object.freeze([])\n this.submissionRootErrors = Object.freeze([])\n this.retrySubmission = undefined\n this.resuming = false\n this.publish(source)\n }\n\n getInterrupts(): BoundInterrupts<TTools, TInterrupts> {\n return this.snapshot\n }\n\n getState(): ChatInterruptState<TTools, TInterrupts> {\n return this.state\n }\n\n getDescriptors(): ReadonlyArray<Interrupt> {\n return this.hydration?.interrupts ?? Object.freeze([])\n }\n\n hasValidatedFirstPartyGenericBatch(): boolean {\n return this.items.some(\n (item) => item.kind === 'generic' && item.definition !== undefined,\n )\n }\n\n reset(options?: {\n preserveRootErrors?: boolean\n source?: InterruptManagerChangeSource\n }): void {\n this.hydration = undefined\n this.items = []\n this.snapshot = Object.freeze([])\n if (options?.preserveRootErrors !== true) {\n this.rootErrors = Object.freeze([])\n this.submissionRootErrors = Object.freeze([])\n }\n this.retrySubmission = undefined\n this.resuming = false\n this.state = Object.freeze({\n interrupts: this.snapshot,\n pendingInterrupts: this.snapshot,\n interruptErrors: this.rootErrors,\n resuming: false,\n })\n this.options.onChange?.(options?.source ?? 'live')\n }\n\n getInterruptErrors(): ReadonlyArray<BatchInterruptError> {\n return this.rootErrors\n }\n\n getResuming(): boolean {\n return this.resuming\n }\n\n resolve(approved: boolean): void\n resolve(\n resolver: (\n interrupt: ResolvableChatInterrupt<TTools, TInterrupts>,\n ) => undefined,\n ): void\n resolve(\n resolution:\n | boolean\n | ((interrupt: ResolvableChatInterrupt<TTools, TInterrupts>) => unknown),\n ): void {\n this.assertRootMutable()\n if (typeof resolution === 'boolean') {\n this.resolveBooleanBulk(resolution)\n return\n }\n this.resolveTransaction(resolution)\n }\n\n cancel(): void {\n this.assertRootMutable()\n this.invalidateRetry()\n for (const item of this.items) {\n if (!isClientOwnedInterrupt(item)) continue\n item.validationGeneration++\n item.resolution = Object.freeze(\n resolutionWithContinuation(item, {\n interruptId: item.descriptor.id,\n status: 'cancelled',\n }),\n )\n item.status = 'staged'\n item.error = undefined\n }\n this.publish()\n this.maybeSubmit()\n }\n\n retry(): void {\n if (this.resuming)\n throw new Error('Interrupt submission is already active.')\n const submission = this.retrySubmission\n if (!submission) {\n this.addRootError(\n 'transport',\n 'There is no retryable interrupt submission.',\n false,\n )\n return\n }\n this.submitBatch(submission)\n }\n\n resolveClientToolOutput(toolCallId: string, output: unknown): boolean {\n const item = this.items.find(\n (candidate) =>\n (candidate.kind === 'client-tool-execution' &&\n candidate.binding?.kind === 'client-tool-execution' &&\n candidate.binding.toolCallId === toolCallId) ||\n (candidate.kind === 'generic' &&\n isClientToolExecutionReason(candidate.descriptor.reason) &&\n candidate.descriptor.toolCallId === toolCallId &&\n isLegacyClientToolMetadata(candidate.descriptor.metadata)),\n )\n if (!item) return false\n this.resolveItem(item.descriptor.id, output)\n return true\n }\n\n resolveToolApprovalDecision(interruptId: string, approved: boolean): boolean {\n const item = this.items.find(\n (candidate) =>\n candidate.descriptor.id === interruptId &&\n (candidate.kind === 'tool-approval' ||\n (candidate.kind === 'generic' &&\n candidate.descriptor.reason === 'approval_required' &&\n isLegacyApprovalMetadata(candidate.descriptor.metadata))),\n )\n if (!item) return false\n this.resolveItem(item.descriptor.id, { approved })\n return true\n }\n\n private hydrateInterrupt(\n descriptor: Interrupt,\n hydration: InterruptManagerHydration,\n firstPartyIndexes: ReadonlyMap<number, number>,\n ): RuntimeInterrupt {\n const interrupt = cloneAndDeepFreezeJson(descriptor)\n const candidate = getDescriptorBinding(interrupt)\n const legacyResumable =\n candidate === undefined && isLegacyInterruptMetadata(interrupt)\n\n // No binding we understand, and nothing else identifying the descriptor as\n // ours, means this interrupt was not produced by this package's resume\n // path — a workflow engine's durable approval projected onto the same\n // AG-UI stream, a third-party agent's pause, or a binding written at a\n // protocol version we don't know.\n //\n // Do not invent a binding for it. Synthesising one would render a\n // resolvable form whose answer is submitted against a run that has no\n // matching pending descriptor, failing late as `unknown-interrupt` after\n // the user has already filled it in. Surface it as unresolvable instead,\n // so \"someone else owns this pause\" is visible rather than silently\n // translated into an AI-domain interrupt.\n //\n // Pre-binding TanStack descriptors are still ours: they carry the legacy\n // `metadata.kind` marker, so they keep hydrating through the generic path\n // below.\n if (candidate === undefined && !legacyResumable) {\n if (hasReservedFirstPartyBindingMarker(interrupt)) {\n return {\n descriptor: interrupt,\n binding: genericBinding(interrupt, hydration, undefined),\n kind: 'generic',\n status: 'error',\n canResolve: false,\n resumable: false,\n error: this.itemError(\n interrupt.id,\n 'stale',\n 'The interrupt binding is invalid or incomplete.',\n ),\n validationGeneration: 0,\n }\n }\n return {\n descriptor: interrupt,\n binding: undefined,\n kind: 'unbound',\n status: 'pending',\n canResolve: false,\n resumable: false,\n validationGeneration: 0,\n }\n }\n\n const correlated =\n candidate !== undefined &&\n candidate.interruptId === interrupt.id &&\n candidate.interruptedRunId === hydration.interruptedRunId &&\n candidate.generation === hydration.generation &&\n responseSchemaHash(interrupt) === candidate.responseSchemaHash\n\n const structurallyCorrelated =\n candidate !== undefined &&\n candidate.interruptId === interrupt.id &&\n candidate.interruptedRunId === hydration.interruptedRunId &&\n candidate.generation === hydration.generation &&\n candidate.responseSchemaHash ===\n (responseSchemaHash(interrupt) ?? candidate.responseSchemaHash)\n\n if (\n candidate !== undefined &&\n hasFirstPartyGenericMarker(interrupt) &&\n (!structurallyCorrelated ||\n candidate.kind !== 'generic' ||\n candidate.definitionId === undefined ||\n candidate.key === undefined ||\n candidate.batchIndex === undefined)\n ) {\n return {\n descriptor: interrupt,\n binding: genericBinding(interrupt, hydration, candidate),\n kind: 'generic',\n status: 'error',\n canResolve: false,\n resumable: false,\n error: this.itemError(\n interrupt.id,\n 'stale',\n 'The interrupt binding does not match this interrupted run.',\n ),\n validationGeneration: 0,\n }\n }\n\n if (structurallyCorrelated && candidate.kind === 'tool-approval') {\n const tool = this.tools?.find(\n (configured) => configured.name === candidate.toolName,\n )\n // Gated on the binding and the schema hashes below, not on\n // `interrupt.reason` — that string is free-form AG-UI text another\n // producer can also use, so it cannot be what decides ownership.\n if (\n tool?.needsApproval === true &&\n interrupt.toolCallId === candidate.toolCallId\n ) {\n try {\n const approval = normalizeApprovalSchema(\n tool.approvalSchema,\n tool.inputSchema,\n )\n if (\n hashSchemaInput(tool.inputSchema) === candidate.inputSchemaHash &&\n approval.approvalSchemaHash === candidate.approvalSchemaHash &&\n approval.responseSchemaHash === candidate.responseSchemaHash\n ) {\n return {\n descriptor: interrupt,\n binding: cloneAndDeepFreezeJson(candidate),\n kind: 'tool-approval',\n status: 'pending',\n canResolve: true,\n resumable: true,\n tool,\n validationGeneration: 0,\n }\n }\n } catch {\n // Invalid configured schemas cannot safely grant typed hydration.\n }\n }\n }\n\n if (structurallyCorrelated && candidate.kind === 'client-tool-execution') {\n const tool = this.tools?.find(\n (configured) => configured.name === candidate.toolName,\n )\n // Binding-gated, for the same reason as tool approvals above.\n if (\n tool !== undefined &&\n interrupt.toolCallId === candidate.toolCallId &&\n hashSchemaInput(tool.outputSchema) === candidate.outputSchemaHash\n ) {\n return {\n descriptor: interrupt,\n binding: cloneAndDeepFreezeJson(candidate),\n kind: 'client-tool-execution',\n status: 'pending',\n canResolve: true,\n resumable: true,\n tool,\n validationGeneration: 0,\n }\n }\n }\n\n if (\n candidate !== undefined &&\n candidate.kind === 'generic' &&\n candidate.definitionId !== undefined &&\n candidate.key !== undefined &&\n candidate.batchIndex !== undefined &&\n candidate.key.length > 0 &&\n firstPartyIndexes.get(candidate.batchIndex) !== 1\n ) {\n return {\n descriptor: interrupt,\n binding: cloneAndDeepFreezeJson(candidate),\n kind: 'generic',\n status: 'error',\n canResolve: false,\n resumable: false,\n error: this.itemError(\n interrupt.id,\n 'stale',\n 'Generic interrupt batch contains a duplicate batchIndex.',\n ),\n validationGeneration: 0,\n }\n }\n\n if (\n correlated &&\n candidate.kind === 'generic' &&\n candidate.definitionId !== undefined &&\n candidate.key !== undefined &&\n candidate.batchIndex !== undefined &&\n candidate.key.length > 0 &&\n firstPartyIndexes.get(candidate.batchIndex) === 1\n ) {\n const definition = this.interruptDefinitions.get(candidate.definitionId)\n if (\n definition !== undefined &&\n definitionSchemaHash(definition.responseSchema) ===\n candidate.responseSchemaHash &&\n (definition.payloadSchema === undefined\n ? candidate.payloadSchemaHash === undefined\n : candidate.payloadSchemaHash ===\n definitionSchemaHash(definition.payloadSchema))\n ) {\n const rawPayload = getInterruptPayload(interrupt)\n // First-party display payloads are parsed by definition.interrupt()\n // before the server emits them. Re-validating here would feed schema\n // output back through an input schema and reject transforms such as\n // z.string().transform(Number). The checks above still bind this value\n // to the exact descriptor, run, generation, definition, and schemas.\n return {\n descriptor: interrupt,\n binding: cloneAndDeepFreezeJson(candidate),\n definition,\n kind: 'generic',\n status: 'pending',\n canResolve: true,\n resumable: true,\n ...(rawPayload === undefined\n ? {}\n : { payload: cloneAndDeepFreezeJson(rawPayload) }),\n validationGeneration: 0,\n }\n }\n }\n\n const resumable =\n legacyResumable ||\n (candidate !== undefined &&\n candidate.interruptId === interrupt.id &&\n candidate.interruptedRunId === hydration.interruptedRunId &&\n candidate.generation === hydration.generation &&\n (candidate.kind !== 'generic' ||\n responseSchemaHash(interrupt) === undefined ||\n candidate.responseSchemaHash === responseSchemaHash(interrupt)))\n return {\n descriptor: interrupt,\n binding: genericBinding(interrupt, hydration, candidate),\n kind: 'generic',\n status: 'pending',\n // A valid raw binding is an explicit request to use this resume path,\n // even when this client has no registered first-party definition. Keep\n // it untyped, but preserve its existing generic controls. Missing,\n // malformed, and unsupported bindings remain display-only.\n canResolve: resumable,\n resumable,\n validationGeneration: 0,\n }\n }\n\n private buildSnapshot(\n transaction?: TransactionToken,\n ): BoundInterrupts<TTools, TInterrupts> {\n const hydration = this.requireHydration()\n // `client-tool-execution` items stay in `this.items` (they usually gate\n // batch submission and are resolved internally via auto-execution /\n // addToolResult), but they are never surfaced as public bound interrupts.\n // A mixed generic batch is the exception: those client tools wait for\n // `toolResume` and must not block submit.\n //\n // Items with status `submitting` are also omitted: the resume stream is\n // already in flight, so Approve/Deny is not actionable. Keeping them in\n // the public list made UIs look stuck after a successful approve and\n // blocked follow-up turns that key off `interrupts.length`.\n const next = this.items\n .filter(\n (item) =>\n item.kind !== 'client-tool-execution' && item.status !== 'submitting',\n )\n .map((item) => {\n const base = baseSnapshot(item, hydration)\n // Not ours to resume: expose the descriptor so a UI can show the run\n // is paused, with no `resolveInterrupt` to call.\n if (item.kind === 'unbound' || item.binding === undefined) {\n const snapshot: UnboundInterrupt = {\n ...base,\n kind: 'unbound',\n canResolve: false,\n }\n return Object.freeze(snapshot)\n }\n if (\n item.kind === 'tool-approval' &&\n item.binding.kind === 'tool-approval'\n ) {\n const binding = cloneAndDeepFreezeJson(item.binding)\n const snapshot = {\n ...base,\n kind: 'tool-approval' as const,\n binding,\n toolName: item.binding.toolName,\n toolCallId: item.binding.toolCallId,\n originalArgs: cloneAndDeepFreezeJson(item.binding.originalArgs),\n cancel: () => this.cancelItem(item.descriptor.id, transaction),\n clearResolution: () =>\n this.clearItem(item.descriptor.id, transaction),\n resolveInterrupt: (approved: boolean, options?: unknown) => {\n const details = isUnknownObject(options) ? options : undefined\n this.resolveItem(\n item.descriptor.id,\n {\n approved,\n ...(approved && details?.['editedArgs'] !== undefined\n ? { editedArgs: details['editedArgs'] }\n : {}),\n ...(details?.['payload'] !== undefined\n ? { payload: details['payload'] }\n : {}),\n },\n transaction,\n )\n },\n }\n return Object.freeze(snapshot)\n }\n const boundGeneric =\n item.binding.kind === 'generic'\n ? cloneAndDeepFreezeJson(item.binding)\n : cloneAndDeepFreezeJson({\n v: INTERRUPT_BINDING_VERSION,\n kind: 'generic' as const,\n interruptId: item.descriptor.id,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n ...(typeof item.binding.responseSchemaHash === 'string'\n ? { responseSchemaHash: item.binding.responseSchemaHash }\n : {}),\n })\n if (item.definition !== undefined && item.binding.kind === 'generic') {\n const snapshot = {\n ...base,\n kind: 'generic',\n definitionId: item.definition.id,\n key: item.binding.key ?? '',\n payload: item.payload,\n binding: boundGeneric,\n cancel: () => this.cancelItem(item.descriptor.id, transaction),\n clearResolution: () =>\n this.clearItem(item.descriptor.id, transaction),\n resolveInterrupt: (response: unknown) =>\n this.resolveItem(item.descriptor.id, response, transaction),\n }\n return Object.freeze(snapshot)\n }\n const snapshot: GenericAGUIInterrupt = {\n ...base,\n kind: 'generic',\n binding: boundGeneric,\n cancel: () => this.cancelItem(item.descriptor.id, transaction),\n clearResolution: () =>\n this.clearItem(item.descriptor.id, transaction),\n resolveInterrupt: (payload) =>\n this.resolveItem(item.descriptor.id, payload, transaction),\n }\n return Object.freeze(snapshot)\n })\n\n // The runtime items are created only from the exact configured TTools entry\n // selected by name. TypeScript cannot preserve that per-element lookup\n // through Array.map, so this generic return boundary restores the proven\n // distributive public union.\n return Object.freeze(next) as BoundInterrupts<TTools, TInterrupts>\n }\n\n // Provenance belongs to each publication because `onChange` may synchronously\n // mutate the manager and publish again before an outer callback returns.\n private publish(source: InterruptManagerChangeSource = 'live'): void {\n if (!this.hydration) {\n this.snapshot = Object.freeze([])\n this.state = Object.freeze({\n interrupts: this.snapshot,\n pendingInterrupts: this.snapshot,\n interruptErrors: this.rootErrors,\n resuming: this.resuming,\n })\n this.options.onChange?.(source)\n return\n }\n this.snapshot = this.buildSnapshot()\n this.state = Object.freeze({\n interrupts: this.snapshot,\n pendingInterrupts: this.snapshot,\n interruptErrors: this.rootErrors,\n resuming: this.resuming,\n })\n this.options.onChange?.(source)\n }\n\n private resolveItem(\n interruptId: string,\n payload: unknown,\n transaction?: TransactionToken,\n ): void {\n this.assertItemMutable(transaction)\n const item = this.findItem(interruptId)\n this.invalidateRetry()\n if (!item.canResolve) {\n item.status = 'error'\n item.error = this.itemError(\n interruptId,\n 'invalid-response-schema',\n 'The interrupt response schema is invalid and cannot be resolved.',\n )\n if (!transaction) this.publish()\n return\n }\n const validationGeneration = ++item.validationGeneration\n const validation = this.validateCandidate(item, payload)\n if (isPromiseLike(validation)) {\n item.status = 'validating'\n item.error = undefined\n if (!transaction) this.publish()\n void Promise.resolve(validation)\n .then((result) => {\n if (validationGeneration !== item.validationGeneration) return\n this.applyValidation(item, result, transaction)\n })\n .catch((error: unknown) => {\n if (validationGeneration !== item.validationGeneration) return\n this.applyValidation(\n item,\n {\n code: this.validationCode(item),\n message: error instanceof Error ? error.message : String(error),\n },\n transaction,\n )\n })\n return\n }\n this.applyValidation(item, validation, transaction)\n }\n\n private cancelItem(\n interruptId: string,\n transaction?: TransactionToken,\n ): void {\n this.assertItemMutable(transaction)\n const item = this.findItem(interruptId)\n this.invalidateRetry()\n item.validationGeneration++\n item.resolution = Object.freeze(\n resolutionWithContinuation(item, { interruptId, status: 'cancelled' }),\n )\n item.status = 'staged'\n item.error = undefined\n if (!transaction) {\n this.publish()\n this.maybeSubmit()\n }\n }\n\n private clearItem(interruptId: string, transaction?: TransactionToken): void {\n this.assertItemMutable(transaction)\n const item = this.findItem(interruptId)\n this.invalidateRetry()\n item.validationGeneration++\n item.resolution = undefined\n item.error = undefined\n item.status = 'pending'\n if (!transaction) this.publish()\n }\n\n private maybeSubmit(): void {\n // Unbound items can never be resolved through this path — something else\n // owns them. Including them in the completeness gate would deadlock the\n // batch, so the run's own interrupts could never be answered once a\n // foreign one shared the stream.\n const hasGeneric = this.items.some((item) => item.kind === 'generic')\n const ours = this.items.filter(\n (item) =>\n isClientOwnedInterrupt(item) &&\n !(hasGeneric && item.kind === 'client-tool-execution'),\n )\n if (\n ours.length === 0 ||\n ours.some(\n (item) => item.resolution === undefined || item.status !== 'staged',\n )\n ) {\n return\n }\n const hydration = this.requireHydration()\n const canonical = canonicalizeInterruptResolutions(\n ours.map((item) => item.resolution).filter((item) => item !== undefined),\n )\n const submission = Object.freeze({\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n resolutions: canonical.resolutions,\n canonicalResolutions: canonical.canonicalResolutions,\n fingerprint: canonical.fingerprint,\n })\n this.submitBatch(submission)\n }\n\n private applyValidation(\n item: RuntimeInterrupt,\n result: ValidationResult,\n transaction?: TransactionToken,\n ): void {\n if (!('valid' in result)) {\n item.status = 'error'\n const itemError = this.itemError(\n item.descriptor.id,\n result.code,\n result.message,\n result.path,\n )\n item.error = itemError\n // Client-tool-execution items are hidden from the public interrupt list,\n // so promote their validation failures onto interruptErrors for the UI.\n if (item.kind === 'client-tool-execution') {\n this.rootErrors = Object.freeze([\n ...this.rootErrors.filter(\n (error) =>\n !(\n error.code === 'item-validation-failed' &&\n error.interruptIds.includes(item.descriptor.id)\n ),\n ),\n Object.freeze({\n scope: 'batch' as const,\n code: 'item-validation-failed' as const,\n message: itemError.message,\n source: 'client' as const,\n retryable: false,\n interruptIds: Object.freeze([item.descriptor.id]),\n threadId: itemError.threadId,\n interruptedRunId: itemError.interruptedRunId,\n generation: itemError.generation,\n }),\n ])\n }\n if (!transaction) this.publish()\n return\n }\n item.resolution = cloneAndDeepFreezeJson(\n resolutionWithContinuation(item, {\n interruptId: item.descriptor.id,\n status: 'resolved',\n payload: result.payload,\n }),\n )\n item.status = 'staged'\n item.error = undefined\n if (!transaction) {\n this.publish()\n this.maybeSubmit()\n }\n }\n\n private validateCandidate(\n item: RuntimeInterrupt,\n payload: unknown,\n ): ValidationResult | Promise<ValidationResult> {\n if (item.kind === 'generic') {\n const validation = validateWithSchema(\n item.definition?.responseSchema ?? item.descriptor.responseSchema,\n payload,\n 'invalid-payload',\n )\n if (item.definition === undefined) return validation\n const preserveInput = (result: ValidationResult): ValidationResult =>\n 'valid' in result ? { valid: true, payload } : result\n return isPromiseLike(validation)\n ? Promise.resolve(validation).then(preserveInput)\n : preserveInput(validation)\n }\n if (item.kind === 'client-tool-execution') {\n return validateWithSchema(\n item.tool?.outputSchema,\n payload,\n 'invalid-tool-output',\n )\n }\n return this.validateApprovalCandidate(item, payload)\n }\n\n private validateApprovalCandidate(\n item: RuntimeInterrupt,\n payload: unknown,\n ): ValidationResult | Promise<ValidationResult> {\n if (!isUnknownObject(payload) || typeof payload['approved'] !== 'boolean') {\n return {\n code: 'invalid-payload',\n message: 'Tool approval resolutions require an approved boolean.',\n }\n }\n const approved = payload['approved']\n const editedArgs = payload['editedArgs']\n if (!approved && editedArgs !== undefined) {\n return {\n code: 'invalid-edited-args',\n message: 'Rejected tool approvals cannot edit tool arguments.',\n }\n }\n if (approved && editedArgs !== undefined) {\n const editedValidation = validateWithSchema(\n item.tool?.inputSchema,\n editedArgs,\n 'invalid-edited-args',\n )\n if (isPromiseLike(editedValidation)) {\n return Promise.resolve(editedValidation).then((result) =>\n 'valid' in result\n ? this.validateApprovalPayload(item, payload, result.payload)\n : result,\n )\n }\n if (!('valid' in editedValidation)) return editedValidation\n return this.validateApprovalPayload(\n item,\n payload,\n editedValidation.payload,\n )\n }\n return this.validateApprovalPayload(item, payload, undefined)\n }\n\n private validateApprovalPayload(\n item: RuntimeInterrupt,\n envelope: UnknownObject,\n validatedEditedArgs: unknown,\n ): ValidationResult | Promise<ValidationResult> {\n const approved = envelope['approved'] === true\n const schema = this.approvalBranchSchema(item.tool, approved)\n const branchPayload = envelope['payload']\n if (schema === undefined && branchPayload !== undefined) {\n return {\n code: 'invalid-payload',\n message: 'This approval branch does not accept a payload.',\n }\n }\n if (schema !== undefined && branchPayload === undefined) {\n return {\n code: 'invalid-payload',\n message: 'This approval branch requires a payload.',\n }\n }\n const validation = validateWithSchema(\n schema,\n branchPayload,\n 'invalid-payload',\n )\n const buildEnvelope = (result: ValidationResult): ValidationResult => {\n if (!('valid' in result)) return result\n return {\n valid: true,\n payload: {\n approved,\n ...(validatedEditedArgs !== undefined\n ? { editedArgs: validatedEditedArgs }\n : {}),\n ...(schema !== undefined ? { payload: result.payload } : {}),\n },\n }\n }\n return isPromiseLike(validation)\n ? Promise.resolve(validation).then(buildEnvelope)\n : buildEnvelope(validation)\n }\n\n private approvalBranchSchema(\n tool: AnyClientTool | undefined,\n approved: boolean,\n ): unknown {\n const approvalSchema: unknown = tool?.approvalSchema\n if (!isUnknownObject(approvalSchema)) return approvalSchema\n const hasBranches =\n 'approve' in approvalSchema || 'reject' in approvalSchema\n if (!hasBranches) return approvalSchema\n return approved ? approvalSchema['approve'] : approvalSchema['reject']\n }\n\n private validationCode(item: RuntimeInterrupt): ItemInterruptError['code'] {\n return item.kind === 'client-tool-execution'\n ? 'invalid-tool-output'\n : 'invalid-payload'\n }\n\n private resolveBooleanBulk(approved: boolean): void {\n // `client-tool-execution` items resolve out-of-band (auto execution /\n // addToolResult); they are transparent to the boolean shorthand. Eligibility\n // and resolution consider only the publicly resolvable items.\n const resolvable = this.items.filter(\n (item) =>\n isClientOwnedInterrupt(item) && item.kind !== 'client-tool-execution',\n )\n const eligible = resolvable.every(\n (item) =>\n item.kind === 'tool-approval' &&\n this.approvalBranchSchema(item.tool, approved) === undefined,\n )\n if (!eligible || resolvable.length === 0) {\n this.addRootError(\n 'unsupported-bulk-operation',\n 'Boolean bulk resolution requires payloadless tool approvals.',\n false,\n )\n return\n }\n this.invalidateRetry()\n for (const item of resolvable) {\n item.validationGeneration++\n item.resolution = cloneAndDeepFreezeJson({\n interruptId: item.descriptor.id,\n status: 'resolved',\n payload: { approved },\n })\n item.status = 'staged'\n item.error = undefined\n }\n this.publish()\n this.maybeSubmit()\n }\n\n private resolveTransaction(\n resolver: (\n interrupt: ResolvableChatInterrupt<TTools, TInterrupts>,\n ) => unknown,\n ): void {\n const checkpoints = this.items.map<RuntimeInterruptCheckpoint>((item) => ({\n status: item.status,\n ...(item.resolution !== undefined ? { resolution: item.resolution } : {}),\n ...(item.error !== undefined ? { error: item.error } : {}),\n validationGeneration: item.validationGeneration,\n }))\n const token: TransactionToken = { active: true }\n this.activeTransaction = token\n const stable = this.buildSnapshot(token).filter(isRootResolvableInterrupt)\n let failure:\n | { code: BatchInterruptError['code']; message: string }\n | undefined\n try {\n for (const interrupt of stable) {\n const result = resolver(interrupt)\n if (result !== undefined) {\n failure = {\n code: isPromiseLike(result)\n ? 'async-resolver'\n : 'inactive-transaction',\n message: isPromiseLike(result)\n ? 'Interrupt transaction resolvers must be synchronous.'\n : 'Interrupt transaction resolvers must return literal undefined.',\n }\n break\n }\n }\n if (\n failure === undefined &&\n this.items.some(\n (item) =>\n // `client-tool-execution` items are resolved out-of-band (auto\n // execution / addToolResult), not by this synchronous resolver, so\n // they don't count against transaction completeness. `maybeSubmit`\n // still waits for them unless a generic interrupt shares the batch.\n isClientOwnedInterrupt(item) &&\n item.kind !== 'client-tool-execution' &&\n (item.resolution === undefined || item.status !== 'staged'),\n )\n ) {\n failure = {\n code: 'incomplete-batch',\n message: 'Interrupt transaction did not resolve every item.',\n }\n }\n } catch (error) {\n failure = {\n code: 'item-validation-failed',\n message: error instanceof Error ? error.message : String(error),\n }\n } finally {\n token.active = false\n this.activeTransaction = undefined\n }\n\n if (failure) {\n this.restoreCheckpoints(checkpoints)\n this.addRootError(failure.code, failure.message, false)\n return\n }\n this.publish()\n this.maybeSubmit()\n }\n\n private restoreCheckpoints(\n checkpoints: ReadonlyArray<RuntimeInterruptCheckpoint>,\n ): void {\n this.items.forEach((item, index) => {\n const checkpoint = checkpoints[index]\n if (!checkpoint) return\n item.status = checkpoint.status\n item.resolution = checkpoint.resolution\n item.error = checkpoint.error\n item.validationGeneration = checkpoint.validationGeneration + 1\n })\n this.publish()\n }\n\n private assertItemMutable(transaction?: TransactionToken): void {\n if (transaction && !transaction.active) {\n throw new Error('Interrupt transaction is inactive.')\n }\n if (this.activeTransaction && transaction !== this.activeTransaction) {\n throw new Error('Interrupt transaction is inactive.')\n }\n if (this.resuming) {\n throw new Error('Interrupts cannot be mutated while submitting.')\n }\n }\n\n private assertRootMutable(): void {\n if (this.activeTransaction) {\n throw new Error('Interrupt transaction is already active.')\n }\n if (this.resuming) {\n throw new Error('Interrupts cannot be mutated while submitting.')\n }\n }\n\n private invalidateRetry(): void {\n this.retrySubmission = undefined\n }\n\n private submitBatch(submission: InterruptManagerSubmission): void {\n this.resuming = true\n this.retrySubmission = undefined\n for (const item of this.items) {\n if (isClientOwnedInterrupt(item)) item.status = 'submitting'\n }\n this.publish()\n void this.performSubmission(submission)\n }\n\n private async performSubmission(\n submission: InterruptManagerSubmission,\n ): Promise<void> {\n try {\n await this.options.submit(submission)\n } catch (error) {\n this.handleSubmissionFailure(error, submission)\n } finally {\n this.resuming = false\n this.publish()\n }\n }\n\n private handleSubmissionFailure(\n error: unknown,\n submission: InterruptManagerSubmission,\n ): void {\n const errors = readSubmissionErrors(error)\n if (errors.length === 0) {\n const message = error instanceof Error ? error.message : String(error)\n this.addRootError('transport', message, true, 'transport')\n this.retrySubmission = submission\n for (const item of this.items) {\n if (isClientOwnedInterrupt(item)) item.status = 'error'\n }\n return\n }\n\n const correlatedErrors = errors.filter((submissionError) =>\n submissionErrorMatchesActiveBatch(submissionError, submission),\n )\n if (correlatedErrors.length !== errors.length) {\n this.addRootError(\n 'protocol',\n 'Interrupt submission errors did not match the active batch.',\n false,\n )\n }\n\n let nonRetryable = false\n let retryable = false\n const batchErrors: Array<BatchInterruptError> = []\n for (const submissionError of correlatedErrors) {\n if (\n submissionError.code === 'stale' ||\n submissionError.code === 'expired' ||\n submissionError.code === 'conflict'\n ) {\n nonRetryable = true\n }\n retryable ||= submissionError.retryable\n if (submissionError.scope === 'item') {\n const item = this.items.find(\n (candidate) =>\n isClientOwnedInterrupt(candidate) &&\n candidate.descriptor.id === submissionError.interruptId,\n )\n if (item) {\n item.status = 'error'\n item.error = cloneAndDeepFreezeJson(submissionError)\n }\n } else {\n batchErrors.push(cloneAndDeepFreezeJson(submissionError))\n }\n }\n const mergedBatchErrors = mergeSubmissionBatchErrors(\n this.rootErrors,\n this.submissionRootErrors,\n batchErrors,\n )\n this.rootErrors = mergedBatchErrors.rootErrors\n this.submissionRootErrors = mergedBatchErrors.submissionRootErrors\n for (const item of this.items) {\n if (isClientOwnedInterrupt(item) && item.status === 'submitting') {\n item.status = 'error'\n }\n }\n this.retrySubmission = retryable && !nonRetryable ? submission : undefined\n }\n\n private addRootError(\n code: BatchInterruptError['code'],\n message: string,\n retryable: boolean,\n source: BatchInterruptError['source'] = 'client',\n ): void {\n const hydration = this.requireHydration()\n this.rootErrors = Object.freeze([\n ...this.rootErrors,\n Object.freeze({\n scope: 'batch' as const,\n code,\n message,\n source,\n retryable,\n interruptIds: Object.freeze(\n this.items\n .filter(isClientOwnedInterrupt)\n .map((item) => item.descriptor.id),\n ),\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n }),\n ])\n this.publish()\n }\n\n private findItem(interruptId: string): RuntimeInterrupt {\n const item = this.items.find(\n (candidate) => candidate.descriptor.id === interruptId,\n )\n if (!item) throw new Error(`Unknown interrupt: ${interruptId}`)\n return item\n }\n\n private requireHydration(): InterruptManagerHydration {\n if (!this.hydration) throw new Error('InterruptManager is not hydrated.')\n return this.hydration\n }\n\n private itemError(\n interruptId: string,\n code: ItemInterruptError['code'],\n message: string,\n path?: ReadonlyArray<string | number>,\n ): ItemInterruptError {\n const hydration = this.requireHydration()\n return Object.freeze({\n scope: 'item',\n interruptId,\n code,\n message,\n ...(path !== undefined ? { path: Object.freeze([...path]) } : {}),\n source: 'client',\n retryable: false,\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n })\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"interrupt-manager.js","names":[],"sources":["../../src/interrupt-manager.ts"],"sourcesContent":["import {\n INTERRUPT_BINDING_METADATA_KEY,\n INTERRUPT_BINDING_VERSION,\n canonicalInterruptJson,\n canonicalizeInterruptResolutions,\n cloneAndDeepFreezeJson,\n digestInterruptJson,\n genericInterruptContinuationFromDescriptor,\n hashInterruptDefinitionSchema,\n hashSchemaInput,\n isStandardSchema,\n normalizeApprovalSchema,\n readInterruptBinding,\n wrapGenericInterruptContinuation,\n} from '@tanstack/ai/client'\nimport type {\n AnyClientTool,\n BatchInterruptError,\n Interrupt,\n InterruptBinding,\n InterruptDefinition,\n InterruptSubmissionError,\n ItemInterruptError,\n RunAgentResumeItem,\n} from '@tanstack/ai/client'\nimport type {\n BoundInterruptBase,\n BoundInterrupts,\n ChatInterrupt,\n ChatInterruptState,\n GenericAGUIInterrupt,\n InterruptItemStatus,\n ResolvableChatInterrupt,\n UnboundInterrupt,\n} from './types'\n\nexport interface InterruptManagerHydration {\n threadId: string\n interruptedRunId: string\n generation: number\n interrupts: ReadonlyArray<Interrupt>\n}\n\nexport interface InterruptManagerSubmission {\n threadId: string\n interruptedRunId: string\n generation: number\n resolutions: ReadonlyArray<RunAgentResumeItem>\n canonicalResolutions: string\n fingerprint: string\n}\n\nexport type InterruptManagerChangeSource = 'hydrate' | 'live'\n\nexport interface InterruptManagerOptions<\n TTools extends ReadonlyArray<AnyClientTool>,\n TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>> =\n readonly [],\n> {\n tools?: TTools\n interrupts?: TInterrupts\n submit: (submission: InterruptManagerSubmission) => Promise<void>\n onChange?: (source: InterruptManagerChangeSource) => void\n}\n\ntype UnknownObject = { [key: string]: unknown }\n\ntype RuntimeKind =\n | 'generic'\n | 'tool-approval'\n | 'client-tool-execution'\n /** Carries no binding we understand — not ours to resume. */\n | 'unbound'\n\ninterface RuntimeInterrupt {\n descriptor: Interrupt\n /** `undefined` only for `unbound` items. */\n binding: InterruptBinding | undefined\n kind: RuntimeKind\n status: InterruptItemStatus\n canResolve: boolean\n error?: ItemInterruptError\n resolution?: RunAgentResumeItem\n tool?: AnyClientTool\n definition?: InterruptDefinition<any, any, any, any>\n /** Validated display payload for a registered first-party generic item. */\n payload?: unknown\n /** This binding is valid and can participate in this chat resume batch. */\n resumable: boolean\n validationGeneration: number\n}\n\ninterface ValidationFailure {\n code: ItemInterruptError['code']\n message: string\n path?: ReadonlyArray<string | number>\n}\n\ntype ValidationResult = { valid: true; payload: unknown } | ValidationFailure\n\ninterface TransactionToken {\n active: boolean\n}\n\ninterface SubmissionOperation {\n submission: InterruptManagerSubmission\n}\n\ninterface RuntimeInterruptCheckpoint {\n status: InterruptItemStatus\n resolution?: RunAgentResumeItem\n error?: ItemInterruptError\n validationGeneration: number\n}\n\nfunction isClientOwnedInterrupt(item: RuntimeInterrupt): boolean {\n return item.resumable\n}\n\nfunction resolutionWithContinuation(\n item: RuntimeInterrupt,\n resolution: RunAgentResumeItem,\n): RunAgentResumeItem {\n const continuation = genericInterruptContinuationFromDescriptor(\n item.descriptor,\n )\n if (!continuation) return resolution\n return {\n ...resolution,\n metadata: wrapGenericInterruptContinuation(continuation),\n }\n}\n\nfunction isRootResolvableInterrupt<\n TTools extends ReadonlyArray<AnyClientTool>,\n TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>>,\n>(\n interrupt: ChatInterrupt<TTools, TInterrupts>,\n): interrupt is ResolvableChatInterrupt<TTools, TInterrupts> {\n return 'cancel' in interrupt && 'clearResolution' in interrupt\n}\n\nconst itemErrorCodes = new Set<ItemInterruptError['code']>([\n 'invalid-payload',\n 'invalid-edited-args',\n 'invalid-tool-output',\n 'invalid-response-schema',\n 'unknown-interrupt',\n 'expired',\n 'stale',\n 'conflict',\n 'legacy-unsupported',\n])\n\nconst batchErrorCodes = new Set<BatchInterruptError['code']>([\n 'incomplete-batch',\n 'item-validation-failed',\n 'unsupported-bulk-operation',\n 'async-resolver',\n 'inactive-transaction',\n 'mixed-provenance',\n 'transport',\n 'server',\n 'protocol',\n 'invalid-response-schema',\n 'expired',\n 'stale',\n 'conflict',\n 'legacy-submit-failed',\n])\n\nfunction isUnknownObject(value: unknown): value is UnknownObject {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction isLegacyApprovalMetadata(value: unknown): boolean {\n return (\n isUnknownObject(value) &&\n value['kind'] === 'approval' &&\n typeof value['toolName'] === 'string' &&\n 'input' in value\n )\n}\n\nfunction isLegacyClientToolMetadata(value: unknown): boolean {\n return (\n isUnknownObject(value) &&\n value['kind'] === 'client_tool' &&\n typeof value['toolName'] === 'string' &&\n 'input' in value\n )\n}\n\n/**\n * Does this descriptor carry the pre-binding TanStack metadata marker?\n *\n * Descriptors emitted before the resume binding existed are still ours to\n * resume, so they must not be mistaken for another producer's interrupt.\n */\nfunction isLegacyInterruptMetadata(interrupt: Interrupt): boolean {\n return (\n isLegacyApprovalMetadata(interrupt.metadata) ||\n isLegacyClientToolMetadata(interrupt.metadata)\n )\n}\n\nfunction getDescriptorBinding(\n interrupt: Interrupt,\n): InterruptBinding | undefined {\n return readInterruptBinding(interrupt)\n}\n\nfunction hasReservedFirstPartyBindingMarker(interrupt: Interrupt): boolean {\n if (!isUnknownObject(interrupt.metadata)) return false\n const binding = interrupt.metadata[INTERRUPT_BINDING_METADATA_KEY]\n if (!isUnknownObject(binding)) return false\n if (\n binding['v'] !== undefined &&\n binding['v'] !== INTERRUPT_BINDING_VERSION\n ) {\n return false\n }\n return (\n binding['kind'] === 'generic' ||\n binding['kind'] === 'tool-approval' ||\n binding['kind'] === 'client-tool-execution' ||\n 'definitionId' in binding ||\n 'key' in binding ||\n 'batchIndex' in binding ||\n 'payloadSchemaHash' in binding\n )\n}\n\nfunction hasFirstPartyGenericMarker(interrupt: Interrupt): boolean {\n if (!isUnknownObject(interrupt.metadata)) return false\n const binding = interrupt.metadata[INTERRUPT_BINDING_METADATA_KEY]\n if (!isUnknownObject(binding) || binding['kind'] !== 'generic') return false\n return (\n 'definitionId' in binding ||\n 'key' in binding ||\n 'batchIndex' in binding ||\n 'payloadSchemaHash' in binding\n )\n}\n\nfunction getInterruptPayload(interrupt: Interrupt): unknown {\n return interrupt.metadata?.['tanstack:interruptPayload']\n}\n\n/**\n * Only used to route *legacy* (pre-binding) descriptors, which have no binding\n * to classify off. Current descriptors are classified by their binding alone.\n */\nfunction isClientToolExecutionReason(reason: string): boolean {\n return (\n reason === 'tanstack:client_tool_execution' ||\n reason === 'client_tool_input'\n )\n}\n\nfunction responseSchemaHash(interrupt: Interrupt): string | undefined {\n if (interrupt.responseSchema === undefined) return undefined\n try {\n return digestInterruptJson(canonicalInterruptJson(interrupt.responseSchema))\n } catch {\n return undefined\n }\n}\n\nfunction definitionSchemaHash(\n schema: InterruptDefinition<any, any, any, any>['responseSchema'] | undefined,\n): string | undefined {\n if (schema === undefined) return undefined\n try {\n return hashInterruptDefinitionSchema(schema)\n } catch {\n return undefined\n }\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n value !== null &&\n (typeof value === 'object' || typeof value === 'function') &&\n 'then' in value &&\n typeof value.then === 'function'\n )\n}\n\nfunction validateWithSchema(\n schema: unknown,\n value: unknown,\n code: ItemInterruptError['code'],\n): ValidationResult | Promise<ValidationResult> {\n if (schema === undefined) return { valid: true, payload: value }\n if (isStandardSchema(schema)) {\n const result = schema['~standard'].validate(value)\n const normalize = (\n validation: Awaited<typeof result>,\n ): ValidationResult => {\n if (!validation.issues) {\n return { valid: true, payload: validation.value }\n }\n return {\n code,\n message: validation.issues[0]?.message ?? 'Schema validation failed.',\n }\n }\n return isPromiseLike(result)\n ? Promise.resolve(result).then(normalize)\n : normalize(result)\n }\n // A non-Standard-Schema value (a raw JSON Schema arriving over the wire) is\n // not validated by the library. The application transforms the schema and\n // validates the value itself before resolving; whatever it passes flows\n // through as-is.\n return { valid: true, payload: value }\n}\n\nfunction isItemErrorCode(value: string): value is ItemInterruptError['code'] {\n for (const code of itemErrorCodes) if (code === value) return true\n return false\n}\n\nfunction isBatchErrorCode(value: string): value is BatchInterruptError['code'] {\n for (const code of batchErrorCodes) if (code === value) return true\n return false\n}\n\nfunction isSubmissionError(value: unknown): value is InterruptSubmissionError {\n if (!isUnknownObject(value)) return false\n const scope = value['scope']\n const code = value['code']\n const base =\n typeof code === 'string' &&\n typeof value['message'] === 'string' &&\n typeof value['retryable'] === 'boolean' &&\n typeof value['threadId'] === 'string' &&\n typeof value['interruptedRunId'] === 'string' &&\n typeof value['generation'] === 'number'\n if (!base) return false\n if (scope === 'item') {\n return (\n isItemErrorCode(code) &&\n typeof value['interruptId'] === 'string' &&\n (value['source'] === 'client' || value['source'] === 'server')\n )\n }\n return (\n scope === 'batch' &&\n isBatchErrorCode(code) &&\n Array.isArray(value['interruptIds']) &&\n value['interruptIds'].every((id) => typeof id === 'string') &&\n (value['source'] === 'client' ||\n value['source'] === 'server' ||\n value['source'] === 'transport')\n )\n}\n\nfunction readSubmissionErrors(\n error: unknown,\n): ReadonlyArray<InterruptSubmissionError> {\n if (isSubmissionError(error)) return [error]\n if (!isUnknownObject(error) || !Array.isArray(error['errors'])) return []\n return error['errors'].every(isSubmissionError) ? error['errors'] : []\n}\n\nfunction haveSameInterruptIds(\n left: ReadonlyArray<string>,\n right: ReadonlyArray<string>,\n): boolean {\n if (left.length !== right.length) return false\n const sortedLeft = [...left].sort()\n const sortedRight = [...right].sort()\n return sortedLeft.every((id, index) => id === sortedRight[index])\n}\n\nfunction haveSameBatchCorrelation(\n left: BatchInterruptError,\n right: BatchInterruptError,\n): boolean {\n return (\n left.threadId === right.threadId &&\n left.interruptedRunId === right.interruptedRunId &&\n left.generation === right.generation &&\n haveSameInterruptIds(left.interruptIds, right.interruptIds)\n )\n}\n\nfunction mergeSubmissionBatchErrors(\n current: ReadonlyArray<BatchInterruptError>,\n previousSubmission: ReadonlyArray<BatchInterruptError>,\n incoming: ReadonlyArray<BatchInterruptError>,\n): {\n rootErrors: ReadonlyArray<BatchInterruptError>\n submissionRootErrors: ReadonlyArray<BatchInterruptError>\n} {\n const replaceableIncoming = incoming.filter(\n (error) => error.source !== 'transport',\n )\n const isSuperseded = (candidate: BatchInterruptError): boolean =>\n previousSubmission.includes(candidate) &&\n replaceableIncoming.some((error) =>\n haveSameBatchCorrelation(candidate, error),\n )\n const retainedRootErrors = current.filter(\n (candidate) => !isSuperseded(candidate),\n )\n const retainedSubmissionRootErrors = previousSubmission.filter(\n (candidate) =>\n !replaceableIncoming.some((error) =>\n haveSameBatchCorrelation(candidate, error),\n ),\n )\n return Object.freeze({\n rootErrors: Object.freeze([...retainedRootErrors, ...incoming]),\n submissionRootErrors: Object.freeze([\n ...retainedSubmissionRootErrors,\n ...replaceableIncoming,\n ]),\n })\n}\n\nfunction submissionErrorMatchesActiveBatch(\n error: InterruptSubmissionError,\n submission: InterruptManagerSubmission,\n): boolean {\n if (\n error.threadId !== submission.threadId ||\n error.interruptedRunId !== submission.interruptedRunId ||\n error.generation !== submission.generation\n ) {\n return false\n }\n const interruptIds = submission.resolutions.map(\n (resolution) => resolution.interruptId,\n )\n return error.scope === 'item'\n ? interruptIds.includes(error.interruptId)\n : haveSameInterruptIds(error.interruptIds, interruptIds)\n}\n\nfunction genericBinding(\n interrupt: Interrupt,\n hydration: InterruptManagerHydration,\n candidate: InterruptBinding | undefined,\n): InterruptBinding {\n const schemaHash =\n responseSchemaHash(interrupt) ?? candidate?.responseSchemaHash\n return cloneAndDeepFreezeJson({\n v: INTERRUPT_BINDING_VERSION,\n kind: 'generic',\n interruptId: interrupt.id,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n ...(schemaHash !== undefined ? { responseSchemaHash: schemaHash } : {}),\n ...(interrupt.expiresAt !== undefined\n ? { expiresAt: interrupt.expiresAt }\n : {}),\n })\n}\n\nfunction baseSnapshot(\n item: RuntimeInterrupt,\n hydration: InterruptManagerHydration,\n): Omit<BoundInterruptBase, 'cancel' | 'clearResolution'> {\n const descriptor = cloneAndDeepFreezeJson(item.descriptor)\n const errors: ReadonlyArray<ItemInterruptError> =\n item.error === undefined\n ? Object.freeze([])\n : Object.freeze([cloneAndDeepFreezeJson(item.error)])\n const error = errors[0]\n return {\n id: descriptor.id,\n interruptId: descriptor.id,\n reason: descriptor.reason,\n ...(descriptor.message !== undefined\n ? { message: descriptor.message }\n : {}),\n ...(descriptor.responseSchema !== undefined\n ? { responseSchema: descriptor.responseSchema }\n : {}),\n ...(descriptor.expiresAt !== undefined\n ? { expiresAt: descriptor.expiresAt }\n : {}),\n ...(descriptor.metadata !== undefined\n ? { metadata: descriptor.metadata }\n : {}),\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n status: item.status,\n errors,\n ...(error !== undefined ? { error } : {}),\n canResolve: item.canResolve,\n }\n}\n\nexport class InterruptManager<\n TTools extends ReadonlyArray<AnyClientTool> = ReadonlyArray<AnyClientTool>,\n TInterrupts extends ReadonlyArray<InterruptDefinition<any, any, any, any>> =\n readonly [],\n> {\n private hydration: InterruptManagerHydration | undefined\n private items: Array<RuntimeInterrupt> = []\n private snapshot: ReadonlyArray<ChatInterrupt<TTools, TInterrupts>> =\n Object.freeze([])\n private rootErrors: ReadonlyArray<BatchInterruptError> = Object.freeze([])\n private submissionRootErrors: ReadonlyArray<BatchInterruptError> =\n Object.freeze([])\n private state: ChatInterruptState<TTools, TInterrupts> = Object.freeze({\n interrupts: this.snapshot,\n pendingInterrupts: this.snapshot,\n interruptErrors: this.rootErrors,\n resuming: false,\n })\n private activeTransaction: TransactionToken | undefined\n private activeSubmissionOperation: SubmissionOperation | undefined\n private retrySubmission: InterruptManagerSubmission | undefined\n private resuming = false\n private tools: TTools | undefined\n private readonly interruptDefinitions: ReadonlyMap<\n string,\n InterruptDefinition<any, any, any, any>\n >\n\n constructor(\n private readonly options: InterruptManagerOptions<TTools, TInterrupts>,\n ) {\n this.tools = options.tools\n const definitions = new Map<\n string,\n InterruptDefinition<any, any, any, any>\n >()\n for (const definition of options.interrupts ?? []) {\n if (definitions.has(definition.id)) {\n throw new Error(`Duplicate interrupt definition id: ${definition.id}`)\n }\n definitions.set(definition.id, definition)\n }\n this.interruptDefinitions = definitions\n }\n\n updateTools(tools: TTools): void {\n this.tools = tools\n }\n\n hydrate(\n hydration: InterruptManagerHydration,\n source: InterruptManagerChangeSource = 'live',\n ): void {\n this.activeSubmissionOperation = undefined\n this.hydration = {\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n interrupts: cloneAndDeepFreezeJson(hydration.interrupts),\n }\n const firstPartyIndexes = new Map<number, number>()\n for (const interrupt of hydration.interrupts) {\n const binding = getDescriptorBinding(interrupt)\n if (\n binding?.kind === 'generic' &&\n binding.definitionId !== undefined &&\n binding.key !== undefined &&\n binding.batchIndex !== undefined\n ) {\n firstPartyIndexes.set(\n binding.batchIndex,\n (firstPartyIndexes.get(binding.batchIndex) ?? 0) + 1,\n )\n }\n }\n this.items = hydration.interrupts.map((interrupt) =>\n this.hydrateInterrupt(interrupt, hydration, firstPartyIndexes),\n )\n this.rootErrors = Object.freeze([])\n this.submissionRootErrors = Object.freeze([])\n this.retrySubmission = undefined\n this.resuming = false\n this.publish(source)\n }\n\n getInterrupts(): BoundInterrupts<TTools, TInterrupts> {\n return this.snapshot\n }\n\n getState(): ChatInterruptState<TTools, TInterrupts> {\n return this.state\n }\n\n getDescriptors(): ReadonlyArray<Interrupt> {\n return this.hydration?.interrupts ?? Object.freeze([])\n }\n\n hasValidatedFirstPartyGenericBatch(): boolean {\n return this.items.some(\n (item) => item.kind === 'generic' && item.definition !== undefined,\n )\n }\n\n reset(options?: {\n preserveRootErrors?: boolean\n source?: InterruptManagerChangeSource\n }): void {\n this.activeSubmissionOperation = undefined\n this.hydration = undefined\n this.items = []\n this.snapshot = Object.freeze([])\n if (options?.preserveRootErrors !== true) {\n this.rootErrors = Object.freeze([])\n this.submissionRootErrors = Object.freeze([])\n }\n this.retrySubmission = undefined\n this.resuming = false\n this.state = Object.freeze({\n interrupts: this.snapshot,\n pendingInterrupts: this.snapshot,\n interruptErrors: this.rootErrors,\n resuming: false,\n })\n this.options.onChange?.(options?.source ?? 'live')\n }\n\n getInterruptErrors(): ReadonlyArray<BatchInterruptError> {\n return this.rootErrors\n }\n\n getResuming(): boolean {\n return this.resuming\n }\n\n resolve(approved: boolean): void\n resolve(\n resolver: (\n interrupt: ResolvableChatInterrupt<TTools, TInterrupts>,\n ) => undefined,\n ): void\n resolve(\n resolution:\n | boolean\n | ((interrupt: ResolvableChatInterrupt<TTools, TInterrupts>) => unknown),\n ): void {\n this.assertRootMutable()\n if (typeof resolution === 'boolean') {\n this.resolveBooleanBulk(resolution)\n return\n }\n this.resolveTransaction(resolution)\n }\n\n cancel(): void {\n this.assertRootMutable()\n this.invalidateRetry()\n for (const item of this.items) {\n if (!isClientOwnedInterrupt(item)) continue\n item.validationGeneration++\n item.resolution = Object.freeze(\n resolutionWithContinuation(item, {\n interruptId: item.descriptor.id,\n status: 'cancelled',\n }),\n )\n item.status = 'staged'\n item.error = undefined\n }\n this.publish()\n this.maybeSubmit()\n }\n\n retry(): void {\n if (this.resuming)\n throw new Error('Interrupt submission is already active.')\n const submission = this.retrySubmission\n if (!submission) {\n this.addRootError(\n 'transport',\n 'There is no retryable interrupt submission.',\n false,\n )\n return\n }\n this.submitBatch(submission)\n }\n\n resolveClientToolOutput(toolCallId: string, output: unknown): boolean {\n const item = this.items.find(\n (candidate) =>\n (candidate.kind === 'client-tool-execution' &&\n candidate.binding?.kind === 'client-tool-execution' &&\n candidate.binding.toolCallId === toolCallId) ||\n (candidate.kind === 'generic' &&\n isClientToolExecutionReason(candidate.descriptor.reason) &&\n candidate.descriptor.toolCallId === toolCallId &&\n isLegacyClientToolMetadata(candidate.descriptor.metadata)),\n )\n if (!item) return false\n this.resolveItem(item.descriptor.id, output)\n return true\n }\n\n resolveToolApprovalDecision(interruptId: string, approved: boolean): boolean {\n const item = this.items.find(\n (candidate) =>\n candidate.descriptor.id === interruptId &&\n (candidate.kind === 'tool-approval' ||\n (candidate.kind === 'generic' &&\n candidate.descriptor.reason === 'approval_required' &&\n isLegacyApprovalMetadata(candidate.descriptor.metadata))),\n )\n if (!item) return false\n this.resolveItem(item.descriptor.id, { approved })\n return true\n }\n\n private hydrateInterrupt(\n descriptor: Interrupt,\n hydration: InterruptManagerHydration,\n firstPartyIndexes: ReadonlyMap<number, number>,\n ): RuntimeInterrupt {\n const interrupt = cloneAndDeepFreezeJson(descriptor)\n const candidate = getDescriptorBinding(interrupt)\n const legacyResumable =\n candidate === undefined && isLegacyInterruptMetadata(interrupt)\n\n // No binding we understand, and nothing else identifying the descriptor as\n // ours, means this interrupt was not produced by this package's resume\n // path — a workflow engine's durable approval projected onto the same\n // AG-UI stream, a third-party agent's pause, or a binding written at a\n // protocol version we don't know.\n //\n // Do not invent a binding for it. Synthesising one would render a\n // resolvable form whose answer is submitted against a run that has no\n // matching pending descriptor, failing late as `unknown-interrupt` after\n // the user has already filled it in. Surface it as unresolvable instead,\n // so \"someone else owns this pause\" is visible rather than silently\n // translated into an AI-domain interrupt.\n //\n // Pre-binding TanStack descriptors are still ours: they carry the legacy\n // `metadata.kind` marker, so they keep hydrating through the generic path\n // below.\n if (candidate === undefined && !legacyResumable) {\n if (hasReservedFirstPartyBindingMarker(interrupt)) {\n return {\n descriptor: interrupt,\n binding: genericBinding(interrupt, hydration, undefined),\n kind: 'generic',\n status: 'error',\n canResolve: false,\n resumable: false,\n error: this.itemError(\n interrupt.id,\n 'stale',\n 'The interrupt binding is invalid or incomplete.',\n ),\n validationGeneration: 0,\n }\n }\n return {\n descriptor: interrupt,\n binding: undefined,\n kind: 'unbound',\n status: 'pending',\n canResolve: false,\n resumable: false,\n validationGeneration: 0,\n }\n }\n\n const correlated =\n candidate !== undefined &&\n candidate.interruptId === interrupt.id &&\n candidate.interruptedRunId === hydration.interruptedRunId &&\n candidate.generation === hydration.generation &&\n responseSchemaHash(interrupt) === candidate.responseSchemaHash\n\n const structurallyCorrelated =\n candidate !== undefined &&\n candidate.interruptId === interrupt.id &&\n candidate.interruptedRunId === hydration.interruptedRunId &&\n candidate.generation === hydration.generation &&\n candidate.responseSchemaHash ===\n (responseSchemaHash(interrupt) ?? candidate.responseSchemaHash)\n\n if (\n candidate !== undefined &&\n hasFirstPartyGenericMarker(interrupt) &&\n (!structurallyCorrelated ||\n candidate.kind !== 'generic' ||\n candidate.definitionId === undefined ||\n candidate.key === undefined ||\n candidate.batchIndex === undefined)\n ) {\n return {\n descriptor: interrupt,\n binding: genericBinding(interrupt, hydration, candidate),\n kind: 'generic',\n status: 'error',\n canResolve: false,\n resumable: false,\n error: this.itemError(\n interrupt.id,\n 'stale',\n 'The interrupt binding does not match this interrupted run.',\n ),\n validationGeneration: 0,\n }\n }\n\n if (structurallyCorrelated && candidate.kind === 'tool-approval') {\n const tool = this.tools?.find(\n (configured) => configured.name === candidate.toolName,\n )\n // Gated on the binding and the schema hashes below, not on\n // `interrupt.reason` — that string is free-form AG-UI text another\n // producer can also use, so it cannot be what decides ownership.\n if (\n tool?.needsApproval === true &&\n interrupt.toolCallId === candidate.toolCallId\n ) {\n try {\n const approval = normalizeApprovalSchema(\n tool.approvalSchema,\n tool.inputSchema,\n )\n if (\n hashSchemaInput(tool.inputSchema) === candidate.inputSchemaHash &&\n approval.approvalSchemaHash === candidate.approvalSchemaHash &&\n approval.responseSchemaHash === candidate.responseSchemaHash\n ) {\n return {\n descriptor: interrupt,\n binding: cloneAndDeepFreezeJson(candidate),\n kind: 'tool-approval',\n status: 'pending',\n canResolve: true,\n resumable: true,\n tool,\n validationGeneration: 0,\n }\n }\n } catch {\n // Invalid configured schemas cannot safely grant typed hydration.\n }\n }\n }\n\n if (structurallyCorrelated && candidate.kind === 'client-tool-execution') {\n const tool = this.tools?.find(\n (configured) => configured.name === candidate.toolName,\n )\n // Binding-gated, for the same reason as tool approvals above.\n if (\n tool !== undefined &&\n interrupt.toolCallId === candidate.toolCallId &&\n hashSchemaInput(tool.outputSchema) === candidate.outputSchemaHash\n ) {\n return {\n descriptor: interrupt,\n binding: cloneAndDeepFreezeJson(candidate),\n kind: 'client-tool-execution',\n status: 'pending',\n canResolve: true,\n resumable: true,\n tool,\n validationGeneration: 0,\n }\n }\n }\n\n if (\n candidate !== undefined &&\n candidate.kind === 'generic' &&\n candidate.definitionId !== undefined &&\n candidate.key !== undefined &&\n candidate.batchIndex !== undefined &&\n candidate.key.length > 0 &&\n firstPartyIndexes.get(candidate.batchIndex) !== 1\n ) {\n return {\n descriptor: interrupt,\n binding: cloneAndDeepFreezeJson(candidate),\n kind: 'generic',\n status: 'error',\n canResolve: false,\n resumable: false,\n error: this.itemError(\n interrupt.id,\n 'stale',\n 'Generic interrupt batch contains a duplicate batchIndex.',\n ),\n validationGeneration: 0,\n }\n }\n\n if (\n correlated &&\n candidate.kind === 'generic' &&\n candidate.definitionId !== undefined &&\n candidate.key !== undefined &&\n candidate.batchIndex !== undefined &&\n candidate.key.length > 0 &&\n firstPartyIndexes.get(candidate.batchIndex) === 1\n ) {\n const definition = this.interruptDefinitions.get(candidate.definitionId)\n if (\n definition !== undefined &&\n definitionSchemaHash(definition.responseSchema) ===\n candidate.responseSchemaHash &&\n (definition.payloadSchema === undefined\n ? candidate.payloadSchemaHash === undefined\n : candidate.payloadSchemaHash ===\n definitionSchemaHash(definition.payloadSchema))\n ) {\n const rawPayload = getInterruptPayload(interrupt)\n // First-party display payloads are parsed by definition.interrupt()\n // before the server emits them. Re-validating here would feed schema\n // output back through an input schema and reject transforms such as\n // z.string().transform(Number). The checks above still bind this value\n // to the exact descriptor, run, generation, definition, and schemas.\n return {\n descriptor: interrupt,\n binding: cloneAndDeepFreezeJson(candidate),\n definition,\n kind: 'generic',\n status: 'pending',\n canResolve: true,\n resumable: true,\n ...(rawPayload === undefined\n ? {}\n : { payload: cloneAndDeepFreezeJson(rawPayload) }),\n validationGeneration: 0,\n }\n }\n }\n\n const resumable =\n legacyResumable ||\n (candidate !== undefined &&\n candidate.interruptId === interrupt.id &&\n candidate.interruptedRunId === hydration.interruptedRunId &&\n candidate.generation === hydration.generation &&\n (candidate.kind !== 'generic' ||\n responseSchemaHash(interrupt) === undefined ||\n candidate.responseSchemaHash === responseSchemaHash(interrupt)))\n return {\n descriptor: interrupt,\n binding: genericBinding(interrupt, hydration, candidate),\n kind: 'generic',\n status: 'pending',\n // A valid raw binding is an explicit request to use this resume path,\n // even when this client has no registered first-party definition. Keep\n // it untyped, but preserve its existing generic controls. Missing,\n // malformed, and unsupported bindings remain display-only.\n canResolve: resumable,\n resumable,\n validationGeneration: 0,\n }\n }\n\n private buildSnapshot(\n transaction?: TransactionToken,\n ): BoundInterrupts<TTools, TInterrupts> {\n const hydration = this.requireHydration()\n // `client-tool-execution` items stay in `this.items` (they usually gate\n // batch submission and are resolved internally via auto-execution /\n // addToolResult), but they are never surfaced as public bound interrupts.\n // A mixed generic batch is the exception: those client tools wait for\n // `toolResume` and must not block submit.\n //\n // Items with status `submitting` are also omitted: the resume stream is\n // already in flight, so Approve/Deny is not actionable. Keeping them in\n // the public list made UIs look stuck after a successful approve and\n // blocked follow-up turns that key off `interrupts.length`.\n const next = this.items\n .filter(\n (item) =>\n item.kind !== 'client-tool-execution' && item.status !== 'submitting',\n )\n .map((item) => {\n const base = baseSnapshot(item, hydration)\n // Not ours to resume: expose the descriptor so a UI can show the run\n // is paused, with no `resolveInterrupt` to call.\n if (item.kind === 'unbound' || item.binding === undefined) {\n const snapshot: UnboundInterrupt = {\n ...base,\n kind: 'unbound',\n canResolve: false,\n }\n return Object.freeze(snapshot)\n }\n if (\n item.kind === 'tool-approval' &&\n item.binding.kind === 'tool-approval'\n ) {\n const binding = cloneAndDeepFreezeJson(item.binding)\n const snapshot = {\n ...base,\n kind: 'tool-approval' as const,\n binding,\n toolName: item.binding.toolName,\n toolCallId: item.binding.toolCallId,\n originalArgs: cloneAndDeepFreezeJson(item.binding.originalArgs),\n cancel: () => this.cancelItem(item.descriptor.id, transaction),\n clearResolution: () =>\n this.clearItem(item.descriptor.id, transaction),\n resolveInterrupt: (approved: boolean, options?: unknown) => {\n const details = isUnknownObject(options) ? options : undefined\n this.resolveItem(\n item.descriptor.id,\n {\n approved,\n ...(approved && details?.['editedArgs'] !== undefined\n ? { editedArgs: details['editedArgs'] }\n : {}),\n ...(details?.['payload'] !== undefined\n ? { payload: details['payload'] }\n : {}),\n },\n transaction,\n )\n },\n }\n return Object.freeze(snapshot)\n }\n const boundGeneric =\n item.binding.kind === 'generic'\n ? cloneAndDeepFreezeJson(item.binding)\n : cloneAndDeepFreezeJson({\n v: INTERRUPT_BINDING_VERSION,\n kind: 'generic' as const,\n interruptId: item.descriptor.id,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n ...(typeof item.binding.responseSchemaHash === 'string'\n ? { responseSchemaHash: item.binding.responseSchemaHash }\n : {}),\n })\n if (item.definition !== undefined && item.binding.kind === 'generic') {\n const snapshot = {\n ...base,\n kind: 'generic',\n definitionId: item.definition.id,\n key: item.binding.key ?? '',\n payload: item.payload,\n binding: boundGeneric,\n cancel: () => this.cancelItem(item.descriptor.id, transaction),\n clearResolution: () =>\n this.clearItem(item.descriptor.id, transaction),\n resolveInterrupt: (response: unknown) =>\n this.resolveItem(item.descriptor.id, response, transaction),\n }\n return Object.freeze(snapshot)\n }\n const snapshot: GenericAGUIInterrupt = {\n ...base,\n kind: 'generic',\n binding: boundGeneric,\n cancel: () => this.cancelItem(item.descriptor.id, transaction),\n clearResolution: () =>\n this.clearItem(item.descriptor.id, transaction),\n resolveInterrupt: (payload) =>\n this.resolveItem(item.descriptor.id, payload, transaction),\n }\n return Object.freeze(snapshot)\n })\n\n // The runtime items are created only from the exact configured TTools entry\n // selected by name. TypeScript cannot preserve that per-element lookup\n // through Array.map, so this generic return boundary restores the proven\n // distributive public union.\n return Object.freeze(next) as BoundInterrupts<TTools, TInterrupts>\n }\n\n // Provenance belongs to each publication because `onChange` may synchronously\n // mutate the manager and publish again before an outer callback returns.\n private publish(source: InterruptManagerChangeSource = 'live'): void {\n if (!this.hydration) {\n this.snapshot = Object.freeze([])\n this.state = Object.freeze({\n interrupts: this.snapshot,\n pendingInterrupts: this.snapshot,\n interruptErrors: this.rootErrors,\n resuming: this.resuming,\n })\n this.options.onChange?.(source)\n return\n }\n this.snapshot = this.buildSnapshot()\n this.state = Object.freeze({\n interrupts: this.snapshot,\n pendingInterrupts: this.snapshot,\n interruptErrors: this.rootErrors,\n resuming: this.resuming,\n })\n this.options.onChange?.(source)\n }\n\n private resolveItem(\n interruptId: string,\n payload: unknown,\n transaction?: TransactionToken,\n ): void {\n this.assertItemMutable(transaction)\n const item = this.findItem(interruptId)\n this.invalidateRetry()\n if (!item.canResolve) {\n item.status = 'error'\n item.error = this.itemError(\n interruptId,\n 'invalid-response-schema',\n 'The interrupt response schema is invalid and cannot be resolved.',\n )\n if (!transaction) this.publish()\n return\n }\n const validationGeneration = ++item.validationGeneration\n const validation = this.validateCandidate(item, payload)\n if (isPromiseLike(validation)) {\n item.status = 'validating'\n item.error = undefined\n if (!transaction) this.publish()\n void Promise.resolve(validation)\n .then((result) => {\n if (validationGeneration !== item.validationGeneration) return\n this.applyValidation(item, result, transaction)\n })\n .catch((error: unknown) => {\n if (validationGeneration !== item.validationGeneration) return\n this.applyValidation(\n item,\n {\n code: this.validationCode(item),\n message: error instanceof Error ? error.message : String(error),\n },\n transaction,\n )\n })\n return\n }\n this.applyValidation(item, validation, transaction)\n }\n\n private cancelItem(\n interruptId: string,\n transaction?: TransactionToken,\n ): void {\n this.assertItemMutable(transaction)\n const item = this.findItem(interruptId)\n this.invalidateRetry()\n item.validationGeneration++\n item.resolution = Object.freeze(\n resolutionWithContinuation(item, { interruptId, status: 'cancelled' }),\n )\n item.status = 'staged'\n item.error = undefined\n if (!transaction) {\n this.publish()\n this.maybeSubmit()\n }\n }\n\n private clearItem(interruptId: string, transaction?: TransactionToken): void {\n this.assertItemMutable(transaction)\n const item = this.findItem(interruptId)\n this.invalidateRetry()\n item.validationGeneration++\n item.resolution = undefined\n item.error = undefined\n item.status = 'pending'\n if (!transaction) this.publish()\n }\n\n private maybeSubmit(): void {\n // Unbound items can never be resolved through this path — something else\n // owns them. Including them in the completeness gate would deadlock the\n // batch, so the run's own interrupts could never be answered once a\n // foreign one shared the stream.\n const hasGeneric = this.items.some((item) => item.kind === 'generic')\n const ours = this.items.filter(\n (item) =>\n isClientOwnedInterrupt(item) &&\n !(hasGeneric && item.kind === 'client-tool-execution'),\n )\n if (\n ours.length === 0 ||\n ours.some(\n (item) => item.resolution === undefined || item.status !== 'staged',\n )\n ) {\n return\n }\n const hydration = this.requireHydration()\n const canonical = canonicalizeInterruptResolutions(\n ours.map((item) => item.resolution).filter((item) => item !== undefined),\n )\n const submission = Object.freeze({\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n resolutions: canonical.resolutions,\n canonicalResolutions: canonical.canonicalResolutions,\n fingerprint: canonical.fingerprint,\n })\n this.submitBatch(submission)\n }\n\n private applyValidation(\n item: RuntimeInterrupt,\n result: ValidationResult,\n transaction?: TransactionToken,\n ): void {\n if (!('valid' in result)) {\n item.status = 'error'\n const itemError = this.itemError(\n item.descriptor.id,\n result.code,\n result.message,\n result.path,\n )\n item.error = itemError\n // Client-tool-execution items are hidden from the public interrupt list,\n // so promote their validation failures onto interruptErrors for the UI.\n if (item.kind === 'client-tool-execution') {\n this.rootErrors = Object.freeze([\n ...this.rootErrors.filter(\n (error) =>\n !(\n error.code === 'item-validation-failed' &&\n error.interruptIds.includes(item.descriptor.id)\n ),\n ),\n Object.freeze({\n scope: 'batch' as const,\n code: 'item-validation-failed' as const,\n message: itemError.message,\n source: 'client' as const,\n retryable: false,\n interruptIds: Object.freeze([item.descriptor.id]),\n threadId: itemError.threadId,\n interruptedRunId: itemError.interruptedRunId,\n generation: itemError.generation,\n }),\n ])\n }\n if (!transaction) this.publish()\n return\n }\n item.resolution = cloneAndDeepFreezeJson(\n resolutionWithContinuation(item, {\n interruptId: item.descriptor.id,\n status: 'resolved',\n payload: result.payload,\n }),\n )\n item.status = 'staged'\n item.error = undefined\n if (!transaction) {\n this.publish()\n this.maybeSubmit()\n }\n }\n\n private validateCandidate(\n item: RuntimeInterrupt,\n payload: unknown,\n ): ValidationResult | Promise<ValidationResult> {\n if (item.kind === 'generic') {\n const validation = validateWithSchema(\n item.definition?.responseSchema ?? item.descriptor.responseSchema,\n payload,\n 'invalid-payload',\n )\n if (item.definition === undefined) return validation\n const preserveInput = (result: ValidationResult): ValidationResult =>\n 'valid' in result ? { valid: true, payload } : result\n return isPromiseLike(validation)\n ? Promise.resolve(validation).then(preserveInput)\n : preserveInput(validation)\n }\n if (item.kind === 'client-tool-execution') {\n return validateWithSchema(\n item.tool?.outputSchema,\n payload,\n 'invalid-tool-output',\n )\n }\n return this.validateApprovalCandidate(item, payload)\n }\n\n private validateApprovalCandidate(\n item: RuntimeInterrupt,\n payload: unknown,\n ): ValidationResult | Promise<ValidationResult> {\n if (!isUnknownObject(payload) || typeof payload['approved'] !== 'boolean') {\n return {\n code: 'invalid-payload',\n message: 'Tool approval resolutions require an approved boolean.',\n }\n }\n const approved = payload['approved']\n const editedArgs = payload['editedArgs']\n if (!approved && editedArgs !== undefined) {\n return {\n code: 'invalid-edited-args',\n message: 'Rejected tool approvals cannot edit tool arguments.',\n }\n }\n if (approved && editedArgs !== undefined) {\n const editedValidation = validateWithSchema(\n item.tool?.inputSchema,\n editedArgs,\n 'invalid-edited-args',\n )\n if (isPromiseLike(editedValidation)) {\n return Promise.resolve(editedValidation).then((result) =>\n 'valid' in result\n ? this.validateApprovalPayload(item, payload, result.payload)\n : result,\n )\n }\n if (!('valid' in editedValidation)) return editedValidation\n return this.validateApprovalPayload(\n item,\n payload,\n editedValidation.payload,\n )\n }\n return this.validateApprovalPayload(item, payload, undefined)\n }\n\n private validateApprovalPayload(\n item: RuntimeInterrupt,\n envelope: UnknownObject,\n validatedEditedArgs: unknown,\n ): ValidationResult | Promise<ValidationResult> {\n const approved = envelope['approved'] === true\n const schema = this.approvalBranchSchema(item.tool, approved)\n const branchPayload = envelope['payload']\n if (schema === undefined && branchPayload !== undefined) {\n return {\n code: 'invalid-payload',\n message: 'This approval branch does not accept a payload.',\n }\n }\n if (schema !== undefined && branchPayload === undefined) {\n return {\n code: 'invalid-payload',\n message: 'This approval branch requires a payload.',\n }\n }\n const validation = validateWithSchema(\n schema,\n branchPayload,\n 'invalid-payload',\n )\n const buildEnvelope = (result: ValidationResult): ValidationResult => {\n if (!('valid' in result)) return result\n return {\n valid: true,\n payload: {\n approved,\n ...(validatedEditedArgs !== undefined\n ? { editedArgs: validatedEditedArgs }\n : {}),\n ...(schema !== undefined ? { payload: result.payload } : {}),\n },\n }\n }\n return isPromiseLike(validation)\n ? Promise.resolve(validation).then(buildEnvelope)\n : buildEnvelope(validation)\n }\n\n private approvalBranchSchema(\n tool: AnyClientTool | undefined,\n approved: boolean,\n ): unknown {\n const approvalSchema: unknown = tool?.approvalSchema\n if (!isUnknownObject(approvalSchema)) return approvalSchema\n const hasBranches =\n 'approve' in approvalSchema || 'reject' in approvalSchema\n if (!hasBranches) return approvalSchema\n return approved ? approvalSchema['approve'] : approvalSchema['reject']\n }\n\n private validationCode(item: RuntimeInterrupt): ItemInterruptError['code'] {\n return item.kind === 'client-tool-execution'\n ? 'invalid-tool-output'\n : 'invalid-payload'\n }\n\n private resolveBooleanBulk(approved: boolean): void {\n // `client-tool-execution` items resolve out-of-band (auto execution /\n // addToolResult); they are transparent to the boolean shorthand. Eligibility\n // and resolution consider only the publicly resolvable items.\n const resolvable = this.items.filter(\n (item) =>\n isClientOwnedInterrupt(item) && item.kind !== 'client-tool-execution',\n )\n const eligible = resolvable.every(\n (item) =>\n item.kind === 'tool-approval' &&\n this.approvalBranchSchema(item.tool, approved) === undefined,\n )\n if (!eligible || resolvable.length === 0) {\n this.addRootError(\n 'unsupported-bulk-operation',\n 'Boolean bulk resolution requires payloadless tool approvals.',\n false,\n )\n return\n }\n this.invalidateRetry()\n for (const item of resolvable) {\n item.validationGeneration++\n item.resolution = cloneAndDeepFreezeJson({\n interruptId: item.descriptor.id,\n status: 'resolved',\n payload: { approved },\n })\n item.status = 'staged'\n item.error = undefined\n }\n this.publish()\n this.maybeSubmit()\n }\n\n private resolveTransaction(\n resolver: (\n interrupt: ResolvableChatInterrupt<TTools, TInterrupts>,\n ) => unknown,\n ): void {\n const checkpoints = this.items.map<RuntimeInterruptCheckpoint>((item) => ({\n status: item.status,\n ...(item.resolution !== undefined ? { resolution: item.resolution } : {}),\n ...(item.error !== undefined ? { error: item.error } : {}),\n validationGeneration: item.validationGeneration,\n }))\n const token: TransactionToken = { active: true }\n this.activeTransaction = token\n const stable = this.buildSnapshot(token).filter(isRootResolvableInterrupt)\n let failure:\n | { code: BatchInterruptError['code']; message: string }\n | undefined\n try {\n for (const interrupt of stable) {\n const result = resolver(interrupt)\n if (result !== undefined) {\n failure = {\n code: isPromiseLike(result)\n ? 'async-resolver'\n : 'inactive-transaction',\n message: isPromiseLike(result)\n ? 'Interrupt transaction resolvers must be synchronous.'\n : 'Interrupt transaction resolvers must return literal undefined.',\n }\n break\n }\n }\n if (\n failure === undefined &&\n this.items.some(\n (item) =>\n // `client-tool-execution` items are resolved out-of-band (auto\n // execution / addToolResult), not by this synchronous resolver, so\n // they don't count against transaction completeness. `maybeSubmit`\n // still waits for them unless a generic interrupt shares the batch.\n isClientOwnedInterrupt(item) &&\n item.kind !== 'client-tool-execution' &&\n (item.resolution === undefined || item.status !== 'staged'),\n )\n ) {\n failure = {\n code: 'incomplete-batch',\n message: 'Interrupt transaction did not resolve every item.',\n }\n }\n } catch (error) {\n failure = {\n code: 'item-validation-failed',\n message: error instanceof Error ? error.message : String(error),\n }\n } finally {\n token.active = false\n this.activeTransaction = undefined\n }\n\n if (failure) {\n this.restoreCheckpoints(checkpoints)\n this.addRootError(failure.code, failure.message, false)\n return\n }\n this.publish()\n this.maybeSubmit()\n }\n\n private restoreCheckpoints(\n checkpoints: ReadonlyArray<RuntimeInterruptCheckpoint>,\n ): void {\n this.items.forEach((item, index) => {\n const checkpoint = checkpoints[index]\n if (!checkpoint) return\n item.status = checkpoint.status\n item.resolution = checkpoint.resolution\n item.error = checkpoint.error\n item.validationGeneration = checkpoint.validationGeneration + 1\n })\n this.publish()\n }\n\n private assertItemMutable(transaction?: TransactionToken): void {\n if (transaction && !transaction.active) {\n throw new Error('Interrupt transaction is inactive.')\n }\n if (this.activeTransaction && transaction !== this.activeTransaction) {\n throw new Error('Interrupt transaction is inactive.')\n }\n if (this.resuming) {\n throw new Error('Interrupts cannot be mutated while submitting.')\n }\n }\n\n private assertRootMutable(): void {\n if (this.activeTransaction) {\n throw new Error('Interrupt transaction is already active.')\n }\n if (this.resuming) {\n throw new Error('Interrupts cannot be mutated while submitting.')\n }\n }\n\n private invalidateRetry(): void {\n this.retrySubmission = undefined\n }\n\n private submitBatch(submission: InterruptManagerSubmission): void {\n // Track ownership so a superseded submission cannot mutate current state.\n const operation = { submission }\n this.activeSubmissionOperation = operation\n this.resuming = true\n this.retrySubmission = undefined\n for (const item of this.items) {\n if (isClientOwnedInterrupt(item)) item.status = 'submitting'\n }\n this.publish()\n void this.performSubmission(operation)\n }\n\n private async performSubmission(\n operation: SubmissionOperation,\n ): Promise<void> {\n try {\n await this.options.submit(operation.submission)\n } catch (error) {\n if (this.activeSubmissionOperation !== operation) return\n this.handleSubmissionFailure(error, operation.submission)\n } finally {\n if (this.activeSubmissionOperation === operation) {\n this.activeSubmissionOperation = undefined\n this.resuming = false\n this.publish()\n }\n }\n }\n\n private handleSubmissionFailure(\n error: unknown,\n submission: InterruptManagerSubmission,\n ): void {\n const errors = readSubmissionErrors(error)\n if (errors.length === 0) {\n const message = error instanceof Error ? error.message : String(error)\n this.addRootError('transport', message, true, 'transport')\n this.retrySubmission = submission\n for (const item of this.items) {\n if (isClientOwnedInterrupt(item)) item.status = 'error'\n }\n return\n }\n\n const correlatedErrors = errors.filter((submissionError) =>\n submissionErrorMatchesActiveBatch(submissionError, submission),\n )\n if (correlatedErrors.length !== errors.length) {\n this.addRootError(\n 'protocol',\n 'Interrupt submission errors did not match the active batch.',\n false,\n )\n }\n\n let nonRetryable = false\n let retryable = false\n const batchErrors: Array<BatchInterruptError> = []\n for (const submissionError of correlatedErrors) {\n if (\n submissionError.code === 'stale' ||\n submissionError.code === 'expired' ||\n submissionError.code === 'conflict'\n ) {\n nonRetryable = true\n }\n retryable ||= submissionError.retryable\n if (submissionError.scope === 'item') {\n const item = this.items.find(\n (candidate) =>\n isClientOwnedInterrupt(candidate) &&\n candidate.descriptor.id === submissionError.interruptId,\n )\n if (item) {\n item.status = 'error'\n item.error = cloneAndDeepFreezeJson(submissionError)\n }\n } else {\n batchErrors.push(cloneAndDeepFreezeJson(submissionError))\n }\n }\n const mergedBatchErrors = mergeSubmissionBatchErrors(\n this.rootErrors,\n this.submissionRootErrors,\n batchErrors,\n )\n this.rootErrors = mergedBatchErrors.rootErrors\n this.submissionRootErrors = mergedBatchErrors.submissionRootErrors\n for (const item of this.items) {\n if (isClientOwnedInterrupt(item) && item.status === 'submitting') {\n item.status = 'error'\n }\n }\n this.retrySubmission = retryable && !nonRetryable ? submission : undefined\n }\n\n private addRootError(\n code: BatchInterruptError['code'],\n message: string,\n retryable: boolean,\n source: BatchInterruptError['source'] = 'client',\n ): void {\n const hydration = this.requireHydration()\n this.rootErrors = Object.freeze([\n ...this.rootErrors,\n Object.freeze({\n scope: 'batch' as const,\n code,\n message,\n source,\n retryable,\n interruptIds: Object.freeze(\n this.items\n .filter(isClientOwnedInterrupt)\n .map((item) => item.descriptor.id),\n ),\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n }),\n ])\n this.publish()\n }\n\n private findItem(interruptId: string): RuntimeInterrupt {\n const item = this.items.find(\n (candidate) => candidate.descriptor.id === interruptId,\n )\n if (!item) throw new Error(`Unknown interrupt: ${interruptId}`)\n return item\n }\n\n private requireHydration(): InterruptManagerHydration {\n if (!this.hydration) throw new Error('InterruptManager is not hydrated.')\n return this.hydration\n }\n\n private itemError(\n interruptId: string,\n code: ItemInterruptError['code'],\n message: string,\n path?: ReadonlyArray<string | number>,\n ): ItemInterruptError {\n const hydration = this.requireHydration()\n return Object.freeze({\n scope: 'item',\n interruptId,\n code,\n message,\n ...(path !== undefined ? { path: Object.freeze([...path]) } : {}),\n source: 'client',\n retryable: false,\n threadId: hydration.threadId,\n interruptedRunId: hydration.interruptedRunId,\n generation: hydration.generation,\n })\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { UIMessage } from './types.js';
2
+ export declare function normalizeMessageDates(message: UIMessage): UIMessage;
3
+ export declare function normalizeMessagesDates(messages: Array<UIMessage>): Array<UIMessage>;
@@ -0,0 +1,35 @@
1
+ //#region src/message-date-normalizer.ts
2
+ function validDate(value) {
3
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? void 0 : value;
4
+ if (typeof value !== "string") return void 0;
5
+ const date = new Date(value);
6
+ return Number.isNaN(date.getTime()) ? void 0 : date;
7
+ }
8
+ function normalizeMessageDates(message) {
9
+ const messageDate = validDate(message.createdAt);
10
+ const parts = message.parts.map((part) => {
11
+ if (part.type !== "tool-result") return part;
12
+ const date = validDate(part.createdAt);
13
+ const { createdAt: _ignored, ...rest } = part;
14
+ return date ? {
15
+ ...rest,
16
+ createdAt: date
17
+ } : rest;
18
+ });
19
+ const { createdAt: _ignored, ...rest } = message;
20
+ return messageDate ? {
21
+ ...rest,
22
+ parts,
23
+ createdAt: messageDate
24
+ } : {
25
+ ...rest,
26
+ parts
27
+ };
28
+ }
29
+ function normalizeMessagesDates(messages) {
30
+ return messages.map(normalizeMessageDates);
31
+ }
32
+ //#endregion
33
+ export { normalizeMessageDates, normalizeMessagesDates };
34
+
35
+ //# sourceMappingURL=message-date-normalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-date-normalizer.js","names":[],"sources":["../../src/message-date-normalizer.ts"],"sourcesContent":["import type { UIMessage } from './types'\n\nfunction validDate(value: unknown): Date | undefined {\n if (value instanceof Date)\n return Number.isNaN(value.getTime()) ? undefined : value\n if (typeof value !== 'string') return undefined\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? undefined : date\n}\n\nexport function normalizeMessageDates(message: UIMessage): UIMessage {\n const messageDate = validDate(message.createdAt)\n const parts = message.parts.map((part) => {\n if (part.type !== 'tool-result') return part\n const date = validDate(part.createdAt)\n const { createdAt: _ignored, ...rest } = part\n return date ? { ...rest, createdAt: date } : rest\n })\n const { createdAt: _ignored, ...rest } = message\n return messageDate\n ? { ...rest, parts, createdAt: messageDate }\n : { ...rest, parts }\n}\n\nexport function normalizeMessagesDates(\n messages: Array<UIMessage>,\n): Array<UIMessage> {\n return messages.map(normalizeMessageDates)\n}\n"],"mappings":";AAEA,SAAS,UAAU,OAAkC;CACnD,IAAI,iBAAiB,MACnB,OAAO,OAAO,MAAM,MAAM,QAAQ,CAAC,IAAI,KAAA,IAAY;CACrD,IAAI,OAAO,UAAU,UAAU,OAAO,KAAA;CACtC,MAAM,OAAO,IAAI,KAAK,KAAK;CAC3B,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,IAAI,KAAA,IAAY;AACpD;AAEA,SAAgB,sBAAsB,SAA+B;CACnE,MAAM,cAAc,UAAU,QAAQ,SAAS;CAC/C,MAAM,QAAQ,QAAQ,MAAM,KAAK,SAAS;EACxC,IAAI,KAAK,SAAS,eAAe,OAAO;EACxC,MAAM,OAAO,UAAU,KAAK,SAAS;EACrC,MAAM,EAAE,WAAW,UAAU,GAAG,SAAS;EACzC,OAAO,OAAO;GAAE,GAAG;GAAM,WAAW;EAAK,IAAI;CAC/C,CAAC;CACD,MAAM,EAAE,WAAW,UAAU,GAAG,SAAS;CACzC,OAAO,cACH;EAAE,GAAG;EAAM;EAAO,WAAW;CAAY,IACzC;EAAE,GAAG;EAAM;CAAM;AACvB;AAEA,SAAgB,uBACd,UACkB;CAClB,OAAO,SAAS,IAAI,qBAAqB;AAC3C"}
@@ -1,5 +1,6 @@
1
1
  import { createResponseStreamTextDecoder, getResponseStreamReader } from "./response-stream.js";
2
2
  import { parseSseDataLine } from "./sse-utils.js";
3
+ import { ByokMissingError, isByokMissingBody } from "@tanstack/ai/byok";
3
4
  //#region src/sse-parser.ts
4
5
  /**
5
6
  * Read lines from a stream (newline-delimited)
@@ -28,7 +29,13 @@ async function* readStreamLines(reader, abortSignal) {
28
29
  * (e.g., TanStack Start server functions using `toServerSentEventsResponse()`).
29
30
  */
30
31
  async function* parseSSEResponse(response, abortSignal) {
31
- if (!response.ok) throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
32
+ if (!response.ok) {
33
+ if (response.status === 401) {
34
+ const body = await response.clone().json().catch(() => null);
35
+ if (isByokMissingBody(body)) throw new ByokMissingError(body.error.provider);
36
+ }
37
+ throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
38
+ }
32
39
  const reader = getResponseStreamReader(response);
33
40
  for await (const line of readStreamLines(reader, abortSignal)) {
34
41
  const data = parseSseDataLine(line);
@@ -1 +1 @@
1
- {"version":3,"file":"sse-parser.js","names":[],"sources":["../../src/sse-parser.ts"],"sourcesContent":["import {\n createResponseStreamTextDecoder,\n getResponseStreamReader,\n} from './response-stream'\nimport { parseSseDataLine } from './sse-utils'\nimport type { StreamChunk } from '@tanstack/ai/client'\n\n/**\n * Read lines from a stream (newline-delimited)\n */\nasync function* readStreamLines(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n abortSignal?: AbortSignal,\n): AsyncGenerator<string> {\n try {\n const decoder = createResponseStreamTextDecoder()\n let buffer = ''\n\n while (!abortSignal?.aborted) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n\n buffer = lines.pop() || ''\n\n for (const line of lines) {\n if (line.trim()) {\n yield line\n }\n }\n }\n\n if (buffer.trim()) {\n yield buffer\n }\n } finally {\n reader.releaseLock()\n }\n}\n\n/**\n * Parse a Response body as Server-Sent Events, yielding StreamChunks.\n *\n * Used by GenerationClient to parse SSE Responses returned from fetchers\n * (e.g., TanStack Start server functions using `toServerSentEventsResponse()`).\n */\nexport async function* parseSSEResponse(\n response: Response,\n abortSignal?: AbortSignal,\n): AsyncGenerator<StreamChunk> {\n if (!response.ok) {\n throw new Error(\n `HTTP error! status: ${response.status} ${response.statusText}`,\n )\n }\n\n const reader = getResponseStreamReader(response)\n\n for await (const line of readStreamLines(reader, abortSignal)) {\n const data = parseSseDataLine(line)\n\n if (data === '[DONE]') {\n console.warn(\n '[@tanstack/ai-client] Received [DONE] sentinel. This is deprecated — upgrade your @tanstack/ai server package. RUN_FINISHED is the stream terminator.',\n )\n continue\n }\n\n try {\n const parsed: StreamChunk = JSON.parse(data)\n yield parsed\n } catch (parseError) {\n console.warn('Failed to parse SSE chunk:', data)\n }\n }\n}\n"],"mappings":";;;;;;AAUA,gBAAgB,gBACd,QACA,aACwB;CACxB,IAAI;EACF,MAAM,UAAU,gCAAgC;EAChD,IAAI,SAAS;EAEb,OAAO,CAAC,aAAa,SAAS;GAC5B,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;GAC1C,IAAI,MAAM;GAEV,UAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;GAChD,MAAM,QAAQ,OAAO,MAAM,IAAI;GAE/B,SAAS,MAAM,IAAI,KAAK;GAExB,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,KAAK,GACZ,MAAM;EAGZ;EAEA,IAAI,OAAO,KAAK,GACd,MAAM;CAEV,UAAU;EACR,OAAO,YAAY;CACrB;AACF;;;;;;;AAQA,gBAAuB,iBACrB,UACA,aAC6B;CAC7B,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MACR,uBAAuB,SAAS,OAAO,GAAG,SAAS,YACrD;CAGF,MAAM,SAAS,wBAAwB,QAAQ;CAE/C,WAAW,MAAM,QAAQ,gBAAgB,QAAQ,WAAW,GAAG;EAC7D,MAAM,OAAO,iBAAiB,IAAI;EAElC,IAAI,SAAS,UAAU;GACrB,QAAQ,KACN,uJACF;GACA;EACF;EAEA,IAAI;GAEF,MAD4B,KAAK,MAAM,IACjC;EACR,SAAS,YAAY;GACnB,QAAQ,KAAK,8BAA8B,IAAI;EACjD;CACF;AACF"}
1
+ {"version":3,"file":"sse-parser.js","names":[],"sources":["../../src/sse-parser.ts"],"sourcesContent":["import { ByokMissingError, isByokMissingBody } from '@tanstack/ai/byok'\nimport {\n createResponseStreamTextDecoder,\n getResponseStreamReader,\n} from './response-stream'\nimport { parseSseDataLine } from './sse-utils'\nimport type { StreamChunk } from '@tanstack/ai/client'\n\n/**\n * Read lines from a stream (newline-delimited)\n */\nasync function* readStreamLines(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n abortSignal?: AbortSignal,\n): AsyncGenerator<string> {\n try {\n const decoder = createResponseStreamTextDecoder()\n let buffer = ''\n\n while (!abortSignal?.aborted) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n\n buffer = lines.pop() || ''\n\n for (const line of lines) {\n if (line.trim()) {\n yield line\n }\n }\n }\n\n if (buffer.trim()) {\n yield buffer\n }\n } finally {\n reader.releaseLock()\n }\n}\n\n/**\n * Parse a Response body as Server-Sent Events, yielding StreamChunks.\n *\n * Used by GenerationClient to parse SSE Responses returned from fetchers\n * (e.g., TanStack Start server functions using `toServerSentEventsResponse()`).\n */\nexport async function* parseSSEResponse(\n response: Response,\n abortSignal?: AbortSignal,\n): AsyncGenerator<StreamChunk> {\n if (!response.ok) {\n if (response.status === 401) {\n const body: unknown = await response\n .clone()\n .json()\n .catch(() => null)\n if (isByokMissingBody(body)) {\n throw new ByokMissingError(body.error.provider)\n }\n }\n throw new Error(\n `HTTP error! status: ${response.status} ${response.statusText}`,\n )\n }\n\n const reader = getResponseStreamReader(response)\n\n for await (const line of readStreamLines(reader, abortSignal)) {\n const data = parseSseDataLine(line)\n\n if (data === '[DONE]') {\n console.warn(\n '[@tanstack/ai-client] Received [DONE] sentinel. This is deprecated — upgrade your @tanstack/ai server package. RUN_FINISHED is the stream terminator.',\n )\n continue\n }\n\n try {\n const parsed: StreamChunk = JSON.parse(data)\n yield parsed\n } catch (parseError) {\n console.warn('Failed to parse SSE chunk:', data)\n }\n }\n}\n"],"mappings":";;;;;;;AAWA,gBAAgB,gBACd,QACA,aACwB;CACxB,IAAI;EACF,MAAM,UAAU,gCAAgC;EAChD,IAAI,SAAS;EAEb,OAAO,CAAC,aAAa,SAAS;GAC5B,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;GAC1C,IAAI,MAAM;GAEV,UAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;GAChD,MAAM,QAAQ,OAAO,MAAM,IAAI;GAE/B,SAAS,MAAM,IAAI,KAAK;GAExB,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,KAAK,GACZ,MAAM;EAGZ;EAEA,IAAI,OAAO,KAAK,GACd,MAAM;CAEV,UAAU;EACR,OAAO,YAAY;CACrB;AACF;;;;;;;AAQA,gBAAuB,iBACrB,UACA,aAC6B;CAC7B,IAAI,CAAC,SAAS,IAAI;EAChB,IAAI,SAAS,WAAW,KAAK;GAC3B,MAAM,OAAgB,MAAM,SACzB,MAAM,CAAC,CACP,KAAK,CAAC,CACN,YAAY,IAAI;GACnB,IAAI,kBAAkB,IAAI,GACxB,MAAM,IAAI,iBAAiB,KAAK,MAAM,QAAQ;EAElD;EACA,MAAM,IAAI,MACR,uBAAuB,SAAS,OAAO,GAAG,SAAS,YACrD;CACF;CAEA,MAAM,SAAS,wBAAwB,QAAQ;CAE/C,WAAW,MAAM,QAAQ,gBAAgB,QAAQ,WAAW,GAAG;EAC7D,MAAM,OAAO,iBAAiB,IAAI;EAElC,IAAI,SAAS,UAAU;GACrB,QAAQ,KACN,uJACF;GACA;EACF;EAEA,IAAI;GAEF,MAD4B,KAAK,MAAM,IACjC;EACR,SAAS,YAAY;GACnB,QAAQ,KAAK,8BAA8B,IAAI;EACjD;CACF;AACF"}
@@ -1,3 +1,4 @@
1
+ import { normalizeMessagesDates } from "./message-date-normalizer.js";
1
2
  //#region src/storage-adapters.ts
2
3
  /**
3
4
  * Thrown by a storage adapter when its backing store is absent — most commonly
@@ -20,6 +21,17 @@ function stringifyJson(value) {
20
21
  if (typeof serialized !== "string") throw new TypeError("The value is not JSON serializable.");
21
22
  return serialized;
22
23
  }
24
+ function reviveMessageCreatedAt(message) {
25
+ return normalizeMessagesDates([message]).at(0) ?? message;
26
+ }
27
+ function revivePersistedState(state) {
28
+ if (state == null || typeof state !== "object") return state;
29
+ if (!Array.isArray(state.messages)) return state;
30
+ return {
31
+ ...state,
32
+ messages: state.messages.map(reviveMessageCreatedAt)
33
+ };
34
+ }
23
35
  function createWebStoragePersistence(storageName, options) {
24
36
  const keyPrefix = options.keyPrefix ?? "tanstack-ai:";
25
37
  const serialize = options.serialize ?? stringifyJson;
@@ -33,7 +45,7 @@ function createWebStoragePersistence(storageName, options) {
33
45
  return {
34
46
  getItem(id) {
35
47
  const item = getStorage().getItem(key(id));
36
- return item === null ? null : deserialize(item);
48
+ return item === null ? null : revivePersistedState(deserialize(item));
37
49
  },
38
50
  setItem(id, value) {
39
51
  getStorage().setItem(key(id), serialize(value));
@@ -1 +1 @@
1
- {"version":3,"file":"storage-adapters.js","names":[],"sources":["../../src/storage-adapters.ts"],"sourcesContent":["import type { ChatPersistedState, ChatStorageAdapter } from './types'\n\nexport interface WebStoragePersistenceOptions {\n keyPrefix?: string\n /**\n * Defaults to `JSON.stringify`. Override only for values JSON can't\n * round-trip losslessly (a `Map`, a `bigint`, a `Date` you need back as a\n * `Date` rather than an ISO string).\n */\n serialize?: (value: ChatPersistedState) => string\n /** Defaults to `JSON.parse`. */\n deserialize?: (value: string) => ChatPersistedState\n}\n\nexport interface IndexedDBPersistenceOptions {\n databaseName?: string\n objectStoreName?: string\n keyPrefix?: string\n}\n\ntype StorageName = 'localStorage' | 'sessionStorage' | 'indexedDB'\n\n/**\n * Thrown by a storage adapter when its backing store is absent — most commonly\n * during server-side rendering, where `localStorage` / `sessionStorage` /\n * `indexedDB` do not exist on `globalThis`. The adapters check availability\n * lazily, **per operation**, so constructing an adapter never throws; the error\n * surfaces from `getItem` / `setItem` / `removeItem` (rejected promise for\n * IndexedDB). The chat persistence layer treats adapter failures as best-effort\n * (storage errors never break chat setup or streaming).\n */\nexport class StorageUnavailableError extends Error {\n constructor(storageName: StorageName) {\n super(`${storageName} is not available in this environment.`)\n this.name = 'StorageUnavailableError'\n }\n}\n\nfunction stringifyJson(value: ChatPersistedState): string {\n const stringify: (input: unknown) => unknown = JSON.stringify\n const serialized = stringify(value)\n if (typeof serialized !== 'string') {\n throw new TypeError('The value is not JSON serializable.')\n }\n return serialized\n}\n\nfunction createWebStoragePersistence(\n storageName: 'localStorage' | 'sessionStorage',\n options: WebStoragePersistenceOptions,\n): ChatStorageAdapter<ChatPersistedState> {\n const keyPrefix = options.keyPrefix ?? 'tanstack-ai:'\n const serialize = options.serialize ?? stringifyJson\n const deserialize = options.deserialize ?? JSON.parse\n const key = (id: string) => `${keyPrefix}${id}`\n\n const getStorage = (): Storage => {\n const browserGlobals: {\n localStorage?: Storage\n sessionStorage?: Storage\n } = globalThis\n const storage = browserGlobals[storageName]\n if (!storage) {\n throw new StorageUnavailableError(storageName)\n }\n return storage\n }\n\n return {\n getItem(id) {\n const item = getStorage().getItem(key(id))\n return item === null ? null : deserialize(item)\n },\n setItem(id, value) {\n getStorage().setItem(key(id), serialize(value))\n },\n removeItem(id) {\n getStorage().removeItem(key(id))\n },\n }\n}\n\n/**\n * A `ChatStorageAdapter` backed by `window.localStorage` (persists across\n * reloads and browser restarts). Keys are namespaced with `keyPrefix`, which\n * defaults to `tanstack-ai:`. Every operation reads `localStorage` lazily and\n * throws {@link StorageUnavailableError} when it is absent (e.g. SSR), so the\n * adapter can be constructed safely on the server.\n *\n * The `serialize` / `deserialize` codec defaults to `JSON.stringify` /\n * `JSON.parse`, so the common case needs no codec.\n */\nexport function localStoragePersistence(\n options: WebStoragePersistenceOptions = {},\n): ChatStorageAdapter<ChatPersistedState> {\n return createWebStoragePersistence('localStorage', options)\n}\n\n/**\n * A `ChatStorageAdapter` backed by `window.sessionStorage` (scoped to the tab\n * and cleared when it closes). Identical to {@link localStoragePersistence} in\n * every other respect: the `tanstack-ai:` default `keyPrefix`, lazy\n * per-operation {@link StorageUnavailableError} on SSR, and a JSON codec that\n * defaults to `JSON.stringify` / `JSON.parse`.\n */\nexport function sessionStoragePersistence(\n options: WebStoragePersistenceOptions = {},\n): ChatStorageAdapter<ChatPersistedState> {\n return createWebStoragePersistence('sessionStorage', options)\n}\n\n/**\n * A `ChatStorageAdapter` backed by IndexedDB, for values too large for Web\n * Storage or that benefit from structured-clone storage. All operations are\n * async and the database opens lazily on first use; keys are namespaced with\n * `keyPrefix` (default `tanstack-ai:`). When IndexedDB is unavailable (e.g.\n * SSR) each operation rejects with {@link StorageUnavailableError}.\n *\n * No serialize/deserialize codec is needed or accepted — values are stored via\n * IndexedDB's native structured clone, so `Date`, `Map`, `ArrayBuffer`, etc.\n * round-trip without a JSON step.\n */\nexport function indexedDBPersistence(\n options: IndexedDBPersistenceOptions = {},\n): ChatStorageAdapter<ChatPersistedState> {\n const databaseName = options.databaseName ?? 'tanstack-ai'\n const objectStoreName = options.objectStoreName ?? 'persistence'\n const keyPrefix = options.keyPrefix ?? 'tanstack-ai:'\n let databasePromise: Promise<IDBDatabase> | undefined\n\n const openDatabase = (): Promise<IDBDatabase> => {\n if (databasePromise) {\n return databasePromise\n }\n\n databasePromise = new Promise<IDBDatabase>((resolve, reject) => {\n const browserGlobals: { indexedDB?: IDBFactory } = globalThis\n const factory = browserGlobals.indexedDB\n if (!factory) {\n reject(new StorageUnavailableError('indexedDB'))\n return\n }\n\n let request: IDBOpenDBRequest\n let openFailed = false\n try {\n request = factory.open(databaseName)\n } catch (error) {\n reject(error)\n return\n }\n\n request.onupgradeneeded = () => {\n if (!request.result.objectStoreNames.contains(objectStoreName)) {\n request.result.createObjectStore(objectStoreName)\n }\n }\n request.onerror = () => {\n openFailed = true\n reject(request.error ?? new Error(`Failed to open ${databaseName}.`))\n }\n request.onblocked = () => {\n openFailed = true\n reject(\n new Error(\n `Opening IndexedDB database \"${databaseName}\" was blocked.`,\n ),\n )\n }\n request.onsuccess = () => {\n const database = request.result\n if (openFailed) {\n database.close()\n return\n }\n database.onversionchange = () => {\n database.close()\n databasePromise = undefined\n }\n resolve(database)\n }\n }).catch((error: unknown) => {\n databasePromise = undefined\n throw error\n })\n\n return databasePromise\n }\n\n const runRequest = async <TResult>(\n mode: IDBTransactionMode,\n createRequest: (store: IDBObjectStore) => IDBRequest<TResult>,\n ): Promise<TResult> => {\n const database = await openDatabase()\n return new Promise<TResult>((resolve, reject) => {\n let request: IDBRequest<TResult>\n let result: TResult\n try {\n const transaction = database.transaction(objectStoreName, mode)\n request = createRequest(transaction.objectStore(objectStoreName))\n request.onsuccess = () => {\n result = request.result\n }\n request.onerror = () => {\n reject(request.error ?? new Error('IndexedDB request failed.'))\n }\n transaction.oncomplete = () => {\n resolve(result)\n }\n transaction.onerror = () => {\n reject(\n transaction.error ?? new Error('IndexedDB transaction failed.'),\n )\n }\n transaction.onabort = () => {\n reject(\n transaction.error ?? new Error('IndexedDB transaction aborted.'),\n )\n }\n } catch (error) {\n reject(error)\n }\n })\n }\n\n const key = (id: string) => `${keyPrefix}${id}`\n return {\n getItem(id) {\n return runRequest('readonly', (store) => store.get(key(id)))\n },\n setItem(id, value) {\n return runRequest('readwrite', (store) => store.put(value, key(id))).then(\n () => undefined,\n )\n },\n removeItem(id) {\n return runRequest('readwrite', (store) => store.delete(key(id))).then(\n () => undefined,\n )\n },\n }\n}\n"],"mappings":";;;;;;;;;;AA+BA,IAAa,0BAAb,cAA6C,MAAM;CACjD,YAAY,aAA0B;EACpC,MAAM,GAAG,YAAY,uCAAuC;EAC5D,KAAK,OAAO;CACd;AACF;AAEA,SAAS,cAAc,OAAmC;CACxD,MAAM,YAAyC,KAAK;CACpD,MAAM,aAAa,UAAU,KAAK;CAClC,IAAI,OAAO,eAAe,UACxB,MAAM,IAAI,UAAU,qCAAqC;CAE3D,OAAO;AACT;AAEA,SAAS,4BACP,aACA,SACwC;CACxC,MAAM,YAAY,QAAQ,aAAa;CACvC,MAAM,YAAY,QAAQ,aAAa;CACvC,MAAM,cAAc,QAAQ,eAAe,KAAK;CAChD,MAAM,OAAO,OAAe,GAAG,YAAY;CAE3C,MAAM,mBAA4B;EAKhC,MAAM,UAAU,WAAe;EAC/B,IAAI,CAAC,SACH,MAAM,IAAI,wBAAwB,WAAW;EAE/C,OAAO;CACT;CAEA,OAAO;EACL,QAAQ,IAAI;GACV,MAAM,OAAO,WAAW,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC;GACzC,OAAO,SAAS,OAAO,OAAO,YAAY,IAAI;EAChD;EACA,QAAQ,IAAI,OAAO;GACjB,WAAW,CAAC,CAAC,QAAQ,IAAI,EAAE,GAAG,UAAU,KAAK,CAAC;EAChD;EACA,WAAW,IAAI;GACb,WAAW,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC;EACjC;CACF;AACF;;;;;;;;;;;AAYA,SAAgB,wBACd,UAAwC,CAAC,GACD;CACxC,OAAO,4BAA4B,gBAAgB,OAAO;AAC5D;;;;;;;;AASA,SAAgB,0BACd,UAAwC,CAAC,GACD;CACxC,OAAO,4BAA4B,kBAAkB,OAAO;AAC9D;;;;;;;;;;;;AAaA,SAAgB,qBACd,UAAuC,CAAC,GACA;CACxC,MAAM,eAAe,QAAQ,gBAAgB;CAC7C,MAAM,kBAAkB,QAAQ,mBAAmB;CACnD,MAAM,YAAY,QAAQ,aAAa;CACvC,IAAI;CAEJ,MAAM,qBAA2C;EAC/C,IAAI,iBACF,OAAO;EAGT,kBAAkB,IAAI,SAAsB,SAAS,WAAW;GAE9D,MAAM,UAAU,WAAe;GAC/B,IAAI,CAAC,SAAS;IACZ,OAAO,IAAI,wBAAwB,WAAW,CAAC;IAC/C;GACF;GAEA,IAAI;GACJ,IAAI,aAAa;GACjB,IAAI;IACF,UAAU,QAAQ,KAAK,YAAY;GACrC,SAAS,OAAO;IACd,OAAO,KAAK;IACZ;GACF;GAEA,QAAQ,wBAAwB;IAC9B,IAAI,CAAC,QAAQ,OAAO,iBAAiB,SAAS,eAAe,GAC3D,QAAQ,OAAO,kBAAkB,eAAe;GAEpD;GACA,QAAQ,gBAAgB;IACtB,aAAa;IACb,OAAO,QAAQ,yBAAS,IAAI,MAAM,kBAAkB,aAAa,EAAE,CAAC;GACtE;GACA,QAAQ,kBAAkB;IACxB,aAAa;IACb,uBACE,IAAI,MACF,+BAA+B,aAAa,eAC9C,CACF;GACF;GACA,QAAQ,kBAAkB;IACxB,MAAM,WAAW,QAAQ;IACzB,IAAI,YAAY;KACd,SAAS,MAAM;KACf;IACF;IACA,SAAS,wBAAwB;KAC/B,SAAS,MAAM;KACf,kBAAkB,KAAA;IACpB;IACA,QAAQ,QAAQ;GAClB;EACF,CAAC,CAAC,CAAC,OAAO,UAAmB;GAC3B,kBAAkB,KAAA;GAClB,MAAM;EACR,CAAC;EAED,OAAO;CACT;CAEA,MAAM,aAAa,OACjB,MACA,kBACqB;EACrB,MAAM,WAAW,MAAM,aAAa;EACpC,OAAO,IAAI,SAAkB,SAAS,WAAW;GAC/C,IAAI;GACJ,IAAI;GACJ,IAAI;IACF,MAAM,cAAc,SAAS,YAAY,iBAAiB,IAAI;IAC9D,UAAU,cAAc,YAAY,YAAY,eAAe,CAAC;IAChE,QAAQ,kBAAkB;KACxB,SAAS,QAAQ;IACnB;IACA,QAAQ,gBAAgB;KACtB,OAAO,QAAQ,yBAAS,IAAI,MAAM,2BAA2B,CAAC;IAChE;IACA,YAAY,mBAAmB;KAC7B,QAAQ,MAAM;IAChB;IACA,YAAY,gBAAgB;KAC1B,OACE,YAAY,yBAAS,IAAI,MAAM,+BAA+B,CAChE;IACF;IACA,YAAY,gBAAgB;KAC1B,OACE,YAAY,yBAAS,IAAI,MAAM,gCAAgC,CACjE;IACF;GACF,SAAS,OAAO;IACd,OAAO,KAAK;GACd;EACF,CAAC;CACH;CAEA,MAAM,OAAO,OAAe,GAAG,YAAY;CAC3C,OAAO;EACL,QAAQ,IAAI;GACV,OAAO,WAAW,aAAa,UAAU,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;EAC7D;EACA,QAAQ,IAAI,OAAO;GACjB,OAAO,WAAW,cAAc,UAAU,MAAM,IAAI,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,WAC7D,KAAA,CACR;EACF;EACA,WAAW,IAAI;GACb,OAAO,WAAW,cAAc,UAAU,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,WACzD,KAAA,CACR;EACF;CACF;AACF"}
1
+ {"version":3,"file":"storage-adapters.js","names":[],"sources":["../../src/storage-adapters.ts"],"sourcesContent":["import type { ChatPersistedState, ChatStorageAdapter, UIMessage } from './types'\nimport { normalizeMessagesDates } from './message-date-normalizer'\n\nexport interface WebStoragePersistenceOptions {\n keyPrefix?: string\n /**\n * Defaults to `JSON.stringify`. Override only for values JSON can't\n * round-trip losslessly (a `Map`, a `bigint`, a `Date` you need back as a\n * `Date` rather than an ISO string).\n */\n serialize?: (value: ChatPersistedState) => string\n /** Defaults to `JSON.parse`. */\n deserialize?: (value: string) => ChatPersistedState\n}\n\nexport interface IndexedDBPersistenceOptions {\n databaseName?: string\n objectStoreName?: string\n keyPrefix?: string\n}\n\ntype StorageName = 'localStorage' | 'sessionStorage' | 'indexedDB'\n\n/**\n * Thrown by a storage adapter when its backing store is absent — most commonly\n * during server-side rendering, where `localStorage` / `sessionStorage` /\n * `indexedDB` do not exist on `globalThis`. The adapters check availability\n * lazily, **per operation**, so constructing an adapter never throws; the error\n * surfaces from `getItem` / `setItem` / `removeItem` (rejected promise for\n * IndexedDB). The chat persistence layer treats adapter failures as best-effort\n * (storage errors never break chat setup or streaming).\n */\nexport class StorageUnavailableError extends Error {\n constructor(storageName: StorageName) {\n super(`${storageName} is not available in this environment.`)\n this.name = 'StorageUnavailableError'\n }\n}\n\nfunction stringifyJson(value: ChatPersistedState): string {\n const stringify: (input: unknown) => unknown = JSON.stringify\n const serialized = stringify(value)\n if (typeof serialized !== 'string') {\n throw new TypeError('The value is not JSON serializable.')\n }\n return serialized\n}\n\nfunction reviveMessageCreatedAt(message: UIMessage): UIMessage {\n return normalizeMessagesDates([message]).at(0) ?? message\n}\n\nfunction revivePersistedState(state: ChatPersistedState): ChatPersistedState {\n if (state == null || typeof state !== 'object') return state\n if (!Array.isArray(state.messages)) return state\n return { ...state, messages: state.messages.map(reviveMessageCreatedAt) }\n}\n\nfunction createWebStoragePersistence(\n storageName: 'localStorage' | 'sessionStorage',\n options: WebStoragePersistenceOptions,\n): ChatStorageAdapter<ChatPersistedState> {\n const keyPrefix = options.keyPrefix ?? 'tanstack-ai:'\n const serialize = options.serialize ?? stringifyJson\n const deserialize = options.deserialize ?? JSON.parse\n const key = (id: string) => `${keyPrefix}${id}`\n\n const getStorage = (): Storage => {\n const browserGlobals: {\n localStorage?: Storage\n sessionStorage?: Storage\n } = globalThis\n const storage = browserGlobals[storageName]\n if (!storage) {\n throw new StorageUnavailableError(storageName)\n }\n return storage\n }\n\n return {\n getItem(id) {\n const item = getStorage().getItem(key(id))\n return item === null ? null : revivePersistedState(deserialize(item))\n },\n setItem(id, value) {\n getStorage().setItem(key(id), serialize(value))\n },\n removeItem(id) {\n getStorage().removeItem(key(id))\n },\n }\n}\n\n/**\n * A `ChatStorageAdapter` backed by `window.localStorage` (persists across\n * reloads and browser restarts). Keys are namespaced with `keyPrefix`, which\n * defaults to `tanstack-ai:`. Every operation reads `localStorage` lazily and\n * throws {@link StorageUnavailableError} when it is absent (e.g. SSR), so the\n * adapter can be constructed safely on the server.\n *\n * The `serialize` / `deserialize` codec defaults to `JSON.stringify` /\n * `JSON.parse`, so the common case needs no codec.\n */\nexport function localStoragePersistence(\n options: WebStoragePersistenceOptions = {},\n): ChatStorageAdapter<ChatPersistedState> {\n return createWebStoragePersistence('localStorage', options)\n}\n\n/**\n * A `ChatStorageAdapter` backed by `window.sessionStorage` (scoped to the tab\n * and cleared when it closes). Identical to {@link localStoragePersistence} in\n * every other respect: the `tanstack-ai:` default `keyPrefix`, lazy\n * per-operation {@link StorageUnavailableError} on SSR, and a JSON codec that\n * defaults to `JSON.stringify` / `JSON.parse`.\n */\nexport function sessionStoragePersistence(\n options: WebStoragePersistenceOptions = {},\n): ChatStorageAdapter<ChatPersistedState> {\n return createWebStoragePersistence('sessionStorage', options)\n}\n\n/**\n * A `ChatStorageAdapter` backed by IndexedDB, for values too large for Web\n * Storage or that benefit from structured-clone storage. All operations are\n * async and the database opens lazily on first use; keys are namespaced with\n * `keyPrefix` (default `tanstack-ai:`). When IndexedDB is unavailable (e.g.\n * SSR) each operation rejects with {@link StorageUnavailableError}.\n *\n * No serialize/deserialize codec is needed or accepted — values are stored via\n * IndexedDB's native structured clone, so `Date`, `Map`, `ArrayBuffer`, etc.\n * round-trip without a JSON step.\n */\nexport function indexedDBPersistence(\n options: IndexedDBPersistenceOptions = {},\n): ChatStorageAdapter<ChatPersistedState> {\n const databaseName = options.databaseName ?? 'tanstack-ai'\n const objectStoreName = options.objectStoreName ?? 'persistence'\n const keyPrefix = options.keyPrefix ?? 'tanstack-ai:'\n let databasePromise: Promise<IDBDatabase> | undefined\n\n const openDatabase = (): Promise<IDBDatabase> => {\n if (databasePromise) {\n return databasePromise\n }\n\n databasePromise = new Promise<IDBDatabase>((resolve, reject) => {\n const browserGlobals: { indexedDB?: IDBFactory } = globalThis\n const factory = browserGlobals.indexedDB\n if (!factory) {\n reject(new StorageUnavailableError('indexedDB'))\n return\n }\n\n let request: IDBOpenDBRequest\n let openFailed = false\n try {\n request = factory.open(databaseName)\n } catch (error) {\n reject(error)\n return\n }\n\n request.onupgradeneeded = () => {\n if (!request.result.objectStoreNames.contains(objectStoreName)) {\n request.result.createObjectStore(objectStoreName)\n }\n }\n request.onerror = () => {\n openFailed = true\n reject(request.error ?? new Error(`Failed to open ${databaseName}.`))\n }\n request.onblocked = () => {\n openFailed = true\n reject(\n new Error(\n `Opening IndexedDB database \"${databaseName}\" was blocked.`,\n ),\n )\n }\n request.onsuccess = () => {\n const database = request.result\n if (openFailed) {\n database.close()\n return\n }\n database.onversionchange = () => {\n database.close()\n databasePromise = undefined\n }\n resolve(database)\n }\n }).catch((error: unknown) => {\n databasePromise = undefined\n throw error\n })\n\n return databasePromise\n }\n\n const runRequest = async <TResult>(\n mode: IDBTransactionMode,\n createRequest: (store: IDBObjectStore) => IDBRequest<TResult>,\n ): Promise<TResult> => {\n const database = await openDatabase()\n return new Promise<TResult>((resolve, reject) => {\n let request: IDBRequest<TResult>\n let result: TResult\n try {\n const transaction = database.transaction(objectStoreName, mode)\n request = createRequest(transaction.objectStore(objectStoreName))\n request.onsuccess = () => {\n result = request.result\n }\n request.onerror = () => {\n reject(request.error ?? new Error('IndexedDB request failed.'))\n }\n transaction.oncomplete = () => {\n resolve(result)\n }\n transaction.onerror = () => {\n reject(\n transaction.error ?? new Error('IndexedDB transaction failed.'),\n )\n }\n transaction.onabort = () => {\n reject(\n transaction.error ?? new Error('IndexedDB transaction aborted.'),\n )\n }\n } catch (error) {\n reject(error)\n }\n })\n }\n\n const key = (id: string) => `${keyPrefix}${id}`\n return {\n getItem(id) {\n return runRequest('readonly', (store) => store.get(key(id)))\n },\n setItem(id, value) {\n return runRequest('readwrite', (store) => store.put(value, key(id))).then(\n () => undefined,\n )\n },\n removeItem(id) {\n return runRequest('readwrite', (store) => store.delete(key(id))).then(\n () => undefined,\n )\n },\n }\n}\n"],"mappings":"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"}