@inflexa-ai/harness 0.45.0 → 0.46.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 (802) hide show
  1. package/README.md +6 -3
  2. package/dist/agents/conversation-agent.d.ts +19 -3
  3. package/dist/agents/conversation-agent.js +49 -30
  4. package/dist/agents/report-session-agent.d.ts +15 -15
  5. package/dist/agents/report-session-agent.js +23 -15
  6. package/dist/agents/sandbox/index.d.ts +1 -1
  7. package/dist/agents/sandbox/index.js +1 -1
  8. package/dist/agents/sandbox/shared.d.ts +35 -16
  9. package/dist/agents/sandbox/shared.js +63 -24
  10. package/dist/agents/sandbox/translational-safety-agent.js +26 -0
  11. package/dist/agents/sandbox/types.d.ts +26 -3
  12. package/dist/agents/sandbox/validate-skills.d.ts +2 -2
  13. package/dist/agents/sandbox/validate-skills.js +3 -1
  14. package/dist/agents/sandbox-catalog.d.ts +16 -2
  15. package/dist/agents/sandbox-catalog.js +22 -3
  16. package/dist/agents/system-prompt.d.ts +2 -2
  17. package/dist/app/approve-plan.d.ts +5 -2
  18. package/dist/app/approve-plan.js +1 -1
  19. package/dist/app/chat-turn-workflow.d.ts +114 -0
  20. package/dist/app/chat-turn-workflow.js +307 -0
  21. package/dist/app/chat-turn.d.ts +85 -57
  22. package/dist/app/chat-turn.js +125 -99
  23. package/dist/app/data-profile-orientation.js +10 -8
  24. package/dist/app/data-profile-view.d.ts +4 -4
  25. package/dist/app/data-profile-view.js +9 -8
  26. package/dist/app/in-process-turn.d.ts +42 -0
  27. package/dist/app/in-process-turn.js +139 -0
  28. package/dist/app/message-assembly.d.ts +10 -4
  29. package/dist/app/message-assembly.js +13 -8
  30. package/dist/app/report-session-runtime.d.ts +4 -4
  31. package/dist/app/report-session-runtime.js +36 -21
  32. package/dist/app/spawn-report-session.d.ts +33 -28
  33. package/dist/app/spawn-report-session.js +25 -40
  34. package/dist/app/synthesize-run.d.ts +22 -16
  35. package/dist/app/synthesize-run.js +41 -35
  36. package/dist/app/work.d.ts +96 -0
  37. package/dist/app/work.js +147 -0
  38. package/dist/auth/local-auth-context.d.ts +1 -3
  39. package/dist/auth/local-auth-context.js +1 -3
  40. package/dist/auth/local-run-authorizer.d.ts +1 -1
  41. package/dist/auth/local-run-authorizer.js +5 -3
  42. package/dist/auth/types.d.ts +26 -26
  43. package/dist/billing/cached-resolver.d.ts +4 -4
  44. package/dist/billing/run-charge.d.ts +5 -8
  45. package/dist/billing/run-charge.js +2 -2
  46. package/dist/billing/usage-recorder.d.ts +9 -9
  47. package/dist/citations/aggregate.js +1 -1
  48. package/dist/citations/clients/arxiv.d.ts +2 -2
  49. package/dist/citations/clients/arxiv.js +12 -4
  50. package/dist/citations/clients/common.js +4 -2
  51. package/dist/citations/clients/crossref.d.ts +2 -2
  52. package/dist/citations/clients/crossref.js +37 -37
  53. package/dist/citations/clients/doi-registry.js +15 -16
  54. package/dist/citations/clients/pubmed.d.ts +2 -2
  55. package/dist/citations/clients/pubmed.js +20 -13
  56. package/dist/citations/clients/semantic-scholar.d.ts +2 -2
  57. package/dist/citations/clients/semantic-scholar.js +9 -9
  58. package/dist/citations/compare.js +2 -2
  59. package/dist/citations/match.d.ts +2 -2
  60. package/dist/citations/match.js +12 -7
  61. package/dist/citations/normalize.js +35 -26
  62. package/dist/citations/plan.js +6 -2
  63. package/dist/citations/resolve.d.ts +6 -6
  64. package/dist/citations/resolve.js +34 -25
  65. package/dist/citations/types.d.ts +77 -77
  66. package/dist/config/environment-stores.d.ts +10 -8
  67. package/dist/config/resource-limits.js +1 -3
  68. package/dist/contracts/analogy-report.d.ts +7 -7
  69. package/dist/contracts/analogy-report.js +2 -2
  70. package/dist/contracts/chat-events.d.ts +46 -22
  71. package/dist/contracts/chat-events.js +1 -1
  72. package/dist/contracts/chat-frame.d.ts +15 -5
  73. package/dist/contracts/chat-frame.js +67 -40
  74. package/dist/contracts/chat-parts.d.ts +130 -67
  75. package/dist/contracts/chat-parts.js +1 -0
  76. package/dist/contracts/content-url.js +16 -2
  77. package/dist/contracts/data-profile.d.ts +38 -38
  78. package/dist/contracts/index.d.ts +3 -3
  79. package/dist/contracts/index.js +1 -1
  80. package/dist/contracts/message.d.ts +6 -6
  81. package/dist/contracts/organ-system.d.ts +11 -11
  82. package/dist/contracts/part-registry.d.ts +5 -4
  83. package/dist/contracts/part-registry.js +5 -0
  84. package/dist/contracts/profile-vocabulary.d.ts +11 -10
  85. package/dist/contracts/profile-vocabulary.js +10 -3
  86. package/dist/contracts/report-blocks.d.ts +329 -329
  87. package/dist/contracts/report-reference.d.ts +105 -81
  88. package/dist/contracts/report-reference.js +30 -13
  89. package/dist/contracts/schemas/chat-events.d.ts +45 -6
  90. package/dist/contracts/schemas/chat-events.js +16 -0
  91. package/dist/contracts/schemas/chat-parts.d.ts +214 -102
  92. package/dist/contracts/schemas/chat-parts.js +50 -7
  93. package/dist/contracts/schemas/index.d.ts +1 -1
  94. package/dist/contracts/schemas/index.js +1 -1
  95. package/dist/contracts/severity.d.ts +1 -1
  96. package/dist/contracts/structure-source.d.ts +3 -3
  97. package/dist/contracts/structure-source.js +6 -2
  98. package/dist/contracts/subagent-activity.d.ts +2 -2
  99. package/dist/contracts/subagent-activity.js +5 -3
  100. package/dist/contracts/usage.d.ts +2 -2
  101. package/dist/data/safety-panel-schema.d.ts +25 -25
  102. package/dist/data/safety-panel-schema.js +13 -4
  103. package/dist/execution/artifact-metadata.d.ts +23 -15
  104. package/dist/execution/artifact-metadata.js +33 -10
  105. package/dist/execution/artifact-record.d.ts +2 -2
  106. package/dist/execution/artifact-registration.d.ts +5 -5
  107. package/dist/execution/artifact-registry.d.ts +8 -8
  108. package/dist/execution/dbos-run-launcher.d.ts +24 -4
  109. package/dist/execution/dbos-run-launcher.js +58 -4
  110. package/dist/execution/dbos-workflow-purger.d.ts +7 -6
  111. package/dist/execution/dbos-workflow-purger.js +29 -21
  112. package/dist/execution/input-signature.d.ts +2 -2
  113. package/dist/execution/post-step-pipeline.d.ts +9 -9
  114. package/dist/execution/post-step-pipeline.js +1 -1
  115. package/dist/execution/post-step.js +2 -2
  116. package/dist/execution/reconcile-manifest.d.ts +4 -4
  117. package/dist/execution/reconcile-manifest.js +3 -2
  118. package/dist/execution/run-authorizer.d.ts +46 -37
  119. package/dist/execution/run-authorizer.js +8 -8
  120. package/dist/execution/run-canceler.d.ts +39 -17
  121. package/dist/execution/run-canceler.js +137 -28
  122. package/dist/execution/run-end-record.d.ts +29 -0
  123. package/dist/execution/run-end-record.js +27 -0
  124. package/dist/execution/run-event-parts.d.ts +0 -8
  125. package/dist/execution/run-event-parts.js +29 -24
  126. package/dist/execution/run-event-stream.d.ts +8 -8
  127. package/dist/execution/run-event-stream.js +3 -4
  128. package/dist/execution/run-launcher.d.ts +4 -4
  129. package/dist/execution/run-synthesis.d.ts +49 -48
  130. package/dist/execution/run-synthesis.js +96 -255
  131. package/dist/execution/staged-input.d.ts +2 -2
  132. package/dist/execution/step-summary.d.ts +6 -6
  133. package/dist/execution/step-summary.js +4 -8
  134. package/dist/execution/topo-sort.js +4 -3
  135. package/dist/execution/workflow-purger.d.ts +2 -2
  136. package/dist/index.d.ts +25 -24
  137. package/dist/index.js +36 -37
  138. package/dist/input-sanitization.js +9 -2
  139. package/dist/input-scan/clustering.d.ts +6 -6
  140. package/dist/input-scan/clustering.js +11 -5
  141. package/dist/input-scan/companions.js +3 -2
  142. package/dist/input-scan/detect-sets.d.ts +2 -2
  143. package/dist/input-scan/detect-sets.js +25 -21
  144. package/dist/input-scan/enrich.d.ts +6 -6
  145. package/dist/input-scan/enrich.js +29 -12
  146. package/dist/input-scan/formats.d.ts +2 -2
  147. package/dist/input-scan/formats.js +8 -2
  148. package/dist/input-scan/markers.d.ts +2 -2
  149. package/dist/input-scan/markers.js +14 -5
  150. package/dist/input-scan/menu.d.ts +10 -10
  151. package/dist/input-scan/menu.js +0 -0
  152. package/dist/input-scan/quarantine.d.ts +2 -2
  153. package/dist/input-scan/quarantine.js +23 -18
  154. package/dist/input-scan/readout-budget.d.ts +2 -2
  155. package/dist/input-scan/readout-budget.js +1 -1
  156. package/dist/input-scan/readout.d.ts +2 -2
  157. package/dist/input-scan/readout.js +47 -34
  158. package/dist/input-scan/scan.d.ts +2 -2
  159. package/dist/input-scan/scan.js +7 -5
  160. package/dist/input-scan/set-types.d.ts +28 -28
  161. package/dist/input-scan/shapes.d.ts +4 -4
  162. package/dist/input-scan/shapes.js +0 -0
  163. package/dist/input-scan/templates.d.ts +10 -10
  164. package/dist/input-scan/templates.js +30 -22
  165. package/dist/input-scan/tokens.d.ts +6 -4
  166. package/dist/input-scan/tokens.js +100 -38
  167. package/dist/input-scan/types.d.ts +22 -22
  168. package/dist/lib/async-utils.d.ts +3 -7
  169. package/dist/lib/async-utils.js +5 -9
  170. package/dist/lib/cache.js +1 -1
  171. package/dist/lib/chrome.d.ts +46 -6
  172. package/dist/lib/console-logger.js +2 -2
  173. package/dist/lib/db-result.d.ts +22 -6
  174. package/dist/lib/db-result.js +9 -13
  175. package/dist/lib/eyes.d.ts +4 -4
  176. package/dist/lib/eyes.js +1 -1
  177. package/dist/lib/fs-helpers.js +18 -6
  178. package/dist/lib/fs-result.d.ts +1 -0
  179. package/dist/lib/fs-result.js +5 -6
  180. package/dist/lib/hooks.d.ts +23 -7
  181. package/dist/lib/hooks.js +17 -3
  182. package/dist/lib/host-concurrency.js +3 -2
  183. package/dist/lib/logger.d.ts +2 -2
  184. package/dist/lib/logger.js +2 -1
  185. package/dist/lib/metrics.d.ts +1 -1
  186. package/dist/lib/null-proto.d.ts +6 -0
  187. package/dist/lib/null-proto.js +17 -0
  188. package/dist/lib/otel-spans.d.ts +1 -1
  189. package/dist/lib/otel-spans.js +9 -5
  190. package/dist/lib/otel.d.ts +4 -2
  191. package/dist/lib/otel.js +10 -2
  192. package/dist/lib/page-capture.d.ts +8 -8
  193. package/dist/lib/page-capture.js +9 -4
  194. package/dist/lib/parse-json.d.ts +5 -0
  195. package/dist/lib/parse-json.js +12 -0
  196. package/dist/lib/present.d.ts +12 -0
  197. package/dist/lib/present.js +39 -0
  198. package/dist/lib/rate-limit.d.ts +4 -4
  199. package/dist/lib/rate-limit.js +12 -13
  200. package/dist/lib/regulatory-corpus/fetch-fda-guidance.d.ts +4 -4
  201. package/dist/lib/regulatory-corpus/fetch-fda-guidance.js +4 -10
  202. package/dist/lib/regulatory-corpus/fetch-ich.d.ts +4 -4
  203. package/dist/lib/regulatory-corpus/fetch-ich.js +18 -14
  204. package/dist/lib/regulatory-corpus/normalize-whitespace.d.ts +6 -0
  205. package/dist/lib/regulatory-corpus/normalize-whitespace.js +41 -0
  206. package/dist/lib/regulatory-corpus.d.ts +10 -10
  207. package/dist/lib/regulatory-corpus.js +3 -1
  208. package/dist/lib/result.d.ts +10 -11
  209. package/dist/lib/result.js +15 -13
  210. package/dist/lib/storage.d.ts +2 -2
  211. package/dist/lib/test/async-iterable.d.ts +9 -0
  212. package/dist/lib/test/async-iterable.js +28 -0
  213. package/dist/lib/test/request-url.d.ts +5 -0
  214. package/dist/lib/test/request-url.js +7 -0
  215. package/dist/lib/test/result-assert.d.ts +12 -0
  216. package/dist/lib/test/result-assert.js +17 -0
  217. package/dist/lib/test/text-shapes.d.ts +24 -0
  218. package/dist/lib/test/text-shapes.js +63 -0
  219. package/dist/lib/text.d.ts +22 -0
  220. package/dist/lib/text.js +68 -0
  221. package/dist/lib/thrown.d.ts +18 -0
  222. package/dist/lib/thrown.js +30 -0
  223. package/dist/lib/unknown-array.d.ts +6 -0
  224. package/dist/lib/unknown-array.js +8 -0
  225. package/dist/lib/unknown-containers.d.ts +14 -0
  226. package/dist/lib/unknown-containers.js +17 -0
  227. package/dist/lib/unknown-text.d.ts +8 -0
  228. package/dist/lib/unknown-text.js +28 -0
  229. package/dist/lib/zod-issue-shape.d.ts +1 -1
  230. package/dist/lib/zod-issue-shape.js +31 -31
  231. package/dist/lib/zod-issues.d.ts +3 -3
  232. package/dist/lib/zod-issues.js +30 -17
  233. package/dist/literature/sources/arxiv.d.ts +6 -6
  234. package/dist/literature/sources/arxiv.js +92 -35
  235. package/dist/literature/sources/http.d.ts +2 -2
  236. package/dist/literature/sources/http.js +16 -15
  237. package/dist/literature/sources/pubmed.d.ts +16 -16
  238. package/dist/literature/sources/pubmed.js +96 -61
  239. package/dist/literature/sources/semantic-scholar.d.ts +8 -8
  240. package/dist/literature/sources/semantic-scholar.js +22 -13
  241. package/dist/loop/accounting.d.ts +63 -0
  242. package/dist/loop/accounting.js +141 -0
  243. package/dist/loop/call-policy.d.ts +73 -0
  244. package/dist/loop/call-policy.js +109 -0
  245. package/dist/loop/chat-stream.d.ts +62 -0
  246. package/dist/loop/chat-stream.js +237 -0
  247. package/dist/loop/compaction.d.ts +14 -9
  248. package/dist/loop/compaction.js +17 -0
  249. package/dist/loop/metrics.d.ts +12 -15
  250. package/dist/loop/metrics.js +14 -26
  251. package/dist/loop/run-loop.d.ts +233 -0
  252. package/dist/loop/run-loop.js +770 -0
  253. package/dist/loop/sub-agent.d.ts +61 -0
  254. package/dist/loop/sub-agent.js +161 -0
  255. package/dist/loop/tool-adapter.d.ts +98 -0
  256. package/dist/loop/tool-adapter.js +364 -0
  257. package/dist/loop/tool-detail.d.ts +1 -1
  258. package/dist/loop/tool-detail.js +6 -5
  259. package/dist/loop/tool-outcome.d.ts +1 -1
  260. package/dist/loop/tool-output.d.ts +4 -4
  261. package/dist/loop/tool-output.js +2 -2
  262. package/dist/loop/turn-credentials.d.ts +34 -0
  263. package/dist/loop/turn-credentials.js +73 -0
  264. package/dist/loop/types.d.ts +34 -37
  265. package/dist/loop/types.js +2 -7
  266. package/dist/memory/ai-sdk-message-storage.d.ts +5 -5
  267. package/dist/memory/ai-sdk-message-storage.js +13 -11
  268. package/dist/memory/card-builders.d.ts +14 -14
  269. package/dist/memory/card-builders.js +19 -15
  270. package/dist/memory/conversation-display-recorder.d.ts +22 -6
  271. package/dist/memory/conversation-display-recorder.js +64 -20
  272. package/dist/memory/conversation-display-replay.js +3 -2
  273. package/dist/memory/conversation-display-storage.d.ts +15 -7
  274. package/dist/memory/conversation-display-storage.js +141 -36
  275. package/dist/memory/conversation-view.d.ts +4 -4
  276. package/dist/memory/conversation-view.js +5 -4
  277. package/dist/memory/count-tokens.js +10 -8
  278. package/dist/memory/derive-thread-title.d.ts +0 -13
  279. package/dist/memory/derive-thread-title.js +2 -1
  280. package/dist/memory/message-backfill.d.ts +12 -5
  281. package/dist/memory/message-backfill.js +5 -3
  282. package/dist/memory/thread-history.d.ts +66 -24
  283. package/dist/memory/thread-history.js +212 -79
  284. package/dist/memory/thread-store.d.ts +26 -17
  285. package/dist/memory/thread-store.js +15 -9
  286. package/dist/memory/tool-call-integrity.d.ts +2 -2
  287. package/dist/memory/tool-call-integrity.js +4 -3
  288. package/dist/memory/working-memory.d.ts +16 -12
  289. package/dist/memory/working-memory.js +72 -61
  290. package/dist/prompts/briefing.d.ts +63 -9
  291. package/dist/prompts/briefing.js +130 -3
  292. package/dist/prompts/planner.js +13 -2
  293. package/dist/prompts/synthesis-agent.d.ts +1 -1
  294. package/dist/prompts/synthesis-agent.js +6 -14
  295. package/dist/provenance/collector.d.ts +6 -6
  296. package/dist/provenance/collector.js +15 -8
  297. package/dist/provenance/exec-frame.d.ts +2 -2
  298. package/dist/provenance/exec-frame.js +6 -1
  299. package/dist/provenance/seam.d.ts +24 -19
  300. package/dist/provenance/seam.js +7 -5
  301. package/dist/provenance/types.d.ts +6 -6
  302. package/dist/providers/ai-sdk.d.ts +113 -62
  303. package/dist/providers/ai-sdk.js +303 -458
  304. package/dist/providers/embedding.d.ts +2 -2
  305. package/dist/providers/embedding.js +1 -1
  306. package/dist/providers/errors.d.ts +22 -2
  307. package/dist/providers/errors.js +98 -50
  308. package/dist/providers/prompt-cache.d.ts +8 -8
  309. package/dist/providers/prompt-cache.js +13 -11
  310. package/dist/providers/reasoning.d.ts +2 -2
  311. package/dist/providers/reasoning.js +2 -2
  312. package/dist/providers/types.d.ts +59 -92
  313. package/dist/reference-data/catalog.d.ts +2 -15
  314. package/dist/reference-data/catalog.js +166 -10
  315. package/dist/reference-data/receipt.d.ts +2 -2
  316. package/dist/report-model/assert-rules.js +1 -1
  317. package/dist/report-model/authoring-grammar.d.ts +209 -231
  318. package/dist/report-model/block-walk.d.ts +10 -10
  319. package/dist/report-model/block-walk.js +2 -0
  320. package/dist/report-model/draft-finish.d.ts +8 -8
  321. package/dist/report-model/draft-finish.js +1 -1
  322. package/dist/report-model/draft-hash.js +8 -7
  323. package/dist/report-model/draft-operations.d.ts +22 -10
  324. package/dist/report-model/draft-operations.js +48 -30
  325. package/dist/report-model/draft-read.d.ts +19 -7
  326. package/dist/report-model/draft-read.js +16 -6
  327. package/dist/report-model/draft.d.ts +844 -2
  328. package/dist/report-model/draft.js +3 -1
  329. package/dist/report-model/fixture-resolver.js +39 -16
  330. package/dist/report-model/pin-snapshot.d.ts +2 -2
  331. package/dist/report-model/pin-snapshot.js +15 -15
  332. package/dist/report-model/production-resolver.d.ts +18 -18
  333. package/dist/report-model/production-resolver.js +50 -42
  334. package/dist/report-model/reference-resolver.d.ts +26 -10
  335. package/dist/report-model/reference-resolver.js +68 -5
  336. package/dist/report-model/reference-stamp.js +30 -38
  337. package/dist/report-model/structural-validation.js +12 -4
  338. package/dist/report-model/validate.d.ts +7 -7
  339. package/dist/report-model/validate.js +6 -6
  340. package/dist/report-render/assets.d.ts +2 -2
  341. package/dist/report-render/assets.js +27 -3
  342. package/dist/report-render/chart-export.d.ts +10 -2
  343. package/dist/report-render/chart-export.js +37 -11
  344. package/dist/report-render/chart-presets.d.ts +8 -8
  345. package/dist/report-render/chart-presets.js +3 -3
  346. package/dist/report-render/chart-renderers.d.ts +23 -16
  347. package/dist/report-render/chart-renderers.js +74 -53
  348. package/dist/report-render/chart-toolbox.d.ts +2 -2
  349. package/dist/report-render/chart-toolbox.js +7 -6
  350. package/dist/report-render/chart.d.ts +15 -16
  351. package/dist/report-render/chart.js +369 -252
  352. package/dist/report-render/design.d.ts +36 -297
  353. package/dist/report-render/design.js +0 -12
  354. package/dist/report-render/figures/common.d.ts +12 -12
  355. package/dist/report-render/figures/common.js +42 -31
  356. package/dist/report-render/figures/dendrogram.d.ts +3 -3
  357. package/dist/report-render/figures/dendrogram.js +10 -10
  358. package/dist/report-render/figures/dense.js +15 -8
  359. package/dist/report-render/figures/dotplot.js +46 -33
  360. package/dist/report-render/figures/embedding.js +52 -43
  361. package/dist/report-render/figures/equal-units.d.ts +10 -10
  362. package/dist/report-render/figures/equal-units.js +27 -27
  363. package/dist/report-render/figures/forest.js +9 -7
  364. package/dist/report-render/figures/gsea.js +21 -11
  365. package/dist/report-render/figures/heatmap.js +13 -9
  366. package/dist/report-render/figures/index.d.ts +10 -10
  367. package/dist/report-render/figures/index.js +4 -2
  368. package/dist/report-render/figures/km.js +10 -9
  369. package/dist/report-render/figures/label-room.d.ts +12 -12
  370. package/dist/report-render/figures/label-room.js +7 -2
  371. package/dist/report-render/figures/locuszoom.d.ts +2 -2
  372. package/dist/report-render/figures/locuszoom.js +59 -31
  373. package/dist/report-render/figures/lollipop.js +3 -2
  374. package/dist/report-render/figures/ma.js +8 -4
  375. package/dist/report-render/figures/manhattan.d.ts +1 -2
  376. package/dist/report-render/figures/manhattan.js +52 -34
  377. package/dist/report-render/figures/oncoprint.js +4 -5
  378. package/dist/report-render/figures/pca.js +25 -11
  379. package/dist/report-render/figures/qq.js +20 -9
  380. package/dist/report-render/figures/roc.js +1 -1
  381. package/dist/report-render/figures/sankey.d.ts +2 -2
  382. package/dist/report-render/figures/sankey.js +11 -10
  383. package/dist/report-render/figures/upset.d.ts +6 -6
  384. package/dist/report-render/figures/upset.js +7 -4
  385. package/dist/report-render/figures/volcano.js +12 -10
  386. package/dist/report-render/hybrid-svg.d.ts +4 -4
  387. package/dist/report-render/hybrid-svg.js +7 -5
  388. package/dist/report-render/number-format.d.ts +4 -4
  389. package/dist/report-render/number-format.js +62 -27
  390. package/dist/report-render/page.js +2 -1
  391. package/dist/report-render/provenance-data.d.ts +2 -2
  392. package/dist/report-render/references.d.ts +4 -4
  393. package/dist/report-render/render.d.ts +2 -2
  394. package/dist/report-render/render.js +10 -11
  395. package/dist/report-render/script-json.js +1 -1
  396. package/dist/report-render/table-data.d.ts +6 -6
  397. package/dist/report-render/test/options.d.ts +49 -0
  398. package/dist/report-render/test/options.js +143 -0
  399. package/dist/report-render/test/page-function.d.ts +19 -0
  400. package/dist/report-render/test/page-function.js +33 -0
  401. package/dist/report-render/types.d.ts +10 -10
  402. package/dist/report-render/value-bridge.d.ts +4 -4
  403. package/dist/report-render/value-bridge.js +27 -14
  404. package/dist/report-render/views/chart-view.d.ts +2 -2
  405. package/dist/report-render/views/chart-view.js +2 -2
  406. package/dist/report-render/views/lineage.d.ts +6 -6
  407. package/dist/report-render/views/lineage.js +2 -0
  408. package/dist/report-render/views/page-view.d.ts +2 -2
  409. package/dist/report-render/views/page-view.js +1 -0
  410. package/dist/report-render/views/prose.js +25 -8
  411. package/dist/report-render/views/references-view.js +12 -1
  412. package/dist/report-render/views/values.js +1 -1
  413. package/dist/runtime/assemble.d.ts +53 -26
  414. package/dist/runtime/assemble.js +103 -56
  415. package/dist/runtime/boot.d.ts +8 -7
  416. package/dist/runtime/boot.js +1 -1
  417. package/dist/runtime/connection-budget.d.ts +6 -6
  418. package/dist/runtime/connection-budget.js +1 -1
  419. package/dist/runtime/dbos.d.ts +29 -19
  420. package/dist/runtime/dbos.js +35 -20
  421. package/dist/runtime/result-serialization.js +18 -5
  422. package/dist/runtime/shutdown.d.ts +2 -2
  423. package/dist/sandbox/client.d.ts +7 -3
  424. package/dist/sandbox/cpu-files.d.ts +2 -2
  425. package/dist/sandbox/cpu-files.js +21 -4
  426. package/dist/sandbox/create-sandbox.d.ts +7 -8
  427. package/dist/sandbox/create-sandbox.js +6 -12
  428. package/dist/sandbox/docker-client.d.ts +48 -3
  429. package/dist/sandbox/docker-client.js +10 -6
  430. package/dist/sandbox/estimate-data-profile-resources.js +2 -7
  431. package/dist/sandbox/exec-outcome.d.ts +2 -2
  432. package/dist/sandbox/exec-outcome.js +1 -1
  433. package/dist/sandbox/exec.d.ts +10 -6
  434. package/dist/sandbox/exec.js +27 -12
  435. package/dist/sandbox/execution-id.js +14 -6
  436. package/dist/sandbox/farm.d.ts +2 -2
  437. package/dist/sandbox/farm.js +22 -27
  438. package/dist/sandbox/identity.d.ts +7 -0
  439. package/dist/sandbox/identity.js +14 -3
  440. package/dist/sandbox/image-packages.d.ts +26 -4
  441. package/dist/sandbox/image-packages.js +29 -27
  442. package/dist/sandbox/k8s-client.d.ts +35 -8
  443. package/dist/sandbox/k8s-client.js +6 -5
  444. package/dist/sandbox/labels.js +1 -0
  445. package/dist/sandbox/liveness.js +3 -1
  446. package/dist/sandbox/mount-plan.d.ts +10 -10
  447. package/dist/sandbox/mount-plan.js +13 -14
  448. package/dist/sandbox/notification-sweep.d.ts +4 -4
  449. package/dist/sandbox/notification-sweep.js +4 -7
  450. package/dist/sandbox/package-identity.d.ts +6 -13
  451. package/dist/sandbox/package-identity.js +46 -28
  452. package/dist/sandbox/reaper.d.ts +10 -10
  453. package/dist/sandbox/reaper.js +4 -6
  454. package/dist/sandbox/sandbox-error.d.ts +2 -9
  455. package/dist/sandbox/sandbox-error.js +21 -8
  456. package/dist/sandbox/sandbox-step-translate.d.ts +8 -5
  457. package/dist/sandbox/sandbox-step-translate.js +22 -8
  458. package/dist/sandbox/step-sandbox.d.ts +47 -0
  459. package/dist/sandbox/step-sandbox.js +53 -0
  460. package/dist/sandbox/types.d.ts +18 -19
  461. package/dist/sandbox/types.js +1 -1
  462. package/dist/schemas/artifact-manifest.d.ts +4 -4
  463. package/dist/schemas/data-profile-schemas.d.ts +351 -306
  464. package/dist/schemas/file-metadata.js +2 -4
  465. package/dist/schemas/plan-schemas.d.ts +79 -25
  466. package/dist/schemas/plan-schemas.js +1 -1
  467. package/dist/schemas/run-synthesis.d.ts +95 -26
  468. package/dist/schemas/run-synthesis.js +3 -1
  469. package/dist/schemas/validate-plan.d.ts +4 -4
  470. package/dist/schemas/validate-plan.js +17 -5
  471. package/dist/schemas/workflow-state.d.ts +127 -14
  472. package/dist/schemas/workflow-state.js +56 -2
  473. package/dist/state/active-turns.d.ts +36 -0
  474. package/dist/state/active-turns.js +67 -0
  475. package/dist/state/analyses-metrics.d.ts +8 -8
  476. package/dist/state/analyses-metrics.js +4 -4
  477. package/dist/state/analyses.d.ts +0 -14
  478. package/dist/state/analyses.js +0 -32
  479. package/dist/state/artifacts.d.ts +47 -18
  480. package/dist/state/artifacts.js +48 -7
  481. package/dist/state/data-profile.d.ts +2 -2
  482. package/dist/state/db.d.ts +12 -2
  483. package/dist/state/db.js +5 -0
  484. package/dist/state/edit-intents.d.ts +4 -0
  485. package/dist/state/edit-intents.js +71 -0
  486. package/dist/state/index.d.ts +5 -5
  487. package/dist/state/index.js +3 -3
  488. package/dist/state/init.d.ts +2 -1
  489. package/dist/state/init.js +5 -2
  490. package/dist/state/migrations/20260927120000_baseline.js +3 -1
  491. package/dist/state/migrations/20261026120000_add_the_edit_intents.d.ts +7 -0
  492. package/dist/state/migrations/20261026120000_add_the_edit_intents.js +21 -0
  493. package/dist/state/migrations/20261027120000_record_the_applied_memory_edits.d.ts +7 -0
  494. package/dist/state/migrations/20261027120000_record_the_applied_memory_edits.js +16 -0
  495. package/dist/state/migrations/20261027120100_store_the_authoring_results.d.ts +8 -0
  496. package/dist/state/migrations/20261027120100_store_the_authoring_results.js +20 -0
  497. package/dist/state/migrations/20261027120200_key_the_groups_of_a_turn.d.ts +7 -0
  498. package/dist/state/migrations/20261027120200_key_the_groups_of_a_turn.js +12 -0
  499. package/dist/state/migrations/20261027120300_mark_the_active_turn_of_a_thread.d.ts +7 -0
  500. package/dist/state/migrations/20261027120300_mark_the_active_turn_of_a_thread.js +11 -0
  501. package/dist/state/migrations/20261028120000_record_the_paused_work.d.ts +7 -0
  502. package/dist/state/migrations/20261028120000_record_the_paused_work.js +25 -0
  503. package/dist/state/migrations/20261028120100_end_the_suspended_runs.d.ts +8 -0
  504. package/dist/state/migrations/20261028120100_end_the_suspended_runs.js +13 -0
  505. package/dist/state/migrations/20261029120000_reference_the_run_mandate.d.ts +7 -0
  506. package/dist/state/migrations/20261029120000_reference_the_run_mandate.js +23 -0
  507. package/dist/state/migrations/20261029120100_record_the_run_session_of_a_pause.d.ts +7 -0
  508. package/dist/state/migrations/20261029120100_record_the_run_session_of_a_pause.js +11 -0
  509. package/dist/state/migrations/index.js +18 -0
  510. package/dist/state/paused-work.d.ts +52 -0
  511. package/dist/state/paused-work.js +105 -0
  512. package/dist/state/plans.d.ts +27 -8
  513. package/dist/state/plans.js +14 -11
  514. package/dist/state/purge-analysis.d.ts +6 -6
  515. package/dist/state/purge-analysis.js +10 -2
  516. package/dist/state/report-session-state.d.ts +43 -18
  517. package/dist/state/report-session-state.js +43 -4
  518. package/dist/state/report-versions.d.ts +16 -11
  519. package/dist/state/report-versions.js +5 -3
  520. package/dist/state/runs.d.ts +70 -25
  521. package/dist/state/runs.js +127 -64
  522. package/dist/state/schema.d.ts +18 -21
  523. package/dist/state/schema.js +4 -5
  524. package/dist/state/snapshot-parse.d.ts +2 -2
  525. package/dist/state/snapshot-parse.js +14 -8
  526. package/dist/state/step-executions.d.ts +29 -8
  527. package/dist/state/step-executions.js +28 -4
  528. package/dist/state/tool-outputs.d.ts +2 -2
  529. package/dist/state/tool-outputs.js +2 -1
  530. package/dist/state/vector-store.d.ts +16 -16
  531. package/dist/state/vector-store.js +11 -7
  532. package/dist/tasks/data-profile-absorb.d.ts +3 -3
  533. package/dist/tasks/data-profile-absorb.js +21 -16
  534. package/dist/tasks/data-profile-activity.d.ts +5 -5
  535. package/dist/tasks/data-profile-activity.js +5 -5
  536. package/dist/tasks/data-profile-index.d.ts +4 -4
  537. package/dist/tasks/data-profile-index.js +32 -17
  538. package/dist/tasks/data-profile-resolve.d.ts +8 -8
  539. package/dist/tasks/data-profile-resolve.js +88 -62
  540. package/dist/tasks/data-profile.d.ts +40 -31
  541. package/dist/tasks/data-profile.js +138 -95
  542. package/dist/tasks/extract-values.d.ts +26 -79
  543. package/dist/tasks/extract-values.js +48 -108
  544. package/dist/tasks/refresh-regulatory-corpus.d.ts +4 -20
  545. package/dist/tasks/refresh-regulatory-corpus.js +12 -8
  546. package/dist/tasks/regulatory-corpus-boot-refresh.d.ts +2 -2
  547. package/dist/tasks/regulatory-corpus-boot-refresh.js +12 -10
  548. package/dist/testing.d.ts +60 -0
  549. package/dist/testing.js +96 -0
  550. package/dist/tools/ad-hoc-router.d.ts +11 -9
  551. package/dist/tools/ad-hoc-router.js +80 -51
  552. package/dist/tools/analysis-invocation.d.ts +7 -0
  553. package/dist/tools/analysis-invocation.js +29 -5
  554. package/dist/tools/approval/contract.d.ts +8 -52
  555. package/dist/tools/approval/contract.js +7 -36
  556. package/dist/tools/approval/gateway.d.ts +27 -28
  557. package/dist/tools/approval/gateway.js +33 -130
  558. package/dist/tools/approval/queries.d.ts +6 -11
  559. package/dist/tools/approval/queries.js +43 -29
  560. package/dist/tools/approval/uuidv7.js +2 -2
  561. package/dist/tools/bio/chembl.d.ts +3 -3
  562. package/dist/tools/bio/chembl.js +10 -0
  563. package/dist/tools/bio/comptox.d.ts +25 -8
  564. package/dist/tools/bio/comptox.js +4 -2
  565. package/dist/tools/bio/drug-gene-interactions.d.ts +27 -17
  566. package/dist/tools/bio/drug-gene-interactions.js +11 -8
  567. package/dist/tools/bio/gene-disease-evidence.d.ts +61 -15
  568. package/dist/tools/bio/gene-disease-evidence.js +10 -6
  569. package/dist/tools/bio/gene-preclinical-profile.d.ts +11 -11
  570. package/dist/tools/bio/keys.d.ts +2 -2
  571. package/dist/tools/bio/keys.js +3 -3
  572. package/dist/tools/bio/lookup-annotation.d.ts +5 -5
  573. package/dist/tools/bio/lookup-annotation.js +3 -0
  574. package/dist/tools/bio/opentargets.d.ts +1 -1
  575. package/dist/tools/bio/opentargets.js +6 -0
  576. package/dist/tools/bio/pubchem.d.ts +2 -2
  577. package/dist/tools/bio/pubchem.js +6 -0
  578. package/dist/tools/bio/pubmed.d.ts +26 -16
  579. package/dist/tools/bio/pubmed.js +9 -3
  580. package/dist/tools/bio/search-clinical-trials.d.ts +4 -4
  581. package/dist/tools/bio/search-clinical-trials.js +5 -1
  582. package/dist/tools/bio/search-faers.d.ts +2 -2
  583. package/dist/tools/bio/search-faers.js +1 -1
  584. package/dist/tools/bio/search-gene.d.ts +2 -2
  585. package/dist/tools/bio/search-gene.js +1 -0
  586. package/dist/tools/bio/search-geo-datasets.d.ts +4 -4
  587. package/dist/tools/bio/search-geo-datasets.js +5 -5
  588. package/dist/tools/bio/search-interactions.d.ts +1 -1
  589. package/dist/tools/bio/search-patents.d.ts +28 -22
  590. package/dist/tools/bio/search-patents.js +20 -17
  591. package/dist/tools/bio/search-protein.d.ts +2 -2
  592. package/dist/tools/bio/search-protein.js +1 -1
  593. package/dist/tools/bio/search-regulatory-approvals.d.ts +64 -18
  594. package/dist/tools/bio/search-regulatory-approvals.js +21 -16
  595. package/dist/tools/bio/target-safety.d.ts +8 -8
  596. package/dist/tools/bio/target-safety.js +11 -6
  597. package/dist/tools/capability-data.d.ts +40 -0
  598. package/dist/tools/capability-data.js +74 -0
  599. package/dist/tools/define-tool.d.ts +55 -46
  600. package/dist/tools/define-tool.js +39 -27
  601. package/dist/tools/display/normalize-echart-spec.d.ts +2 -2
  602. package/dist/tools/display/normalize-echart-spec.js +51 -27
  603. package/dist/tools/display/show-user.d.ts +2 -2
  604. package/dist/tools/display/show-user.js +1 -1
  605. package/dist/tools/execute-analysis.d.ts +54 -17
  606. package/dist/tools/execute-analysis.js +193 -62
  607. package/dist/tools/knowledge/check.d.ts +182 -0
  608. package/dist/tools/knowledge/check.js +94 -0
  609. package/dist/tools/knowledge/client.d.ts +351 -0
  610. package/dist/tools/knowledge/client.js +319 -0
  611. package/dist/tools/knowledge/environment.d.ts +78 -0
  612. package/dist/tools/knowledge/environment.js +116 -0
  613. package/dist/tools/knowledge/index.d.ts +49 -0
  614. package/dist/tools/knowledge/index.js +70 -0
  615. package/dist/tools/knowledge/local-slots.d.ts +62 -0
  616. package/dist/tools/knowledge/local-slots.js +184 -0
  617. package/dist/tools/knowledge/pin.d.ts +14 -0
  618. package/dist/tools/knowledge/pin.js +17 -0
  619. package/dist/tools/knowledge/recommend.d.ts +67 -0
  620. package/dist/tools/knowledge/recommend.js +106 -0
  621. package/dist/tools/knowledge/situation.d.ts +143 -0
  622. package/dist/tools/knowledge/situation.js +157 -0
  623. package/dist/tools/knowledge/skeleton.d.ts +69 -0
  624. package/dist/tools/knowledge/skeleton.js +201 -0
  625. package/dist/tools/knowledge/template.d.ts +139 -0
  626. package/dist/tools/knowledge/template.js +273 -0
  627. package/dist/tools/lib/alphafold-client.js +2 -1
  628. package/dist/tools/lib/amass-client.d.ts +28 -28
  629. package/dist/tools/lib/amass-client.js +20 -10
  630. package/dist/tools/lib/api-utils.d.ts +13 -3
  631. package/dist/tools/lib/api-utils.js +17 -3
  632. package/dist/tools/lib/bgee-client.d.ts +6 -6
  633. package/dist/tools/lib/bgee-client.js +16 -10
  634. package/dist/tools/lib/cbioportal-client.d.ts +4 -4
  635. package/dist/tools/lib/cbioportal-client.js +9 -8
  636. package/dist/tools/lib/chembl-client.d.ts +14 -14
  637. package/dist/tools/lib/chembl-client.js +11 -4
  638. package/dist/tools/lib/clinical-benchmarks-client.d.ts +4 -4
  639. package/dist/tools/lib/clinical-benchmarks-client.js +4 -7
  640. package/dist/tools/lib/clinical-trials-client.d.ts +18 -18
  641. package/dist/tools/lib/clinical-trials-client.js +10 -10
  642. package/dist/tools/lib/clinvar-client.d.ts +2 -2
  643. package/dist/tools/lib/clinvar-client.js +6 -6
  644. package/dist/tools/lib/ctx-ops.d.ts +23 -23
  645. package/dist/tools/lib/ctx-ops.js +13 -10
  646. package/dist/tools/lib/dgidb-client.d.ts +6 -6
  647. package/dist/tools/lib/dgidb-client.js +10 -12
  648. package/dist/tools/lib/disgenet-client.d.ts +4 -4
  649. package/dist/tools/lib/ema-client.d.ts +2 -2
  650. package/dist/tools/lib/ensembl-client.d.ts +4 -4
  651. package/dist/tools/lib/ensembl-client.js +5 -4
  652. package/dist/tools/lib/gwas-catalog-client.d.ts +4 -4
  653. package/dist/tools/lib/gwas-catalog-client.js +17 -17
  654. package/dist/tools/lib/html-text.d.ts +6 -0
  655. package/dist/tools/lib/html-text.js +9 -0
  656. package/dist/tools/lib/identifier-resolver.d.ts +4 -4
  657. package/dist/tools/lib/identifier-resolver.js +7 -3
  658. package/dist/tools/lib/impc-client.d.ts +8 -8
  659. package/dist/tools/lib/impc-client.js +46 -35
  660. package/dist/tools/lib/iuphar-client.d.ts +2 -2
  661. package/dist/tools/lib/iuphar-client.js +7 -16
  662. package/dist/tools/lib/monarch-client.d.ts +4 -4
  663. package/dist/tools/lib/openfda-client.d.ts +22 -22
  664. package/dist/tools/lib/openfda-client.js +23 -22
  665. package/dist/tools/lib/opentargets-client.d.ts +12 -12
  666. package/dist/tools/lib/pathway-client.d.ts +4 -4
  667. package/dist/tools/lib/pathway-client.js +15 -19
  668. package/dist/tools/lib/pharmgkb-client.d.ts +2 -2
  669. package/dist/tools/lib/pharmgkb-client.js +1 -1
  670. package/dist/tools/lib/protein-family-modality.d.ts +2 -2
  671. package/dist/tools/lib/protein-family-modality.js +0 -2
  672. package/dist/tools/lib/protein-family-normalize.js +7 -0
  673. package/dist/tools/lib/pubchem-client.d.ts +2 -2
  674. package/dist/tools/lib/pubchem-client.js +1 -0
  675. package/dist/tools/lib/pubchem-ops.d.ts +4 -4
  676. package/dist/tools/lib/pubchem-ops.js +8 -0
  677. package/dist/tools/lib/pubmed-client.d.ts +9 -9
  678. package/dist/tools/lib/pubmed-client.js +1 -1
  679. package/dist/tools/lib/string-client.d.ts +6 -6
  680. package/dist/tools/lib/uniprot-client.d.ts +8 -8
  681. package/dist/tools/lib/uniprot-client.js +5 -1
  682. package/dist/tools/memory/update-working-memory.d.ts +16 -13
  683. package/dist/tools/memory/update-working-memory.js +21 -3
  684. package/dist/tools/read-tool-output.js +8 -2
  685. package/dist/tools/registry.d.ts +2 -2
  686. package/dist/tools/report-authoring/authoring-tools.d.ts +54 -23
  687. package/dist/tools/report-authoring/authoring-tools.js +128 -62
  688. package/dist/tools/report-session/derive-table.d.ts +19 -59
  689. package/dist/tools/report-session/derive-table.js +120 -122
  690. package/dist/tools/report-session/examine-page.d.ts +6 -6
  691. package/dist/tools/report-session/examine-page.js +14 -12
  692. package/dist/tools/report-session/list-artifacts.d.ts +6 -6
  693. package/dist/tools/report-session/list-artifacts.js +5 -5
  694. package/dist/tools/report-session/page-faults.d.ts +6 -6
  695. package/dist/tools/report-session/page-faults.js +3 -1
  696. package/dist/tools/report-session/preview-report.d.ts +4 -3
  697. package/dist/tools/report-session/preview-report.js +26 -7
  698. package/dist/tools/report-session/record-version.d.ts +9 -4
  699. package/dist/tools/report-session/record-version.js +16 -9
  700. package/dist/tools/report-session/session-page-publisher.d.ts +6 -6
  701. package/dist/tools/research/generate-analogy-report.d.ts +14 -7
  702. package/dist/tools/research/generate-analogy-report.js +80 -76
  703. package/dist/tools/research/generate-plan.d.ts +39 -16
  704. package/dist/tools/research/generate-plan.js +565 -338
  705. package/dist/tools/research/guarded-address.d.ts +20 -0
  706. package/dist/tools/research/guarded-address.js +149 -0
  707. package/dist/tools/research/inspect-data-profile.d.ts +27 -20
  708. package/dist/tools/research/inspect-data-profile.js +26 -25
  709. package/dist/tools/research/inspect-run.d.ts +54 -27
  710. package/dist/tools/research/inspect-run.js +50 -40
  711. package/dist/tools/research/literature-reviewer.d.ts +8 -7
  712. package/dist/tools/research/literature-reviewer.js +29 -28
  713. package/dist/tools/research/search-arxiv.d.ts +1 -1
  714. package/dist/tools/research/search-arxiv.js +1 -1
  715. package/dist/tools/research/search-github-repos.d.ts +10 -7
  716. package/dist/tools/research/search-github-repos.js +25 -22
  717. package/dist/tools/research/search-semantic-scholar.js +1 -1
  718. package/dist/tools/research/searxng-engine.d.ts +40 -0
  719. package/dist/tools/research/searxng-engine.js +122 -0
  720. package/dist/tools/research/web-fetch.d.ts +127 -0
  721. package/dist/tools/research/web-fetch.js +618 -0
  722. package/dist/tools/research/web-search.d.ts +84 -0
  723. package/dist/tools/research/web-search.js +117 -0
  724. package/dist/tools/sandbox/link-packages.d.ts +11 -7
  725. package/dist/tools/sandbox/link-packages.js +11 -8
  726. package/dist/tools/sandbox/list-available-packages.d.ts +24 -12
  727. package/dist/tools/sandbox/list-available-packages.js +43 -29
  728. package/dist/tools/sandbox/list-available-refs.d.ts +38 -14
  729. package/dist/tools/sandbox/list-available-refs.js +119 -37
  730. package/dist/tools/sandbox/report-blocker.d.ts +30 -37
  731. package/dist/tools/sandbox/report-blocker.js +22 -68
  732. package/dist/tools/sandbox/skills.d.ts +16 -12
  733. package/dist/tools/sandbox/skills.js +16 -12
  734. package/dist/tools/sandbox/submit-file-metadata.d.ts +12 -9
  735. package/dist/tools/sandbox/submit-file-metadata.js +18 -21
  736. package/dist/tools/start-report-session.d.ts +13 -5
  737. package/dist/tools/start-report-session.js +35 -8
  738. package/dist/tools/terminal-text.d.ts +14 -0
  739. package/dist/tools/terminal-text.js +51 -0
  740. package/dist/tools/workspace/decision-record.d.ts +81 -0
  741. package/dist/tools/workspace/decision-record.js +127 -0
  742. package/dist/tools/workspace/edit-file.d.ts +59 -18
  743. package/dist/tools/workspace/edit-file.js +98 -15
  744. package/dist/tools/workspace/execute-command.d.ts +31 -12
  745. package/dist/tools/workspace/execute-command.js +37 -8
  746. package/dist/tools/workspace/file-stat.d.ts +6 -3
  747. package/dist/tools/workspace/grep.d.ts +10 -7
  748. package/dist/tools/workspace/grep.js +9 -3
  749. package/dist/tools/workspace/index.d.ts +1 -0
  750. package/dist/tools/workspace/index.js +1 -0
  751. package/dist/tools/workspace/list-files.d.ts +6 -3
  752. package/dist/tools/workspace/mutator.d.ts +28 -15
  753. package/dist/tools/workspace/mutator.js +107 -53
  754. package/dist/tools/workspace/read-file.d.ts +8 -5
  755. package/dist/tools/workspace/result-bounds.d.ts +5 -5
  756. package/dist/tools/workspace/result-bounds.js +4 -2
  757. package/dist/tools/workspace/run-exec.d.ts +2 -2
  758. package/dist/tools/workspace/run-exec.js +3 -3
  759. package/dist/tools/workspace/scan-inputs.d.ts +8 -5
  760. package/dist/tools/workspace/scan-inputs.js +17 -5
  761. package/dist/tools/workspace/show-file.d.ts +1 -1
  762. package/dist/tools/workspace/show-file.js +2 -1
  763. package/dist/tools/workspace/show-plan.d.ts +8 -5
  764. package/dist/tools/workspace/show-plan.js +9 -8
  765. package/dist/tools/workspace/workspace-search.d.ts +41 -13
  766. package/dist/tools/workspace/workspace-search.js +27 -14
  767. package/dist/tools/workspace/write-file.d.ts +9 -7
  768. package/dist/workflows/execute-analysis-scheduler.d.ts +9 -9
  769. package/dist/workflows/execute-analysis-scheduler.js +6 -3
  770. package/dist/workflows/execute-analysis.d.ts +100 -76
  771. package/dist/workflows/execute-analysis.js +380 -247
  772. package/dist/workflows/pause.d.ts +71 -0
  773. package/dist/workflows/pause.js +173 -0
  774. package/dist/workflows/sandbox-step.d.ts +50 -61
  775. package/dist/workflows/sandbox-step.js +99 -106
  776. package/dist/workflows/test/sql-writes.d.ts +21 -0
  777. package/dist/workflows/test/sql-writes.js +36 -0
  778. package/dist/workspace/filesystem.d.ts +6 -6
  779. package/dist/workspace/filesystem.js +10 -8
  780. package/dist/workspace/paths.d.ts +1 -1
  781. package/dist/workspace/paths.js +15 -4
  782. package/dist/workspace/search-config.d.ts +2 -2
  783. package/dist/workspace/search-config.js +1 -1
  784. package/package.json +25 -22
  785. package/dist/loop/continue-agent.d.ts +0 -40
  786. package/dist/loop/continue-agent.js +0 -38
  787. package/dist/loop/genai-spans.d.ts +0 -47
  788. package/dist/loop/genai-spans.js +0 -134
  789. package/dist/loop/run-agent.d.ts +0 -236
  790. package/dist/loop/run-agent.js +0 -1110
  791. package/dist/loop/run-step.d.ts +0 -29
  792. package/dist/loop/run-step.js +0 -34
  793. package/dist/loop/run-to-terminal.d.ts +0 -66
  794. package/dist/loop/run-to-terminal.js +0 -90
  795. package/dist/loop/tool-mask.d.ts +0 -23
  796. package/dist/loop/tool-mask.js +0 -46
  797. package/dist/providers/streaming-chat.d.ts +0 -32
  798. package/dist/providers/streaming-chat.js +0 -91
  799. package/dist/tasks/derive-table-exec.d.ts +0 -54
  800. package/dist/tasks/derive-table-exec.js +0 -86
  801. package/dist/workflows/suspension.d.ts +0 -32
  802. package/dist/workflows/suspension.js +0 -38
@@ -1,5 +1,7 @@
1
- import { createHash } from "node:crypto";
2
- import { streamText, wrapLanguageModel, } from "ai";
1
+ import { errorOf, errorNameOf } from "../lib/thrown.js";
2
+ import { textOf } from "../lib/unknown-text.js";
3
+ import { createHash, randomUUID } from "node:crypto";
4
+ import { wrapLanguageModel } from "ai";
3
5
  import { createAnthropic } from "@ai-sdk/anthropic";
4
6
  // Any `providerOptions.anthropic.thinking` bypasses this table's thinking
5
7
  // selection (see `thinkingWithBinding`).
@@ -10,11 +12,12 @@ import { OpenTelemetry } from "@ai-sdk/otel";
10
12
  import { APICallError } from "@ai-sdk/provider";
11
13
  import { retryWithExponentialBackoff } from "@ai-sdk/provider-utils";
12
14
  import { trace } from "@opentelemetry/api";
13
- import { ResultAsync, err, ok } from "neverthrow";
14
15
  import { scopeWorkloadId } from "../auth/types.js";
15
16
  import { createNoopLogger } from "../lib/console-logger.js";
16
- import { passThroughTracer } from "../lib/otel-spans.js";
17
- import { DEFAULT_SUSPEND_ON, classifyProviderError, RequestTimeoutError, toProviderError } from "./errors.js";
17
+ import { ResultError } from "../lib/result.js";
18
+ import { isUnknownArray } from "../lib/unknown-array.js";
19
+ import { parseUnknownRecord } from "../lib/unknown-containers.js";
20
+ import { DEFAULT_SUSPEND_ON, classifyProviderError, extractStatus, RequestTimeoutError, toProviderError, } from "./errors.js";
18
21
  import { DEFAULT_REASONING } from "./reasoning.js";
19
22
  import { headersRefusalError, requestHeadersFor } from "./request-headers.js";
20
23
  /**
@@ -55,14 +58,15 @@ export const DEFAULT_MAX_OUTPUT_TOKENS = 64_000;
55
58
  * provider over a boot shares one sink.
56
59
  */
57
60
  function routeSdkWarningsTo(logger) {
58
- const g = globalThis;
59
- if (g.AI_SDK_LOG_WARNINGS !== undefined)
61
+ // The SDK names a global that no declaration of `globalThis` describes, so the install reads and
62
+ // writes the key reflectively.
63
+ if (Reflect.get(globalThis, "AI_SDK_LOG_WARNINGS") !== undefined)
60
64
  return;
61
- g.AI_SDK_LOG_WARNINGS = (options) => {
65
+ Reflect.set(globalThis, "AI_SDK_LOG_WARNINGS", (options) => {
62
66
  for (const warning of options.warnings) {
63
67
  logger.warn("ai sdk warning", { provider: options.provider, model: options.model, warning });
64
68
  }
65
- };
69
+ });
66
70
  }
67
71
  function workloadOf(session) {
68
72
  return `${session.scope.kind}:${scopeWorkloadId(session.scope)}`;
@@ -97,26 +101,60 @@ function thinkingWithBinding(reasoning, mode) {
97
101
  return { blockBinding };
98
102
  return { type: "adaptive", display: "summarized", blockBinding };
99
103
  }
104
+ /**
105
+ * The model that answered after a server-side fallback hop, `""` when the hop is
106
+ * reported without one, and `undefined` when no hop happened.
107
+ *
108
+ * A model can refuse a request by category — a biology prompt is one such category —
109
+ * and the API then re-serves it on another model. It reports the hop TWICE: as a
110
+ * `fallback` content block inside the assistant turn, and on
111
+ * `providerMetadata.anthropic.iterations`. `@ai-sdk/anthropic` keeps only the second,
112
+ * because the AI SDK has no part for a model hop, and it drops the block from the
113
+ * content it returns (`anthropic-messages-language-model`, the `content_block_start`
114
+ * case). Thus the turn the harness holds is not the turn the API produced, and every
115
+ * signed thinking block of that turn is rejected from the next request on.
116
+ *
117
+ * The API holds the whole turn against the signature of each of its thinking blocks, so
118
+ * echoing that turn earns `thinking ... blocks in the latest assistant message cannot be
119
+ * modified`, which is a 400 that no retry can pass. A thinking block is optional on the
120
+ * way back, thus the loop records the reply of a hop with no thinking block, and the next
121
+ * request continues. The cost is the reasoning of this one turn and the cache write that
122
+ * its new prefix pays for.
123
+ *
124
+ * The response metadata of the package carries `message_start.message.model`, and that
125
+ * field keeps the REQUESTED model across a hop. The iteration names the model that
126
+ * answered, thus it wins for the usage record.
127
+ */
128
+ export function fallbackModelOf(metadata) {
129
+ const entries = metadata?.["anthropic"]?.["iterations"];
130
+ if (!isUnknownArray(entries))
131
+ return undefined;
132
+ for (const entry of entries) {
133
+ const record = parseUnknownRecord(entry);
134
+ if (record === undefined || !("type" in record))
135
+ continue;
136
+ if (record["type"] !== "fallback_message")
137
+ continue;
138
+ return "model" in record && typeof record["model"] === "string" ? record["model"] : "";
139
+ }
140
+ return undefined;
141
+ }
100
142
  /** Reads `providerMetadata.anthropic.inputTransformations`; empty for another vendor. */
101
143
  function inputTransformationsOf(metadata) {
102
144
  const entries = metadata?.["anthropic"]?.["inputTransformations"];
103
- if (!Array.isArray(entries))
145
+ if (!isUnknownArray(entries))
104
146
  return [];
105
147
  return entries.map((entry) => {
106
- const fields = typeof entry === "object" && entry !== null ? entry : {};
148
+ const record = parseUnknownRecord(entry);
107
149
  const text = (key) => {
108
- const value = fields[key];
150
+ const value = record?.[key];
109
151
  return typeof value === "string" ? value : undefined;
110
152
  };
111
153
  return { type: text("type"), path: text("path"), reason: text("reason") };
112
154
  });
113
155
  }
114
156
  function isAbortError(value) {
115
- if (value instanceof DOMException && value.name === "AbortError")
116
- return true;
117
- if (value instanceof Error && value.name === "AbortError")
118
- return true;
119
- return false;
157
+ return errorNameOf(value) === "AbortError";
120
158
  }
121
159
  /**
122
160
  * Locate an `APICallError` on the throwable itself or one hop down its `cause`.
@@ -127,7 +165,9 @@ function isAbortError(value) {
127
165
  function apiCallErrorOf(error) {
128
166
  if (APICallError.isInstance(error))
129
167
  return error;
130
- const cause = error?.cause;
168
+ if (error === null || typeof error !== "object" || !("cause" in error))
169
+ return undefined;
170
+ const cause = error.cause;
131
171
  if (APICallError.isInstance(cause))
132
172
  return cause;
133
173
  return undefined;
@@ -242,8 +282,9 @@ export function failureOf(e, workload, suspendOn) {
242
282
  * timeout. Without this guard the envelope would loop an expiry that the caller
243
283
  * itself declared.
244
284
  */
245
- export function createRetry(signal, logger, maxRetries, suspendOn, hookCall) {
285
+ export function createRetry(signal, logger, maxRetries, suspendOn, hookCall, onRetry) {
246
286
  let retryCount = 0;
287
+ const requestId = randomUUID();
247
288
  return retryWithExponentialBackoff({
248
289
  maxRetries,
249
290
  initialDelayInMs: RETRY_INITIAL_DELAY_MS,
@@ -254,6 +295,8 @@ export function createRetry(signal, logger, maxRetries, suspendOn, hookCall) {
254
295
  const delayMs = computeRetryDelayMs(error, exponentialBackoffDelay);
255
296
  retryCount += 1;
256
297
  logger.debug("retrying provider call", { attempt: retryCount, delayMs, ...logger.errorFields(error) });
298
+ const status = extractStatus(error);
299
+ onRetry?.({ requestId, attempt: retryCount, maxRetries, delayMs, status: status !== undefined && status >= 400 ? status : undefined });
257
300
  return delayMs;
258
301
  },
259
302
  createRetryError: ({ message, errors }) => {
@@ -275,9 +318,7 @@ export function createRetry(signal, logger, maxRetries, suspendOn, hookCall) {
275
318
  * `@ai-sdk/openai-compatible` maps `prompt_tokens_details.cached_tokens` →
276
319
  * `cacheReadTokens` (it never reports a write — that family caches
277
320
  * server-side, with no billed write step). Reading the neutral field is
278
- * therefore both correct and vendor-agnostic; the raw vendor payload remains
279
- * available under `providerMetadata.anthropic.usage` for debugging, in the
280
- * vendor's own snake_case.
321
+ * therefore both correct and vendor-agnostic.
281
322
  *
282
323
  * `inputTokens` is the total billed prefix, cache reads included.
283
324
  *
@@ -285,134 +326,24 @@ export function createRetry(signal, logger, maxRetries, suspendOn, hookCall) {
285
326
  * count and is copied verbatim: providers disagree on whether reasoning tokens
286
327
  * are already inside the output total, so the harness reconciles nothing.
287
328
  */
288
- function toChatUsage(usage) {
329
+ export function toChatUsage(usage) {
289
330
  if (usage === undefined)
290
331
  return undefined;
291
332
  return {
292
333
  inputTokens: usage.inputTokens,
293
334
  outputTokens: usage.outputTokens,
294
- cacheCreationInputTokens: usage.inputTokenDetails?.cacheWriteTokens,
295
- cacheReadInputTokens: usage.inputTokenDetails?.cacheReadTokens,
296
- reasoningTokens: usage.outputTokenDetails?.reasoningTokens,
335
+ cacheCreationInputTokens: usage.inputTokenDetails.cacheWriteTokens,
336
+ cacheReadInputTokens: usage.inputTokenDetails.cacheReadTokens,
337
+ reasoningTokens: usage.outputTokenDetails.reasoningTokens,
297
338
  };
298
339
  }
299
- /** The id of the model bound into this provider — a bare id string is its own id. */
300
- function requestedModelIdOf(model) {
301
- return typeof model === "string" ? model : model.modelId;
302
- }
303
- /** The provider id of the model bound into this provider, as the AI SDK names it — a bare id string names no provider. */
304
- function providerIdOf(model) {
305
- return typeof model === "string" ? undefined : model.provider;
306
- }
307
- /**
308
- * Capture the served model id at the raw model boundary, because that is the
309
- * only place it is still distinguishable from the requested one: `streamText`
310
- * coalesces an unreported response model id to the bound model's own id, so
311
- * reading `result.response.modelId` would silently republish the requested id
312
- * as an endpoint's claim. A middleware sees the provider's
313
- * result before that fallback applies, so "reported nothing" stays absent.
314
- *
315
- * Built per call, never per provider: one provider instance serves concurrent
316
- * calls, and a shared mutable slot would hand one call another's answer. A bare
317
- * model-id string has no wire result to observe, so it captures nothing.
318
- */
319
- function captureServedModelId(model) {
320
- if (typeof model === "string")
321
- return { model, servedModelId: () => undefined };
322
- let served;
323
- const wrapped = wrapLanguageModel({
324
- model,
325
- middleware: {
326
- wrapGenerate: async ({ doGenerate }) => {
327
- const result = await doGenerate();
328
- served = result.response?.modelId;
329
- return result;
330
- },
331
- wrapStream: async ({ doStream }) => {
332
- const result = await doStream();
333
- return {
334
- ...result,
335
- stream: result.stream.pipeThrough(new TransformStream({
336
- transform(chunk, controller) {
337
- if (chunk.type === "response-metadata" && chunk.modelId !== undefined)
338
- served = chunk.modelId;
339
- controller.enqueue(chunk);
340
- },
341
- })),
342
- };
343
- },
344
- },
345
- });
346
- return { model: wrapped, servedModelId: () => served };
347
- }
348
- function responseFromMessages(input) {
349
- const { messages, fallbackText, finishReason, rawFinishReason, requestedModelId, servedModelId, provider } = input;
350
- const usage = toChatUsage(input.usage);
351
- const message = [...messages].reverse().find((m) => m.role === "assistant");
352
- if (message === undefined) {
353
- return { message: { role: "assistant", content: fallbackText }, finishReason, rawFinishReason, usage, requestedModelId, servedModelId, provider };
354
- }
355
- return { message, finishReason, rawFinishReason, usage, requestedModelId, servedModelId, provider };
356
- }
357
- /**
358
- * Drop empty text parts — and messages left with no content at all — before
359
- * the wire call. The Anthropic Messages API rejects any request containing an
360
- * empty text block, and the SDK's own response assembly legitimately produces
361
- * them: a turn that goes straight to tool calls yields an assistant message
362
- * carrying a ""-text part, which the agent loop then echoes back as history
363
- * on its next request. Filtering once at the outbound boundary covers every
364
- * source at once — loop echo, stored thread history, legacy backfill, and the
365
- * empty-string fallback in `responseFromMessages`.
366
- */
367
- function sanitizeMessages(messages) {
368
- const out = [];
369
- for (const m of messages) {
370
- if (typeof m.content === "string") {
371
- if (m.content !== "")
372
- out.push(m);
373
- continue;
374
- }
375
- const parts = m.content.filter((p) => p.type !== "text" || p.text !== "");
376
- // The filtered parts are a subset of this message's own content, so the
377
- // message remains valid for its role — the cast only re-associates the
378
- // narrowed array with the union member TS can no longer correlate.
379
- if (parts.length > 0)
380
- out.push({ ...m, content: parts });
381
- }
382
- return out;
383
- }
384
- /**
385
- * Advance the SDK stream to the next text delta.
386
- *
387
- * The full stream carries one part for each event of a turn, and only a text
388
- * part reaches the consumer of the harness. Thus the pull skips each other part.
389
- * The `abort` part stops the pull, because the SDK closes the stream directly
390
- * after it. Thus a timeout can never end the stream in silence with the text
391
- * that arrived before it.
392
- */
393
- async function pullNextDelta(iterator) {
394
- for (let next = await iterator.next(); next.done !== true; next = await iterator.next()) {
395
- const part = next.value;
396
- if (part.type === "text-delta")
397
- return { kind: "delta", text: part.text };
398
- if (part.type === "abort")
399
- return { kind: "aborted", reason: part.reason };
400
- // The SDK reports a wire failure as a part, not as a rejection, and it
401
- // then closes the stream. Skipping it would turn a failed call into an
402
- // empty assistant turn that the loop reads as a real answer.
403
- if (part.type === "error")
404
- return { kind: "failed", error: part.error };
405
- }
406
- return { kind: "end" };
407
- }
408
340
  /**
409
341
  * The HTTP status that each Anthropic stream error type stands for.
410
342
  *
411
343
  * A provider names a mid-stream failure in the payload, not in the status line:
412
344
  * a stream that carries `overloaded_error` reports the condition that a 529
413
345
  * names on the non-streaming wire. The classifier reads the status alone, thus
414
- * the part has to reach it as an error that names one, or the same condition
415
- * would classify one way on `chat` and another way on `chatStream`.
346
+ * the part has to reach it as an error that names one.
416
347
  */
417
348
  const STREAM_ERROR_STATUS = {
418
349
  invalid_request_error: 400,
@@ -426,20 +357,20 @@ const STREAM_ERROR_STATUS = {
426
357
  overloaded_error: 529,
427
358
  };
428
359
  /**
429
- * The failure that an `error` part of the SDK stream stands for.
360
+ * The failure that an `error` part of the model stream stands for.
430
361
  *
431
362
  * The part carries whatever the provider put on the wire, and that is often a
432
363
  * bare object rather than an `Error`. Left as it is, it reaches the message as
433
364
  * `[object Object]` and reaches the classifier with no status at all.
434
365
  */
435
366
  function streamPartFailure(error) {
436
- if (error instanceof Error)
437
- return error;
367
+ const thrownError = errorOf(error);
368
+ if (thrownError !== undefined)
369
+ return thrownError;
438
370
  if (typeof error !== "object" || error === null)
439
- return new Error(String(error));
440
- const reported = error;
441
- const type = typeof reported.type === "string" ? reported.type : undefined;
442
- const message = typeof reported.message === "string" ? reported.message : undefined;
371
+ return new Error(textOf(error));
372
+ const type = "type" in error && typeof error.type === "string" ? error.type : undefined;
373
+ const message = "message" in error && typeof error.message === "string" ? error.message : undefined;
443
374
  const failure = new Error(message ?? type ?? "The provider reported a stream error.", { cause: error });
444
375
  const status = type === undefined ? undefined : STREAM_ERROR_STATUS[type];
445
376
  // `extractStatus` walks the chain for this field, thus the named condition
@@ -449,304 +380,215 @@ function streamPartFailure(error) {
449
380
  return failure;
450
381
  }
451
382
  /**
452
- * The failure that an `abort` part of the SDK stream stands for.
453
- *
454
- * The part carries a message only, thus the caller signal is the one thing that
455
- * separates a cancellation from a timeout. When the caller signal is aborted,
456
- * the reason of that signal rides out, and the cancellation path applies
457
- * unchanged. Otherwise the SDK chunk bound stopped the stream, and the sentinel
458
- * names the configured value for the classifier.
383
+ * A part that the reader of a reply can see. A retry after one would show the
384
+ * reader the start of the reply again, thus a live call retries only before the
385
+ * first one. The same parts reset the silent-interval bound: a part that carries
386
+ * no content does not prove that the model writes.
387
+ */
388
+ function isOutputPart(part) {
389
+ return part.type !== "stream-start" && part.type !== "response-metadata" && part.type !== "raw";
390
+ }
391
+ /**
392
+ * A reader of one model stream under the silent-interval bound. The bound runs
393
+ * from the start of the read, and each output part resets it. A part with no
394
+ * content leaves the bound as it was.
459
395
  */
460
- function abortedStreamFailure(signal, reason, requestTimeoutMs) {
461
- if (signal?.aborted === true)
462
- return signal.reason;
463
- if (requestTimeoutMs !== undefined)
464
- return new RequestTimeoutError(requestTimeoutMs);
465
- return new Error(reason ?? "The provider aborted the stream.");
396
+ function boundedReader(stream, timeoutMs) {
397
+ const reader = stream.getReader();
398
+ let deadline = timeoutMs === undefined ? undefined : performance.now() + timeoutMs;
399
+ return {
400
+ async read() {
401
+ if (deadline === undefined || timeoutMs === undefined) {
402
+ const next = await reader.read();
403
+ return next.done ? { done: true } : { done: false, value: next.value };
404
+ }
405
+ const remaining = Math.max(deadline - performance.now(), 0);
406
+ let timer;
407
+ const expiry = new Promise((_resolve, reject) => {
408
+ // oxlint-disable-next-line eslint-js/no-restricted-syntax -- a guard, not a wait: it rejects the read of a silent stream at the bound, unrefs so an armed guard never holds a short-lived process, and the finally clears it.
409
+ timer = setTimeout(() => reject(new RequestTimeoutError(timeoutMs)), remaining);
410
+ timer.unref();
411
+ });
412
+ try {
413
+ const next = await Promise.race([reader.read(), expiry]);
414
+ if (next.done)
415
+ return { done: true };
416
+ if (isOutputPart(next.value))
417
+ deadline = performance.now() + timeoutMs;
418
+ return { done: false, value: next.value };
419
+ }
420
+ catch (e) {
421
+ void reader.cancel(e).catch(() => undefined);
422
+ throw e;
423
+ }
424
+ finally {
425
+ clearTimeout(timer);
426
+ }
427
+ },
428
+ cancel(reason) {
429
+ void reader.cancel(reason).catch(() => undefined);
430
+ },
431
+ };
466
432
  }
467
- /** The `gen_ai.operation.name` of the operation span and of the step span that the AI SDK opens around each `chat` span. */
468
- function isSdkWrapperSpan(operation) {
469
- return operation === "invoke_agent" || operation === "agent_step";
433
+ /**
434
+ * The retry envelope of a model call, as a model middleware.
435
+ *
436
+ * Each attempt resolves the request headers of the host first: a host header can
437
+ * be time-limited, and the retry window can last minutes. A live call retries
438
+ * until its first output part, because a reader already saw each part after it.
439
+ * A call with no live reader takes the whole reply inside the attempt, thus a
440
+ * failure at any point of the stream runs the whole attempt again.
441
+ *
442
+ * After the last attempt, the failure leaves as a `ResultError` that carries the
443
+ * classified `ProviderError`. An abort and a rejection of the headers hook leave
444
+ * unchanged.
445
+ */
446
+ function retryEnvelope(options) {
447
+ const { session, live, logger, maxRetries, suspendOn, requestTimeoutMs, onRetry } = options;
448
+ const workload = workloadOf(session);
449
+ /** The one record of a call that the envelope gave up on: the reply carries the failure, and the operator sees this. */
450
+ const failed = (thrown) => {
451
+ const failure = failureOf(thrown, workload, suspendOn);
452
+ logger.error("provider call failed", { workload, kind: failure.type, retryable: failure.retryable, ...logger.errorFields(thrown) });
453
+ return new ResultError(failure);
454
+ };
455
+ const observeFinish = (part) => {
456
+ if (part.type !== "finish")
457
+ return;
458
+ for (const drop of inputTransformationsOf(part.providerMetadata)) {
459
+ logger.warn("thinking block dropped", { workload, type: drop.type, path: drop.path, reason: drop.reason });
460
+ }
461
+ const servedBy = fallbackModelOf(part.providerMetadata);
462
+ if (servedBy !== undefined) {
463
+ logger.warn("reply served by a fallback model, thus the harness drops the thinking of that turn", {
464
+ workload,
465
+ servedBy: servedBy === "" ? undefined : servedBy,
466
+ });
467
+ }
468
+ };
469
+ return {
470
+ specificationVersion: "v4",
471
+ wrapStream: async ({ params, model }) => {
472
+ const signal = params.abortSignal;
473
+ const hookCall = { unsettled: false };
474
+ const retry = createRetry(signal, logger, maxRetries, suspendOn, hookCall, onRetry);
475
+ let opened;
476
+ try {
477
+ opened = await retry(async () => {
478
+ const headers = await headersForAttempt(options.resolveRequestHeaders, session, hookCall);
479
+ const { stream, ...rest } = await model.doStream({ ...params, headers: { ...params.headers, ...headers } });
480
+ const reader = boundedReader(stream, requestTimeoutMs);
481
+ const head = [];
482
+ for (let next = await reader.read(); !next.done; next = await reader.read()) {
483
+ const part = next.value;
484
+ // The provider reports a wire failure as a part, and then it closes the stream.
485
+ if (part.type === "error") {
486
+ reader.cancel();
487
+ throw streamPartFailure(part.error);
488
+ }
489
+ head.push(part);
490
+ if (live && isOutputPart(part))
491
+ return { rest, head, tail: reader };
492
+ }
493
+ return { rest, head };
494
+ });
495
+ }
496
+ catch (e) {
497
+ if (isAbortError(e) || signal?.aborted === true || hookCall.unsettled)
498
+ throw e;
499
+ throw failed(e);
500
+ }
501
+ const { rest, head, tail } = opened;
502
+ const stream = new ReadableStream({
503
+ start(controller) {
504
+ for (const part of head) {
505
+ observeFinish(part);
506
+ controller.enqueue(part);
507
+ }
508
+ if (tail === undefined)
509
+ controller.close();
510
+ },
511
+ async pull(controller) {
512
+ if (tail === undefined)
513
+ return;
514
+ try {
515
+ const next = await tail.read();
516
+ if (next.done) {
517
+ controller.close();
518
+ return;
519
+ }
520
+ const part = next.value;
521
+ if (part.type === "error") {
522
+ tail.cancel();
523
+ controller.enqueue({ type: "error", error: failed(streamPartFailure(part.error)) });
524
+ controller.close();
525
+ return;
526
+ }
527
+ observeFinish(part);
528
+ controller.enqueue(part);
529
+ }
530
+ catch (e) {
531
+ // Past the first output part, a failure ends the reply with no retry: the reader saw its start.
532
+ if (isAbortError(e) || signal?.aborted === true) {
533
+ controller.error(e);
534
+ return;
535
+ }
536
+ controller.enqueue({ type: "error", error: failed(e) });
537
+ controller.close();
538
+ }
539
+ },
540
+ cancel(reason) {
541
+ tail?.cancel(reason);
542
+ },
543
+ });
544
+ return { ...rest, stream };
545
+ },
546
+ };
470
547
  }
471
548
  export function createAiSdkProvider(deps) {
472
549
  const capabilities = {
473
550
  toolCalling: deps.capabilities?.toolCalling ?? true,
474
551
  // Propagate a picture flag only when the caller states it. An absent
475
- // flag stays absent, thus the loop degrades to the next placement for a
476
- // wire that carries no picture there.
477
- ...(deps.capabilities?.imageToolResults !== undefined ? { imageToolResults: deps.capabilities.imageToolResults } : {}),
478
- ...(deps.capabilities?.imageUserMessages !== undefined ? { imageUserMessages: deps.capabilities.imageUserMessages } : {}),
552
+ // flag stays absent, thus the loop drops a picture for a wire that
553
+ // carries none in a tool result.
554
+ imageToolResults: deps.capabilities?.imageToolResults,
555
+ contextWindow: deps.capabilities?.contextWindow,
479
556
  };
480
557
  const logger = (deps.logger ?? createNoopLogger()).named("providers.ai-sdk");
481
558
  const maxOutputTokens = deps.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS;
482
559
  // The sentinel hands the SDK no ceiling, thus the request carries none and the
483
- // server enforces the cap of the model. One binding feeds the call and the
484
- // stream, thus the two cannot disagree about the ceiling of a request.
560
+ // server enforces the cap of the model.
485
561
  const outputCeiling = maxOutputTokens === "provider-maximum" ? {} : { maxOutputTokens };
486
562
  const maxRetries = deps.maxRetries ?? RETRY_MAX_RETRIES;
487
563
  const suspendOn = deps.suspendOn ?? DEFAULT_SUSPEND_ON;
488
564
  const requestTimeoutMs = deps.requestTimeoutMs;
489
- const requestedModelId = requestedModelIdOf(deps.model);
490
- const providerId = providerIdOf(deps.model);
491
- const effortOf = (req) => req.reasoning ?? deps.reasoning ?? DEFAULT_REASONING;
492
- // Each model call emits OpenTelemetry GenAI spans through the AI SDK, with no
493
- // prompt or completion text on them. The integration rides on each call
494
- // instead of the global registry, so the harness never traces the embedder's
495
- // own AI SDK calls. Of the SDK spans only `chat` is written. The operation
496
- // span and the step span around it repeat what `chat` and the span of the
497
- // caller (the loop's `invoke_agent`) say already. Thus they pass through, and
498
- // `chat` attaches to the span of the caller.
499
- const tracer = passThroughTracer(trace.getTracer("gen_ai"), (_name, options) => isSdkWrapperSpan(options.attributes?.["gen_ai.operation.name"]));
500
- const telemetry = { integrations: new OpenTelemetry({ tracer }), recordInputs: false, recordOutputs: false };
565
+ // Each model call and each tool call emits OpenTelemetry GenAI spans through the
566
+ // AI SDK, with no prompt or completion text on them. The integration rides on each
567
+ // call instead of the global registry, so the harness never traces the embedder's
568
+ // own AI SDK calls.
569
+ const telemetry = { integrations: new OpenTelemetry({ tracer: trace.getTracer("gen_ai") }), recordInputs: false, recordOutputs: false };
501
570
  routeSdkWarningsTo(logger);
502
- /**
503
- * Record a call that the envelope gave up on.
504
- *
505
- * The envelope reports one attempt at `debug`, thus a deployment that runs
506
- * at `info` keeps no trace of a call that exhausted its retries: the reply
507
- * carries the failure to the user and the operator sees nothing. This is the
508
- * one record that names the outcome.
509
- */
510
- function logFailure(session, failure, thrown) {
511
- logger.error("provider call failed", {
512
- workload: workloadOf(session),
513
- kind: failure.type,
514
- retryable: failure.retryable,
515
- ...logger.errorFields(thrown),
571
+ function bind(call) {
572
+ const reasoning = call.reasoning ?? deps.reasoning ?? DEFAULT_REASONING;
573
+ const model = wrapLanguageModel({
574
+ model: deps.model,
575
+ middleware: retryEnvelope({
576
+ session: call.session,
577
+ live: call.live,
578
+ logger,
579
+ maxRetries,
580
+ suspendOn,
581
+ requestTimeoutMs,
582
+ resolveRequestHeaders: deps.resolveRequestHeaders,
583
+ onRetry: call.onRetry,
584
+ }),
516
585
  });
517
- }
518
- /**
519
- * Logs each dropped thinking block; the drop does not fail the call.
520
- * `reason` is `prefix_binding_mismatch` or `model_binding_mismatch`.
521
- */
522
- function logDroppedThinkingBlocks(session, metadata) {
523
- for (const drop of inputTransformationsOf(metadata)) {
524
- logger.warn("thinking block dropped", { workload: workloadOf(session), type: drop.type, path: drop.path, reason: drop.reason });
525
- }
526
- }
527
- function chat(req, session, signal) {
528
- const reasoning = effortOf(req);
529
- const providerOptions = deps.providerOptionsFor?.({ session, reasoning });
530
- const run = async () => {
531
- const hookCall = { unsettled: false };
532
- const retry = createRetry(signal, logger, maxRetries, suspendOn, hookCall);
533
- const capture = captureServedModelId(deps.model);
534
- try {
535
- const collected = await retry(async () => {
536
- // The hook runs before each attempt: a host header can be
537
- // time-limited, and the retry window can last minutes.
538
- const headers = await headersForAttempt(deps.resolveRequestHeaders, session, hookCall);
539
- // The call streams on the wire and collapses below.
540
- //
541
- // A non-streaming turn sends no header until the model completes,
542
- // thus the `headersTimeout` of the host HTTP client bounds the whole
543
- // generation. No option of the SDK lifts that bound, because it sits
544
- // under the fetch. Node defaults the field to 300s, and a turn near
545
- // 18k output tokens reaches it, while `DEFAULT_MAX_OUTPUT_TOKENS`
546
- // asks for up to 64k. A cut turn then costs twice: the envelope
547
- // starts the same generation again from zero.
548
- //
549
- // Anthropic states the rule for its own SDKs: a large `max_tokens`
550
- // makes streaming necessary, to prevent an HTTP timeout. Thus a
551
- // ceiling this size streams whether or not a consumer wants the
552
- // deltas, and `chatStream` stays the seam that forwards them.
553
- const result = streamText({
554
- model: capture.model,
555
- system: req.system,
556
- messages: sanitizeMessages(req.messages),
557
- tools: req.tools,
558
- toolChoice: req.toolChoice ?? "auto",
559
- ...outputCeiling,
560
- stopWhen: [],
561
- // The harness envelope owns retries; leaving the SDK default in
562
- // place would multiply attempts (10 outer × 3 inner).
563
- maxRetries: 0,
564
- headers,
565
- abortSignal: signal,
566
- telemetry,
567
- // `firstChunkMs` bounds the wait for the first content chunk,
568
- // and `chunkMs` bounds each later gap. Thus each silent interval
569
- // carries the one configured bound, and a turn that writes
570
- // steadily runs as long as it needs.
571
- ...(requestTimeoutMs !== undefined ? { timeout: { firstChunkMs: requestTimeoutMs, chunkMs: requestTimeoutMs } } : {}),
572
- providerOptions,
573
- reasoning,
574
- });
575
- // The drain sits inside the retried closure, thus a failure at any
576
- // point of the stream re-runs the whole attempt and the envelope
577
- // keeps its whole-call scope. No delta reaches a consumer here —
578
- // `chatStream` is the seam that forwards them.
579
- const iterator = result.fullStream[Symbol.asyncIterator]();
580
- let text = "";
581
- for (let pull = await pullNextDelta(iterator); pull.kind !== "end"; pull = await pullNextDelta(iterator)) {
582
- // A caller abort rides out as the reason of its own signal, thus
583
- // it stays a cancellation and reaches the caller as a throw.
584
- if (pull.kind === "aborted")
585
- throw abortedStreamFailure(signal, pull.reason, requestTimeoutMs);
586
- if (pull.kind === "failed")
587
- throw streamPartFailure(pull.error);
588
- text += pull.text;
589
- }
590
- // These promises settle only once the stream is fully drained, thus
591
- // the loop above must reach its end before this point.
592
- return {
593
- messages: await result.responseMessages,
594
- fallbackText: text,
595
- finishReason: await result.finishReason,
596
- rawFinishReason: await result.rawFinishReason,
597
- usage: await result.usage,
598
- providerMetadata: (await result.finalStep).providerMetadata,
599
- };
600
- });
601
- // Logged past the envelope, thus only the attempt that succeeded
602
- // reports its drops.
603
- const { providerMetadata: metadata, ...reply } = collected;
604
- logDroppedThinkingBlocks(session, metadata);
605
- return ok(responseFromMessages({
606
- ...reply,
607
- requestedModelId,
608
- // Read after the drain: the metadata chunk that carries the
609
- // served id reaches the capture only as the stream is consumed.
610
- servedModelId: capture.servedModelId(),
611
- provider: providerId,
612
- }));
613
- }
614
- catch (e) {
615
- if (isAbortError(e) || signal?.aborted || hookCall.unsettled)
616
- throw e;
617
- const failure = failureOf(e, workloadOf(session), suspendOn);
618
- logFailure(session, failure, e);
619
- return err(failure);
620
- }
621
- };
622
- return new ResultAsync(run());
623
- }
624
- async function* chatStream(req, session, signal) {
625
- const reasoning = effortOf(req);
626
- const providerOptions = deps.providerOptionsFor?.({ session, reasoning });
627
- const hookCall = { unsettled: false };
628
- const retry = createRetry(signal, logger, maxRetries, suspendOn, hookCall);
629
- const capture = captureServedModelId(deps.model);
630
- try {
631
- // Retry covers only stream establishment: streamText defers wire errors
632
- // to consumption, so a failure is not visible until the stream is read.
633
- // The retried closure resolves to one of two outcomes — the stream is
634
- // live with a first delta in hand, or it finished without yielding any
635
- // text — and a delta is only ever yielded OUTSIDE the closure, so a
636
- // retried attempt can never re-emit a delta the consumer already saw.
637
- const opened = await retry(async () => {
638
- const headers = await headersForAttempt(deps.resolveRequestHeaders, session, hookCall);
639
- const result = streamText({
640
- model: capture.model,
641
- system: req.system,
642
- messages: sanitizeMessages(req.messages),
643
- tools: req.tools,
644
- toolChoice: req.toolChoice ?? "auto",
645
- ...outputCeiling,
646
- stopWhen: [],
647
- maxRetries: 0,
648
- headers,
649
- abortSignal: signal,
650
- telemetry,
651
- // The fetch guard bounds the wait until the headers. Past the
652
- // headers the SDK owns two bounds: `firstChunkMs` covers the wait
653
- // for the first content chunk, and `chunkMs` covers each later
654
- // gap. The two take the same value, thus each silent interval of
655
- // the stream has the one configured bound. A chunk that carries
656
- // no content, for example a keep-alive comment, produces no part,
657
- // thus it feeds neither bound.
658
- ...(requestTimeoutMs !== undefined ? { timeout: { firstChunkMs: requestTimeoutMs, chunkMs: requestTimeoutMs } } : {}),
659
- providerOptions,
660
- reasoning,
661
- });
662
- const iterator = result.fullStream[Symbol.asyncIterator]();
663
- const first = await pullNextDelta(iterator);
664
- // The chunk bound can stop the stream before any content arrives. The
665
- // throw carries the sentinel, thus the envelope gives the attempt a
666
- // fresh window under the retry policy of a connection error.
667
- if (first.kind === "aborted")
668
- throw abortedStreamFailure(signal, first.reason, requestTimeoutMs);
669
- if (first.kind === "failed")
670
- throw streamPartFailure(first.error);
671
- if (first.kind === "end") {
672
- // A doStream promise rejection — the shape a real connection
673
- // failure takes — does NOT surface at this first pull: streamText
674
- // resolves it `{ done: true }` and defers the rejection to the
675
- // deferred result promises. Awaiting them here brings that failure
676
- // inside the retry envelope so a text-less establishment error is
677
- // retried; a genuine text-less turn resolves them, and the terminal
678
- // event is built from these already-resolved values without a
679
- // second await. (These promises only settle once the stream is
680
- // fully drained, so they can be awaited here only because the pull
681
- // already reported the stream done.)
682
- return {
683
- kind: "completed",
684
- messages: await result.responseMessages,
685
- finishReason: await result.finishReason,
686
- rawFinishReason: await result.rawFinishReason,
687
- usage: await result.usage,
688
- providerMetadata: (await result.finalStep).providerMetadata,
689
- };
690
- }
691
- return { kind: "streaming", result, iterator, firstDelta: first.text };
692
- });
693
- if (opened.kind === "completed") {
694
- logDroppedThinkingBlocks(session, opened.providerMetadata);
695
- const response = responseFromMessages({
696
- messages: opened.messages,
697
- fallbackText: "",
698
- finishReason: opened.finishReason,
699
- rawFinishReason: opened.rawFinishReason,
700
- usage: opened.usage,
701
- requestedModelId,
702
- servedModelId: capture.servedModelId(),
703
- provider: providerId,
704
- });
705
- yield { type: "done", response };
706
- return;
707
- }
708
- const { result, iterator, firstDelta } = opened;
709
- let text = firstDelta;
710
- yield { type: "text-delta", text: firstDelta };
711
- // Drain the same iterator: past the first delta, errors propagate
712
- // unchanged (no retry, no re-emit).
713
- for (let pull = await pullNextDelta(iterator); pull.kind !== "end"; pull = await pullNextDelta(iterator)) {
714
- // A mid-stream abort ends the turn with an error, never with the
715
- // partial text that arrived before it. The catch below builds the
716
- // terminal `ProviderError` from the throwable.
717
- if (pull.kind === "aborted")
718
- throw abortedStreamFailure(signal, pull.reason, requestTimeoutMs);
719
- if (pull.kind === "failed")
720
- throw streamPartFailure(pull.error);
721
- text += pull.text;
722
- yield { type: "text-delta", text: pull.text };
723
- }
724
- const response = responseFromMessages({
725
- messages: await result.responseMessages,
726
- fallbackText: text,
727
- finishReason: await result.finishReason,
728
- rawFinishReason: await result.rawFinishReason,
729
- usage: await result.usage,
730
- requestedModelId,
731
- // Read after the drain: the metadata chunk carrying the served id
732
- // reaches the capture only as the stream is consumed.
733
- servedModelId: capture.servedModelId(),
734
- provider: providerId,
735
- });
736
- logDroppedThinkingBlocks(session, (await result.finalStep).providerMetadata);
737
- yield { type: "done", response };
738
- }
739
- catch (e) {
740
- if (isAbortError(e) || signal?.aborted || hookCall.unsettled)
741
- throw e;
742
- const failure = failureOf(e, workloadOf(session), suspendOn);
743
- logFailure(session, failure, e);
744
- throw failure;
745
- }
586
+ const providerOptions = deps.providerOptionsFor?.({ session: call.session, reasoning });
587
+ return { model, settings: { ...outputCeiling, reasoning, providerOptions }, telemetry };
746
588
  }
747
589
  // The provider advertises the guard limit on its own instance, thus a
748
590
  // consumer that scales a deadline reads it from the provider in its deps.
749
- return { capabilities, chat, chatStream, ...(requestTimeoutMs !== undefined ? { requestTimeoutMs } : {}) };
591
+ return { capabilities, bind, requestTimeoutMs };
750
592
  }
751
593
  /**
752
594
  * Wrap a fetch so that the wait until the response starts does not exceed
@@ -757,24 +599,23 @@ export function createAiSdkProvider(deps) {
757
599
  * signal through `AbortSignal.any`. Thus the caller signal keeps its normal
758
600
  * effect, and a caller abort stays a cancellation.
759
601
  *
760
- * The guard bounds the response start only. The SDK bounds each later gap of a
761
- * streamed body with its own `chunkMs` setting, thus no timer of the wrapper
762
- * survives the headers. Thus a stream with steady content does not trip the
763
- * guard, whatever its total length. One fetch call is one attempt, because the
764
- * SDK retries are off, thus the window is per attempt.
602
+ * The guard bounds the response start only. The retry envelope bounds each later
603
+ * gap of a streamed body, thus no timer of the wrapper survives the headers. One
604
+ * fetch call is one attempt, because the SDK retries are off, thus the window is
605
+ * per attempt.
765
606
  *
766
607
  * When the field is absent, `createConfiguredAiSdkProvider` installs no wrapper,
767
608
  * and the behavior stays byte-identical.
768
609
  */
769
610
  export function wrapFetchWithRequestTimeout(fetchImpl, requestTimeoutMs) {
770
- return async (input, init) => {
611
+ return Object.assign(async (input, init) => {
771
612
  const controller = new AbortController();
772
613
  const callerSignal = init?.signal ?? undefined;
614
+ // oxlint-disable-next-line eslint-js/no-restricted-syntax -- a guard, not a wait: it aborts the controller of the in-flight fetch at the deadline, unrefs so an armed guard never holds a short-lived process, and the finally clears it.
773
615
  const timer = setTimeout(() => controller.abort(new RequestTimeoutError(requestTimeoutMs)), requestTimeoutMs);
774
616
  // The harness runs on Node, where a timer has `unref`. Unref the guard
775
617
  // timer, thus an armed guard does not keep a short-lived process alive.
776
- // The DOM type of `setTimeout` declares no `unref`, thus guard the call.
777
- timer.unref?.();
618
+ timer.unref();
778
619
  const clear = () => {
779
620
  clearTimeout(timer);
780
621
  // The harness runs on Node, where a caller signal can outlive one fetch
@@ -794,7 +635,7 @@ export function wrapFetchWithRequestTimeout(fetchImpl, requestTimeoutMs) {
794
635
  // is inert there. A probe on Bun 1.4.2 proved both results: the cut fired
795
636
  // at 360 seconds, because Bun pads the timer to its minute wheel, and a
796
637
  // request with the key completed after 420 seconds. The `RequestInit` type
797
- // declares no such member, thus the cast.
638
+ // declares no such member, thus the wider annotation.
798
639
  const forwarded = { ...init, signal, timeout: false };
799
640
  try {
800
641
  return await fetchImpl(input, forwarded);
@@ -802,7 +643,10 @@ export function wrapFetchWithRequestTimeout(fetchImpl, requestTimeoutMs) {
802
643
  finally {
803
644
  clear();
804
645
  }
805
- };
646
+ },
647
+ // `typeof fetch` is a callable with the `preconnect` member of the Bun declaration, so the
648
+ // wrapper carries the member of the fetch it wraps.
649
+ { preconnect: fetchImpl.preconnect });
806
650
  }
807
651
  /**
808
652
  * Bind one explicit `store` directive onto each call of a model.
@@ -818,7 +662,7 @@ function withStoreDirective(model, store) {
818
662
  return wrapLanguageModel({
819
663
  model,
820
664
  middleware: {
821
- transformParams: async ({ params }) => ({
665
+ transformParams: ({ params }) => Promise.resolve({
822
666
  ...params,
823
667
  providerOptions: { ...params.providerOptions, openai: { ...params.providerOptions?.openai, store } },
824
668
  }),
@@ -827,22 +671,21 @@ function withStoreDirective(model, store) {
827
671
  }
828
672
  export function hostPolicyOf(deps) {
829
673
  return {
830
- ...(deps.resolveRequestHeaders !== undefined ? { resolveRequestHeaders: deps.resolveRequestHeaders } : {}),
831
- ...(deps.suspendOn !== undefined ? { suspendOn: deps.suspendOn } : {}),
674
+ resolveRequestHeaders: deps.resolveRequestHeaders,
675
+ suspendOn: deps.suspendOn,
832
676
  };
833
677
  }
834
678
  /**
835
679
  * Realize an `AiSdkProviderConfig` into a `ChatProvider` bound to that config's
836
- * connection and model. The model is closed into the returned provider here (it
837
- * is never passed per `ChatRequest`), so N models require N provider
838
- * instances over one shared connection configuration — one instance serves the
839
- * single model it was built with.
680
+ * connection and model. The model is closed into the returned provider here, so
681
+ * N models require N provider instances over one shared connection
682
+ * configuration — one instance serves the single model it was built with.
840
683
  *
841
684
  * When the config sets `requestTimeoutMs`, the provider wraps the effective fetch
842
- * (`config.fetch ?? globalThis.fetch`) with the response-start guard, it hands
843
- * the value to the stream call as the SDK chunk bound, and it advertises the
844
- * value on the returned instance. When the field is absent, it installs no
845
- * wrapper, it hands the SDK no bound, and it advertises no value.
685
+ * (`config.fetch ?? globalThis.fetch`) with the response-start guard, the retry
686
+ * envelope bounds each later silent interval with the same value, and the
687
+ * provider advertises the value on the returned instance. When the field is
688
+ * absent, it installs no wrapper, it bounds nothing, and it advertises no value.
846
689
  */
847
690
  export function createConfiguredAiSdkProvider(deps) {
848
691
  const config = deps.config;
@@ -870,16 +713,16 @@ export function createConfiguredAiSdkProvider(deps) {
870
713
  ...hostPolicyOf(deps),
871
714
  capabilities: { ...pictureDefault, ...config.capabilities },
872
715
  logger: deps.logger,
873
- ...(config.maxOutputTokens !== undefined ? { maxOutputTokens: config.maxOutputTokens } : {}),
874
- ...(config.maxRetries !== undefined ? { maxRetries: config.maxRetries } : {}),
875
- ...(requestTimeoutMs !== undefined ? { requestTimeoutMs } : {}),
876
- ...(config.reasoning !== undefined ? { reasoning: config.reasoning } : {}),
716
+ maxOutputTokens: config.maxOutputTokens,
717
+ maxRetries: config.maxRetries,
718
+ requestTimeoutMs,
719
+ reasoning: config.reasoning,
877
720
  // The package sends the key as `metadata.user_id`, and the binding as
878
721
  // `thinking.block_binding`.
879
722
  providerOptionsFor: ({ session, reasoning }) => ({
880
723
  anthropic: {
881
724
  metadata: { userId: sessionKeyDigestOf(session) },
882
- ...(binding !== undefined ? { thinking: thinkingWithBinding(reasoning, binding) } : {}),
725
+ thinking: binding === undefined ? undefined : thinkingWithBinding(reasoning, binding),
883
726
  },
884
727
  }),
885
728
  });
@@ -912,9 +755,9 @@ export function createConfiguredAiSdkProvider(deps) {
912
755
  // unset config sends no ceiling, and the server holds the reply at the
913
756
  // cap of the model.
914
757
  maxOutputTokens: config.maxOutputTokens ?? "provider-maximum",
915
- ...(config.maxRetries !== undefined ? { maxRetries: config.maxRetries } : {}),
916
- ...(requestTimeoutMs !== undefined ? { requestTimeoutMs } : {}),
917
- ...(config.reasoning !== undefined ? { reasoning: config.reasoning } : {}),
758
+ maxRetries: config.maxRetries,
759
+ requestTimeoutMs,
760
+ reasoning: config.reasoning,
918
761
  // The package sends the key as `prompt_cache_key`. The store
919
762
  // directive merges into the same namespace, and it keeps this key.
920
763
  providerOptionsFor: ({ session }) => ({ openai: { promptCacheKey: sessionKeyDigestOf(session) } }),
@@ -925,10 +768,12 @@ export function createConfiguredAiSdkProvider(deps) {
925
768
  baseURL: config.baseURL,
926
769
  apiKey: config.apiKey,
927
770
  fetch: effectiveFetch,
928
- // Each call of the provider streams, `chat` included. Without this flag
929
- // the package asks for no usage on a stream, and the call reports none.
771
+ // Each call of the provider streams. Without this flag the package asks for
772
+ // no usage on a stream, and the call reports none.
930
773
  includeUsage: true,
774
+ supportsMultiPartToolContent: config.supportsMultiPartToolContent,
931
775
  });
776
+ const pictureDefault = config.supportsMultiPartToolContent === true ? { imageToolResults: true } : {};
932
777
  // The compatible wire has no standard field for a session key, thus this arm
933
778
  // gives no provider options of its own.
934
779
  return createAiSdkProvider({
@@ -936,11 +781,11 @@ export function createConfiguredAiSdkProvider(deps) {
936
781
  // the seam needs no middleware to carry the depth into its namespace.
937
782
  model: provider.chatModel(config.model),
938
783
  ...hostPolicyOf(deps),
939
- capabilities: config.capabilities,
784
+ capabilities: { ...pictureDefault, ...config.capabilities },
940
785
  logger: deps.logger,
941
- ...(config.maxOutputTokens !== undefined ? { maxOutputTokens: config.maxOutputTokens } : {}),
942
- ...(config.maxRetries !== undefined ? { maxRetries: config.maxRetries } : {}),
943
- ...(requestTimeoutMs !== undefined ? { requestTimeoutMs } : {}),
944
- ...(config.reasoning !== undefined ? { reasoning: config.reasoning } : {}),
786
+ maxOutputTokens: config.maxOutputTokens,
787
+ maxRetries: config.maxRetries,
788
+ requestTimeoutMs,
789
+ reasoning: config.reasoning,
945
790
  });
946
791
  }