@witqq/agent-sdk 0.6.1 → 0.8.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 (145) hide show
  1. package/README.md +539 -6
  2. package/dist/{types-BvwNzZCj.d.cts → agent-CW9XbmG_.d.ts} +148 -95
  3. package/dist/{types-BvwNzZCj.d.ts → agent-DxY68NZL.d.cts} +148 -95
  4. package/dist/auth/index.cjs +260 -2
  5. package/dist/auth/index.cjs.map +1 -1
  6. package/dist/auth/index.d.cts +21 -138
  7. package/dist/auth/index.d.ts +21 -138
  8. package/dist/auth/index.js +260 -3
  9. package/dist/auth/index.js.map +1 -1
  10. package/dist/backends/claude.cjs +653 -140
  11. package/dist/backends/claude.cjs.map +1 -1
  12. package/dist/backends/claude.d.cts +4 -1
  13. package/dist/backends/claude.d.ts +4 -1
  14. package/dist/backends/claude.js +653 -140
  15. package/dist/backends/claude.js.map +1 -1
  16. package/dist/backends/copilot.cjs +428 -88
  17. package/dist/backends/copilot.cjs.map +1 -1
  18. package/dist/backends/copilot.d.cts +13 -4
  19. package/dist/backends/copilot.d.ts +13 -4
  20. package/dist/backends/copilot.js +428 -88
  21. package/dist/backends/copilot.js.map +1 -1
  22. package/dist/backends/vercel-ai.cjs +349 -77
  23. package/dist/backends/vercel-ai.cjs.map +1 -1
  24. package/dist/backends/vercel-ai.d.cts +3 -1
  25. package/dist/backends/vercel-ai.d.ts +3 -1
  26. package/dist/backends/vercel-ai.js +349 -77
  27. package/dist/backends/vercel-ai.js.map +1 -1
  28. package/dist/backends-BSrsBYFn.d.cts +39 -0
  29. package/dist/backends-BSrsBYFn.d.ts +39 -0
  30. package/dist/chat/accumulator.cjs +147 -0
  31. package/dist/chat/accumulator.cjs.map +1 -0
  32. package/dist/chat/accumulator.d.cts +64 -0
  33. package/dist/chat/accumulator.d.ts +64 -0
  34. package/dist/chat/accumulator.js +145 -0
  35. package/dist/chat/accumulator.js.map +1 -0
  36. package/dist/chat/backends.cjs +3524 -0
  37. package/dist/chat/backends.cjs.map +1 -0
  38. package/dist/chat/backends.d.cts +66 -0
  39. package/dist/chat/backends.d.ts +66 -0
  40. package/dist/chat/backends.js +3512 -0
  41. package/dist/chat/backends.js.map +1 -0
  42. package/dist/chat/context.cjs +280 -0
  43. package/dist/chat/context.cjs.map +1 -0
  44. package/dist/chat/context.d.cts +191 -0
  45. package/dist/chat/context.d.ts +191 -0
  46. package/dist/chat/context.js +277 -0
  47. package/dist/chat/context.js.map +1 -0
  48. package/dist/chat/core.cjs +305 -0
  49. package/dist/chat/core.cjs.map +1 -0
  50. package/dist/chat/core.d.cts +84 -0
  51. package/dist/chat/core.d.ts +84 -0
  52. package/dist/chat/core.js +282 -0
  53. package/dist/chat/core.js.map +1 -0
  54. package/dist/chat/errors.cjs +273 -0
  55. package/dist/chat/errors.cjs.map +1 -0
  56. package/dist/chat/errors.d.cts +97 -0
  57. package/dist/chat/errors.d.ts +97 -0
  58. package/dist/chat/errors.js +266 -0
  59. package/dist/chat/errors.js.map +1 -0
  60. package/dist/chat/events.cjs +203 -0
  61. package/dist/chat/events.cjs.map +1 -0
  62. package/dist/chat/events.d.cts +245 -0
  63. package/dist/chat/events.d.ts +245 -0
  64. package/dist/chat/events.js +196 -0
  65. package/dist/chat/events.js.map +1 -0
  66. package/dist/chat/index.cjs +5550 -0
  67. package/dist/chat/index.cjs.map +1 -0
  68. package/dist/chat/index.d.cts +77 -0
  69. package/dist/chat/index.d.ts +77 -0
  70. package/dist/chat/index.js +5505 -0
  71. package/dist/chat/index.js.map +1 -0
  72. package/dist/chat/react/theme.css +2517 -0
  73. package/dist/chat/react.cjs +3589 -0
  74. package/dist/chat/react.cjs.map +1 -0
  75. package/dist/chat/react.d.cts +1088 -0
  76. package/dist/chat/react.d.ts +1088 -0
  77. package/dist/chat/react.js +3547 -0
  78. package/dist/chat/react.js.map +1 -0
  79. package/dist/chat/runtime.cjs +1245 -0
  80. package/dist/chat/runtime.cjs.map +1 -0
  81. package/dist/chat/runtime.d.cts +182 -0
  82. package/dist/chat/runtime.d.ts +182 -0
  83. package/dist/chat/runtime.js +1243 -0
  84. package/dist/chat/runtime.js.map +1 -0
  85. package/dist/chat/server.cjs +2668 -0
  86. package/dist/chat/server.cjs.map +1 -0
  87. package/dist/chat/server.d.cts +648 -0
  88. package/dist/chat/server.d.ts +648 -0
  89. package/dist/chat/server.js +2628 -0
  90. package/dist/chat/server.js.map +1 -0
  91. package/dist/chat/sessions.cjs +380 -0
  92. package/dist/chat/sessions.cjs.map +1 -0
  93. package/dist/chat/sessions.d.cts +158 -0
  94. package/dist/chat/sessions.d.ts +158 -0
  95. package/dist/chat/sessions.js +376 -0
  96. package/dist/chat/sessions.js.map +1 -0
  97. package/dist/chat/sqlite.cjs +441 -0
  98. package/dist/chat/sqlite.cjs.map +1 -0
  99. package/dist/chat/sqlite.d.cts +128 -0
  100. package/dist/chat/sqlite.d.ts +128 -0
  101. package/dist/chat/sqlite.js +435 -0
  102. package/dist/chat/sqlite.js.map +1 -0
  103. package/dist/chat/state.cjs +190 -0
  104. package/dist/chat/state.cjs.map +1 -0
  105. package/dist/chat/state.d.cts +95 -0
  106. package/dist/chat/state.d.ts +95 -0
  107. package/dist/chat/state.js +180 -0
  108. package/dist/chat/state.js.map +1 -0
  109. package/dist/chat/storage.cjs +249 -0
  110. package/dist/chat/storage.cjs.map +1 -0
  111. package/dist/chat/storage.d.cts +197 -0
  112. package/dist/chat/storage.d.ts +197 -0
  113. package/dist/chat/storage.js +245 -0
  114. package/dist/chat/storage.js.map +1 -0
  115. package/dist/errors-C-so0M4t.d.cts +33 -0
  116. package/dist/errors-C-so0M4t.d.ts +33 -0
  117. package/dist/errors-CmVvczxZ.d.cts +28 -0
  118. package/dist/errors-CmVvczxZ.d.ts +28 -0
  119. package/dist/in-process-transport-C1JnJGVR.d.ts +228 -0
  120. package/dist/in-process-transport-C7DSqPyX.d.cts +228 -0
  121. package/dist/index.cjs +365 -59
  122. package/dist/index.cjs.map +1 -1
  123. package/dist/index.d.cts +322 -125
  124. package/dist/index.d.ts +322 -125
  125. package/dist/index.js +359 -60
  126. package/dist/index.js.map +1 -1
  127. package/dist/provider-types-PTSlRPNB.d.cts +39 -0
  128. package/dist/provider-types-PTSlRPNB.d.ts +39 -0
  129. package/dist/refresh-manager-B81PpYBr.d.cts +153 -0
  130. package/dist/refresh-manager-Dlv_iNZi.d.ts +153 -0
  131. package/dist/testing.cjs +383 -0
  132. package/dist/testing.cjs.map +1 -0
  133. package/dist/testing.d.cts +132 -0
  134. package/dist/testing.d.ts +132 -0
  135. package/dist/testing.js +377 -0
  136. package/dist/testing.js.map +1 -0
  137. package/dist/token-store-CSUBgYwn.d.ts +48 -0
  138. package/dist/token-store-CuC4hB9Z.d.cts +48 -0
  139. package/dist/transport-Cdh3M0tS.d.cts +68 -0
  140. package/dist/transport-Ciap4PWK.d.ts +68 -0
  141. package/dist/types-4vbcmPTp.d.cts +143 -0
  142. package/dist/types-BxggH0Yh.d.ts +143 -0
  143. package/dist/types-DRgd_9R7.d.cts +363 -0
  144. package/dist/types-ajANVzf7.d.ts +363 -0
  145. package/package.json +178 -6
@@ -0,0 +1,282 @@
1
+ // src/chat/types.ts
2
+ function createChatId() {
3
+ return crypto.randomUUID();
4
+ }
5
+ var 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;
6
+ function toChatId(value) {
7
+ if (!UUID_RE.test(value)) {
8
+ throw new TypeError(`Invalid ChatId: "${value}" is not a valid UUID`);
9
+ }
10
+ return value;
11
+ }
12
+ function createTextMessage(text, role = "user") {
13
+ return {
14
+ id: createChatId(),
15
+ role,
16
+ parts: [{ type: "text", text, status: "complete" }],
17
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
18
+ status: "complete"
19
+ };
20
+ }
21
+ function isObservableSession(session) {
22
+ return "subscribe" in session && typeof session.subscribe === "function" && "getSnapshot" in session && typeof session.getSnapshot === "function";
23
+ }
24
+
25
+ // src/chat/chat-utils.ts
26
+ function getMessageText(message) {
27
+ return message.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
28
+ }
29
+ function getMessageToolCalls(message) {
30
+ return message.parts.filter((p) => p.type === "tool_call");
31
+ }
32
+ function getMessageReasoning(message) {
33
+ return message.parts.filter((p) => p.type === "reasoning").map((p) => p.text).join("");
34
+ }
35
+
36
+ // src/chat/guards.ts
37
+ function isChatMessage(value) {
38
+ if (typeof value !== "object" || value === null) return false;
39
+ const obj = value;
40
+ return typeof obj.id === "string" && typeof obj.role === "string" && (obj.role === "user" || obj.role === "assistant" || obj.role === "system") && Array.isArray(obj.parts) && typeof obj.createdAt === "string" && typeof obj.status === "string";
41
+ }
42
+ function isChatSession(value) {
43
+ if (typeof value !== "object" || value === null) return false;
44
+ const obj = value;
45
+ return typeof obj.id === "string" && Array.isArray(obj.messages) && typeof obj.config === "object" && obj.config !== null && typeof obj.createdAt === "string" && typeof obj.updatedAt === "string" && typeof obj.status === "string";
46
+ }
47
+ function isMessagePart(value) {
48
+ if (typeof value !== "object" || value === null) return false;
49
+ const obj = value;
50
+ return typeof obj.type === "string" && (obj.type === "text" || obj.type === "reasoning" || obj.type === "tool_call" || obj.type === "source" || obj.type === "file");
51
+ }
52
+ function isTextPart(value) {
53
+ if (typeof value !== "object" || value === null) return false;
54
+ const obj = value;
55
+ return obj.type === "text" && typeof obj.text === "string";
56
+ }
57
+ function isToolCallPart(value) {
58
+ if (typeof value !== "object" || value === null) return false;
59
+ const obj = value;
60
+ return obj.type === "tool_call" && typeof obj.toolCallId === "string" && typeof obj.name === "string";
61
+ }
62
+ function isReasoningPart(value) {
63
+ if (typeof value !== "object" || value === null) return false;
64
+ const obj = value;
65
+ return obj.type === "reasoning" && typeof obj.text === "string";
66
+ }
67
+ function isSourcePart(value) {
68
+ if (typeof value !== "object" || value === null) return false;
69
+ const obj = value;
70
+ return obj.type === "source" && typeof obj.url === "string";
71
+ }
72
+ function isFilePart(value) {
73
+ if (typeof value !== "object" || value === null) return false;
74
+ const obj = value;
75
+ return obj.type === "file" && typeof obj.name === "string" && typeof obj.mimeType === "string";
76
+ }
77
+ function isChatEvent(value) {
78
+ if (typeof value !== "object" || value === null) return false;
79
+ const obj = value;
80
+ const validTypes = [
81
+ "message:start",
82
+ "message:delta",
83
+ "message:complete",
84
+ "tool:start",
85
+ "tool:complete",
86
+ "thinking:start",
87
+ "thinking:delta",
88
+ "thinking:end",
89
+ "permission:request",
90
+ "permission:response",
91
+ "usage",
92
+ "session:created",
93
+ "session:updated",
94
+ "error",
95
+ "typing:start",
96
+ "typing:end",
97
+ "heartbeat",
98
+ "done"
99
+ ];
100
+ return validTypes.includes(obj.type);
101
+ }
102
+
103
+ // src/chat/bridge.ts
104
+ function agentEventToChatEvent(event, messageId) {
105
+ switch (event.type) {
106
+ case "text_delta":
107
+ return { type: "message:delta", messageId, text: event.text };
108
+ case "thinking_start":
109
+ return { type: "thinking:start", messageId };
110
+ case "thinking_delta":
111
+ return { type: "thinking:delta", messageId, text: event.text };
112
+ case "thinking_end":
113
+ return { type: "thinking:end", messageId };
114
+ case "tool_call_start":
115
+ return {
116
+ type: "tool:start",
117
+ messageId,
118
+ toolCallId: event.toolCallId,
119
+ toolName: event.toolName,
120
+ args: event.args
121
+ };
122
+ case "tool_call_end":
123
+ return {
124
+ type: "tool:complete",
125
+ messageId,
126
+ toolCallId: event.toolCallId,
127
+ toolName: event.toolName,
128
+ result: event.result
129
+ };
130
+ case "permission_request":
131
+ return {
132
+ type: "permission:request",
133
+ messageId,
134
+ toolName: event.request.toolName,
135
+ toolArgs: event.request.toolArgs
136
+ };
137
+ case "permission_response":
138
+ return {
139
+ type: "permission:response",
140
+ messageId,
141
+ toolName: event.toolName,
142
+ allowed: event.decision.allowed
143
+ };
144
+ case "usage_update":
145
+ return {
146
+ type: "usage",
147
+ promptTokens: event.promptTokens,
148
+ completionTokens: event.completionTokens,
149
+ model: event.model
150
+ };
151
+ case "error":
152
+ return {
153
+ type: "error",
154
+ error: event.error,
155
+ recoverable: event.recoverable,
156
+ code: event.code,
157
+ messageId
158
+ };
159
+ case "heartbeat":
160
+ return { type: "heartbeat" };
161
+ case "ask_user":
162
+ case "ask_user_response":
163
+ case "session_info":
164
+ case "done":
165
+ return null;
166
+ default:
167
+ return null;
168
+ }
169
+ }
170
+ async function* adaptAgentEvents(events, messageId) {
171
+ for await (const event of events) {
172
+ const chatEvent = agentEventToChatEvent(event, messageId);
173
+ if (chatEvent !== null) {
174
+ yield chatEvent;
175
+ }
176
+ }
177
+ }
178
+ function chatEventToAgentEvent(event) {
179
+ switch (event.type) {
180
+ case "message:delta":
181
+ return { type: "text_delta", text: event.text };
182
+ case "thinking:start":
183
+ return { type: "thinking_start" };
184
+ case "thinking:delta":
185
+ return { type: "thinking_delta", text: event.text };
186
+ case "thinking:end":
187
+ return { type: "thinking_end" };
188
+ case "tool:start":
189
+ return {
190
+ type: "tool_call_start",
191
+ toolCallId: event.toolCallId,
192
+ toolName: event.toolName,
193
+ args: event.args
194
+ };
195
+ case "tool:complete":
196
+ return {
197
+ type: "tool_call_end",
198
+ toolCallId: event.toolCallId,
199
+ toolName: event.toolName,
200
+ result: event.result
201
+ };
202
+ case "error":
203
+ return { type: "error", error: event.error, recoverable: event.recoverable, code: event.code };
204
+ default:
205
+ return null;
206
+ }
207
+ }
208
+
209
+ // src/chat/conversion.ts
210
+ function toAgentMessage(message) {
211
+ const textContent = getMessageText(message);
212
+ const toolCallParts = getMessageToolCalls(message);
213
+ switch (message.role) {
214
+ case "user":
215
+ return { role: "user", content: textContent };
216
+ case "assistant": {
217
+ const toolCalls = toolCallParts.length > 0 ? toolCallParts.map((p) => ({ id: p.toolCallId, name: p.name, args: p.args })) : void 0;
218
+ return {
219
+ role: "assistant",
220
+ content: textContent,
221
+ toolCalls
222
+ };
223
+ }
224
+ case "system":
225
+ return { role: "system", content: textContent };
226
+ }
227
+ }
228
+ function fromAgentMessage(message, id) {
229
+ const chatId = id ?? createChatId();
230
+ const now = (/* @__PURE__ */ new Date()).toISOString();
231
+ const parts = [];
232
+ const textContent = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n") : message.content ?? "";
233
+ if (textContent) {
234
+ parts.push({ type: "text", text: textContent, status: "complete" });
235
+ }
236
+ if (message.role === "assistant" && message.toolCalls) {
237
+ for (const tc of message.toolCalls) {
238
+ parts.push({
239
+ type: "tool_call",
240
+ toolCallId: tc.id,
241
+ name: tc.name,
242
+ args: tc.args,
243
+ status: "complete"
244
+ });
245
+ }
246
+ }
247
+ if (message.role === "tool" && message.toolResults) {
248
+ for (const tr of message.toolResults) {
249
+ parts.push({
250
+ type: "tool_call",
251
+ toolCallId: tr.toolCallId,
252
+ name: tr.name,
253
+ args: {},
254
+ result: tr.result,
255
+ status: "complete"
256
+ });
257
+ }
258
+ }
259
+ if (parts.length === 0) {
260
+ parts.push({ type: "text", text: "", status: "complete" });
261
+ }
262
+ const role = message.role === "tool" ? "assistant" : message.role;
263
+ return {
264
+ id: chatId,
265
+ role,
266
+ parts,
267
+ createdAt: now,
268
+ status: "complete"
269
+ };
270
+ }
271
+ function extractToolResults(message) {
272
+ return getMessageToolCalls(message).filter((p) => p.result !== void 0).map((p) => ({
273
+ toolCallId: p.toolCallId,
274
+ name: p.name,
275
+ result: p.result,
276
+ isError: p.status === "error" ? true : void 0
277
+ }));
278
+ }
279
+
280
+ export { adaptAgentEvents, agentEventToChatEvent, chatEventToAgentEvent, createChatId, createTextMessage, extractToolResults, fromAgentMessage, getMessageReasoning, getMessageText, getMessageToolCalls, isChatEvent, isChatMessage, isChatSession, isFilePart, isMessagePart, isObservableSession, isReasoningPart, isSourcePart, isTextPart, isToolCallPart, toAgentMessage, toChatId };
281
+ //# sourceMappingURL=core.js.map
282
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/chat/types.ts","../../src/chat/chat-utils.ts","../../src/chat/guards.ts","../../src/chat/bridge.ts","../../src/chat/conversion.ts"],"names":[],"mappings":"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","file":"core.js","sourcesContent":["/**\n * @witqq/agent-sdk — Chat domain types\n *\n * All type definitions and interfaces for the chat layer.\n * Pure types + ChatId generation (tightly coupled to branded type).\n */\n\nimport type { UsageData, ToolDefinition, ErrorCode } from \"../types.js\";\nimport type { AuthToken } from \"../auth/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 */\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\";\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 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// ─── Supporting Types ──────────────────────────────────────────\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/**\n * Session metadata tracking usage statistics and custom extensions.\n *\n * Updated automatically by session stores on each `addMessage()` call.\n * The generic `TCustom` parameter allows type-safe application-specific\n * metadata via the `custom` field.\n *\n * @typeParam TCustom - Shape of the `custom` field (defaults to `Record<string, unknown>`)\n */\nexport interface ChatSessionMetadata<TCustom extends Record<string, unknown> = Record<string, unknown>> {\n /** Number of messages in the session (updated by session store) */\n messageCount: number;\n /** Total token count across all messages in the session */\n totalTokens: number;\n /** Optional tags for session categorization and filtering */\n tags?: string[];\n /** Application-specific metadata — typed via the TCustom generic parameter */\n custom?: TCustom;\n}\n\n/** Chat session — a conversation with ordered messages (pure serializable data) */\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}\n\n/**\n * Reactive wrapper around ChatSession — provides subscribe/getSnapshot for\n * React useSyncExternalStore integration and lastMessage convenience getter.\n * Session stores may optionally return ObservableSession instances.\n */\nexport interface ObservableSession<TCustom extends Record<string, unknown> = Record<string, unknown>>\n extends ChatSession<TCustom> {\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 | undefined;\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 code?: ErrorCode;\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. Return null to reject the send. */\n onBeforeSend?(message: ChatMessage, context: ChatMiddlewareContext): ChatMessage | null | Promise<ChatMessage | null>;\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 to use for this request. Required for server-side runtime.send(). */\n model?: string;\n /** Per-call system prompt override (forwarded to the backend agent) */\n systemPrompt?: string;\n context?: Record<string, unknown>;\n /** Additional tools to include in this request */\n tools?: ToolDefinition[];\n}\n\n/** Options for runtime.send() — requires backend routing info */\nexport interface RuntimeSendOptions {\n /** Backend to route this request to (key in backends map) */\n backend: string;\n /** Authentication credentials for the backend factory */\n credentials: AuthToken;\n /** Model to use for this request */\n model: string;\n /** Per-call system prompt override (forwarded to the backend agent) */\n systemPrompt?: string;\n /** Abort signal */\n signal?: AbortSignal;\n /** Request-scoped context */\n context?: Record<string, unknown>;\n /** Additional tools */\n tools?: ToolDefinition[];\n}\n\n/**\n * @deprecated IChatProvider has been inlined into IChatBackend.\n * Import IChatBackend from \"@witqq/agent-sdk/chat/backends\" instead.\n * Kept as type alias for backward compatibility.\n */\nexport type IChatProvider = import(\"./backends/types.js\").IChatBackend;\n\n// ─── Factory Functions ─────────────────────────────────────────\n\n/**\n * Create a simple text ChatMessage.\n *\n * @param text - Message text content\n * @param role - Message role (default: \"user\")\n * @returns A complete ChatMessage with a single TextPart\n */\nexport function createTextMessage(text: string, role: ChatRole = \"user\"): ChatMessage {\n return {\n id: createChatId(),\n role,\n parts: [{ type: \"text\", text, status: \"complete\" }],\n createdAt: new Date().toISOString(),\n status: \"complete\",\n };\n}\n\n/** Type guard: checks if a session has reactive API (subscribe/getSnapshot) */\nexport function isObservableSession<TCustom extends Record<string, unknown> = Record<string, unknown>>(\n session: ChatSession<TCustom>,\n): session is ObservableSession<TCustom> {\n return \"subscribe\" in session && typeof (session as ObservableSession<TCustom>).subscribe === \"function\"\n && \"getSnapshot\" in session && typeof (session as ObservableSession<TCustom>).getSnapshot === \"function\";\n}\n","/**\n * @witqq/agent-sdk — Chat utility functions\n */\n\nimport type { ChatMessage, TextPart, ToolCallPart, ReasoningPart } from \"./types.js\";\nexport { createChatId, toChatId } from \"./types.js\";\n\n/**\n * Join all TextPart texts in a message\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 */\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 */\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 * @witqq/agent-sdk — Chat type guards\n */\n\nimport type {\n ChatMessage,\n ChatSession,\n MessagePart,\n TextPart,\n ToolCallPart,\n ReasoningPart,\n SourcePart,\n FilePart,\n ChatEvent,\n ChatEventType,\n} from \"./types.js\";\n\n/** Check if a value is a ChatMessage */\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\" || obj.role === \"assistant\" || obj.role === \"system\") &&\n Array.isArray(obj.parts) &&\n typeof obj.createdAt === \"string\" &&\n typeof obj.status === \"string\"\n );\n}\n\n/** Check if a value is a ChatSession */\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/** Check if a value is a MessagePart */\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\" || obj.type === \"reasoning\" || obj.type === \"tool_call\" || obj.type === \"source\" || obj.type === \"file\")\n );\n}\n\n/** Check if a value is a TextPart */\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/** Check if a value is a ToolCallPart */\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/** Check if a value is a ReasoningPart */\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/** Check if a value is a SourcePart */\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/** Check if a value is a FilePart */\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/** Check if a value is a ChatEvent */\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\", \"message:delta\", \"message:complete\",\n \"tool:start\", \"tool:complete\",\n \"thinking:start\", \"thinking:delta\", \"thinking:end\",\n \"permission:request\", \"permission:response\",\n \"usage\", \"session:created\", \"session:updated\",\n \"error\", \"typing:start\", \"typing:end\", \"heartbeat\", \"done\",\n ];\n return validTypes.includes(obj.type as ChatEventType);\n}\n","/**\n * @witqq/agent-sdk — AgentEvent ↔ ChatEvent bridge\n */\n\nimport type { AgentEvent, JSONValue } from \"../types.js\";\nimport type { ChatId, ChatEvent } from \"./types.js\";\n\n/**\n * Map a single AgentEvent to a ChatEvent (or null if no mapping)\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 code: event.code,\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 */\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 */\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, code: event.code };\n default:\n return null;\n }\n}\n","/**\n * @witqq/agent-sdk — ChatMessage ↔ agent-sdk Message conversion\n */\n\nimport type { Message, ToolCall, ToolResult, JSONValue } from \"../types.js\";\nimport type { ChatId, ChatMessage, ChatRole, MessagePart } from \"./types.js\";\nimport { createChatId, getMessageText, getMessageToolCalls } from \"./chat-utils.js\";\n\n/**\n * Convert a ChatMessage to agent-sdk Message format\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 */\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 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 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 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 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 */\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"]}
@@ -0,0 +1,273 @@
1
+ 'use strict';
2
+
3
+ // src/types/errors.ts
4
+ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
5
+ ErrorCode2["AUTH_EXPIRED"] = "AUTH_EXPIRED";
6
+ ErrorCode2["AUTH_INVALID"] = "AUTH_INVALID";
7
+ ErrorCode2["RATE_LIMIT"] = "RATE_LIMIT";
8
+ ErrorCode2["NETWORK"] = "NETWORK";
9
+ ErrorCode2["TIMEOUT"] = "TIMEOUT";
10
+ ErrorCode2["PROVIDER_ERROR"] = "PROVIDER_ERROR";
11
+ ErrorCode2["MODEL_NOT_FOUND"] = "MODEL_NOT_FOUND";
12
+ ErrorCode2["MODEL_OVERLOADED"] = "MODEL_OVERLOADED";
13
+ ErrorCode2["CONTEXT_OVERFLOW"] = "CONTEXT_OVERFLOW";
14
+ ErrorCode2["INVALID_INPUT"] = "INVALID_INPUT";
15
+ ErrorCode2["INVALID_RESPONSE"] = "INVALID_RESPONSE";
16
+ ErrorCode2["REENTRANCY"] = "REENTRANCY";
17
+ ErrorCode2["DISPOSED"] = "DISPOSED";
18
+ ErrorCode2["ABORTED"] = "ABORTED";
19
+ ErrorCode2["INVALID_TRANSITION"] = "INVALID_TRANSITION";
20
+ ErrorCode2["DEPENDENCY_MISSING"] = "DEPENDENCY_MISSING";
21
+ ErrorCode2["BACKEND_NOT_INSTALLED"] = "BACKEND_NOT_INSTALLED";
22
+ ErrorCode2["TOOL_EXECUTION"] = "TOOL_EXECUTION";
23
+ ErrorCode2["PERMISSION_DENIED"] = "PERMISSION_DENIED";
24
+ ErrorCode2["SESSION_NOT_FOUND"] = "SESSION_NOT_FOUND";
25
+ ErrorCode2["SESSION_EXPIRED"] = "SESSION_EXPIRED";
26
+ ErrorCode2["PROVIDER_NOT_FOUND"] = "PROVIDER_NOT_FOUND";
27
+ ErrorCode2["AUTH_REQUIRED"] = "AUTH_REQUIRED";
28
+ ErrorCode2["STORAGE_ERROR"] = "STORAGE_ERROR";
29
+ ErrorCode2["STORAGE_NOT_FOUND"] = "STORAGE_NOT_FOUND";
30
+ ErrorCode2["STORAGE_DUPLICATE_KEY"] = "STORAGE_DUPLICATE_KEY";
31
+ ErrorCode2["STORAGE_IO_ERROR"] = "STORAGE_IO_ERROR";
32
+ ErrorCode2["STORAGE_SERIALIZATION_ERROR"] = "STORAGE_SERIALIZATION_ERROR";
33
+ return ErrorCode2;
34
+ })(ErrorCode || {});
35
+
36
+ // src/errors.ts
37
+ var AgentSDKError = class extends Error {
38
+ /** @internal Marker for cross-bundle identity checks */
39
+ _agentSDKError = true;
40
+ /** Machine-readable error code. Prefer values from the ErrorCode enum. */
41
+ code;
42
+ /** Whether this error is safe to retry */
43
+ retryable;
44
+ /** HTTP status code hint for error classification */
45
+ httpStatus;
46
+ constructor(message, options) {
47
+ super(message, options);
48
+ this.name = "AgentSDKError";
49
+ this.code = options?.code;
50
+ this.retryable = options?.retryable ?? false;
51
+ this.httpStatus = options?.httpStatus;
52
+ }
53
+ /** Check if an error is an AgentSDKError (works across bundled copies) */
54
+ static is(error) {
55
+ return error instanceof Error && "_agentSDKError" in error && error._agentSDKError === true;
56
+ }
57
+ };
58
+
59
+ // src/chat/errors.ts
60
+ var ChatError = class extends AgentSDKError {
61
+ code;
62
+ retryable;
63
+ retryAfter;
64
+ timestamp;
65
+ constructor(message, options) {
66
+ super(message, {
67
+ cause: options.cause,
68
+ code: options.code,
69
+ retryable: options.retryable
70
+ });
71
+ this.name = "ChatError";
72
+ this.code = options.code;
73
+ this.retryable = options.retryable ?? false;
74
+ this.retryAfter = options.retryAfter;
75
+ this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
76
+ }
77
+ };
78
+ function classifyError(error) {
79
+ if (error instanceof ChatError) {
80
+ return error;
81
+ }
82
+ if (error instanceof Error) {
83
+ const msg = error.message.toLowerCase();
84
+ if (isNetworkError(msg)) {
85
+ return new ChatError(error.message, {
86
+ code: "NETWORK" /* NETWORK */,
87
+ retryable: true,
88
+ cause: error
89
+ });
90
+ }
91
+ if (isTimeoutPattern(msg)) {
92
+ return new ChatError(error.message, {
93
+ code: "TIMEOUT" /* TIMEOUT */,
94
+ retryable: true,
95
+ cause: error
96
+ });
97
+ }
98
+ if (isZodError(error)) {
99
+ return new ChatError(error.message, {
100
+ code: "INVALID_INPUT" /* INVALID_INPUT */,
101
+ retryable: false,
102
+ cause: error
103
+ });
104
+ }
105
+ const statusCode = extractStatusCode(error);
106
+ if (statusCode !== null) {
107
+ return classifyByStatusCode(statusCode, error);
108
+ }
109
+ if (isContextOverflow(msg)) {
110
+ return new ChatError(error.message, {
111
+ code: "CONTEXT_OVERFLOW" /* CONTEXT_OVERFLOW */,
112
+ retryable: false,
113
+ cause: error
114
+ });
115
+ }
116
+ }
117
+ const message = error instanceof Error ? error.message : String(error);
118
+ return new ChatError(message, {
119
+ code: "PROVIDER_ERROR" /* PROVIDER_ERROR */,
120
+ retryable: false,
121
+ cause: error
122
+ });
123
+ }
124
+ var NETWORK_PATTERNS = [
125
+ "econnrefused",
126
+ "econnreset",
127
+ "enotfound",
128
+ "etimedout",
129
+ "enetunreach",
130
+ "epipe",
131
+ "fetch failed",
132
+ "network error",
133
+ "network request failed",
134
+ "failed to fetch",
135
+ "dns lookup failed"
136
+ ];
137
+ function isNetworkError(msg) {
138
+ return NETWORK_PATTERNS.some((p) => msg.includes(p));
139
+ }
140
+ function isTimeoutPattern(msg) {
141
+ return msg.includes("timeout") || msg.includes("timed out") || msg.includes("deadline exceeded") || msg.includes("aborted due to timeout");
142
+ }
143
+ function isZodError(error) {
144
+ return error.name === "ZodError" || "issues" in error && Array.isArray(error.issues);
145
+ }
146
+ function extractStatusCode(error) {
147
+ const errRecord = error;
148
+ if (typeof errRecord.status === "number") return errRecord.status;
149
+ if (typeof errRecord.statusCode === "number") return errRecord.statusCode;
150
+ const match = error.message.match(/\b(4\d{2}|5\d{2})\b/);
151
+ return match ? parseInt(match[1], 10) : null;
152
+ }
153
+ function classifyByStatusCode(status, error) {
154
+ if (status === 401 || status === 403) {
155
+ return new ChatError(error.message, {
156
+ code: "AUTH_INVALID" /* AUTH_INVALID */,
157
+ retryable: false,
158
+ cause: error
159
+ });
160
+ }
161
+ if (status === 429) {
162
+ const retryAfterSeconds = extractRetryAfter(error);
163
+ return new ChatError(error.message, {
164
+ code: "RATE_LIMIT" /* RATE_LIMIT */,
165
+ retryable: true,
166
+ retryAfter: retryAfterSeconds != null ? retryAfterSeconds * 1e3 : void 0,
167
+ cause: error
168
+ });
169
+ }
170
+ if (status >= 500) {
171
+ return new ChatError(error.message, {
172
+ code: "PROVIDER_ERROR" /* PROVIDER_ERROR */,
173
+ retryable: true,
174
+ cause: error
175
+ });
176
+ }
177
+ if (status >= 400 && status < 500) {
178
+ return new ChatError(error.message, {
179
+ code: "INVALID_INPUT" /* INVALID_INPUT */,
180
+ retryable: false,
181
+ cause: error
182
+ });
183
+ }
184
+ return new ChatError(error.message, {
185
+ code: "NETWORK" /* NETWORK */,
186
+ retryable: true,
187
+ cause: error
188
+ });
189
+ }
190
+ function extractRetryAfter(error) {
191
+ const errRecord = error;
192
+ if (typeof errRecord.retryAfter === "number") return errRecord.retryAfter;
193
+ const match = error.message.match(/retry.after[:\s]*(\d+)/i);
194
+ return match ? parseInt(match[1], 10) : void 0;
195
+ }
196
+ function isContextOverflow(msg) {
197
+ return msg.includes("context length exceeded") || msg.includes("maximum context length") || msg.includes("context window") || msg.includes("token limit") || msg.includes("too many tokens");
198
+ }
199
+ var ExponentialBackoffStrategy = class {
200
+ baseMs;
201
+ maxMs;
202
+ maxAttempts;
203
+ jitter;
204
+ constructor(options) {
205
+ this.baseMs = options?.baseMs ?? 1e3;
206
+ this.maxMs = options?.maxMs ?? 3e4;
207
+ this.maxAttempts = options?.maxAttempts ?? 3;
208
+ this.jitter = Math.max(0, Math.min(1, options?.jitter ?? 0.1));
209
+ }
210
+ nextDelay(attempt, error) {
211
+ if (attempt >= this.maxAttempts) return null;
212
+ if (!error.retryable) return null;
213
+ if (error.code === "RATE_LIMIT" /* RATE_LIMIT */ && error.retryAfter) {
214
+ return error.retryAfter;
215
+ }
216
+ const delay = Math.min(this.baseMs * Math.pow(2, attempt), this.maxMs);
217
+ const jitterAmount = delay * this.jitter * (Math.random() * 2 - 1);
218
+ return Math.max(0, Math.round(delay + jitterAmount));
219
+ }
220
+ };
221
+ async function withRetry(fn, strategy, options) {
222
+ let attempt = 0;
223
+ for (; ; ) {
224
+ try {
225
+ return await fn();
226
+ } catch (raw) {
227
+ const error = classifyError(raw);
228
+ const delay = strategy.nextDelay(attempt, error);
229
+ if (delay === null) {
230
+ throw error;
231
+ }
232
+ if (options?.signal?.aborted) {
233
+ throw error;
234
+ }
235
+ options?.onRetry?.(error, attempt, delay);
236
+ await sleep(delay, options?.signal);
237
+ attempt++;
238
+ }
239
+ }
240
+ }
241
+ function isRetryable(error) {
242
+ if (error instanceof ChatError) {
243
+ return error.retryable;
244
+ }
245
+ const classified = classifyError(error);
246
+ return classified.retryable;
247
+ }
248
+ function sleep(ms, signal) {
249
+ return new Promise((resolve, reject) => {
250
+ if (signal?.aborted) {
251
+ reject(new ChatError("Retry aborted", { code: "ABORTED" /* ABORTED */ }));
252
+ return;
253
+ }
254
+ const timer = setTimeout(resolve, ms);
255
+ signal?.addEventListener(
256
+ "abort",
257
+ () => {
258
+ clearTimeout(timer);
259
+ reject(new ChatError("Retry aborted", { code: "ABORTED" /* ABORTED */ }));
260
+ },
261
+ { once: true }
262
+ );
263
+ });
264
+ }
265
+
266
+ exports.ChatError = ChatError;
267
+ exports.ErrorCode = ErrorCode;
268
+ exports.ExponentialBackoffStrategy = ExponentialBackoffStrategy;
269
+ exports.classifyError = classifyError;
270
+ exports.isRetryable = isRetryable;
271
+ exports.withRetry = withRetry;
272
+ //# sourceMappingURL=errors.cjs.map
273
+ //# sourceMappingURL=errors.cjs.map