@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.
- package/README.md +6 -3
- package/dist/agents/conversation-agent.d.ts +19 -3
- package/dist/agents/conversation-agent.js +49 -30
- package/dist/agents/report-session-agent.d.ts +15 -15
- package/dist/agents/report-session-agent.js +23 -15
- package/dist/agents/sandbox/index.d.ts +1 -1
- package/dist/agents/sandbox/index.js +1 -1
- package/dist/agents/sandbox/shared.d.ts +35 -16
- package/dist/agents/sandbox/shared.js +63 -24
- package/dist/agents/sandbox/translational-safety-agent.js +26 -0
- package/dist/agents/sandbox/types.d.ts +26 -3
- package/dist/agents/sandbox/validate-skills.d.ts +2 -2
- package/dist/agents/sandbox/validate-skills.js +3 -1
- package/dist/agents/sandbox-catalog.d.ts +16 -2
- package/dist/agents/sandbox-catalog.js +22 -3
- package/dist/agents/system-prompt.d.ts +2 -2
- package/dist/app/approve-plan.d.ts +5 -2
- package/dist/app/approve-plan.js +1 -1
- package/dist/app/chat-turn-workflow.d.ts +114 -0
- package/dist/app/chat-turn-workflow.js +307 -0
- package/dist/app/chat-turn.d.ts +85 -57
- package/dist/app/chat-turn.js +125 -99
- package/dist/app/data-profile-orientation.js +10 -8
- package/dist/app/data-profile-view.d.ts +4 -4
- package/dist/app/data-profile-view.js +9 -8
- package/dist/app/in-process-turn.d.ts +42 -0
- package/dist/app/in-process-turn.js +139 -0
- package/dist/app/message-assembly.d.ts +10 -4
- package/dist/app/message-assembly.js +13 -8
- package/dist/app/report-session-runtime.d.ts +4 -4
- package/dist/app/report-session-runtime.js +36 -21
- package/dist/app/spawn-report-session.d.ts +33 -28
- package/dist/app/spawn-report-session.js +25 -40
- package/dist/app/synthesize-run.d.ts +22 -16
- package/dist/app/synthesize-run.js +41 -35
- package/dist/app/work.d.ts +96 -0
- package/dist/app/work.js +147 -0
- package/dist/auth/local-auth-context.d.ts +1 -3
- package/dist/auth/local-auth-context.js +1 -3
- package/dist/auth/local-run-authorizer.d.ts +1 -1
- package/dist/auth/local-run-authorizer.js +5 -3
- package/dist/auth/types.d.ts +26 -26
- package/dist/billing/cached-resolver.d.ts +4 -4
- package/dist/billing/run-charge.d.ts +5 -8
- package/dist/billing/run-charge.js +2 -2
- package/dist/billing/usage-recorder.d.ts +9 -9
- package/dist/citations/aggregate.js +1 -1
- package/dist/citations/clients/arxiv.d.ts +2 -2
- package/dist/citations/clients/arxiv.js +12 -4
- package/dist/citations/clients/common.js +4 -2
- package/dist/citations/clients/crossref.d.ts +2 -2
- package/dist/citations/clients/crossref.js +37 -37
- package/dist/citations/clients/doi-registry.js +15 -16
- package/dist/citations/clients/pubmed.d.ts +2 -2
- package/dist/citations/clients/pubmed.js +20 -13
- package/dist/citations/clients/semantic-scholar.d.ts +2 -2
- package/dist/citations/clients/semantic-scholar.js +9 -9
- package/dist/citations/compare.js +2 -2
- package/dist/citations/match.d.ts +2 -2
- package/dist/citations/match.js +12 -7
- package/dist/citations/normalize.js +35 -26
- package/dist/citations/plan.js +6 -2
- package/dist/citations/resolve.d.ts +6 -6
- package/dist/citations/resolve.js +34 -25
- package/dist/citations/types.d.ts +77 -77
- package/dist/config/environment-stores.d.ts +10 -8
- package/dist/config/resource-limits.js +1 -3
- package/dist/contracts/analogy-report.d.ts +7 -7
- package/dist/contracts/analogy-report.js +2 -2
- package/dist/contracts/chat-events.d.ts +46 -22
- package/dist/contracts/chat-events.js +1 -1
- package/dist/contracts/chat-frame.d.ts +15 -5
- package/dist/contracts/chat-frame.js +67 -40
- package/dist/contracts/chat-parts.d.ts +130 -67
- package/dist/contracts/chat-parts.js +1 -0
- package/dist/contracts/content-url.js +16 -2
- package/dist/contracts/data-profile.d.ts +38 -38
- package/dist/contracts/index.d.ts +3 -3
- package/dist/contracts/index.js +1 -1
- package/dist/contracts/message.d.ts +6 -6
- package/dist/contracts/organ-system.d.ts +11 -11
- package/dist/contracts/part-registry.d.ts +5 -4
- package/dist/contracts/part-registry.js +5 -0
- package/dist/contracts/profile-vocabulary.d.ts +11 -10
- package/dist/contracts/profile-vocabulary.js +10 -3
- package/dist/contracts/report-blocks.d.ts +329 -329
- package/dist/contracts/report-reference.d.ts +105 -81
- package/dist/contracts/report-reference.js +30 -13
- package/dist/contracts/schemas/chat-events.d.ts +45 -6
- package/dist/contracts/schemas/chat-events.js +16 -0
- package/dist/contracts/schemas/chat-parts.d.ts +214 -102
- package/dist/contracts/schemas/chat-parts.js +50 -7
- package/dist/contracts/schemas/index.d.ts +1 -1
- package/dist/contracts/schemas/index.js +1 -1
- package/dist/contracts/severity.d.ts +1 -1
- package/dist/contracts/structure-source.d.ts +3 -3
- package/dist/contracts/structure-source.js +6 -2
- package/dist/contracts/subagent-activity.d.ts +2 -2
- package/dist/contracts/subagent-activity.js +5 -3
- package/dist/contracts/usage.d.ts +2 -2
- package/dist/data/safety-panel-schema.d.ts +25 -25
- package/dist/data/safety-panel-schema.js +13 -4
- package/dist/execution/artifact-metadata.d.ts +23 -15
- package/dist/execution/artifact-metadata.js +33 -10
- package/dist/execution/artifact-record.d.ts +2 -2
- package/dist/execution/artifact-registration.d.ts +5 -5
- package/dist/execution/artifact-registry.d.ts +8 -8
- package/dist/execution/dbos-run-launcher.d.ts +24 -4
- package/dist/execution/dbos-run-launcher.js +58 -4
- package/dist/execution/dbos-workflow-purger.d.ts +7 -6
- package/dist/execution/dbos-workflow-purger.js +29 -21
- package/dist/execution/input-signature.d.ts +2 -2
- package/dist/execution/post-step-pipeline.d.ts +9 -9
- package/dist/execution/post-step-pipeline.js +1 -1
- package/dist/execution/post-step.js +2 -2
- package/dist/execution/reconcile-manifest.d.ts +4 -4
- package/dist/execution/reconcile-manifest.js +3 -2
- package/dist/execution/run-authorizer.d.ts +46 -37
- package/dist/execution/run-authorizer.js +8 -8
- package/dist/execution/run-canceler.d.ts +39 -17
- package/dist/execution/run-canceler.js +137 -28
- package/dist/execution/run-end-record.d.ts +29 -0
- package/dist/execution/run-end-record.js +27 -0
- package/dist/execution/run-event-parts.d.ts +0 -8
- package/dist/execution/run-event-parts.js +29 -24
- package/dist/execution/run-event-stream.d.ts +8 -8
- package/dist/execution/run-event-stream.js +3 -4
- package/dist/execution/run-launcher.d.ts +4 -4
- package/dist/execution/run-synthesis.d.ts +49 -48
- package/dist/execution/run-synthesis.js +96 -255
- package/dist/execution/staged-input.d.ts +2 -2
- package/dist/execution/step-summary.d.ts +6 -6
- package/dist/execution/step-summary.js +4 -8
- package/dist/execution/topo-sort.js +4 -3
- package/dist/execution/workflow-purger.d.ts +2 -2
- package/dist/index.d.ts +25 -24
- package/dist/index.js +36 -37
- package/dist/input-sanitization.js +9 -2
- package/dist/input-scan/clustering.d.ts +6 -6
- package/dist/input-scan/clustering.js +11 -5
- package/dist/input-scan/companions.js +3 -2
- package/dist/input-scan/detect-sets.d.ts +2 -2
- package/dist/input-scan/detect-sets.js +25 -21
- package/dist/input-scan/enrich.d.ts +6 -6
- package/dist/input-scan/enrich.js +29 -12
- package/dist/input-scan/formats.d.ts +2 -2
- package/dist/input-scan/formats.js +8 -2
- package/dist/input-scan/markers.d.ts +2 -2
- package/dist/input-scan/markers.js +14 -5
- package/dist/input-scan/menu.d.ts +10 -10
- package/dist/input-scan/menu.js +0 -0
- package/dist/input-scan/quarantine.d.ts +2 -2
- package/dist/input-scan/quarantine.js +23 -18
- package/dist/input-scan/readout-budget.d.ts +2 -2
- package/dist/input-scan/readout-budget.js +1 -1
- package/dist/input-scan/readout.d.ts +2 -2
- package/dist/input-scan/readout.js +47 -34
- package/dist/input-scan/scan.d.ts +2 -2
- package/dist/input-scan/scan.js +7 -5
- package/dist/input-scan/set-types.d.ts +28 -28
- package/dist/input-scan/shapes.d.ts +4 -4
- package/dist/input-scan/shapes.js +0 -0
- package/dist/input-scan/templates.d.ts +10 -10
- package/dist/input-scan/templates.js +30 -22
- package/dist/input-scan/tokens.d.ts +6 -4
- package/dist/input-scan/tokens.js +100 -38
- package/dist/input-scan/types.d.ts +22 -22
- package/dist/lib/async-utils.d.ts +3 -7
- package/dist/lib/async-utils.js +5 -9
- package/dist/lib/cache.js +1 -1
- package/dist/lib/chrome.d.ts +46 -6
- package/dist/lib/console-logger.js +2 -2
- package/dist/lib/db-result.d.ts +22 -6
- package/dist/lib/db-result.js +9 -13
- package/dist/lib/eyes.d.ts +4 -4
- package/dist/lib/eyes.js +1 -1
- package/dist/lib/fs-helpers.js +18 -6
- package/dist/lib/fs-result.d.ts +1 -0
- package/dist/lib/fs-result.js +5 -6
- package/dist/lib/hooks.d.ts +23 -7
- package/dist/lib/hooks.js +17 -3
- package/dist/lib/host-concurrency.js +3 -2
- package/dist/lib/logger.d.ts +2 -2
- package/dist/lib/logger.js +2 -1
- package/dist/lib/metrics.d.ts +1 -1
- package/dist/lib/null-proto.d.ts +6 -0
- package/dist/lib/null-proto.js +17 -0
- package/dist/lib/otel-spans.d.ts +1 -1
- package/dist/lib/otel-spans.js +9 -5
- package/dist/lib/otel.d.ts +4 -2
- package/dist/lib/otel.js +10 -2
- package/dist/lib/page-capture.d.ts +8 -8
- package/dist/lib/page-capture.js +9 -4
- package/dist/lib/parse-json.d.ts +5 -0
- package/dist/lib/parse-json.js +12 -0
- package/dist/lib/present.d.ts +12 -0
- package/dist/lib/present.js +39 -0
- package/dist/lib/rate-limit.d.ts +4 -4
- package/dist/lib/rate-limit.js +12 -13
- package/dist/lib/regulatory-corpus/fetch-fda-guidance.d.ts +4 -4
- package/dist/lib/regulatory-corpus/fetch-fda-guidance.js +4 -10
- package/dist/lib/regulatory-corpus/fetch-ich.d.ts +4 -4
- package/dist/lib/regulatory-corpus/fetch-ich.js +18 -14
- package/dist/lib/regulatory-corpus/normalize-whitespace.d.ts +6 -0
- package/dist/lib/regulatory-corpus/normalize-whitespace.js +41 -0
- package/dist/lib/regulatory-corpus.d.ts +10 -10
- package/dist/lib/regulatory-corpus.js +3 -1
- package/dist/lib/result.d.ts +10 -11
- package/dist/lib/result.js +15 -13
- package/dist/lib/storage.d.ts +2 -2
- package/dist/lib/test/async-iterable.d.ts +9 -0
- package/dist/lib/test/async-iterable.js +28 -0
- package/dist/lib/test/request-url.d.ts +5 -0
- package/dist/lib/test/request-url.js +7 -0
- package/dist/lib/test/result-assert.d.ts +12 -0
- package/dist/lib/test/result-assert.js +17 -0
- package/dist/lib/test/text-shapes.d.ts +24 -0
- package/dist/lib/test/text-shapes.js +63 -0
- package/dist/lib/text.d.ts +22 -0
- package/dist/lib/text.js +68 -0
- package/dist/lib/thrown.d.ts +18 -0
- package/dist/lib/thrown.js +30 -0
- package/dist/lib/unknown-array.d.ts +6 -0
- package/dist/lib/unknown-array.js +8 -0
- package/dist/lib/unknown-containers.d.ts +14 -0
- package/dist/lib/unknown-containers.js +17 -0
- package/dist/lib/unknown-text.d.ts +8 -0
- package/dist/lib/unknown-text.js +28 -0
- package/dist/lib/zod-issue-shape.d.ts +1 -1
- package/dist/lib/zod-issue-shape.js +31 -31
- package/dist/lib/zod-issues.d.ts +3 -3
- package/dist/lib/zod-issues.js +30 -17
- package/dist/literature/sources/arxiv.d.ts +6 -6
- package/dist/literature/sources/arxiv.js +92 -35
- package/dist/literature/sources/http.d.ts +2 -2
- package/dist/literature/sources/http.js +16 -15
- package/dist/literature/sources/pubmed.d.ts +16 -16
- package/dist/literature/sources/pubmed.js +96 -61
- package/dist/literature/sources/semantic-scholar.d.ts +8 -8
- package/dist/literature/sources/semantic-scholar.js +22 -13
- package/dist/loop/accounting.d.ts +63 -0
- package/dist/loop/accounting.js +141 -0
- package/dist/loop/call-policy.d.ts +73 -0
- package/dist/loop/call-policy.js +109 -0
- package/dist/loop/chat-stream.d.ts +62 -0
- package/dist/loop/chat-stream.js +237 -0
- package/dist/loop/compaction.d.ts +14 -9
- package/dist/loop/compaction.js +17 -0
- package/dist/loop/metrics.d.ts +12 -15
- package/dist/loop/metrics.js +14 -26
- package/dist/loop/run-loop.d.ts +233 -0
- package/dist/loop/run-loop.js +770 -0
- package/dist/loop/sub-agent.d.ts +61 -0
- package/dist/loop/sub-agent.js +161 -0
- package/dist/loop/tool-adapter.d.ts +98 -0
- package/dist/loop/tool-adapter.js +364 -0
- package/dist/loop/tool-detail.d.ts +1 -1
- package/dist/loop/tool-detail.js +6 -5
- package/dist/loop/tool-outcome.d.ts +1 -1
- package/dist/loop/tool-output.d.ts +4 -4
- package/dist/loop/tool-output.js +2 -2
- package/dist/loop/turn-credentials.d.ts +34 -0
- package/dist/loop/turn-credentials.js +73 -0
- package/dist/loop/types.d.ts +34 -37
- package/dist/loop/types.js +2 -7
- package/dist/memory/ai-sdk-message-storage.d.ts +5 -5
- package/dist/memory/ai-sdk-message-storage.js +13 -11
- package/dist/memory/card-builders.d.ts +14 -14
- package/dist/memory/card-builders.js +19 -15
- package/dist/memory/conversation-display-recorder.d.ts +22 -6
- package/dist/memory/conversation-display-recorder.js +64 -20
- package/dist/memory/conversation-display-replay.js +3 -2
- package/dist/memory/conversation-display-storage.d.ts +15 -7
- package/dist/memory/conversation-display-storage.js +141 -36
- package/dist/memory/conversation-view.d.ts +4 -4
- package/dist/memory/conversation-view.js +5 -4
- package/dist/memory/count-tokens.js +10 -8
- package/dist/memory/derive-thread-title.d.ts +0 -13
- package/dist/memory/derive-thread-title.js +2 -1
- package/dist/memory/message-backfill.d.ts +12 -5
- package/dist/memory/message-backfill.js +5 -3
- package/dist/memory/thread-history.d.ts +66 -24
- package/dist/memory/thread-history.js +212 -79
- package/dist/memory/thread-store.d.ts +26 -17
- package/dist/memory/thread-store.js +15 -9
- package/dist/memory/tool-call-integrity.d.ts +2 -2
- package/dist/memory/tool-call-integrity.js +4 -3
- package/dist/memory/working-memory.d.ts +16 -12
- package/dist/memory/working-memory.js +72 -61
- package/dist/prompts/briefing.d.ts +63 -9
- package/dist/prompts/briefing.js +130 -3
- package/dist/prompts/planner.js +13 -2
- package/dist/prompts/synthesis-agent.d.ts +1 -1
- package/dist/prompts/synthesis-agent.js +6 -14
- package/dist/provenance/collector.d.ts +6 -6
- package/dist/provenance/collector.js +15 -8
- package/dist/provenance/exec-frame.d.ts +2 -2
- package/dist/provenance/exec-frame.js +6 -1
- package/dist/provenance/seam.d.ts +24 -19
- package/dist/provenance/seam.js +7 -5
- package/dist/provenance/types.d.ts +6 -6
- package/dist/providers/ai-sdk.d.ts +113 -62
- package/dist/providers/ai-sdk.js +303 -458
- package/dist/providers/embedding.d.ts +2 -2
- package/dist/providers/embedding.js +1 -1
- package/dist/providers/errors.d.ts +22 -2
- package/dist/providers/errors.js +98 -50
- package/dist/providers/prompt-cache.d.ts +8 -8
- package/dist/providers/prompt-cache.js +13 -11
- package/dist/providers/reasoning.d.ts +2 -2
- package/dist/providers/reasoning.js +2 -2
- package/dist/providers/types.d.ts +59 -92
- package/dist/reference-data/catalog.d.ts +2 -15
- package/dist/reference-data/catalog.js +166 -10
- package/dist/reference-data/receipt.d.ts +2 -2
- package/dist/report-model/assert-rules.js +1 -1
- package/dist/report-model/authoring-grammar.d.ts +209 -231
- package/dist/report-model/block-walk.d.ts +10 -10
- package/dist/report-model/block-walk.js +2 -0
- package/dist/report-model/draft-finish.d.ts +8 -8
- package/dist/report-model/draft-finish.js +1 -1
- package/dist/report-model/draft-hash.js +8 -7
- package/dist/report-model/draft-operations.d.ts +22 -10
- package/dist/report-model/draft-operations.js +48 -30
- package/dist/report-model/draft-read.d.ts +19 -7
- package/dist/report-model/draft-read.js +16 -6
- package/dist/report-model/draft.d.ts +844 -2
- package/dist/report-model/draft.js +3 -1
- package/dist/report-model/fixture-resolver.js +39 -16
- package/dist/report-model/pin-snapshot.d.ts +2 -2
- package/dist/report-model/pin-snapshot.js +15 -15
- package/dist/report-model/production-resolver.d.ts +18 -18
- package/dist/report-model/production-resolver.js +50 -42
- package/dist/report-model/reference-resolver.d.ts +26 -10
- package/dist/report-model/reference-resolver.js +68 -5
- package/dist/report-model/reference-stamp.js +30 -38
- package/dist/report-model/structural-validation.js +12 -4
- package/dist/report-model/validate.d.ts +7 -7
- package/dist/report-model/validate.js +6 -6
- package/dist/report-render/assets.d.ts +2 -2
- package/dist/report-render/assets.js +27 -3
- package/dist/report-render/chart-export.d.ts +10 -2
- package/dist/report-render/chart-export.js +37 -11
- package/dist/report-render/chart-presets.d.ts +8 -8
- package/dist/report-render/chart-presets.js +3 -3
- package/dist/report-render/chart-renderers.d.ts +23 -16
- package/dist/report-render/chart-renderers.js +74 -53
- package/dist/report-render/chart-toolbox.d.ts +2 -2
- package/dist/report-render/chart-toolbox.js +7 -6
- package/dist/report-render/chart.d.ts +15 -16
- package/dist/report-render/chart.js +369 -252
- package/dist/report-render/design.d.ts +36 -297
- package/dist/report-render/design.js +0 -12
- package/dist/report-render/figures/common.d.ts +12 -12
- package/dist/report-render/figures/common.js +42 -31
- package/dist/report-render/figures/dendrogram.d.ts +3 -3
- package/dist/report-render/figures/dendrogram.js +10 -10
- package/dist/report-render/figures/dense.js +15 -8
- package/dist/report-render/figures/dotplot.js +46 -33
- package/dist/report-render/figures/embedding.js +52 -43
- package/dist/report-render/figures/equal-units.d.ts +10 -10
- package/dist/report-render/figures/equal-units.js +27 -27
- package/dist/report-render/figures/forest.js +9 -7
- package/dist/report-render/figures/gsea.js +21 -11
- package/dist/report-render/figures/heatmap.js +13 -9
- package/dist/report-render/figures/index.d.ts +10 -10
- package/dist/report-render/figures/index.js +4 -2
- package/dist/report-render/figures/km.js +10 -9
- package/dist/report-render/figures/label-room.d.ts +12 -12
- package/dist/report-render/figures/label-room.js +7 -2
- package/dist/report-render/figures/locuszoom.d.ts +2 -2
- package/dist/report-render/figures/locuszoom.js +59 -31
- package/dist/report-render/figures/lollipop.js +3 -2
- package/dist/report-render/figures/ma.js +8 -4
- package/dist/report-render/figures/manhattan.d.ts +1 -2
- package/dist/report-render/figures/manhattan.js +52 -34
- package/dist/report-render/figures/oncoprint.js +4 -5
- package/dist/report-render/figures/pca.js +25 -11
- package/dist/report-render/figures/qq.js +20 -9
- package/dist/report-render/figures/roc.js +1 -1
- package/dist/report-render/figures/sankey.d.ts +2 -2
- package/dist/report-render/figures/sankey.js +11 -10
- package/dist/report-render/figures/upset.d.ts +6 -6
- package/dist/report-render/figures/upset.js +7 -4
- package/dist/report-render/figures/volcano.js +12 -10
- package/dist/report-render/hybrid-svg.d.ts +4 -4
- package/dist/report-render/hybrid-svg.js +7 -5
- package/dist/report-render/number-format.d.ts +4 -4
- package/dist/report-render/number-format.js +62 -27
- package/dist/report-render/page.js +2 -1
- package/dist/report-render/provenance-data.d.ts +2 -2
- package/dist/report-render/references.d.ts +4 -4
- package/dist/report-render/render.d.ts +2 -2
- package/dist/report-render/render.js +10 -11
- package/dist/report-render/script-json.js +1 -1
- package/dist/report-render/table-data.d.ts +6 -6
- package/dist/report-render/test/options.d.ts +49 -0
- package/dist/report-render/test/options.js +143 -0
- package/dist/report-render/test/page-function.d.ts +19 -0
- package/dist/report-render/test/page-function.js +33 -0
- package/dist/report-render/types.d.ts +10 -10
- package/dist/report-render/value-bridge.d.ts +4 -4
- package/dist/report-render/value-bridge.js +27 -14
- package/dist/report-render/views/chart-view.d.ts +2 -2
- package/dist/report-render/views/chart-view.js +2 -2
- package/dist/report-render/views/lineage.d.ts +6 -6
- package/dist/report-render/views/lineage.js +2 -0
- package/dist/report-render/views/page-view.d.ts +2 -2
- package/dist/report-render/views/page-view.js +1 -0
- package/dist/report-render/views/prose.js +25 -8
- package/dist/report-render/views/references-view.js +12 -1
- package/dist/report-render/views/values.js +1 -1
- package/dist/runtime/assemble.d.ts +53 -26
- package/dist/runtime/assemble.js +103 -56
- package/dist/runtime/boot.d.ts +8 -7
- package/dist/runtime/boot.js +1 -1
- package/dist/runtime/connection-budget.d.ts +6 -6
- package/dist/runtime/connection-budget.js +1 -1
- package/dist/runtime/dbos.d.ts +29 -19
- package/dist/runtime/dbos.js +35 -20
- package/dist/runtime/result-serialization.js +18 -5
- package/dist/runtime/shutdown.d.ts +2 -2
- package/dist/sandbox/client.d.ts +7 -3
- package/dist/sandbox/cpu-files.d.ts +2 -2
- package/dist/sandbox/cpu-files.js +21 -4
- package/dist/sandbox/create-sandbox.d.ts +7 -8
- package/dist/sandbox/create-sandbox.js +6 -12
- package/dist/sandbox/docker-client.d.ts +48 -3
- package/dist/sandbox/docker-client.js +10 -6
- package/dist/sandbox/estimate-data-profile-resources.js +2 -7
- package/dist/sandbox/exec-outcome.d.ts +2 -2
- package/dist/sandbox/exec-outcome.js +1 -1
- package/dist/sandbox/exec.d.ts +10 -6
- package/dist/sandbox/exec.js +27 -12
- package/dist/sandbox/execution-id.js +14 -6
- package/dist/sandbox/farm.d.ts +2 -2
- package/dist/sandbox/farm.js +22 -27
- package/dist/sandbox/identity.d.ts +7 -0
- package/dist/sandbox/identity.js +14 -3
- package/dist/sandbox/image-packages.d.ts +26 -4
- package/dist/sandbox/image-packages.js +29 -27
- package/dist/sandbox/k8s-client.d.ts +35 -8
- package/dist/sandbox/k8s-client.js +6 -5
- package/dist/sandbox/labels.js +1 -0
- package/dist/sandbox/liveness.js +3 -1
- package/dist/sandbox/mount-plan.d.ts +10 -10
- package/dist/sandbox/mount-plan.js +13 -14
- package/dist/sandbox/notification-sweep.d.ts +4 -4
- package/dist/sandbox/notification-sweep.js +4 -7
- package/dist/sandbox/package-identity.d.ts +6 -13
- package/dist/sandbox/package-identity.js +46 -28
- package/dist/sandbox/reaper.d.ts +10 -10
- package/dist/sandbox/reaper.js +4 -6
- package/dist/sandbox/sandbox-error.d.ts +2 -9
- package/dist/sandbox/sandbox-error.js +21 -8
- package/dist/sandbox/sandbox-step-translate.d.ts +8 -5
- package/dist/sandbox/sandbox-step-translate.js +22 -8
- package/dist/sandbox/step-sandbox.d.ts +47 -0
- package/dist/sandbox/step-sandbox.js +53 -0
- package/dist/sandbox/types.d.ts +18 -19
- package/dist/sandbox/types.js +1 -1
- package/dist/schemas/artifact-manifest.d.ts +4 -4
- package/dist/schemas/data-profile-schemas.d.ts +351 -306
- package/dist/schemas/file-metadata.js +2 -4
- package/dist/schemas/plan-schemas.d.ts +79 -25
- package/dist/schemas/plan-schemas.js +1 -1
- package/dist/schemas/run-synthesis.d.ts +95 -26
- package/dist/schemas/run-synthesis.js +3 -1
- package/dist/schemas/validate-plan.d.ts +4 -4
- package/dist/schemas/validate-plan.js +17 -5
- package/dist/schemas/workflow-state.d.ts +127 -14
- package/dist/schemas/workflow-state.js +56 -2
- package/dist/state/active-turns.d.ts +36 -0
- package/dist/state/active-turns.js +67 -0
- package/dist/state/analyses-metrics.d.ts +8 -8
- package/dist/state/analyses-metrics.js +4 -4
- package/dist/state/analyses.d.ts +0 -14
- package/dist/state/analyses.js +0 -32
- package/dist/state/artifacts.d.ts +47 -18
- package/dist/state/artifacts.js +48 -7
- package/dist/state/data-profile.d.ts +2 -2
- package/dist/state/db.d.ts +12 -2
- package/dist/state/db.js +5 -0
- package/dist/state/edit-intents.d.ts +4 -0
- package/dist/state/edit-intents.js +71 -0
- package/dist/state/index.d.ts +5 -5
- package/dist/state/index.js +3 -3
- package/dist/state/init.d.ts +2 -1
- package/dist/state/init.js +5 -2
- package/dist/state/migrations/20260927120000_baseline.js +3 -1
- package/dist/state/migrations/20261026120000_add_the_edit_intents.d.ts +7 -0
- package/dist/state/migrations/20261026120000_add_the_edit_intents.js +21 -0
- package/dist/state/migrations/20261027120000_record_the_applied_memory_edits.d.ts +7 -0
- package/dist/state/migrations/20261027120000_record_the_applied_memory_edits.js +16 -0
- package/dist/state/migrations/20261027120100_store_the_authoring_results.d.ts +8 -0
- package/dist/state/migrations/20261027120100_store_the_authoring_results.js +20 -0
- package/dist/state/migrations/20261027120200_key_the_groups_of_a_turn.d.ts +7 -0
- package/dist/state/migrations/20261027120200_key_the_groups_of_a_turn.js +12 -0
- package/dist/state/migrations/20261027120300_mark_the_active_turn_of_a_thread.d.ts +7 -0
- package/dist/state/migrations/20261027120300_mark_the_active_turn_of_a_thread.js +11 -0
- package/dist/state/migrations/20261028120000_record_the_paused_work.d.ts +7 -0
- package/dist/state/migrations/20261028120000_record_the_paused_work.js +25 -0
- package/dist/state/migrations/20261028120100_end_the_suspended_runs.d.ts +8 -0
- package/dist/state/migrations/20261028120100_end_the_suspended_runs.js +13 -0
- package/dist/state/migrations/20261029120000_reference_the_run_mandate.d.ts +7 -0
- package/dist/state/migrations/20261029120000_reference_the_run_mandate.js +23 -0
- package/dist/state/migrations/20261029120100_record_the_run_session_of_a_pause.d.ts +7 -0
- package/dist/state/migrations/20261029120100_record_the_run_session_of_a_pause.js +11 -0
- package/dist/state/migrations/index.js +18 -0
- package/dist/state/paused-work.d.ts +52 -0
- package/dist/state/paused-work.js +105 -0
- package/dist/state/plans.d.ts +27 -8
- package/dist/state/plans.js +14 -11
- package/dist/state/purge-analysis.d.ts +6 -6
- package/dist/state/purge-analysis.js +10 -2
- package/dist/state/report-session-state.d.ts +43 -18
- package/dist/state/report-session-state.js +43 -4
- package/dist/state/report-versions.d.ts +16 -11
- package/dist/state/report-versions.js +5 -3
- package/dist/state/runs.d.ts +70 -25
- package/dist/state/runs.js +127 -64
- package/dist/state/schema.d.ts +18 -21
- package/dist/state/schema.js +4 -5
- package/dist/state/snapshot-parse.d.ts +2 -2
- package/dist/state/snapshot-parse.js +14 -8
- package/dist/state/step-executions.d.ts +29 -8
- package/dist/state/step-executions.js +28 -4
- package/dist/state/tool-outputs.d.ts +2 -2
- package/dist/state/tool-outputs.js +2 -1
- package/dist/state/vector-store.d.ts +16 -16
- package/dist/state/vector-store.js +11 -7
- package/dist/tasks/data-profile-absorb.d.ts +3 -3
- package/dist/tasks/data-profile-absorb.js +21 -16
- package/dist/tasks/data-profile-activity.d.ts +5 -5
- package/dist/tasks/data-profile-activity.js +5 -5
- package/dist/tasks/data-profile-index.d.ts +4 -4
- package/dist/tasks/data-profile-index.js +32 -17
- package/dist/tasks/data-profile-resolve.d.ts +8 -8
- package/dist/tasks/data-profile-resolve.js +88 -62
- package/dist/tasks/data-profile.d.ts +40 -31
- package/dist/tasks/data-profile.js +138 -95
- package/dist/tasks/extract-values.d.ts +26 -79
- package/dist/tasks/extract-values.js +48 -108
- package/dist/tasks/refresh-regulatory-corpus.d.ts +4 -20
- package/dist/tasks/refresh-regulatory-corpus.js +12 -8
- package/dist/tasks/regulatory-corpus-boot-refresh.d.ts +2 -2
- package/dist/tasks/regulatory-corpus-boot-refresh.js +12 -10
- package/dist/testing.d.ts +60 -0
- package/dist/testing.js +96 -0
- package/dist/tools/ad-hoc-router.d.ts +11 -9
- package/dist/tools/ad-hoc-router.js +80 -51
- package/dist/tools/analysis-invocation.d.ts +7 -0
- package/dist/tools/analysis-invocation.js +29 -5
- package/dist/tools/approval/contract.d.ts +8 -52
- package/dist/tools/approval/contract.js +7 -36
- package/dist/tools/approval/gateway.d.ts +27 -28
- package/dist/tools/approval/gateway.js +33 -130
- package/dist/tools/approval/queries.d.ts +6 -11
- package/dist/tools/approval/queries.js +43 -29
- package/dist/tools/approval/uuidv7.js +2 -2
- package/dist/tools/bio/chembl.d.ts +3 -3
- package/dist/tools/bio/chembl.js +10 -0
- package/dist/tools/bio/comptox.d.ts +25 -8
- package/dist/tools/bio/comptox.js +4 -2
- package/dist/tools/bio/drug-gene-interactions.d.ts +27 -17
- package/dist/tools/bio/drug-gene-interactions.js +11 -8
- package/dist/tools/bio/gene-disease-evidence.d.ts +61 -15
- package/dist/tools/bio/gene-disease-evidence.js +10 -6
- package/dist/tools/bio/gene-preclinical-profile.d.ts +11 -11
- package/dist/tools/bio/keys.d.ts +2 -2
- package/dist/tools/bio/keys.js +3 -3
- package/dist/tools/bio/lookup-annotation.d.ts +5 -5
- package/dist/tools/bio/lookup-annotation.js +3 -0
- package/dist/tools/bio/opentargets.d.ts +1 -1
- package/dist/tools/bio/opentargets.js +6 -0
- package/dist/tools/bio/pubchem.d.ts +2 -2
- package/dist/tools/bio/pubchem.js +6 -0
- package/dist/tools/bio/pubmed.d.ts +26 -16
- package/dist/tools/bio/pubmed.js +9 -3
- package/dist/tools/bio/search-clinical-trials.d.ts +4 -4
- package/dist/tools/bio/search-clinical-trials.js +5 -1
- package/dist/tools/bio/search-faers.d.ts +2 -2
- package/dist/tools/bio/search-faers.js +1 -1
- package/dist/tools/bio/search-gene.d.ts +2 -2
- package/dist/tools/bio/search-gene.js +1 -0
- package/dist/tools/bio/search-geo-datasets.d.ts +4 -4
- package/dist/tools/bio/search-geo-datasets.js +5 -5
- package/dist/tools/bio/search-interactions.d.ts +1 -1
- package/dist/tools/bio/search-patents.d.ts +28 -22
- package/dist/tools/bio/search-patents.js +20 -17
- package/dist/tools/bio/search-protein.d.ts +2 -2
- package/dist/tools/bio/search-protein.js +1 -1
- package/dist/tools/bio/search-regulatory-approvals.d.ts +64 -18
- package/dist/tools/bio/search-regulatory-approvals.js +21 -16
- package/dist/tools/bio/target-safety.d.ts +8 -8
- package/dist/tools/bio/target-safety.js +11 -6
- package/dist/tools/capability-data.d.ts +40 -0
- package/dist/tools/capability-data.js +74 -0
- package/dist/tools/define-tool.d.ts +55 -46
- package/dist/tools/define-tool.js +39 -27
- package/dist/tools/display/normalize-echart-spec.d.ts +2 -2
- package/dist/tools/display/normalize-echart-spec.js +51 -27
- package/dist/tools/display/show-user.d.ts +2 -2
- package/dist/tools/display/show-user.js +1 -1
- package/dist/tools/execute-analysis.d.ts +54 -17
- package/dist/tools/execute-analysis.js +193 -62
- package/dist/tools/knowledge/check.d.ts +182 -0
- package/dist/tools/knowledge/check.js +94 -0
- package/dist/tools/knowledge/client.d.ts +351 -0
- package/dist/tools/knowledge/client.js +319 -0
- package/dist/tools/knowledge/environment.d.ts +78 -0
- package/dist/tools/knowledge/environment.js +116 -0
- package/dist/tools/knowledge/index.d.ts +49 -0
- package/dist/tools/knowledge/index.js +70 -0
- package/dist/tools/knowledge/local-slots.d.ts +62 -0
- package/dist/tools/knowledge/local-slots.js +184 -0
- package/dist/tools/knowledge/pin.d.ts +14 -0
- package/dist/tools/knowledge/pin.js +17 -0
- package/dist/tools/knowledge/recommend.d.ts +67 -0
- package/dist/tools/knowledge/recommend.js +106 -0
- package/dist/tools/knowledge/situation.d.ts +143 -0
- package/dist/tools/knowledge/situation.js +157 -0
- package/dist/tools/knowledge/skeleton.d.ts +69 -0
- package/dist/tools/knowledge/skeleton.js +201 -0
- package/dist/tools/knowledge/template.d.ts +139 -0
- package/dist/tools/knowledge/template.js +273 -0
- package/dist/tools/lib/alphafold-client.js +2 -1
- package/dist/tools/lib/amass-client.d.ts +28 -28
- package/dist/tools/lib/amass-client.js +20 -10
- package/dist/tools/lib/api-utils.d.ts +13 -3
- package/dist/tools/lib/api-utils.js +17 -3
- package/dist/tools/lib/bgee-client.d.ts +6 -6
- package/dist/tools/lib/bgee-client.js +16 -10
- package/dist/tools/lib/cbioportal-client.d.ts +4 -4
- package/dist/tools/lib/cbioportal-client.js +9 -8
- package/dist/tools/lib/chembl-client.d.ts +14 -14
- package/dist/tools/lib/chembl-client.js +11 -4
- package/dist/tools/lib/clinical-benchmarks-client.d.ts +4 -4
- package/dist/tools/lib/clinical-benchmarks-client.js +4 -7
- package/dist/tools/lib/clinical-trials-client.d.ts +18 -18
- package/dist/tools/lib/clinical-trials-client.js +10 -10
- package/dist/tools/lib/clinvar-client.d.ts +2 -2
- package/dist/tools/lib/clinvar-client.js +6 -6
- package/dist/tools/lib/ctx-ops.d.ts +23 -23
- package/dist/tools/lib/ctx-ops.js +13 -10
- package/dist/tools/lib/dgidb-client.d.ts +6 -6
- package/dist/tools/lib/dgidb-client.js +10 -12
- package/dist/tools/lib/disgenet-client.d.ts +4 -4
- package/dist/tools/lib/ema-client.d.ts +2 -2
- package/dist/tools/lib/ensembl-client.d.ts +4 -4
- package/dist/tools/lib/ensembl-client.js +5 -4
- package/dist/tools/lib/gwas-catalog-client.d.ts +4 -4
- package/dist/tools/lib/gwas-catalog-client.js +17 -17
- package/dist/tools/lib/html-text.d.ts +6 -0
- package/dist/tools/lib/html-text.js +9 -0
- package/dist/tools/lib/identifier-resolver.d.ts +4 -4
- package/dist/tools/lib/identifier-resolver.js +7 -3
- package/dist/tools/lib/impc-client.d.ts +8 -8
- package/dist/tools/lib/impc-client.js +46 -35
- package/dist/tools/lib/iuphar-client.d.ts +2 -2
- package/dist/tools/lib/iuphar-client.js +7 -16
- package/dist/tools/lib/monarch-client.d.ts +4 -4
- package/dist/tools/lib/openfda-client.d.ts +22 -22
- package/dist/tools/lib/openfda-client.js +23 -22
- package/dist/tools/lib/opentargets-client.d.ts +12 -12
- package/dist/tools/lib/pathway-client.d.ts +4 -4
- package/dist/tools/lib/pathway-client.js +15 -19
- package/dist/tools/lib/pharmgkb-client.d.ts +2 -2
- package/dist/tools/lib/pharmgkb-client.js +1 -1
- package/dist/tools/lib/protein-family-modality.d.ts +2 -2
- package/dist/tools/lib/protein-family-modality.js +0 -2
- package/dist/tools/lib/protein-family-normalize.js +7 -0
- package/dist/tools/lib/pubchem-client.d.ts +2 -2
- package/dist/tools/lib/pubchem-client.js +1 -0
- package/dist/tools/lib/pubchem-ops.d.ts +4 -4
- package/dist/tools/lib/pubchem-ops.js +8 -0
- package/dist/tools/lib/pubmed-client.d.ts +9 -9
- package/dist/tools/lib/pubmed-client.js +1 -1
- package/dist/tools/lib/string-client.d.ts +6 -6
- package/dist/tools/lib/uniprot-client.d.ts +8 -8
- package/dist/tools/lib/uniprot-client.js +5 -1
- package/dist/tools/memory/update-working-memory.d.ts +16 -13
- package/dist/tools/memory/update-working-memory.js +21 -3
- package/dist/tools/read-tool-output.js +8 -2
- package/dist/tools/registry.d.ts +2 -2
- package/dist/tools/report-authoring/authoring-tools.d.ts +54 -23
- package/dist/tools/report-authoring/authoring-tools.js +128 -62
- package/dist/tools/report-session/derive-table.d.ts +19 -59
- package/dist/tools/report-session/derive-table.js +120 -122
- package/dist/tools/report-session/examine-page.d.ts +6 -6
- package/dist/tools/report-session/examine-page.js +14 -12
- package/dist/tools/report-session/list-artifacts.d.ts +6 -6
- package/dist/tools/report-session/list-artifacts.js +5 -5
- package/dist/tools/report-session/page-faults.d.ts +6 -6
- package/dist/tools/report-session/page-faults.js +3 -1
- package/dist/tools/report-session/preview-report.d.ts +4 -3
- package/dist/tools/report-session/preview-report.js +26 -7
- package/dist/tools/report-session/record-version.d.ts +9 -4
- package/dist/tools/report-session/record-version.js +16 -9
- package/dist/tools/report-session/session-page-publisher.d.ts +6 -6
- package/dist/tools/research/generate-analogy-report.d.ts +14 -7
- package/dist/tools/research/generate-analogy-report.js +80 -76
- package/dist/tools/research/generate-plan.d.ts +39 -16
- package/dist/tools/research/generate-plan.js +565 -338
- package/dist/tools/research/guarded-address.d.ts +20 -0
- package/dist/tools/research/guarded-address.js +149 -0
- package/dist/tools/research/inspect-data-profile.d.ts +27 -20
- package/dist/tools/research/inspect-data-profile.js +26 -25
- package/dist/tools/research/inspect-run.d.ts +54 -27
- package/dist/tools/research/inspect-run.js +50 -40
- package/dist/tools/research/literature-reviewer.d.ts +8 -7
- package/dist/tools/research/literature-reviewer.js +29 -28
- package/dist/tools/research/search-arxiv.d.ts +1 -1
- package/dist/tools/research/search-arxiv.js +1 -1
- package/dist/tools/research/search-github-repos.d.ts +10 -7
- package/dist/tools/research/search-github-repos.js +25 -22
- package/dist/tools/research/search-semantic-scholar.js +1 -1
- package/dist/tools/research/searxng-engine.d.ts +40 -0
- package/dist/tools/research/searxng-engine.js +122 -0
- package/dist/tools/research/web-fetch.d.ts +127 -0
- package/dist/tools/research/web-fetch.js +618 -0
- package/dist/tools/research/web-search.d.ts +84 -0
- package/dist/tools/research/web-search.js +117 -0
- package/dist/tools/sandbox/link-packages.d.ts +11 -7
- package/dist/tools/sandbox/link-packages.js +11 -8
- package/dist/tools/sandbox/list-available-packages.d.ts +24 -12
- package/dist/tools/sandbox/list-available-packages.js +43 -29
- package/dist/tools/sandbox/list-available-refs.d.ts +38 -14
- package/dist/tools/sandbox/list-available-refs.js +119 -37
- package/dist/tools/sandbox/report-blocker.d.ts +30 -37
- package/dist/tools/sandbox/report-blocker.js +22 -68
- package/dist/tools/sandbox/skills.d.ts +16 -12
- package/dist/tools/sandbox/skills.js +16 -12
- package/dist/tools/sandbox/submit-file-metadata.d.ts +12 -9
- package/dist/tools/sandbox/submit-file-metadata.js +18 -21
- package/dist/tools/start-report-session.d.ts +13 -5
- package/dist/tools/start-report-session.js +35 -8
- package/dist/tools/terminal-text.d.ts +14 -0
- package/dist/tools/terminal-text.js +51 -0
- package/dist/tools/workspace/decision-record.d.ts +81 -0
- package/dist/tools/workspace/decision-record.js +127 -0
- package/dist/tools/workspace/edit-file.d.ts +59 -18
- package/dist/tools/workspace/edit-file.js +98 -15
- package/dist/tools/workspace/execute-command.d.ts +31 -12
- package/dist/tools/workspace/execute-command.js +37 -8
- package/dist/tools/workspace/file-stat.d.ts +6 -3
- package/dist/tools/workspace/grep.d.ts +10 -7
- package/dist/tools/workspace/grep.js +9 -3
- package/dist/tools/workspace/index.d.ts +1 -0
- package/dist/tools/workspace/index.js +1 -0
- package/dist/tools/workspace/list-files.d.ts +6 -3
- package/dist/tools/workspace/mutator.d.ts +28 -15
- package/dist/tools/workspace/mutator.js +107 -53
- package/dist/tools/workspace/read-file.d.ts +8 -5
- package/dist/tools/workspace/result-bounds.d.ts +5 -5
- package/dist/tools/workspace/result-bounds.js +4 -2
- package/dist/tools/workspace/run-exec.d.ts +2 -2
- package/dist/tools/workspace/run-exec.js +3 -3
- package/dist/tools/workspace/scan-inputs.d.ts +8 -5
- package/dist/tools/workspace/scan-inputs.js +17 -5
- package/dist/tools/workspace/show-file.d.ts +1 -1
- package/dist/tools/workspace/show-file.js +2 -1
- package/dist/tools/workspace/show-plan.d.ts +8 -5
- package/dist/tools/workspace/show-plan.js +9 -8
- package/dist/tools/workspace/workspace-search.d.ts +41 -13
- package/dist/tools/workspace/workspace-search.js +27 -14
- package/dist/tools/workspace/write-file.d.ts +9 -7
- package/dist/workflows/execute-analysis-scheduler.d.ts +9 -9
- package/dist/workflows/execute-analysis-scheduler.js +6 -3
- package/dist/workflows/execute-analysis.d.ts +100 -76
- package/dist/workflows/execute-analysis.js +380 -247
- package/dist/workflows/pause.d.ts +71 -0
- package/dist/workflows/pause.js +173 -0
- package/dist/workflows/sandbox-step.d.ts +50 -61
- package/dist/workflows/sandbox-step.js +99 -106
- package/dist/workflows/test/sql-writes.d.ts +21 -0
- package/dist/workflows/test/sql-writes.js +36 -0
- package/dist/workspace/filesystem.d.ts +6 -6
- package/dist/workspace/filesystem.js +10 -8
- package/dist/workspace/paths.d.ts +1 -1
- package/dist/workspace/paths.js +15 -4
- package/dist/workspace/search-config.d.ts +2 -2
- package/dist/workspace/search-config.js +1 -1
- package/package.json +25 -22
- package/dist/loop/continue-agent.d.ts +0 -40
- package/dist/loop/continue-agent.js +0 -38
- package/dist/loop/genai-spans.d.ts +0 -47
- package/dist/loop/genai-spans.js +0 -134
- package/dist/loop/run-agent.d.ts +0 -236
- package/dist/loop/run-agent.js +0 -1110
- package/dist/loop/run-step.d.ts +0 -29
- package/dist/loop/run-step.js +0 -34
- package/dist/loop/run-to-terminal.d.ts +0 -66
- package/dist/loop/run-to-terminal.js +0 -90
- package/dist/loop/tool-mask.d.ts +0 -23
- package/dist/loop/tool-mask.js +0 -46
- package/dist/providers/streaming-chat.d.ts +0 -32
- package/dist/providers/streaming-chat.js +0 -91
- package/dist/tasks/derive-table-exec.d.ts +0 -54
- package/dist/tasks/derive-table-exec.js +0 -86
- package/dist/workflows/suspension.d.ts +0 -32
- package/dist/workflows/suspension.js +0 -38
package/dist/providers/ai-sdk.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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 {
|
|
17
|
-
import {
|
|
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
|
-
|
|
59
|
-
|
|
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
|
-
|
|
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 (!
|
|
145
|
+
if (!isUnknownArray(entries))
|
|
104
146
|
return [];
|
|
105
147
|
return entries.map((entry) => {
|
|
106
|
-
const
|
|
148
|
+
const record = parseUnknownRecord(entry);
|
|
107
149
|
const text = (key) => {
|
|
108
|
-
const value =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
295
|
-
cacheReadInputTokens: usage.inputTokenDetails
|
|
296
|
-
reasoningTokens: usage.outputTokenDetails
|
|
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
|
|
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
|
|
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
|
-
|
|
437
|
-
|
|
367
|
+
const thrownError = errorOf(error);
|
|
368
|
+
if (thrownError !== undefined)
|
|
369
|
+
return thrownError;
|
|
438
370
|
if (typeof error !== "object" || error === null)
|
|
439
|
-
return new Error(
|
|
440
|
-
const
|
|
441
|
-
const
|
|
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
|
-
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
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
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
-
/**
|
|
468
|
-
|
|
469
|
-
|
|
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
|
|
476
|
-
//
|
|
477
|
-
|
|
478
|
-
|
|
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.
|
|
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
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
//
|
|
493
|
-
|
|
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
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
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,
|
|
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
|
|
761
|
-
*
|
|
762
|
-
*
|
|
763
|
-
*
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
-
|
|
831
|
-
|
|
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
|
|
837
|
-
*
|
|
838
|
-
*
|
|
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,
|
|
843
|
-
*
|
|
844
|
-
* value on the returned instance. When the field is
|
|
845
|
-
*
|
|
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
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
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
|
-
|
|
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
|
-
|
|
916
|
-
|
|
917
|
-
|
|
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
|
|
929
|
-
//
|
|
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
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
786
|
+
maxOutputTokens: config.maxOutputTokens,
|
|
787
|
+
maxRetries: config.maxRetries,
|
|
788
|
+
requestTimeoutMs,
|
|
789
|
+
reasoning: config.reasoning,
|
|
945
790
|
});
|
|
946
791
|
}
|