@inflexa-ai/harness 0.45.1 → 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 +9 -3
- package/dist/agents/conversation-agent.js +34 -33
- 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 +12 -14
- package/dist/agents/sandbox/shared.js +18 -12
- package/dist/agents/sandbox/types.d.ts +4 -4
- 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 +2 -2
- package/dist/agents/sandbox-catalog.js +3 -3
- package/dist/agents/system-prompt.d.ts +2 -2
- 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 +123 -100
- 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 +6 -6
- 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 +38 -24
- package/dist/contracts/chat-frame.d.ts +15 -5
- package/dist/contracts/chat-frame.js +64 -41
- 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 +2 -2
- 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 +30 -16
- package/dist/contracts/schemas/chat-events.js +15 -6
- package/dist/contracts/schemas/chat-parts.d.ts +175 -102
- package/dist/contracts/schemas/chat-parts.js +33 -7
- 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 +5 -6
- package/dist/execution/dbos-workflow-purger.js +8 -7
- 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 +7 -7
- package/dist/execution/run-canceler.js +14 -7
- package/dist/execution/run-end-record.d.ts +2 -3
- 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 +17 -20
- package/dist/index.js +25 -36
- 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 +9 -9
- package/dist/loop/compaction.js +1 -1
- 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 +29 -38
- 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 -4
- package/dist/memory/conversation-display-recorder.js +43 -24
- 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 +36 -21
- package/dist/memory/thread-history.js +78 -54
- 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 +12 -12
- package/dist/prompts/briefing.js +1 -1
- 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 +1 -4
- package/dist/provenance/types.d.ts +6 -6
- package/dist/providers/ai-sdk.d.ts +113 -62
- package/dist/providers/ai-sdk.js +283 -518
- 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 +55 -94
- package/dist/reference-data/catalog.d.ts +2 -15
- package/dist/reference-data/catalog.js +25 -8
- 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 +211 -233
- 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.js +15 -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 +343 -298
- package/dist/schemas/file-metadata.js +2 -4
- package/dist/schemas/plan-schemas.d.ts +31 -31
- 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 +19 -19
- package/dist/schemas/workflow-state.js +2 -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 +32 -19
- package/dist/state/artifacts.js +28 -5
- 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 +4 -4
- package/dist/state/index.js +2 -2
- 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 +30 -19
- package/dist/state/runs.js +43 -51
- 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 +20 -8
- package/dist/state/step-executions.js +6 -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 +9 -9
- package/dist/tools/ad-hoc-router.js +65 -52
- 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 +9 -5
- package/dist/tools/capability-data.js +2 -1
- 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 +19 -10
- package/dist/tools/execute-analysis.js +83 -62
- package/dist/tools/knowledge/check.d.ts +166 -44
- package/dist/tools/knowledge/check.js +5 -3
- package/dist/tools/knowledge/client.d.ts +31 -62
- package/dist/tools/knowledge/client.js +44 -27
- package/dist/tools/knowledge/environment.d.ts +6 -6
- package/dist/tools/knowledge/environment.js +18 -7
- package/dist/tools/knowledge/index.d.ts +2 -2
- package/dist/tools/knowledge/index.js +9 -9
- package/dist/tools/knowledge/local-slots.d.ts +4 -4
- package/dist/tools/knowledge/local-slots.js +11 -4
- package/dist/tools/knowledge/pin.d.ts +2 -2
- package/dist/tools/knowledge/recommend.d.ts +20 -45
- package/dist/tools/knowledge/recommend.js +27 -19
- package/dist/tools/knowledge/situation.d.ts +40 -40
- package/dist/tools/knowledge/situation.js +2 -9
- package/dist/tools/knowledge/skeleton.d.ts +4 -4
- package/dist/tools/knowledge/skeleton.js +10 -11
- package/dist/tools/knowledge/template.d.ts +20 -18
- package/dist/tools/knowledge/template.js +38 -32
- 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 +16 -16
- package/dist/tools/research/generate-plan.js +410 -374
- package/dist/tools/research/guarded-address.js +3 -2
- 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 +2 -2
- package/dist/tools/research/searxng-engine.js +6 -4
- package/dist/tools/research/web-fetch.d.ts +24 -21
- package/dist/tools/research/web-fetch.js +65 -74
- package/dist/tools/research/web-search.d.ts +26 -17
- package/dist/tools/research/web-search.js +26 -21
- 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 +17 -8
- package/dist/tools/sandbox/list-available-packages.js +31 -25
- package/dist/tools/sandbox/list-available-refs.d.ts +17 -14
- package/dist/tools/sandbox/list-available-refs.js +61 -36
- package/dist/tools/sandbox/report-blocker.d.ts +30 -37
- package/dist/tools/sandbox/report-blocker.js +23 -73
- 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 +5 -2
- package/dist/tools/terminal-text.js +35 -3
- package/dist/tools/workspace/decision-record.d.ts +4 -4
- package/dist/tools/workspace/decision-record.js +23 -13
- package/dist/tools/workspace/edit-file.d.ts +59 -20
- package/dist/tools/workspace/edit-file.js +81 -16
- package/dist/tools/workspace/execute-command.d.ts +15 -13
- package/dist/tools/workspace/execute-command.js +11 -9
- 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/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 +46 -62
- package/dist/workflows/execute-analysis.js +137 -219
- package/dist/workflows/pause.d.ts +71 -0
- package/dist/workflows/pause.js +173 -0
- package/dist/workflows/sandbox-step.d.ts +38 -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 +21 -22
- package/dist/loop/call-guard.d.ts +0 -50
- package/dist/loop/call-guard.js +0 -90
- 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 -245
- package/dist/loop/run-agent.js +0 -1124
- 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 -93
- 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)}`;
|
|
@@ -108,55 +112,49 @@ function thinkingWithBinding(reasoning, mode) {
|
|
|
108
112
|
* because the AI SDK has no part for a model hop, and it drops the block from the
|
|
109
113
|
* content it returns (`anthropic-messages-language-model`, the `content_block_start`
|
|
110
114
|
* case). Thus the turn the harness holds is not the turn the API produced, and every
|
|
111
|
-
* signed thinking block of that turn is rejected from the next request on.
|
|
112
|
-
*
|
|
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.
|
|
113
127
|
*/
|
|
114
|
-
function fallbackModelOf(metadata) {
|
|
128
|
+
export function fallbackModelOf(metadata) {
|
|
115
129
|
const entries = metadata?.["anthropic"]?.["iterations"];
|
|
116
|
-
if (!
|
|
130
|
+
if (!isUnknownArray(entries))
|
|
117
131
|
return undefined;
|
|
118
132
|
for (const entry of entries) {
|
|
119
|
-
|
|
133
|
+
const record = parseUnknownRecord(entry);
|
|
134
|
+
if (record === undefined || !("type" in record))
|
|
120
135
|
continue;
|
|
121
|
-
|
|
122
|
-
if (fields["type"] !== "fallback_message")
|
|
136
|
+
if (record["type"] !== "fallback_message")
|
|
123
137
|
continue;
|
|
124
|
-
return typeof
|
|
138
|
+
return "model" in record && typeof record["model"] === "string" ? record["model"] : "";
|
|
125
139
|
}
|
|
126
140
|
return undefined;
|
|
127
141
|
}
|
|
128
|
-
/**
|
|
129
|
-
* The assistant message with no thinking block, and with `""` for content when it held
|
|
130
|
-
* nothing else. An empty message reaches no wire: `sanitizeMessages` drops it.
|
|
131
|
-
*/
|
|
132
|
-
function withoutThinking(message) {
|
|
133
|
-
if (typeof message.content === "string")
|
|
134
|
-
return message;
|
|
135
|
-
const content = message.content.filter((part) => part.type !== "reasoning" && part.type !== "reasoning-file");
|
|
136
|
-
if (content.length === message.content.length)
|
|
137
|
-
return message;
|
|
138
|
-
return content.length === 0 ? { ...message, content: "" } : { ...message, content };
|
|
139
|
-
}
|
|
140
142
|
/** Reads `providerMetadata.anthropic.inputTransformations`; empty for another vendor. */
|
|
141
143
|
function inputTransformationsOf(metadata) {
|
|
142
144
|
const entries = metadata?.["anthropic"]?.["inputTransformations"];
|
|
143
|
-
if (!
|
|
145
|
+
if (!isUnknownArray(entries))
|
|
144
146
|
return [];
|
|
145
147
|
return entries.map((entry) => {
|
|
146
|
-
const
|
|
148
|
+
const record = parseUnknownRecord(entry);
|
|
147
149
|
const text = (key) => {
|
|
148
|
-
const value =
|
|
150
|
+
const value = record?.[key];
|
|
149
151
|
return typeof value === "string" ? value : undefined;
|
|
150
152
|
};
|
|
151
153
|
return { type: text("type"), path: text("path"), reason: text("reason") };
|
|
152
154
|
});
|
|
153
155
|
}
|
|
154
156
|
function isAbortError(value) {
|
|
155
|
-
|
|
156
|
-
return true;
|
|
157
|
-
if (value instanceof Error && value.name === "AbortError")
|
|
158
|
-
return true;
|
|
159
|
-
return false;
|
|
157
|
+
return errorNameOf(value) === "AbortError";
|
|
160
158
|
}
|
|
161
159
|
/**
|
|
162
160
|
* Locate an `APICallError` on the throwable itself or one hop down its `cause`.
|
|
@@ -167,7 +165,9 @@ function isAbortError(value) {
|
|
|
167
165
|
function apiCallErrorOf(error) {
|
|
168
166
|
if (APICallError.isInstance(error))
|
|
169
167
|
return error;
|
|
170
|
-
|
|
168
|
+
if (error === null || typeof error !== "object" || !("cause" in error))
|
|
169
|
+
return undefined;
|
|
170
|
+
const cause = error.cause;
|
|
171
171
|
if (APICallError.isInstance(cause))
|
|
172
172
|
return cause;
|
|
173
173
|
return undefined;
|
|
@@ -282,8 +282,9 @@ export function failureOf(e, workload, suspendOn) {
|
|
|
282
282
|
* timeout. Without this guard the envelope would loop an expiry that the caller
|
|
283
283
|
* itself declared.
|
|
284
284
|
*/
|
|
285
|
-
export function createRetry(signal, logger, maxRetries, suspendOn, hookCall) {
|
|
285
|
+
export function createRetry(signal, logger, maxRetries, suspendOn, hookCall, onRetry) {
|
|
286
286
|
let retryCount = 0;
|
|
287
|
+
const requestId = randomUUID();
|
|
287
288
|
return retryWithExponentialBackoff({
|
|
288
289
|
maxRetries,
|
|
289
290
|
initialDelayInMs: RETRY_INITIAL_DELAY_MS,
|
|
@@ -294,6 +295,8 @@ export function createRetry(signal, logger, maxRetries, suspendOn, hookCall) {
|
|
|
294
295
|
const delayMs = computeRetryDelayMs(error, exponentialBackoffDelay);
|
|
295
296
|
retryCount += 1;
|
|
296
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 });
|
|
297
300
|
return delayMs;
|
|
298
301
|
},
|
|
299
302
|
createRetryError: ({ message, errors }) => {
|
|
@@ -315,9 +318,7 @@ export function createRetry(signal, logger, maxRetries, suspendOn, hookCall) {
|
|
|
315
318
|
* `@ai-sdk/openai-compatible` maps `prompt_tokens_details.cached_tokens` →
|
|
316
319
|
* `cacheReadTokens` (it never reports a write — that family caches
|
|
317
320
|
* server-side, with no billed write step). Reading the neutral field is
|
|
318
|
-
* therefore both correct and vendor-agnostic
|
|
319
|
-
* available under `providerMetadata.anthropic.usage` for debugging, in the
|
|
320
|
-
* vendor's own snake_case.
|
|
321
|
+
* therefore both correct and vendor-agnostic.
|
|
321
322
|
*
|
|
322
323
|
* `inputTokens` is the total billed prefix, cache reads included.
|
|
323
324
|
*
|
|
@@ -325,134 +326,24 @@ export function createRetry(signal, logger, maxRetries, suspendOn, hookCall) {
|
|
|
325
326
|
* count and is copied verbatim: providers disagree on whether reasoning tokens
|
|
326
327
|
* are already inside the output total, so the harness reconciles nothing.
|
|
327
328
|
*/
|
|
328
|
-
function toChatUsage(usage) {
|
|
329
|
+
export function toChatUsage(usage) {
|
|
329
330
|
if (usage === undefined)
|
|
330
331
|
return undefined;
|
|
331
332
|
return {
|
|
332
333
|
inputTokens: usage.inputTokens,
|
|
333
334
|
outputTokens: usage.outputTokens,
|
|
334
|
-
cacheCreationInputTokens: usage.inputTokenDetails
|
|
335
|
-
cacheReadInputTokens: usage.inputTokenDetails
|
|
336
|
-
reasoningTokens: usage.outputTokenDetails
|
|
335
|
+
cacheCreationInputTokens: usage.inputTokenDetails.cacheWriteTokens,
|
|
336
|
+
cacheReadInputTokens: usage.inputTokenDetails.cacheReadTokens,
|
|
337
|
+
reasoningTokens: usage.outputTokenDetails.reasoningTokens,
|
|
337
338
|
};
|
|
338
339
|
}
|
|
339
|
-
/** The id of the model bound into this provider — a bare id string is its own id. */
|
|
340
|
-
function requestedModelIdOf(model) {
|
|
341
|
-
return typeof model === "string" ? model : model.modelId;
|
|
342
|
-
}
|
|
343
|
-
/** The provider id of the model bound into this provider, as the AI SDK names it — a bare id string names no provider. */
|
|
344
|
-
function providerIdOf(model) {
|
|
345
|
-
return typeof model === "string" ? undefined : model.provider;
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Capture the served model id at the raw model boundary, because that is the
|
|
349
|
-
* only place it is still distinguishable from the requested one: `streamText`
|
|
350
|
-
* coalesces an unreported response model id to the bound model's own id, so
|
|
351
|
-
* reading `result.response.modelId` would silently republish the requested id
|
|
352
|
-
* as an endpoint's claim. A middleware sees the provider's
|
|
353
|
-
* result before that fallback applies, so "reported nothing" stays absent.
|
|
354
|
-
*
|
|
355
|
-
* Built per call, never per provider: one provider instance serves concurrent
|
|
356
|
-
* calls, and a shared mutable slot would hand one call another's answer. A bare
|
|
357
|
-
* model-id string has no wire result to observe, so it captures nothing.
|
|
358
|
-
*/
|
|
359
|
-
function captureServedModelId(model) {
|
|
360
|
-
if (typeof model === "string")
|
|
361
|
-
return { model, servedModelId: () => undefined };
|
|
362
|
-
let served;
|
|
363
|
-
const wrapped = wrapLanguageModel({
|
|
364
|
-
model,
|
|
365
|
-
middleware: {
|
|
366
|
-
wrapGenerate: async ({ doGenerate }) => {
|
|
367
|
-
const result = await doGenerate();
|
|
368
|
-
served = result.response?.modelId;
|
|
369
|
-
return result;
|
|
370
|
-
},
|
|
371
|
-
wrapStream: async ({ doStream }) => {
|
|
372
|
-
const result = await doStream();
|
|
373
|
-
return {
|
|
374
|
-
...result,
|
|
375
|
-
stream: result.stream.pipeThrough(new TransformStream({
|
|
376
|
-
transform(chunk, controller) {
|
|
377
|
-
if (chunk.type === "response-metadata" && chunk.modelId !== undefined)
|
|
378
|
-
served = chunk.modelId;
|
|
379
|
-
controller.enqueue(chunk);
|
|
380
|
-
},
|
|
381
|
-
})),
|
|
382
|
-
};
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
});
|
|
386
|
-
return { model: wrapped, servedModelId: () => served };
|
|
387
|
-
}
|
|
388
|
-
function responseFromMessages(input) {
|
|
389
|
-
const { messages, fallbackText, finishReason, rawFinishReason, requestedModelId, servedModelId, provider } = input;
|
|
390
|
-
const usage = toChatUsage(input.usage);
|
|
391
|
-
const message = [...messages].reverse().find((m) => m.role === "assistant");
|
|
392
|
-
if (message === undefined) {
|
|
393
|
-
return { message: { role: "assistant", content: fallbackText }, finishReason, rawFinishReason, usage, requestedModelId, servedModelId, provider };
|
|
394
|
-
}
|
|
395
|
-
return { message, finishReason, rawFinishReason, usage, requestedModelId, servedModelId, provider };
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Drop empty text parts — and messages left with no content at all — before
|
|
399
|
-
* the wire call. The Anthropic Messages API rejects any request containing an
|
|
400
|
-
* empty text block, and the SDK's own response assembly legitimately produces
|
|
401
|
-
* them: a turn that goes straight to tool calls yields an assistant message
|
|
402
|
-
* carrying a ""-text part, which the agent loop then echoes back as history
|
|
403
|
-
* on its next request. Filtering once at the outbound boundary covers every
|
|
404
|
-
* source at once — loop echo, stored thread history, legacy backfill, and the
|
|
405
|
-
* empty-string fallback in `responseFromMessages`.
|
|
406
|
-
*/
|
|
407
|
-
function sanitizeMessages(messages) {
|
|
408
|
-
const out = [];
|
|
409
|
-
for (const m of messages) {
|
|
410
|
-
if (typeof m.content === "string") {
|
|
411
|
-
if (m.content !== "")
|
|
412
|
-
out.push(m);
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
const parts = m.content.filter((p) => p.type !== "text" || p.text !== "");
|
|
416
|
-
// The filtered parts are a subset of this message's own content, so the
|
|
417
|
-
// message remains valid for its role — the cast only re-associates the
|
|
418
|
-
// narrowed array with the union member TS can no longer correlate.
|
|
419
|
-
if (parts.length > 0)
|
|
420
|
-
out.push({ ...m, content: parts });
|
|
421
|
-
}
|
|
422
|
-
return out;
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* Advance the SDK stream to the next text delta.
|
|
426
|
-
*
|
|
427
|
-
* The full stream carries one part for each event of a turn, and only a text
|
|
428
|
-
* part reaches the consumer of the harness. Thus the pull skips each other part.
|
|
429
|
-
* The `abort` part stops the pull, because the SDK closes the stream directly
|
|
430
|
-
* after it. Thus a timeout can never end the stream in silence with the text
|
|
431
|
-
* that arrived before it.
|
|
432
|
-
*/
|
|
433
|
-
async function pullNextDelta(iterator) {
|
|
434
|
-
for (let next = await iterator.next(); next.done !== true; next = await iterator.next()) {
|
|
435
|
-
const part = next.value;
|
|
436
|
-
if (part.type === "text-delta")
|
|
437
|
-
return { kind: "delta", text: part.text };
|
|
438
|
-
if (part.type === "abort")
|
|
439
|
-
return { kind: "aborted", reason: part.reason };
|
|
440
|
-
// The SDK reports a wire failure as a part, not as a rejection, and it
|
|
441
|
-
// then closes the stream. Skipping it would turn a failed call into an
|
|
442
|
-
// empty assistant turn that the loop reads as a real answer.
|
|
443
|
-
if (part.type === "error")
|
|
444
|
-
return { kind: "failed", error: part.error };
|
|
445
|
-
}
|
|
446
|
-
return { kind: "end" };
|
|
447
|
-
}
|
|
448
340
|
/**
|
|
449
341
|
* The HTTP status that each Anthropic stream error type stands for.
|
|
450
342
|
*
|
|
451
343
|
* A provider names a mid-stream failure in the payload, not in the status line:
|
|
452
344
|
* a stream that carries `overloaded_error` reports the condition that a 529
|
|
453
345
|
* names on the non-streaming wire. The classifier reads the status alone, thus
|
|
454
|
-
* the part has to reach it as an error that names one
|
|
455
|
-
* would classify one way on `chat` and another way on `chatStream`.
|
|
346
|
+
* the part has to reach it as an error that names one.
|
|
456
347
|
*/
|
|
457
348
|
const STREAM_ERROR_STATUS = {
|
|
458
349
|
invalid_request_error: 400,
|
|
@@ -466,20 +357,20 @@ const STREAM_ERROR_STATUS = {
|
|
|
466
357
|
overloaded_error: 529,
|
|
467
358
|
};
|
|
468
359
|
/**
|
|
469
|
-
* The failure that an `error` part of the
|
|
360
|
+
* The failure that an `error` part of the model stream stands for.
|
|
470
361
|
*
|
|
471
362
|
* The part carries whatever the provider put on the wire, and that is often a
|
|
472
363
|
* bare object rather than an `Error`. Left as it is, it reaches the message as
|
|
473
364
|
* `[object Object]` and reaches the classifier with no status at all.
|
|
474
365
|
*/
|
|
475
366
|
function streamPartFailure(error) {
|
|
476
|
-
|
|
477
|
-
|
|
367
|
+
const thrownError = errorOf(error);
|
|
368
|
+
if (thrownError !== undefined)
|
|
369
|
+
return thrownError;
|
|
478
370
|
if (typeof error !== "object" || error === null)
|
|
479
|
-
return new Error(
|
|
480
|
-
const
|
|
481
|
-
const
|
|
482
|
-
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;
|
|
483
374
|
const failure = new Error(message ?? type ?? "The provider reported a stream error.", { cause: error });
|
|
484
375
|
const status = type === undefined ? undefined : STREAM_ERROR_STATUS[type];
|
|
485
376
|
// `extractStatus` walks the chain for this field, thus the named condition
|
|
@@ -489,344 +380,215 @@ function streamPartFailure(error) {
|
|
|
489
380
|
return failure;
|
|
490
381
|
}
|
|
491
382
|
/**
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
* the reason of that signal rides out, and the cancellation path applies
|
|
497
|
-
* unchanged. Otherwise the SDK chunk bound stopped the stream, and the sentinel
|
|
498
|
-
* 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.
|
|
499
387
|
*/
|
|
500
|
-
function
|
|
501
|
-
|
|
502
|
-
return signal.reason;
|
|
503
|
-
if (requestTimeoutMs !== undefined)
|
|
504
|
-
return new RequestTimeoutError(requestTimeoutMs);
|
|
505
|
-
return new Error(reason ?? "The provider aborted the stream.");
|
|
388
|
+
function isOutputPart(part) {
|
|
389
|
+
return part.type !== "stream-start" && part.type !== "response-metadata" && part.type !== "raw";
|
|
506
390
|
}
|
|
507
|
-
/**
|
|
508
|
-
|
|
509
|
-
|
|
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.
|
|
395
|
+
*/
|
|
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
|
+
};
|
|
432
|
+
}
|
|
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
|
+
};
|
|
510
547
|
}
|
|
511
548
|
export function createAiSdkProvider(deps) {
|
|
512
549
|
const capabilities = {
|
|
513
550
|
toolCalling: deps.capabilities?.toolCalling ?? true,
|
|
514
551
|
// Propagate a picture flag only when the caller states it. An absent
|
|
515
|
-
// flag stays absent, thus the loop
|
|
516
|
-
//
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
...(deps.capabilities?.contextWindow !== undefined ? { contextWindow: deps.capabilities.contextWindow } : {}),
|
|
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,
|
|
520
556
|
};
|
|
521
557
|
const logger = (deps.logger ?? createNoopLogger()).named("providers.ai-sdk");
|
|
522
558
|
const maxOutputTokens = deps.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS;
|
|
523
559
|
// The sentinel hands the SDK no ceiling, thus the request carries none and the
|
|
524
|
-
// server enforces the cap of the model.
|
|
525
|
-
// stream, thus the two cannot disagree about the ceiling of a request.
|
|
560
|
+
// server enforces the cap of the model.
|
|
526
561
|
const outputCeiling = maxOutputTokens === "provider-maximum" ? {} : { maxOutputTokens };
|
|
527
562
|
const maxRetries = deps.maxRetries ?? RETRY_MAX_RETRIES;
|
|
528
563
|
const suspendOn = deps.suspendOn ?? DEFAULT_SUSPEND_ON;
|
|
529
564
|
const requestTimeoutMs = deps.requestTimeoutMs;
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
//
|
|
534
|
-
|
|
535
|
-
// instead of the global registry, so the harness never traces the embedder's
|
|
536
|
-
// own AI SDK calls. Of the SDK spans only `chat` is written. The operation
|
|
537
|
-
// span and the step span around it repeat what `chat` and the span of the
|
|
538
|
-
// caller (the loop's `invoke_agent`) say already. Thus they pass through, and
|
|
539
|
-
// `chat` attaches to the span of the caller.
|
|
540
|
-
const tracer = passThroughTracer(trace.getTracer("gen_ai"), (_name, options) => isSdkWrapperSpan(options.attributes?.["gen_ai.operation.name"]));
|
|
541
|
-
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 };
|
|
542
570
|
routeSdkWarningsTo(logger);
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
/**
|
|
560
|
-
* Logs each dropped thinking block; the drop does not fail the call.
|
|
561
|
-
* `reason` is `prefix_binding_mismatch` or `model_binding_mismatch`.
|
|
562
|
-
*/
|
|
563
|
-
function logDroppedThinkingBlocks(session, metadata) {
|
|
564
|
-
for (const drop of inputTransformationsOf(metadata)) {
|
|
565
|
-
logger.warn("thinking block dropped", { workload: workloadOf(session), type: drop.type, path: drop.path, reason: drop.reason });
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* The reply as the harness must hold it when a fallback model served it: with no
|
|
570
|
-
* thinking block, and with the model that answered named.
|
|
571
|
-
*
|
|
572
|
-
* A reply that carries a fallback hop ({@link fallbackModelOf}) reaches the harness
|
|
573
|
-
* already short of the `fallback` content block the API put in the turn. The API holds
|
|
574
|
-
* the whole turn against the signature of each of its thinking blocks, so echoing that
|
|
575
|
-
* turn earns `thinking ... blocks in the latest assistant message cannot be modified`,
|
|
576
|
-
* which is a 400 that no retry can pass. The conversation is then dead: the loop sends
|
|
577
|
-
* its history on every request, and nothing downstream can repair a turn.
|
|
578
|
-
*
|
|
579
|
-
* A thinking block is optional on the way back, thus the reply without them is a valid
|
|
580
|
-
* turn, and the next request continues. The cost is the reasoning of this one turn and
|
|
581
|
-
* the cache write that its new prefix pays for. A reply of nothing but thinking carries
|
|
582
|
-
* no part at all, and `sanitizeMessages` drops such a message from the next request.
|
|
583
|
-
*
|
|
584
|
-
* `servedModelId` needs the same correction. {@link captureServedModelId} reads the id
|
|
585
|
-
* the response metadata of the package carries, which is `message_start.message.model`,
|
|
586
|
-
* and that field keeps the REQUESTED model across a hop. Published as it stands, it
|
|
587
|
-
* makes the usage ledger of an embedder attribute the tokens to the model that refused
|
|
588
|
-
* the work. The iteration names the model that answered, thus it wins. An iteration that
|
|
589
|
-
* names no model changes nothing: there is no better id to publish, and the record above
|
|
590
|
-
* is then the only account of the hop.
|
|
591
|
-
*/
|
|
592
|
-
function settleFallbackReply(session, response, metadata) {
|
|
593
|
-
const servedBy = fallbackModelOf(metadata);
|
|
594
|
-
if (servedBy === undefined)
|
|
595
|
-
return response;
|
|
596
|
-
logger.warn("reply served by a fallback model, thus the harness drops the thinking of that turn", {
|
|
597
|
-
workload: workloadOf(session),
|
|
598
|
-
...(servedBy === "" ? {} : { servedBy }),
|
|
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
|
+
}),
|
|
599
585
|
});
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
message: withoutThinking(response.message),
|
|
603
|
-
...(servedBy === "" ? {} : { servedModelId: servedBy }),
|
|
604
|
-
};
|
|
605
|
-
}
|
|
606
|
-
function chat(req, session, signal) {
|
|
607
|
-
const reasoning = effortOf(req);
|
|
608
|
-
const providerOptions = deps.providerOptionsFor?.({ session, reasoning });
|
|
609
|
-
const run = async () => {
|
|
610
|
-
const hookCall = { unsettled: false };
|
|
611
|
-
const retry = createRetry(signal, logger, maxRetries, suspendOn, hookCall);
|
|
612
|
-
const capture = captureServedModelId(deps.model);
|
|
613
|
-
try {
|
|
614
|
-
const collected = await retry(async () => {
|
|
615
|
-
// The hook runs before each attempt: a host header can be
|
|
616
|
-
// time-limited, and the retry window can last minutes.
|
|
617
|
-
const headers = await headersForAttempt(deps.resolveRequestHeaders, session, hookCall);
|
|
618
|
-
// The call streams on the wire and collapses below.
|
|
619
|
-
//
|
|
620
|
-
// A non-streaming turn sends no header until the model completes,
|
|
621
|
-
// thus the `headersTimeout` of the host HTTP client bounds the whole
|
|
622
|
-
// generation. No option of the SDK lifts that bound, because it sits
|
|
623
|
-
// under the fetch. Node defaults the field to 300s, and a turn near
|
|
624
|
-
// 18k output tokens reaches it, while `DEFAULT_MAX_OUTPUT_TOKENS`
|
|
625
|
-
// asks for up to 64k. A cut turn then costs twice: the envelope
|
|
626
|
-
// starts the same generation again from zero.
|
|
627
|
-
//
|
|
628
|
-
// Anthropic states the rule for its own SDKs: a large `max_tokens`
|
|
629
|
-
// makes streaming necessary, to prevent an HTTP timeout. Thus a
|
|
630
|
-
// ceiling this size streams whether or not a consumer wants the
|
|
631
|
-
// deltas, and `chatStream` stays the seam that forwards them.
|
|
632
|
-
const result = streamText({
|
|
633
|
-
model: capture.model,
|
|
634
|
-
system: req.system,
|
|
635
|
-
messages: sanitizeMessages(req.messages),
|
|
636
|
-
tools: req.tools,
|
|
637
|
-
toolChoice: req.toolChoice ?? "auto",
|
|
638
|
-
...outputCeiling,
|
|
639
|
-
stopWhen: [],
|
|
640
|
-
// The harness envelope owns retries; leaving the SDK default in
|
|
641
|
-
// place would multiply attempts (10 outer × 3 inner).
|
|
642
|
-
maxRetries: 0,
|
|
643
|
-
headers,
|
|
644
|
-
abortSignal: signal,
|
|
645
|
-
telemetry,
|
|
646
|
-
// `firstChunkMs` bounds the wait for the first content chunk,
|
|
647
|
-
// and `chunkMs` bounds each later gap. Thus each silent interval
|
|
648
|
-
// carries the one configured bound, and a turn that writes
|
|
649
|
-
// steadily runs as long as it needs.
|
|
650
|
-
...(requestTimeoutMs !== undefined ? { timeout: { firstChunkMs: requestTimeoutMs, chunkMs: requestTimeoutMs } } : {}),
|
|
651
|
-
providerOptions,
|
|
652
|
-
reasoning,
|
|
653
|
-
});
|
|
654
|
-
// The drain sits inside the retried closure, thus a failure at any
|
|
655
|
-
// point of the stream re-runs the whole attempt and the envelope
|
|
656
|
-
// keeps its whole-call scope. No delta reaches a consumer here —
|
|
657
|
-
// `chatStream` is the seam that forwards them.
|
|
658
|
-
const iterator = result.fullStream[Symbol.asyncIterator]();
|
|
659
|
-
let text = "";
|
|
660
|
-
for (let pull = await pullNextDelta(iterator); pull.kind !== "end"; pull = await pullNextDelta(iterator)) {
|
|
661
|
-
// A caller abort rides out as the reason of its own signal, thus
|
|
662
|
-
// it stays a cancellation and reaches the caller as a throw.
|
|
663
|
-
if (pull.kind === "aborted")
|
|
664
|
-
throw abortedStreamFailure(signal, pull.reason, requestTimeoutMs);
|
|
665
|
-
if (pull.kind === "failed")
|
|
666
|
-
throw streamPartFailure(pull.error);
|
|
667
|
-
text += pull.text;
|
|
668
|
-
}
|
|
669
|
-
// These promises settle only once the stream is fully drained, thus
|
|
670
|
-
// the loop above must reach its end before this point.
|
|
671
|
-
return {
|
|
672
|
-
messages: await result.responseMessages,
|
|
673
|
-
fallbackText: text,
|
|
674
|
-
finishReason: await result.finishReason,
|
|
675
|
-
rawFinishReason: await result.rawFinishReason,
|
|
676
|
-
usage: await result.usage,
|
|
677
|
-
providerMetadata: (await result.finalStep).providerMetadata,
|
|
678
|
-
};
|
|
679
|
-
});
|
|
680
|
-
// Logged past the envelope, thus only the attempt that succeeded
|
|
681
|
-
// reports its drops.
|
|
682
|
-
const { providerMetadata: metadata, ...reply } = collected;
|
|
683
|
-
logDroppedThinkingBlocks(session, metadata);
|
|
684
|
-
return ok(settleFallbackReply(session, responseFromMessages({
|
|
685
|
-
...reply,
|
|
686
|
-
requestedModelId,
|
|
687
|
-
// Read after the drain: the metadata chunk that carries the
|
|
688
|
-
// served id reaches the capture only as the stream is consumed.
|
|
689
|
-
servedModelId: capture.servedModelId(),
|
|
690
|
-
provider: providerId,
|
|
691
|
-
}), metadata));
|
|
692
|
-
}
|
|
693
|
-
catch (e) {
|
|
694
|
-
if (isAbortError(e) || signal?.aborted || hookCall.unsettled)
|
|
695
|
-
throw e;
|
|
696
|
-
const failure = failureOf(e, workloadOf(session), suspendOn);
|
|
697
|
-
logFailure(session, failure, e);
|
|
698
|
-
return err(failure);
|
|
699
|
-
}
|
|
700
|
-
};
|
|
701
|
-
return new ResultAsync(run());
|
|
702
|
-
}
|
|
703
|
-
async function* chatStream(req, session, signal) {
|
|
704
|
-
const reasoning = effortOf(req);
|
|
705
|
-
const providerOptions = deps.providerOptionsFor?.({ session, reasoning });
|
|
706
|
-
const hookCall = { unsettled: false };
|
|
707
|
-
const retry = createRetry(signal, logger, maxRetries, suspendOn, hookCall);
|
|
708
|
-
const capture = captureServedModelId(deps.model);
|
|
709
|
-
try {
|
|
710
|
-
// Retry covers only stream establishment: streamText defers wire errors
|
|
711
|
-
// to consumption, so a failure is not visible until the stream is read.
|
|
712
|
-
// The retried closure resolves to one of two outcomes — the stream is
|
|
713
|
-
// live with a first delta in hand, or it finished without yielding any
|
|
714
|
-
// text — and a delta is only ever yielded OUTSIDE the closure, so a
|
|
715
|
-
// retried attempt can never re-emit a delta the consumer already saw.
|
|
716
|
-
const opened = await retry(async () => {
|
|
717
|
-
const headers = await headersForAttempt(deps.resolveRequestHeaders, session, hookCall);
|
|
718
|
-
const result = streamText({
|
|
719
|
-
model: capture.model,
|
|
720
|
-
system: req.system,
|
|
721
|
-
messages: sanitizeMessages(req.messages),
|
|
722
|
-
tools: req.tools,
|
|
723
|
-
toolChoice: req.toolChoice ?? "auto",
|
|
724
|
-
...outputCeiling,
|
|
725
|
-
stopWhen: [],
|
|
726
|
-
maxRetries: 0,
|
|
727
|
-
headers,
|
|
728
|
-
abortSignal: signal,
|
|
729
|
-
telemetry,
|
|
730
|
-
// The fetch guard bounds the wait until the headers. Past the
|
|
731
|
-
// headers the SDK owns two bounds: `firstChunkMs` covers the wait
|
|
732
|
-
// for the first content chunk, and `chunkMs` covers each later
|
|
733
|
-
// gap. The two take the same value, thus each silent interval of
|
|
734
|
-
// the stream has the one configured bound. A chunk that carries
|
|
735
|
-
// no content, for example a keep-alive comment, produces no part,
|
|
736
|
-
// thus it feeds neither bound.
|
|
737
|
-
...(requestTimeoutMs !== undefined ? { timeout: { firstChunkMs: requestTimeoutMs, chunkMs: requestTimeoutMs } } : {}),
|
|
738
|
-
providerOptions,
|
|
739
|
-
reasoning,
|
|
740
|
-
});
|
|
741
|
-
const iterator = result.fullStream[Symbol.asyncIterator]();
|
|
742
|
-
const first = await pullNextDelta(iterator);
|
|
743
|
-
// The chunk bound can stop the stream before any content arrives. The
|
|
744
|
-
// throw carries the sentinel, thus the envelope gives the attempt a
|
|
745
|
-
// fresh window under the retry policy of a connection error.
|
|
746
|
-
if (first.kind === "aborted")
|
|
747
|
-
throw abortedStreamFailure(signal, first.reason, requestTimeoutMs);
|
|
748
|
-
if (first.kind === "failed")
|
|
749
|
-
throw streamPartFailure(first.error);
|
|
750
|
-
if (first.kind === "end") {
|
|
751
|
-
// A doStream promise rejection — the shape a real connection
|
|
752
|
-
// failure takes — does NOT surface at this first pull: streamText
|
|
753
|
-
// resolves it `{ done: true }` and defers the rejection to the
|
|
754
|
-
// deferred result promises. Awaiting them here brings that failure
|
|
755
|
-
// inside the retry envelope so a text-less establishment error is
|
|
756
|
-
// retried; a genuine text-less turn resolves them, and the terminal
|
|
757
|
-
// event is built from these already-resolved values without a
|
|
758
|
-
// second await. (These promises only settle once the stream is
|
|
759
|
-
// fully drained, so they can be awaited here only because the pull
|
|
760
|
-
// already reported the stream done.)
|
|
761
|
-
return {
|
|
762
|
-
kind: "completed",
|
|
763
|
-
messages: await result.responseMessages,
|
|
764
|
-
finishReason: await result.finishReason,
|
|
765
|
-
rawFinishReason: await result.rawFinishReason,
|
|
766
|
-
usage: await result.usage,
|
|
767
|
-
providerMetadata: (await result.finalStep).providerMetadata,
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
return { kind: "streaming", result, iterator, firstDelta: first.text };
|
|
771
|
-
});
|
|
772
|
-
if (opened.kind === "completed") {
|
|
773
|
-
logDroppedThinkingBlocks(session, opened.providerMetadata);
|
|
774
|
-
const response = settleFallbackReply(session, responseFromMessages({
|
|
775
|
-
messages: opened.messages,
|
|
776
|
-
fallbackText: "",
|
|
777
|
-
finishReason: opened.finishReason,
|
|
778
|
-
rawFinishReason: opened.rawFinishReason,
|
|
779
|
-
usage: opened.usage,
|
|
780
|
-
requestedModelId,
|
|
781
|
-
servedModelId: capture.servedModelId(),
|
|
782
|
-
provider: providerId,
|
|
783
|
-
}), opened.providerMetadata);
|
|
784
|
-
yield { type: "done", response };
|
|
785
|
-
return;
|
|
786
|
-
}
|
|
787
|
-
const { result, iterator, firstDelta } = opened;
|
|
788
|
-
let text = firstDelta;
|
|
789
|
-
yield { type: "text-delta", text: firstDelta };
|
|
790
|
-
// Drain the same iterator: past the first delta, errors propagate
|
|
791
|
-
// unchanged (no retry, no re-emit).
|
|
792
|
-
for (let pull = await pullNextDelta(iterator); pull.kind !== "end"; pull = await pullNextDelta(iterator)) {
|
|
793
|
-
// A mid-stream abort ends the turn with an error, never with the
|
|
794
|
-
// partial text that arrived before it. The catch below builds the
|
|
795
|
-
// terminal `ProviderError` from the throwable.
|
|
796
|
-
if (pull.kind === "aborted")
|
|
797
|
-
throw abortedStreamFailure(signal, pull.reason, requestTimeoutMs);
|
|
798
|
-
if (pull.kind === "failed")
|
|
799
|
-
throw streamPartFailure(pull.error);
|
|
800
|
-
text += pull.text;
|
|
801
|
-
yield { type: "text-delta", text: pull.text };
|
|
802
|
-
}
|
|
803
|
-
const metadata = (await result.finalStep).providerMetadata;
|
|
804
|
-
const response = settleFallbackReply(session, responseFromMessages({
|
|
805
|
-
messages: await result.responseMessages,
|
|
806
|
-
fallbackText: text,
|
|
807
|
-
finishReason: await result.finishReason,
|
|
808
|
-
rawFinishReason: await result.rawFinishReason,
|
|
809
|
-
usage: await result.usage,
|
|
810
|
-
requestedModelId,
|
|
811
|
-
// Read after the drain: the metadata chunk carrying the served id
|
|
812
|
-
// reaches the capture only as the stream is consumed.
|
|
813
|
-
servedModelId: capture.servedModelId(),
|
|
814
|
-
provider: providerId,
|
|
815
|
-
}), metadata);
|
|
816
|
-
logDroppedThinkingBlocks(session, metadata);
|
|
817
|
-
yield { type: "done", response };
|
|
818
|
-
}
|
|
819
|
-
catch (e) {
|
|
820
|
-
if (isAbortError(e) || signal?.aborted || hookCall.unsettled)
|
|
821
|
-
throw e;
|
|
822
|
-
const failure = failureOf(e, workloadOf(session), suspendOn);
|
|
823
|
-
logFailure(session, failure, e);
|
|
824
|
-
throw failure;
|
|
825
|
-
}
|
|
586
|
+
const providerOptions = deps.providerOptionsFor?.({ session: call.session, reasoning });
|
|
587
|
+
return { model, settings: { ...outputCeiling, reasoning, providerOptions }, telemetry };
|
|
826
588
|
}
|
|
827
589
|
// The provider advertises the guard limit on its own instance, thus a
|
|
828
590
|
// consumer that scales a deadline reads it from the provider in its deps.
|
|
829
|
-
return { capabilities,
|
|
591
|
+
return { capabilities, bind, requestTimeoutMs };
|
|
830
592
|
}
|
|
831
593
|
/**
|
|
832
594
|
* Wrap a fetch so that the wait until the response starts does not exceed
|
|
@@ -837,24 +599,23 @@ export function createAiSdkProvider(deps) {
|
|
|
837
599
|
* signal through `AbortSignal.any`. Thus the caller signal keeps its normal
|
|
838
600
|
* effect, and a caller abort stays a cancellation.
|
|
839
601
|
*
|
|
840
|
-
* The guard bounds the response start only. The
|
|
841
|
-
*
|
|
842
|
-
*
|
|
843
|
-
*
|
|
844
|
-
* 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.
|
|
845
606
|
*
|
|
846
607
|
* When the field is absent, `createConfiguredAiSdkProvider` installs no wrapper,
|
|
847
608
|
* and the behavior stays byte-identical.
|
|
848
609
|
*/
|
|
849
610
|
export function wrapFetchWithRequestTimeout(fetchImpl, requestTimeoutMs) {
|
|
850
|
-
return async (input, init) => {
|
|
611
|
+
return Object.assign(async (input, init) => {
|
|
851
612
|
const controller = new AbortController();
|
|
852
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.
|
|
853
615
|
const timer = setTimeout(() => controller.abort(new RequestTimeoutError(requestTimeoutMs)), requestTimeoutMs);
|
|
854
616
|
// The harness runs on Node, where a timer has `unref`. Unref the guard
|
|
855
617
|
// timer, thus an armed guard does not keep a short-lived process alive.
|
|
856
|
-
|
|
857
|
-
timer.unref?.();
|
|
618
|
+
timer.unref();
|
|
858
619
|
const clear = () => {
|
|
859
620
|
clearTimeout(timer);
|
|
860
621
|
// The harness runs on Node, where a caller signal can outlive one fetch
|
|
@@ -874,7 +635,7 @@ export function wrapFetchWithRequestTimeout(fetchImpl, requestTimeoutMs) {
|
|
|
874
635
|
// is inert there. A probe on Bun 1.4.2 proved both results: the cut fired
|
|
875
636
|
// at 360 seconds, because Bun pads the timer to its minute wheel, and a
|
|
876
637
|
// request with the key completed after 420 seconds. The `RequestInit` type
|
|
877
|
-
// declares no such member, thus the
|
|
638
|
+
// declares no such member, thus the wider annotation.
|
|
878
639
|
const forwarded = { ...init, signal, timeout: false };
|
|
879
640
|
try {
|
|
880
641
|
return await fetchImpl(input, forwarded);
|
|
@@ -882,7 +643,10 @@ export function wrapFetchWithRequestTimeout(fetchImpl, requestTimeoutMs) {
|
|
|
882
643
|
finally {
|
|
883
644
|
clear();
|
|
884
645
|
}
|
|
885
|
-
}
|
|
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 });
|
|
886
650
|
}
|
|
887
651
|
/**
|
|
888
652
|
* Bind one explicit `store` directive onto each call of a model.
|
|
@@ -898,7 +662,7 @@ function withStoreDirective(model, store) {
|
|
|
898
662
|
return wrapLanguageModel({
|
|
899
663
|
model,
|
|
900
664
|
middleware: {
|
|
901
|
-
transformParams:
|
|
665
|
+
transformParams: ({ params }) => Promise.resolve({
|
|
902
666
|
...params,
|
|
903
667
|
providerOptions: { ...params.providerOptions, openai: { ...params.providerOptions?.openai, store } },
|
|
904
668
|
}),
|
|
@@ -907,22 +671,21 @@ function withStoreDirective(model, store) {
|
|
|
907
671
|
}
|
|
908
672
|
export function hostPolicyOf(deps) {
|
|
909
673
|
return {
|
|
910
|
-
|
|
911
|
-
|
|
674
|
+
resolveRequestHeaders: deps.resolveRequestHeaders,
|
|
675
|
+
suspendOn: deps.suspendOn,
|
|
912
676
|
};
|
|
913
677
|
}
|
|
914
678
|
/**
|
|
915
679
|
* Realize an `AiSdkProviderConfig` into a `ChatProvider` bound to that config's
|
|
916
|
-
* connection and model. The model is closed into the returned provider here
|
|
917
|
-
*
|
|
918
|
-
*
|
|
919
|
-
* 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.
|
|
920
683
|
*
|
|
921
684
|
* When the config sets `requestTimeoutMs`, the provider wraps the effective fetch
|
|
922
|
-
* (`config.fetch ?? globalThis.fetch`) with the response-start guard,
|
|
923
|
-
*
|
|
924
|
-
* value on the returned instance. When the field is
|
|
925
|
-
*
|
|
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.
|
|
926
689
|
*/
|
|
927
690
|
export function createConfiguredAiSdkProvider(deps) {
|
|
928
691
|
const config = deps.config;
|
|
@@ -950,16 +713,16 @@ export function createConfiguredAiSdkProvider(deps) {
|
|
|
950
713
|
...hostPolicyOf(deps),
|
|
951
714
|
capabilities: { ...pictureDefault, ...config.capabilities },
|
|
952
715
|
logger: deps.logger,
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
716
|
+
maxOutputTokens: config.maxOutputTokens,
|
|
717
|
+
maxRetries: config.maxRetries,
|
|
718
|
+
requestTimeoutMs,
|
|
719
|
+
reasoning: config.reasoning,
|
|
957
720
|
// The package sends the key as `metadata.user_id`, and the binding as
|
|
958
721
|
// `thinking.block_binding`.
|
|
959
722
|
providerOptionsFor: ({ session, reasoning }) => ({
|
|
960
723
|
anthropic: {
|
|
961
724
|
metadata: { userId: sessionKeyDigestOf(session) },
|
|
962
|
-
|
|
725
|
+
thinking: binding === undefined ? undefined : thinkingWithBinding(reasoning, binding),
|
|
963
726
|
},
|
|
964
727
|
}),
|
|
965
728
|
});
|
|
@@ -992,9 +755,9 @@ export function createConfiguredAiSdkProvider(deps) {
|
|
|
992
755
|
// unset config sends no ceiling, and the server holds the reply at the
|
|
993
756
|
// cap of the model.
|
|
994
757
|
maxOutputTokens: config.maxOutputTokens ?? "provider-maximum",
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
758
|
+
maxRetries: config.maxRetries,
|
|
759
|
+
requestTimeoutMs,
|
|
760
|
+
reasoning: config.reasoning,
|
|
998
761
|
// The package sends the key as `prompt_cache_key`. The store
|
|
999
762
|
// directive merges into the same namespace, and it keeps this key.
|
|
1000
763
|
providerOptionsFor: ({ session }) => ({ openai: { promptCacheKey: sessionKeyDigestOf(session) } }),
|
|
@@ -1005,10 +768,12 @@ export function createConfiguredAiSdkProvider(deps) {
|
|
|
1005
768
|
baseURL: config.baseURL,
|
|
1006
769
|
apiKey: config.apiKey,
|
|
1007
770
|
fetch: effectiveFetch,
|
|
1008
|
-
// Each call of the provider streams
|
|
1009
|
-
//
|
|
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.
|
|
1010
773
|
includeUsage: true,
|
|
774
|
+
supportsMultiPartToolContent: config.supportsMultiPartToolContent,
|
|
1011
775
|
});
|
|
776
|
+
const pictureDefault = config.supportsMultiPartToolContent === true ? { imageToolResults: true } : {};
|
|
1012
777
|
// The compatible wire has no standard field for a session key, thus this arm
|
|
1013
778
|
// gives no provider options of its own.
|
|
1014
779
|
return createAiSdkProvider({
|
|
@@ -1016,11 +781,11 @@ export function createConfiguredAiSdkProvider(deps) {
|
|
|
1016
781
|
// the seam needs no middleware to carry the depth into its namespace.
|
|
1017
782
|
model: provider.chatModel(config.model),
|
|
1018
783
|
...hostPolicyOf(deps),
|
|
1019
|
-
capabilities: config.capabilities,
|
|
784
|
+
capabilities: { ...pictureDefault, ...config.capabilities },
|
|
1020
785
|
logger: deps.logger,
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
786
|
+
maxOutputTokens: config.maxOutputTokens,
|
|
787
|
+
maxRetries: config.maxRetries,
|
|
788
|
+
requestTimeoutMs,
|
|
789
|
+
reasoning: config.reasoning,
|
|
1025
790
|
});
|
|
1026
791
|
}
|