nexus-ai-pro 2.2.0 → 2.4.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 (298) hide show
  1. package/API_STABILITY.md +225 -0
  2. package/CHANGELOG.md +325 -1
  3. package/README.md +20 -6
  4. package/SECURITY.md +140 -0
  5. package/dist/adapter-kit/contracts.d.ts +87 -0
  6. package/dist/adapter-kit/contracts.js +237 -0
  7. package/dist/adapter-kit/errors.d.ts +39 -0
  8. package/dist/adapter-kit/errors.js +52 -0
  9. package/dist/adapter-kit/index.d.ts +144 -0
  10. package/dist/adapter-kit/index.js +178 -0
  11. package/dist/adapter-kit/semver.d.ts +12 -0
  12. package/dist/adapter-kit/semver.js +55 -0
  13. package/dist/agent/capabilities.d.ts +39 -0
  14. package/dist/agent/capabilities.js +36 -0
  15. package/dist/agent/create-agent.d.ts +61 -11
  16. package/dist/agent/create-agent.js +136 -22
  17. package/dist/agent/index.d.ts +3 -2
  18. package/dist/agent/index.js +1 -1
  19. package/dist/agent/middleware/approval.d.ts +26 -0
  20. package/dist/agent/middleware/approval.js +23 -0
  21. package/dist/agent/{middleware.d.ts → middleware/basic.d.ts} +5 -4
  22. package/dist/agent/{middleware.js → middleware/basic.js} +3 -5
  23. package/dist/agent/middleware/context-editor.d.ts +52 -0
  24. package/dist/agent/middleware/context-editor.js +66 -0
  25. package/dist/agent/middleware/filesystem.d.ts +44 -0
  26. package/dist/agent/middleware/filesystem.js +83 -0
  27. package/dist/agent/middleware/index.d.ts +19 -0
  28. package/dist/agent/middleware/index.js +9 -0
  29. package/dist/agent/middleware/limits.d.ts +42 -0
  30. package/dist/agent/middleware/limits.js +52 -0
  31. package/dist/agent/middleware/models.d.ts +48 -0
  32. package/dist/agent/middleware/models.js +44 -0
  33. package/dist/agent/middleware/pii.d.ts +67 -0
  34. package/dist/agent/middleware/pii.js +142 -0
  35. package/dist/agent/middleware/retry.d.ts +66 -0
  36. package/dist/agent/middleware/retry.js +59 -0
  37. package/dist/agent/middleware/shared.d.ts +41 -0
  38. package/dist/agent/middleware/shared.js +73 -0
  39. package/dist/agent/middleware/tool-selector.d.ts +64 -0
  40. package/dist/agent/middleware/tool-selector.js +106 -0
  41. package/dist/agent/permissions.d.ts +113 -0
  42. package/dist/agent/permissions.js +180 -0
  43. package/dist/agent/sandbox.d.ts +151 -0
  44. package/dist/agent/sandbox.js +257 -0
  45. package/dist/agent/tool.d.ts +8 -3
  46. package/dist/agent/tool.js +14 -3
  47. package/dist/core/secure-stream.js +4 -3
  48. package/dist/deep-agent/index.d.ts +109 -0
  49. package/dist/deep-agent/index.js +216 -0
  50. package/dist/embeddings/adapters.js +2 -1
  51. package/dist/evals/judge.js +2 -5
  52. package/dist/evaluate/cache.d.ts +0 -14
  53. package/dist/evaluate/cache.js +0 -30
  54. package/dist/evaluate/file-cache.d.ts +15 -0
  55. package/dist/evaluate/file-cache.js +30 -0
  56. package/dist/evaluate/index.d.ts +2 -1
  57. package/dist/evaluate/index.js +2 -1
  58. package/dist/evaluate/review.js +2 -2
  59. package/dist/evaluate/run.js +2 -2
  60. package/dist/evaluate/version.js +3 -3
  61. package/dist/graph/functional.d.ts +9 -0
  62. package/dist/graph/functional.js +20 -3
  63. package/dist/graph/graph.js +27 -6
  64. package/dist/graph/lint.d.ts +4 -1
  65. package/dist/graph/lint.js +35 -0
  66. package/dist/graph/node-cache.js +3 -3
  67. package/dist/hallucination/rag.d.ts +4 -1
  68. package/dist/hallucination/rag.js +6 -1
  69. package/dist/images/asset-stores.js +2 -3
  70. package/dist/images/asset-support.js +2 -2
  71. package/dist/images/assets.js +1 -2
  72. package/dist/images/evals.js +4 -4
  73. package/dist/insights/proposals.js +1 -2
  74. package/dist/insights/regressions.d.ts +26 -2
  75. package/dist/insights/regressions.js +129 -3
  76. package/dist/loaders/git.js +8 -1
  77. package/dist/loaders/web.js +7 -1
  78. package/dist/mcp/client.d.ts +14 -0
  79. package/dist/mcp/client.js +59 -1
  80. package/dist/mcp/registry.d.ts +6 -0
  81. package/dist/mcp/registry.js +7 -0
  82. package/dist/postgres/fulltext.d.ts +67 -0
  83. package/dist/postgres/fulltext.js +91 -0
  84. package/dist/prompts/file.js +28 -11
  85. package/dist/protocols/a2a.d.ts +235 -0
  86. package/dist/protocols/a2a.js +386 -0
  87. package/dist/protocols/acp.d.ts +87 -0
  88. package/dist/protocols/acp.js +322 -0
  89. package/dist/protocols/ag-ui.d.ts +120 -0
  90. package/dist/protocols/ag-ui.js +180 -0
  91. package/dist/protocols/shared.d.ts +80 -0
  92. package/dist/protocols/shared.js +49 -0
  93. package/dist/providers/anthropic.js +1 -0
  94. package/dist/providers/cohere.js +2 -2
  95. package/dist/providers/google.js +2 -11
  96. package/dist/providers/openai.js +1 -0
  97. package/dist/rag/elasticsearch.d.ts +71 -0
  98. package/dist/rag/elasticsearch.js +130 -0
  99. package/dist/rag/file-ingestion.js +15 -9
  100. package/dist/rag/pipeline.d.ts +140 -0
  101. package/dist/rag/pipeline.js +187 -0
  102. package/dist/rag/rerankers.d.ts +92 -0
  103. package/dist/rag/rerankers.js +97 -0
  104. package/dist/rag/retrievers.d.ts +12 -1
  105. package/dist/runtime/detect.d.ts +17 -0
  106. package/dist/runtime/detect.js +16 -0
  107. package/dist/runtime/index.d.ts +19 -0
  108. package/dist/runtime/index.js +7 -0
  109. package/dist/security/injection-detector.d.ts +2 -0
  110. package/dist/security/injection-detector.js +7 -1
  111. package/dist/security/input-guard.js +5 -2
  112. package/dist/security/output-guard.js +8 -4
  113. package/dist/security/pii-detector.js +22 -6
  114. package/dist/security/prompt-hardening.js +6 -2
  115. package/dist/security/semantic-injection-classifier.d.ts +2 -1
  116. package/dist/security/semantic-injection-classifier.js +31 -35
  117. package/dist/security/upload-scanner.d.ts +8 -0
  118. package/dist/security/upload-scanner.js +51 -9
  119. package/dist/server/assistant.d.ts +5 -1
  120. package/dist/server/assistant.js +4 -2
  121. package/dist/server/auth.d.ts +250 -0
  122. package/dist/server/auth.js +392 -0
  123. package/dist/server/deployments.d.ts +63 -1
  124. package/dist/server/deployments.js +75 -2
  125. package/dist/server/runs.d.ts +9 -0
  126. package/dist/server/runs.js +20 -0
  127. package/dist/server/server.js +5 -0
  128. package/dist/store/memory.d.ts +10 -0
  129. package/dist/store/memory.js +10 -0
  130. package/dist/testing/record.js +2 -2
  131. package/dist/tracing/stores.js +2 -1
  132. package/dist/tracing/tracer.js +2 -2
  133. package/dist/types/config.d.ts +20 -0
  134. package/dist/types/graph.d.ts +38 -0
  135. package/dist/types/messages.d.ts +36 -2
  136. package/dist/types/principal.d.ts +21 -0
  137. package/dist/types/principal.js +1 -0
  138. package/dist/types/server.d.ts +8 -9
  139. package/dist/utils/base64.d.ts +4 -0
  140. package/dist/utils/base64.js +21 -0
  141. package/dist/utils/checksums.d.ts +22 -0
  142. package/dist/utils/checksums.js +39 -0
  143. package/dist/utils/ids.d.ts +8 -0
  144. package/dist/utils/ids.js +26 -2
  145. package/dist/utils/sha256.d.ts +22 -0
  146. package/dist/utils/sha256.js +120 -0
  147. package/dist/utils/tenant.d.ts +11 -0
  148. package/dist/utils/tenant.js +14 -0
  149. package/dist/version.d.ts +1 -1
  150. package/dist/version.js +1 -1
  151. package/dist-cjs/adapter-kit/contracts.d.ts +87 -0
  152. package/dist-cjs/adapter-kit/contracts.js +243 -0
  153. package/dist-cjs/adapter-kit/errors.d.ts +39 -0
  154. package/dist-cjs/adapter-kit/errors.js +57 -0
  155. package/dist-cjs/adapter-kit/index.d.ts +144 -0
  156. package/dist-cjs/adapter-kit/index.js +194 -0
  157. package/dist-cjs/adapter-kit/semver.d.ts +12 -0
  158. package/dist-cjs/adapter-kit/semver.js +59 -0
  159. package/dist-cjs/agent/capabilities.d.ts +39 -0
  160. package/dist-cjs/agent/capabilities.js +41 -0
  161. package/dist-cjs/agent/create-agent.d.ts +61 -11
  162. package/dist-cjs/agent/create-agent.js +136 -22
  163. package/dist-cjs/agent/index.d.ts +3 -2
  164. package/dist-cjs/agent/index.js +4 -4
  165. package/dist-cjs/agent/middleware/approval.d.ts +26 -0
  166. package/dist-cjs/agent/middleware/approval.js +26 -0
  167. package/dist-cjs/agent/{middleware.d.ts → middleware/basic.d.ts} +5 -4
  168. package/dist-cjs/agent/{middleware.js → middleware/basic.js} +3 -5
  169. package/dist-cjs/agent/middleware/context-editor.d.ts +52 -0
  170. package/dist-cjs/agent/middleware/context-editor.js +70 -0
  171. package/dist-cjs/agent/middleware/filesystem.d.ts +44 -0
  172. package/dist-cjs/agent/middleware/filesystem.js +86 -0
  173. package/dist-cjs/agent/middleware/index.d.ts +19 -0
  174. package/dist-cjs/agent/middleware/index.js +28 -0
  175. package/dist-cjs/agent/middleware/limits.d.ts +42 -0
  176. package/dist-cjs/agent/middleware/limits.js +57 -0
  177. package/dist-cjs/agent/middleware/models.d.ts +48 -0
  178. package/dist-cjs/agent/middleware/models.js +48 -0
  179. package/dist-cjs/agent/middleware/pii.d.ts +67 -0
  180. package/dist-cjs/agent/middleware/pii.js +147 -0
  181. package/dist-cjs/agent/middleware/retry.d.ts +66 -0
  182. package/dist-cjs/agent/middleware/retry.js +63 -0
  183. package/dist-cjs/agent/middleware/shared.d.ts +41 -0
  184. package/dist-cjs/agent/middleware/shared.js +83 -0
  185. package/dist-cjs/agent/middleware/tool-selector.d.ts +64 -0
  186. package/dist-cjs/agent/middleware/tool-selector.js +109 -0
  187. package/dist-cjs/agent/permissions.d.ts +113 -0
  188. package/dist-cjs/agent/permissions.js +189 -0
  189. package/dist-cjs/agent/sandbox.d.ts +151 -0
  190. package/dist-cjs/agent/sandbox.js +297 -0
  191. package/dist-cjs/agent/tool.d.ts +8 -3
  192. package/dist-cjs/agent/tool.js +14 -3
  193. package/dist-cjs/core/secure-stream.js +4 -3
  194. package/dist-cjs/deep-agent/index.d.ts +109 -0
  195. package/dist-cjs/deep-agent/index.js +219 -0
  196. package/dist-cjs/embeddings/adapters.js +2 -1
  197. package/dist-cjs/evals/judge.js +2 -5
  198. package/dist-cjs/evaluate/cache.d.ts +0 -14
  199. package/dist-cjs/evaluate/cache.js +1 -65
  200. package/dist-cjs/evaluate/file-cache.d.ts +15 -0
  201. package/dist-cjs/evaluate/file-cache.js +67 -0
  202. package/dist-cjs/evaluate/index.d.ts +2 -1
  203. package/dist-cjs/evaluate/index.js +3 -2
  204. package/dist-cjs/evaluate/review.js +2 -2
  205. package/dist-cjs/evaluate/run.js +2 -2
  206. package/dist-cjs/evaluate/version.js +3 -3
  207. package/dist-cjs/graph/functional.d.ts +9 -0
  208. package/dist-cjs/graph/functional.js +20 -3
  209. package/dist-cjs/graph/graph.js +27 -6
  210. package/dist-cjs/graph/lint.d.ts +4 -1
  211. package/dist-cjs/graph/lint.js +35 -0
  212. package/dist-cjs/graph/node-cache.js +3 -3
  213. package/dist-cjs/hallucination/rag.d.ts +4 -1
  214. package/dist-cjs/hallucination/rag.js +6 -1
  215. package/dist-cjs/images/asset-stores.js +2 -3
  216. package/dist-cjs/images/asset-support.js +2 -2
  217. package/dist-cjs/images/assets.js +1 -2
  218. package/dist-cjs/images/evals.js +4 -4
  219. package/dist-cjs/insights/proposals.js +1 -2
  220. package/dist-cjs/insights/regressions.d.ts +26 -2
  221. package/dist-cjs/insights/regressions.js +129 -3
  222. package/dist-cjs/loaders/git.js +8 -1
  223. package/dist-cjs/loaders/web.js +7 -1
  224. package/dist-cjs/mcp/client.d.ts +14 -0
  225. package/dist-cjs/mcp/client.js +60 -1
  226. package/dist-cjs/mcp/registry.d.ts +6 -0
  227. package/dist-cjs/mcp/registry.js +7 -0
  228. package/dist-cjs/postgres/fulltext.d.ts +67 -0
  229. package/dist-cjs/postgres/fulltext.js +129 -0
  230. package/dist-cjs/prompts/file.js +28 -11
  231. package/dist-cjs/protocols/a2a.d.ts +235 -0
  232. package/dist-cjs/protocols/a2a.js +393 -0
  233. package/dist-cjs/protocols/acp.d.ts +87 -0
  234. package/dist-cjs/protocols/acp.js +326 -0
  235. package/dist-cjs/protocols/ag-ui.d.ts +120 -0
  236. package/dist-cjs/protocols/ag-ui.js +186 -0
  237. package/dist-cjs/protocols/shared.d.ts +80 -0
  238. package/dist-cjs/protocols/shared.js +59 -0
  239. package/dist-cjs/providers/anthropic.js +1 -0
  240. package/dist-cjs/providers/cohere.js +2 -2
  241. package/dist-cjs/providers/google.js +3 -12
  242. package/dist-cjs/providers/openai.js +1 -0
  243. package/dist-cjs/rag/elasticsearch.d.ts +71 -0
  244. package/dist-cjs/rag/elasticsearch.js +135 -0
  245. package/dist-cjs/rag/file-ingestion.js +14 -8
  246. package/dist-cjs/rag/pipeline.d.ts +140 -0
  247. package/dist-cjs/rag/pipeline.js +191 -0
  248. package/dist-cjs/rag/rerankers.d.ts +92 -0
  249. package/dist-cjs/rag/rerankers.js +107 -0
  250. package/dist-cjs/rag/retrievers.d.ts +12 -1
  251. package/dist-cjs/runtime/detect.d.ts +17 -0
  252. package/dist-cjs/runtime/detect.js +19 -0
  253. package/dist-cjs/runtime/index.d.ts +19 -0
  254. package/dist-cjs/runtime/index.js +31 -0
  255. package/dist-cjs/security/injection-detector.d.ts +2 -0
  256. package/dist-cjs/security/injection-detector.js +7 -1
  257. package/dist-cjs/security/input-guard.js +5 -2
  258. package/dist-cjs/security/output-guard.js +8 -4
  259. package/dist-cjs/security/pii-detector.js +22 -6
  260. package/dist-cjs/security/prompt-hardening.js +6 -2
  261. package/dist-cjs/security/semantic-injection-classifier.d.ts +2 -1
  262. package/dist-cjs/security/semantic-injection-classifier.js +31 -35
  263. package/dist-cjs/security/upload-scanner.d.ts +8 -0
  264. package/dist-cjs/security/upload-scanner.js +53 -9
  265. package/dist-cjs/server/assistant.d.ts +5 -1
  266. package/dist-cjs/server/assistant.js +4 -2
  267. package/dist-cjs/server/auth.d.ts +250 -0
  268. package/dist-cjs/server/auth.js +402 -0
  269. package/dist-cjs/server/deployments.d.ts +63 -1
  270. package/dist-cjs/server/deployments.js +75 -2
  271. package/dist-cjs/server/runs.d.ts +9 -0
  272. package/dist-cjs/server/runs.js +20 -0
  273. package/dist-cjs/server/server.js +5 -0
  274. package/dist-cjs/store/memory.d.ts +10 -0
  275. package/dist-cjs/store/memory.js +10 -0
  276. package/dist-cjs/testing/record.js +2 -2
  277. package/dist-cjs/tracing/stores.js +2 -1
  278. package/dist-cjs/tracing/tracer.js +2 -2
  279. package/dist-cjs/types/config.d.ts +20 -0
  280. package/dist-cjs/types/graph.d.ts +38 -0
  281. package/dist-cjs/types/messages.d.ts +36 -2
  282. package/dist-cjs/types/principal.d.ts +21 -0
  283. package/dist-cjs/types/principal.js +2 -0
  284. package/dist-cjs/types/server.d.ts +8 -9
  285. package/dist-cjs/utils/base64.d.ts +4 -0
  286. package/dist-cjs/utils/base64.js +25 -0
  287. package/dist-cjs/utils/checksums.d.ts +22 -0
  288. package/dist-cjs/utils/checksums.js +46 -0
  289. package/dist-cjs/utils/ids.d.ts +8 -0
  290. package/dist-cjs/utils/ids.js +28 -2
  291. package/dist-cjs/utils/sha256.d.ts +22 -0
  292. package/dist-cjs/utils/sha256.js +125 -0
  293. package/dist-cjs/utils/tenant.d.ts +11 -0
  294. package/dist-cjs/utils/tenant.js +15 -0
  295. package/dist-cjs/version.d.ts +1 -1
  296. package/dist-cjs/version.js +1 -1
  297. package/llms.txt +7 -3
  298. package/package.json +193 -6
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filesystemContext = filesystemContext;
4
+ function filesystemContext(options) {
5
+ const maxChars = options.maxChars ?? 32_000;
6
+ const offload = options.offload === true
7
+ ? {}
8
+ : options.offload === false || options.offload === undefined
9
+ ? undefined
10
+ : options.offload;
11
+ if (offload && !options.source.writeFile) {
12
+ throw new TypeError('filesystemContext() offloading needs a source with writeFile()');
13
+ }
14
+ const loaded = new Map();
15
+ const load = async () => {
16
+ const sections = [];
17
+ let budget = maxChars;
18
+ for (const file of options.include ?? []) {
19
+ if (budget <= 0)
20
+ break;
21
+ let text;
22
+ try {
23
+ text = await options.source.readFile(file);
24
+ }
25
+ catch {
26
+ continue;
27
+ }
28
+ const cut = text.length > budget ? `${text.slice(0, budget)}\n[cut: ${text.length - budget} more characters]` : text;
29
+ budget -= text.length;
30
+ sections.push(`<file path="${file}">\n${cut}\n</file>`);
31
+ }
32
+ if (options.listing && options.source.listFiles) {
33
+ try {
34
+ const entries = await options.source.listFiles(options.listing.directory ?? '.');
35
+ const max = options.listing.maxEntries ?? 200;
36
+ const shown = entries.slice(0, max).join('\n');
37
+ sections.push(`<listing directory="${options.listing.directory ?? '.'}">\n${shown}${entries.length > max ? `\n[${entries.length - max} more]` : ''}\n</listing>`);
38
+ }
39
+ catch {
40
+ }
41
+ }
42
+ return sections.length ? `Files from the workspace:\n\n${sections.join('\n\n')}` : undefined;
43
+ };
44
+ return {
45
+ name: 'filesystem-context',
46
+ async beforeModel({ request, state, threadId }) {
47
+ if (!options.include?.length && !options.listing)
48
+ return;
49
+ const turn = state.messages.filter((message) => message.role === 'user').length;
50
+ const key = `${threadId}:${turn}`;
51
+ let pending = loaded.get(key);
52
+ if (!pending) {
53
+ pending = load();
54
+ loaded.set(key, pending);
55
+ if (loaded.size > 256)
56
+ loaded.delete(loaded.keys().next().value);
57
+ }
58
+ const text = await pending;
59
+ if (!text)
60
+ return;
61
+ const systemCount = request.messages.findIndex((message) => message.role !== 'system');
62
+ const at = systemCount === -1 ? request.messages.length : systemCount;
63
+ const context = { role: 'system', content: text };
64
+ return { ...request, messages: [...request.messages.slice(0, at), context, ...request.messages.slice(at)] };
65
+ },
66
+ async wrapToolCall(call, next) {
67
+ const result = await next();
68
+ if (!offload || !result.ok || (offload.exclude ?? ['read_file']).includes(call.name))
69
+ return result;
70
+ const value = result.result;
71
+ if (value?.type === 'tool_output')
72
+ return result;
73
+ const text = typeof value === 'string' ? value : JSON.stringify(value);
74
+ if (text === undefined || text.length <= (offload.overChars ?? 20_000))
75
+ return result;
76
+ const directory = (offload.directory ?? '.context').replace(/\/+$/, '');
77
+ const file = `${directory}/${`${call.name}-${call.id}`.replace(/[^A-Za-z0-9._-]/g, '_')}.txt`;
78
+ await options.source.writeFile?.(file, text);
79
+ const preview = text.slice(0, offload.previewChars ?? 1_000);
80
+ return {
81
+ ok: true,
82
+ result: `${preview}\n\n[This result is ${text.length} characters; the first ${preview.length} are above. The whole result is in ${file}: read it with read_file when you need the rest.]`,
83
+ };
84
+ },
85
+ };
86
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Middleware for `createAgent()`, each its own import: retries, fallbacks, model choice, tool
3
+ * selection, context editing, personal data, approvals, limits, and the filesystem as context.
4
+ *
5
+ * Each is ordinary `AgentMiddleware` built on the same hooks an application's own middleware uses,
6
+ * so any of them can be read, copied, and changed. None adds a dependency, and a bundler keeps only
7
+ * the ones imported.
8
+ */
9
+ export { limitToolCalls, redactMessages, type RedactOptions, summarizeHistory, type SummarizeOptions, } from './basic.js';
10
+ export { type ClearedToolResult, type ContextEdit, contextEditor, type ContextEditorOptions, estimateRequestTokens, } from './context-editor.js';
11
+ export { type ContextOffloadOptions, filesystemContext, type FilesystemContextOptions, type FilesystemContextSource, } from './filesystem.js';
12
+ export { humanApproval, type HumanApprovalOptions } from './approval.js';
13
+ export { modelCallLimit, ModelCallLimitError, type ModelCallLimitOptions } from './limits.js';
14
+ export { type DynamicModelContext, dynamicModel, modelFallback, type ModelFallbackEvent, type ModelFallbackOptions, type ModelFallbackTarget, } from './models.js';
15
+ export { PiiBlockedError, type PiiFinding, type PiiKind, piiMiddleware, type PiiMiddlewareOptions, type PiiStrategy, type PiiWhere, } from './pii.js';
16
+ export { modelRetry, type ModelRetryOptions, type RetryEvent, toolRetry, type ToolRetryOptions } from './retry.js';
17
+ export type { RetryBackoff } from './shared.js';
18
+ export { type ToolSelection, type ToolSelectionContext, toolSelector, type ToolSelectorOptions, } from './tool-selector.js';
19
+ export type { AgentMiddleware, AgentMiddlewareContext, AgentModelCallContext, AgentToolCall, AgentToolResult, } from '../create-agent.js';
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toolSelector = exports.toolRetry = exports.modelRetry = exports.piiMiddleware = exports.PiiBlockedError = exports.modelFallback = exports.dynamicModel = exports.ModelCallLimitError = exports.modelCallLimit = exports.humanApproval = exports.filesystemContext = exports.estimateRequestTokens = exports.contextEditor = exports.summarizeHistory = exports.redactMessages = exports.limitToolCalls = void 0;
4
+ var basic_js_1 = require("./basic.js");
5
+ Object.defineProperty(exports, "limitToolCalls", { enumerable: true, get: function () { return basic_js_1.limitToolCalls; } });
6
+ Object.defineProperty(exports, "redactMessages", { enumerable: true, get: function () { return basic_js_1.redactMessages; } });
7
+ Object.defineProperty(exports, "summarizeHistory", { enumerable: true, get: function () { return basic_js_1.summarizeHistory; } });
8
+ var context_editor_js_1 = require("./context-editor.js");
9
+ Object.defineProperty(exports, "contextEditor", { enumerable: true, get: function () { return context_editor_js_1.contextEditor; } });
10
+ Object.defineProperty(exports, "estimateRequestTokens", { enumerable: true, get: function () { return context_editor_js_1.estimateRequestTokens; } });
11
+ var filesystem_js_1 = require("./filesystem.js");
12
+ Object.defineProperty(exports, "filesystemContext", { enumerable: true, get: function () { return filesystem_js_1.filesystemContext; } });
13
+ var approval_js_1 = require("./approval.js");
14
+ Object.defineProperty(exports, "humanApproval", { enumerable: true, get: function () { return approval_js_1.humanApproval; } });
15
+ var limits_js_1 = require("./limits.js");
16
+ Object.defineProperty(exports, "modelCallLimit", { enumerable: true, get: function () { return limits_js_1.modelCallLimit; } });
17
+ Object.defineProperty(exports, "ModelCallLimitError", { enumerable: true, get: function () { return limits_js_1.ModelCallLimitError; } });
18
+ var models_js_1 = require("./models.js");
19
+ Object.defineProperty(exports, "dynamicModel", { enumerable: true, get: function () { return models_js_1.dynamicModel; } });
20
+ Object.defineProperty(exports, "modelFallback", { enumerable: true, get: function () { return models_js_1.modelFallback; } });
21
+ var pii_js_1 = require("./pii.js");
22
+ Object.defineProperty(exports, "PiiBlockedError", { enumerable: true, get: function () { return pii_js_1.PiiBlockedError; } });
23
+ Object.defineProperty(exports, "piiMiddleware", { enumerable: true, get: function () { return pii_js_1.piiMiddleware; } });
24
+ var retry_js_1 = require("./retry.js");
25
+ Object.defineProperty(exports, "modelRetry", { enumerable: true, get: function () { return retry_js_1.modelRetry; } });
26
+ Object.defineProperty(exports, "toolRetry", { enumerable: true, get: function () { return retry_js_1.toolRetry; } });
27
+ var tool_selector_js_1 = require("./tool-selector.js");
28
+ Object.defineProperty(exports, "toolSelector", { enumerable: true, get: function () { return tool_selector_js_1.toolSelector; } });
@@ -0,0 +1,42 @@
1
+ import type { AgentMiddleware } from '../create-agent.js';
2
+ /** Options for `modelCallLimit()`. Set `run`, `thread`, or both. */
3
+ export interface ModelCallLimitOptions {
4
+ /** Model calls in one run: from a user message to the answer, a resumed approval included. */
5
+ run?: number;
6
+ /**
7
+ * Model calls over a thread's whole life, every run on it included. Counted in the agent's store
8
+ * when it has one, so every process shares the count and it survives a restart; otherwise in this
9
+ * process. A budget, not a lock: two runs on one thread at the same moment may each pass it once.
10
+ */
11
+ thread?: number;
12
+ /**
13
+ * What happens at a limit: `end` answers with `message` and stops with `stopReason: 'stopped'`,
14
+ * without calling the model; `error` fails the run with a `ModelCallLimitError`. Defaults to `end`.
15
+ */
16
+ onLimit?: 'end' | 'error';
17
+ /** The answer a run ends with under `end`. Defaults to a sentence naming the limit. */
18
+ message?: string;
19
+ }
20
+ /** Thrown by `modelCallLimit()` under `onLimit: 'error'`. */
21
+ export declare class ModelCallLimitError extends Error {
22
+ /** Which limit was reached. */
23
+ readonly scope: 'run' | 'thread';
24
+ /** The limit. */
25
+ readonly limit: number;
26
+ /** Always `MODEL_CALL_LIMIT`. */
27
+ readonly code = "MODEL_CALL_LIMIT";
28
+ constructor(
29
+ /** Which limit was reached. */
30
+ scope: 'run' | 'thread',
31
+ /** The limit. */
32
+ limit: number);
33
+ }
34
+ /**
35
+ * Caps the model calls of a run, of a thread, or both.
36
+ *
37
+ * `maxIterations` stops one run that keeps calling tools; this is a budget an application sets per
38
+ * run and per conversation, so a thread a user keeps coming back to cannot spend without bound. The
39
+ * run count is read from the transcript, so it survives a restart. A run that reaches a limit ends
40
+ * with an answer rather than an error, unless you ask for one.
41
+ */
42
+ export declare function modelCallLimit(options: ModelCallLimitOptions): AgentMiddleware;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModelCallLimitError = void 0;
4
+ exports.modelCallLimit = modelCallLimit;
5
+ const shared_js_1 = require("./shared.js");
6
+ class ModelCallLimitError extends Error {
7
+ scope;
8
+ limit;
9
+ code = 'MODEL_CALL_LIMIT';
10
+ constructor(scope, limit) {
11
+ super(`The agent reached its limit of ${limit} model calls per ${scope}`);
12
+ this.scope = scope;
13
+ this.limit = limit;
14
+ this.name = 'ModelCallLimitError';
15
+ }
16
+ }
17
+ exports.ModelCallLimitError = ModelCallLimitError;
18
+ const NAMESPACE = ['nexus', 'agent', 'model-calls'];
19
+ function modelCallLimit(options) {
20
+ if (options.run === undefined && options.thread === undefined) {
21
+ throw new RangeError('modelCallLimit() needs a run limit, a thread limit, or both');
22
+ }
23
+ const local = new Map();
24
+ return {
25
+ name: 'model-call-limit',
26
+ async wrapModelCall(request, next, context) {
27
+ let reached;
28
+ if (options.run !== undefined && (0, shared_js_1.modelCallsInTurn)(context.state.messages) >= options.run) {
29
+ reached = ['run', options.run];
30
+ }
31
+ let used = 0;
32
+ if (!reached && options.thread !== undefined) {
33
+ used = context.store
34
+ ? ((await context.store.get(NAMESPACE, context.threadId))?.value ?? 0)
35
+ : (local.get(context.threadId) ?? 0);
36
+ if (used >= options.thread)
37
+ reached = ['thread', options.thread];
38
+ }
39
+ if (reached) {
40
+ const [scope, limit] = reached;
41
+ if (options.onLimit === 'error')
42
+ throw new ModelCallLimitError(scope, limit);
43
+ return context.stop(options.message ?? `I stopped here: this ${scope} reached its limit of ${limit} model calls.`);
44
+ }
45
+ if (options.thread !== undefined) {
46
+ if (context.store)
47
+ await context.store.put(NAMESPACE, context.threadId, used + 1);
48
+ else {
49
+ local.set(context.threadId, used + 1);
50
+ if (local.size > 10_000)
51
+ local.delete(local.keys().next().value);
52
+ }
53
+ }
54
+ return next(request);
55
+ },
56
+ };
57
+ }
@@ -0,0 +1,48 @@
1
+ import type { CompletionRequest } from '../../types/messages.js';
2
+ import type { AgentMiddleware, AgentMiddlewareContext, AgentModelClient } from '../create-agent.js';
3
+ /** A model to fall back to: a model name for the agent's own client, or another client. */
4
+ export type ModelFallbackTarget = string | {
5
+ client: AgentModelClient;
6
+ model?: string;
7
+ };
8
+ /** One fallback about to happen. */
9
+ export interface ModelFallbackEvent {
10
+ /** The model that failed. */
11
+ from: string;
12
+ /** The model tried next. */
13
+ to: string;
14
+ /** What the failed call threw. */
15
+ error: unknown;
16
+ }
17
+ /** Options for `modelFallback()`. */
18
+ export interface ModelFallbackOptions {
19
+ /** Whether an error moves on to the next model. Defaults to every error but a cancellation. */
20
+ fallbackOn?: (error: unknown, model: string) => boolean;
21
+ /** Called before each fallback, for logs and metrics. */
22
+ onFallback?: (event: ModelFallbackEvent) => void;
23
+ }
24
+ /**
25
+ * Tries other models, in order, when the model call fails.
26
+ *
27
+ * The client's router already falls back between providers for one request; this is the fallback
28
+ * it cannot make: to a client of a different kind, or once the client's own routes are exhausted. A
29
+ * target with its own client is called through `complete()`, never streamed, and middleware after
30
+ * this one does not wrap it.
31
+ */
32
+ export declare function modelFallback(models: readonly ModelFallbackTarget[], options?: ModelFallbackOptions): AgentMiddleware;
33
+ /** What `dynamicModel()` decides from: the step's context and the request about to be sent. */
34
+ export type DynamicModelContext = AgentMiddlewareContext & {
35
+ request: CompletionRequest;
36
+ };
37
+ /**
38
+ * Chooses the model for each call from the run so far.
39
+ *
40
+ * A cheap model for the first steps and a stronger one once the task proves hard, a model with a
41
+ * longer context once the transcript grows, or a tenant's own model. Returning nothing keeps the
42
+ * model the request already names.
43
+ *
44
+ * ```ts
45
+ * dynamicModel(({ state }) => (state.iterations >= 4 ? 'gpt-5' : 'gpt-5-mini'))
46
+ * ```
47
+ */
48
+ export declare function dynamicModel(select: (context: DynamicModelContext) => string | undefined | Promise<string | undefined>): AgentMiddleware;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.modelFallback = modelFallback;
4
+ exports.dynamicModel = dynamicModel;
5
+ const shared_js_1 = require("./shared.js");
6
+ function modelFallback(models, options = {}) {
7
+ if (models.length === 0)
8
+ throw new RangeError('modelFallback() needs at least one model to fall back to');
9
+ return {
10
+ name: 'model-fallback',
11
+ async wrapModelCall(request, next, context) {
12
+ try {
13
+ return await next(request);
14
+ }
15
+ catch (first) {
16
+ let error = first;
17
+ let from = request.model;
18
+ for (const target of models) {
19
+ if ((0, shared_js_1.isCancellation)(error, context.signal) || !(options.fallbackOn?.(error, from) ?? true))
20
+ throw error;
21
+ const model = typeof target === 'string' ? target : (target.model ?? request.model);
22
+ options.onFallback?.({ from, to: model, error });
23
+ try {
24
+ return typeof target === 'string'
25
+ ? await next({ ...request, model })
26
+ : await target.client.complete({ ...request, model });
27
+ }
28
+ catch (failure) {
29
+ error = failure;
30
+ from = model;
31
+ }
32
+ }
33
+ throw error;
34
+ }
35
+ },
36
+ };
37
+ }
38
+ function dynamicModel(select) {
39
+ return {
40
+ name: 'dynamic-model',
41
+ async beforeModel(context) {
42
+ const model = await select(context);
43
+ if (!model || model === context.request.model)
44
+ return;
45
+ return { ...context.request, model };
46
+ },
47
+ };
48
+ }
@@ -0,0 +1,67 @@
1
+ import type { AgentMiddleware } from '../create-agent.js';
2
+ /** The personal data and secrets `piiMiddleware()` finds on its own. */
3
+ export type PiiKind = 'email' | 'credit-card' | 'ssn' | 'phone' | 'iban' | 'ip-address' | 'secret';
4
+ /**
5
+ * What happens to a match: `redact` replaces it with its kind, `mask` keeps its last four
6
+ * characters, `hash` replaces it with a stable token so two values stay distinguishable, and `block`
7
+ * refuses the whole message.
8
+ */
9
+ export type PiiStrategy = 'redact' | 'mask' | 'hash' | 'block';
10
+ /** Where a match was found. */
11
+ export type PiiWhere = 'input' | 'output' | 'tool';
12
+ /** One match, as `onDetect` sees it: never the value itself. */
13
+ export interface PiiFinding {
14
+ /** Its kind: a built-in kind or a name from `patterns`. */
15
+ kind: string;
16
+ /** Where it was found. */
17
+ where: PiiWhere;
18
+ /** What was done with it. */
19
+ strategy: PiiStrategy;
20
+ }
21
+ /** Options for `piiMiddleware()`. */
22
+ export interface PiiMiddlewareOptions {
23
+ /** The built-in kinds to find. Defaults to all of them. */
24
+ kinds?: readonly PiiKind[];
25
+ /** Kinds of your own, by name: `{ 'employee-id': /\bEMP-\d{6}\b/ }`. */
26
+ patterns?: Readonly<Record<string, RegExp>>;
27
+ /**
28
+ * What happens to a match, for every kind or per kind: `'mask'`, or
29
+ * `{ email: 'hash', 'credit-card': 'block' }`. Kinds not named are redacted.
30
+ */
31
+ strategy?: PiiStrategy | Readonly<Record<string, PiiStrategy>>;
32
+ /**
33
+ * Where to look. `input` is every message sent to the model but the system prompt; `output` is
34
+ * the model's answer; `toolResults` cleans a result before it enters the transcript, so it is never
35
+ * checkpointed either. Defaults to input and tool results.
36
+ */
37
+ apply?: {
38
+ input?: boolean;
39
+ output?: boolean;
40
+ toolResults?: boolean;
41
+ };
42
+ /** Called for each match, for an audit trail. */
43
+ onDetect?: (finding: PiiFinding) => void;
44
+ }
45
+ /** Thrown when a match under the `block` strategy is found in the model's input or output. */
46
+ export declare class PiiBlockedError extends Error {
47
+ /** The kind that was found. */
48
+ readonly kind: string;
49
+ /** Where it was found. */
50
+ readonly where: PiiWhere;
51
+ /** Always `PII_BLOCKED`. */
52
+ readonly code = "PII_BLOCKED";
53
+ constructor(
54
+ /** The kind that was found. */
55
+ kind: string,
56
+ /** Where it was found. */
57
+ where: PiiWhere);
58
+ }
59
+ /**
60
+ * Keeps personal data and secrets away from the model, the transcript, or both.
61
+ *
62
+ * Finds emails, card numbers (checked with Luhn), US social security numbers, phone numbers, IBANs
63
+ * (checked with their checksum), IP addresses, and common API keys and private keys, plus any kinds
64
+ * of your own; and redacts, masks, hashes, or blocks each. The validated kinds keep false positives
65
+ * low: an order number is not a card number unless its checksum says so.
66
+ */
67
+ export declare function piiMiddleware(options?: PiiMiddlewareOptions): AgentMiddleware;
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PiiBlockedError = void 0;
4
+ exports.piiMiddleware = piiMiddleware;
5
+ const checksums_js_1 = require("../../utils/checksums.js");
6
+ const shared_js_1 = require("./shared.js");
7
+ class PiiBlockedError extends Error {
8
+ kind;
9
+ where;
10
+ code = 'PII_BLOCKED';
11
+ constructor(kind, where) {
12
+ super(`The ${where === 'input' ? 'request' : 'response'} contains ${kind}, which is blocked`);
13
+ this.kind = kind;
14
+ this.where = where;
15
+ this.name = 'PiiBlockedError';
16
+ }
17
+ }
18
+ exports.PiiBlockedError = PiiBlockedError;
19
+ const DETECTORS = {
20
+ secret: {
21
+ pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----|\b(?:sk-[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|gh[pousr]_[A-Za-z0-9]{36,}|xox[abprs]-[A-Za-z0-9-]{10,}|AIza[0-9A-Za-z_-]{35})\b/g,
22
+ },
23
+ email: { pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g },
24
+ 'credit-card': { pattern: /\b\d(?:[ -]?\d){12,18}\b/g, valid: checksums_js_1.luhn },
25
+ iban: { pattern: /\b[A-Z]{2}\d{2}(?: ?[A-Z0-9]{4}){2,7}(?: ?[A-Z0-9]{1,4})?\b/g, valid: checksums_js_1.ibanChecksum },
26
+ ssn: { pattern: /\b(?!000|666|9\d\d)\d{3}-(?!00)\d{2}-(?!0000)\d{4}\b/g },
27
+ 'ip-address': { pattern: /\b(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)\b/g },
28
+ phone: {
29
+ pattern: /(?<![\w+])\+?(?:\(\d{1,4}\)|\d{1,4})(?:[ .-]?(?:\(\d{1,4}\)|\d{2,4})){2,4}(?!\w)/g,
30
+ valid: checksums_js_1.phoneNumber,
31
+ },
32
+ };
33
+ const ORDER = ['secret', 'email', 'credit-card', 'iban', 'ssn', 'ip-address', 'phone'];
34
+ function piiMiddleware(options = {}) {
35
+ const kinds = new Set(options.kinds ?? ORDER);
36
+ const detectors = [
37
+ ...ORDER.filter((kind) => kinds.has(kind)).map((kind) => [kind, DETECTORS[kind]]),
38
+ ...Object.entries(options.patterns ?? {}).map(([kind, pattern]) => [
39
+ kind,
40
+ { pattern: pattern.flags.includes('g') ? pattern : new RegExp(pattern.source, `${pattern.flags}g`) },
41
+ ]),
42
+ ];
43
+ const apply = { input: true, output: false, toolResults: true, ...options.apply };
44
+ const strategyOf = (kind) => typeof options.strategy === 'string' ? options.strategy : (options.strategy?.[kind] ?? 'redact');
45
+ const clean = (text, where) => {
46
+ let current = text;
47
+ for (const [kind, detector] of detectors) {
48
+ const strategy = strategyOf(kind);
49
+ let blocked = false;
50
+ current = current.replace(detector.pattern, (match) => {
51
+ if (detector.valid && !detector.valid(match))
52
+ return match;
53
+ options.onDetect?.({ kind, where, strategy });
54
+ if (strategy === 'block')
55
+ blocked = true;
56
+ return replace(match, kind, strategy);
57
+ });
58
+ if (blocked)
59
+ return { blocked: kind };
60
+ }
61
+ return { text: current };
62
+ };
63
+ const cleanMessage = (message, where) => {
64
+ if (typeof message.content === 'string') {
65
+ const result = clean(message.content, where);
66
+ if ('blocked' in result)
67
+ throw new PiiBlockedError(result.blocked, where);
68
+ return result.text === message.content ? message : { ...message, content: result.text };
69
+ }
70
+ let changed = false;
71
+ const content = message.content.map((part) => {
72
+ if (part.type !== 'text')
73
+ return part;
74
+ const result = clean(part.text, where);
75
+ if ('blocked' in result)
76
+ throw new PiiBlockedError(result.blocked, where);
77
+ if (result.text === part.text)
78
+ return part;
79
+ changed = true;
80
+ return { ...part, text: result.text };
81
+ });
82
+ return changed ? { ...message, content } : message;
83
+ };
84
+ return {
85
+ name: 'pii',
86
+ beforeModel({ request }) {
87
+ if (!apply.input)
88
+ return;
89
+ return {
90
+ ...request,
91
+ messages: request.messages.map((message) => message.role === 'system' ? message : cleanMessage(message, 'input')),
92
+ };
93
+ },
94
+ afterModel({ response }) {
95
+ if (!apply.output || !response.content)
96
+ return;
97
+ const result = clean(response.content, 'output');
98
+ if ('blocked' in result)
99
+ throw new PiiBlockedError(result.blocked, 'output');
100
+ return result.text === response.content ? undefined : { ...response, content: result.text };
101
+ },
102
+ async wrapToolCall(_call, next) {
103
+ const result = await next();
104
+ if (!apply.toolResults || !result.ok)
105
+ return result;
106
+ let blocked;
107
+ const walk = (value) => {
108
+ if (blocked)
109
+ return value;
110
+ if (typeof value === 'string') {
111
+ const cleaned = clean(value, 'tool');
112
+ if ('blocked' in cleaned) {
113
+ blocked = cleaned.blocked;
114
+ return value;
115
+ }
116
+ return cleaned.text;
117
+ }
118
+ if (Array.isArray(value))
119
+ return value.map(walk);
120
+ if (isToolOutput(value)) {
121
+ const content = value.content.map((part) => part.type === 'text' ? { ...part, text: walk(part.text) } : part);
122
+ return { ...value, content };
123
+ }
124
+ if (value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype) {
125
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, walk(entry)]));
126
+ }
127
+ return value;
128
+ };
129
+ const cleaned = walk(result.result);
130
+ if (blocked)
131
+ return { ok: false, error: `The tool's result was withheld: it contains ${blocked}` };
132
+ return { ...result, result: cleaned };
133
+ },
134
+ };
135
+ }
136
+ function replace(match, kind, strategy) {
137
+ if (strategy === 'mask') {
138
+ const visible = match.replace(/[^A-Za-z0-9]/g, '').slice(-4);
139
+ return `${'*'.repeat(Math.max(4, match.length - visible.length))}${visible}`;
140
+ }
141
+ if (strategy === 'hash')
142
+ return `[${kind}:${(0, shared_js_1.shortHash)(match)}]`;
143
+ return `[${kind}]`;
144
+ }
145
+ function isToolOutput(value) {
146
+ return value?.type === 'tool_output' && Array.isArray(value.content);
147
+ }
@@ -0,0 +1,66 @@
1
+ import type { NexusResponse } from '../../types/response.js';
2
+ import type { AgentMiddleware, AgentToolCall, AgentToolResult } from '../create-agent.js';
3
+ import { type RetryBackoff } from './shared.js';
4
+ /** One retry about to happen. */
5
+ export interface RetryEvent {
6
+ /** The attempt that failed, from 1. */
7
+ attempt: number;
8
+ /** How long until the next attempt, in milliseconds. */
9
+ delayMs: number;
10
+ /** The error a model call threw, when it threw. */
11
+ error?: unknown;
12
+ /** The failed tool call's result, for a tool retry. */
13
+ result?: AgentToolResult;
14
+ /** The tool's name, for a tool retry. */
15
+ tool?: string;
16
+ }
17
+ /** Options for `modelRetry()`. */
18
+ export interface ModelRetryOptions {
19
+ /** Attempts in all, the first included. Defaults to 3. */
20
+ attempts?: number;
21
+ /** How long to wait between attempts. */
22
+ backoff?: RetryBackoff;
23
+ /**
24
+ * Whether an error is worth another attempt. Defaults to every error not marked
25
+ * `retryable: false`, such as a provider's authentication error, and never a cancellation.
26
+ */
27
+ retryOn?: (error: unknown, attempt: number) => boolean;
28
+ /** Whether a response that did arrive is tried again, such as an empty one. Defaults to never. */
29
+ retryResponse?: (response: NexusResponse, attempt: number) => boolean;
30
+ /** Called before each new attempt, for logs and metrics. */
31
+ onRetry?: (event: RetryEvent) => void;
32
+ }
33
+ /**
34
+ * Tries a failed model call again, with exponential backoff.
35
+ *
36
+ * The client already retries one provider request; this retries the agent's step as a whole, after
37
+ * the client gave up, and can retry a response that arrived but is unusable. A streamed call that
38
+ * fails halfway streams again from the start. Waits stop when the run is cancelled.
39
+ */
40
+ export declare function modelRetry(options?: ModelRetryOptions): AgentMiddleware;
41
+ /** Options for `toolRetry()`. */
42
+ export interface ToolRetryOptions {
43
+ /** Attempts in all, the first included. Defaults to 3. */
44
+ attempts?: number;
45
+ /** How long to wait between attempts. */
46
+ backoff?: RetryBackoff;
47
+ /**
48
+ * Which calls may run again: tool names, `'all'`, or a function of the call. Defaults to calls
49
+ * that are safe to repeat, whose tool declares capabilities and none of them writes, runs a
50
+ * command or code, reaches the network, or is the application's own. A call that may already have
51
+ * changed something is retried only when you say so.
52
+ */
53
+ tools?: readonly string[] | 'all' | ((call: AgentToolCall) => boolean);
54
+ /** Whether a result is a failure worth another attempt. Defaults to any result with `ok: false`. */
55
+ retryOn?: (result: AgentToolResult, call: AgentToolCall, attempt: number) => boolean;
56
+ /** Called before each new attempt, for logs and metrics. */
57
+ onRetry?: (event: RetryEvent) => void;
58
+ }
59
+ /**
60
+ * Runs a failed tool call again, with exponential backoff.
61
+ *
62
+ * By default only a call that cannot have changed anything is repeated: retrying a payment or a
63
+ * write that timed out after it landed would do it twice. Name the tools that are idempotent to
64
+ * retry those too.
65
+ */
66
+ export declare function toolRetry(options?: ToolRetryOptions): AgentMiddleware;