@witqq/agent-sdk 0.6.0 → 0.7.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 (122) hide show
  1. package/README.md +433 -6
  2. package/dist/auth/index.cjs +188 -1
  3. package/dist/auth/index.cjs.map +1 -1
  4. package/dist/auth/index.d.cts +154 -138
  5. package/dist/auth/index.d.ts +154 -138
  6. package/dist/auth/index.js +188 -2
  7. package/dist/auth/index.js.map +1 -1
  8. package/dist/backends/claude.cjs +341 -22
  9. package/dist/backends/claude.cjs.map +1 -1
  10. package/dist/backends/claude.d.cts +2 -1
  11. package/dist/backends/claude.d.ts +2 -1
  12. package/dist/backends/claude.js +341 -22
  13. package/dist/backends/claude.js.map +1 -1
  14. package/dist/backends/copilot.cjs +133 -25
  15. package/dist/backends/copilot.cjs.map +1 -1
  16. package/dist/backends/copilot.d.cts +2 -1
  17. package/dist/backends/copilot.d.ts +2 -1
  18. package/dist/backends/copilot.js +133 -25
  19. package/dist/backends/copilot.js.map +1 -1
  20. package/dist/backends/vercel-ai.cjs +66 -19
  21. package/dist/backends/vercel-ai.cjs.map +1 -1
  22. package/dist/backends/vercel-ai.d.cts +1 -1
  23. package/dist/backends/vercel-ai.d.ts +1 -1
  24. package/dist/backends/vercel-ai.js +66 -19
  25. package/dist/backends/vercel-ai.js.map +1 -1
  26. package/dist/chat/accumulator.cjs +147 -0
  27. package/dist/chat/accumulator.cjs.map +1 -0
  28. package/dist/chat/accumulator.d.cts +61 -0
  29. package/dist/chat/accumulator.d.ts +61 -0
  30. package/dist/chat/accumulator.js +145 -0
  31. package/dist/chat/accumulator.js.map +1 -0
  32. package/dist/chat/backends.cjs +3534 -0
  33. package/dist/chat/backends.cjs.map +1 -0
  34. package/dist/chat/backends.d.cts +62 -0
  35. package/dist/chat/backends.d.ts +62 -0
  36. package/dist/chat/backends.js +3501 -0
  37. package/dist/chat/backends.js.map +1 -0
  38. package/dist/chat/context.cjs +230 -0
  39. package/dist/chat/context.cjs.map +1 -0
  40. package/dist/chat/context.d.cts +167 -0
  41. package/dist/chat/context.d.ts +167 -0
  42. package/dist/chat/context.js +227 -0
  43. package/dist/chat/context.js.map +1 -0
  44. package/dist/chat/core.cjs +282 -0
  45. package/dist/chat/core.cjs.map +1 -0
  46. package/dist/chat/core.d.cts +435 -0
  47. package/dist/chat/core.d.ts +435 -0
  48. package/dist/chat/core.js +261 -0
  49. package/dist/chat/core.js.map +1 -0
  50. package/dist/chat/errors.cjs +251 -0
  51. package/dist/chat/errors.cjs.map +1 -0
  52. package/dist/chat/errors.d.cts +122 -0
  53. package/dist/chat/errors.d.ts +122 -0
  54. package/dist/chat/errors.js +243 -0
  55. package/dist/chat/errors.js.map +1 -0
  56. package/dist/chat/events.cjs +203 -0
  57. package/dist/chat/events.cjs.map +1 -0
  58. package/dist/chat/events.d.cts +241 -0
  59. package/dist/chat/events.d.ts +241 -0
  60. package/dist/chat/events.js +196 -0
  61. package/dist/chat/events.js.map +1 -0
  62. package/dist/chat/index.cjs +5359 -0
  63. package/dist/chat/index.cjs.map +1 -0
  64. package/dist/chat/index.d.cts +52 -0
  65. package/dist/chat/index.d.ts +52 -0
  66. package/dist/chat/index.js +5296 -0
  67. package/dist/chat/index.js.map +1 -0
  68. package/dist/chat/react.cjs +2739 -0
  69. package/dist/chat/react.cjs.map +1 -0
  70. package/dist/chat/react.d.cts +619 -0
  71. package/dist/chat/react.d.ts +619 -0
  72. package/dist/chat/react.js +2714 -0
  73. package/dist/chat/react.js.map +1 -0
  74. package/dist/chat/runtime.cjs +1030 -0
  75. package/dist/chat/runtime.cjs.map +1 -0
  76. package/dist/chat/runtime.d.cts +118 -0
  77. package/dist/chat/runtime.d.ts +118 -0
  78. package/dist/chat/runtime.js +1028 -0
  79. package/dist/chat/runtime.js.map +1 -0
  80. package/dist/chat/server.cjs +643 -0
  81. package/dist/chat/server.cjs.map +1 -0
  82. package/dist/chat/server.d.cts +287 -0
  83. package/dist/chat/server.d.ts +287 -0
  84. package/dist/chat/server.js +617 -0
  85. package/dist/chat/server.js.map +1 -0
  86. package/dist/chat/sessions.cjs +398 -0
  87. package/dist/chat/sessions.cjs.map +1 -0
  88. package/dist/chat/sessions.d.cts +239 -0
  89. package/dist/chat/sessions.d.ts +239 -0
  90. package/dist/chat/sessions.js +394 -0
  91. package/dist/chat/sessions.js.map +1 -0
  92. package/dist/chat/state.cjs +177 -0
  93. package/dist/chat/state.cjs.map +1 -0
  94. package/dist/chat/state.d.cts +92 -0
  95. package/dist/chat/state.d.ts +92 -0
  96. package/dist/chat/state.js +167 -0
  97. package/dist/chat/state.js.map +1 -0
  98. package/dist/chat/storage.cjs +240 -0
  99. package/dist/chat/storage.cjs.map +1 -0
  100. package/dist/chat/storage.d.cts +191 -0
  101. package/dist/chat/storage.d.ts +191 -0
  102. package/dist/chat/storage.js +236 -0
  103. package/dist/chat/storage.js.map +1 -0
  104. package/dist/errors-BDLbNu9w.d.cts +13 -0
  105. package/dist/errors-BDLbNu9w.d.ts +13 -0
  106. package/dist/in-process-transport-C2oPTYs6.d.ts +223 -0
  107. package/dist/in-process-transport-DG-w5G6k.d.cts +223 -0
  108. package/dist/index.cjs +25 -13
  109. package/dist/index.cjs.map +1 -1
  110. package/dist/index.d.cts +32 -4
  111. package/dist/index.d.ts +32 -4
  112. package/dist/index.js +25 -13
  113. package/dist/index.js.map +1 -1
  114. package/dist/transport-D1OaUgRk.d.ts +67 -0
  115. package/dist/transport-DX1Nhm4N.d.cts +67 -0
  116. package/dist/types-Bh5AhqD-.d.ts +141 -0
  117. package/dist/types-CGF7AEX1.d.cts +141 -0
  118. package/dist/{types-BvwNzZCj.d.cts → types-CqvUAYxt.d.cts} +21 -3
  119. package/dist/{types-BvwNzZCj.d.ts → types-CqvUAYxt.d.ts} +21 -3
  120. package/dist/types-DLZzlJxt.d.ts +39 -0
  121. package/dist/types-tE0CXwBl.d.cts +39 -0
  122. package/package.json +149 -2
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/chat/core.ts","../../src/chat/context.ts","../../src/errors.ts","../../src/chat/errors.ts","../../src/chat/state.ts","../../src/chat/accumulator.ts","../../src/chat/watchdog.ts","../../src/chat/runtime.ts"],"names":[],"mappings":"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","file":"runtime.js","sourcesContent":["/**\n * @witqq/agent-sdk/chat/core\n *\n * Foundational chat types and utilities: ChatMessage, ChatSession, ChatEvent,\n * IChatProvider, type guards, and AgentEvent↔ChatEvent bridge functions.\n */\n\nimport type {\n AgentEvent,\n Message,\n ToolCall,\n ToolResult,\n ToolDefinition,\n UsageData,\n ModelInfo,\n JSONValue,\n} from \"../types.js\";\n\n// ─── Unique ID ─────────────────────────────────────────────────\n\n/** Branded type for unique identifiers */\nexport type ChatId = string & { readonly __brand: \"ChatId\" };\n\n/**\n * Generate a new unique ChatId (crypto.randomUUID-based)\n * @returns Branded ChatId string\n */\nexport function createChatId(): ChatId {\n return crypto.randomUUID() as ChatId;\n}\n\n/** UUID v4 pattern for ChatId validation */\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/**\n * Cast a string to ChatId with UUID format validation.\n * Use this instead of manual `as ChatId` type assertions.\n *\n * @param value - String to validate and cast\n * @returns Branded ChatId\n * @throws {TypeError} If value is not a valid UUID v4 format\n *\n * @example\n * ```ts\n * const id = toChatId(\"550e8400-e29b-41d4-a716-446655440000\");\n * ```\n */\nexport function toChatId(value: string): ChatId {\n if (!UUID_RE.test(value)) {\n throw new TypeError(`Invalid ChatId: \"${value}\" is not a valid UUID`);\n }\n return value as ChatId;\n}\n\n/**\n * Accepts either a plain string or branded ChatId for API convenience.\n * Use this in public API signatures so consumers don't need `as ChatId` casts.\n */\nexport type ChatIdLike = string | ChatId;\n\n// ─── Status Types ──────────────────────────────────────────────\n\n/** Lifecycle status of a message part (text, reasoning, etc.) */\nexport type PartStatus = \"pending\" | \"streaming\" | \"complete\" | \"error\";\n/** Lifecycle status of a tool call within a message */\nexport type ToolCallStatus = \"pending\" | \"running\" | \"requires_approval\" | \"complete\" | \"error\" | \"denied\";\n/** Lifecycle status of an entire message */\nexport type MessageStatus = \"pending\" | \"streaming\" | \"complete\" | \"error\" | \"cancelled\";\n/** Lifecycle status of a chat session */\nexport type SessionStatus = \"active\" | \"archived\";\n/** Lifecycle status of the chat runtime */\nexport type RuntimeStatus = \"idle\" | \"streaming\" | \"error\" | \"disposed\";\n\n// ─── Message Parts (union) ─────────────────────────────────────\n\n/** Plain text content part */\nexport interface TextPart { type: \"text\"; text: string; status: PartStatus; }\n/** Model reasoning/thinking content part */\nexport interface ReasoningPart { type: \"reasoning\"; text: string; status: PartStatus; }\n/** Tool invocation part with call ID, arguments, optional result */\nexport interface ToolCallPart { type: \"tool_call\"; toolCallId: string; name: string; args: unknown; result?: unknown; status: ToolCallStatus; error?: string; }\n/** Source reference part (URL citation) */\nexport interface SourcePart { type: \"source\"; url: string; title?: string; status: PartStatus; }\n/** File attachment part (base64-encoded data) */\nexport interface FilePart { type: \"file\"; name: string; mimeType: string; data: string; status: PartStatus; }\n/** Union of all message part types */\nexport type MessagePart = TextPart | ReasoningPart | ToolCallPart | SourcePart | FilePart;\n\n// ─── Chat Message ──────────────────────────────────────────────\n\n/** Role of message author */\nexport type ChatRole = \"user\" | \"assistant\" | \"system\";\n\n/** Metadata attached to messages — useful preset for the TMetadata generic */\nexport interface ChatMessageMetadata {\n model?: string;\n backend?: string;\n usage?: UsageData;\n isSummary?: boolean;\n isArchived?: boolean;\n estimatedTokens?: number;\n custom?: Record<string, unknown>;\n}\n\n/** Message status */\nexport type ChatMessageStatus = MessageStatus;\n\n/** A single chat message — the fundamental unit of conversation */\nexport interface ChatMessage<TMetadata = unknown> {\n id: ChatId;\n role: ChatRole;\n parts: MessagePart[];\n metadata?: TMetadata;\n createdAt: string;\n updatedAt?: string;\n status: MessageStatus;\n}\n\n// ─── Convenience Getters ───────────────────────────────────────\n\n/**\n * Join all TextPart texts in a message\n * @param message - The chat message to extract text from\n * @returns Concatenated text content\n */\nexport function getMessageText(message: ChatMessage): string {\n return message.parts\n .filter((p): p is TextPart => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\");\n}\n\n/**\n * Filter all ToolCallParts from a message\n * @param message - The chat message to extract tool calls from\n * @returns Array of ToolCallPart\n */\nexport function getMessageToolCalls(message: ChatMessage): ToolCallPart[] {\n return message.parts.filter((p): p is ToolCallPart => p.type === \"tool_call\");\n}\n\n/**\n * Join all ReasoningPart texts in a message\n * @param message - The chat message to extract reasoning from\n * @returns Concatenated reasoning content\n */\nexport function getMessageReasoning(message: ChatMessage): string {\n return message.parts\n .filter((p): p is ReasoningPart => p.type === \"reasoning\")\n .map((p) => p.text)\n .join(\"\");\n}\n\n// ─── Supporting Types ──────────────────────────────────────────\n\n/** Options for sending a message */\nexport interface SendOpts { sessionId?: string; model?: string; signal?: AbortSignal; metadata?: Record<string, unknown>; }\n/** Options for creating a new session */\nexport interface CreateSessionOpts { id?: string; title?: string; model?: string; metadata?: Record<string, unknown>; }\n/** Options for listing sessions with pagination */\nexport interface ListOpts { limit?: number; offset?: number; status?: SessionStatus; }\n/** Options for backend execution (model, tokens, tools) */\nexport interface BackendOpts { model: string; signal?: AbortSignal; systemPrompt?: string; temperature?: number; maxTokens?: number; tools?: Record<string, unknown>; providerOptions?: Record<string, unknown>; }\n/** Context passed to tool execute functions */\nexport interface ToolContext { sessionId: string; userId?: string; signal: AbortSignal; }\n/** Configuration for creating a chat runtime */\nexport interface ChatRuntimeConfig { backend: string; model?: string; apiKey?: string; baseUrl?: string; context?: { maxTokens?: number; reserveTokens?: number; strategy?: \"sliding\" | \"summarize\" | \"truncate\"; }; retry?: { maxRetries?: number; initialDelay?: number; backoffFactor?: number; }; providerOptions?: Record<string, unknown>; }\n\n// ─── Chat Session ──────────────────────────────────────────────\n\n/** Session configuration snapshot */\nexport interface ChatSessionConfig {\n model: string;\n backend: string;\n systemPrompt?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\n/** Session metadata */\nexport interface ChatSessionMetadata<TCustom extends Record<string, unknown> = Record<string, unknown>> {\n messageCount: number;\n totalTokens: number;\n tags?: string[];\n custom?: TCustom;\n}\n\n/** Chat session — a conversation with ordered messages */\nexport interface ChatSession<TCustom extends Record<string, unknown> = Record<string, unknown>> {\n id: ChatId;\n title?: string;\n messages: ChatMessage[];\n config: ChatSessionConfig;\n metadata: ChatSessionMetadata<TCustom>;\n status: SessionStatus;\n createdAt: string;\n updatedAt: string;\n backendSessionId?: string;\n /** Subscribe to session changes (for React useSyncExternalStore) */\n subscribe?(callback: () => void): () => void;\n /** Get immutable snapshot of session state (for React useSyncExternalStore) */\n getSnapshot?(): ChatSession<TCustom>;\n /** Last message in the session */\n readonly lastMessage?: ChatMessage;\n}\n\n/** Lightweight session info for listing (without full message array) */\nexport interface SessionInfo {\n id: ChatId;\n title?: string;\n status: SessionStatus;\n messageCount: number;\n lastMessage?: ChatMessage;\n createdAt: string;\n updatedAt: string;\n}\n\n// ─── Chat Events ───────────────────────────────────────────────\n\n/** Events emitted during chat operation */\nexport type ChatEvent =\n | { type: \"message:start\"; messageId: ChatId; role: ChatRole }\n | { type: \"message:delta\"; messageId: ChatId; text: string }\n | { type: \"message:complete\"; messageId: ChatId; message: ChatMessage }\n | {\n type: \"tool:start\";\n messageId: ChatId;\n toolCallId: string;\n toolName: string;\n args: Record<string, unknown>;\n }\n | {\n type: \"tool:complete\";\n messageId: ChatId;\n toolCallId: string;\n toolName: string;\n result: unknown;\n isError?: boolean;\n }\n | { type: \"thinking:start\"; messageId: ChatId }\n | { type: \"thinking:delta\"; messageId: ChatId; text: string }\n | { type: \"thinking:end\"; messageId: ChatId }\n | {\n type: \"permission:request\";\n messageId: ChatId;\n toolName: string;\n toolArgs: Record<string, unknown>;\n }\n | {\n type: \"permission:response\";\n messageId: ChatId;\n toolName: string;\n allowed: boolean;\n }\n | {\n type: \"usage\";\n promptTokens: number;\n completionTokens: number;\n model?: string;\n }\n | { type: \"session:created\"; sessionId: ChatId }\n | { type: \"session:updated\"; sessionId: ChatId }\n | {\n type: \"error\";\n error: string;\n recoverable: boolean;\n messageId?: ChatId;\n }\n | { type: \"typing:start\" }\n | { type: \"typing:end\" }\n | { type: \"heartbeat\" }\n | { type: \"done\"; finalOutput?: string };\n\n/** All possible ChatEvent type strings */\nexport type ChatEventType = ChatEvent[\"type\"];\n\n// ─── Chat Middleware ───────────────────────────────────────────\n\n/** Context passed to ChatMiddleware hooks */\nexport interface ChatMiddlewareContext {\n sessionId: ChatId;\n signal: AbortSignal;\n}\n\n/** Runtime-level middleware for the send/receive lifecycle.\n * Different from EventMiddleware which operates at the event bus level. */\nexport interface ChatMiddleware {\n /** Transform message before sending to backend */\n onBeforeSend?(message: ChatMessage, context: ChatMiddlewareContext): ChatMessage | Promise<ChatMessage>;\n /** Transform/intercept stream events */\n onEvent?(event: ChatEvent, context: ChatMiddlewareContext): ChatEvent | null | Promise<ChatEvent | null>;\n /** Transform completed message after receiving from backend */\n onAfterReceive?(message: ChatMessage, context: ChatMiddlewareContext): ChatMessage | Promise<ChatMessage>;\n /** Intercept errors — return null to suppress, return error to propagate */\n onError?(error: Error, context: ChatMiddlewareContext): Error | null | Promise<Error | null>;\n}\n\n// ─── Chat Provider Abstraction ─────────────────────────────────\n\n/** Options for sending a message to a provider */\nexport interface SendMessageOptions {\n signal?: AbortSignal;\n model?: string;\n context?: Record<string, unknown>;\n /** Additional tools to include in this request */\n tools?: ToolDefinition[];\n}\n\n/** Abstract chat provider — wraps an IAgentService for chat use */\nexport interface IChatProvider {\n readonly name: string;\n sendMessage(\n session: ChatSession,\n message: string,\n options?: SendMessageOptions,\n ): Promise<ChatMessage>;\n streamMessage(\n session: ChatSession,\n message: string,\n options?: SendMessageOptions,\n ): AsyncIterable<ChatEvent>;\n listModels(): Promise<ModelInfo[]>;\n validate(): Promise<{ valid: boolean; errors: string[] }>;\n dispose(): Promise<void>;\n}\n\n// ─── Type Guards ───────────────────────────────────────────────\n\n/**\n * Check if a value is a ChatMessage\n * @param value - Value to check\n * @returns True if value has ChatMessage shape\n */\nexport function isChatMessage(value: unknown): value is ChatMessage {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.id === \"string\" &&\n typeof obj.role === \"string\" &&\n (obj.role === \"user\" ||\n obj.role === \"assistant\" ||\n obj.role === \"system\") &&\n Array.isArray(obj.parts) &&\n typeof obj.createdAt === \"string\" &&\n typeof obj.status === \"string\"\n );\n}\n\n/**\n * Check if a value is a ChatSession\n * @param value - Value to check\n * @returns True if value has ChatSession shape\n */\nexport function isChatSession(value: unknown): value is ChatSession {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.id === \"string\" &&\n Array.isArray(obj.messages) &&\n typeof obj.config === \"object\" &&\n obj.config !== null &&\n typeof obj.createdAt === \"string\" &&\n typeof obj.updatedAt === \"string\" &&\n typeof obj.status === \"string\"\n );\n}\n\n/**\n * Check if a value is a MessagePart\n * @param value - Value to check\n * @returns True if value has MessagePart shape\n */\nexport function isMessagePart(value: unknown): value is MessagePart {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.type === \"string\" &&\n (obj.type === \"text\" ||\n obj.type === \"reasoning\" ||\n obj.type === \"tool_call\" ||\n obj.type === \"source\" ||\n obj.type === \"file\")\n );\n}\n\n/**\n * Check if a value is a TextPart\n * @param value - Value to check\n * @returns True if value is a TextPart\n */\nexport function isTextPart(value: unknown): value is TextPart {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return obj.type === \"text\" && typeof obj.text === \"string\";\n}\n\n/**\n * Check if a value is a ToolCallPart\n * @param value - Value to check\n * @returns True if value is a ToolCallPart\n */\nexport function isToolCallPart(value: unknown): value is ToolCallPart {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return obj.type === \"tool_call\" && typeof obj.toolCallId === \"string\" && typeof obj.name === \"string\";\n}\n\n/**\n * Check if a value is a ReasoningPart\n * @param value - Value to check\n * @returns True if value is a ReasoningPart\n */\nexport function isReasoningPart(value: unknown): value is ReasoningPart {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return obj.type === \"reasoning\" && typeof obj.text === \"string\";\n}\n\n/**\n * Check if a value is a SourcePart\n * @param value - Value to check\n * @returns True if value is a SourcePart\n */\nexport function isSourcePart(value: unknown): value is SourcePart {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return obj.type === \"source\" && typeof obj.url === \"string\";\n}\n\n/**\n * Check if a value is a FilePart\n * @param value - Value to check\n * @returns True if value is a FilePart\n */\nexport function isFilePart(value: unknown): value is FilePart {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return obj.type === \"file\" && typeof obj.name === \"string\" && typeof obj.mimeType === \"string\";\n}\n\n/**\n * Check if a value is a ChatEvent\n * @param value - Value to check\n * @returns True if value has a valid ChatEvent type\n */\nexport function isChatEvent(value: unknown): value is ChatEvent {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n const validTypes: ChatEventType[] = [\n \"message:start\",\n \"message:delta\",\n \"message:complete\",\n \"tool:start\",\n \"tool:complete\",\n \"thinking:start\",\n \"thinking:delta\",\n \"thinking:end\",\n \"permission:request\",\n \"permission:response\",\n \"usage\",\n \"session:created\",\n \"session:updated\",\n \"error\",\n \"typing:start\",\n \"typing:end\",\n \"heartbeat\",\n \"done\",\n ];\n return validTypes.includes(obj.type as ChatEventType);\n}\n\n// ─── Agent Event Adapter ───────────────────────────────────────\n\n/**\n * Map a single AgentEvent to a ChatEvent (or null if no mapping)\n * @param event - The AgentEvent to convert\n * @param messageId - ChatId to associate with the event\n * @returns Corresponding ChatEvent or null if unmappable\n */\nexport function agentEventToChatEvent(\n event: AgentEvent,\n messageId: ChatId,\n): ChatEvent | null {\n switch (event.type) {\n case \"text_delta\":\n return { type: \"message:delta\", messageId, text: event.text };\n case \"thinking_start\":\n return { type: \"thinking:start\", messageId };\n case \"thinking_delta\":\n return { type: \"thinking:delta\", messageId, text: event.text };\n case \"thinking_end\":\n return { type: \"thinking:end\", messageId };\n case \"tool_call_start\":\n return {\n type: \"tool:start\",\n messageId,\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n args: event.args as Record<string, unknown>,\n };\n case \"tool_call_end\":\n return {\n type: \"tool:complete\",\n messageId,\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n result: event.result,\n };\n case \"permission_request\":\n return {\n type: \"permission:request\",\n messageId,\n toolName: event.request.toolName,\n toolArgs: event.request.toolArgs,\n };\n case \"permission_response\":\n return {\n type: \"permission:response\",\n messageId,\n toolName: event.toolName,\n allowed: event.decision.allowed,\n };\n case \"usage_update\":\n return {\n type: \"usage\",\n promptTokens: event.promptTokens,\n completionTokens: event.completionTokens,\n model: event.model,\n };\n case \"error\":\n return {\n type: \"error\",\n error: event.error,\n recoverable: event.recoverable,\n messageId,\n };\n case \"heartbeat\":\n return { type: \"heartbeat\" };\n case \"ask_user\":\n case \"ask_user_response\":\n case \"session_info\":\n case \"done\":\n return null;\n default:\n return null;\n }\n}\n\n/**\n * Convert AgentEvent async iterable to ChatEvent async iterable\n * @param events - Source agent events\n * @param messageId - ChatId to associate with converted events\n * @returns Async iterable of ChatEvent (nulls filtered out)\n */\nexport async function* adaptAgentEvents(\n events: AsyncIterable<AgentEvent>,\n messageId: ChatId,\n): AsyncIterable<ChatEvent> {\n for await (const event of events) {\n const chatEvent = agentEventToChatEvent(event, messageId);\n if (chatEvent !== null) {\n yield chatEvent;\n }\n }\n}\n\n/**\n * Map a ChatEvent back to an AgentEvent for accumulator consumption.\n * Returns null for events that don't map to accumulator-relevant AgentEvents\n * (e.g. message:start, message:complete, usage, permission:*, heartbeat).\n *\n * @param event - The ChatEvent to convert\n * @returns Corresponding AgentEvent or null if not accumulator-relevant\n */\nexport function chatEventToAgentEvent(event: ChatEvent): AgentEvent | null {\n switch (event.type) {\n case \"message:delta\":\n return { type: \"text_delta\", text: event.text };\n case \"thinking:start\":\n return { type: \"thinking_start\" };\n case \"thinking:delta\":\n return { type: \"thinking_delta\", text: event.text };\n case \"thinking:end\":\n return { type: \"thinking_end\" };\n case \"tool:start\":\n return {\n type: \"tool_call_start\",\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n args: event.args as JSONValue,\n };\n case \"tool:complete\":\n return {\n type: \"tool_call_end\",\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n result: event.result as JSONValue,\n };\n case \"error\":\n return { type: \"error\", error: event.error, recoverable: event.recoverable };\n default:\n return null;\n }\n}\n\n// ─── Message Conversion ────────────────────────────────────────\n\n/**\n * Convert a ChatMessage to agent-sdk Message format\n * @param message - The ChatMessage to convert\n * @returns agent-sdk Message\n */\nexport function toAgentMessage(message: ChatMessage): Message {\n const textContent = getMessageText(message);\n const toolCallParts = getMessageToolCalls(message);\n\n switch (message.role) {\n case \"user\":\n return { role: \"user\", content: textContent };\n case \"assistant\": {\n const toolCalls: ToolCall[] | undefined = toolCallParts.length > 0\n ? toolCallParts.map((p) => ({ id: p.toolCallId, name: p.name, args: p.args as JSONValue }))\n : undefined;\n return {\n role: \"assistant\",\n content: textContent,\n toolCalls,\n };\n }\n case \"system\":\n return { role: \"system\", content: textContent };\n }\n}\n\n/**\n * Convert an agent-sdk Message to ChatMessage\n * @param message - The agent-sdk Message to convert\n * @param id - Optional ChatId (auto-generated if omitted)\n * @returns ChatMessage with status \"complete\"\n */\nexport function fromAgentMessage(message: Message, id?: ChatId): ChatMessage {\n const chatId = id ?? createChatId();\n const now = new Date().toISOString();\n\n const parts: MessagePart[] = [];\n\n // Build text content\n const textContent =\n typeof message.content === \"string\"\n ? message.content\n : Array.isArray(message.content)\n ? message.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\\n\")\n : (message.content ?? \"\");\n\n if (textContent) {\n parts.push({ type: \"text\", text: textContent, status: \"complete\" });\n }\n\n // Add tool calls from assistant messages\n if (message.role === \"assistant\" && message.toolCalls) {\n for (const tc of message.toolCalls) {\n parts.push({\n type: \"tool_call\",\n toolCallId: tc.id,\n name: tc.name,\n args: tc.args,\n status: \"complete\",\n });\n }\n }\n\n // Add tool results — map 'tool' role to 'assistant'\n if (message.role === \"tool\" && message.toolResults) {\n for (const tr of message.toolResults) {\n parts.push({\n type: \"tool_call\",\n toolCallId: tr.toolCallId,\n name: tr.name,\n args: {},\n result: tr.result,\n status: \"complete\",\n });\n }\n }\n\n // Ensure at least an empty text part for empty messages\n if (parts.length === 0) {\n parts.push({ type: \"text\", text: \"\", status: \"complete\" });\n }\n\n const role: ChatRole = message.role === \"tool\" ? \"assistant\" : message.role;\n\n return {\n id: chatId,\n role,\n parts,\n createdAt: now,\n status: \"complete\",\n };\n}\n\n/**\n * Extract ToolResults from ToolCallParts that have results\n * @param message - The ChatMessage to extract results from\n * @returns Array of ToolResult for completed tool calls\n */\nexport function extractToolResults(message: ChatMessage): ToolResult[] {\n return getMessageToolCalls(message)\n .filter((p) => p.result !== undefined)\n .map((p) => ({\n toolCallId: p.toolCallId,\n name: p.name,\n result: p.result as JSONValue,\n isError: p.status === \"error\" ? true : undefined,\n }));\n}\n","/**\n * @witqq/agent-sdk/chat/context\n *\n * Context window manager for selecting which messages fit within a token budget.\n * Stateless: takes messages in, returns trimmed messages out.\n * Three overflow strategies: truncate-oldest, sliding-window, summarize-placeholder.\n */\n\nimport type { ChatMessage, MessagePart } from \"./core.js\";\n\n// ─── Token Estimation ──────────────────────────────────────────\n\n/**\n * Options for token estimation.\n */\nexport interface TokenEstimationOptions {\n /**\n * Characters per token ratio.\n * Lower = more conservative (fewer messages fit).\n * @default 4\n */\n charsPerToken?: number;\n}\n\n/**\n * Estimate token count for a single chat message.\n * Uses character-based heuristic: `Math.ceil(charCount / charsPerToken)`.\n *\n * Counts:\n * - Text content (string or text parts)\n * - Serialized tool calls and tool results\n * - Thinking blocks\n * - Role overhead (~4 tokens)\n *\n * @param message - Chat message to estimate\n * @param options - Estimation options\n * @returns Estimated token count\n *\n * @example\n * ```typescript\n * const tokens = estimateTokens(message);\n * const conservative = estimateTokens(message, { charsPerToken: 3 });\n * ```\n */\nexport function estimateTokens(\n message: ChatMessage,\n options?: TokenEstimationOptions,\n): number {\n const ratio = options?.charsPerToken ?? 4;\n let charCount = 0;\n\n // Role overhead\n charCount += message.role.length + 4;\n\n // Parts\n for (const part of message.parts) {\n charCount += estimatePartChars(part);\n }\n\n return Math.ceil(charCount / ratio);\n}\n\nfunction estimatePartChars(part: MessagePart): number {\n switch (part.type) {\n case \"text\":\n return part.text.length;\n case \"reasoning\":\n return part.text.length;\n case \"tool_call\":\n return JSON.stringify(part.args).length + part.name.length + 20 +\n (part.result !== undefined ? JSON.stringify(part.result).length : 0);\n case \"source\":\n return (part.title?.length ?? 0) + part.url.length + 10;\n case \"file\":\n return part.name.length + part.data.length + 20;\n }\n}\n\n// ─── Overflow Strategies ───────────────────────────────────────\n\n/** Overflow strategy type */\nexport type OverflowStrategy =\n | \"truncate-oldest\"\n | \"sliding-window\"\n | \"summarize-placeholder\";\n\n// ─── Context Window Configuration ──────────────────────────────\n\n/**\n * Async summarizer function for the summarize-placeholder strategy.\n * Receives removed messages and returns a summary string.\n * When configured, replaces the static placeholder text with actual summary.\n */\nexport type ContextSummarizer = (removedMessages: readonly ChatMessage[]) => Promise<string>;\n\n/**\n * Configuration for the context window manager.\n */\nexport interface ContextWindowConfig {\n /** Maximum token budget for the context window */\n maxTokens: number;\n\n /**\n * Tokens reserved for system prompt and response generation.\n * Subtracted from maxTokens to get available budget.\n * @default 0\n */\n reservedTokens?: number;\n\n /**\n * Strategy for handling overflow when messages exceed budget.\n * @default \"truncate-oldest\"\n */\n strategy?: OverflowStrategy;\n\n /**\n * Token estimation options.\n */\n estimation?: TokenEstimationOptions;\n\n /**\n * Optional async summarizer for the summarize-placeholder strategy.\n * When provided, replaces the static placeholder with a generated summary.\n * Falls back to static placeholder if summarizer throws.\n */\n summarizer?: ContextSummarizer;\n}\n\n// ─── Context Window Result ─────────────────────────────────────\n\n/**\n * Result of context window trimming.\n */\nexport interface ContextWindowResult {\n /** Messages that fit within the budget */\n messages: ChatMessage[];\n /** Total estimated tokens for included messages */\n totalTokens: number;\n /** Number of messages removed */\n removedCount: number;\n /** Whether any messages were truncated */\n wasTruncated: boolean;\n}\n\n// ─── Context Stats ─────────────────────────────────────────────\n\n/**\n * Context usage statistics for a session.\n * Returned by `IChatRuntime.getContextStats()`.\n */\nexport interface ContextStats {\n /** Estimated total tokens in the trimmed context */\n totalTokens: number;\n /** Number of messages removed by trimming */\n removedCount: number;\n /** Whether context was truncated */\n wasTruncated: boolean;\n /** Available token budget (maxTokens − reservedTokens) */\n availableBudget: number;\n}\n\n// ─── Context Window Manager ────────────────────────────────────\n\n/**\n * Stateless context window manager.\n * Takes messages and returns the subset that fits within a token budget.\n *\n * @example\n * ```typescript\n * const manager = new ContextWindowManager({\n * maxTokens: 4096,\n * reservedTokens: 500,\n * strategy: \"sliding-window\",\n * });\n *\n * const result = manager.fitMessages(messages);\n * // result.messages — trimmed to fit budget\n * // result.totalTokens — estimated token usage\n * // result.wasTruncated — whether messages were removed\n * ```\n */\nexport class ContextWindowManager {\n private readonly config: Required<\n Pick<ContextWindowConfig, \"maxTokens\" | \"reservedTokens\" | \"strategy\">\n > &\n Pick<ContextWindowConfig, \"estimation\" | \"summarizer\">;\n\n constructor(config: ContextWindowConfig) {\n this.config = {\n maxTokens: config.maxTokens,\n reservedTokens: config.reservedTokens ?? 0,\n strategy: config.strategy ?? \"truncate-oldest\",\n estimation: config.estimation,\n summarizer: config.summarizer,\n };\n }\n\n /** Available token budget after reserving tokens */\n get availableBudget(): number {\n return Math.max(0, this.config.maxTokens - this.config.reservedTokens);\n }\n\n /**\n * Estimate tokens for a single message.\n * @param message - Message to estimate\n * @returns Estimated token count\n */\n estimateMessageTokens(message: ChatMessage): number {\n return estimateTokens(message, this.config.estimation);\n }\n\n /**\n * Fit messages within the token budget using the configured strategy.\n * @param messages - All messages to consider\n * @returns Result with fitted messages and metadata\n */\n fitMessages(messages: readonly ChatMessage[]): ContextWindowResult {\n if (messages.length === 0) {\n return { messages: [], totalTokens: 0, removedCount: 0, wasTruncated: false };\n }\n\n const budget = this.availableBudget;\n\n // Calculate tokens for each message\n const tokenCounts = messages.map((m) => this.estimateMessageTokens(m));\n const totalTokens = tokenCounts.reduce((a, b) => a + b, 0);\n\n // All messages fit\n if (totalTokens <= budget) {\n return {\n messages: [...messages],\n totalTokens,\n removedCount: 0,\n wasTruncated: false,\n };\n }\n\n switch (this.config.strategy) {\n case \"truncate-oldest\":\n return this.truncateOldest(messages, tokenCounts, budget);\n case \"sliding-window\":\n return this.slidingWindow(messages, tokenCounts, budget);\n case \"summarize-placeholder\":\n return this.summarizePlaceholder(messages, tokenCounts, budget);\n }\n }\n\n /**\n * Async variant of fitMessages that supports async summarization.\n * When strategy is \"summarize-placeholder\" and a summarizer is configured,\n * calls the summarizer with removed messages and replaces the placeholder text.\n * Falls back to static placeholder if summarizer throws.\n * For other strategies, behaves identically to fitMessages().\n */\n async fitMessagesAsync(messages: readonly ChatMessage[]): Promise<ContextWindowResult> {\n const result = this.fitMessages(messages);\n\n // Only enhance if summarize-placeholder strategy, messages were removed, and summarizer is configured\n if (\n this.config.strategy !== \"summarize-placeholder\" ||\n !result.wasTruncated ||\n !this.config.summarizer\n ) {\n return result;\n }\n\n // Find removed messages (those in original but not in result)\n const keptIds = new Set(result.messages.map(m => m.id));\n const removed = messages.filter(m => !keptIds.has(m.id));\n if (removed.length === 0) return result;\n\n // Call async summarizer, fall back to static placeholder on error\n let summaryText: string;\n try {\n summaryText = await this.config.summarizer(removed);\n } catch {\n return result; // Keep static placeholder on summarizer failure\n }\n\n // Replace placeholder text with summarizer output\n const updatedMessages = result.messages.map(m => {\n if ((m.metadata as Record<string, unknown>)?.isSummary === true) {\n return {\n ...m,\n parts: [{ type: \"text\" as const, text: summaryText, status: \"complete\" as const }],\n };\n }\n return m;\n });\n\n return { ...result, messages: updatedMessages };\n }\n\n /**\n * Truncate oldest: keeps system messages, removes oldest non-system messages first.\n * Always keeps the most recent user message.\n */\n private truncateOldest(\n messages: readonly ChatMessage[],\n tokenCounts: number[],\n budget: number,\n ): ContextWindowResult {\n // Separate system messages (always kept) and non-system\n const systemIndices: number[] = [];\n const nonSystemIndices: number[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role === \"system\") {\n systemIndices.push(i);\n } else {\n nonSystemIndices.push(i);\n }\n }\n\n // System messages cost\n let usedTokens = systemIndices.reduce(\n (sum, i) => sum + tokenCounts[i],\n 0,\n );\n\n // If system messages alone exceed budget, still include them\n // (caller should configure reservedTokens properly)\n\n // Try to fit non-system from newest to oldest\n const includedNonSystem: number[] = [];\n for (let i = nonSystemIndices.length - 1; i >= 0; i--) {\n const idx = nonSystemIndices[i];\n if (usedTokens + tokenCounts[idx] <= budget) {\n includedNonSystem.unshift(idx);\n usedTokens += tokenCounts[idx];\n }\n }\n\n // Build result preserving original order\n const includedSet = new Set([...systemIndices, ...includedNonSystem]);\n const result: ChatMessage[] = [];\n let resultTokens = 0;\n for (let i = 0; i < messages.length; i++) {\n if (includedSet.has(i)) {\n result.push(messages[i]);\n resultTokens += tokenCounts[i];\n }\n }\n\n return {\n messages: result,\n totalTokens: resultTokens,\n removedCount: messages.length - result.length,\n wasTruncated: true,\n };\n }\n\n /**\n * Sliding window: keeps the most recent messages that fit within budget.\n */\n private slidingWindow(\n messages: readonly ChatMessage[],\n tokenCounts: number[],\n budget: number,\n ): ContextWindowResult {\n const result: ChatMessage[] = [];\n let usedTokens = 0;\n\n // Walk from newest to oldest\n for (let i = messages.length - 1; i >= 0; i--) {\n if (usedTokens + tokenCounts[i] <= budget) {\n result.unshift(messages[i]);\n usedTokens += tokenCounts[i];\n } else {\n break;\n }\n }\n\n return {\n messages: result,\n totalTokens: usedTokens,\n removedCount: messages.length - result.length,\n wasTruncated: true,\n };\n }\n\n /**\n * Summarize placeholder: replaces truncated messages with a placeholder,\n * preserving system messages and recent context.\n */\n private summarizePlaceholder(\n messages: readonly ChatMessage[],\n tokenCounts: number[],\n budget: number,\n ): ContextWindowResult {\n // First, identify system messages and recent messages\n const systemMessages: { msg: ChatMessage; tokens: number }[] = [];\n const nonSystem: { msg: ChatMessage; tokens: number; idx: number }[] = [];\n\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role === \"system\") {\n systemMessages.push({ msg: messages[i], tokens: tokenCounts[i] });\n } else {\n nonSystem.push({ msg: messages[i], tokens: tokenCounts[i], idx: i });\n }\n }\n\n // System message cost\n let usedTokens = systemMessages.reduce((s, m) => s + m.tokens, 0);\n\n // Placeholder costs ~20 tokens\n const placeholderTokens = 20;\n usedTokens += placeholderTokens;\n\n // Fit recent non-system messages from newest\n const recentKept: typeof nonSystem = [];\n for (let i = nonSystem.length - 1; i >= 0; i--) {\n if (usedTokens + nonSystem[i].tokens <= budget) {\n recentKept.unshift(nonSystem[i]);\n usedTokens += nonSystem[i].tokens;\n } else {\n break;\n }\n }\n\n const removedCount =\n messages.length -\n systemMessages.length -\n recentKept.length;\n\n // Build result: system messages, placeholder, recent messages\n const result: ChatMessage[] = [];\n\n // System messages first\n for (const sm of systemMessages) {\n result.push(sm.msg);\n }\n\n // Placeholder if messages were removed\n if (removedCount > 0) {\n result.push({\n id: \"context-placeholder\" as ChatMessage[\"id\"],\n role: \"system\",\n parts: [{ type: \"text\", text: `[${removedCount} earlier message${removedCount === 1 ? \"\" : \"s\"} omitted for context window]`, status: \"complete\" as const }],\n metadata: { isSummary: true },\n createdAt: new Date().toISOString(),\n status: \"complete\",\n });\n }\n\n // Recent messages\n for (const m of recentKept) {\n result.push(m.msg);\n }\n\n return {\n messages: result,\n totalTokens: usedTokens,\n removedCount,\n wasTruncated: true,\n };\n }\n}\n","/** Base error class for agent-sdk.\n *\n * Use `AgentSDKError.is(err)` for reliable cross-module `instanceof` checks\n * (works across separately bundled entry points where `instanceof` may fail). */\nexport class AgentSDKError extends Error {\n /** @internal Marker for cross-bundle identity checks */\n readonly _agentSDKError = true as const;\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"AgentSDKError\";\n }\n\n /** Check if an error is an AgentSDKError (works across bundled copies) */\n static is(error: unknown): error is AgentSDKError {\n return (\n error instanceof Error &&\n \"_agentSDKError\" in error &&\n (error as AgentSDKError)._agentSDKError === true\n );\n }\n}\n\n/** Thrown when agent.run() is called while already running (M8 re-entrancy guard) */\nexport class ReentrancyError extends AgentSDKError {\n constructor() {\n super(\"Agent is already running. Await the current run before starting another.\");\n this.name = \"ReentrancyError\";\n }\n}\n\n/** Thrown when an operation is attempted on a disposed agent/service */\nexport class DisposedError extends AgentSDKError {\n constructor(entity: string) {\n super(`${entity} has been disposed and cannot be used.`);\n this.name = \"DisposedError\";\n }\n}\n\n/** Thrown when a backend is not found in the registry */\nexport class BackendNotFoundError extends AgentSDKError {\n constructor(backend: string) {\n super(\n `Unknown backend: \"${backend}\". ` +\n `Built-in: copilot, claude, vercel-ai. ` +\n `Custom: use registerBackend() first.`,\n );\n this.name = \"BackendNotFoundError\";\n }\n}\n\n/** Thrown when a backend is already registered */\nexport class BackendAlreadyRegisteredError extends AgentSDKError {\n constructor(backend: string) {\n super(`Backend \"${backend}\" is already registered. Use a different name or unregister first.`);\n this.name = \"BackendAlreadyRegisteredError\";\n }\n}\n\n/** Thrown when subprocess management fails */\nexport class SubprocessError extends AgentSDKError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"SubprocessError\";\n }\n}\n\n/** Thrown when a required peer dependency is not installed */\nexport class DependencyError extends AgentSDKError {\n public readonly packageName: string;\n\n constructor(packageName: string) {\n super(`${packageName} is not installed. Install it: npm install ${packageName}`);\n this.name = \"DependencyError\";\n this.packageName = packageName;\n }\n}\n\n/** Thrown when an agent run is aborted */\nexport class AbortError extends AgentSDKError {\n constructor() {\n super(\"Agent run was aborted.\");\n this.name = \"AbortError\";\n }\n}\n\n/** Thrown when a tool execution fails */\nexport class ToolExecutionError extends AgentSDKError {\n public readonly toolName: string;\n\n constructor(toolName: string, message: string, options?: ErrorOptions) {\n super(`Tool \"${toolName}\" failed: ${message}`, options);\n this.name = \"ToolExecutionError\";\n this.toolName = toolName;\n }\n}\n\n/** Thrown when structured output parsing fails */\nexport class StructuredOutputError extends AgentSDKError {\n constructor(message: string, options?: ErrorOptions) {\n super(`Structured output error: ${message}`, options);\n this.name = \"StructuredOutputError\";\n }\n}\n","/**\n * @witqq/agent-sdk/chat/errors\n *\n * Flat error taxonomy with ChatErrorCode enum, unified ChatError class,\n * pattern-matching classifier, retry strategies with exponential backoff.\n * Extends the existing AgentSDKError from @witqq/agent-sdk.\n */\n\nimport { AgentSDKError } from \"../errors.js\";\n\n// ─── Error Code Enum ───────────────────────────────────────────\n\n/** Error codes for chat-specific errors — used by classifyError() and ChatError */\nexport enum ChatErrorCode {\n NETWORK = \"NETWORK\",\n TIMEOUT = \"TIMEOUT\",\n AUTH_EXPIRED = \"AUTH_EXPIRED\",\n AUTH_INVALID = \"AUTH_INVALID\",\n RATE_LIMIT = \"RATE_LIMIT\",\n PROVIDER_ERROR = \"PROVIDER_ERROR\",\n MODEL_NOT_FOUND = \"MODEL_NOT_FOUND\",\n MODEL_OVERLOADED = \"MODEL_OVERLOADED\",\n CONTEXT_OVERFLOW = \"CONTEXT_OVERFLOW\",\n INVALID_INPUT = \"INVALID_INPUT\",\n INVALID_RESPONSE = \"INVALID_RESPONSE\",\n PERMISSION_DENIED = \"PERMISSION_DENIED\",\n BACKEND_NOT_INSTALLED = \"BACKEND_NOT_INSTALLED\",\n SESSION_NOT_FOUND = \"SESSION_NOT_FOUND\",\n STORAGE_ERROR = \"STORAGE_ERROR\",\n SESSION_EXPIRED = \"SESSION_EXPIRED\",\n DISPOSED = \"DISPOSED\",\n ABORTED = \"ABORTED\",\n INVALID_TRANSITION = \"INVALID_TRANSITION\",\n REENTRANCY = \"REENTRANCY\",\n}\n\n// ─── Error Options ─────────────────────────────────────────────\n\n/** Options for constructing a ChatError */\nexport interface ChatErrorOptions {\n /** Machine-readable error code */\n code: ChatErrorCode;\n /** Whether this error is retryable (default: false) */\n retryable?: boolean;\n /** Retry delay hint in milliseconds */\n retryAfter?: number;\n /** Original cause, if wrapping another error */\n cause?: unknown;\n}\n\n/** @deprecated Use ChatErrorOptions */\nexport type ChatSDKErrorOptions = ChatErrorOptions;\n\n// ─── Unified Error Class ───────────────────────────────────────\n\n/** Unified error class for all chat SDK errors */\nexport class ChatError extends AgentSDKError {\n readonly code: ChatErrorCode;\n readonly retryable: boolean;\n readonly retryAfter?: number;\n readonly timestamp: string;\n\n constructor(message: string, options: ChatErrorOptions) {\n super(message, { cause: options.cause });\n this.name = \"ChatError\";\n this.code = options.code;\n this.retryable = options.retryable ?? false;\n this.retryAfter = options.retryAfter;\n this.timestamp = new Date().toISOString();\n }\n}\n\n/** @deprecated Use ChatError */\nexport { ChatError as ChatSDKError };\n\n// ─── Classification ────────────────────────────────────────────\n\n/**\n * Classify an unknown thrown value into a ChatError with the appropriate code.\n * Pattern-matches against common error shapes:\n * - Already a ChatError → returned as-is\n * - Fetch/network errors (ECONNREFUSED, ETIMEDOUT, etc.)\n * - HTTP status codes (401→AUTH_INVALID, 429→RATE_LIMIT, 5xx→PROVIDER_ERROR)\n * - Timeout patterns\n * - Zod validation errors\n * - Context overflow patterns\n * - Unknown → wrapped as ChatError with PROVIDER_ERROR\n *\n * @param error - The thrown value to classify\n * @returns ChatError with appropriate error code and retryable flag\n */\nexport function classifyError(error: unknown): ChatError {\n if (error instanceof ChatError) {\n return error;\n }\n\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n\n // Network errors\n if (isNetworkError(msg)) {\n return new ChatError(error.message, {\n code: ChatErrorCode.NETWORK,\n retryable: true,\n cause: error,\n });\n }\n\n // Timeout errors\n if (isTimeoutPattern(msg)) {\n return new ChatError(error.message, {\n code: ChatErrorCode.TIMEOUT,\n retryable: true,\n cause: error,\n });\n }\n\n // Zod validation errors\n if (isZodError(error)) {\n return new ChatError(error.message, {\n code: ChatErrorCode.INVALID_INPUT,\n retryable: false,\n cause: error,\n });\n }\n\n // HTTP status code errors\n const statusCode = extractStatusCode(error);\n if (statusCode !== null) {\n return classifyByStatusCode(statusCode, error);\n }\n\n // Context overflow patterns\n if (isContextOverflow(msg)) {\n return new ChatError(error.message, {\n code: ChatErrorCode.CONTEXT_OVERFLOW,\n retryable: false,\n cause: error,\n });\n }\n }\n\n // Unknown errors\n const message =\n error instanceof Error ? error.message : String(error);\n return new ChatError(message, {\n code: ChatErrorCode.PROVIDER_ERROR,\n retryable: false,\n cause: error,\n });\n}\n\n// ─── Classification Helpers ────────────────────────────────────\n\nconst NETWORK_PATTERNS = [\n \"econnrefused\",\n \"econnreset\",\n \"enotfound\",\n \"etimedout\",\n \"enetunreach\",\n \"epipe\",\n \"fetch failed\",\n \"network error\",\n \"network request failed\",\n \"failed to fetch\",\n \"dns lookup failed\",\n] as const;\n\nfunction isNetworkError(msg: string): boolean {\n return NETWORK_PATTERNS.some((p) => msg.includes(p));\n}\n\nfunction isTimeoutPattern(msg: string): boolean {\n return (\n msg.includes(\"timeout\") ||\n msg.includes(\"timed out\") ||\n msg.includes(\"deadline exceeded\") ||\n msg.includes(\"aborted due to timeout\")\n );\n}\n\nfunction isZodError(error: Error): boolean {\n return (\n error.name === \"ZodError\" ||\n (\"issues\" in error && Array.isArray((error as unknown as Record<string, unknown>).issues))\n );\n}\n\nfunction extractStatusCode(error: Error): number | null {\n const errRecord = error as unknown as Record<string, unknown>;\n if (typeof errRecord.status === \"number\") return errRecord.status;\n if (typeof errRecord.statusCode === \"number\") return errRecord.statusCode;\n\n // Check message for HTTP status codes\n const match = error.message.match(/\\b(4\\d{2}|5\\d{2})\\b/);\n return match ? parseInt(match[1], 10) : null;\n}\n\nfunction classifyByStatusCode(status: number, error: Error): ChatError {\n if (status === 401 || status === 403) {\n return new ChatError(error.message, {\n code: ChatErrorCode.AUTH_INVALID,\n retryable: false,\n cause: error,\n });\n }\n if (status === 429) {\n const retryAfterSeconds = extractRetryAfter(error);\n return new ChatError(error.message, {\n code: ChatErrorCode.RATE_LIMIT,\n retryable: true,\n retryAfter: retryAfterSeconds != null ? retryAfterSeconds * 1000 : undefined,\n cause: error,\n });\n }\n if (status >= 500) {\n return new ChatError(error.message, {\n code: ChatErrorCode.PROVIDER_ERROR,\n retryable: true,\n cause: error,\n });\n }\n // 4xx other than auth/rate-limit → invalid input\n if (status >= 400 && status < 500) {\n return new ChatError(error.message, {\n code: ChatErrorCode.INVALID_INPUT,\n retryable: false,\n cause: error,\n });\n }\n return new ChatError(error.message, {\n code: ChatErrorCode.NETWORK,\n retryable: true,\n cause: error,\n });\n}\n\nfunction extractRetryAfter(error: Error): number | undefined {\n const errRecord = error as unknown as Record<string, unknown>;\n if (typeof errRecord.retryAfter === \"number\") return errRecord.retryAfter;\n const match = error.message.match(/retry.after[:\\s]*(\\d+)/i);\n return match ? parseInt(match[1], 10) : undefined;\n}\n\nfunction isContextOverflow(msg: string): boolean {\n return (\n msg.includes(\"context length exceeded\") ||\n msg.includes(\"maximum context length\") ||\n msg.includes(\"context window\") ||\n msg.includes(\"token limit\") ||\n msg.includes(\"too many tokens\")\n );\n}\n\n// ─── Retry Strategy ────────────────────────────────────────────\n\n/** Strategy for computing retry delays */\nexport interface RetryStrategy {\n /** Return delay in ms for the given attempt (0-based), or null to stop */\n nextDelay(attempt: number, error: ChatError): number | null;\n}\n\n/** Options for ExponentialBackoffStrategy */\nexport interface ExponentialBackoffOptions {\n /** Base delay in ms (default: 1000) */\n baseMs?: number;\n /** Maximum delay in ms (default: 30000) */\n maxMs?: number;\n /** Maximum number of attempts (default: 3) */\n maxAttempts?: number;\n /** Jitter factor 0–1 (default: 0.1) */\n jitter?: number;\n}\n\n/** Exponential backoff with optional jitter */\nexport class ExponentialBackoffStrategy implements RetryStrategy {\n private readonly baseMs: number;\n private readonly maxMs: number;\n private readonly maxAttempts: number;\n private readonly jitter: number;\n\n constructor(options?: ExponentialBackoffOptions) {\n this.baseMs = options?.baseMs ?? 1000;\n this.maxMs = options?.maxMs ?? 30000;\n this.maxAttempts = options?.maxAttempts ?? 3;\n this.jitter = Math.max(0, Math.min(1, options?.jitter ?? 0.1));\n }\n\n nextDelay(attempt: number, error: ChatError): number | null {\n if (attempt >= this.maxAttempts) return null;\n if (!error.retryable) return null;\n\n // Rate-limit errors with retryAfter (already in ms) take priority\n if (error.code === ChatErrorCode.RATE_LIMIT && error.retryAfter) {\n return error.retryAfter;\n }\n\n const delay = Math.min(this.baseMs * Math.pow(2, attempt), this.maxMs);\n const jitterAmount = delay * this.jitter * (Math.random() * 2 - 1);\n return Math.max(0, Math.round(delay + jitterAmount));\n }\n}\n\n// ─── Retry Execution ───────────────────────────────────────────\n\n/** Options for withRetry execution */\nexport interface RetryOptions {\n /** Abort signal to cancel retries */\n signal?: AbortSignal;\n /** Called before each retry with the error and delay */\n onRetry?: (error: ChatError, attempt: number, delayMs: number) => void;\n}\n\n/**\n * Execute an async function with automatic retries using the provided strategy.\n * Respects ChatError.retryable and ChatError.retryAfter.\n * Classifies non-ChatError errors before deciding on retry.\n *\n * @param fn - Async function to execute\n * @param strategy - Retry strategy providing delay calculations\n * @param options - Optional abort signal and retry callback\n * @returns Result of fn on success\n * @throws ChatError when all retries exhausted or error is non-retryable\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n strategy: RetryStrategy,\n options?: RetryOptions,\n): Promise<T> {\n let attempt = 0;\n\n for (;;) {\n try {\n return await fn();\n } catch (raw) {\n const error = classifyError(raw);\n const delay = strategy.nextDelay(attempt, error);\n\n if (delay === null) {\n throw error;\n }\n\n if (options?.signal?.aborted) {\n throw error;\n }\n\n options?.onRetry?.(error, attempt, delay);\n\n await sleep(delay, options?.signal);\n attempt++;\n }\n }\n}\n\n/**\n * Type guard: check if an error is retryable\n * @param error - The error to check\n * @returns True if error is a retryable ChatError\n */\nexport function isRetryable(error: unknown): boolean {\n if (error instanceof ChatError) {\n return error.retryable;\n }\n const classified = classifyError(error);\n return classified.retryable;\n}\n\n// ─── Internal Helpers ──────────────────────────────────────────\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(new ChatError(\"Retry aborted\", { code: ChatErrorCode.ABORTED }));\n return;\n }\n\n const timer = setTimeout(resolve, ms);\n\n signal?.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(new ChatError(\"Retry aborted\", { code: ChatErrorCode.ABORTED }));\n },\n { once: true },\n );\n });\n}\n","/**\n * @witqq/agent-sdk/chat/state\n *\n * Validated state machines for runtime, message, and tool-call lifecycles.\n * Generic StateMachine<S> with declarative transition maps.\n */\n\nimport type { RuntimeStatus, MessageStatus, ToolCallStatus } from \"./core.js\";\nimport { ChatError, ChatErrorCode } from \"./errors.js\";\n\n// ─── Generic State Machine ─────────────────────────────────────\n\n/** Map of allowed transitions: current state → set of valid next states */\nexport type TransitionMap<S extends string> = Readonly<Record<S, readonly S[]>>;\n\n/**\n * Generic validated state machine.\n * Enforces that every transition is declared in the transition map.\n * Throws ChatError(INVALID_TRANSITION) on illegal moves.\n */\nexport class StateMachine<S extends string> {\n private _current: S;\n\n constructor(\n readonly initial: S,\n readonly transitions: TransitionMap<S>,\n ) {\n this._current = initial;\n }\n\n /** Current state */\n get current(): S {\n return this._current;\n }\n\n /**\n * Check whether transitioning to `next` is allowed from current state\n * @param next - Target state to check\n * @returns True if transition is allowed\n */\n canTransition(next: S): boolean {\n const allowed = this.transitions[this._current];\n return allowed !== undefined && allowed.includes(next);\n }\n\n /**\n * Transition to `next` state.\n * @throws ChatError(INVALID_TRANSITION) if the transition is not allowed\n */\n transition(next: S): void {\n if (!this.canTransition(next)) {\n throw new ChatError(\n `Invalid transition: ${this._current} → ${next}`,\n { code: ChatErrorCode.INVALID_TRANSITION },\n );\n }\n this._current = next;\n }\n\n /** Reset to initial state */\n reset(): void {\n this._current = this.initial;\n }\n}\n\n// ─── Transition Maps ───────────────────────────────────────────\n\n/** Allowed transitions for RuntimeStatus (idle → streaming/disposed, etc.) */\nexport const RUNTIME_TRANSITIONS: TransitionMap<RuntimeStatus> = {\n idle: [\"streaming\", \"disposed\"],\n streaming: [\"idle\", \"error\", \"disposed\"],\n error: [\"idle\", \"disposed\"],\n disposed: [],\n};\n\n/** Allowed transitions for MessageStatus (pending → streaming → complete, etc.) */\nexport const MESSAGE_TRANSITIONS: TransitionMap<MessageStatus> = {\n pending: [\"streaming\", \"error\", \"cancelled\"],\n streaming: [\"complete\", \"error\", \"cancelled\"],\n complete: [],\n error: [],\n cancelled: [],\n};\n\n/** Allowed transitions for ToolCallStatus (pending → running → complete, etc.) */\nexport const TOOL_CALL_TRANSITIONS: TransitionMap<ToolCallStatus> = {\n pending: [\"running\", \"requires_approval\", \"error\"],\n running: [\"complete\", \"error\"],\n requires_approval: [\"running\", \"denied\", \"error\"],\n complete: [],\n error: [],\n denied: [],\n};\n\n// ─── Pre-configured Factories ──────────────────────────────────\n\n/** Create a RuntimeStatus state machine starting at \"idle\" */\nexport function createRuntimeStateMachine(): StateMachine<RuntimeStatus> {\n return new StateMachine<RuntimeStatus>(\"idle\", RUNTIME_TRANSITIONS);\n}\n\n/** Create a MessageStatus state machine starting at \"pending\" */\nexport function createMessageStateMachine(): StateMachine<MessageStatus> {\n return new StateMachine<MessageStatus>(\"pending\", MESSAGE_TRANSITIONS);\n}\n\n/** Create a ToolCallStatus state machine starting at \"pending\" */\nexport function createToolCallStateMachine(): StateMachine<ToolCallStatus> {\n return new StateMachine<ToolCallStatus>(\"pending\", TOOL_CALL_TRANSITIONS);\n}\n\n// ─── Reentrancy Guard ──────────────────────────────────────────\n\n/**\n * Guards against concurrent send() calls in a chat runtime.\n * acquire() before work, release() after (use try/finally).\n * Throws ChatError(REENTRANCY) if already acquired.\n */\nexport class ChatReentrancyGuard {\n private _acquired = false;\n\n /** Whether the guard is currently held */\n get isAcquired(): boolean {\n return this._acquired;\n }\n\n /**\n * Acquire the guard. Throws if already acquired.\n * @throws ChatError with code REENTRANCY\n */\n acquire(): void {\n if (this._acquired) {\n throw new ChatError(\n \"Concurrent operation detected: a send is already in progress\",\n { code: ChatErrorCode.REENTRANCY },\n );\n }\n this._acquired = true;\n }\n\n /** Release the guard. Safe to call even if not acquired. */\n release(): void {\n this._acquired = false;\n }\n}\n\n// ─── Abort Controller ──────────────────────────────────────────\n\n/**\n * Abort controller with external signal linking.\n * Wraps an AbortController and optionally links an external AbortSignal\n * so aborting either side cancels the operation.\n */\nexport class ChatAbortController {\n private readonly _controller: AbortController;\n private readonly _onExternalAbort?: () => void;\n private readonly _externalSignal?: AbortSignal;\n\n constructor(externalSignal?: AbortSignal) {\n this._controller = new AbortController();\n this._externalSignal = externalSignal;\n\n if (externalSignal) {\n // If external signal already aborted, abort immediately\n if (externalSignal.aborted) {\n this._controller.abort(externalSignal.reason);\n } else {\n // Link: external abort → our controller\n this._onExternalAbort = () => {\n this._controller.abort(externalSignal.reason);\n };\n externalSignal.addEventListener(\"abort\", this._onExternalAbort, { once: true });\n }\n }\n }\n\n /** The AbortSignal for this controller */\n get signal(): AbortSignal {\n return this._controller.signal;\n }\n\n /** Whether the operation has been aborted */\n get isAborted(): boolean {\n return this._controller.signal.aborted;\n }\n\n /**\n * Abort the operation.\n * @param reason - Optional abort reason\n */\n abort(reason?: unknown): void {\n this._controller.abort(reason);\n }\n\n /** Clean up external signal listener to prevent memory leaks */\n dispose(): void {\n if (this._onExternalAbort && this._externalSignal) {\n this._externalSignal.removeEventListener(\"abort\", this._onExternalAbort);\n }\n }\n}\n","/**\n * @witqq/agent-sdk/chat/accumulator\n *\n * MessageAccumulator converts a stream of AgentEvent objects into a ChatMessage\n * with correct MessagePart array. Handles text, reasoning, and tool call\n * accumulation with proper status transitions.\n */\n\nimport type { AgentEvent } from \"../types.js\";\nimport type { ChatMessage, ChatId, MessagePart, TextPart, ReasoningPart, ToolCallPart } from \"./core.js\";\nimport { createChatId } from \"./core.js\";\n\n/**\n * Converts a stream of AgentEvent objects into a complete ChatMessage.\n * Tracks text, reasoning, and tool call parts with proper status transitions.\n *\n * @example\n * ```typescript\n * const acc = new MessageAccumulator();\n * for await (const event of agentEvents) {\n * acc.apply(event);\n * renderMessage(acc.snapshot()); // in-progress UI update\n * }\n * const message = acc.finalize();\n * ```\n */\nexport class MessageAccumulator {\n private readonly messageId: ChatId;\n private readonly parts: MessagePart[] = [];\n private status: \"pending\" | \"streaming\" | \"complete\" | \"error\" | \"cancelled\" = \"pending\";\n private currentTextPart: TextPart | null = null;\n private currentReasoningPart: ReasoningPart | null = null;\n private toolCallParts = new Map<string, ToolCallPart>();\n private _finalized = false;\n\n constructor(messageId?: ChatId) {\n this.messageId = messageId ?? createChatId();\n }\n\n /** Get current message ID */\n get id(): ChatId { return this.messageId; }\n\n /**\n * Apply an AgentEvent to accumulate into the message\n * @param event - AgentEvent to process\n * @throws Error if accumulator is already finalized\n */\n apply(event: AgentEvent): void {\n if (this._finalized) throw new Error(\"Cannot apply events to finalized accumulator\");\n\n if (this.status === \"pending\") {\n this.status = \"streaming\";\n }\n\n switch (event.type) {\n case \"text_delta\":\n this.handleTextDelta(event.text);\n break;\n case \"thinking_start\":\n this.finalizeCurrentText();\n this.currentReasoningPart = { type: \"reasoning\", text: \"\", status: \"streaming\" };\n this.parts.push(this.currentReasoningPart);\n break;\n case \"thinking_delta\":\n if (this.currentReasoningPart) {\n this.currentReasoningPart.text += event.text;\n }\n break;\n case \"thinking_end\":\n if (this.currentReasoningPart) {\n this.currentReasoningPart.status = \"complete\";\n this.currentReasoningPart = null;\n }\n break;\n case \"tool_call_start\": {\n this.finalizeCurrentText();\n const toolPart: ToolCallPart = {\n type: \"tool_call\",\n toolCallId: event.toolCallId,\n name: event.toolName,\n args: event.args,\n status: \"running\",\n };\n this.toolCallParts.set(event.toolCallId, toolPart);\n this.parts.push(toolPart);\n break;\n }\n case \"tool_call_end\": {\n const existing = this.toolCallParts.get(event.toolCallId);\n if (existing) {\n existing.result = event.result;\n existing.status = \"complete\";\n }\n break;\n }\n case \"error\":\n this.status = \"error\";\n break;\n case \"done\":\n break;\n // Other events (heartbeat, ask_user, etc.) — ignore\n }\n }\n\n private handleTextDelta(text: string): void {\n if (!this.currentTextPart) {\n this.currentTextPart = { type: \"text\", text: \"\", status: \"streaming\" };\n this.parts.push(this.currentTextPart);\n }\n this.currentTextPart.text += text;\n }\n\n private finalizeCurrentText(): void {\n if (this.currentTextPart) {\n this.currentTextPart.status = \"complete\";\n this.currentTextPart = null;\n }\n }\n\n /**\n * Get a snapshot of the current accumulated message (for streaming UI)\n * @returns ChatMessage with current parts and \"streaming\" status\n */\n snapshot(): ChatMessage {\n const now = new Date().toISOString();\n return {\n id: this.messageId,\n role: \"assistant\",\n parts: this.parts.map(p => ({ ...p })),\n status: this.status === \"pending\" ? \"pending\" : \"streaming\",\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /**\n * Finalize the accumulator and return the complete ChatMessage\n * @returns Completed ChatMessage with all parts finalized\n * @throws Error if accumulator is already finalized\n */\n finalize(): ChatMessage {\n if (this._finalized) throw new Error(\"Accumulator already finalized\");\n this._finalized = true;\n\n // Finalize any open parts\n this.finalizeCurrentText();\n if (this.currentReasoningPart) {\n this.currentReasoningPart.status = \"complete\";\n this.currentReasoningPart = null;\n }\n\n // Mark incomplete tool calls as error\n for (const [, toolPart] of this.toolCallParts) {\n if (toolPart.status === \"running\" || toolPart.status === \"pending\") {\n toolPart.status = \"error\";\n }\n }\n\n // Set final message status\n if (this.status !== \"error\" && this.status !== \"cancelled\") {\n this.status = \"complete\";\n }\n\n const now = new Date().toISOString();\n return {\n id: this.messageId,\n role: \"assistant\",\n parts: this.parts,\n status: this.status,\n createdAt: now,\n updatedAt: now,\n };\n }\n\n /** Check if the accumulator has been finalized */\n get finalized(): boolean { return this._finalized; }\n}\n","/**\n * @witqq/agent-sdk - Stream Watchdog\n *\n * Activity-based timeout wrapper for async event streams.\n * Aborts the stream if no events arrive within a configurable inactivity window.\n * Timer resets on each received event.\n */\n\nimport { ChatError, ChatErrorCode } from \"./errors.js\";\n\n// ─── Configuration ─────────────────────────────────────────────\n\n/** Stream watchdog configuration */\nexport interface StreamWatchdogConfig {\n /** Maximum inactivity time in milliseconds before aborting the stream */\n timeoutMs: number;\n /** AbortSignal to link with (watchdog aborts when this signal fires) */\n signal?: AbortSignal;\n}\n\n// ─── Watchdog Implementation ───────────────────────────────────\n\n/**\n * Wraps an async iterable with an activity timeout.\n * If no event arrives within `timeoutMs`, the stream is aborted with a ChatError.\n * The timer resets after each received event.\n *\n * Uses Promise.race() so even if the source iterator is stuck on an\n * unresolvable promise, the timeout fires and aborts iteration.\n *\n * @example\n * ```ts\n * const watched = withStreamWatchdog(adapter.streamMessage(session, msg), {\n * timeoutMs: 30000,\n * signal: abortController.signal,\n * });\n *\n * for await (const event of watched) {\n * // Each event resets the 30s inactivity timer\n * }\n * ```\n */\nexport async function* withStreamWatchdog<T>(\n source: AsyncIterable<T>,\n config: StreamWatchdogConfig,\n): AsyncGenerator<T> {\n const { timeoutMs, signal } = config;\n\n const iterator = source[Symbol.asyncIterator]();\n let aborted = false;\n\n // Link external abort signal\n if (signal?.aborted) {\n iterator.return?.();\n return;\n }\n\n const onAbort = (): void => {\n aborted = true;\n iterator.return?.();\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n while (true) {\n if (aborted) break;\n\n // Race iterator.next() against a cancellable inactivity timeout.\n // The timeout is cleared when iterator.next() wins, preventing\n // unhandled promise rejections from orphaned setTimeout callbacks.\n const timeout = new CancellableTimeout<T>(timeoutMs);\n try {\n const result = await Promise.race([\n iterator.next(),\n timeout.promise,\n ]);\n timeout.cancel();\n\n if (result.done) break;\n yield result.value;\n } catch (err) {\n timeout.cancel();\n throw err;\n }\n }\n } finally {\n signal?.removeEventListener(\"abort\", onAbort);\n iterator.return?.();\n }\n}\n\n/** Timeout that can be cancelled to prevent unhandled rejections */\nclass CancellableTimeout<T> {\n readonly promise: Promise<IteratorResult<T>>;\n private _timer: ReturnType<typeof setTimeout> | undefined;\n private _cancelled = false;\n\n constructor(ms: number) {\n this.promise = new Promise<IteratorResult<T>>((_, reject) => {\n this._timer = setTimeout(() => {\n if (!this._cancelled) {\n reject(\n new ChatError(\n `Stream timed out after ${ms}ms of inactivity`,\n { code: ChatErrorCode.TIMEOUT },\n ),\n );\n }\n }, ms);\n });\n // Prevent unhandled rejection when cancelled\n this.promise.catch(() => {});\n }\n\n cancel(): void {\n this._cancelled = true;\n if (this._timer !== undefined) {\n clearTimeout(this._timer);\n this._timer = undefined;\n }\n }\n}\n","/**\n * @witqq/agent-sdk/chat/runtime\n *\n * Unified chat runtime orchestrator. Creates a fully-wired runtime instance\n * from a configuration object, managing backend adapters, sessions, context\n * trimming, streaming, and middleware in a single facade.\n *\n * Usage:\n * ```typescript\n * import { createChatRuntime } from \"@witqq/agent-sdk/chat/runtime\";\n * const runtime = createChatRuntime({ backends: { ... }, sessionStore, ... });\n * const session = await runtime.createSession({ config: { model: \"gpt-4\", backend: \"copilot\" } });\n * for await (const event of runtime.send(session.id, \"Hello\")) { ... }\n * ```\n */\n\nimport type {\n ChatEvent,\n ChatId,\n ChatIdLike,\n ChatMessage,\n ChatMiddleware,\n ChatMiddlewareContext,\n ChatSession,\n ChatSessionConfig,\n RuntimeStatus,\n SendMessageOptions,\n} from \"./core.js\";\nimport { createChatId, toChatId, chatEventToAgentEvent } from \"./core.js\";\nimport type { IBackendAdapter } from \"./backends/types.js\";\nimport type { IChatSessionStore, CreateSessionOptions, SessionListOptions } from \"./sessions.js\";\nimport type { ContextWindowConfig, ContextStats } from \"./context.js\";\nimport { ContextWindowManager } from \"./context.js\";\nimport {\n StateMachine,\n RUNTIME_TRANSITIONS,\n ChatReentrancyGuard,\n ChatAbortController,\n} from \"./state.js\";\nimport { ChatError, ChatErrorCode } from \"./errors.js\";\nimport { MessageAccumulator } from \"./accumulator.js\";\nimport { withStreamWatchdog } from \"./watchdog.js\";\nimport type { ToolDefinition, ToolContext } from \"../types.js\";\nimport type { ModelInfo } from \"../types.js\";\n\n// ─── Runtime Configuration ─────────────────────────────────────\n\n/** Factory function that creates a backend adapter on demand */\nexport type BackendAdapterFactory = () => IBackendAdapter | Promise<IBackendAdapter>;\n\n/** Configuration for creating a chat runtime via createChatRuntime() */\nexport interface ChatRuntimeOptions {\n /** Map of backend name → adapter factory (lazy creation on first use) */\n backends: Record<string, BackendAdapterFactory>;\n /** Default backend name (must be a key in `backends`) */\n defaultBackend: string;\n /** Session store for persistence */\n sessionStore: IChatSessionStore;\n /** Context window configuration (optional) */\n context?: ContextWindowConfig;\n /** Middleware pipeline (optional, applied in order) */\n middleware?: ChatMiddleware[];\n /** Default model override (optional) */\n defaultModel?: string;\n /** Retry configuration for pre-stream connection errors */\n retryConfig?: RetryConfig;\n /**\n * Stream inactivity timeout in milliseconds (optional).\n * When set, aborts the stream if no events arrive within this window.\n * Timer resets after each received event.\n */\n streamTimeoutMs?: number;\n /**\n * Called when context trimming removes messages.\n * Use for archiving, logging, or analytics.\n */\n onContextTrimmed?: (sessionId: ChatIdLike, removedMessages: ChatMessage[]) => void;\n}\n\n/** Retry configuration for pre-stream failures */\nexport interface RetryConfig {\n /** Maximum number of attempts (default: 1 = no retry) */\n maxAttempts: number;\n /** Delay between retries in milliseconds */\n delayMs: number;\n}\n\n// ─── IChatRuntime Interface ────────────────────────────────────\n\n/** The unified chat runtime facade */\nexport interface IChatRuntime<TMetadata extends Record<string, unknown> = Record<string, unknown>> {\n // ── Lifecycle ──\n /** Current runtime status */\n readonly status: RuntimeStatus;\n /** Dispose the runtime and all owned resources */\n dispose(): Promise<void>;\n\n // ── Sessions ──\n createSession(options: CreateSessionOptions<TMetadata>): Promise<ChatSession<TMetadata>>;\n getSession(id: ChatIdLike): Promise<ChatSession<TMetadata> | null>;\n listSessions(options?: SessionListOptions): Promise<ChatSession<TMetadata>[]>;\n deleteSession(id: ChatIdLike): Promise<void>;\n archiveSession(id: ChatIdLike): Promise<void>;\n switchSession(id: ChatIdLike): Promise<ChatSession<TMetadata>>;\n /** Currently active session ID (null if none) */\n readonly activeSessionId: ChatId | null;\n\n // ── Messaging ──\n send(sessionId: ChatIdLike, message: string, options?: SendMessageOptions): AsyncIterable<ChatEvent>;\n abort(): void;\n\n // ── Backend / Model ──\n switchBackend(name: string): Promise<void>;\n switchModel(model: string): void;\n listModels(): Promise<ModelInfo[]>;\n /** Current backend name */\n readonly currentBackend: string;\n /** Current model (from config or default) */\n readonly currentModel: string | undefined;\n\n // ── Tools ──\n registerTool(tool: ToolDefinition): void;\n removeTool(name: string): void;\n readonly registeredTools: ReadonlyMap<string, ToolDefinition>;\n\n // ── Middleware ──\n use(middleware: ChatMiddleware): void;\n removeMiddleware(middleware: ChatMiddleware): void;\n\n // ── Context Stats ──\n /** Get context usage stats from the last send() for a session. Returns null if no trimming has occurred. */\n getContextStats(sessionId: ChatIdLike): ContextStats | null;\n\n // ── Session Subscription ──\n /** Subscribe to session mutations (create, delete, archive, message send complete). Returns unsubscribe function. */\n onSessionChange(callback: () => void): () => void;\n}\n\n// ─── ChatRuntime Implementation ────────────────────────────────\n\nclass ChatRuntime<TMetadata extends Record<string, unknown> = Record<string, unknown>> implements IChatRuntime<TMetadata> {\n private readonly _state: StateMachine<RuntimeStatus>;\n private readonly _guard: ChatReentrancyGuard;\n private readonly _backends: Record<string, BackendAdapterFactory>;\n private readonly _sessionStore: IChatSessionStore;\n private readonly _contextConfig?: ContextWindowConfig;\n private readonly _middleware: ChatMiddleware[];\n private readonly _tools = new Map<string, ToolDefinition>();\n private readonly _retryConfig?: RetryConfig;\n private readonly _contextStats = new Map<ChatId, ContextStats>();\n private readonly _onContextTrimmed?: (sessionId: ChatIdLike, removedMessages: ChatMessage[]) => void;\n private readonly _streamTimeoutMs?: number;\n private readonly _sessionListeners = new Set<() => void>();\n\n private _activeAdapter: IBackendAdapter | null = null;\n private _currentBackend: string;\n private _currentModel: string | undefined;\n private _activeSessionId: ChatId | null = null;\n private _abortController: ChatAbortController | null = null;\n\n constructor(options: ChatRuntimeOptions) {\n this._state = new StateMachine<RuntimeStatus>(\"idle\", RUNTIME_TRANSITIONS);\n this._guard = new ChatReentrancyGuard();\n this._backends = options.backends;\n this._currentBackend = options.defaultBackend;\n this._currentModel = options.defaultModel;\n this._sessionStore = options.sessionStore;\n this._contextConfig = options.context;\n this._middleware = [...(options.middleware ?? [])];\n this._retryConfig = options.retryConfig;\n this._onContextTrimmed = options.onContextTrimmed;\n this._streamTimeoutMs = options.streamTimeoutMs;\n\n if (!options.backends[options.defaultBackend]) {\n throw new ChatError(\n `Default backend \"${options.defaultBackend}\" not found in backends map`,\n { code: ChatErrorCode.INVALID_INPUT },\n );\n }\n }\n\n // ── Lifecycle ──────────────────────────────────────────────\n\n get status(): RuntimeStatus {\n return this._state.current;\n }\n\n async dispose(): Promise<void> {\n if (this._state.current === \"disposed\") return;\n\n // Abort any in-flight send\n this._abortController?.abort(\"Runtime disposed\");\n this._abortController?.dispose();\n this._abortController = null;\n\n // Direct transition to disposed from any state (streaming→disposed now valid)\n this._state.transition(\"disposed\");\n\n // Dispose active adapter\n if (this._activeAdapter) {\n await this._activeAdapter.dispose();\n this._activeAdapter = null;\n }\n }\n\n // ── Sessions ───────────────────────────────────────────────\n\n get activeSessionId(): ChatId | null {\n return this._activeSessionId;\n }\n\n async createSession(options: CreateSessionOptions<TMetadata>): Promise<ChatSession<TMetadata>> {\n this.assertNotDisposed();\n // Fill config defaults from runtime settings when omitted\n const config: ChatSessionConfig = {\n model: options.config?.model ?? this._currentModel ?? \"\",\n backend: options.config?.backend ?? this._currentBackend,\n ...options.config,\n };\n const session = await this._sessionStore.createSession({ ...options, config });\n this._activeSessionId = session.id;\n this._notifySessionChange();\n return session as ChatSession<TMetadata>;\n }\n\n async getSession(id: ChatIdLike): Promise<ChatSession<TMetadata> | null> {\n this.assertNotDisposed();\n const cid = toChatId(id);\n return this._sessionStore.getSession(cid) as Promise<ChatSession<TMetadata> | null>;\n }\n\n async listSessions(options?: SessionListOptions): Promise<ChatSession<TMetadata>[]> {\n this.assertNotDisposed();\n return this._sessionStore.listSessions(options) as Promise<ChatSession<TMetadata>[]>;\n }\n\n async deleteSession(id: ChatIdLike): Promise<void> {\n this.assertNotDisposed();\n const cid = toChatId(id);\n const session = await this._sessionStore.getSession(cid);\n if (!session) return;\n\n await this._sessionStore.deleteSession(cid);\n this._contextStats.delete(cid);\n if (this._activeSessionId === cid) {\n this._activeSessionId = null;\n }\n this._notifySessionChange();\n }\n\n async archiveSession(id: ChatIdLike): Promise<void> {\n this.assertNotDisposed();\n const cid = toChatId(id);\n await this._sessionStore.archiveSession(cid);\n this._notifySessionChange();\n }\n\n async switchSession(id: ChatIdLike): Promise<ChatSession<TMetadata>> {\n this.assertNotDisposed();\n const cid = toChatId(id);\n const session = await this._sessionStore.getSession(cid);\n if (!session) {\n throw new ChatError(\n `Session \"${id}\" not found`,\n { code: ChatErrorCode.SESSION_NOT_FOUND },\n );\n }\n this._activeSessionId = session.id;\n return session as ChatSession<TMetadata>;\n }\n\n // ── Messaging ──────────────────────────────────────────────\n\n async *send(\n sessionId: ChatIdLike,\n message: string,\n options?: SendMessageOptions,\n ): AsyncIterable<ChatEvent> {\n this.assertNotDisposed();\n\n if (!message || message.trim().length === 0) {\n throw new ChatError(\"Message cannot be empty\", { code: ChatErrorCode.INVALID_INPUT });\n }\n\n this._guard.acquire();\n\n // Normalize to branded ChatId for internal use\n const cid = toChatId(sessionId);\n\n // Create abort controller linked to user's signal\n this._abortController = new ChatAbortController(options?.signal);\n\n try {\n // Auto-recover from error state (transient failures shouldn't permanently kill runtime)\n if (this._state.current === \"error\") {\n this._state.transition(\"idle\");\n }\n this._state.transition(\"streaming\");\n\n // 1. Load session\n const session = await this._sessionStore.getSession(cid);\n if (!session) {\n throw new ChatError(\n `Session \"${cid}\" not found`,\n { code: ChatErrorCode.SESSION_NOT_FOUND },\n );\n }\n\n const middlewareContext: ChatMiddlewareContext = {\n sessionId: cid,\n signal: this._abortController.signal,\n };\n\n // 2. Create user message\n let userMessage = this.createUserMessage(message);\n\n // 3. Apply onBeforeSend middleware pipeline (sequential transform)\n for (const mw of this._middleware) {\n if (mw.onBeforeSend) {\n userMessage = await mw.onBeforeSend(userMessage, middlewareContext);\n }\n }\n\n // 4. Persist transformed user message\n await this._sessionStore.appendMessage(cid, userMessage);\n\n // 5. Reload session with user message for context\n const updatedSession = (await this._sessionStore.getSession(cid))!;\n\n // 6. Auto-trim context if configured\n let messagesToSend = updatedSession.messages;\n if (this._contextConfig) {\n const ctxManager = new ContextWindowManager(this._contextConfig);\n const result = await ctxManager.fitMessagesAsync(messagesToSend);\n\n // Track stats for this session\n this._contextStats.set(cid, {\n totalTokens: result.totalTokens,\n removedCount: result.removedCount,\n wasTruncated: result.wasTruncated,\n availableBudget: ctxManager.availableBudget,\n });\n\n // Fire archive callback with removed messages (safe — user callback errors don't crash send)\n if (result.wasTruncated && this._onContextTrimmed) {\n const keptIds = new Set(result.messages.map(m => m.id));\n const removed = messagesToSend.filter(m => !keptIds.has(m.id));\n if (removed.length > 0) {\n try {\n this._onContextTrimmed(cid, removed);\n } catch {\n // User callback error — swallow to avoid disrupting send flow\n }\n }\n }\n\n messagesToSend = result.messages;\n }\n\n // Build a session snapshot with trimmed messages for adapter\n const sessionForAdapter: ChatSession = {\n ...updatedSession,\n messages: messagesToSend,\n };\n\n // 7. Get or create adapter (with retry for pre-stream connection errors)\n const adapter = await this.getOrCreateAdapterWithRetry();\n\n // 8. Create accumulator for building assistant message from stream\n const accumulator = new MessageAccumulator();\n\n // 9. Stream via adapter, passing runtime tools with context injection\n const runtimeTools = this._tools.size > 0\n ? this.injectToolContext([...this._tools.values()], {\n sessionId: cid as string,\n custom: updatedSession.metadata?.custom as Record<string, unknown> | undefined,\n })\n : undefined;\n const streamOptions: SendMessageOptions = {\n ...options,\n signal: this._abortController.signal,\n model: options?.model ?? this._currentModel,\n tools: runtimeTools,\n };\n\n const stream = await this.createStreamWithRetry(adapter, sessionForAdapter, message, streamOptions);\n\n const eventSource = this._streamTimeoutMs\n ? withStreamWatchdog(stream, { timeoutMs: this._streamTimeoutMs, signal: this._abortController.signal })\n : stream;\n\n for await (const event of eventSource) {\n if (this._abortController.isAborted) break;\n\n // Feed events to accumulator for building assistant message\n this.feedAccumulator(accumulator, event);\n\n // Apply onEvent middleware pipeline (sequential transform/suppress)\n let processedEvent: ChatEvent | null = event;\n for (const mw of this._middleware) {\n if (mw.onEvent && processedEvent) {\n processedEvent = await mw.onEvent(processedEvent, middlewareContext);\n }\n }\n\n if (processedEvent) {\n yield processedEvent;\n }\n }\n\n // If runtime was disposed during streaming, exit gracefully\n if (this._state.current === \"disposed\") {\n return;\n }\n\n // 10. Finalize accumulator and persist assistant message\n let assistantMessage = accumulator.finalize();\n\n // Apply onAfterReceive middleware pipeline\n for (const mw of this._middleware) {\n if (mw.onAfterReceive) {\n assistantMessage = await mw.onAfterReceive(assistantMessage, middlewareContext);\n }\n }\n\n await this._sessionStore.appendMessage(cid, assistantMessage);\n this._notifySessionChange();\n\n this._state.transition(\"idle\");\n } catch (error) {\n // Apply onError middleware\n let processedError = error instanceof Error ? error : new Error(String(error));\n const middlewareContext: ChatMiddlewareContext = {\n sessionId: cid,\n signal: this._abortController?.signal ?? new AbortController().signal,\n };\n\n for (const mw of this._middleware) {\n if (mw.onError) {\n const result = await mw.onError(processedError, middlewareContext);\n if (result === null) {\n // Error suppressed by middleware\n if (this._state.canTransition(\"idle\")) {\n this._state.transition(\"idle\");\n }\n return;\n }\n processedError = result;\n }\n }\n\n if (this._state.canTransition(\"error\")) {\n this._state.transition(\"error\");\n }\n throw processedError;\n } finally {\n this._guard.release();\n this._abortController?.dispose();\n this._abortController = null;\n }\n }\n\n abort(): void {\n this._abortController?.abort(\"User abort\");\n }\n\n // ── Backend / Model ────────────────────────────────────────\n\n get currentBackend(): string {\n return this._currentBackend;\n }\n\n get currentModel(): string | undefined {\n return this._currentModel;\n }\n\n async switchBackend(name: string): Promise<void> {\n this.assertNotDisposed();\n if (!this._backends[name]) {\n throw new ChatError(\n `Backend \"${name}\" not found in backends map`,\n { code: ChatErrorCode.INVALID_INPUT },\n );\n }\n\n // Dispose current adapter — new one created lazily on next send\n if (this._activeAdapter) {\n await this._activeAdapter.dispose();\n this._activeAdapter = null;\n }\n\n this._currentBackend = name;\n }\n\n switchModel(model: string): void {\n this.assertNotDisposed();\n this._currentModel = model;\n }\n\n async listModels(): Promise<ModelInfo[]> {\n this.assertNotDisposed();\n const adapter = await this.getOrCreateAdapter();\n return adapter.listModels();\n }\n\n // ── Tools ──────────────────────────────────────────────────\n\n get registeredTools(): ReadonlyMap<string, ToolDefinition> {\n return this._tools;\n }\n\n registerTool(tool: ToolDefinition): void {\n this.assertNotDisposed();\n this._tools.set(tool.name, tool);\n }\n\n removeTool(name: string): void {\n this.assertNotDisposed();\n this._tools.delete(name);\n }\n\n // ── Middleware ──────────────────────────────────────────────\n\n use(middleware: ChatMiddleware): void {\n this.assertNotDisposed();\n this._middleware.push(middleware);\n }\n\n removeMiddleware(middleware: ChatMiddleware): void {\n this.assertNotDisposed();\n const idx = this._middleware.indexOf(middleware);\n if (idx >= 0) this._middleware.splice(idx, 1);\n }\n\n // ── Context Stats ─────────────────────────────────────────\n\n getContextStats(sessionId: ChatIdLike): ContextStats | null {\n const cid = toChatId(sessionId);\n return this._contextStats.get(cid) ?? null;\n }\n\n // ── Session Subscription ──────────────────────────────────\n\n onSessionChange(callback: () => void): () => void {\n this._sessionListeners.add(callback);\n return () => { this._sessionListeners.delete(callback); };\n }\n\n private _notifySessionChange(): void {\n for (const cb of this._sessionListeners) {\n try { cb(); } catch { /* listener errors must not break runtime */ }\n }\n }\n\n // ── Private Helpers ────────────────────────────────────────\n\n private async getOrCreateAdapter(): Promise<IBackendAdapter> {\n if (this._activeAdapter) return this._activeAdapter;\n\n const factory = this._backends[this._currentBackend];\n if (!factory) {\n throw new ChatError(\n `Backend \"${this._currentBackend}\" not found`,\n { code: ChatErrorCode.INVALID_INPUT },\n );\n }\n\n this._activeAdapter = await factory();\n return this._activeAdapter;\n }\n\n /** Wrap each tool's execute to inject ToolContext as 2nd argument */\n private injectToolContext(tools: ToolDefinition[], context: ToolContext): ToolDefinition[] {\n return tools.map(tool => ({\n ...tool,\n execute: (params: unknown) => tool.execute(params, context),\n }));\n }\n\n /** Map ChatEvent to AgentEvent for MessageAccumulator */\n private feedAccumulator(acc: MessageAccumulator, event: ChatEvent): void {\n const agentEvent = chatEventToAgentEvent(event);\n if (agentEvent) acc.apply(agentEvent);\n }\n\n private createUserMessage(text: string): ChatMessage {\n return {\n id: createChatId(),\n role: \"user\",\n parts: [{ type: \"text\", text, status: \"complete\" }],\n createdAt: new Date().toISOString(),\n status: \"complete\",\n };\n }\n\n private assertNotDisposed(): void {\n if (this._state.current === \"disposed\") {\n throw new ChatError(\n \"Runtime is disposed\",\n { code: ChatErrorCode.DISPOSED },\n );\n }\n }\n\n /** Get or create adapter with retry on connection errors */\n private async getOrCreateAdapterWithRetry(): Promise<IBackendAdapter> {\n const maxAttempts = this._retryConfig?.maxAttempts ?? 1;\n const delayMs = this._retryConfig?.delayMs ?? 0;\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await this.getOrCreateAdapter();\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < maxAttempts) {\n // Reset adapter so next attempt creates fresh\n this._activeAdapter = null;\n await delay(delayMs);\n }\n }\n }\n\n throw lastError!;\n }\n\n /**\n * Create stream with retry for pre-stream connection errors.\n * Tries to get the first event from the stream; if that fails,\n * retries with a fresh adapter. Once first event is received,\n * the stream is committed (no more retries).\n */\n private async createStreamWithRetry(\n adapter: IBackendAdapter,\n session: ChatSession,\n message: string,\n options: SendMessageOptions | undefined,\n ): Promise<AsyncIterable<ChatEvent>> {\n const maxAttempts = this._retryConfig?.maxAttempts ?? 1;\n const delayMs = this._retryConfig?.delayMs ?? 0;\n let lastError: Error | undefined;\n let currentAdapter = adapter;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const stream = currentAdapter.streamMessage(session, message, options);\n const iterator = (stream as AsyncIterable<ChatEvent>)[Symbol.asyncIterator]();\n const first = await iterator.next();\n\n // First event received — stream is live. Wrap remaining into iterable.\n return (async function* () {\n if (!first.done) yield first.value;\n while (true) {\n const next = await iterator.next();\n if (next.done) break;\n yield next.value;\n }\n })();\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < maxAttempts) {\n // Dispose failed adapter before creating fresh one\n if (this._activeAdapter) {\n await this._activeAdapter.dispose().catch(() => {});\n }\n this._activeAdapter = null;\n await delay(delayMs);\n currentAdapter = await this.getOrCreateAdapter();\n }\n }\n }\n\n throw lastError!;\n }\n}\n\n// ─── Helpers ───────────────────────────────────────────────────\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ─── Factory ───────────────────────────────────────────────────\n\n/**\n * Create a fully-wired chat runtime from configuration.\n *\n * @param options - Runtime configuration (backends, session store, context, middleware)\n * @returns IChatRuntime instance ready to use\n *\n * @example\n * ```typescript\n * import { createChatRuntime } from \"@witqq/agent-sdk/chat/runtime\";\n * import { InMemorySessionStore } from \"@witqq/agent-sdk/chat/sessions\";\n *\n * const runtime = createChatRuntime({\n * backends: {\n * copilot: () => new CopilotAdapter({ agentConfig: { model: \"gpt-4\" } }),\n * },\n * defaultBackend: \"copilot\",\n * sessionStore: new InMemorySessionStore(),\n * });\n * ```\n */\nexport function createChatRuntime<TMetadata extends Record<string, unknown> = Record<string, unknown>>(\n options: ChatRuntimeOptions,\n): IChatRuntime<TMetadata> {\n return new ChatRuntime<TMetadata>(options);\n}\n"]}