@lleverage-ai/agent-sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2321 -0
  3. package/dist/agent.d.ts +52 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +2122 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/backend.d.ts +378 -0
  8. package/dist/backend.d.ts.map +1 -0
  9. package/dist/backend.js +71 -0
  10. package/dist/backend.js.map +1 -0
  11. package/dist/backends/composite.d.ts +258 -0
  12. package/dist/backends/composite.d.ts.map +1 -0
  13. package/dist/backends/composite.js +437 -0
  14. package/dist/backends/composite.js.map +1 -0
  15. package/dist/backends/filesystem.d.ts +268 -0
  16. package/dist/backends/filesystem.d.ts.map +1 -0
  17. package/dist/backends/filesystem.js +623 -0
  18. package/dist/backends/filesystem.js.map +1 -0
  19. package/dist/backends/index.d.ts +14 -0
  20. package/dist/backends/index.d.ts.map +1 -0
  21. package/dist/backends/index.js +14 -0
  22. package/dist/backends/index.js.map +1 -0
  23. package/dist/backends/persistent.d.ts +312 -0
  24. package/dist/backends/persistent.d.ts.map +1 -0
  25. package/dist/backends/persistent.js +519 -0
  26. package/dist/backends/persistent.js.map +1 -0
  27. package/dist/backends/sandbox.d.ts +315 -0
  28. package/dist/backends/sandbox.d.ts.map +1 -0
  29. package/dist/backends/sandbox.js +490 -0
  30. package/dist/backends/sandbox.js.map +1 -0
  31. package/dist/backends/state.d.ts +225 -0
  32. package/dist/backends/state.d.ts.map +1 -0
  33. package/dist/backends/state.js +396 -0
  34. package/dist/backends/state.js.map +1 -0
  35. package/dist/checkpointer/file-saver.d.ts +182 -0
  36. package/dist/checkpointer/file-saver.d.ts.map +1 -0
  37. package/dist/checkpointer/file-saver.js +298 -0
  38. package/dist/checkpointer/file-saver.js.map +1 -0
  39. package/dist/checkpointer/index.d.ts +40 -0
  40. package/dist/checkpointer/index.d.ts.map +1 -0
  41. package/dist/checkpointer/index.js +40 -0
  42. package/dist/checkpointer/index.js.map +1 -0
  43. package/dist/checkpointer/kv-saver.d.ts +142 -0
  44. package/dist/checkpointer/kv-saver.d.ts.map +1 -0
  45. package/dist/checkpointer/kv-saver.js +176 -0
  46. package/dist/checkpointer/kv-saver.js.map +1 -0
  47. package/dist/checkpointer/memory-saver.d.ts +158 -0
  48. package/dist/checkpointer/memory-saver.d.ts.map +1 -0
  49. package/dist/checkpointer/memory-saver.js +222 -0
  50. package/dist/checkpointer/memory-saver.js.map +1 -0
  51. package/dist/checkpointer/types.d.ts +353 -0
  52. package/dist/checkpointer/types.d.ts.map +1 -0
  53. package/dist/checkpointer/types.js +159 -0
  54. package/dist/checkpointer/types.js.map +1 -0
  55. package/dist/context-manager.d.ts +627 -0
  56. package/dist/context-manager.d.ts.map +1 -0
  57. package/dist/context-manager.js +1039 -0
  58. package/dist/context-manager.js.map +1 -0
  59. package/dist/context.d.ts +57 -0
  60. package/dist/context.d.ts.map +1 -0
  61. package/dist/context.js +76 -0
  62. package/dist/context.js.map +1 -0
  63. package/dist/errors/index.d.ts +611 -0
  64. package/dist/errors/index.d.ts.map +1 -0
  65. package/dist/errors/index.js +1023 -0
  66. package/dist/errors/index.js.map +1 -0
  67. package/dist/generation-helpers.d.ts +126 -0
  68. package/dist/generation-helpers.d.ts.map +1 -0
  69. package/dist/generation-helpers.js +181 -0
  70. package/dist/generation-helpers.js.map +1 -0
  71. package/dist/hooks/audit.d.ts +210 -0
  72. package/dist/hooks/audit.d.ts.map +1 -0
  73. package/dist/hooks/audit.js +305 -0
  74. package/dist/hooks/audit.js.map +1 -0
  75. package/dist/hooks/cache.d.ts +180 -0
  76. package/dist/hooks/cache.d.ts.map +1 -0
  77. package/dist/hooks/cache.js +273 -0
  78. package/dist/hooks/cache.js.map +1 -0
  79. package/dist/hooks/guardrails.d.ts +145 -0
  80. package/dist/hooks/guardrails.d.ts.map +1 -0
  81. package/dist/hooks/guardrails.js +326 -0
  82. package/dist/hooks/guardrails.js.map +1 -0
  83. package/dist/hooks/index.d.ts +18 -0
  84. package/dist/hooks/index.d.ts.map +1 -0
  85. package/dist/hooks/index.js +32 -0
  86. package/dist/hooks/index.js.map +1 -0
  87. package/dist/hooks/logging.d.ts +193 -0
  88. package/dist/hooks/logging.d.ts.map +1 -0
  89. package/dist/hooks/logging.js +345 -0
  90. package/dist/hooks/logging.js.map +1 -0
  91. package/dist/hooks/parallel-guardrails.d.ts +268 -0
  92. package/dist/hooks/parallel-guardrails.d.ts.map +1 -0
  93. package/dist/hooks/parallel-guardrails.js +416 -0
  94. package/dist/hooks/parallel-guardrails.js.map +1 -0
  95. package/dist/hooks/rate-limit.d.ts +305 -0
  96. package/dist/hooks/rate-limit.d.ts.map +1 -0
  97. package/dist/hooks/rate-limit.js +372 -0
  98. package/dist/hooks/rate-limit.js.map +1 -0
  99. package/dist/hooks/retry.d.ts +144 -0
  100. package/dist/hooks/retry.d.ts.map +1 -0
  101. package/dist/hooks/retry.js +210 -0
  102. package/dist/hooks/retry.js.map +1 -0
  103. package/dist/hooks/secrets.d.ts +174 -0
  104. package/dist/hooks/secrets.d.ts.map +1 -0
  105. package/dist/hooks/secrets.js +306 -0
  106. package/dist/hooks/secrets.js.map +1 -0
  107. package/dist/hooks.d.ts +229 -0
  108. package/dist/hooks.d.ts.map +1 -0
  109. package/dist/hooks.js +352 -0
  110. package/dist/hooks.js.map +1 -0
  111. package/dist/index.d.ts +97 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +182 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/mcp/env.d.ts +25 -0
  116. package/dist/mcp/env.d.ts.map +1 -0
  117. package/dist/mcp/env.js +18 -0
  118. package/dist/mcp/env.js.map +1 -0
  119. package/dist/mcp/index.d.ts +16 -0
  120. package/dist/mcp/index.d.ts.map +1 -0
  121. package/dist/mcp/index.js +17 -0
  122. package/dist/mcp/index.js.map +1 -0
  123. package/dist/mcp/manager.d.ts +184 -0
  124. package/dist/mcp/manager.d.ts.map +1 -0
  125. package/dist/mcp/manager.js +446 -0
  126. package/dist/mcp/manager.js.map +1 -0
  127. package/dist/mcp/types.d.ts +58 -0
  128. package/dist/mcp/types.d.ts.map +1 -0
  129. package/dist/mcp/types.js +7 -0
  130. package/dist/mcp/types.js.map +1 -0
  131. package/dist/mcp/validation.d.ts +119 -0
  132. package/dist/mcp/validation.d.ts.map +1 -0
  133. package/dist/mcp/validation.js +407 -0
  134. package/dist/mcp/validation.js.map +1 -0
  135. package/dist/mcp/virtual-server.d.ts +78 -0
  136. package/dist/mcp/virtual-server.d.ts.map +1 -0
  137. package/dist/mcp/virtual-server.js +137 -0
  138. package/dist/mcp/virtual-server.js.map +1 -0
  139. package/dist/memory/filesystem-store.d.ts +217 -0
  140. package/dist/memory/filesystem-store.d.ts.map +1 -0
  141. package/dist/memory/filesystem-store.js +343 -0
  142. package/dist/memory/filesystem-store.js.map +1 -0
  143. package/dist/memory/index.d.ts +46 -0
  144. package/dist/memory/index.d.ts.map +1 -0
  145. package/dist/memory/index.js +46 -0
  146. package/dist/memory/index.js.map +1 -0
  147. package/dist/memory/loader.d.ts +396 -0
  148. package/dist/memory/loader.d.ts.map +1 -0
  149. package/dist/memory/loader.js +419 -0
  150. package/dist/memory/loader.js.map +1 -0
  151. package/dist/memory/permissions.d.ts +282 -0
  152. package/dist/memory/permissions.d.ts.map +1 -0
  153. package/dist/memory/permissions.js +297 -0
  154. package/dist/memory/permissions.js.map +1 -0
  155. package/dist/memory/rules.d.ts +249 -0
  156. package/dist/memory/rules.d.ts.map +1 -0
  157. package/dist/memory/rules.js +362 -0
  158. package/dist/memory/rules.js.map +1 -0
  159. package/dist/memory/store.d.ts +286 -0
  160. package/dist/memory/store.d.ts.map +1 -0
  161. package/dist/memory/store.js +263 -0
  162. package/dist/memory/store.js.map +1 -0
  163. package/dist/middleware/apply.d.ts +73 -0
  164. package/dist/middleware/apply.d.ts.map +1 -0
  165. package/dist/middleware/apply.js +219 -0
  166. package/dist/middleware/apply.js.map +1 -0
  167. package/dist/middleware/context.d.ts +33 -0
  168. package/dist/middleware/context.d.ts.map +1 -0
  169. package/dist/middleware/context.js +176 -0
  170. package/dist/middleware/context.js.map +1 -0
  171. package/dist/middleware/index.d.ts +31 -0
  172. package/dist/middleware/index.d.ts.map +1 -0
  173. package/dist/middleware/index.js +32 -0
  174. package/dist/middleware/index.js.map +1 -0
  175. package/dist/middleware/logging.d.ts +137 -0
  176. package/dist/middleware/logging.d.ts.map +1 -0
  177. package/dist/middleware/logging.js +374 -0
  178. package/dist/middleware/logging.js.map +1 -0
  179. package/dist/middleware/types.d.ts +183 -0
  180. package/dist/middleware/types.d.ts.map +1 -0
  181. package/dist/middleware/types.js +11 -0
  182. package/dist/middleware/types.js.map +1 -0
  183. package/dist/observability/events.d.ts +183 -0
  184. package/dist/observability/events.d.ts.map +1 -0
  185. package/dist/observability/events.js +305 -0
  186. package/dist/observability/events.js.map +1 -0
  187. package/dist/observability/index.d.ts +55 -0
  188. package/dist/observability/index.d.ts.map +1 -0
  189. package/dist/observability/index.js +87 -0
  190. package/dist/observability/index.js.map +1 -0
  191. package/dist/observability/logger.d.ts +318 -0
  192. package/dist/observability/logger.d.ts.map +1 -0
  193. package/dist/observability/logger.js +436 -0
  194. package/dist/observability/logger.js.map +1 -0
  195. package/dist/observability/metrics.d.ts +341 -0
  196. package/dist/observability/metrics.d.ts.map +1 -0
  197. package/dist/observability/metrics.js +490 -0
  198. package/dist/observability/metrics.js.map +1 -0
  199. package/dist/observability/preset.d.ts +161 -0
  200. package/dist/observability/preset.d.ts.map +1 -0
  201. package/dist/observability/preset.js +133 -0
  202. package/dist/observability/preset.js.map +1 -0
  203. package/dist/observability/streaming.d.ts +113 -0
  204. package/dist/observability/streaming.d.ts.map +1 -0
  205. package/dist/observability/streaming.js +114 -0
  206. package/dist/observability/streaming.js.map +1 -0
  207. package/dist/observability/tracing.d.ts +378 -0
  208. package/dist/observability/tracing.d.ts.map +1 -0
  209. package/dist/observability/tracing.js +539 -0
  210. package/dist/observability/tracing.js.map +1 -0
  211. package/dist/plugins.d.ts +55 -0
  212. package/dist/plugins.d.ts.map +1 -0
  213. package/dist/plugins.js +63 -0
  214. package/dist/plugins.js.map +1 -0
  215. package/dist/presets/index.d.ts +7 -0
  216. package/dist/presets/index.d.ts.map +1 -0
  217. package/dist/presets/index.js +7 -0
  218. package/dist/presets/index.js.map +1 -0
  219. package/dist/presets/production.d.ts +262 -0
  220. package/dist/presets/production.d.ts.map +1 -0
  221. package/dist/presets/production.js +295 -0
  222. package/dist/presets/production.js.map +1 -0
  223. package/dist/security/index.d.ts +179 -0
  224. package/dist/security/index.d.ts.map +1 -0
  225. package/dist/security/index.js +323 -0
  226. package/dist/security/index.js.map +1 -0
  227. package/dist/subagents/advanced.d.ts +413 -0
  228. package/dist/subagents/advanced.d.ts.map +1 -0
  229. package/dist/subagents/advanced.js +396 -0
  230. package/dist/subagents/advanced.js.map +1 -0
  231. package/dist/subagents/index.d.ts +14 -0
  232. package/dist/subagents/index.d.ts.map +1 -0
  233. package/dist/subagents/index.js +15 -0
  234. package/dist/subagents/index.js.map +1 -0
  235. package/dist/subagents.d.ts +73 -0
  236. package/dist/subagents.d.ts.map +1 -0
  237. package/dist/subagents.js +213 -0
  238. package/dist/subagents.js.map +1 -0
  239. package/dist/task-store/file-store.d.ts +76 -0
  240. package/dist/task-store/file-store.d.ts.map +1 -0
  241. package/dist/task-store/file-store.js +190 -0
  242. package/dist/task-store/file-store.js.map +1 -0
  243. package/dist/task-store/index.d.ts +11 -0
  244. package/dist/task-store/index.d.ts.map +1 -0
  245. package/dist/task-store/index.js +10 -0
  246. package/dist/task-store/index.js.map +1 -0
  247. package/dist/task-store/kv-store.d.ts +140 -0
  248. package/dist/task-store/kv-store.d.ts.map +1 -0
  249. package/dist/task-store/kv-store.js +169 -0
  250. package/dist/task-store/kv-store.js.map +1 -0
  251. package/dist/task-store/memory-store.d.ts +66 -0
  252. package/dist/task-store/memory-store.d.ts.map +1 -0
  253. package/dist/task-store/memory-store.js +125 -0
  254. package/dist/task-store/memory-store.js.map +1 -0
  255. package/dist/task-store/types.d.ts +235 -0
  256. package/dist/task-store/types.d.ts.map +1 -0
  257. package/dist/task-store/types.js +110 -0
  258. package/dist/task-store/types.js.map +1 -0
  259. package/dist/testing/assertions.d.ts +401 -0
  260. package/dist/testing/assertions.d.ts.map +1 -0
  261. package/dist/testing/assertions.js +630 -0
  262. package/dist/testing/assertions.js.map +1 -0
  263. package/dist/testing/index.d.ts +343 -0
  264. package/dist/testing/index.d.ts.map +1 -0
  265. package/dist/testing/index.js +360 -0
  266. package/dist/testing/index.js.map +1 -0
  267. package/dist/testing/mock-agent.d.ts +214 -0
  268. package/dist/testing/mock-agent.d.ts.map +1 -0
  269. package/dist/testing/mock-agent.js +448 -0
  270. package/dist/testing/mock-agent.js.map +1 -0
  271. package/dist/testing/recorder.d.ts +288 -0
  272. package/dist/testing/recorder.d.ts.map +1 -0
  273. package/dist/testing/recorder.js +499 -0
  274. package/dist/testing/recorder.js.map +1 -0
  275. package/dist/tools/execute.d.ts +104 -0
  276. package/dist/tools/execute.d.ts.map +1 -0
  277. package/dist/tools/execute.js +191 -0
  278. package/dist/tools/execute.js.map +1 -0
  279. package/dist/tools/factory.d.ts +260 -0
  280. package/dist/tools/factory.d.ts.map +1 -0
  281. package/dist/tools/factory.js +241 -0
  282. package/dist/tools/factory.js.map +1 -0
  283. package/dist/tools/filesystem.d.ts +215 -0
  284. package/dist/tools/filesystem.d.ts.map +1 -0
  285. package/dist/tools/filesystem.js +311 -0
  286. package/dist/tools/filesystem.js.map +1 -0
  287. package/dist/tools/index.d.ts +33 -0
  288. package/dist/tools/index.d.ts.map +1 -0
  289. package/dist/tools/index.js +33 -0
  290. package/dist/tools/index.js.map +1 -0
  291. package/dist/tools/search.d.ts +59 -0
  292. package/dist/tools/search.d.ts.map +1 -0
  293. package/dist/tools/search.js +94 -0
  294. package/dist/tools/search.js.map +1 -0
  295. package/dist/tools/skills.d.ts +354 -0
  296. package/dist/tools/skills.d.ts.map +1 -0
  297. package/dist/tools/skills.js +413 -0
  298. package/dist/tools/skills.js.map +1 -0
  299. package/dist/tools/task.d.ts +272 -0
  300. package/dist/tools/task.d.ts.map +1 -0
  301. package/dist/tools/task.js +521 -0
  302. package/dist/tools/task.js.map +1 -0
  303. package/dist/tools/todos.d.ts +131 -0
  304. package/dist/tools/todos.d.ts.map +1 -0
  305. package/dist/tools/todos.js +120 -0
  306. package/dist/tools/todos.js.map +1 -0
  307. package/dist/tools/tool-registry.d.ts +424 -0
  308. package/dist/tools/tool-registry.d.ts.map +1 -0
  309. package/dist/tools/tool-registry.js +607 -0
  310. package/dist/tools/tool-registry.js.map +1 -0
  311. package/dist/tools/user-interaction.d.ts +116 -0
  312. package/dist/tools/user-interaction.d.ts.map +1 -0
  313. package/dist/tools/user-interaction.js +147 -0
  314. package/dist/tools/user-interaction.js.map +1 -0
  315. package/dist/tools/utils.d.ts +124 -0
  316. package/dist/tools/utils.d.ts.map +1 -0
  317. package/dist/tools/utils.js +189 -0
  318. package/dist/tools/utils.js.map +1 -0
  319. package/dist/tools.d.ts +74 -0
  320. package/dist/tools.d.ts.map +1 -0
  321. package/dist/tools.js +73 -0
  322. package/dist/tools.js.map +1 -0
  323. package/dist/types.d.ts +2421 -0
  324. package/dist/types.d.ts.map +1 -0
  325. package/dist/types.js +55 -0
  326. package/dist/types.js.map +1 -0
  327. package/package.json +81 -0
@@ -0,0 +1,1023 @@
1
+ /**
2
+ * Error Handling System.
3
+ *
4
+ * Provides typed error classes, utilities, and patterns for robust error handling
5
+ * across the agent SDK.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ /**
10
+ * Base error class for all agent SDK errors.
11
+ *
12
+ * Provides consistent structure with error codes, user-friendly messages,
13
+ * and metadata support.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * throw new AgentError("Something went wrong", {
18
+ * code: "TOOL_ERROR",
19
+ * userMessage: "The operation failed. Please try again.",
20
+ * cause: originalError,
21
+ * metadata: { toolName: "read_file", path: "/path/to/file" },
22
+ * });
23
+ * ```
24
+ *
25
+ * @category Errors
26
+ */
27
+ export class AgentError extends Error {
28
+ /**
29
+ * Error code for categorization.
30
+ */
31
+ code;
32
+ /**
33
+ * User-friendly error message suitable for display.
34
+ */
35
+ userMessage;
36
+ /**
37
+ * Severity level of the error.
38
+ */
39
+ severity;
40
+ /**
41
+ * Whether this error can be retried.
42
+ */
43
+ retryable;
44
+ /**
45
+ * Suggested delay before retry in milliseconds.
46
+ */
47
+ retryAfterMs;
48
+ /**
49
+ * Additional metadata about the error.
50
+ */
51
+ metadata;
52
+ /**
53
+ * The original error that caused this error.
54
+ */
55
+ cause;
56
+ /**
57
+ * Timestamp when the error occurred.
58
+ */
59
+ timestamp;
60
+ constructor(message, options = {}) {
61
+ super(message);
62
+ this.name = "AgentError";
63
+ this.code = options.code ?? "AGENT_ERROR";
64
+ this.userMessage = options.userMessage ?? this.generateUserMessage(message);
65
+ this.severity = options.severity ?? "error";
66
+ this.retryable = options.retryable ?? false;
67
+ this.retryAfterMs = options.retryAfterMs;
68
+ this.metadata = options.metadata ?? {};
69
+ this.cause = options.cause;
70
+ this.timestamp = Date.now();
71
+ // Maintain proper stack trace
72
+ if (Error.captureStackTrace) {
73
+ Error.captureStackTrace(this, this.constructor);
74
+ }
75
+ }
76
+ /**
77
+ * Generate a user-friendly message from the technical message.
78
+ */
79
+ generateUserMessage(message) {
80
+ // Remove technical details for user display
81
+ return message
82
+ .replace(/\b[A-Z_]+Error\b/g, "An error")
83
+ .replace(/\{[^}]+\}/g, "")
84
+ .replace(/\s+/g, " ")
85
+ .trim();
86
+ }
87
+ /**
88
+ * Get a structured representation of the error for logging.
89
+ */
90
+ toJSON() {
91
+ return {
92
+ name: this.name,
93
+ code: this.code,
94
+ message: this.message,
95
+ userMessage: this.userMessage,
96
+ severity: this.severity,
97
+ retryable: this.retryable,
98
+ retryAfterMs: this.retryAfterMs,
99
+ metadata: this.metadata,
100
+ cause: this.cause?.message,
101
+ timestamp: this.timestamp,
102
+ stack: this.stack,
103
+ };
104
+ }
105
+ /**
106
+ * Check if an error is a specific type of AgentError.
107
+ */
108
+ static is(error) {
109
+ return error instanceof AgentError;
110
+ }
111
+ /**
112
+ * Check if an error has a specific code.
113
+ */
114
+ static hasCode(error, code) {
115
+ return AgentError.is(error) && error.code === code;
116
+ }
117
+ }
118
+ // =============================================================================
119
+ // Specific Error Classes
120
+ // =============================================================================
121
+ /**
122
+ * Error thrown when agent configuration is invalid.
123
+ *
124
+ * @category Errors
125
+ */
126
+ export class ConfigurationError extends AgentError {
127
+ constructor(message, options = {}) {
128
+ super(message, {
129
+ code: "CONFIGURATION_ERROR",
130
+ severity: "fatal",
131
+ userMessage: `Configuration error: ${options.configKey ? `Invalid value for '${options.configKey}'` : message}`,
132
+ metadata: {
133
+ configKey: options.configKey,
134
+ expectedType: options.expectedType,
135
+ actualValue: options.actualValue,
136
+ ...options.metadata,
137
+ },
138
+ cause: options.cause,
139
+ });
140
+ this.name = "ConfigurationError";
141
+ }
142
+ }
143
+ /**
144
+ * Error thrown when input validation fails.
145
+ *
146
+ * @category Errors
147
+ */
148
+ export class ValidationError extends AgentError {
149
+ /**
150
+ * Validation errors for specific fields.
151
+ */
152
+ fieldErrors;
153
+ constructor(message, options = {}) {
154
+ super(message, {
155
+ code: "VALIDATION_ERROR",
156
+ severity: "error",
157
+ userMessage: "The provided input is invalid. Please check and try again.",
158
+ metadata: {
159
+ fieldErrors: options.fieldErrors,
160
+ ...options.metadata,
161
+ },
162
+ cause: options.cause,
163
+ });
164
+ this.name = "ValidationError";
165
+ this.fieldErrors = options.fieldErrors ?? {};
166
+ }
167
+ /**
168
+ * Get a formatted list of validation errors.
169
+ */
170
+ getErrorList() {
171
+ const errors = [];
172
+ for (const [field, messages] of Object.entries(this.fieldErrors)) {
173
+ for (const msg of messages) {
174
+ errors.push(`${field}: ${msg}`);
175
+ }
176
+ }
177
+ return errors;
178
+ }
179
+ }
180
+ /**
181
+ * Error thrown when a tool execution fails.
182
+ *
183
+ * @category Errors
184
+ */
185
+ export class ToolExecutionError extends AgentError {
186
+ /**
187
+ * Name of the tool that failed.
188
+ */
189
+ toolName;
190
+ /**
191
+ * Input that was passed to the tool.
192
+ */
193
+ toolInput;
194
+ constructor(message, options) {
195
+ super(message, {
196
+ code: "TOOL_ERROR",
197
+ severity: "error",
198
+ userMessage: `The tool '${options.toolName}' encountered an error. Please try again or use a different approach.`,
199
+ retryable: true,
200
+ metadata: {
201
+ toolName: options.toolName,
202
+ toolInput: options.toolInput,
203
+ ...options.metadata,
204
+ },
205
+ cause: options.cause,
206
+ });
207
+ this.name = "ToolExecutionError";
208
+ this.toolName = options.toolName;
209
+ this.toolInput = options.toolInput;
210
+ }
211
+ }
212
+ /**
213
+ * Error thrown when a tool execution is denied by a PreToolUse hook.
214
+ *
215
+ * @category Errors
216
+ */
217
+ export class ToolPermissionDeniedError extends AgentError {
218
+ /**
219
+ * Name of the tool that was denied.
220
+ */
221
+ toolName;
222
+ /**
223
+ * Input that was attempted.
224
+ */
225
+ toolInput;
226
+ /**
227
+ * Reason provided by the hook (if any).
228
+ */
229
+ reason;
230
+ constructor(message, options) {
231
+ super(message, {
232
+ code: "AUTHORIZATION_ERROR",
233
+ severity: "error",
234
+ userMessage: `Tool '${options.toolName}' was blocked: ${options.reason || "Permission denied"}`,
235
+ retryable: false,
236
+ metadata: {
237
+ toolName: options.toolName,
238
+ toolInput: options.toolInput,
239
+ reason: options.reason,
240
+ ...options.metadata,
241
+ },
242
+ cause: options.cause,
243
+ });
244
+ this.name = "ToolPermissionDeniedError";
245
+ this.toolName = options.toolName;
246
+ this.toolInput = options.toolInput;
247
+ this.reason = options.reason;
248
+ }
249
+ }
250
+ /**
251
+ * Error thrown when a generation request is denied by a PreGenerate hook.
252
+ *
253
+ * @category Errors
254
+ */
255
+ export class GeneratePermissionDeniedError extends AgentError {
256
+ /**
257
+ * Reason provided by the hook (if any).
258
+ */
259
+ reason;
260
+ /**
261
+ * IDs of messages that caused the block (for client-side cleanup).
262
+ */
263
+ blockedMessageIds;
264
+ constructor(message, options = {}) {
265
+ super(message, {
266
+ code: "AUTHORIZATION_ERROR",
267
+ severity: "error",
268
+ userMessage: options.reason || "Generation blocked by content policy",
269
+ retryable: false,
270
+ metadata: {
271
+ reason: options.reason,
272
+ blockedMessageIds: options.blockedMessageIds,
273
+ ...options.metadata,
274
+ },
275
+ cause: options.cause,
276
+ });
277
+ this.name = "GeneratePermissionDeniedError";
278
+ this.reason = options.reason;
279
+ this.blockedMessageIds = options.blockedMessageIds;
280
+ }
281
+ }
282
+ /**
283
+ * Error thrown when the AI model fails or returns an error.
284
+ *
285
+ * @category Errors
286
+ */
287
+ export class ModelError extends AgentError {
288
+ /**
289
+ * Model identifier that failed.
290
+ */
291
+ modelId;
292
+ constructor(message, options = {}) {
293
+ const isRateLimit = options.statusCode === 429 || message.toLowerCase().includes("rate limit");
294
+ const isTimeout = message.toLowerCase().includes("timeout") || message.toLowerCase().includes("timed out");
295
+ super(message, {
296
+ code: isRateLimit ? "RATE_LIMIT_ERROR" : isTimeout ? "TIMEOUT_ERROR" : "MODEL_ERROR",
297
+ severity: "error",
298
+ userMessage: isRateLimit
299
+ ? "The AI service is busy. Please wait a moment and try again."
300
+ : isTimeout
301
+ ? "The request took too long. Please try again."
302
+ : "The AI service encountered an error. Please try again.",
303
+ retryable: isRateLimit || isTimeout,
304
+ retryAfterMs: isRateLimit ? 30000 : isTimeout ? 5000 : undefined,
305
+ metadata: {
306
+ modelId: options.modelId,
307
+ statusCode: options.statusCode,
308
+ ...options.metadata,
309
+ },
310
+ cause: options.cause,
311
+ });
312
+ this.name = "ModelError";
313
+ this.modelId = options.modelId;
314
+ }
315
+ }
316
+ /**
317
+ * Error thrown when a network request fails.
318
+ *
319
+ * @category Errors
320
+ */
321
+ export class NetworkError extends AgentError {
322
+ constructor(message, options = {}) {
323
+ super(message, {
324
+ code: "NETWORK_ERROR",
325
+ severity: "error",
326
+ userMessage: "A network error occurred. Please check your connection and try again.",
327
+ retryable: true,
328
+ retryAfterMs: 2000,
329
+ metadata: {
330
+ url: options.url,
331
+ statusCode: options.statusCode,
332
+ ...options.metadata,
333
+ },
334
+ cause: options.cause,
335
+ });
336
+ this.name = "NetworkError";
337
+ }
338
+ }
339
+ /**
340
+ * Error thrown when an operation times out.
341
+ *
342
+ * @category Errors
343
+ */
344
+ export class TimeoutError extends AgentError {
345
+ /**
346
+ * Timeout duration in milliseconds.
347
+ */
348
+ timeoutMs;
349
+ /**
350
+ * Operation that timed out.
351
+ */
352
+ operation;
353
+ constructor(message, options) {
354
+ super(message, {
355
+ code: "TIMEOUT_ERROR",
356
+ severity: "error",
357
+ userMessage: `The operation '${options.operation}' took too long and was stopped.`,
358
+ retryable: true,
359
+ retryAfterMs: 1000,
360
+ metadata: {
361
+ timeoutMs: options.timeoutMs,
362
+ operation: options.operation,
363
+ ...options.metadata,
364
+ },
365
+ cause: options.cause,
366
+ });
367
+ this.name = "TimeoutError";
368
+ this.timeoutMs = options.timeoutMs;
369
+ this.operation = options.operation;
370
+ }
371
+ }
372
+ /**
373
+ * Error thrown when rate limits are exceeded.
374
+ *
375
+ * @category Errors
376
+ */
377
+ export class RateLimitError extends AgentError {
378
+ /**
379
+ * When to retry after (Date or ms).
380
+ */
381
+ retryAfter;
382
+ constructor(message, options = {}) {
383
+ const retryMs = options.retryAfter instanceof Date
384
+ ? options.retryAfter.getTime() - Date.now()
385
+ : (options.retryAfter ?? 60000);
386
+ super(message, {
387
+ code: "RATE_LIMIT_ERROR",
388
+ severity: "error",
389
+ userMessage: "Rate limit reached. Please wait a moment before trying again.",
390
+ retryable: true,
391
+ retryAfterMs: Math.max(retryMs, 1000),
392
+ metadata: {
393
+ retryAfter: options.retryAfter,
394
+ limit: options.limit,
395
+ remaining: options.remaining,
396
+ ...options.metadata,
397
+ },
398
+ cause: options.cause,
399
+ });
400
+ this.name = "RateLimitError";
401
+ this.retryAfter = options.retryAfter;
402
+ }
403
+ }
404
+ /**
405
+ * Error thrown when authentication fails.
406
+ *
407
+ * @category Errors
408
+ */
409
+ export class AuthenticationError extends AgentError {
410
+ constructor(message, options = {}) {
411
+ super(message, {
412
+ code: "AUTHENTICATION_ERROR",
413
+ severity: "fatal",
414
+ userMessage: "Authentication failed. Please check your credentials.",
415
+ retryable: false,
416
+ metadata: options.metadata,
417
+ cause: options.cause,
418
+ });
419
+ this.name = "AuthenticationError";
420
+ }
421
+ }
422
+ /**
423
+ * Error thrown when authorization fails.
424
+ *
425
+ * @category Errors
426
+ */
427
+ export class AuthorizationError extends AgentError {
428
+ constructor(message, options = {}) {
429
+ super(message, {
430
+ code: "AUTHORIZATION_ERROR",
431
+ severity: "error",
432
+ userMessage: "You don't have permission to perform this action.",
433
+ retryable: false,
434
+ metadata: {
435
+ resource: options.resource,
436
+ action: options.action,
437
+ ...options.metadata,
438
+ },
439
+ cause: options.cause,
440
+ });
441
+ this.name = "AuthorizationError";
442
+ }
443
+ }
444
+ /**
445
+ * Error thrown when checkpoint operations fail.
446
+ *
447
+ * @category Errors
448
+ */
449
+ export class CheckpointError extends AgentError {
450
+ /**
451
+ * Thread ID associated with the checkpoint.
452
+ */
453
+ threadId;
454
+ /**
455
+ * Operation that failed (save, load, delete, fork).
456
+ */
457
+ operation;
458
+ constructor(message, options) {
459
+ super(message, {
460
+ code: "CHECKPOINT_ERROR",
461
+ severity: "error",
462
+ userMessage: `Failed to ${options.operation} session state. Your progress may not be saved.`,
463
+ retryable: options.operation === "save" || options.operation === "fork",
464
+ metadata: {
465
+ operation: options.operation,
466
+ threadId: options.threadId,
467
+ ...options.metadata,
468
+ },
469
+ cause: options.cause,
470
+ });
471
+ this.name = "CheckpointError";
472
+ this.threadId = options.threadId;
473
+ this.operation = options.operation;
474
+ }
475
+ }
476
+ /**
477
+ * Error thrown when backend operations fail.
478
+ *
479
+ * @category Errors
480
+ */
481
+ export class BackendError extends AgentError {
482
+ /**
483
+ * Backend operation that failed.
484
+ */
485
+ operation;
486
+ /**
487
+ * Path involved in the operation.
488
+ */
489
+ path;
490
+ constructor(message, options) {
491
+ super(message, {
492
+ code: "BACKEND_ERROR",
493
+ severity: "error",
494
+ userMessage: `Failed to ${options.operation}${options.path ? ` for '${options.path}'` : ""}. Please try again.`,
495
+ retryable: true,
496
+ metadata: {
497
+ operation: options.operation,
498
+ path: options.path,
499
+ ...options.metadata,
500
+ },
501
+ cause: options.cause,
502
+ });
503
+ this.name = "BackendError";
504
+ this.operation = options.operation;
505
+ this.path = options.path;
506
+ }
507
+ }
508
+ /**
509
+ * Error thrown when context management fails.
510
+ *
511
+ * @category Errors
512
+ */
513
+ export class ContextError extends AgentError {
514
+ constructor(message, options = {}) {
515
+ super(message, {
516
+ code: "CONTEXT_ERROR",
517
+ severity: "warning",
518
+ userMessage: "Context management encountered an issue. The conversation may be truncated.",
519
+ retryable: false,
520
+ metadata: {
521
+ operation: options.operation,
522
+ currentTokens: options.currentTokens,
523
+ maxTokens: options.maxTokens,
524
+ ...options.metadata,
525
+ },
526
+ cause: options.cause,
527
+ });
528
+ this.name = "ContextError";
529
+ }
530
+ }
531
+ /**
532
+ * Error thrown when subagent operations fail.
533
+ *
534
+ * @category Errors
535
+ */
536
+ export class SubagentError extends AgentError {
537
+ /**
538
+ * Name of the subagent that failed.
539
+ */
540
+ subagentName;
541
+ /**
542
+ * Task that was being executed.
543
+ */
544
+ task;
545
+ constructor(message, options) {
546
+ super(message, {
547
+ code: "SUBAGENT_ERROR",
548
+ severity: "error",
549
+ userMessage: `The assistant '${options.subagentName}' encountered an error while working on your request.`,
550
+ retryable: true,
551
+ metadata: {
552
+ subagentName: options.subagentName,
553
+ task: options.task,
554
+ ...options.metadata,
555
+ },
556
+ cause: options.cause,
557
+ });
558
+ this.name = "SubagentError";
559
+ this.subagentName = options.subagentName;
560
+ this.task = options.task;
561
+ }
562
+ }
563
+ /**
564
+ * Error thrown when memory operations fail.
565
+ *
566
+ * @category Errors
567
+ */
568
+ export class MemoryError extends AgentError {
569
+ /**
570
+ * Memory path that was being accessed.
571
+ */
572
+ memoryPath;
573
+ /**
574
+ * Operation that failed.
575
+ */
576
+ operation;
577
+ constructor(message, options) {
578
+ super(message, {
579
+ code: "MEMORY_ERROR",
580
+ severity: "warning",
581
+ userMessage: `Failed to ${options.operation} memory${options.memoryPath ? ` at '${options.memoryPath}'` : ""}.`,
582
+ retryable: options.operation !== "delete",
583
+ metadata: {
584
+ operation: options.operation,
585
+ memoryPath: options.memoryPath,
586
+ ...options.metadata,
587
+ },
588
+ cause: options.cause,
589
+ });
590
+ this.name = "MemoryError";
591
+ this.memoryPath = options.memoryPath;
592
+ this.operation = options.operation;
593
+ }
594
+ }
595
+ /**
596
+ * Error thrown when an operation is aborted.
597
+ *
598
+ * @category Errors
599
+ */
600
+ export class AbortError extends AgentError {
601
+ /**
602
+ * Reason for the abort.
603
+ */
604
+ reason;
605
+ constructor(message = "Operation was aborted", options = {}) {
606
+ super(message, {
607
+ code: "ABORT_ERROR",
608
+ severity: "warning",
609
+ userMessage: options.reason ?? "The operation was cancelled.",
610
+ retryable: false,
611
+ metadata: {
612
+ reason: options.reason,
613
+ ...options.metadata,
614
+ },
615
+ cause: options.cause,
616
+ });
617
+ this.name = "AbortError";
618
+ this.reason = options.reason;
619
+ }
620
+ }
621
+ /**
622
+ * Wrap any error as an AgentError.
623
+ *
624
+ * Preserves existing AgentErrors while wrapping other errors with additional context.
625
+ *
626
+ * @param error - The error to wrap
627
+ * @param message - Additional context message
628
+ * @param options - Options for the wrapped error
629
+ * @returns An AgentError instance
630
+ *
631
+ * @example
632
+ * ```typescript
633
+ * try {
634
+ * await riskyOperation();
635
+ * } catch (error) {
636
+ * throw wrapError(error, "Failed to perform risky operation", {
637
+ * code: "BACKEND_ERROR",
638
+ * metadata: { operation: "risky" },
639
+ * });
640
+ * }
641
+ * ```
642
+ *
643
+ * @category Errors
644
+ */
645
+ export function wrapError(error, message, options = {}) {
646
+ // Already an AgentError - preserve it
647
+ if (AgentError.is(error)) {
648
+ return error;
649
+ }
650
+ // Wrap standard Error
651
+ if (error instanceof Error) {
652
+ return new AgentError(message, {
653
+ code: options.code ?? inferErrorCode(error),
654
+ userMessage: options.userMessage,
655
+ severity: options.severity,
656
+ retryable: options.retryable ?? isRetryable(error),
657
+ metadata: options.metadata,
658
+ cause: error,
659
+ });
660
+ }
661
+ // Wrap unknown error
662
+ return new AgentError(message, {
663
+ code: options.code ?? "UNKNOWN_ERROR",
664
+ userMessage: options.userMessage,
665
+ severity: options.severity,
666
+ retryable: options.retryable ?? false,
667
+ metadata: {
668
+ ...options.metadata,
669
+ originalError: String(error),
670
+ },
671
+ });
672
+ }
673
+ /**
674
+ * Infer error code from an Error instance.
675
+ */
676
+ function inferErrorCode(error) {
677
+ const message = error.message.toLowerCase();
678
+ const name = error.name.toLowerCase();
679
+ if (name.includes("abort") || message.includes("abort")) {
680
+ return "ABORT_ERROR";
681
+ }
682
+ if (message.includes("timeout") || message.includes("timed out")) {
683
+ return "TIMEOUT_ERROR";
684
+ }
685
+ if (message.includes("rate limit") || message.includes("429")) {
686
+ return "RATE_LIMIT_ERROR";
687
+ }
688
+ if (message.includes("network") ||
689
+ message.includes("fetch") ||
690
+ message.includes("econnrefused") ||
691
+ message.includes("econnreset")) {
692
+ return "NETWORK_ERROR";
693
+ }
694
+ if (message.includes("auth") || message.includes("401")) {
695
+ return "AUTHENTICATION_ERROR";
696
+ }
697
+ if (message.includes("permission") || message.includes("forbidden") || message.includes("403")) {
698
+ return "AUTHORIZATION_ERROR";
699
+ }
700
+ if (message.includes("validation") || message.includes("invalid")) {
701
+ return "VALIDATION_ERROR";
702
+ }
703
+ return "UNKNOWN_ERROR";
704
+ }
705
+ /**
706
+ * Check if an error is retryable.
707
+ *
708
+ * @param error - The error to check
709
+ * @returns Whether the error is retryable
710
+ *
711
+ * @category Errors
712
+ */
713
+ export function isRetryable(error) {
714
+ if (AgentError.is(error)) {
715
+ return error.retryable;
716
+ }
717
+ if (error instanceof Error) {
718
+ const message = error.message.toLowerCase();
719
+ // Retryable conditions
720
+ if (message.includes("rate limit") ||
721
+ message.includes("timeout") ||
722
+ message.includes("timed out") ||
723
+ message.includes("network") ||
724
+ message.includes("econnreset") ||
725
+ message.includes("econnrefused") ||
726
+ message.includes("503") ||
727
+ message.includes("502") ||
728
+ message.includes("504")) {
729
+ return true;
730
+ }
731
+ // Non-retryable conditions
732
+ if (message.includes("invalid") ||
733
+ message.includes("validation") ||
734
+ message.includes("auth") ||
735
+ message.includes("permission") ||
736
+ message.includes("not found")) {
737
+ return false;
738
+ }
739
+ }
740
+ return false;
741
+ }
742
+ /**
743
+ * Get a user-friendly error message from any error.
744
+ *
745
+ * @param error - The error to get a message from
746
+ * @param fallback - Fallback message if extraction fails
747
+ * @returns A user-friendly error message
748
+ *
749
+ * @category Errors
750
+ */
751
+ export function getUserMessage(error, fallback = "An unexpected error occurred. Please try again.") {
752
+ if (AgentError.is(error)) {
753
+ return error.userMessage;
754
+ }
755
+ if (error instanceof Error) {
756
+ // Try to make the message more user-friendly
757
+ const message = error.message;
758
+ // Common error patterns to user-friendly messages
759
+ if (message.toLowerCase().includes("rate limit")) {
760
+ return "The service is busy. Please wait a moment and try again.";
761
+ }
762
+ if (message.toLowerCase().includes("timeout") || message.toLowerCase().includes("timed out")) {
763
+ return "The request took too long. Please try again.";
764
+ }
765
+ if (message.toLowerCase().includes("network")) {
766
+ return "A network error occurred. Please check your connection.";
767
+ }
768
+ if (message.toLowerCase().includes("auth") || message.toLowerCase().includes("401")) {
769
+ return "Authentication failed. Please check your credentials.";
770
+ }
771
+ if (message.toLowerCase().includes("permission") || message.toLowerCase().includes("403")) {
772
+ return "You don't have permission to perform this action.";
773
+ }
774
+ if (message.toLowerCase().includes("not found") || message.includes("404")) {
775
+ return "The requested resource was not found.";
776
+ }
777
+ // Return the original message if it's reasonably short
778
+ if (message.length < 100 && !message.includes("Error:")) {
779
+ return message;
780
+ }
781
+ }
782
+ return fallback;
783
+ }
784
+ /**
785
+ * Format an error for logging.
786
+ *
787
+ * @param error - The error to format
788
+ * @returns A structured object suitable for logging
789
+ *
790
+ * @category Errors
791
+ */
792
+ export function formatErrorForLogging(error) {
793
+ if (AgentError.is(error)) {
794
+ return error.toJSON();
795
+ }
796
+ if (error instanceof Error) {
797
+ return {
798
+ name: error.name,
799
+ message: error.message,
800
+ stack: error.stack,
801
+ cause: error.cause instanceof Error ? error.cause.message : error.cause,
802
+ };
803
+ }
804
+ return {
805
+ type: typeof error,
806
+ value: String(error),
807
+ };
808
+ }
809
+ /**
810
+ * Create an error handler that catches and transforms errors.
811
+ *
812
+ * @param options - Handler options
813
+ * @returns A function that wraps async operations with error handling
814
+ *
815
+ * @example
816
+ * ```typescript
817
+ * const handle = createErrorHandler({
818
+ * onError: (error) => console.error(error),
819
+ * transform: (error) => wrapError(error, "Operation failed"),
820
+ * });
821
+ *
822
+ * const result = await handle(async () => {
823
+ * return await riskyOperation();
824
+ * });
825
+ * ```
826
+ *
827
+ * @category Errors
828
+ */
829
+ export function createErrorHandler(options) {
830
+ const { onError, transform } = options;
831
+ return async (fn) => {
832
+ try {
833
+ return await fn();
834
+ }
835
+ catch (error) {
836
+ const agentError = transform ? transform(error) : wrapError(error, "An error occurred");
837
+ if (onError) {
838
+ await onError(agentError);
839
+ }
840
+ throw agentError;
841
+ }
842
+ };
843
+ }
844
+ /**
845
+ * Execute an operation with a fallback value on error.
846
+ *
847
+ * Provides graceful degradation by returning a fallback value when
848
+ * the primary operation fails.
849
+ *
850
+ * @param fn - The operation to execute
851
+ * @param options - Fallback options
852
+ * @returns The result or fallback value
853
+ *
854
+ * @example
855
+ * ```typescript
856
+ * const memory = await withFallback(
857
+ * () => loadAgentMemory("/path/to/memory.md"),
858
+ * { fallback: "", logError: true }
859
+ * );
860
+ * ```
861
+ *
862
+ * @category Errors
863
+ */
864
+ export async function withFallback(fn, options) {
865
+ const { fallback, logError = true, onError, rethrowFatal = true } = options;
866
+ try {
867
+ return await fn();
868
+ }
869
+ catch (error) {
870
+ const agentError = wrapError(error, "Operation failed");
871
+ // Rethrow fatal errors
872
+ if (rethrowFatal && agentError.severity === "fatal") {
873
+ throw agentError;
874
+ }
875
+ // Log if requested
876
+ if (logError) {
877
+ console.warn(`[withFallback] Using fallback due to error: ${agentError.message}`);
878
+ }
879
+ // Call error handler
880
+ if (onError) {
881
+ await onError(agentError);
882
+ }
883
+ return fallback;
884
+ }
885
+ }
886
+ /**
887
+ * Execute an operation with a fallback function on error.
888
+ *
889
+ * Similar to withFallback but allows computing the fallback value.
890
+ *
891
+ * @param fn - The primary operation
892
+ * @param fallbackFn - Function to compute the fallback
893
+ * @param onError - Optional error callback
894
+ * @returns The result or computed fallback
895
+ *
896
+ * @example
897
+ * ```typescript
898
+ * const data = await withFallbackFn(
899
+ * () => fetchFromPrimary(),
900
+ * (error) => fetchFromBackup(error)
901
+ * );
902
+ * ```
903
+ *
904
+ * @category Errors
905
+ */
906
+ export async function withFallbackFn(fn, fallbackFn, onError) {
907
+ try {
908
+ return await fn();
909
+ }
910
+ catch (error) {
911
+ const agentError = wrapError(error, "Operation failed");
912
+ if (onError) {
913
+ await onError(agentError);
914
+ }
915
+ return fallbackFn(agentError);
916
+ }
917
+ }
918
+ /**
919
+ * Execute multiple operations until one succeeds.
920
+ *
921
+ * Tries each operation in order and returns the first successful result.
922
+ *
923
+ * @param operations - Array of operations to try
924
+ * @param options - Options including error handling
925
+ * @returns The first successful result
926
+ * @throws The last error if all operations fail
927
+ *
928
+ * @example
929
+ * ```typescript
930
+ * const result = await tryOperations([
931
+ * () => fetchFromPrimaryAPI(),
932
+ * () => fetchFromSecondaryAPI(),
933
+ * () => fetchFromCache(),
934
+ * ]);
935
+ * ```
936
+ *
937
+ * @category Errors
938
+ */
939
+ export async function tryOperations(operations, options = {}) {
940
+ const { onError } = options;
941
+ let lastError;
942
+ for (let i = 0; i < operations.length; i++) {
943
+ try {
944
+ const operation = operations[i];
945
+ if (!operation)
946
+ continue;
947
+ return await operation();
948
+ }
949
+ catch (error) {
950
+ lastError = wrapError(error, `Operation ${i + 1} failed`);
951
+ if (onError) {
952
+ await onError(lastError, i);
953
+ }
954
+ }
955
+ }
956
+ throw (lastError ??
957
+ new AgentError("All operations failed", {
958
+ code: "UNKNOWN_ERROR",
959
+ }));
960
+ }
961
+ /**
962
+ * Create a circuit breaker for error protection.
963
+ *
964
+ * Opens the circuit after threshold failures to prevent cascading failures.
965
+ *
966
+ * @param options - Circuit breaker options
967
+ * @returns A function that wraps operations with circuit breaker protection
968
+ *
969
+ * @example
970
+ * ```typescript
971
+ * const breaker = createCircuitBreaker({
972
+ * failureThreshold: 5,
973
+ * resetTimeout: 60000,
974
+ * });
975
+ *
976
+ * const result = await breaker(() => callExternalService());
977
+ * ```
978
+ *
979
+ * @category Errors
980
+ */
981
+ export function createCircuitBreaker(options) {
982
+ const { failureThreshold = 5, resetTimeout = 60000, onStateChange } = options;
983
+ let failures = 0;
984
+ let state = "closed";
985
+ let lastFailureTime = 0;
986
+ function setState(newState) {
987
+ if (state !== newState) {
988
+ state = newState;
989
+ onStateChange?.(newState);
990
+ }
991
+ }
992
+ return async (fn) => {
993
+ // Check if circuit should be opened
994
+ if (state === "open") {
995
+ if (Date.now() - lastFailureTime >= resetTimeout) {
996
+ setState("half-open");
997
+ }
998
+ else {
999
+ throw new AgentError("Circuit breaker is open", {
1000
+ code: "NETWORK_ERROR",
1001
+ userMessage: "Service temporarily unavailable. Please try again later.",
1002
+ retryable: true,
1003
+ retryAfterMs: Math.max(1000, resetTimeout - (Date.now() - lastFailureTime)),
1004
+ });
1005
+ }
1006
+ }
1007
+ try {
1008
+ const result = await fn();
1009
+ failures = 0;
1010
+ setState("closed");
1011
+ return result;
1012
+ }
1013
+ catch (error) {
1014
+ failures++;
1015
+ lastFailureTime = Date.now();
1016
+ if (failures >= failureThreshold) {
1017
+ setState("open");
1018
+ }
1019
+ throw error;
1020
+ }
1021
+ };
1022
+ }
1023
+ //# sourceMappingURL=index.js.map