@sema-agent/core 7.47.0 → 7.49.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/CHANGELOG.md +472 -0
- package/README.md +2 -2
- package/dist/agents/cascade.d.ts +2 -5
- package/dist/agents/child-failure.d.ts +20 -0
- package/dist/agents/child-failure.js +28 -0
- package/dist/agents/cross-session-ref.d.ts +11 -3
- package/dist/agents/cross-session-ref.js +6 -0
- package/dist/agents/cumulative-stats.d.ts +12 -15
- package/dist/agents/cumulative-stats.js +1 -1
- package/dist/agents/extra-tool-names.js +1 -1
- package/dist/agents/inherited-tool-pool.d.ts +17 -13
- package/dist/agents/inherited-tool-pool.js +4 -3
- package/dist/agents/peer-session-drain.d.ts +3 -2
- package/dist/agents/peer-session-drain.js +5 -4
- package/dist/agents/send-message-tool.js +2 -9
- package/dist/agents/subagent.d.ts +10 -29
- package/dist/agents/subagent.js +65 -53
- package/dist/agents/suspend-guard.d.ts +1 -1
- package/dist/agents/tool-filter.d.ts +76 -65
- package/dist/agents/tool-filter.js +122 -92
- package/dist/agents/verify.d.ts +4 -7
- package/dist/agents/verify.js +6 -7
- package/dist/bench/metrics.d.ts +1 -2
- package/dist/brain/anthropic.js +133 -79
- package/dist/brain/errors.d.ts +53 -6
- package/dist/brain/errors.js +22 -2
- package/dist/brain/input-too-long.d.ts +40 -19
- package/dist/brain/input-too-long.js +3 -16
- package/dist/brain/open-responses.js +19 -10
- package/dist/brain/openai.js +123 -32
- package/dist/brain/provider-dialect.d.ts +214 -0
- package/dist/brain/provider-dialect.js +186 -0
- package/dist/brain/request-params.d.ts +27 -8
- package/dist/brain/request-params.js +7 -12
- package/dist/brain/request-route.d.ts +84 -0
- package/dist/brain/request-route.js +41 -0
- package/dist/brain/retry.d.ts +8 -0
- package/dist/brain/retry.js +10 -4
- package/dist/brain/route-adjudicator.d.ts +7 -0
- package/dist/brain/route-adjudicator.js +5 -1
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +11 -0
- package/dist/brain/stream-engine.d.ts +52 -1
- package/dist/brain/stream-engine.js +81 -24
- package/dist/brain/stream-shared.d.ts +57 -11
- package/dist/brain/stream-shared.js +28 -2
- package/dist/core/a2a.d.ts +1 -0
- package/dist/core/agent-config-dir.js +3 -2
- package/dist/core/allow-entry.d.ts +21 -12
- package/dist/core/allow-entry.js +39 -32
- package/dist/core/arg-summary.d.ts +17 -24
- package/dist/core/arg-summary.js +169 -68
- package/dist/core/ask-origin.d.ts +42 -24
- package/dist/core/ask-origin.js +18 -13
- package/dist/core/auto-mode-prompt-assets.d.ts +2 -2
- package/dist/core/auto-mode-prompt-assets.js +1 -1
- package/dist/core/auto-mode-prompt.d.ts +11 -1
- package/dist/core/auto-mode-prompt.js +13 -10
- package/dist/core/auto-mode-rebuild.d.ts +7 -0
- package/dist/core/auto-mode-rebuild.js +4 -1
- package/dist/core/canonical-json.d.ts +3 -0
- package/dist/core/canonical-json.js +2 -1
- package/dist/core/checkpoint-requirements.d.ts +892 -0
- package/dist/core/checkpoint-requirements.js +333 -0
- package/dist/core/checkpoint-store.d.ts +95 -66
- package/dist/core/checkpoint-store.js +14 -26
- package/dist/core/child-clamp-seats.d.ts +228 -69
- package/dist/core/child-clamp-seats.js +211 -17
- package/dist/core/classifier-unavailable-arm.d.ts +5 -1
- package/dist/core/classifier-unavailable-arm.js +3 -3
- package/dist/core/compliance.d.ts +3 -0
- package/dist/core/compliance.js +9 -4
- package/dist/core/credential-vocabulary.d.ts +140 -0
- package/dist/core/credential-vocabulary.js +131 -0
- package/dist/core/decision-receipt.js +1 -1
- package/dist/core/effective-path-target.d.ts +73 -16
- package/dist/core/effective-path-target.js +63 -33
- package/dist/core/engine-notice.d.ts +32 -7
- package/dist/core/file-history-store.js +2 -2
- package/dist/core/fs-write-gate-policy.d.ts +4 -0
- package/dist/core/fs-write-gate-policy.js +22 -5
- package/dist/core/gate-bounded-await.d.ts +28 -13
- package/dist/core/gate-bounded-await.js +41 -4
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +24 -25
- package/dist/core/gate-lanes.js +16 -15
- package/dist/core/gate-outcome.d.ts +20 -5
- package/dist/core/gate-outcome.js +5 -0
- package/dist/core/governance-codes.d.ts +11 -4
- package/dist/core/governance-codes.js +14 -3
- package/dist/core/hooks.d.ts +4 -0
- package/dist/core/locked-config.d.ts +8 -0
- package/dist/core/locked-config.js +14 -2
- package/dist/core/lsp.js +3 -5
- package/dist/core/mailbox-store.d.ts +3 -4
- package/dist/core/mcp-connection-pool.d.ts +75 -0
- package/dist/core/mcp-connection-pool.js +128 -0
- package/dist/core/mcp-failure.d.ts +2 -1
- package/dist/core/mcp-failure.js +13 -2
- package/dist/core/mcp-server-spec.d.ts +1 -1
- package/dist/core/mcp.d.ts +4 -0
- package/dist/core/mcp.js +70 -43
- package/dist/core/memory-engine/content-origin.js +2 -14
- package/dist/core/memory-engine/engine.d.ts +32 -22
- package/dist/core/memory-engine/engine.js +103 -55
- package/dist/core/memory-engine/file-backend.d.ts +13 -30
- package/dist/core/memory-engine/file-backend.js +37 -252
- package/dist/core/memory-engine/index.d.ts +1 -1
- package/dist/core/memory-engine/index.js +1 -1
- package/dist/core/memory-engine/layout.d.ts +139 -9
- package/dist/core/memory-engine/layout.js +350 -7
- package/dist/core/memory-engine/scope-contract.d.ts +10 -0
- package/dist/core/memory-engine/scope-contract.js +8 -0
- package/dist/core/memory-engine/session-incarnation.d.ts +14 -4
- package/dist/core/memory-engine/session-incarnation.js +5 -2
- package/dist/core/memory-engine/types.d.ts +10 -1
- package/dist/core/memory.js +5 -17
- package/dist/core/model-seat.d.ts +4 -4
- package/dist/core/model-seat.js +1 -1
- package/dist/core/mounted-mcp.d.ts +57 -0
- package/dist/core/mounted-mcp.js +19 -0
- package/dist/core/namespaced-rule-name.d.ts +29 -0
- package/dist/core/namespaced-rule-name.js +52 -0
- package/dist/core/park-selfcheck.d.ts +1 -1
- package/dist/core/park-selfcheck.js +16 -6
- package/dist/core/path-guard-rows.d.ts +99 -0
- package/dist/core/path-guard-rows.js +45 -0
- package/dist/core/path-identity.d.ts +22 -16
- package/dist/core/path-identity.js +10 -10
- package/dist/core/path-rule-binding.d.ts +2 -1
- package/dist/core/path-rule-binding.js +3 -1
- package/dist/core/pause-registry.d.ts +16 -2
- package/dist/core/pause-registry.js +6 -0
- package/dist/core/permission-rule-consent.js +0 -7
- package/dist/core/permission-rule-model.d.ts +68 -24
- package/dist/core/permission-rule-model.js +105 -24
- package/dist/core/permission-rule-store.js +2 -2
- package/dist/core/permission-rules.d.ts +3 -30
- package/dist/core/permission-rules.js +4 -54
- package/dist/core/read-root-candidate.d.ts +1 -3
- package/dist/core/read-root-candidate.js +4 -15
- package/dist/core/real-approval.d.ts +4 -3
- package/dist/core/retired-keys.d.ts +13 -0
- package/dist/core/retired-keys.js +14 -0
- package/dist/core/roles.d.ts +2 -3
- package/dist/core/roles.js +15 -6
- package/dist/core/runner/assemble-result.d.ts +0 -7
- package/dist/core/runner/assemble-result.js +19 -31
- package/dist/core/runner/caller-roster.d.ts +78 -0
- package/dist/core/runner/caller-roster.js +219 -0
- package/dist/core/runner/checkpoint-scope.d.ts +16 -16
- package/dist/core/runner/checkpoint-scope.js +2 -2
- package/dist/core/runner/child-tree.js +2 -2
- package/dist/core/runner/contracts.d.ts +68 -35
- package/dist/core/runner/decide-continuation.d.ts +51 -3
- package/dist/core/runner/decide-continuation.js +76 -21
- package/dist/core/runner/denial-limit-arms.d.ts +17 -5
- package/dist/core/runner/denial-limit-arms.js +11 -9
- package/dist/core/runner/extra-body-dropped-seat.d.ts +8 -0
- package/dist/core/runner/extra-body-dropped-seat.js +22 -0
- package/dist/core/runner/finish-reason-seat.d.ts +9 -0
- package/dist/core/runner/finish-reason-seat.js +40 -0
- package/dist/core/runner/gate-exit.d.ts +44 -32
- package/dist/core/runner/gate-exit.js +112 -25
- package/dist/core/runner/inherited-ask-grants.js +6 -4
- package/dist/core/runner/mcp-redial.d.ts +3 -3
- package/dist/core/runner/mcp-redial.js +3 -4
- package/dist/core/runner/park-commit.d.ts +1 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +1 -2
- package/dist/core/runner/permission-rule-lanes.js +5 -4
- package/dist/core/runner/prepare-artifact.d.ts +4 -0
- package/dist/core/runner/prepare-artifact.js +2 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -0
- package/dist/core/runner/prepare-ask-lane.js +12 -6
- package/dist/core/runner/prepare-boundary-parks.d.ts +5 -8
- package/dist/core/runner/prepare-boundary-parks.js +4 -7
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +11 -15
- package/dist/core/runner/prepare-caps-and-workflow.js +19 -27
- package/dist/core/runner/prepare-config-doors.d.ts +9 -9
- package/dist/core/runner/prepare-config-doors.js +10 -5
- package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
- package/dist/core/runner/prepare-defer-classify.js +5 -3
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-delegation-surface.js +3 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +4 -4
- package/dist/core/runner/prepare-gate-stations.js +9 -7
- package/dist/core/runner/prepare-hands-readface.d.ts +7 -7
- package/dist/core/runner/prepare-hands-readface.js +7 -7
- package/dist/core/runner/prepare-inherited-gate.d.ts +7 -6
- package/dist/core/runner/prepare-inherited-gate.js +14 -15
- package/dist/core/runner/prepare-listings.d.ts +7 -24
- package/dist/core/runner/prepare-listings.js +4 -5
- package/dist/core/runner/prepare-memory-engine-session.d.ts +2 -0
- package/dist/core/runner/prepare-memory-engine-session.js +4 -3
- package/dist/core/runner/prepare-memory.d.ts +6 -0
- package/dist/core/runner/prepare-memory.js +13 -13
- package/dist/core/runner/prepare-offload-wrappers.d.ts +5 -0
- package/dist/core/runner/prepare-offload-wrappers.js +3 -3
- package/dist/core/runner/prepare-park-ask.d.ts +7 -8
- package/dist/core/runner/prepare-park-ask.js +17 -10
- package/dist/core/runner/prepare-policy-chain.js +24 -44
- package/dist/core/runner/prepare-project-context.d.ts +1 -1
- package/dist/core/runner/prepare-project-context.js +3 -4
- package/dist/core/runner/prepare-protocol-tools.d.ts +9 -3
- package/dist/core/runner/prepare-protocol-tools.js +3 -4
- package/dist/core/runner/prepare-run-refs.d.ts +3 -0
- package/dist/core/runner/prepare-run-refs.js +2 -1
- package/dist/core/runner/prepare-safety-scan.d.ts +4 -8
- package/dist/core/runner/prepare-safety-scan.js +1 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +7 -1
- package/dist/core/runner/prepare-suspend-saga.js +28 -12
- package/dist/core/runner/prepare-task.d.ts +1 -1
- package/dist/core/runner/prepare-task.js +67 -56
- package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -10
- package/dist/core/runner/prepare-wiring-manifest.js +5 -8
- package/dist/core/runner/resume-apply.js +7 -14
- package/dist/core/runner/resume-checkpoint-screen.js +11 -4
- package/dist/core/runner/resume-internals-and-config.js +2 -2
- package/dist/core/runner/resume-policy-outcome.js +5 -32
- package/dist/core/runner/resume-review-outcome.js +4 -1
- package/dist/core/runner/retired-runner-deps.d.ts +6 -0
- package/dist/core/runner/retired-runner-deps.js +10 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -0
- package/dist/core/runner/run-brain-sinks.js +5 -2
- package/dist/core/runner/run-harness-handlers.js +27 -34
- package/dist/core/runner/run-leg.d.ts +0 -2
- package/dist/core/runner/run-leg.js +32 -33
- package/dist/core/runner/run-terminal-adoption.js +4 -3
- package/dist/core/runner/runtask.js +8 -8
- package/dist/core/runner/session-rule-policy.js +5 -5
- package/dist/core/runner/stream-settle-backstop.js +7 -4
- package/dist/core/runner/sub-agent-deny-lists.d.ts +51 -12
- package/dist/core/runner/sub-agent-deny-lists.js +111 -80
- package/dist/core/runner/terminal-account.d.ts +48 -0
- package/dist/core/runner/terminal-account.js +186 -0
- package/dist/core/runner/tool-end-body.d.ts +54 -17
- package/dist/core/runner/tool-end-body.js +27 -2
- package/dist/core/runner/tool-face-overlay.d.ts +3 -1
- package/dist/core/runner/tool-face-overlay.js +6 -4
- package/dist/core/runner/tool-occurrence.d.ts +106 -0
- package/dist/core/runner/tool-occurrence.js +123 -0
- package/dist/core/runner/tool-progress-lane.d.ts +16 -8
- package/dist/core/runner/tool-progress-lane.js +25 -34
- package/dist/core/runner/turn-attachments.d.ts +1 -1
- package/dist/core/runner/write-protection-station.d.ts +21 -9
- package/dist/core/runner/write-protection-station.js +20 -17
- package/dist/core/runner-deps.d.ts +12 -22
- package/dist/core/safety-axis-vocab.d.ts +1 -1
- package/dist/core/safety-merge-corpus.d.ts +1 -1
- package/dist/core/secret-env.d.ts +16 -5
- package/dist/core/secret-env.js +23 -63
- package/dist/core/sensitive-path-policy.d.ts +19 -18
- package/dist/core/sensitive-path-policy.js +73 -49
- package/dist/core/session-policy-store.d.ts +6 -3
- package/dist/core/session-policy-store.js +28 -10
- package/dist/core/session-reconcile.d.ts +3 -0
- package/dist/core/session-reconcile.js +5 -4
- package/dist/core/session-store.d.ts +5 -0
- package/dist/core/session-store.js +12 -0
- package/dist/core/session.d.ts +13 -0
- package/dist/core/shared-memory/normalize.d.ts +17 -4
- package/dist/core/shared-memory/normalize.js +7 -7
- package/dist/core/shell-lexer.js +5 -4
- package/dist/core/shell-wrapper-table.d.ts +2 -2
- package/dist/core/shell-wrapper-table.js +1 -1
- package/dist/core/skill-grant.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +2 -2
- package/dist/core/task-event.d.ts +59 -5
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +42 -9
- package/dist/core/terminal-cause.d.ts +94 -11
- package/dist/core/tighten-task-spec.d.ts +5 -4
- package/dist/core/tighten-task-spec.js +20 -25
- package/dist/core/tool-catalog-entries.d.ts +5 -7
- package/dist/core/tool-catalog-entries.js +14 -15
- package/dist/core/tool-face.d.ts +47 -0
- package/dist/core/tool-face.js +5 -0
- package/dist/core/tool-model-gate.d.ts +5 -5
- package/dist/core/tool-name-aliases.d.ts +35 -10
- package/dist/core/tool-name-aliases.js +15 -0
- package/dist/core/tool-name-list.d.ts +30 -0
- package/dist/core/tool-name-list.js +55 -0
- package/dist/core/tool-name-readings.d.ts +1 -9
- package/dist/core/tool-name-readings.js +1 -3
- package/dist/core/tool-policy.d.ts +195 -85
- package/dist/core/tool-policy.js +165 -381
- package/dist/core/tool-registry.d.ts +44 -1
- package/dist/core/tool-registry.js +26 -0
- package/dist/core/tool-roster.d.ts +19 -1
- package/dist/core/tool-roster.js +21 -2
- package/dist/core/tool-spec-members.d.ts +45 -0
- package/dist/core/tool-spec-members.js +169 -0
- package/dist/core/tool-spec.d.ts +46 -8
- package/dist/core/tools.d.ts +6 -2
- package/dist/core/tools.js +8 -4
- package/dist/core/untrusted-egress.js +29 -26
- package/dist/core/untrusted-text.d.ts +13 -10
- package/dist/core/untrusted-text.js +6 -44
- package/dist/core/workflow-journal-store.d.ts +4 -1
- package/dist/core/write-protect.d.ts +65 -29
- package/dist/core/write-protect.js +235 -177
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
- package/dist/engine/execution-env/node-execution-env.js +16 -38
- package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
- package/dist/engine/execution-env/symlink-chain.js +32 -0
- package/dist/engine/harness/types.d.ts +7 -0
- package/dist/engine/llm/tool-turns.d.ts +3 -0
- package/dist/engine/llm/tool-turns.js +1 -0
- package/dist/engine/llm/types.d.ts +59 -23
- package/dist/engine/loop/agent-loop.js +16 -2
- package/dist/engine/session/memory-repo.js +11 -3
- package/dist/engine/session/repo-utils.d.ts +8 -0
- package/dist/engine/session/repo-utils.js +13 -0
- package/dist/index.d.ts +20 -23
- package/dist/index.js +17 -20
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/governance-baseline-validity.js +1 -1
- package/dist/orchestration/run-spec.js +3 -3
- package/dist/orchestration/run-workflow-tool.d.ts +16 -35
- package/dist/orchestration/run-workflow-tool.js +38 -78
- package/dist/orchestration/workflow-governance.d.ts +21 -25
- package/dist/orchestration/workflow-governance.js +38 -78
- package/dist/orchestration/workflow-primitives.d.ts +7 -22
- package/dist/orchestration/workflow-primitives.js +5 -12
- package/dist/orchestration/workflow-types.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +61 -11
- package/dist/orchestration/workflow.js +191 -119
- package/dist/prompt-assembly/types.d.ts +1 -1
- package/dist/scenarios/full-body.d.ts +1 -1
- package/dist/shell/lex.d.ts +0 -21
- package/dist/shell/lex.js +278 -70
- package/dist/shell/shell-words.d.ts +35 -0
- package/dist/shell/shell-words.js +65 -0
- package/dist/stores/file/checkpoint-store.d.ts +5 -5
- package/dist/stores/file/checkpoint-store.js +5 -2
- package/dist/stores/file/index.d.ts +0 -8
- package/dist/stores/file/index.js +0 -12
- package/dist/stores/file/session-store.d.ts +3 -0
- package/dist/stores/file/session-store.js +44 -19
- package/dist/tools/artifact/artifact-tool.js +2 -0
- package/dist/tools/fs/bash-program-position.d.ts +17 -3
- package/dist/tools/fs/bash-program-position.js +25 -10
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/bash-readonly-classifier.js +8 -7
- package/dist/tools/fs/containment-face.d.ts +4 -0
- package/dist/tools/fs/containment-face.js +3 -0
- package/dist/tools/fs/fs-shared.d.ts +10 -0
- package/dist/tools/fs/fs-shared.js +18 -0
- package/dist/tools/fs/fs-write.js +4 -2
- package/dist/tools/fs/index.d.ts +3 -2
- package/dist/tools/fs/index.js +2 -2
- package/dist/tools/fs/program-read-model.d.ts +99 -23
- package/dist/tools/fs/program-read-model.js +129 -55
- package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
- package/dist/tools/fs/program-read-model.rows.js +18 -10
- package/dist/tools/fs/read-deny-home.d.ts +35 -30
- package/dist/tools/fs/read-deny-home.js +45 -38
- package/dist/tools/fs/read-deny.d.ts +35 -27
- package/dist/tools/fs/read-deny.js +126 -92
- package/dist/tools/fs/removal-targets.d.ts +56 -23
- package/dist/tools/fs/removal-targets.js +74 -87
- package/dist/tools/fs/safety.d.ts +29 -22
- package/dist/tools/fs/safety.js +17 -11
- package/dist/tools/fs/search.js +10 -8
- package/dist/tools/fs/shell-read-argv.d.ts +4 -7
- package/dist/tools/fs/shell-read-argv.js +6 -8
- package/dist/tools/fs/shell-read-bindings.d.ts +203 -46
- package/dist/tools/fs/shell-read-bindings.js +488 -144
- package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
- package/dist/tools/fs/shell-read-builtins.js +43 -0
- package/dist/tools/fs/shell-read-check.d.ts +15 -1
- package/dist/tools/fs/shell-read-check.js +51 -42
- package/dist/tools/fs/shell-read-establish.js +9 -10
- package/dist/tools/fs/shell-read-functions.d.ts +22 -0
- package/dist/tools/fs/shell-read-functions.js +29 -0
- package/dist/tools/fs/shell-read-judge.d.ts +48 -18
- package/dist/tools/fs/shell-read-judge.js +33 -4
- package/dist/tools/fs/shell-read-plan.d.ts +13 -20
- package/dist/tools/fs/shell-read-plan.js +200 -194
- package/dist/tools/fs/shell-read-start.d.ts +80 -0
- package/dist/tools/fs/shell-read-start.js +99 -0
- package/dist/tools/fs/shell-read-word.d.ts +35 -6
- package/dist/tools/fs/shell-read-word.js +89 -9
- package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
- package/dist/tools/fs/shell-read-workdir.js +281 -0
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
- package/dist/tools/fs/shell-read-write-targets.js +14 -5
- package/dist/tools/fs/shell-reentry-text.d.ts +26 -26
- package/dist/tools/fs/shell-reentry-text.js +31 -34
- package/dist/tools/task-list.d.ts +1 -2
- package/dist/tools/web.js +1 -1
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +107 -143
- package/wire-changes/core@7.48.0.json +252 -0
- package/wire-changes/core@7.49.0.json +4765 -0
- package/dist/agents/teacher.d.ts +0 -159
- package/dist/agents/teacher.js +0 -577
- package/dist/agents/team.d.ts +0 -226
- package/dist/agents/team.js +0 -257
- package/dist/core/strategy-store.d.ts +0 -238
- package/dist/core/strategy-store.js +0 -253
- package/dist/orchestration/builtin-workflows.d.ts +0 -133
- package/dist/orchestration/builtin-workflows.js +0 -159
- package/dist/scenarios/env.d.ts +0 -40
- package/dist/scenarios/env.js +0 -39
- package/dist/scenarios/scenario-registry.d.ts +0 -110
- package/dist/scenarios/scenario-registry.js +0 -140
- package/dist/scenarios/teacher-quickstart.d.ts +0 -40
- package/dist/scenarios/teacher-quickstart.js +0 -12
- package/dist/stores/cc/lockfile.d.ts +0 -10
- package/dist/stores/cc/lockfile.js +0 -98
- package/dist/stores/cc/mailbox-store.d.ts +0 -20
- package/dist/stores/cc/mailbox-store.js +0 -255
- package/dist/stores/cc/roster-adapter.d.ts +0 -12
- package/dist/stores/cc/roster-adapter.js +0 -117
- package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
- package/dist/stores/cc/sidecar-transcript.js +0 -264
- package/dist/stores/cc/task-list-store.d.ts +0 -2
- package/dist/stores/cc/task-list-store.js +0 -125
- package/dist/stores/file/strategy-store.d.ts +0 -97
- package/dist/stores/file/strategy-store.js +0 -341
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { BrainError, carriedProviderWord, providerErrorWord, statedEnvelope } from "./errors.js";
|
|
2
|
+
import { readUnifiedResetEpochMs } from "./retry.js";
|
|
3
|
+
export const PROVIDER_CONDITIONS = Object.freeze(["quota_exhausted", "throttled", "overloaded", "stop_other", "unknown"]);
|
|
4
|
+
export const PROVIDER_CONDITION_SOURCES = Object.freeze(["unified_header", "provider_code", "status"]);
|
|
5
|
+
export const PROVIDER_CONDITION_TRAITS = {
|
|
6
|
+
quota_exhausted: { retryable: false, inBandCode: "rate_limit" },
|
|
7
|
+
throttled: { retryable: true, inBandCode: "rate_limit" },
|
|
8
|
+
overloaded: { retryable: true, inBandCode: "server" },
|
|
9
|
+
stop_other: { retryable: false, inBandCode: "invalid_request" },
|
|
10
|
+
unknown: { retryable: true, inBandCode: "server" },
|
|
11
|
+
};
|
|
12
|
+
Object.freeze(PROVIDER_CONDITION_TRAITS);
|
|
13
|
+
export function isProviderCondition(v) {
|
|
14
|
+
return typeof v === "string" && PROVIDER_CONDITIONS.includes(v);
|
|
15
|
+
}
|
|
16
|
+
export function isProviderConditionSource(v) {
|
|
17
|
+
return typeof v === "string" && PROVIDER_CONDITION_SOURCES.includes(v);
|
|
18
|
+
}
|
|
19
|
+
export const INPUT_TOO_LONG_ANCHORED_RE = /^(?:prompt is too long|prompt too long|input is too long|this model's maximum context length is |context.{0,3}length|context window (?:limit|exceeded)|reached its context window|too many tokens|maximum context|input length and `max_tokens` exceed context limit|(?:the )?request(?: \([^)]{0,40}\))? exceeds|(?:the )?input token count(?: \([^)]{0,40}\))? exceeds|requested tokens(?: \([^)]{0,40}\))? exceed|your input exceeds|(?:the )?number of tokens in the request exceeds|range of input length should be|input token length too long|invalid request: your request exceeded model token limit|total message size)/i;
|
|
20
|
+
export function startsWithInputTooLongAnchor(diagnostic) {
|
|
21
|
+
return INPUT_TOO_LONG_ANCHORED_RE.test(diagnostic.trimStart());
|
|
22
|
+
}
|
|
23
|
+
const INPUT_TOO_LONG_STATUSES = new Set([400, 413, 422]);
|
|
24
|
+
const OPENAI_CHAT = "openai-completions";
|
|
25
|
+
const OPENAI_RESPONSES = "openai-responses";
|
|
26
|
+
const ANTHROPIC = "anthropic-messages";
|
|
27
|
+
const OPENAI_SPEND_CODES = ["credit_balance_exhausted", "organization_spend_limit_exceeded", "project_spend_limit_exceeded", "organization_usage_limit_exceeded"];
|
|
28
|
+
export const PROVIDER_DIALECTS = Object.freeze([
|
|
29
|
+
{
|
|
30
|
+
name: "deepseek",
|
|
31
|
+
key: { wires: [OPENAI_CHAT, ANTHROPIC], hosts: ["api.deepseek.com"] },
|
|
32
|
+
failures: [
|
|
33
|
+
{ status: [429], condition: "throttled" },
|
|
34
|
+
{ status: [503], condition: "overloaded" },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "dashscope",
|
|
39
|
+
key: { wires: [OPENAI_CHAT], hosts: ["dashscope.aliyuncs.com", "dashscope-intl.aliyuncs.com"] },
|
|
40
|
+
failures: [
|
|
41
|
+
{ status: [429], word: ["limit_requests", "limit_burst_rate", "Throttling.Concurrency", "Throttling"], condition: "throttled" },
|
|
42
|
+
{ status: [429], word: ["insufficient_quota", "Throttling.AllocationQuota"], sentence: /^free allocated quota exceeded/i, condition: "quota_exhausted" },
|
|
43
|
+
{ status: [429], word: ["insufficient_quota", "Throttling.AllocationQuota"], condition: "throttled" },
|
|
44
|
+
{ status: [429], word: ["Throttling.ServiceOverloaded", "ResourceExhausted"], condition: "overloaded" },
|
|
45
|
+
{ status: [429], word: ["PrepaidBillOverdue", "PostpaidBillOverdue", "BudgetLimitExceeded", "CommodityNotPurchased"], condition: "quota_exhausted" },
|
|
46
|
+
{ status: [429], condition: "throttled" },
|
|
47
|
+
{ status: [400], word: ["Arrearage"], condition: "quota_exhausted" },
|
|
48
|
+
{ status: [403], word: ["AllocationQuota.FreeTierOnly"], condition: "quota_exhausted" },
|
|
49
|
+
{ status: [400], word: ["DataInspectionFailed"], condition: "stop_other" },
|
|
50
|
+
{ status: [500, 503], word: ["InternalError", "RequestTimeOut", "ModelUnavailable"], condition: "overloaded" },
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "moonshot",
|
|
55
|
+
key: { wires: [OPENAI_CHAT], hosts: ["api.moonshot.cn", "api.moonshot.ai"] },
|
|
56
|
+
failures: [
|
|
57
|
+
{ status: [429], word: ["exceeded_current_quota_error"], condition: "quota_exhausted" },
|
|
58
|
+
{ status: [429], word: ["rate_limit_reached_error"], sentence: /\bTPD\b|每日/i, condition: "quota_exhausted" },
|
|
59
|
+
{ status: [429], word: ["rate_limit_reached_error"], condition: "throttled" },
|
|
60
|
+
{ status: [429], word: ["engine_overloaded_error"], condition: "overloaded" },
|
|
61
|
+
{ status: [429], condition: "throttled" },
|
|
62
|
+
{ status: [503], word: ["server_unavailable"], condition: "overloaded" },
|
|
63
|
+
{ status: [403], word: ["permission_denied_error"], condition: "stop_other" },
|
|
64
|
+
{ status: [400], word: ["content_filter"], condition: "stop_other" },
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "kimi-code",
|
|
69
|
+
key: { wires: [ANTHROPIC, OPENAI_CHAT], hosts: ["api.kimi.com"], path: "/coding" },
|
|
70
|
+
failures: [
|
|
71
|
+
{ status: [429], sentence: /^the engine is currently overloaded/i, condition: "overloaded" },
|
|
72
|
+
{ status: [429], condition: "throttled" },
|
|
73
|
+
{ status: [403], sentence: /^you(?:'|’)ve reached your\b.*\busage limit/i, condition: "quota_exhausted" },
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "glm",
|
|
78
|
+
key: { wires: [OPENAI_CHAT, ANTHROPIC], hosts: ["open.bigmodel.cn", "api.z.ai"] },
|
|
79
|
+
failures: [
|
|
80
|
+
{ status: [429], word: ["1302"], condition: "throttled" },
|
|
81
|
+
{ status: [429], word: ["1305"], condition: "overloaded" },
|
|
82
|
+
{
|
|
83
|
+
status: [429],
|
|
84
|
+
word: ["1113", "1308", "1309", "1310", "1314", "1315", "1316", "1317", "1318", "1319", "1320", "1321"],
|
|
85
|
+
condition: "quota_exhausted",
|
|
86
|
+
},
|
|
87
|
+
{ status: [429], word: ["1311", "1313"], condition: "stop_other" },
|
|
88
|
+
{ status: [400], word: ["1261"], condition: "stop_other", inputTooLong: true },
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "openai",
|
|
93
|
+
key: { wires: [OPENAI_CHAT, OPENAI_RESPONSES], hosts: ["api.openai.com"] },
|
|
94
|
+
failures: [
|
|
95
|
+
{ status: [429], word: [...OPENAI_SPEND_CODES, "insufficient_quota"], condition: "quota_exhausted" },
|
|
96
|
+
{ status: [429], word: ["slow_down", "rate_limit_exceeded", "rate_limit_error"], condition: "throttled" },
|
|
97
|
+
{ status: [429], condition: "throttled" },
|
|
98
|
+
{ status: [503], word: ["server_is_overloaded"], condition: "overloaded" },
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
]);
|
|
102
|
+
export const GENERIC_FAILURES = Object.freeze([
|
|
103
|
+
{ status: [402], condition: "quota_exhausted" },
|
|
104
|
+
{ status: [429], word: [...OPENAI_SPEND_CODES], condition: "quota_exhausted" },
|
|
105
|
+
{ status: [429], word: ["insufficient_quota"], condition: "unknown" },
|
|
106
|
+
{ status: [400, 422], word: ["context_length_exceeded"], condition: "stop_other", inputTooLong: true },
|
|
107
|
+
{ status: [400, 422], sentence: INPUT_TOO_LONG_ANCHORED_RE, condition: "stop_other", inputTooLong: true },
|
|
108
|
+
{ status: [413], condition: "stop_other", inputTooLong: true },
|
|
109
|
+
]);
|
|
110
|
+
export function isTransientStatus(status) {
|
|
111
|
+
return status >= 500 || status === 408 || status === 409;
|
|
112
|
+
}
|
|
113
|
+
export function resolveProviderDialect(url, wire) {
|
|
114
|
+
if (!URL.canParse(url))
|
|
115
|
+
return undefined;
|
|
116
|
+
const u = new URL(url);
|
|
117
|
+
const host = u.hostname.toLowerCase().replace(/\.$/, "");
|
|
118
|
+
const path = u.pathname;
|
|
119
|
+
return PROVIDER_DIALECTS.find((d) => d.key.wires.includes(wire) &&
|
|
120
|
+
d.key.hosts.some((h) => host === h || host.endsWith(`.${h}`)) &&
|
|
121
|
+
(d.key.path === undefined || path === d.key.path || path.startsWith(`${d.key.path}/`)));
|
|
122
|
+
}
|
|
123
|
+
function statementOf(err) {
|
|
124
|
+
if (err === undefined)
|
|
125
|
+
return undefined;
|
|
126
|
+
const word = providerErrorWord(err);
|
|
127
|
+
const sentence = typeof err.message === "string" ? err.message.trimStart() : undefined;
|
|
128
|
+
return { ...(word !== undefined ? { word } : {}), ...(sentence !== undefined ? { sentence } : {}) };
|
|
129
|
+
}
|
|
130
|
+
function bestRow(rows, status, stated) {
|
|
131
|
+
let best;
|
|
132
|
+
let bestRank = -1;
|
|
133
|
+
for (const row of rows) {
|
|
134
|
+
if (status === undefined ? row.word === undefined && row.sentence === undefined : row.status !== undefined && !row.status.includes(status))
|
|
135
|
+
continue;
|
|
136
|
+
if (row.word !== undefined && (stated?.word === undefined || !row.word.includes(stated.word)))
|
|
137
|
+
continue;
|
|
138
|
+
if (row.sentence !== undefined && (stated?.sentence === undefined || !row.sentence.test(stated.sentence)))
|
|
139
|
+
continue;
|
|
140
|
+
const rank = (row.word !== undefined ? 2 : 0) + (row.sentence !== undefined ? 1 : 0);
|
|
141
|
+
if (rank > bestRank) {
|
|
142
|
+
best = row;
|
|
143
|
+
bestRank = rank;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return best;
|
|
147
|
+
}
|
|
148
|
+
function verdictOf(dialect, status, stated, enveloped) {
|
|
149
|
+
const row = bestRow(dialect?.failures ?? [], status, stated) ?? bestRow(GENERIC_FAILURES, status, stated);
|
|
150
|
+
const condition = row?.condition ?? (status === undefined || status === 429 || isTransientStatus(status) ? "unknown" : "stop_other");
|
|
151
|
+
const source = row !== undefined && (row.word !== undefined || row.sentence !== undefined) ? "provider_code" : "status";
|
|
152
|
+
const inputTooLong = status !== undefined && !INPUT_TOO_LONG_STATUSES.has(status) ? "no" : row?.inputTooLong === true ? "yes" : enveloped ? "no" : "unknown";
|
|
153
|
+
return { condition, source, inputTooLong };
|
|
154
|
+
}
|
|
155
|
+
const UNIFIED_QUOTA_HEADERS = [
|
|
156
|
+
"anthropic-ratelimit-unified-representative-claim",
|
|
157
|
+
"anthropic-ratelimit-unified-overage-status",
|
|
158
|
+
"anthropic-ratelimit-unified-overage-disabled-reason",
|
|
159
|
+
];
|
|
160
|
+
function headerPresent(headers, name) {
|
|
161
|
+
const v = headers?.get?.(name);
|
|
162
|
+
return typeof v === "string" && v.length > 0;
|
|
163
|
+
}
|
|
164
|
+
export function judgeHttpFailure(args) {
|
|
165
|
+
const { dialect, status, headers, body } = args;
|
|
166
|
+
if (status === 429 && UNIFIED_QUOTA_HEADERS.some((h) => headerPresent(headers, h))) {
|
|
167
|
+
const resetAtMs = readUnifiedResetEpochMs(headers);
|
|
168
|
+
return { condition: "quota_exhausted", source: "unified_header", ...(resetAtMs !== undefined ? { resetAtMs } : {}), inputTooLong: "no" };
|
|
169
|
+
}
|
|
170
|
+
const envelope = statedEnvelope(body);
|
|
171
|
+
return verdictOf(dialect, status, statementOf(envelope), envelope !== undefined);
|
|
172
|
+
}
|
|
173
|
+
export function judgeInBandError(dialect, envelope) {
|
|
174
|
+
return verdictOf(dialect, undefined, statementOf(envelope), true);
|
|
175
|
+
}
|
|
176
|
+
export function inBandProviderError(dialect, envelope, label) {
|
|
177
|
+
const v = judgeInBandError(dialect, envelope);
|
|
178
|
+
const word = carriedProviderWord(envelope);
|
|
179
|
+
const sentence = typeof envelope.message === "string" ? envelope.message : "";
|
|
180
|
+
return new BrainError(PROVIDER_CONDITION_TRAITS[v.condition].inBandCode, `${label} stream error (${word ?? "unknown"}): ${sentence}`, undefined, {
|
|
181
|
+
apiError: true,
|
|
182
|
+
...(v.inputTooLong === "yes" ? { inputTooLong: true } : v.inputTooLong === "no" ? { inputTooLongRuledOut: true } : {}),
|
|
183
|
+
...(word !== undefined ? { providerCode: word } : {}),
|
|
184
|
+
verdict: { condition: v.condition, source: v.source },
|
|
185
|
+
});
|
|
186
|
+
}
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request-parameter passthrough (design/40). A deployment can set official provider params it wants but
|
|
3
|
+
* core doesn't model as first-class fields (OpenAI `frequency_penalty`/`presence_penalty`/`top_p`/`seed`/
|
|
4
|
+
* `logit_bias`; Anthropic `top_k`/`top_p`/`stop_sequences`; …) via `Model.extraBody`, and core merges them
|
|
5
|
+
* into the brain's request body. Anchored at the **Model** level (not per-turn) so the serialized body
|
|
6
|
+
* stays byte-stable across turns → the prefix cache holds (design/9/31).
|
|
7
|
+
*
|
|
8
|
+
* Symmetric: each brain owns its structural + tuning keys (`reserved`) and ALWAYS wins — `extraBody` can
|
|
9
|
+
* only supply the long tail, never clobber `messages`/`tools`/`temperature`/etc. Stripping is the safety
|
|
10
|
+
* enforcement (the brains are standalone-usable), and a strip is never silent: {@link applyExtraBody}
|
|
11
|
+
* RETURNS the keys it stripped, the brain reports them on the request it built
|
|
12
|
+
* (`SSERequest.extraBodyDropped`), the stream engine reports them to the run's sink when it commits that
|
|
13
|
+
* request (`reportExtraBodyDropped`), and the Runner announces them (`route.extra_body_reserved_dropped`).
|
|
14
|
+
* One reading, at the one place the strip happens — so an `extraBody` a host brain swapped in for a single
|
|
15
|
+
* request, or one on the compaction model, is said the same way the task's own model spec is.
|
|
16
|
+
*/
|
|
1
17
|
/** OpenAI request-body keys core owns; `extraBody` cannot override these. */
|
|
2
18
|
export declare const OPENAI_RESERVED: ReadonlySet<string>;
|
|
3
19
|
/** Anthropic request-body keys core owns; `extraBody` cannot override these. (Note the asymmetry vs
|
|
@@ -9,19 +25,24 @@ export declare const ANTHROPIC_RESERVED: ReadonlySet<string>;
|
|
|
9
25
|
* The last three are NOT keys the adapter sets — they are keys it must be IMPOSSIBLE to set. The
|
|
10
26
|
* Open Responses lane is stateless by contract (this engine is the transcript authority), and
|
|
11
27
|
* `extraBody` is the only other path to the request body, so `store` / `previous_response_id` /
|
|
12
|
-
* `conversation` are reserved purely to close it. A deployment that sets one gets the
|
|
13
|
-
*
|
|
28
|
+
* `conversation` are reserved purely to close it. A deployment that sets one gets a stripped key on the
|
|
29
|
+
* wire and the drop announced, never a silently server-linked turn.
|
|
14
30
|
*/
|
|
15
31
|
export declare const RESPONSES_RESERVED: ReadonlySet<string>;
|
|
16
|
-
/** Reserved set for a model's API. */
|
|
17
|
-
export declare function reservedFor(api: string): ReadonlySet<string>;
|
|
18
32
|
/**
|
|
19
33
|
* Merge `extraBody` into a brain's already-built request `body`, dropping any key the brain owns so core
|
|
20
|
-
* always wins.
|
|
34
|
+
* always wins. `body` is a NEW object (passthrough keys first, then core keys) when `extraBody` is set; the
|
|
21
35
|
* exact `body` reference (no allocation, byte-identical serialization) when it isn't — so an existing
|
|
22
36
|
* deployment with no `extraBody` is unaffected.
|
|
37
|
+
*
|
|
38
|
+
* `dropped` is the keys of `extraBody` that were stripped, in `extraBody`'s insertion order, names only (a
|
|
39
|
+
* value never leaves this function except inside `body`). It is a property of the same walk that strips, so
|
|
40
|
+
* what is said and what is dropped cannot disagree; empty when nothing was stripped.
|
|
23
41
|
*/
|
|
24
|
-
export declare function applyExtraBody(body: Record<string, unknown>, extraBody: Record<string, unknown> | undefined, reserved: ReadonlySet<string>):
|
|
42
|
+
export declare function applyExtraBody(body: Record<string, unknown>, extraBody: Record<string, unknown> | undefined, reserved: ReadonlySet<string>): {
|
|
43
|
+
body: Record<string, unknown>;
|
|
44
|
+
dropped: readonly string[];
|
|
45
|
+
};
|
|
25
46
|
/** The auth-bearing header names (case-fold), single-sourced for the credential enforcement
|
|
26
47
|
* (`applyRouteCredentialHeaders`, route-adjudicator.ts — the ONE authority over auth spelling: a
|
|
27
48
|
* per-model winner strips every carrier, any case, and re-asserts the winning bag's own),
|
|
@@ -99,5 +120,3 @@ export declare const OUTPUT_CAP_KEYS: Readonly<Record<"openai" | "anthropic" | "
|
|
|
99
120
|
* request that carries two. Smallest wins so a consumer reasoning about the bound stays conservative.
|
|
100
121
|
*/
|
|
101
122
|
export declare function effectiveOutputCap(body: Record<string, unknown>, keys: readonly string[]): number | undefined;
|
|
102
|
-
/** Names in `extraBody` that collide with a reserved (core-owned) key — for a load-time warning. */
|
|
103
|
-
export declare function reservedCollisions(extraBody: Record<string, unknown> | undefined, reserved: ReadonlySet<string>): string[];
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { RESPONSES_APIS } from "./reasoning.js";
|
|
2
1
|
export const OPENAI_RESERVED = new Set([
|
|
3
2
|
"model",
|
|
4
3
|
"messages",
|
|
@@ -39,20 +38,19 @@ export const RESPONSES_RESERVED = new Set([
|
|
|
39
38
|
"previous_response_id",
|
|
40
39
|
"conversation",
|
|
41
40
|
]);
|
|
42
|
-
|
|
43
|
-
if (RESPONSES_APIS.has(api))
|
|
44
|
-
return RESPONSES_RESERVED;
|
|
45
|
-
return api === "anthropic-messages" ? ANTHROPIC_RESERVED : OPENAI_RESERVED;
|
|
46
|
-
}
|
|
41
|
+
const NO_KEYS = Object.freeze([]);
|
|
47
42
|
export function applyExtraBody(body, extraBody, reserved) {
|
|
48
43
|
if (!extraBody)
|
|
49
|
-
return body;
|
|
44
|
+
return { body, dropped: NO_KEYS };
|
|
50
45
|
const passthrough = {};
|
|
46
|
+
const dropped = [];
|
|
51
47
|
for (const [k, v] of Object.entries(extraBody)) {
|
|
52
|
-
if (
|
|
48
|
+
if (reserved.has(k))
|
|
49
|
+
dropped.push(k);
|
|
50
|
+
else
|
|
53
51
|
passthrough[k] = v;
|
|
54
52
|
}
|
|
55
|
-
return { ...passthrough, ...body };
|
|
53
|
+
return { body: { ...passthrough, ...body }, dropped: dropped.length === 0 ? NO_KEYS : dropped };
|
|
56
54
|
}
|
|
57
55
|
export const AUTH_CARRIER_NAMES = new Set(["authorization", "x-api-key"]);
|
|
58
56
|
export function lockHeader(headers, lowerName, value) {
|
|
@@ -109,6 +107,3 @@ export function effectiveOutputCap(body, keys) {
|
|
|
109
107
|
}
|
|
110
108
|
return smallest;
|
|
111
109
|
}
|
|
112
|
-
export function reservedCollisions(extraBody, reserved) {
|
|
113
|
-
return extraBody ? Object.keys(extraBody).filter((k) => reserved.has(k)) : [];
|
|
114
|
-
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The route a provider request took, as the brain that built it states it: where the credential it carried came
|
|
3
|
+
* from, how that credential rode, and which knob named the request's root. One projection of the two resolutions a
|
|
4
|
+
* request build already runs ({@link import("./route-adjudicator.js").resolveRouteCredential} and
|
|
5
|
+
* {@link import("./route-adjudicator.js").resolveRequestRootOf}) — never a key value, never a URL.
|
|
6
|
+
*
|
|
7
|
+
* Who reads it: the engine's terminal-shell mint lifts the committed request's route onto
|
|
8
|
+
* `AssistantMessage.apiErrorRoute` (only beside `isApiErrorMessage`), and a run whose terminal is a provider refusal
|
|
9
|
+
* carries it on `terminal.detail.route`. {@link ROUTE_CREDENTIAL_PAIRING} is the same vocabulary as a table: one row
|
|
10
|
+
* per declaration shape a request can carry, naming the knob(s) the credential is read from and the root knob it is
|
|
11
|
+
* paired with — the machine-readable half of the pairing law whose verdicts the conformance corpus pins.
|
|
12
|
+
*/
|
|
13
|
+
import type { RouteCredential } from "../internal/llm.js";
|
|
14
|
+
/** Where the credential a request would carry came from.
|
|
15
|
+
* - `"per-model"` — resolved FOR this model: a per-call key/headers from the per-model auth hook
|
|
16
|
+
* (`getApiKeyAndHeaders`), or an auth-bearing header declared on `Model.headers`. Paired by
|
|
17
|
+
* construction (the resolver was asked about THIS entry), so the adjudicator never refuses it.
|
|
18
|
+
* - `"deployment-config"` — the brain construction-time fallback (`config.apiKey` / an auth header
|
|
19
|
+
* in `config.headers`). Paired only with the deployment's own declared root (`config.baseUrl`).
|
|
20
|
+
* - `"absent"` — no credential anywhere. Legal for keyless gateways; refused only where an entry
|
|
21
|
+
* declares its OWN URL away from a declared deployment root (a distinct endpoint with no
|
|
22
|
+
* credential route is a configuration hole, not a keyless deployment). */
|
|
23
|
+
export declare const ROUTE_CREDENTIAL_SOURCES: readonly ["per-model", "deployment-config", "absent"];
|
|
24
|
+
export type RouteCredentialSource = (typeof ROUTE_CREDENTIAL_SOURCES)[number];
|
|
25
|
+
/** How a credential rode: the brain's apiKey knob (written as the lane's own auth header), or an auth-bearing header
|
|
26
|
+
* from one of the header bags. */
|
|
27
|
+
export declare const ROUTE_CARRIERS: readonly ["apiKey", "header"];
|
|
28
|
+
export type RouteCarrier = (typeof ROUTE_CARRIERS)[number];
|
|
29
|
+
/** The header bag an auth-bearing header came from: the per-call options (the per-model auth hook's headers), the
|
|
30
|
+
* model entry (`Model.headers`), or the brain's construction config (`config.headers`). */
|
|
31
|
+
export declare const ROUTE_CARRIER_BAGS: readonly ["options", "model", "config"];
|
|
32
|
+
export type RouteCarrierBag = (typeof ROUTE_CARRIER_BAGS)[number];
|
|
33
|
+
/** Which knob named the request's root: the model entry (`Model.baseUrl`), the brain's construction config
|
|
34
|
+
* (`config.baseUrl`), or the lane's own default endpoint (neither was declared). */
|
|
35
|
+
export declare const REQUEST_ROOT_ORIGINS: readonly ["model", "deployment", "lane-default"];
|
|
36
|
+
export type RequestRootOrigin = (typeof REQUEST_ROOT_ORIGINS)[number];
|
|
37
|
+
/**
|
|
38
|
+
* The route a request took ({@link requestRouteOf}). Never a key value and never a URL — the words name knobs, so the
|
|
39
|
+
* value may travel wherever the failure it describes travels.
|
|
40
|
+
* - `credentialSource` — {@link RouteCredentialSource}.
|
|
41
|
+
* - `carrier` — how the credential rode ({@link RouteCarrier}); absent exactly when `credentialSource` is `"absent"`.
|
|
42
|
+
* - `carrierBag` — the header bag whose auth header rode ({@link RouteCarrierBag}); present exactly when one did:
|
|
43
|
+
* with carrier `"header"`, and beside carrier `"apiKey"` in the deployment shape that sets both `config.apiKey`
|
|
44
|
+
* and an auth header in `config.headers` (both ride).
|
|
45
|
+
* - `root` — which knob named the request's root ({@link RequestRootOrigin}).
|
|
46
|
+
* The legal shapes are exactly the rows of {@link ROUTE_CREDENTIAL_PAIRING}.
|
|
47
|
+
*/
|
|
48
|
+
export interface RequestRoute {
|
|
49
|
+
credentialSource: RouteCredentialSource;
|
|
50
|
+
carrier?: RouteCarrier;
|
|
51
|
+
carrierBag?: RouteCarrierBag;
|
|
52
|
+
root: RequestRootOrigin;
|
|
53
|
+
}
|
|
54
|
+
/** The route of a request carrying `credential`, rooted at the knob `root` names — the one mint of a
|
|
55
|
+
* {@link RequestRoute}. Reads the credential's SHAPE only; its key value never leaves this function. */
|
|
56
|
+
export declare function requestRouteOf(credential: RouteCredential, root: RequestRootOrigin): RequestRoute;
|
|
57
|
+
/** One row of {@link ROUTE_CREDENTIAL_PAIRING}. */
|
|
58
|
+
export interface RouteCredentialPairingRow {
|
|
59
|
+
readonly credentialSource: RouteCredentialSource;
|
|
60
|
+
readonly carrier?: RouteCarrier;
|
|
61
|
+
readonly carrierBag?: RouteCarrierBag;
|
|
62
|
+
/** The knob(s) the credential is read from, in this engine's own spelling (`getApiKeyAndHeaders` is the per-model
|
|
63
|
+
* auth hook, whose answer reaches the brain as the per-call options). Empty for `"absent"`. */
|
|
64
|
+
readonly credentialKnobs: readonly string[];
|
|
65
|
+
/** The root knob the credential is paired with: `"Model.baseUrl"` for a per-model credential (paired by
|
|
66
|
+
* construction — it was resolved for this entry), `"config.baseUrl"` for the deployment credential (paired only
|
|
67
|
+
* when that root is declared and the request targets it; undeclared = the unpinned posture). Absent for
|
|
68
|
+
* `"absent"`. */
|
|
69
|
+
readonly pairsWith?: "Model.baseUrl" | "config.baseUrl";
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The pairing law as a table — one row per route shape a request can carry, in resolution precedence (an earlier
|
|
73
|
+
* row's source wins when several are configured; the three deployment rows are one rank, the deployment credential
|
|
74
|
+
* judged as one). A consumer naming "which key was that" reads the row a {@link RequestRoute} lands on (same
|
|
75
|
+
* `credentialSource` / `carrier` / `carrierBag`), never a sentence. The verdicts the law gives these shapes are the
|
|
76
|
+
* conformance corpus's (`ROUTE_ADJUDICATION_CONFORMANCE_CORPUS`).
|
|
77
|
+
*/
|
|
78
|
+
export declare const ROUTE_CREDENTIAL_PAIRING: readonly RouteCredentialPairingRow[];
|
|
79
|
+
/** The pairing row a route lands on, `undefined` for a shape no request carries. */
|
|
80
|
+
export declare function routePairingRowOf(route: Pick<RequestRoute, "credentialSource" | "carrier" | "carrierBag">): RouteCredentialPairingRow | undefined;
|
|
81
|
+
/** A route as a value this engine did not build carries it (a host Brain's message, an adapter's request): each member
|
|
82
|
+
* read once, and the whole value admitted only as a shape some request carries — a {@link ROUTE_CREDENTIAL_PAIRING}
|
|
83
|
+
* row plus a closed-set root. Anything else is no route (absent), never a partial one. */
|
|
84
|
+
export declare function admittedRequestRoute(value: unknown): RequestRoute | undefined;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { readMember } from "../core/thrown-value.js";
|
|
2
|
+
export const ROUTE_CREDENTIAL_SOURCES = Object.freeze(["per-model", "deployment-config", "absent"]);
|
|
3
|
+
export const ROUTE_CARRIERS = Object.freeze(["apiKey", "header"]);
|
|
4
|
+
export const ROUTE_CARRIER_BAGS = Object.freeze(["options", "model", "config"]);
|
|
5
|
+
export const REQUEST_ROOT_ORIGINS = Object.freeze(["model", "deployment", "lane-default"]);
|
|
6
|
+
export function requestRouteOf(credential, root) {
|
|
7
|
+
const carrier = credential.apiKey !== undefined ? "apiKey" : credential.headersBorne === true ? "header" : undefined;
|
|
8
|
+
return {
|
|
9
|
+
credentialSource: credential.source,
|
|
10
|
+
...(carrier !== undefined ? { carrier } : {}),
|
|
11
|
+
...(credential.headersBorne === true && credential.carrierBag !== undefined ? { carrierBag: credential.carrierBag } : {}),
|
|
12
|
+
root,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export const ROUTE_CREDENTIAL_PAIRING = Object.freeze([
|
|
16
|
+
{ credentialSource: "per-model", carrier: "apiKey", credentialKnobs: ["getApiKeyAndHeaders().apiKey"], pairsWith: "Model.baseUrl" },
|
|
17
|
+
{ credentialSource: "per-model", carrier: "header", carrierBag: "options", credentialKnobs: ["getApiKeyAndHeaders().headers"], pairsWith: "Model.baseUrl" },
|
|
18
|
+
{ credentialSource: "per-model", carrier: "header", carrierBag: "model", credentialKnobs: ["Model.headers"], pairsWith: "Model.baseUrl" },
|
|
19
|
+
{ credentialSource: "deployment-config", carrier: "apiKey", credentialKnobs: ["config.apiKey"], pairsWith: "config.baseUrl" },
|
|
20
|
+
{ credentialSource: "deployment-config", carrier: "apiKey", carrierBag: "config", credentialKnobs: ["config.apiKey", "config.headers"], pairsWith: "config.baseUrl" },
|
|
21
|
+
{ credentialSource: "deployment-config", carrier: "header", carrierBag: "config", credentialKnobs: ["config.headers"], pairsWith: "config.baseUrl" },
|
|
22
|
+
{ credentialSource: "absent", credentialKnobs: [] },
|
|
23
|
+
].map((row) => Object.freeze({ ...row, credentialKnobs: Object.freeze([...row.credentialKnobs]) })));
|
|
24
|
+
export function routePairingRowOf(route) {
|
|
25
|
+
return ROUTE_CREDENTIAL_PAIRING.find((row) => row.credentialSource === route.credentialSource && row.carrier === route.carrier && row.carrierBag === route.carrierBag);
|
|
26
|
+
}
|
|
27
|
+
const ROOT_ORIGIN_SET = new Set(REQUEST_ROOT_ORIGINS);
|
|
28
|
+
export function admittedRequestRoute(value) {
|
|
29
|
+
if (value === null || typeof value !== "object")
|
|
30
|
+
return undefined;
|
|
31
|
+
const credentialSource = readMember(value, "credentialSource");
|
|
32
|
+
const carrier = readMember(value, "carrier");
|
|
33
|
+
const carrierBag = readMember(value, "carrierBag");
|
|
34
|
+
const root = readMember(value, "root");
|
|
35
|
+
if (!ROOT_ORIGIN_SET.has(root))
|
|
36
|
+
return undefined;
|
|
37
|
+
const row = ROUTE_CREDENTIAL_PAIRING.find((r) => r.credentialSource === credentialSource && r.carrier === carrier && r.carrierBag === carrierBag);
|
|
38
|
+
if (row === undefined)
|
|
39
|
+
return undefined;
|
|
40
|
+
return { credentialSource: row.credentialSource, ...(row.carrier !== undefined ? { carrier: row.carrier } : {}), ...(row.carrierBag !== undefined ? { carrierBag: row.carrierBag } : {}), root: root };
|
|
41
|
+
}
|
package/dist/brain/retry.d.ts
CHANGED
|
@@ -24,6 +24,14 @@ export declare function parseRetryAfter(res: Response | undefined): number | und
|
|
|
24
24
|
* (a stale stamp carries no wait, so the caller falls back to its computed backoff).
|
|
25
25
|
*/
|
|
26
26
|
export declare function parseRateLimitReset(res: Response | undefined): number | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* The one read of `anthropic-ratelimit-unified-reset`: the absolute instant (epoch ms, wall clock) the window
|
|
29
|
+
* reopens, or undefined when absent, unparseable or not a positive stamp. The backoff floor above reads it
|
|
30
|
+
* relative to now; a quota verdict carries it as the instant itself (`provider-dialect.ts`).
|
|
31
|
+
*/
|
|
32
|
+
export declare function readUnifiedResetEpochMs(headers: {
|
|
33
|
+
get?: (name: string) => string | null;
|
|
34
|
+
} | undefined | null): number | undefined;
|
|
27
35
|
/**
|
|
28
36
|
* A single provider wait hint after clamping, carrying enough of its own history to disclose a
|
|
29
37
|
* truncation: `rawMs` is only set when the response actually asked for more than {@link
|
package/dist/brain/retry.js
CHANGED
|
@@ -15,14 +15,20 @@ export function parseRetryAfter(res) {
|
|
|
15
15
|
return undefined;
|
|
16
16
|
}
|
|
17
17
|
export function parseRateLimitReset(res) {
|
|
18
|
-
const
|
|
18
|
+
const at = readUnifiedResetEpochMs(res?.headers);
|
|
19
|
+
if (at === undefined)
|
|
20
|
+
return undefined;
|
|
21
|
+
const ms = at - Date.now();
|
|
22
|
+
return ms > 0 ? ms : undefined;
|
|
23
|
+
}
|
|
24
|
+
export function readUnifiedResetEpochMs(headers) {
|
|
25
|
+
const h = headers?.get?.("anthropic-ratelimit-unified-reset");
|
|
19
26
|
if (!h)
|
|
20
27
|
return undefined;
|
|
21
28
|
const epochSecs = Number(h);
|
|
22
|
-
if (!Number.isFinite(epochSecs))
|
|
29
|
+
if (!Number.isFinite(epochSecs) || epochSecs <= 0)
|
|
23
30
|
return undefined;
|
|
24
|
-
|
|
25
|
-
return ms > 0 ? ms : undefined;
|
|
31
|
+
return Math.round(epochSecs * 1000);
|
|
26
32
|
}
|
|
27
33
|
function clampHint(rawMs) {
|
|
28
34
|
return rawMs > MAX_HEADER_WAIT_MS ? { ms: MAX_HEADER_WAIT_MS, rawMs } : { ms: rawMs };
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
import type { Model } from "../internal/llm.js";
|
|
41
41
|
import type { RouteAdjudication, RouteCredential, RoutePairingConfig, RoutePairingPosture } from "../internal/llm.js";
|
|
42
42
|
import type { Brain, EngineNotice } from "../core/types.js";
|
|
43
|
+
import type { RequestRootOrigin } from "./request-route.js";
|
|
43
44
|
/** A base URL's ROUTE KEY — the value the pairing law COMPARES, folded to WIRE equivalence: the
|
|
44
45
|
* halves the wire itself treats as case-insensitive (scheme and host, RFC 9110) fold, the scheme's
|
|
45
46
|
* default port elides, and PATH and QUERY ride byte-preserved apart from the trailing slashes the
|
|
@@ -113,6 +114,12 @@ export declare function stripUrlCredentials(text: string): string;
|
|
|
113
114
|
* three homes; now it has one. Answers `""` when nothing is declared and the lane has no default —
|
|
114
115
|
* whether that is a refusal is the caller's. */
|
|
115
116
|
export declare function resolveRequestRoot(modelBaseUrl: string | undefined, configBaseUrl: string | undefined, laneDefault?: string): string;
|
|
117
|
+
/** {@link resolveRequestRoot} with the knob that named the root beside it (`RequestRootOrigin`) — the one
|
|
118
|
+
* resolution; the root a request build sends to and the root its route states cannot come from two readings. */
|
|
119
|
+
export declare function resolveRequestRootOf(modelBaseUrl: string | undefined, configBaseUrl: string | undefined, laneDefault?: string): {
|
|
120
|
+
root: string;
|
|
121
|
+
origin: RequestRootOrigin;
|
|
122
|
+
};
|
|
116
123
|
/** Whether a header bag carries an auth-bearing header (any case). */
|
|
117
124
|
export declare function hasAuthCarrier(headers: Record<string, string> | undefined): boolean;
|
|
118
125
|
/**
|
|
@@ -178,10 +178,14 @@ export function stripUrlCredentials(text) {
|
|
|
178
178
|
return text.replace(/([A-Za-z][A-Za-z0-9+.\-]*:\/\/)[^/\s"'@]*@/g, `$1${REDACTED_CREDENTIALS}@`);
|
|
179
179
|
}
|
|
180
180
|
export function resolveRequestRoot(modelBaseUrl, configBaseUrl, laneDefault = "") {
|
|
181
|
+
return resolveRequestRootOf(modelBaseUrl, configBaseUrl, laneDefault).root;
|
|
182
|
+
}
|
|
183
|
+
export function resolveRequestRootOf(modelBaseUrl, configBaseUrl, laneDefault = "") {
|
|
181
184
|
const entry = judgeRequestRoot(modelBaseUrl, "Model.baseUrl");
|
|
182
185
|
const declared = judgeRequestRoot(configBaseUrl, "config.baseUrl");
|
|
186
|
+
const origin = entry !== undefined ? "model" : declared !== undefined ? "deployment" : "lane-default";
|
|
183
187
|
const chosen = (entry ?? declared)?.parsed ?? servableParse(laneDefault.trim());
|
|
184
|
-
return chosen === undefined ? laneDefault : canonicalRootSpelling(chosen);
|
|
188
|
+
return { root: chosen === undefined ? laneDefault : canonicalRootSpelling(chosen), origin };
|
|
185
189
|
}
|
|
186
190
|
export function hasAuthCarrier(headers) {
|
|
187
191
|
if (!headers)
|
|
@@ -130,3 +130,23 @@ export declare function runWithReasoningWireFacts<T>(observe: (f: ReasoningWireF
|
|
|
130
130
|
* {@link runWithReasoningWireFacts}).
|
|
131
131
|
*/
|
|
132
132
|
export declare function reportReasoningWireFacts(facts: ReasoningWireFacts): void;
|
|
133
|
+
/** What a request that is about to be sent had stripped from its model's `extraBody`: the wire adapter's `api`, the catalog id
|
|
134
|
+
* the request was sent as, and the stripped key NAMES (never a value), in `extraBody`'s order. */
|
|
135
|
+
export interface ExtraBodyDroppedReport {
|
|
136
|
+
api: string;
|
|
137
|
+
modelId: string;
|
|
138
|
+
keys: readonly string[];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Run `fn` with a per-run extraBody-strip sink in scope — the FOURTH brain→runner ALS channel, same decoupling contract as
|
|
142
|
+
* its siblings (no brain-interface field, no per-call option, no-op outside the scope, a report never changes a call's
|
|
143
|
+
* outcome). Unlike them it spans the WHOLE leg (the Runner scopes it around everything the leg does, the end-of-task
|
|
144
|
+
* compaction included), is NOT shielded around the leg's internal calls (the compaction summary, a side query fired from a
|
|
145
|
+
* tool, the classifier: their model specs strip keys too), and is NOT revoked on settlement: it writes to no returned value
|
|
146
|
+
* (the report is an out-of-band notice, attributed to its run by id), and the lanes that run after the result — the
|
|
147
|
+
* next-prompt suggestions, a call the guardrail abandoned — strip keys the operator should hear about all the same.
|
|
148
|
+
*/
|
|
149
|
+
export declare function runWithExtraBodyDropped<T>(observe: (r: ExtraBodyDroppedReport) => void, fn: () => Promise<T>): Promise<T>;
|
|
150
|
+
/** Report the strip of the request the engine has SELECTED to send, to the active per-run sink, if any (called at the
|
|
151
|
+
* engine's commit points, never from `buildRequest`, which is also built speculatively). */
|
|
152
|
+
export declare function reportExtraBodyDropped(report: ExtraBodyDroppedReport): void;
|
|
@@ -57,3 +57,14 @@ export function reportReasoningWireFacts(facts) {
|
|
|
57
57
|
catch {
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
+
const extraBodyDroppedSinkStore = new AsyncLocalStorage();
|
|
61
|
+
export function runWithExtraBodyDropped(observe, fn) {
|
|
62
|
+
return extraBodyDroppedSinkStore.run({ observe }, fn);
|
|
63
|
+
}
|
|
64
|
+
export function reportExtraBodyDropped(report) {
|
|
65
|
+
try {
|
|
66
|
+
extraBodyDroppedSinkStore.getStore()?.observe(report);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import { type AssistantMessage, type Model, createAssistantMessageEventStream } from "../internal/llm.js";
|
|
1
|
+
import { type AssistantMessage, type Model, type Usage, createAssistantMessageEventStream } from "../internal/llm.js";
|
|
2
|
+
import type { BrainRetryErrClass } from "../core/types.js";
|
|
3
|
+
import type { AssertAllKeysHandled } from "../core/ask-origin.js";
|
|
4
|
+
import { type RequestRoute } from "./request-route.js";
|
|
5
|
+
import { type ProviderDialect } from "./provider-dialect.js";
|
|
2
6
|
import { type BrainTimeoutConfig } from "./timeout.js";
|
|
3
7
|
/**
|
|
4
8
|
* Shared streaming engine for the OpenAI- and Anthropic-shaped brains (design/32, consolidation).
|
|
@@ -130,6 +134,21 @@ export interface SSERequest {
|
|
|
130
134
|
* come back identical; an adapter that declares nothing therefore permits no body change at all.
|
|
131
135
|
*/
|
|
132
136
|
capDerivedPaths?: readonly string[];
|
|
137
|
+
/**
|
|
138
|
+
* The keys `Model.extraBody` carried that this adapter owns and therefore stripped from the body
|
|
139
|
+
* ({@link import("./request-params.js").applyExtraBody}'s `dropped`), names only; empty or absent when
|
|
140
|
+
* nothing was stripped. The engine reports them to the run's sink ({@link reportExtraBodyDropped}) when this
|
|
141
|
+
* request is committed to be sent, which is where the Runner announces them.
|
|
142
|
+
*/
|
|
143
|
+
extraBodyDropped?: readonly string[];
|
|
144
|
+
/**
|
|
145
|
+
* The route this request takes, as the adapter that built it states it ({@link RequestRoute}, minted by
|
|
146
|
+
* `requestRouteOf` from the same credential and root resolutions the build used). The engine lifts the committed
|
|
147
|
+
* request's route onto the terminal shell of a provider failure (`AssistantMessage.apiErrorRoute`, beside
|
|
148
|
+
* `isApiErrorMessage`) — every failure of the request states the same route, so it is declared once here rather
|
|
149
|
+
* than on each failure. Absent = the adapter states none.
|
|
150
|
+
*/
|
|
151
|
+
route?: RequestRoute;
|
|
133
152
|
/**
|
|
134
153
|
* Called by the engine once, if and only if THIS request becomes the one that is sent.
|
|
135
154
|
*
|
|
@@ -168,6 +187,20 @@ export interface StreamControls {
|
|
|
168
187
|
sawContentToken(): void;
|
|
169
188
|
/** Cancel the underlying stream (e.g. degenerate-repetition cutoff). The read loop then ends. */
|
|
170
189
|
cancel(): void;
|
|
190
|
+
/** The endpoint this call goes to, as the provider dialect table names it (`undefined` = none declares it):
|
|
191
|
+
* what an in-band error frame is judged by. */
|
|
192
|
+
dialect: ProviderDialect | undefined;
|
|
193
|
+
/** Hand the engine what this attempt produced — its final content and the provider-reported usage — before
|
|
194
|
+
* raising the provider's own in-band failure from `finalize`: the terminal message the engine mints for that
|
|
195
|
+
* failure keeps it (the text the provider streamed, the usage it reported), rather than an empty shell. */
|
|
196
|
+
keepOutput(output: KeptOutput): void;
|
|
197
|
+
}
|
|
198
|
+
/** The output a parser hands over with {@link StreamControls.keepOutput}. */
|
|
199
|
+
export interface KeptOutput {
|
|
200
|
+
content: AssistantMessage["content"];
|
|
201
|
+
usage: Usage;
|
|
202
|
+
/** The provider reported no usage frame (the zeros are not a measurement). */
|
|
203
|
+
usageMissing?: true;
|
|
171
204
|
}
|
|
172
205
|
export interface StreamParser {
|
|
173
206
|
/** Handle one raw SSE line (`data: {...}`); parse, emit events, call `ctrl.sawContentToken()` on content. */
|
|
@@ -215,6 +248,23 @@ export interface StreamParser {
|
|
|
215
248
|
*/
|
|
216
249
|
sealForRetry(): void;
|
|
217
250
|
}
|
|
251
|
+
/**
|
|
252
|
+
* The phase a retry-wait frame of each {@link BrainRetryErrClass} carries — ONE table, so a frame's two
|
|
253
|
+
* classifications are never mapped separately: the phase is what the brain is doing about the wait (waiting
|
|
254
|
+
* out a rate limit, re-connecting, re-sending), read off why it waits. Every retry-wait frame this engine
|
|
255
|
+
* emits — the connect ladder, the first-byte lane, the output-cap re-send, the mid-stream tiers — reads it.
|
|
256
|
+
*/
|
|
257
|
+
declare const RETRY_PHASE_OF_ERR_CLASS: {
|
|
258
|
+
readonly connect_refused: "reconnecting";
|
|
259
|
+
readonly transport: "reconnecting";
|
|
260
|
+
readonly stall: "reconnecting";
|
|
261
|
+
readonly rate_limit: "rate_limited";
|
|
262
|
+
readonly server: "retrying";
|
|
263
|
+
readonly http: "retrying";
|
|
264
|
+
readonly output_cap: "retrying";
|
|
265
|
+
};
|
|
266
|
+
/** Compile-time fence: every retry class has a phase row. */
|
|
267
|
+
export type RetryPhaseTableCoversEveryErrClass = AssertAllKeysHandled<Exclude<BrainRetryErrClass, keyof typeof RETRY_PHASE_OF_ERR_CLASS>>;
|
|
218
268
|
/**
|
|
219
269
|
* Run one streaming request end-to-end and drive the provider `parser`. Returns a fresh event stream;
|
|
220
270
|
* never throws (errors are pushed as `error` events, mirroring the Brain contract).
|
|
@@ -249,3 +299,4 @@ export declare function runStreamingBrain(args: {
|
|
|
249
299
|
* and never more than the brain's own budget ({@link resolveMaxRetries}); a non-finite or negative value caps nothing. */
|
|
250
300
|
maxRetries?: number;
|
|
251
301
|
}): ReturnType<typeof createAssistantMessageEventStream>;
|
|
302
|
+
export {};
|