@witqq/agent-sdk 0.7.0 → 0.9.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 (154) hide show
  1. package/dist/{types-CqvUAYxt.d.ts → agent-C6H2CgJA.d.cts} +139 -102
  2. package/dist/{types-CqvUAYxt.d.cts → agent-F7oB6eKp.d.ts} +139 -102
  3. package/dist/auth/index.cjs +72 -1
  4. package/dist/auth/index.cjs.map +1 -1
  5. package/dist/auth/index.d.cts +21 -154
  6. package/dist/auth/index.d.ts +21 -154
  7. package/dist/auth/index.js +72 -1
  8. package/dist/auth/index.js.map +1 -1
  9. package/dist/backends/claude.cjs +480 -261
  10. package/dist/backends/claude.cjs.map +1 -1
  11. package/dist/backends/claude.d.cts +3 -1
  12. package/dist/backends/claude.d.ts +3 -1
  13. package/dist/backends/claude.js +480 -261
  14. package/dist/backends/claude.js.map +1 -1
  15. package/dist/backends/copilot.cjs +337 -112
  16. package/dist/backends/copilot.cjs.map +1 -1
  17. package/dist/backends/copilot.d.cts +12 -4
  18. package/dist/backends/copilot.d.ts +12 -4
  19. package/dist/backends/copilot.js +337 -112
  20. package/dist/backends/copilot.js.map +1 -1
  21. package/dist/backends/mock-llm.cjs +719 -0
  22. package/dist/backends/mock-llm.cjs.map +1 -0
  23. package/dist/backends/mock-llm.d.cts +37 -0
  24. package/dist/backends/mock-llm.d.ts +37 -0
  25. package/dist/backends/mock-llm.js +717 -0
  26. package/dist/backends/mock-llm.js.map +1 -0
  27. package/dist/backends/vercel-ai.cjs +301 -61
  28. package/dist/backends/vercel-ai.cjs.map +1 -1
  29. package/dist/backends/vercel-ai.d.cts +3 -1
  30. package/dist/backends/vercel-ai.d.ts +3 -1
  31. package/dist/backends/vercel-ai.js +301 -61
  32. package/dist/backends/vercel-ai.js.map +1 -1
  33. package/dist/backends-Cno0gZjy.d.cts +114 -0
  34. package/dist/backends-Cno0gZjy.d.ts +114 -0
  35. package/dist/chat/accumulator.cjs +1 -1
  36. package/dist/chat/accumulator.cjs.map +1 -1
  37. package/dist/chat/accumulator.d.cts +5 -2
  38. package/dist/chat/accumulator.d.ts +5 -2
  39. package/dist/chat/accumulator.js +1 -1
  40. package/dist/chat/accumulator.js.map +1 -1
  41. package/dist/chat/backends.cjs +1084 -821
  42. package/dist/chat/backends.cjs.map +1 -1
  43. package/dist/chat/backends.d.cts +10 -6
  44. package/dist/chat/backends.d.ts +10 -6
  45. package/dist/chat/backends.js +1082 -800
  46. package/dist/chat/backends.js.map +1 -1
  47. package/dist/chat/context.cjs +50 -0
  48. package/dist/chat/context.cjs.map +1 -1
  49. package/dist/chat/context.d.cts +27 -3
  50. package/dist/chat/context.d.ts +27 -3
  51. package/dist/chat/context.js +50 -0
  52. package/dist/chat/context.js.map +1 -1
  53. package/dist/chat/core.cjs +60 -27
  54. package/dist/chat/core.cjs.map +1 -1
  55. package/dist/chat/core.d.cts +41 -382
  56. package/dist/chat/core.d.ts +41 -382
  57. package/dist/chat/core.js +58 -28
  58. package/dist/chat/core.js.map +1 -1
  59. package/dist/chat/errors.cjs +48 -26
  60. package/dist/chat/errors.cjs.map +1 -1
  61. package/dist/chat/errors.d.cts +6 -31
  62. package/dist/chat/errors.d.ts +6 -31
  63. package/dist/chat/errors.js +48 -25
  64. package/dist/chat/errors.js.map +1 -1
  65. package/dist/chat/events.cjs.map +1 -1
  66. package/dist/chat/events.d.cts +6 -2
  67. package/dist/chat/events.d.ts +6 -2
  68. package/dist/chat/events.js.map +1 -1
  69. package/dist/chat/index.cjs +1612 -1125
  70. package/dist/chat/index.cjs.map +1 -1
  71. package/dist/chat/index.d.cts +35 -10
  72. package/dist/chat/index.d.ts +35 -10
  73. package/dist/chat/index.js +1600 -1097
  74. package/dist/chat/index.js.map +1 -1
  75. package/dist/chat/react/theme.css +2517 -0
  76. package/dist/chat/react.cjs +2212 -1158
  77. package/dist/chat/react.cjs.map +1 -1
  78. package/dist/chat/react.d.cts +665 -122
  79. package/dist/chat/react.d.ts +665 -122
  80. package/dist/chat/react.js +2191 -1156
  81. package/dist/chat/react.js.map +1 -1
  82. package/dist/chat/runtime.cjs +405 -186
  83. package/dist/chat/runtime.cjs.map +1 -1
  84. package/dist/chat/runtime.d.cts +92 -28
  85. package/dist/chat/runtime.d.ts +92 -28
  86. package/dist/chat/runtime.js +405 -186
  87. package/dist/chat/runtime.js.map +1 -1
  88. package/dist/chat/server.cjs +2247 -212
  89. package/dist/chat/server.cjs.map +1 -1
  90. package/dist/chat/server.d.cts +451 -90
  91. package/dist/chat/server.d.ts +451 -90
  92. package/dist/chat/server.js +2234 -213
  93. package/dist/chat/server.js.map +1 -1
  94. package/dist/chat/sessions.cjs +64 -66
  95. package/dist/chat/sessions.cjs.map +1 -1
  96. package/dist/chat/sessions.d.cts +37 -118
  97. package/dist/chat/sessions.d.ts +37 -118
  98. package/dist/chat/sessions.js +65 -67
  99. package/dist/chat/sessions.js.map +1 -1
  100. package/dist/chat/sqlite.cjs +536 -0
  101. package/dist/chat/sqlite.cjs.map +1 -0
  102. package/dist/chat/sqlite.d.cts +164 -0
  103. package/dist/chat/sqlite.d.ts +164 -0
  104. package/dist/chat/sqlite.js +527 -0
  105. package/dist/chat/sqlite.js.map +1 -0
  106. package/dist/chat/state.cjs +14 -1
  107. package/dist/chat/state.cjs.map +1 -1
  108. package/dist/chat/state.d.cts +5 -2
  109. package/dist/chat/state.d.ts +5 -2
  110. package/dist/chat/state.js +14 -1
  111. package/dist/chat/state.js.map +1 -1
  112. package/dist/chat/storage.cjs +58 -33
  113. package/dist/chat/storage.cjs.map +1 -1
  114. package/dist/chat/storage.d.cts +18 -8
  115. package/dist/chat/storage.d.ts +18 -8
  116. package/dist/chat/storage.js +59 -34
  117. package/dist/chat/storage.js.map +1 -1
  118. package/dist/errors-C-so0M4t.d.cts +33 -0
  119. package/dist/errors-C-so0M4t.d.ts +33 -0
  120. package/dist/errors-CmVvczxZ.d.cts +28 -0
  121. package/dist/errors-CmVvczxZ.d.ts +28 -0
  122. package/dist/{in-process-transport-C2oPTYs6.d.ts → in-process-transport-7EIit9Xk.d.ts} +72 -33
  123. package/dist/{in-process-transport-DG-w5G6k.d.cts → in-process-transport-Ct9YcX8I.d.cts} +72 -33
  124. package/dist/index.cjs +354 -60
  125. package/dist/index.cjs.map +1 -1
  126. package/dist/index.d.cts +294 -123
  127. package/dist/index.d.ts +294 -123
  128. package/dist/index.js +347 -60
  129. package/dist/index.js.map +1 -1
  130. package/dist/provider-types-PTSlRPNB.d.cts +39 -0
  131. package/dist/provider-types-PTSlRPNB.d.ts +39 -0
  132. package/dist/refresh-manager-B81PpYBr.d.cts +153 -0
  133. package/dist/refresh-manager-Dlv_iNZi.d.ts +153 -0
  134. package/dist/testing.cjs +1107 -0
  135. package/dist/testing.cjs.map +1 -0
  136. package/dist/testing.d.cts +144 -0
  137. package/dist/testing.d.ts +144 -0
  138. package/dist/testing.js +1101 -0
  139. package/dist/testing.js.map +1 -0
  140. package/dist/token-store-CSUBgYwn.d.ts +48 -0
  141. package/dist/token-store-CuC4hB9Z.d.cts +48 -0
  142. package/dist/{transport-DX1Nhm4N.d.cts → transport-DLWCN18G.d.cts} +5 -4
  143. package/dist/{transport-D1OaUgRk.d.ts → transport-DsuS-GeM.d.ts} +5 -4
  144. package/dist/{types-CGF7AEX1.d.cts → types-4vbcmPTp.d.cts} +4 -2
  145. package/dist/{types-Bh5AhqD-.d.ts → types-BxggH0Yh.d.ts} +4 -2
  146. package/dist/types-DgtI1hzh.d.ts +364 -0
  147. package/dist/types-DkSXALKg.d.cts +364 -0
  148. package/package.json +41 -5
  149. package/LICENSE +0 -21
  150. package/README.md +0 -948
  151. package/dist/errors-BDLbNu9w.d.cts +0 -13
  152. package/dist/errors-BDLbNu9w.d.ts +0 -13
  153. package/dist/types-DLZzlJxt.d.ts +0 -39
  154. package/dist/types-tE0CXwBl.d.cts +0 -39
package/dist/index.js CHANGED
@@ -1,8 +1,77 @@
1
- import * as fs from 'fs';
1
+ import * as fsp from 'fs/promises';
2
2
  import * as path from 'path';
3
3
  import * as os from 'os';
4
4
 
5
- // src/types.ts
5
+ // src/types/errors.ts
6
+ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
7
+ ErrorCode2["AUTH_EXPIRED"] = "AUTH_EXPIRED";
8
+ ErrorCode2["AUTH_INVALID"] = "AUTH_INVALID";
9
+ ErrorCode2["RATE_LIMIT"] = "RATE_LIMIT";
10
+ ErrorCode2["NETWORK"] = "NETWORK";
11
+ ErrorCode2["TIMEOUT"] = "TIMEOUT";
12
+ ErrorCode2["PROVIDER_ERROR"] = "PROVIDER_ERROR";
13
+ ErrorCode2["MODEL_NOT_FOUND"] = "MODEL_NOT_FOUND";
14
+ ErrorCode2["MODEL_OVERLOADED"] = "MODEL_OVERLOADED";
15
+ ErrorCode2["CONTEXT_OVERFLOW"] = "CONTEXT_OVERFLOW";
16
+ ErrorCode2["INVALID_INPUT"] = "INVALID_INPUT";
17
+ ErrorCode2["INVALID_RESPONSE"] = "INVALID_RESPONSE";
18
+ ErrorCode2["REENTRANCY"] = "REENTRANCY";
19
+ ErrorCode2["DISPOSED"] = "DISPOSED";
20
+ ErrorCode2["ABORTED"] = "ABORTED";
21
+ ErrorCode2["INVALID_TRANSITION"] = "INVALID_TRANSITION";
22
+ ErrorCode2["DEPENDENCY_MISSING"] = "DEPENDENCY_MISSING";
23
+ ErrorCode2["BACKEND_NOT_INSTALLED"] = "BACKEND_NOT_INSTALLED";
24
+ ErrorCode2["TOOL_EXECUTION"] = "TOOL_EXECUTION";
25
+ ErrorCode2["PERMISSION_DENIED"] = "PERMISSION_DENIED";
26
+ ErrorCode2["SESSION_NOT_FOUND"] = "SESSION_NOT_FOUND";
27
+ ErrorCode2["SESSION_EXPIRED"] = "SESSION_EXPIRED";
28
+ ErrorCode2["PROVIDER_NOT_FOUND"] = "PROVIDER_NOT_FOUND";
29
+ ErrorCode2["AUTH_REQUIRED"] = "AUTH_REQUIRED";
30
+ ErrorCode2["STORAGE_ERROR"] = "STORAGE_ERROR";
31
+ ErrorCode2["STORAGE_NOT_FOUND"] = "STORAGE_NOT_FOUND";
32
+ ErrorCode2["STORAGE_DUPLICATE_KEY"] = "STORAGE_DUPLICATE_KEY";
33
+ ErrorCode2["STORAGE_IO_ERROR"] = "STORAGE_IO_ERROR";
34
+ ErrorCode2["STORAGE_SERIALIZATION_ERROR"] = "STORAGE_SERIALIZATION_ERROR";
35
+ return ErrorCode2;
36
+ })(ErrorCode || {});
37
+ var RECOVERABLE_CODES = /* @__PURE__ */ new Set([
38
+ "TIMEOUT" /* TIMEOUT */,
39
+ "RATE_LIMIT" /* RATE_LIMIT */,
40
+ "NETWORK" /* NETWORK */,
41
+ "TOOL_EXECUTION" /* TOOL_EXECUTION */,
42
+ "MODEL_OVERLOADED" /* MODEL_OVERLOADED */,
43
+ "PROVIDER_ERROR" /* PROVIDER_ERROR */
44
+ ]);
45
+ function isRecoverableErrorCode(code) {
46
+ return RECOVERABLE_CODES.has(code);
47
+ }
48
+ function classifyAgentError(error) {
49
+ const msg = (error instanceof Error ? error.message : error).toLowerCase();
50
+ if (msg.includes("timeout") || msg.includes("timed out") || msg.includes("timedout") || msg.includes("etimedout")) {
51
+ return "TIMEOUT" /* TIMEOUT */;
52
+ }
53
+ if (msg.includes("rate limit") || msg.includes("rate_limit") || msg.includes("429") || msg.includes("too many requests")) {
54
+ return "RATE_LIMIT" /* RATE_LIMIT */;
55
+ }
56
+ if (msg.includes("unauthorized") || msg.includes("401") || msg.includes("auth") && (msg.includes("expired") || msg.includes("invalid") || msg.includes("denied") || msg.includes("failed"))) {
57
+ return "AUTH_EXPIRED" /* AUTH_EXPIRED */;
58
+ }
59
+ if (msg.includes("econnrefused") || msg.includes("econnreset") || msg.includes("enotfound") || msg.includes("network") || msg.includes("fetch failed") || msg.includes("socket hang up")) {
60
+ return "NETWORK" /* NETWORK */;
61
+ }
62
+ if (msg.includes("subprocess") || msg.includes("process exited") || msg.includes("spawn") || msg.includes("enoent") || msg.includes("killed")) {
63
+ return "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */;
64
+ }
65
+ if (msg.includes("abort") || msg.includes("cancel")) {
66
+ return "ABORTED" /* ABORTED */;
67
+ }
68
+ if (msg.includes("500") || msg.includes("502") || msg.includes("503") || msg.includes("internal server error") || msg.includes("service unavailable") || msg.includes("bad gateway") || msg.includes("overloaded")) {
69
+ return "PROVIDER_ERROR" /* PROVIDER_ERROR */;
70
+ }
71
+ return "PROVIDER_ERROR" /* PROVIDER_ERROR */;
72
+ }
73
+
74
+ // src/types/guards.ts
6
75
  function isToolDefinition(tool) {
7
76
  return "execute" in tool && typeof tool.execute === "function";
8
77
  }
@@ -21,9 +90,18 @@ function getTextContent(content) {
21
90
  var AgentSDKError = class extends Error {
22
91
  /** @internal Marker for cross-bundle identity checks */
23
92
  _agentSDKError = true;
93
+ /** Machine-readable error code. Prefer values from the ErrorCode enum. */
94
+ code;
95
+ /** Whether this error is safe to retry */
96
+ retryable;
97
+ /** HTTP status code hint for error classification */
98
+ httpStatus;
24
99
  constructor(message, options) {
25
100
  super(message, options);
26
101
  this.name = "AgentSDKError";
102
+ this.code = options?.code;
103
+ this.retryable = options?.retryable ?? false;
104
+ this.httpStatus = options?.httpStatus;
27
105
  }
28
106
  /** Check if an error is an AgentSDKError (works across bundled copies) */
29
107
  static is(error) {
@@ -32,20 +110,25 @@ var AgentSDKError = class extends Error {
32
110
  };
33
111
  var ReentrancyError = class extends AgentSDKError {
34
112
  constructor() {
35
- super("Agent is already running. Await the current run before starting another.");
113
+ super("Agent is already running. Await the current run before starting another.", {
114
+ code: "REENTRANCY" /* REENTRANCY */
115
+ });
36
116
  this.name = "ReentrancyError";
37
117
  }
38
118
  };
39
119
  var DisposedError = class extends AgentSDKError {
40
120
  constructor(entity) {
41
- super(`${entity} has been disposed and cannot be used.`);
121
+ super(`${entity} has been disposed and cannot be used.`, {
122
+ code: "DISPOSED" /* DISPOSED */
123
+ });
42
124
  this.name = "DisposedError";
43
125
  }
44
126
  };
45
127
  var BackendNotFoundError = class extends AgentSDKError {
46
128
  constructor(backend) {
47
129
  super(
48
- `Unknown backend: "${backend}". Built-in: copilot, claude, vercel-ai. Custom: use registerBackend() first.`
130
+ `Unknown backend: "${backend}". Built-in: copilot, claude, vercel-ai. Custom: use registerBackend() first.`,
131
+ { code: "BACKEND_NOT_INSTALLED" /* BACKEND_NOT_INSTALLED */ }
49
132
  );
50
133
  this.name = "BackendNotFoundError";
51
134
  }
@@ -58,41 +141,56 @@ var BackendAlreadyRegisteredError = class extends AgentSDKError {
58
141
  };
59
142
  var SubprocessError = class extends AgentSDKError {
60
143
  constructor(message, options) {
61
- super(message, options);
144
+ super(message, { ...options, code: "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */ });
62
145
  this.name = "SubprocessError";
63
146
  }
64
147
  };
65
148
  var DependencyError = class extends AgentSDKError {
66
149
  packageName;
67
150
  constructor(packageName) {
68
- super(`${packageName} is not installed. Install it: npm install ${packageName}`);
151
+ super(`${packageName} is not installed. Install it: npm install ${packageName}`, {
152
+ code: "DEPENDENCY_MISSING" /* DEPENDENCY_MISSING */
153
+ });
69
154
  this.name = "DependencyError";
70
155
  this.packageName = packageName;
71
156
  }
72
157
  };
73
158
  var AbortError = class extends AgentSDKError {
74
159
  constructor() {
75
- super("Agent run was aborted.");
160
+ super("Agent run was aborted.", { code: "ABORTED" /* ABORTED */ });
76
161
  this.name = "AbortError";
77
162
  }
78
163
  };
79
164
  var ToolExecutionError = class extends AgentSDKError {
80
165
  toolName;
81
166
  constructor(toolName, message, options) {
82
- super(`Tool "${toolName}" failed: ${message}`, options);
167
+ super(`Tool "${toolName}" failed: ${message}`, { ...options, code: "TOOL_EXECUTION" /* TOOL_EXECUTION */ });
83
168
  this.name = "ToolExecutionError";
84
169
  this.toolName = toolName;
85
170
  }
86
171
  };
172
+ var ActivityTimeoutError = class extends AgentSDKError {
173
+ constructor(timeoutMs) {
174
+ super(`Stream activity timeout: no event received within ${timeoutMs}ms.`, {
175
+ code: "TIMEOUT" /* TIMEOUT */,
176
+ retryable: true
177
+ });
178
+ this.name = "ActivityTimeoutError";
179
+ }
180
+ };
87
181
  var StructuredOutputError = class extends AgentSDKError {
88
182
  constructor(message, options) {
89
- super(`Structured output error: ${message}`, options);
183
+ super(`Structured output error: ${message}`, { ...options, code: "INVALID_RESPONSE" /* INVALID_RESPONSE */ });
90
184
  this.name = "StructuredOutputError";
91
185
  }
92
186
  };
93
187
 
94
188
  // src/registry.ts
95
189
  var registry = /* @__PURE__ */ new Map();
190
+ var serviceCache = /* @__PURE__ */ new Map();
191
+ function configCacheKey(name, configId) {
192
+ return `${name}:${configId}`;
193
+ }
96
194
  function registerBackend(name, factory) {
97
195
  if (registry.has(name)) {
98
196
  throw new BackendAlreadyRegisteredError(name);
@@ -103,49 +201,94 @@ function unregisterBackend(name) {
103
201
  return registry.delete(name);
104
202
  }
105
203
  function hasBackend(name) {
106
- return registry.has(name) || isBuiltinName(name);
204
+ return registry.has(name) || lazyLoaders.has(name);
107
205
  }
108
206
  function listBackends() {
109
207
  const names = new Set(registry.keys());
110
- for (const builtin of BUILTIN_BACKENDS) {
111
- names.add(builtin);
208
+ for (const name of lazyLoaders.keys()) {
209
+ names.add(name);
112
210
  }
113
211
  return [...names];
114
212
  }
115
213
  function resetRegistry() {
116
214
  registry.clear();
215
+ serviceCache.clear();
117
216
  }
118
- var BUILTIN_BACKENDS = /* @__PURE__ */ new Set([
119
- "copilot",
120
- "claude",
121
- "vercel-ai"
122
- ]);
123
- function isBuiltinName(name) {
124
- return BUILTIN_BACKENDS.has(name);
217
+ async function disposeBackend(name, configId) {
218
+ if (configId !== void 0) {
219
+ const key = configCacheKey(name, configId);
220
+ const svc = serviceCache.get(key);
221
+ if (!svc) return 0;
222
+ serviceCache.delete(key);
223
+ await svc.dispose();
224
+ return 1;
225
+ }
226
+ const prefix = `${name}:`;
227
+ const toDispose = [];
228
+ for (const [key, svc] of serviceCache) {
229
+ if (key.startsWith(prefix)) {
230
+ toDispose.push(svc);
231
+ serviceCache.delete(key);
232
+ }
233
+ }
234
+ await Promise.all(toDispose.map((s) => s.dispose()));
235
+ return toDispose.length;
236
+ }
237
+ function listConfigs(name) {
238
+ const prefix = `${name}:`;
239
+ const ids = [];
240
+ for (const key of serviceCache.keys()) {
241
+ if (key.startsWith(prefix)) {
242
+ ids.push(key.slice(prefix.length));
243
+ }
244
+ }
245
+ return ids;
125
246
  }
126
- async function loadBuiltinFactory(name) {
127
- switch (name) {
128
- case "copilot": {
247
+ var lazyLoaders = /* @__PURE__ */ new Map([
248
+ [
249
+ "copilot",
250
+ async () => {
129
251
  const mod = await import('./backends/copilot.js');
130
252
  return (opts) => mod.createCopilotService(opts);
131
253
  }
132
- case "claude": {
254
+ ],
255
+ [
256
+ "claude",
257
+ async () => {
133
258
  const mod = await import('./backends/claude.js');
134
259
  return (opts) => mod.createClaudeService(opts);
135
260
  }
136
- case "vercel-ai": {
261
+ ],
262
+ [
263
+ "vercel-ai",
264
+ async () => {
137
265
  const mod = await import('./backends/vercel-ai.js');
138
266
  return (opts) => mod.createVercelAIService(opts);
139
267
  }
140
- }
268
+ ]
269
+ ]);
270
+ function registerLazyBackend(name, loader) {
271
+ lazyLoaders.set(name, loader);
272
+ }
273
+ async function createAgentService(name, options, configId) {
274
+ if (configId !== void 0) {
275
+ const key = configCacheKey(name, configId);
276
+ const cached = serviceCache.get(key);
277
+ if (cached) return cached;
278
+ const service = await createServiceInstance(name, options);
279
+ serviceCache.set(key, service);
280
+ return service;
281
+ }
282
+ return createServiceInstance(name, options);
141
283
  }
142
- async function createAgentService(name, options) {
284
+ async function createServiceInstance(name, options) {
143
285
  const entry = registry.get(name);
144
286
  if (entry) {
145
287
  return entry.factory(options);
146
288
  }
147
- if (isBuiltinName(name)) {
148
- const factory = await loadBuiltinFactory(name);
289
+ const loader = lazyLoaders.get(name);
290
+ if (loader) {
291
+ const factory = await loader();
149
292
  registry.set(name, { factory, builtin: true });
150
293
  return factory(options);
151
294
  }
@@ -158,6 +301,7 @@ var BaseAgent = class {
158
301
  abortController = null;
159
302
  config;
160
303
  _cleanupExternalSignal = null;
304
+ _streamMiddleware = [];
161
305
  /** CLI session ID for persistent mode. Override in backends that support it. */
162
306
  get sessionId() {
163
307
  return void 0;
@@ -173,8 +317,11 @@ var BaseAgent = class {
173
317
  this.state = "running";
174
318
  try {
175
319
  const messages = [{ role: "user", content: prompt }];
176
- const result = await this.executeRun(messages, options, ac.signal);
177
- this.enrichAndNotifyUsage(result);
320
+ const result = await this.withRetry(
321
+ () => this.executeRun(messages, options, ac.signal),
322
+ options
323
+ );
324
+ this.enrichAndNotifyUsage(result, options);
178
325
  return result;
179
326
  } finally {
180
327
  this.cleanupRun();
@@ -186,8 +333,11 @@ var BaseAgent = class {
186
333
  const ac = this.createAbortController(options?.signal);
187
334
  this.state = "running";
188
335
  try {
189
- const result = await this.executeRun(messages, options, ac.signal);
190
- this.enrichAndNotifyUsage(result);
336
+ const result = await this.withRetry(
337
+ () => this.executeRun(messages, options, ac.signal),
338
+ options
339
+ );
340
+ this.enrichAndNotifyUsage(result, options);
191
341
  return result;
192
342
  } finally {
193
343
  this.cleanupRun();
@@ -200,13 +350,11 @@ var BaseAgent = class {
200
350
  this.state = "running";
201
351
  try {
202
352
  const messages = [{ role: "user", content: prompt }];
203
- const result = await this.executeRunStructured(
204
- messages,
205
- schema,
206
- options,
207
- ac.signal
353
+ const result = await this.withRetry(
354
+ () => this.executeRunStructured(messages, schema, options, ac.signal),
355
+ options
208
356
  );
209
- this.enrichAndNotifyUsage(result);
357
+ this.enrichAndNotifyUsage(result, options);
210
358
  return result;
211
359
  } finally {
212
360
  this.cleanupRun();
@@ -219,8 +367,10 @@ var BaseAgent = class {
219
367
  this.state = "streaming";
220
368
  try {
221
369
  const messages = [{ role: "user", content: prompt }];
222
- const enriched = this.enrichStream(this.executeStream(messages, options, ac.signal));
223
- yield* this.heartbeatStream(enriched);
370
+ yield* this.streamWithRetry(
371
+ () => this.applyStreamPipeline(this.executeStream(messages, options, ac.signal), options, ac),
372
+ options
373
+ );
224
374
  } finally {
225
375
  this.cleanupRun();
226
376
  }
@@ -231,12 +381,37 @@ var BaseAgent = class {
231
381
  const ac = this.createAbortController(options?.signal);
232
382
  this.state = "streaming";
233
383
  try {
234
- const enriched = this.enrichStream(this.executeStream(messages, options, ac.signal));
235
- yield* this.heartbeatStream(enriched);
384
+ yield* this.streamWithRetry(
385
+ () => this.applyStreamPipeline(this.executeStream(messages, options, ac.signal), options, ac),
386
+ options
387
+ );
236
388
  } finally {
237
389
  this.cleanupRun();
238
390
  }
239
391
  }
392
+ /** Register a stream middleware. Applied in registration order after built-in transforms. */
393
+ addStreamMiddleware(middleware) {
394
+ this.guardDisposed();
395
+ this._streamMiddleware.push(middleware);
396
+ }
397
+ /** Apply built-in transforms (enrich→timeout→heartbeat) then custom middleware */
398
+ async *applyStreamPipeline(source, options, ac) {
399
+ let stream = this.enrichStream(source, options);
400
+ stream = this.activityTimeoutStream(stream, options?.activityTimeoutMs, ac);
401
+ stream = this.heartbeatStream(stream);
402
+ if (this._streamMiddleware.length > 0) {
403
+ const ctx = {
404
+ model: options.model,
405
+ backend: this.backendName,
406
+ abortController: ac,
407
+ config: Object.freeze({ ...this.config })
408
+ };
409
+ for (const mw of this._streamMiddleware) {
410
+ stream = mw(stream, ctx);
411
+ }
412
+ }
413
+ yield* stream;
414
+ }
240
415
  abort() {
241
416
  if (this.abortController) {
242
417
  this.abortController.abort();
@@ -259,26 +434,109 @@ var BaseAgent = class {
259
434
  this.abort();
260
435
  this.state = "disposed";
261
436
  }
437
+ // ─── Retry Logic ─────────────────────────────────────────────
438
+ /** Check if an error should be retried given the retry configuration. */
439
+ isRetryableError(error, retry) {
440
+ if (error instanceof AbortError || error instanceof ReentrancyError || error instanceof DisposedError) {
441
+ return false;
442
+ }
443
+ if (AgentSDKError.is(error)) {
444
+ if (retry.retryableErrors && retry.retryableErrors.length > 0 && error.code) {
445
+ return retry.retryableErrors.includes(error.code);
446
+ }
447
+ if (error.retryable) return true;
448
+ if (error.code) return isRecoverableErrorCode(error.code);
449
+ }
450
+ return false;
451
+ }
452
+ /** Execute a function with retry logic per RetryConfig. */
453
+ async withRetry(fn, options) {
454
+ const retry = options?.retry;
455
+ if (!retry || !retry.maxRetries || retry.maxRetries <= 0) {
456
+ return fn();
457
+ }
458
+ const maxRetries = retry.maxRetries;
459
+ const initialDelay = retry.initialDelayMs ?? 1e3;
460
+ const multiplier = retry.backoffMultiplier ?? 2;
461
+ let lastError;
462
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
463
+ try {
464
+ return await fn();
465
+ } catch (err) {
466
+ lastError = err;
467
+ if (attempt >= maxRetries || !this.isRetryableError(err, retry)) {
468
+ throw err;
469
+ }
470
+ const delay = initialDelay * Math.pow(multiplier, attempt);
471
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
472
+ if (options?.signal?.aborted || this.abortController?.signal.aborted) {
473
+ throw err;
474
+ }
475
+ }
476
+ }
477
+ throw lastError;
478
+ }
479
+ /** Execute a stream factory with pre-stream retry: retries until first event, then committed. */
480
+ async *streamWithRetry(factory, options) {
481
+ const retry = options?.retry;
482
+ if (!retry || !retry.maxRetries || retry.maxRetries <= 0) {
483
+ yield* factory();
484
+ return;
485
+ }
486
+ const maxRetries = retry.maxRetries;
487
+ const initialDelay = retry.initialDelayMs ?? 1e3;
488
+ const multiplier = retry.backoffMultiplier ?? 2;
489
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
490
+ try {
491
+ const stream = factory();
492
+ const iterator = stream[Symbol.asyncIterator]();
493
+ const first = await iterator.next();
494
+ if (first.done) return;
495
+ yield first.value;
496
+ while (true) {
497
+ const next = await iterator.next();
498
+ if (next.done) break;
499
+ yield next.value;
500
+ }
501
+ return;
502
+ } catch (err) {
503
+ if (attempt >= maxRetries || !this.isRetryableError(err, retry)) {
504
+ throw err;
505
+ }
506
+ const delay = initialDelay * Math.pow(multiplier, attempt);
507
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
508
+ if (options?.signal?.aborted || this.abortController?.signal.aborted) {
509
+ throw err;
510
+ }
511
+ }
512
+ }
513
+ }
514
+ // ─── CallOptions Resolution ──────────────────────────────────
515
+ /** Resolve tools to use for this call (per-call override > config default) */
516
+ resolveTools(options) {
517
+ return options?.tools ?? this.config.tools ?? [];
518
+ }
262
519
  // ─── Usage Enrichment ───────────────────────────────────────────
263
520
  /** Enrich result usage with model/backend and fire onUsage callback */
264
- enrichAndNotifyUsage(result) {
521
+ enrichAndNotifyUsage(result, options) {
265
522
  if (result.usage) {
266
523
  result.usage = {
267
524
  ...result.usage,
268
- model: this.config.model,
525
+ model: options.model,
269
526
  backend: this.backendName
270
527
  };
271
528
  this.callOnUsage(result.usage);
272
529
  }
273
530
  }
274
531
  /** Wrap a stream to enrich usage_update events and fire onUsage callback */
275
- async *enrichStream(source) {
532
+ async *enrichStream(source, options) {
533
+ const model = options.model;
276
534
  for await (const event of source) {
277
535
  if (event.type === "usage_update") {
278
536
  const usage = {
279
537
  promptTokens: event.promptTokens,
280
538
  completionTokens: event.completionTokens,
281
- model: this.config.model,
539
+ model,
282
540
  backend: this.backendName
283
541
  };
284
542
  this.callOnUsage(usage);
@@ -348,6 +606,35 @@ var BaseAgent = class {
348
606
  heartbeatResolve = null;
349
607
  }
350
608
  }
609
+ // ─── Activity Timeout ────────────────────────────────────────
610
+ /** Wrap a stream to abort on inactivity. Resets timer on every event.
611
+ * When timeoutMs is not set, passes through directly. */
612
+ async *activityTimeoutStream(source, timeoutMs, ac) {
613
+ if (!timeoutMs || timeoutMs <= 0) {
614
+ yield* source;
615
+ return;
616
+ }
617
+ const iterator = source[Symbol.asyncIterator]();
618
+ let timerId;
619
+ try {
620
+ while (true) {
621
+ const timeoutPromise = new Promise((_, reject) => {
622
+ timerId = setTimeout(() => reject(new ActivityTimeoutError(timeoutMs)), timeoutMs);
623
+ });
624
+ const result = await Promise.race([iterator.next(), timeoutPromise]);
625
+ clearTimeout(timerId);
626
+ if (result.done) break;
627
+ yield result.value;
628
+ }
629
+ } catch (err) {
630
+ if (err instanceof ActivityTimeoutError) {
631
+ ac.abort(err);
632
+ }
633
+ throw err;
634
+ } finally {
635
+ clearTimeout(timerId);
636
+ }
637
+ }
351
638
  // ─── Guards ───────────────────────────────────────────────────
352
639
  guardReentrancy() {
353
640
  if (this.state === "running" || this.state === "streaming") {
@@ -495,40 +782,40 @@ var FilePermissionStore = class {
495
782
  this.filePath = path.resolve(filePath);
496
783
  }
497
784
  async isApproved(toolName) {
498
- const data = this.readFile();
785
+ const data = await this.readStore();
499
786
  return toolName in data.approvals;
500
787
  }
501
788
  async approve(toolName, scope) {
502
789
  if (scope === "once") return;
503
- const data = this.readFile();
790
+ const data = await this.readStore();
504
791
  data.approvals[toolName] = { scope, timestamp: Date.now() };
505
- this.writeFileAtomic(data);
792
+ await this.writeStoreAtomic(data);
506
793
  }
507
794
  async revoke(toolName) {
508
- const data = this.readFile();
795
+ const data = await this.readStore();
509
796
  delete data.approvals[toolName];
510
- this.writeFileAtomic(data);
797
+ await this.writeStoreAtomic(data);
511
798
  }
512
799
  async clear() {
513
- this.writeFileAtomic({ approvals: {} });
800
+ await this.writeStoreAtomic({ approvals: {} });
514
801
  }
515
802
  async dispose() {
516
803
  }
517
- readFile() {
804
+ async readStore() {
518
805
  try {
519
- const raw = fs.readFileSync(this.filePath, "utf-8");
806
+ const raw = await fsp.readFile(this.filePath, "utf-8");
520
807
  const parsed = JSON.parse(raw);
521
808
  if (parsed && typeof parsed.approvals === "object") return parsed;
522
809
  } catch {
523
810
  }
524
811
  return { approvals: {} };
525
812
  }
526
- writeFileAtomic(data) {
813
+ async writeStoreAtomic(data) {
527
814
  const dir = path.dirname(this.filePath);
528
- fs.mkdirSync(dir, { recursive: true });
815
+ await fsp.mkdir(dir, { recursive: true });
529
816
  const tmpPath = this.filePath + `.tmp.${process.pid}.${Date.now()}`;
530
- fs.writeFileSync(tmpPath, JSON.stringify(data, null, 2), "utf-8");
531
- fs.renameSync(tmpPath, this.filePath);
817
+ await fsp.writeFile(tmpPath, JSON.stringify(data, null, 2), "utf-8");
818
+ await fsp.rename(tmpPath, this.filePath);
532
819
  }
533
820
  };
534
821
  var CompositePermissionStore = class {
@@ -580,6 +867,6 @@ function createDefaultPermissionStore(projectDir) {
580
867
  return new CompositePermissionStore(sessionStore, projectStore, userStore);
581
868
  }
582
869
 
583
- export { AbortError, AgentSDKError, BackendAlreadyRegisteredError, BackendNotFoundError, BaseAgent, CompositePermissionStore, DependencyError, DisposedError, FilePermissionStore, InMemoryPermissionStore, ReentrancyError, StructuredOutputError, SubprocessError, ToolExecutionError, buildSystemPrompt, contentToText, createAgentService, createDefaultPermissionStore, getTextContent, hasBackend, isMultiPartContent, isTextContent, isToolDefinition, listBackends, messagesToPrompt, registerBackend, resetRegistry, unregisterBackend, zodToJsonSchema };
870
+ export { AbortError, ActivityTimeoutError, AgentSDKError, BackendAlreadyRegisteredError, BackendNotFoundError, BaseAgent, CompositePermissionStore, DependencyError, DisposedError, ErrorCode, FilePermissionStore, InMemoryPermissionStore, ReentrancyError, StructuredOutputError, SubprocessError, ToolExecutionError, buildSystemPrompt, classifyAgentError, contentToText, createAgentService, createDefaultPermissionStore, disposeBackend, getTextContent, hasBackend, isMultiPartContent, isRecoverableErrorCode, isTextContent, isToolDefinition, listBackends, listConfigs, messagesToPrompt, registerBackend, registerLazyBackend, resetRegistry, unregisterBackend, zodToJsonSchema };
584
871
  //# sourceMappingURL=index.js.map
585
872
  //# sourceMappingURL=index.js.map