@sema-agent/core 7.54.1 → 7.55.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 +437 -0
- package/dist/agents/agent-transcript-tool.js +2 -1
- package/dist/agents/builtin-agents.d.ts +12 -14
- package/dist/agents/cc-peer-directory.d.ts +36 -0
- package/dist/agents/cc-peer-directory.js +138 -0
- package/dist/agents/cc-peer-wire.d.ts +105 -0
- package/dist/agents/cc-peer-wire.js +98 -0
- package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
- package/dist/agents/cc-uds-peer-channel.js +457 -0
- package/dist/agents/cross-session-envelope.d.ts +4 -1
- package/dist/agents/cross-session-envelope.js +8 -1
- package/dist/agents/cross-session-judge.d.ts +2 -2
- package/dist/agents/list-agents-tool.js +2 -1
- package/dist/agents/observer.d.ts +4 -5
- package/dist/agents/observer.js +2 -1
- package/dist/agents/peer-admission.d.ts +6 -0
- package/dist/agents/peer-admission.js +4 -1
- package/dist/agents/peer-directory.d.ts +43 -9
- package/dist/agents/peer-directory.js +66 -23
- package/dist/agents/peer-notices.d.ts +1 -1
- package/dist/agents/peer-session-drain.d.ts +3 -1
- package/dist/agents/peer-session-drain.js +1 -0
- package/dist/agents/read-inbox-tool.js +2 -1
- package/dist/agents/retain-ledger.d.ts +1 -1
- package/dist/agents/roster-store.d.ts +1 -1
- package/dist/agents/send-message-tool.d.ts +10 -0
- package/dist/agents/send-message-tool.js +34 -5
- package/dist/agents/subagent.d.ts +34 -79
- package/dist/agents/subagent.js +45 -46
- package/dist/agents/tool-filter.d.ts +29 -46
- package/dist/agents/tool-filter.js +8 -31
- package/dist/agents/verify.d.ts +3 -3
- package/dist/brain/anthropic.js +14 -9
- package/dist/brain/errors.d.ts +15 -0
- package/dist/brain/errors.js +10 -0
- package/dist/brain/model-presets.d.ts +4 -4
- package/dist/brain/open-responses.js +15 -10
- package/dist/brain/openai.js +17 -12
- package/dist/brain/provider-dialect.d.ts +39 -3
- package/dist/brain/provider-dialect.js +28 -0
- package/dist/brain/reasoning.d.ts +1 -1
- package/dist/brain/request-params.d.ts +55 -5
- package/dist/brain/request-params.js +35 -3
- package/dist/brain/retry.d.ts +1 -1
- package/dist/brain/route-adjudicator.d.ts +15 -0
- package/dist/brain/route-adjudicator.js +15 -0
- package/dist/brain/stream-engine.js +6 -5
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/core/advisor-verdict.d.ts +120 -0
- package/dist/core/advisor-verdict.js +92 -0
- package/dist/core/agent-definition.d.ts +7 -8
- package/dist/core/allow-entry.d.ts +49 -23
- package/dist/core/allow-entry.js +57 -32
- package/dist/core/allow-rule-shadow.d.ts +7 -0
- package/dist/core/approval-object.d.ts +2 -1
- package/dist/core/approval-object.js +6 -6
- package/dist/core/ask-origin.d.ts +63 -11
- package/dist/core/ask-origin.js +27 -5
- package/dist/core/ask-question.js +10 -4
- package/dist/core/auto-compaction.d.ts +11 -8
- package/dist/core/auto-compaction.js +4 -2
- package/dist/core/auto-mode-arming.d.ts +2 -2
- package/dist/core/auto-mode-defaults.d.ts +8 -8
- package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
- package/dist/core/auto-mode-prompt.d.ts +1 -1
- package/dist/core/auto-mode.d.ts +17 -9
- package/dist/core/auto-mode.js +9 -6
- package/dist/core/background-agent-store.d.ts +3 -3
- package/dist/core/canonical-json.d.ts +1 -1
- package/dist/core/canonical-json.js +2 -2
- package/dist/core/checkpoint-requirements.d.ts +6 -3
- package/dist/core/checkpoint-requirements.js +4 -14
- package/dist/core/checkpoint-store.d.ts +80 -51
- package/dist/core/checkpoint-store.js +56 -74
- package/dist/core/child-clamp-seats.d.ts +6 -0
- package/dist/core/child-clamp-seats.js +3 -16
- package/dist/core/compliance.d.ts +2 -2
- package/dist/core/context-edit.d.ts +6 -7
- package/dist/core/cross-boundary-taint.d.ts +9 -3
- package/dist/core/cross-boundary-taint.js +5 -3
- package/dist/core/decision-receipt.js +2 -2
- package/dist/core/effective-path-target.d.ts +1 -1
- package/dist/core/engine-notice.d.ts +19 -5
- package/dist/core/exec-output-tail.d.ts +1 -1
- package/dist/core/file-history-retention.d.ts +1 -1
- package/dist/core/file-history-store.d.ts +59 -9
- package/dist/core/file-history-store.js +35 -17
- package/dist/core/gate-fold.js +3 -2
- package/dist/core/gate-lanes.js +12 -8
- package/dist/core/gate-outcome.d.ts +17 -4
- package/dist/core/gate-outcome.js +30 -0
- package/dist/core/governance-codes.d.ts +13 -3
- package/dist/core/governance-codes.js +10 -0
- package/dist/core/hands-band.d.ts +1 -1
- package/dist/core/hooks.d.ts +4 -4
- package/dist/core/host-target.d.ts +49 -0
- package/dist/core/host-target.js +59 -0
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/lsp-diagnostics.d.ts +4 -4
- package/dist/core/lsp.d.ts +3 -3
- package/dist/core/mailbox-store.d.ts +4 -0
- package/dist/core/mcp-connection-pool.d.ts +18 -2
- package/dist/core/mcp-connection-pool.js +53 -6
- package/dist/core/mcp-failure.d.ts +23 -4
- package/dist/core/mcp-failure.js +26 -11
- package/dist/core/mcp-listing-drift.d.ts +10 -0
- package/dist/core/mcp-listing-drift.js +6 -0
- package/dist/core/mcp-server-link.d.ts +173 -0
- package/dist/core/mcp-server-link.js +127 -0
- package/dist/core/mcp-server-spec.d.ts +4 -2
- package/dist/core/mcp-session-end.d.ts +26 -0
- package/dist/core/mcp-session-end.js +29 -0
- package/dist/core/mcp-startup-request.d.ts +17 -0
- package/dist/core/mcp-startup-request.js +17 -0
- package/dist/core/mcp.d.ts +13 -13
- package/dist/core/mcp.js +187 -162
- package/dist/core/media-byte-cap.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +9 -9
- package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
- package/dist/core/memory-engine/tools.js +4 -1
- package/dist/core/mode-policy.d.ts +1 -1
- package/dist/core/namespaced-rule-name.d.ts +33 -7
- package/dist/core/namespaced-rule-name.js +39 -25
- package/dist/core/output-style.d.ts +1 -1
- package/dist/core/param-rule-reach.d.ts +15 -0
- package/dist/core/param-rule-reach.js +30 -0
- package/dist/core/parent-spec-seat.d.ts +8 -1
- package/dist/core/parent-spec-seat.js +4 -0
- package/dist/core/pause-registry.d.ts +16 -5
- package/dist/core/pause-registry.js +6 -2
- package/dist/core/peer-channel.d.ts +70 -0
- package/dist/core/peer-channel.js +1 -0
- package/dist/core/permission-rule-consent.d.ts +11 -5
- package/dist/core/permission-rule-consent.js +37 -30
- package/dist/core/permission-rule-model.d.ts +233 -64
- package/dist/core/permission-rule-model.js +384 -85
- package/dist/core/permission-rule-provider.d.ts +2 -1
- package/dist/core/permission-rule-store.d.ts +20 -25
- package/dist/core/permission-rule-store.js +1 -4
- package/dist/core/permission-rule-sync.d.ts +11 -2
- package/dist/core/permission-rule-sync.js +8 -1
- package/dist/core/permission-rules.d.ts +49 -11
- package/dist/core/permission-rules.js +123 -89
- package/dist/core/persisted-rule-arms.d.ts +4 -2
- package/dist/core/present-plan-tool.js +3 -1
- package/dist/core/protocol-naming.d.ts +2 -2
- package/dist/core/read-only-shell-table.d.ts +1 -1
- package/dist/core/read-only-shell.d.ts +1 -1
- package/dist/core/roles.d.ts +6 -2
- package/dist/core/roles.js +45 -44
- package/dist/core/rule-offer-read.d.ts +53 -0
- package/dist/core/rule-offer-read.js +146 -0
- package/dist/core/rule-owner.d.ts +46 -0
- package/dist/core/rule-owner.js +28 -0
- package/dist/core/runner/advisor-instructions.d.ts +70 -0
- package/dist/core/runner/advisor-instructions.js +61 -0
- package/dist/core/runner/advisor-tool.d.ts +33 -0
- package/dist/core/runner/advisor-tool.js +112 -0
- package/dist/core/runner/announce-once-ledger.d.ts +4 -26
- package/dist/core/runner/announce-once-ledger.js +14 -46
- package/dist/core/runner/approval-feedback.js +6 -3
- package/dist/core/runner/assemble-result.d.ts +1 -1
- package/dist/core/runner/caller-roster.d.ts +7 -0
- package/dist/core/runner/caller-roster.js +11 -0
- package/dist/core/runner/classifier-ladder.d.ts +27 -5
- package/dist/core/runner/classifier-ladder.js +12 -11
- package/dist/core/runner/compaction-restate.d.ts +10 -6
- package/dist/core/runner/compaction-restate.js +9 -3
- package/dist/core/runner/contracts.d.ts +13 -9
- package/dist/core/runner/conversation-segment.d.ts +28 -0
- package/dist/core/runner/conversation-segment.js +42 -0
- package/dist/core/runner/cross-boundary-lane.d.ts +6 -5
- package/dist/core/runner/cross-boundary-lane.js +26 -15
- package/dist/core/runner/decide-continuation.d.ts +7 -4
- package/dist/core/runner/decide-continuation.js +2 -2
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/derived-route-fallback.d.ts +24 -24
- package/dist/core/runner/derived-route-fallback.js +9 -7
- package/dist/core/runner/gate-exit.d.ts +6 -0
- package/dist/core/runner/gate-exit.js +7 -2
- package/dist/core/runner/initial-run-state.js +1 -1
- package/dist/core/runner/permission-rule-lanes.d.ts +2 -2
- package/dist/core/runner/permission-rule-lanes.js +14 -7
- package/dist/core/runner/person-path-rows.js +1 -1
- package/dist/core/runner/prepare-advisor.d.ts +63 -0
- package/dist/core/runner/prepare-advisor.js +77 -0
- package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +6 -4
- package/dist/core/runner/prepare-config-doors.js +18 -12
- package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.js +1 -1
- package/dist/core/runner/prepare-file-history.js +39 -39
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -4
- package/dist/core/runner/prepare-gate-stations.js +2 -7
- package/dist/core/runner/prepare-inherited-gate.d.ts +5 -4
- package/dist/core/runner/prepare-inherited-gate.js +3 -3
- package/dist/core/runner/prepare-park-ask.js +7 -7
- package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
- package/dist/core/runner/prepare-policy-chain.js +4 -10
- package/dist/core/runner/prepare-project-context.d.ts +5 -2
- package/dist/core/runner/prepare-project-context.js +6 -3
- package/dist/core/runner/prepare-prompt-inputs.js +1 -1
- package/dist/core/runner/prepare-protocol-tools.d.ts +2 -2
- package/dist/core/runner/prepare-protocol-tools.js +3 -2
- package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
- package/dist/core/runner/prepare-safety-scan.js +8 -6
- package/dist/core/runner/prepare-task.js +15 -18
- package/dist/core/runner/prepare-tool-disclosure-mount.js +6 -4
- package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -3
- package/dist/core/runner/prepare-wiring-manifest.js +2 -2
- package/dist/core/runner/resume-policy-outcome.js +1 -1
- package/dist/core/runner/retired-runner-deps.js +1 -1
- package/dist/core/runner/run-attachment-seats.js +0 -1
- package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
- package/dist/core/runner/run-compaction-machinery.js +2 -12
- package/dist/core/runner/run-git-lane.d.ts +1 -0
- package/dist/core/runner/run-harness-handlers.js +2 -3
- package/dist/core/runner/run-leg.js +13 -0
- package/dist/core/runner/run-settle-and-teardown.js +1 -1
- package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
- package/dist/core/runner/run-turn-boundary.d.ts +1 -0
- package/dist/core/runner/run-turn-boundary.js +14 -12
- package/dist/core/runner/session-rule-policy.d.ts +22 -21
- package/dist/core/runner/session-rule-policy.js +13 -28
- package/dist/core/runner/side-call-account.d.ts +32 -8
- package/dist/core/runner/side-call-account.js +23 -1
- package/dist/core/runner/strict-output-schema.d.ts +1 -1
- package/dist/core/runner/sub-agent-deny-lists.js +4 -3
- package/dist/core/runner/synthetic-tools.d.ts +10 -13
- package/dist/core/runner/synthetic-tools.js +4 -2
- package/dist/core/runner/tool-disclosure.js +2 -1
- package/dist/core/runner/tool-face-overlay.d.ts +2 -1
- package/dist/core/runner/tool-face-overlay.js +17 -1
- package/dist/core/runner/tool-progress-lane.d.ts +2 -2
- package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
- package/dist/core/runner/turn-attachments.d.ts +60 -67
- package/dist/core/runner-deps.d.ts +37 -37
- package/dist/core/runtime-caps.d.ts +4 -4
- package/dist/core/safety-merge-corpus.js +17 -1
- package/dist/core/same-plain-value.d.ts +40 -0
- package/dist/core/same-plain-value.js +49 -0
- package/dist/core/scheduler.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/sensitive-path-policy.js +1 -1
- package/dist/core/session-policy-store.d.ts +77 -22
- package/dist/core/session-policy-store.js +56 -14
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +80 -30
- package/dist/core/session-store.js +118 -76
- package/dist/core/session.d.ts +24 -46
- package/dist/core/shared-memory/tools.js +3 -1
- package/dist/core/shared-memory/types.d.ts +1 -1
- package/dist/core/side-query.d.ts +10 -0
- package/dist/core/side-query.js +5 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +29 -2
- package/dist/core/store-contracts/file-history-store-contract.js +43 -3
- package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
- package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
- package/dist/core/store-contracts/session-repo-contract.js +125 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +4 -7
- package/dist/core/store-contracts/session-store-contract.js +215 -41
- package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
- package/dist/core/surrogate-safe-slice.d.ts +3 -3
- package/dist/core/task-event.d.ts +10 -4
- package/dist/core/task-notification.d.ts +3 -3
- package/dist/core/task-registry-agent.d.ts +4 -4
- package/dist/core/task-registry-shared.d.ts +4 -4
- package/dist/core/task-registry-shared.js +1 -0
- package/dist/core/task-registry.d.ts +4 -4
- package/dist/core/task-registry.js +3 -1
- package/dist/core/task-result.d.ts +3 -3
- package/dist/core/task-spec.d.ts +52 -52
- package/dist/core/task-stream.d.ts +6 -6
- package/dist/core/task-tool-shape.d.ts +4 -4
- package/dist/core/tighten-task-spec.d.ts +1 -1
- package/dist/core/tool-catalog-entries.d.ts +19 -2
- package/dist/core/tool-catalog-entries.js +57 -42
- package/dist/core/tool-conformance.js +1 -0
- package/dist/core/tool-errors.d.ts +2 -2
- package/dist/core/tool-face-reader.js +5 -3
- package/dist/core/tool-face.d.ts +21 -2
- package/dist/core/tool-face.js +1 -1
- package/dist/core/tool-model-gate.d.ts +3 -3
- package/dist/core/tool-name-aliases.d.ts +29 -8
- package/dist/core/tool-name-aliases.js +27 -3
- package/dist/core/tool-name-readings.d.ts +5 -8
- package/dist/core/tool-name-readings.js +1 -2
- package/dist/core/tool-policy.d.ts +24 -5
- package/dist/core/tool-policy.js +34 -10
- package/dist/core/tool-registry.d.ts +14 -7
- package/dist/core/tool-registry.js +17 -7
- package/dist/core/tool-result-store.js +2 -1
- package/dist/core/tool-roster.d.ts +47 -18
- package/dist/core/tool-roster.js +53 -32
- package/dist/core/tool-spec-members.js +1 -1
- package/dist/core/tool-spec.d.ts +35 -21
- package/dist/core/tools.js +3 -2
- package/dist/core/trace.d.ts +4 -0
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/core/warm-resume.d.ts +1 -1
- package/dist/core/wiring-manifest.d.ts +49 -0
- package/dist/core/wiring-manifest.js +13 -5
- package/dist/core/workflow-journal-store.d.ts +62 -0
- package/dist/core/workflow-journal-store.js +77 -1
- package/dist/core/workflow-run-store.d.ts +6 -0
- package/dist/core/workflow-run-store.js +2 -0
- package/dist/engine/compaction/compaction.d.ts +9 -9
- package/dist/engine/execution-env/node-execution-env.d.ts +19 -5
- package/dist/engine/execution-env/node-execution-env.js +43 -22
- package/dist/engine/harness/agent-harness.d.ts +14 -8
- package/dist/engine/harness/agent-harness.js +33 -26
- package/dist/engine/harness/types.d.ts +29 -7
- package/dist/engine/harness/types.js +12 -1
- package/dist/engine/llm/types.d.ts +9 -9
- package/dist/engine/llm/validation.d.ts +4 -1
- package/dist/engine/llm/validation.js +13 -1
- package/dist/engine/loop/agent-loop.d.ts +1 -1
- package/dist/engine/loop/agent-loop.js +10 -8
- package/dist/engine/loop/types.d.ts +15 -13
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/memory-repo.d.ts +10 -11
- package/dist/engine/session/memory-repo.js +13 -8
- package/dist/engine/session/parent-chain-guard.d.ts +3 -2
- package/dist/engine/session/parent-chain-guard.js +1 -1
- package/dist/engine/session/repo-utils.d.ts +31 -3
- package/dist/engine/session/repo-utils.js +42 -5
- package/dist/index.d.ts +27 -15
- package/dist/index.js +21 -11
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/harness.d.ts +3 -3
- package/dist/internal/harness.js +2 -2
- package/dist/internal/llm.d.ts +1 -1
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/goal.js +2 -2
- package/dist/orchestration/run-workflow-tool.d.ts +2 -2
- package/dist/orchestration/run-workflow-tool.js +5 -3
- package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
- package/dist/orchestration/workflow-types.d.ts +18 -0
- package/dist/orchestration/workflow-types.js +6 -0
- package/dist/orchestration/workflow.d.ts +2 -13
- package/dist/orchestration/workflow.js +21 -31
- package/dist/prompt-assembly/event-registry.js +1 -0
- package/dist/prompt-assembly/tool-catalog.d.ts +3 -0
- package/dist/prompt-assembly/tool-catalog.js +3 -0
- package/dist/prompts/default.d.ts +14 -14
- package/dist/scenarios/full-body.d.ts +4 -4
- package/dist/stores/file/adoption/adopt.d.ts +4 -3
- package/dist/stores/file/adoption/adopt.js +24 -31
- package/dist/stores/file/adoption/marker.d.ts +6 -13
- package/dist/stores/file/adoption/marker.js +6 -15
- package/dist/stores/file/checkpoint-store.d.ts +3 -0
- package/dist/stores/file/checkpoint-store.js +9 -3
- package/dist/stores/file/file-history-store.d.ts +20 -19
- package/dist/stores/file/file-history-store.js +152 -135
- package/dist/stores/file/fs-atomic.d.ts +15 -0
- package/dist/stores/file/fs-atomic.js +89 -14
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/mailbox-store.d.ts +3 -0
- package/dist/stores/file/mailbox-store.js +3 -1
- package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
- package/dist/stores/file/permission-rule-adopt.js +15 -16
- package/dist/stores/file/permission-rule-store.d.ts +18 -2
- package/dist/stores/file/permission-rule-store.js +21 -14
- package/dist/stores/file/session-policy-store.d.ts +3 -3
- package/dist/stores/file/session-store.d.ts +26 -11
- package/dist/stores/file/session-store.js +77 -40
- package/dist/stores/file/workflow-journal-store.d.ts +10 -4
- package/dist/stores/file/workflow-journal-store.js +28 -13
- package/dist/tools/artifact/artifact-text.d.ts +1 -1
- package/dist/tools/artifact/artifact-tool.js +2 -1
- package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
- package/dist/tools/fs/fs-bash.d.ts +2 -2
- package/dist/tools/fs/fs-bash.js +3 -1
- package/dist/tools/fs/fs-shared.d.ts +8 -8
- package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
- package/dist/tools/fs/notebook.d.ts +2 -2
- package/dist/tools/fs/read-deny.d.ts +29 -7
- package/dist/tools/fs/read-deny.js +63 -22
- package/dist/tools/fs/removal-targets.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +6 -6
- package/dist/tools/fs/shell-read-check.js +6 -1
- package/dist/tools/fs/shell-read-judge.d.ts +4 -0
- package/dist/tools/fs/shell-read-judge.js +5 -2
- package/dist/tools/loop-tick.d.ts +2 -2
- package/dist/tools/scheduler-tools.js +5 -1
- package/dist/tools/task-list.d.ts +7 -7
- package/dist/tools/task-list.js +5 -1
- package/dist/tools/todo.js +2 -1
- package/dist/tools/web.d.ts +1 -1
- package/dist/tools/web.js +40 -37
- package/dist/tools/worktree.d.ts +3 -3
- package/dist/tools/worktree.js +3 -1
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +5756 -5638
- package/wire-changes/core@7.55.0.json +3318 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
- package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { type AskClass, type AskOrigin, type AssertAllKeysHandled, type ModeReleaseReason, type PermissionMode, type PersistedRuleMandate } from "./ask-origin.js";
|
|
11
11
|
import { type AutoModeClassifierRound, type AutoModeFallbackCause } from "./auto-mode.js";
|
|
12
|
+
import { type AllowRuleClearance } from "./allow-rule-shadow.js";
|
|
12
13
|
/**
|
|
13
14
|
* How the wait an ask was in ENDED — the closed set. One word per way a wait can end; the `who` on the
|
|
14
15
|
* record says which party ended it and is fixed BY the word (see {@link Settlement}).
|
|
@@ -302,9 +303,9 @@ export type VetoTableCoversEveryDeniedBy = AssertAllKeysHandled<Exclude<DeniedBy
|
|
|
302
303
|
* deny came through the classifier station. The classifier ends a round three ways, and until this
|
|
303
304
|
* member the wire carried the three as one layer word plus prose:
|
|
304
305
|
* - `unavailable` — the classifier could not run (the model leg threw / rejected / ran past the cap):
|
|
305
|
-
* a fail-closed refusal that SAYS SO — the call may simply be retried later
|
|
306
|
+
* a fail-closed refusal that SAYS SO — the call may simply be retried later;
|
|
306
307
|
* - `parse_error` — the classifier answered outside its verdict contract: blocked for safety, counted by
|
|
307
|
-
* the denial limit like a ruling
|
|
308
|
+
* the denial limit like a ruling;
|
|
308
309
|
* - ABSENT beside `deniedBy: "classifier"` — the classifier's own RULING (a `<block>yes` verdict).
|
|
309
310
|
* The WHY behind an `unavailable` (error vs timeout) is not a branching fact: the deny sentence spells it
|
|
310
311
|
* and the `auto_mode.classified` trace frame carries it (`cause: "error" | "timeout"`).
|
|
@@ -350,11 +351,19 @@ export type CauseTableCoversEveryDeniedBy = AssertAllKeysHandled<Exclude<DeniedB
|
|
|
350
351
|
* candidate ladder and can name no model (a hand-built decider; a parked ancestor's cross-process rebuild,
|
|
351
352
|
* whose single fresh leg has none); or one did not rule (it could not run, or replied with no verdict) and
|
|
352
353
|
* handed the question to the approval seat, whose settlement then names the resolution that ask reached.
|
|
353
|
-
* Additive. Invariant I6 ({@link screenGateOutcome}) screens its shape.
|
|
354
|
+
* Additive. Invariant I6 ({@link screenGateOutcome}) screens its shape.
|
|
355
|
+
*
|
|
356
|
+
* `clearedBy` — the allow layer's account of a call it let run without asking: which member's allow rule cleared the ask
|
|
357
|
+
* (`hook` / `deployment` / `persisted` / `skill` / `request`) and the entries it stood on, sanitized and capped as a shadow
|
|
358
|
+
* record is, with `positions` for a list member (the indices of those entries in the list the run received — a host maps them
|
|
359
|
+
* onto the declaration it sent for this run). Present exactly when an allow member cleared a standing ask and nobody answered
|
|
360
|
+
* it: absent on a call nothing asked about, a mode's release or acceptance, the read-only arm's, the classifier's or the
|
|
361
|
+
* sandbox's allow, and a person's yes. Additive. Invariant I9 ({@link screenGateOutcome}) screens its shape. */
|
|
354
362
|
export type GateDisposition = {
|
|
355
363
|
kind: "allowed";
|
|
356
364
|
classifier?: AutoModeClassifierRound;
|
|
357
365
|
released?: ModeRelease;
|
|
366
|
+
clearedBy?: AllowRuleClearance;
|
|
358
367
|
} | {
|
|
359
368
|
kind: "denied";
|
|
360
369
|
deniedBy: DeniedBy;
|
|
@@ -415,7 +424,11 @@ export interface ModeRefusal {
|
|
|
415
424
|
* record outlives the policy of its day), every member of `classes` is an ask class, `origin` / `mandate` / `reason`,
|
|
416
425
|
* when present, are members of their closed sets, and `reason` names a member of `classes` (the mint takes it from
|
|
417
426
|
* that set) — a mode releases nothing a person answered;
|
|
418
|
-
* I8 `deniedBy === "mode"` ⇔ `mode` present (`bypassPermissions` | `dontAsk`) with `askClass` and `classes
|
|
427
|
+
* I8 `deniedBy === "mode"` ⇔ `mode` present (`bypassPermissions` | `dontAsk`) with `askClass` and `classes`;
|
|
428
|
+
* I9 `disposition.clearedBy` present ⇒ `kind === "allowed"`, no settlement and no release (an allow member cleared the ask
|
|
429
|
+
* before anyone answered it), `member` one of the allow layer's members, `entries` a list of strings, `omitted` a positive
|
|
430
|
+
* whole number when present, and `positions` — only on a list member (`request`, `deployment`) — a list of non-negative
|
|
431
|
+
* whole numbers.
|
|
419
432
|
* Nothing here is read out of an ABSENCE: an ordinary allow with no ask is `{ disposition: { kind: "allowed" } }`,
|
|
420
433
|
* a direct policy deny is `{ disposition: { kind: "denied", deniedBy: "policy" } }`, and neither carries a
|
|
421
434
|
* settlement because neither settled one.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isAskClass, isAskOrigin, isModeReleaseReason, isPermissionMode, isPersistedRuleMandate, ASK_FACES, releasableAskClassesFor } from "./ask-origin.js";
|
|
2
2
|
import { isAutoModeFallbackCause } from "./auto-mode.js";
|
|
3
|
+
import { ALLOW_RULE_MEMBERS } from "./allow-rule-shadow.js";
|
|
3
4
|
export const SETTLEMENT_KINDS = Object.freeze([
|
|
4
5
|
"human_allowed",
|
|
5
6
|
"human_refused",
|
|
@@ -153,6 +154,31 @@ export function releasePolicyDefects(g) {
|
|
|
153
154
|
const held = [askClass, ...classes];
|
|
154
155
|
return ASK_FACES.some((face) => held.every((c) => releasableAskClassesFor(face).includes(c))) ? [] : [`I7: released.classes ${JSON.stringify(classes)} is not a set one face of this engine's table releases`];
|
|
155
156
|
}
|
|
157
|
+
const LIST_MEMBERS = new Set(["request", "deployment"]);
|
|
158
|
+
const ALLOW_MEMBER_SET = new Set(ALLOW_RULE_MEMBERS);
|
|
159
|
+
function clearanceDefects(v, settled, released) {
|
|
160
|
+
const c = objectOf(v);
|
|
161
|
+
if (c === undefined)
|
|
162
|
+
return [`I9: disposition.clearedBy is not an object (${shapeOf(v)})`];
|
|
163
|
+
const out = [];
|
|
164
|
+
if (settled)
|
|
165
|
+
out.push("I9: a clearance carries no settlement — an allow rule cleared the ask before anyone answered it");
|
|
166
|
+
if (released)
|
|
167
|
+
out.push("I9: a clearance stands beside no mode release — the ask it cleared never reached the mode");
|
|
168
|
+
if (!ALLOW_MEMBER_SET.has(c.member))
|
|
169
|
+
out.push(`I9: clearedBy.member ${spelled(c.member)} is not one of the allow layer's members (${ALLOW_RULE_MEMBERS.join(", ")})`);
|
|
170
|
+
if (!Array.isArray(c.entries) || !c.entries.every((e) => typeof e === "string"))
|
|
171
|
+
out.push("I9: clearedBy.entries must be a list of strings");
|
|
172
|
+
if (c.omitted !== undefined && !(typeof c.omitted === "number" && Number.isInteger(c.omitted) && c.omitted > 0))
|
|
173
|
+
out.push(`I9: clearedBy.omitted ${spelled(c.omitted)} is not a positive whole number`);
|
|
174
|
+
if (c.positions !== undefined) {
|
|
175
|
+
if (!LIST_MEMBERS.has(c.member))
|
|
176
|
+
out.push(`I9: clearedBy.positions stands only on a list member (request, deployment), not ${spelled(c.member)}`);
|
|
177
|
+
if (!Array.isArray(c.positions) || !c.positions.every((p) => typeof p === "number" && Number.isInteger(p) && p >= 0))
|
|
178
|
+
out.push("I9: clearedBy.positions must be a list of non-negative whole numbers");
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
156
182
|
const DENY_ONLY_MEMBERS = Object.freeze(["deniedBy", "cause", "mode", "askClass", "classes"]);
|
|
157
183
|
function objectOf(v) {
|
|
158
184
|
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
|
|
@@ -252,6 +278,10 @@ export function screenGateOutcome(g, opts) {
|
|
|
252
278
|
defects.push(`I7: released.reason "${String(r.reason)}" is not a member of released.classes`);
|
|
253
279
|
}
|
|
254
280
|
}
|
|
281
|
+
if (denied !== undefined && denied.clearedBy !== undefined)
|
|
282
|
+
defects.push("I9: disposition.clearedBy stands only on an allowed disposition");
|
|
283
|
+
if (d !== undefined && d.clearedBy !== undefined)
|
|
284
|
+
defects.push(...clearanceDefects(d.clearedBy, settled, d.released !== undefined));
|
|
255
285
|
if (denied !== undefined) {
|
|
256
286
|
const modeRefusal = denied.deniedBy === "mode";
|
|
257
287
|
if (modeRefusal !== (denied.mode !== undefined))
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { AssertAllKeysHandled } from "./ask-origin.js";
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
2
|
+
/** The engine's one retry vocabulary, defined here and nowhere else — can repeating the same request succeed?
|
|
3
|
+
* `transient` = a later retry can succeed with nothing changed first (the cause clears by itself, with no stated
|
|
4
|
+
* horizon: a control plane briefly absent, contention, an interrupted call); `terminal` = repeating it changes
|
|
5
|
+
* nothing until something named changes first — a verdict (a policy, or a usage window until the `retryAfterMs` it
|
|
6
|
+
* states), the deployment, the store or the input. Governance codes and file-history faults answer in it. */
|
|
4
7
|
export type GovernanceRetryClass = "transient" | "terminal";
|
|
8
|
+
/** Is `value` one of the two words — the one membership reading (keyed by the type: a word added there is a missing
|
|
9
|
+
* row here, at compile time). */
|
|
10
|
+
export declare function isGovernanceRetryClass(value: unknown): value is GovernanceRetryClass;
|
|
5
11
|
/**
|
|
6
12
|
* The closed governance-code registry. tsc forces every entry to a valid class; the gate test
|
|
7
13
|
* forces the naming convention and pack-family completeness. Adding a code = one deliberate row.
|
|
@@ -139,7 +145,7 @@ export type NoticeAudience = "user" | "operator";
|
|
|
139
145
|
* the union's catalog ({@link EngineNotice.code}). The groups below say only which family a row joins,
|
|
140
146
|
* so the catalog is not written a second time here and the two cannot drift.
|
|
141
147
|
*/
|
|
142
|
-
export declare const ENGINE_NOTICE_CODES: readonly ["config.autocompact_window_clamped", "config.env_timeout_discarded", "config.materialize_env_discarded", "config.models_swapped", "config.context_settings_swapped", "config.read_face_swapped", "config.read_face_deployment_clamped", "config.write_face_swapped", "config.write_face_deployment_clamped", "config.read_deny_swapped", "config.tool_model_gate_removed", "config.tool_model_gate_unknown_class", "config.tool_model_gate_env_invalid", "config.artifact_host_invalid", "config.task_root_not_canonical", "config.write_protection_target_view_absent", "config.path_view_unresolved", "config.execution_env_capability_invalid", "config.tool_card_undeclared", "config.tool_face_undeclared", "config.tool_face_invalid", "config.forward_sink_failed", "config.durable_gate_unavailable", "config.peer_admission_out_of_range", "config.peer_lane_unmounted", "config.secret_env_scrubbed", "config.credential_not_withheld", "config.cross_boundary_posture_undeclared", "config.cross_boundary_record_unwritten", "config.permission_mode_unavailable", "permission.ask_released_by_mode", "permission.read_deny_unapplied", "permission.rule_store_unavailable", "permission.rule_row_dropped", "config.session_rules_earlier_grammar", "permission.allowed_tool_not_granted", "mods.registration_refused", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit", "classifier.fallback", "classifier.role_defaulted", "classifier.contract_broken", "classifier.unavailable", "checkpoint.execution_outcome_unrecorded", "delegation.transcript_integrity", "delegation.ask_unresolvable", "mcp.injection_dropped", "mcp.revocation_probe_failed", "mcp.server_redialed", "workflow.governance_key_stripped", "workflow.agent_option_ignored", "memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.content_class_declared", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "memory.consolidation_recommended", "memory.consolidation_committed", "memory.consolidation_conflict", "memory.consolidation_incomplete", "memory.consolidation_refused", "memory.consolidation_withheld", "memory.restore_withheld", "memory.project_scope_absent", "route.fallback_to_primary", "route.classifier_unroutable", "route.credential_origin_mismatch", "route.response_model_mismatch", "route.tool_call_id_folded", "route.finish_reason_unknown", "route.stream_end_ignored", "route.extra_body_reserved_dropped", "context.tool_turn_repaired", "task.user_steer_undrained", "task.user_followup_undrained", "steering.parked_input_blocked", "task.turn_interrupted", "task.halt_unconsumed", "task.late_approval", "task.interrupt_unconsumed", "task.tool_turn_incomplete", "approval.read_root_granted", "approval.read_root_grant_rejected", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "skills.listing_truncated", "agents.listing_truncated", "tool_result.offload_put_failed", "tool_result.media_refused", "instructions.source_changed", "session.records_skipped", "memory.layer_locked_legacy", "server.model_unreachable", "permission.entry_mode_clamped"];
|
|
148
|
+
export declare const ENGINE_NOTICE_CODES: readonly ["config.autocompact_window_clamped", "config.env_timeout_discarded", "config.materialize_env_discarded", "config.models_swapped", "config.context_settings_swapped", "config.read_face_swapped", "config.read_face_deployment_clamped", "config.write_face_swapped", "config.write_face_deployment_clamped", "config.read_deny_swapped", "config.tool_model_gate_removed", "config.tool_model_gate_unknown_class", "config.tool_model_gate_env_invalid", "config.artifact_host_invalid", "config.task_root_not_canonical", "config.write_protection_target_view_absent", "config.path_view_unresolved", "config.execution_env_capability_invalid", "config.tool_card_undeclared", "config.tool_face_undeclared", "config.tool_face_invalid", "config.forward_sink_failed", "config.durable_gate_unavailable", "config.peer_admission_out_of_range", "config.peer_lane_unmounted", "config.secret_env_scrubbed", "config.credential_not_withheld", "config.cross_boundary_posture_undeclared", "config.cross_boundary_record_unwritten", "config.permission_mode_unavailable", "permission.ask_released_by_mode", "permission.read_deny_unapplied", "permission.rule_store_unavailable", "permission.rule_row_dropped", "config.session_rules_earlier_grammar", "permission.allowed_tool_not_granted", "mods.registration_refused", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit", "classifier.fallback", "classifier.role_defaulted", "classifier.contract_broken", "classifier.unavailable", "checkpoint.execution_outcome_unrecorded", "delegation.transcript_integrity", "delegation.ask_unresolvable", "mcp.injection_dropped", "mcp.revocation_probe_failed", "mcp.server_redialed", "workflow.governance_key_stripped", "workflow.agent_option_ignored", "memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.content_class_declared", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "memory.consolidation_recommended", "memory.consolidation_committed", "memory.consolidation_conflict", "memory.consolidation_incomplete", "memory.consolidation_refused", "memory.consolidation_withheld", "memory.restore_withheld", "memory.project_scope_absent", "route.fallback_to_primary", "route.classifier_unroutable", "route.seat_detached", "advisor.not_attached", "route.credential_origin_mismatch", "route.response_model_mismatch", "route.tool_call_id_folded", "route.finish_reason_unknown", "route.stream_end_ignored", "route.extra_body_reserved_dropped", "context.tool_turn_repaired", "task.user_steer_undrained", "task.user_followup_undrained", "steering.parked_input_blocked", "task.turn_interrupted", "task.halt_unconsumed", "task.late_approval", "task.interrupt_unconsumed", "task.tool_turn_incomplete", "approval.read_root_granted", "approval.read_root_grant_rejected", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "skills.listing_truncated", "agents.listing_truncated", "tool_result.offload_put_failed", "tool_result.media_refused", "instructions.source_changed", "session.records_skipped", "memory.layer_locked_legacy", "server.model_unreachable", "permission.entry_mode_clamped"];
|
|
143
149
|
/** A catalogued code (see {@link ENGINE_NOTICE_CODES}); {@link NOTICE_MINTER} says who mints it. NOT the type of
|
|
144
150
|
* `EngineNotice.code`, which stays `string` — a host forwarding its own notices through the same
|
|
145
151
|
* sink is a supported shape, and narrowing that field would break it. */
|
|
@@ -242,6 +248,8 @@ declare const NOTICE_AUDIENCE_TABLE: {
|
|
|
242
248
|
readonly "memory.project_scope_absent": "operator";
|
|
243
249
|
readonly "route.fallback_to_primary": "operator";
|
|
244
250
|
readonly "route.classifier_unroutable": "operator";
|
|
251
|
+
readonly "route.seat_detached": "operator";
|
|
252
|
+
readonly "advisor.not_attached": "user";
|
|
245
253
|
readonly "route.response_model_mismatch": "operator";
|
|
246
254
|
readonly "route.tool_call_id_folded": "operator";
|
|
247
255
|
readonly "route.extra_body_reserved_dropped": "operator";
|
|
@@ -351,6 +359,8 @@ declare const NOTICE_MINTER_TABLE: {
|
|
|
351
359
|
readonly "memory.project_scope_absent": "engine";
|
|
352
360
|
readonly "route.fallback_to_primary": "engine";
|
|
353
361
|
readonly "route.classifier_unroutable": "engine";
|
|
362
|
+
readonly "route.seat_detached": "engine";
|
|
363
|
+
readonly "advisor.not_attached": "engine";
|
|
354
364
|
readonly "route.credential_origin_mismatch": "engine";
|
|
355
365
|
readonly "route.response_model_mismatch": "engine";
|
|
356
366
|
readonly "route.tool_call_id_folded": "engine";
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
const RETRY_CLASS_WORDS = Object.freeze({ transient: true, terminal: true });
|
|
2
|
+
export function isGovernanceRetryClass(value) {
|
|
3
|
+
return typeof value === "string" && Object.hasOwn(RETRY_CLASS_WORDS, value);
|
|
4
|
+
}
|
|
1
5
|
export const GOVERNANCE_CODES = {
|
|
2
6
|
"usage.window_exhausted": "terminal",
|
|
3
7
|
"memory.admission_required": "transient",
|
|
@@ -189,6 +193,8 @@ export const ENGINE_NOTICE_CODES = Object.freeze([
|
|
|
189
193
|
"memory.project_scope_absent",
|
|
190
194
|
"route.fallback_to_primary",
|
|
191
195
|
"route.classifier_unroutable",
|
|
196
|
+
"route.seat_detached",
|
|
197
|
+
"advisor.not_attached",
|
|
192
198
|
"route.credential_origin_mismatch",
|
|
193
199
|
"route.response_model_mismatch",
|
|
194
200
|
"route.tool_call_id_folded",
|
|
@@ -303,6 +309,8 @@ const NOTICE_AUDIENCE_TABLE = {
|
|
|
303
309
|
"memory.project_scope_absent": "operator",
|
|
304
310
|
"route.fallback_to_primary": "operator",
|
|
305
311
|
"route.classifier_unroutable": "operator",
|
|
312
|
+
"route.seat_detached": "operator",
|
|
313
|
+
"advisor.not_attached": "user",
|
|
306
314
|
"route.response_model_mismatch": "operator",
|
|
307
315
|
"route.tool_call_id_folded": "operator",
|
|
308
316
|
"route.extra_body_reserved_dropped": "operator",
|
|
@@ -393,6 +401,8 @@ const NOTICE_MINTER_TABLE = {
|
|
|
393
401
|
"memory.project_scope_absent": "engine",
|
|
394
402
|
"route.fallback_to_primary": "engine",
|
|
395
403
|
"route.classifier_unroutable": "engine",
|
|
404
|
+
"route.seat_detached": "engine",
|
|
405
|
+
"advisor.not_attached": "engine",
|
|
396
406
|
"route.credential_origin_mismatch": "engine",
|
|
397
407
|
"route.response_model_mismatch": "engine",
|
|
398
408
|
"route.tool_call_id_folded": "engine",
|
|
@@ -110,7 +110,7 @@ export interface HandsBandOptions {
|
|
|
110
110
|
/** Deployment write gate — COMPOSED with (never replacing) the engine's MemoryEngine write-scan gate:
|
|
111
111
|
* this hook judges first (a rejection short-circuits), the engine gate then still runs in full. */
|
|
112
112
|
beforeWrite?: BeforeWriteHook;
|
|
113
|
-
/** RB-198 F1
|
|
113
|
+
/** RB-198 F1: on a foreground Bash command's OWN timeout, an eligible
|
|
114
114
|
* command (see `canAutoBackground` — no `git` anywhere in the command, not a `sleep`-first-word wait) is
|
|
115
115
|
* adopted as a background task instead of being killed — CC's own posture ("received no response for
|
|
116
116
|
* Nms" would otherwise force a wasteful blind re-run of a non-idempotent long command). Default `false`
|
package/dist/core/hooks.d.ts
CHANGED
|
@@ -295,7 +295,7 @@ export interface StopHookResult {
|
|
|
295
295
|
* more turn.
|
|
296
296
|
*
|
|
297
297
|
* **It DOES count toward the consecutive-block cap, and it never resets it.** This sentence used to
|
|
298
|
-
* say the opposite ("the cap is driven by `block` alone"
|
|
298
|
+
* say the opposite ("the cap is driven by `block` alone"), and it was wrong on
|
|
299
299
|
* both halves. Re-read against CC: the `additionalContext` branch pushes into the SAME array as the
|
|
300
300
|
* blocking-error branch, the loop counts that array's length against the cap, and CC never resets
|
|
301
301
|
* mid-run. The engine was fixed to match; the sentence here was not, so the module that DEFINES this
|
|
@@ -971,7 +971,7 @@ export interface ToolGateInput extends PermissionSeatInputs, SkillGateSeats, All
|
|
|
971
971
|
*/
|
|
972
972
|
shellGated?: boolean;
|
|
973
973
|
/**
|
|
974
|
-
* design/276 (
|
|
974
|
+
* design/276 (P11 arm 4): true when the called tool is the peer-message verb — a message
|
|
975
975
|
* to another agent (`SendMessage`). ENGINE-FILLED from the wire name at the caller, never a
|
|
976
976
|
* configuration knob; a caller's same-named shadow tool is keyed too (for a tighten, over-asking is
|
|
977
977
|
* the fail-safe direction). Under an armed {@link autoMode} the gate tightens a surviving `allow` to
|
|
@@ -1009,7 +1009,7 @@ export interface ToolGateInput extends PermissionSeatInputs, SkillGateSeats, All
|
|
|
1009
1009
|
*/
|
|
1010
1010
|
shellReadCheck?: import("../tools/fs/shell-read-check.js").ShellReadCheck;
|
|
1011
1011
|
/**
|
|
1012
|
-
* design/143 批2 (A,
|
|
1012
|
+
* design/143 批2 (A, auto mode): when present, a surviving `ask` is routed to the
|
|
1013
1013
|
* small-model policy CLASSIFIER before any human/durable resolution:
|
|
1014
1014
|
* - verdict `allow` → the ask resolves to allow (`decisionReason:"classifier"`) — no suspend, no onAsk;
|
|
1015
1015
|
* - verdict `block` → deny (`decisionReason:"classifier"`, `source:"classifier"`; CC `automode-blocked`); `parse_error` too;
|
|
@@ -1033,7 +1033,7 @@ export interface ToolGateInput extends PermissionSeatInputs, SkillGateSeats, All
|
|
|
1033
1033
|
autoMode?: {
|
|
1034
1034
|
decider: import("./auto-mode.js").AutoModeDecider;
|
|
1035
1035
|
/**
|
|
1036
|
-
* The per-run DENIAL-LIMIT tracker beside the decider (
|
|
1036
|
+
* The per-run DENIAL-LIMIT tracker beside the decider (same owner,
|
|
1037
1037
|
* same lifetime). Absent ⇒ the pre-#548 chain byte for byte: every block is a deny, without bound.
|
|
1038
1038
|
* Present ⇒ a block first counts, then judges; the block that reaches a bound becomes the fallback
|
|
1039
1039
|
* ask (`requiresRealApproval: true` + `denialLimitFallback`), and a classifier allow or a person's
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The HOST vocabulary, one home for how a host is spelled and read:
|
|
3
|
+
* · {@link hostOfSpelling} — the RULE side: the host a `<Tool>(domain:<host>)` rule names;
|
|
4
|
+
* · {@link hostOfUrl} — the CALL side: the host a URL names, which every host-rule judge reads as the call's subject and the
|
|
5
|
+
* engine's fetch tool reads as the host it connects to (one reading, two readers);
|
|
6
|
+
* · {@link callHostTargetOf} — which argument of a call carries that URL: the host face's protective and declared readings.
|
|
7
|
+
* Both sides go through the URL parser (lower case, IDN in its ASCII form, a full-width dot folded, an IPv4 shorthand expanded)
|
|
8
|
+
* and read trailing dots off; a call's host that does not read back as itself through the rule side's reader names no host a rule
|
|
9
|
+
* can be judged on, so a rule and a call that name one host always name it in one spelling.
|
|
10
|
+
*
|
|
11
|
+
* Leaf module: it reads the catalog's host slots (the protective floor) and the name-reading seat, nothing else.
|
|
12
|
+
*/
|
|
13
|
+
import { type ToolCallLike } from "./tool-registry.js";
|
|
14
|
+
/** The host a spelling names as the URL parser reads it (trailing dots read off), or undefined when the spelling is more or
|
|
15
|
+
* less than a host: empty, carrying whitespace or a separator a URL reads as something else, a port (a `:` outside an
|
|
16
|
+
* address's brackets), credentials, a path. */
|
|
17
|
+
export declare function hostOfSpelling(spelled: string): string | undefined;
|
|
18
|
+
/** Is this host (as {@link hostOfUrl} reads it) an address — the URL parser's IPv4 form or a bracketed IPv6? */
|
|
19
|
+
export declare function isAddressHost(host: string): boolean;
|
|
20
|
+
/** Why a URL names no host a rule can be judged on — the closed set the fetch tool maps to its own refusal sentences:
|
|
21
|
+
* not a string; not a URL; not http(s); credentials in it; a host that does not read back as itself once its trailing dots
|
|
22
|
+
* are read off (`https://2130706433../` — the parser keeps the name, the rule side reads `127.0.0.1`). */
|
|
23
|
+
export declare const HOST_UNREADABLE_REASONS: readonly ["not_text", "not_url", "not_http", "credentials", "unstable"];
|
|
24
|
+
export type HostUnreadableReason = (typeof HOST_UNREADABLE_REASONS)[number];
|
|
25
|
+
/** The host a URL names, or why it names none. */
|
|
26
|
+
export type HostReading = {
|
|
27
|
+
readonly host: string;
|
|
28
|
+
} | {
|
|
29
|
+
readonly unreadable: HostUnreadableReason;
|
|
30
|
+
};
|
|
31
|
+
/** The words a refusal states for each unreadable reason. */
|
|
32
|
+
export declare const HOST_UNREADABLE_SENTENCE: Readonly<Record<HostUnreadableReason, string>>;
|
|
33
|
+
/** THE call-side reading of a URL: the host it names (lower case, IDN in its ASCII form, trailing dots read off), or why it
|
|
34
|
+
* names none ({@link HostUnreadableReason}). */
|
|
35
|
+
export declare function hostOfUrl(value: unknown): HostReading;
|
|
36
|
+
/** Which reading a judge takes: `tighten` for a deny, an ask and the unreadable law; `grant` for an allow. */
|
|
37
|
+
export type HostReadingDirection = "tighten" | "grant";
|
|
38
|
+
/**
|
|
39
|
+
* The host a call reaches as every host-rule judge reads it — the rule policy's host lane, a person's stored rows, the entry
|
|
40
|
+
* lists, the approval card's offer — or undefined when the call has no URL slot in that direction:
|
|
41
|
+
* · `tighten` — the PROTECTIVE reading: the call face's own slot, else the catalog's slot under the first name the call
|
|
42
|
+
* answers to that declares one (a bare request, or a face that declares none). Borrowing a slot can only add a host to
|
|
43
|
+
* judge, so a deny or an ask keeps reaching a same-name tool;
|
|
44
|
+
* · `grant` — the DECLARED reading: the call face's own slot only. A tool that declares none (a caller's tool that merely took
|
|
45
|
+
* the fetch tool's name, a bare request) is not the tool the catalog describes, and no allow by host reaches it.
|
|
46
|
+
* The slot's value is read by {@link hostOfUrl}; a value that names no host answers `{ unreadable }`, and each judge's law
|
|
47
|
+
* says what that means for its direction.
|
|
48
|
+
*/
|
|
49
|
+
export declare function callHostTargetOf(call: ToolCallLike, direction: HostReadingDirection): HostReading | undefined;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { hostTargetOf } from "./tool-registry.js";
|
|
2
|
+
import { seatOf } from "./tool-name-readings.js";
|
|
3
|
+
export function hostOfSpelling(spelled) {
|
|
4
|
+
if (spelled === "" || /[\s/\\@?#%]/.test(spelled) || (spelled.includes(":") && !/^\[[^\]]+\]$/.test(spelled)))
|
|
5
|
+
return undefined;
|
|
6
|
+
let url;
|
|
7
|
+
try {
|
|
8
|
+
url = new URL(`https://${spelled}/`);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
if (url.port !== "" || url.username !== "" || url.password !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "")
|
|
14
|
+
return undefined;
|
|
15
|
+
const host = url.hostname.replace(/\.+$/, "");
|
|
16
|
+
return host === "" ? undefined : host;
|
|
17
|
+
}
|
|
18
|
+
export function isAddressHost(host) {
|
|
19
|
+
return host.startsWith("[") || /^\d+\.\d+\.\d+\.\d+$/.test(host);
|
|
20
|
+
}
|
|
21
|
+
export const HOST_UNREADABLE_REASONS = Object.freeze(["not_text", "not_url", "not_http", "credentials", "unstable"]);
|
|
22
|
+
export const HOST_UNREADABLE_SENTENCE = Object.freeze({
|
|
23
|
+
not_text: "the URL argument is not a string",
|
|
24
|
+
not_url: "the URL does not parse",
|
|
25
|
+
not_http: "the URL is not http(s)",
|
|
26
|
+
credentials: "the URL carries credentials",
|
|
27
|
+
unstable: "the URL's host does not read back as one host",
|
|
28
|
+
});
|
|
29
|
+
export function hostOfUrl(value) {
|
|
30
|
+
if (typeof value !== "string")
|
|
31
|
+
return { unreadable: "not_text" };
|
|
32
|
+
let url;
|
|
33
|
+
try {
|
|
34
|
+
url = new URL(value);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return { unreadable: "not_url" };
|
|
38
|
+
}
|
|
39
|
+
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
40
|
+
return { unreadable: "not_http" };
|
|
41
|
+
if (url.username !== "" || url.password !== "")
|
|
42
|
+
return { unreadable: "credentials" };
|
|
43
|
+
const host = url.hostname.replace(/\.+$/, "");
|
|
44
|
+
return host !== "" && hostOfSpelling(host) === host ? { host } : { unreadable: "unstable" };
|
|
45
|
+
}
|
|
46
|
+
export function callHostTargetOf(call, direction) {
|
|
47
|
+
const slot = hostSlotOf(call, direction);
|
|
48
|
+
if (slot === undefined)
|
|
49
|
+
return undefined;
|
|
50
|
+
const args = call.args;
|
|
51
|
+
const own = typeof args === "object" && args !== null && !Array.isArray(args) && Object.hasOwn(args, slot.param);
|
|
52
|
+
return hostOfUrl(own ? args[slot.param] : undefined);
|
|
53
|
+
}
|
|
54
|
+
function hostSlotOf(call, direction) {
|
|
55
|
+
const declared = call.face?.hostTarget;
|
|
56
|
+
if (declared !== undefined || direction === "grant")
|
|
57
|
+
return declared;
|
|
58
|
+
return seatOf("floor.protectiveHostTarget", { get: hostTargetOf }, call)?.value;
|
|
59
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* `core/types.ts`) needed no changes on this car.
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
|
-
* design/116 W5-1 — the max base64 size of ONE inline image (5MB). Value =
|
|
10
|
+
* design/116 W5-1 — the max base64 size of ONE inline image (5MB). Value =
|
|
11
11
|
* `API_IMAGE_MAX_BASE64_SIZE` (constants/apiLimits.ts:22, "5 * 1024 * 1024 // 5 MB" — the hard Anthropic API
|
|
12
12
|
* limit on a base64 image block; CC resizes/compresses down to fit UNDER it, imageResizer.ts). An MCP server
|
|
13
13
|
* returning a bigger image previously passed straight through = a context/API bomb.
|
|
@@ -83,7 +83,7 @@ export declare class LspDiagnosticsRegistry {
|
|
|
83
83
|
* the map; a judgment that fails withholds them all). The run's drain already marked them delivered, so they do not come back. */
|
|
84
84
|
export declare function withholdListedDiagnostics(files: LspFileDiagnostics[], withheldOf: (uris: readonly string[]) => Promise<ReadonlyMap<string, unknown>>): Promise<LspFileDiagnostics[]>;
|
|
85
85
|
/**
|
|
86
|
-
*
|
|
86
|
+
* `formatDiagnosticsSummary` shape:
|
|
87
87
|
* ```
|
|
88
88
|
* {basename}:
|
|
89
89
|
* {symbol} [Line {line+1}:{col+1}] {message}[ [{code}]][ ({source})]
|
|
@@ -96,16 +96,16 @@ export declare function withholdListedDiagnostics(files: LspFileDiagnostics[], w
|
|
|
96
96
|
* repository. They land inside the `<new-diagnostics>` envelope, and (since this block is now
|
|
97
97
|
* delivered inside a marked reminder shell) inside an authority-marked reminder too, so a diagnostic
|
|
98
98
|
* message carrying `</new-diagnostics>` closed the envelope and placed server text at the top level
|
|
99
|
-
* of engine-authored authority.
|
|
99
|
+
* of engine-authored authority. The reference does not neutralize here either — a deliberate, disclosed
|
|
100
100
|
* hardening divergence: CC ships the same block inside the same reminder shell, so the hole exists on
|
|
101
101
|
* both sides and only the fix is ours. Neutralization runs BEFORE the join, so the 4000-char cap
|
|
102
102
|
* still bounds the FINAL text and can never cut inside a neutralized marker's own bytes.
|
|
103
103
|
*/
|
|
104
104
|
export declare function formatDiagnosticsSummary(files: LspFileDiagnostics[]): string;
|
|
105
|
-
/**
|
|
105
|
+
/** Model-facing injection block.
|
|
106
106
|
*
|
|
107
107
|
* DELIVERY (design/319 sibling work): the runner shells this block in a MARKED `<system-reminder>`
|
|
108
|
-
* before steering it —
|
|
108
|
+
* before steering it — the reference's `case "diagnostics"` does the same (`ih([Vr({content: …})])` → the
|
|
109
109
|
* reminder wrap), and until that was matched this was the engine's only authority text reaching the
|
|
110
110
|
* model as a bare block with no provenance mark at all. The block's own bytes are unchanged; the
|
|
111
111
|
* shell is applied at the delivery site (runtask), not baked in here, so this exported renderer keeps
|
package/dist/core/lsp.d.ts
CHANGED
|
@@ -58,8 +58,8 @@ export interface LspSymbolInfo {
|
|
|
58
58
|
* answered null/[] — today's behavior byte-for-byte, and what an external manager returning bare
|
|
59
59
|
* `{kind:"none"}` keeps getting). The failure reasons exist because one literal "No results." used to cover
|
|
60
60
|
* both real emptiness and every transport-level fault — a findReferences that TIMED OUT read as "no
|
|
61
|
-
* references, safe to delete" (
|
|
62
|
-
* plain empty-result strings
|
|
61
|
+
* references, safe to delete" (the reference keeps these apart: `Error performing ${operation}: ...` vs the
|
|
62
|
+
* plain empty-result strings).
|
|
63
63
|
*/
|
|
64
64
|
export type LspNoneReason = "unsupported_operation" | "server_error" | "timeout" | "cancelled" | "server_terminated" | "no_call_hierarchy_item"
|
|
65
65
|
/** HRD-LSP-7: the QUERIED file could not be read for the didOpen/didChange re-sync (deleted between the
|
|
@@ -246,7 +246,7 @@ export interface LspTransport {
|
|
|
246
246
|
* gate (no read face) only; a gated read is the admitted held object's ({@link LspReadAdmission}). TOC = local fs; TOB =
|
|
247
247
|
* the sandbox ExecutionEnv. */
|
|
248
248
|
export type LspReadText = (filePath: string, signal?: AbortSignal) => Promise<string>;
|
|
249
|
-
/**
|
|
249
|
+
/** The LSP file cap (10MB — `File too large for LSP analysis`). Single-sourced
|
|
250
250
|
* in core: the TOOL-layer check in {@link createLspTool} (the model-visible enforcement, CC-parity) and the
|
|
251
251
|
* defense-in-depth throw in the engine's `defaultLspReadText` must agree on one number. */
|
|
252
252
|
export declare const MAX_LSP_FILE_BYTES: number;
|
|
@@ -221,6 +221,10 @@ export interface MailboxStore {
|
|
|
221
221
|
* (the in-memory reference); absent = undeclared (the CC inbox adapter). Read by
|
|
222
222
|
* {@link mailboxCrossProcessMountVerdict}; any other value is a malformed declaration and refuses. */
|
|
223
223
|
readonly crossProcessSafe?: boolean;
|
|
224
|
+
/** WHICH boxes this store serves, as an opaque word: two store objects with the same identity read and write
|
|
225
|
+
* the same boxes (one backing directory, one database), in whichever process they live. Absent = the store
|
|
226
|
+
* cannot say — and then no peer may assume that a box it appends to here is one another session drains. */
|
|
227
|
+
readonly identity?: string;
|
|
224
228
|
/** Durably park one message. Refuses `"mailbox.recipient_tombstoned"` when the backend can see
|
|
225
229
|
* that its recipient is in the deployment's pre-delete state (see the interface notes above). */
|
|
226
230
|
append(scope: string, handle: string, msg: MailboxAppendMessage): Promise<number>;
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* answer to its questions belongs to the leg that is waiting on it.
|
|
19
19
|
*/
|
|
20
20
|
import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
21
|
+
import { ConnectionListing, type LenientListedTool } from "./mcp-server-link.js";
|
|
21
22
|
import type { McpServerSpec } from "./mcp-server-spec.js";
|
|
22
23
|
/** The slice of a listed tool the SDK client caches per connection (its output validator, its task-support flags). */
|
|
23
24
|
export interface McpToolMeta {
|
|
@@ -31,6 +32,8 @@ export type McpListingWriter = (tools: ReadonlyArray<McpToolMeta>, apply: (all:
|
|
|
31
32
|
/** One leg's hold on a pooled connection. */
|
|
32
33
|
export interface McpLease {
|
|
33
34
|
readonly client: Client;
|
|
35
|
+
/** The connection's listing, one record shared by every holder (mcp-server-link.ts `ConnectionListing`). */
|
|
36
|
+
readonly listing: ConnectionListing<LenientListedTool>;
|
|
34
37
|
/**
|
|
35
38
|
* Open a `tools/list` round trip on the connection — call it BEFORE the request. The returned writer records the result twice over:
|
|
36
39
|
* as the connection's metadata for each listed tool, at this listing's version (its place in the order listings were opened on the
|
|
@@ -65,13 +68,26 @@ export declare class McpConnectionPool {
|
|
|
65
68
|
* Lease the connection for `key`, dialling it with `dial` when none is live. `fresh` replaces the pool's current connection with a new
|
|
66
69
|
* dial (a re-dial): the connection it replaces lives on until its other holders release it. Resolves `undefined` once the pool is
|
|
67
70
|
* closed — the caller dials for itself. A dial that rejects rejects every waiter of that dial, and the pool keeps nothing of it.
|
|
71
|
+
*
|
|
72
|
+
* `signal` is the CALLER's abort, and it is that caller's alone: it ends this caller's wait (rejecting with its reason) and leaves the dial
|
|
73
|
+
* to the legs still waiting on it. The dial belongs to the pool: it is given a stop of its own, fired when the last leg waiting on it has
|
|
74
|
+
* walked away, so a leg's abort neither holds nor cancels a dial another leg still needs.
|
|
68
75
|
*/
|
|
69
|
-
acquire(key: string, dial: () => Promise<Client>, opts?: {
|
|
76
|
+
acquire(key: string, dial: (stop: AbortSignal) => Promise<Client>, opts?: {
|
|
70
77
|
fresh?: boolean;
|
|
78
|
+
signal?: AbortSignal;
|
|
71
79
|
}): Promise<McpLease | undefined>;
|
|
80
|
+
/**
|
|
81
|
+
* Wait for a dial as one of its legs; this leg's abort ends only this leg's wait. The last leg to walk away abandons the dial in the
|
|
82
|
+
* same step as its abort (see {@link abandon}) — the table holds only dials some leg still waits on, so a leg that asks next dials afresh
|
|
83
|
+
* instead of joining a stopped dial and failing with another leg's abort.
|
|
84
|
+
*/
|
|
85
|
+
private waitOn;
|
|
86
|
+
/** A dial nobody waits on any more: out of the table and stopped, and — had it landed already — the connection nobody leased is let go, so such a dial leaves no connection behind. */
|
|
87
|
+
private abandon;
|
|
72
88
|
/** Make the next lease of `key` dial a new connection. */
|
|
73
89
|
detach(key: string): void;
|
|
74
|
-
/** No lease is granted after this; the connections still held stay open until their holders release them. */
|
|
90
|
+
/** No lease is granted after this; the connections still held stay open until their holders release them — one nobody holds is closed now. */
|
|
75
91
|
close(): void;
|
|
76
92
|
/** How many connections the pool holds open right now (for the lifecycle pins). */
|
|
77
93
|
get live(): number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { canonicalize } from "./canonical-json.js";
|
|
2
|
+
import { ConnectionListing } from "./mcp-server-link.js";
|
|
2
3
|
export class McpConnectionPool {
|
|
3
4
|
entries = new Map();
|
|
4
5
|
dialing = new Map();
|
|
@@ -17,25 +18,67 @@ export class McpConnectionPool {
|
|
|
17
18
|
async acquire(key, dial, opts) {
|
|
18
19
|
if (this.shut)
|
|
19
20
|
return undefined;
|
|
21
|
+
opts?.signal?.throwIfAborted();
|
|
20
22
|
if (opts?.fresh === true)
|
|
21
23
|
this.detach(key);
|
|
22
24
|
let entry = this.entries.get(key);
|
|
23
25
|
if (entry === undefined || entry.closed) {
|
|
24
26
|
let pending = this.dialing.get(key);
|
|
25
27
|
if (pending === undefined) {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const stop = new AbortController();
|
|
29
|
+
const started = this.dialNew(key, this.generation.get(key) ?? 0, () => dial(stop.signal));
|
|
30
|
+
const own = { promise: started, waiters: 0, stop };
|
|
31
|
+
pending = own;
|
|
32
|
+
this.dialing.set(key, own);
|
|
29
33
|
const settled = () => {
|
|
30
|
-
if (this.dialing.get(key) ===
|
|
34
|
+
if (this.dialing.get(key) === own)
|
|
31
35
|
this.dialing.delete(key);
|
|
32
36
|
};
|
|
33
37
|
void started.then(settled, settled);
|
|
34
38
|
}
|
|
35
|
-
entry = await pending;
|
|
39
|
+
entry = await this.waitOn(key, pending, opts?.signal);
|
|
36
40
|
}
|
|
37
41
|
return this.lease(entry);
|
|
38
42
|
}
|
|
43
|
+
async waitOn(key, dial, signal) {
|
|
44
|
+
dial.waiters++;
|
|
45
|
+
let waiting = true;
|
|
46
|
+
const stopWaiting = () => {
|
|
47
|
+
if (waiting)
|
|
48
|
+
dial.waiters--;
|
|
49
|
+
waiting = false;
|
|
50
|
+
};
|
|
51
|
+
try {
|
|
52
|
+
if (signal === undefined)
|
|
53
|
+
return await dial.promise;
|
|
54
|
+
return await new Promise((resolve, reject) => {
|
|
55
|
+
const walkAway = () => {
|
|
56
|
+
stopWaiting();
|
|
57
|
+
if (dial.waiters === 0)
|
|
58
|
+
this.abandon(key, dial, signal.reason);
|
|
59
|
+
reject(signal.reason);
|
|
60
|
+
};
|
|
61
|
+
signal.addEventListener("abort", walkAway, { once: true });
|
|
62
|
+
dial.promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", walkAway));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
stopWaiting();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
abandon(key, dial, reason) {
|
|
70
|
+
if (this.dialing.get(key) === dial)
|
|
71
|
+
this.dialing.delete(key);
|
|
72
|
+
dial.stop.abort(reason);
|
|
73
|
+
dial.promise.then((entry) => {
|
|
74
|
+
if (entry.refs > 0 || entry.closed)
|
|
75
|
+
return;
|
|
76
|
+
entry.current = false;
|
|
77
|
+
if (this.entries.get(key) === entry)
|
|
78
|
+
this.entries.delete(key);
|
|
79
|
+
void entry.client.close().catch(() => undefined);
|
|
80
|
+
}, () => undefined);
|
|
81
|
+
}
|
|
39
82
|
detach(key) {
|
|
40
83
|
this.generation.set(key, (this.generation.get(key) ?? 0) + 1);
|
|
41
84
|
const e = this.entries.get(key);
|
|
@@ -47,6 +90,9 @@ export class McpConnectionPool {
|
|
|
47
90
|
}
|
|
48
91
|
close() {
|
|
49
92
|
this.shut = true;
|
|
93
|
+
for (const e of [...this.entries.values()])
|
|
94
|
+
if (e.refs === 0 && !e.closed)
|
|
95
|
+
void e.client.close().catch(() => undefined);
|
|
50
96
|
}
|
|
51
97
|
get live() {
|
|
52
98
|
let n = 0;
|
|
@@ -57,7 +103,7 @@ export class McpConnectionPool {
|
|
|
57
103
|
}
|
|
58
104
|
async dialNew(key, generation, dial) {
|
|
59
105
|
const client = await dial();
|
|
60
|
-
const entry = { client, refs: 0, listeners: new Set(), holders: new Map(), meta: new Map(), nextVersion: 0, current: true, closed: false };
|
|
106
|
+
const entry = { client, listing: new ConnectionListing(), refs: 0, listeners: new Set(), holders: new Map(), meta: new Map(), nextVersion: 0, current: true, closed: false };
|
|
61
107
|
client.onclose = () => {
|
|
62
108
|
entry.closed = true;
|
|
63
109
|
if (this.entries.get(key) === entry)
|
|
@@ -86,6 +132,7 @@ export class McpConnectionPool {
|
|
|
86
132
|
};
|
|
87
133
|
const lease = {
|
|
88
134
|
client: entry.client,
|
|
135
|
+
listing: entry.listing,
|
|
89
136
|
onClose: (fn) => {
|
|
90
137
|
mine.add(fn);
|
|
91
138
|
entry.listeners.add(fn);
|
|
@@ -120,14 +120,17 @@ export type McpExchangeOutcome = McpFailureKind | "completed";
|
|
|
120
120
|
* mint of the record — no two sites can disagree about the word, about which words may carry
|
|
121
121
|
* `errorCode`, or about what a completed exchange proves. */
|
|
122
122
|
export declare function livenessOf(outcome: McpExchangeOutcome, observedAt: number): McpServerLiveness | undefined;
|
|
123
|
+
/** A request over an established connection; `session` when the request carried the session id the server issued at the handshake. */
|
|
124
|
+
export type McpRequestSite = {
|
|
125
|
+
phase: "request";
|
|
126
|
+
session?: true;
|
|
127
|
+
};
|
|
123
128
|
/** Where the failure was judged: at the dial (connect + initial listing), where an errno on a stdio
|
|
124
129
|
* transport is the child process failing to spawn, or on a request over an established connection. */
|
|
125
130
|
export type McpFailureSite = {
|
|
126
131
|
phase: "connect";
|
|
127
132
|
transport: "stdio" | "http" | undefined;
|
|
128
|
-
} |
|
|
129
|
-
phase: "request";
|
|
130
|
-
};
|
|
133
|
+
} | McpRequestSite;
|
|
131
134
|
/**
|
|
132
135
|
* The one MCP failure record. Both fields are always present; `httpStatus` rides only with
|
|
133
136
|
* `kind === "http_status"`.
|
|
@@ -213,4 +216,20 @@ export interface HttpTransportFailure {
|
|
|
213
216
|
delivered: McpDelivered;
|
|
214
217
|
httpStatus?: number;
|
|
215
218
|
}
|
|
216
|
-
export declare function describeHttpTransportFailure(err: unknown): HttpTransportFailure | undefined;
|
|
219
|
+
export declare function describeHttpTransportFailure(err: unknown, at?: McpRequestSite): HttpTransportFailure | undefined;
|
|
220
|
+
/**
|
|
221
|
+
* The one reading of a lost session: a request that carried the session id the server issued at the handshake (`at.session`) was
|
|
222
|
+
* answered 404 by the HTTP endpoint — the protocol's word for a session it no longer knows (a restart, a reaped session). It is the
|
|
223
|
+
* server's REPORT, not a proof that nothing ran: the call lane sends the request again once on a fresh session, and every face that
|
|
224
|
+
* renders the failure names it ({@link LOST_SESSION}), while its record stays the table's (`http_status`, `delivered: "unknown"`) — a
|
|
225
|
+
* server that executed the request and then answered 404 ran it. Read from the thrown value's structure and the site, never from the
|
|
226
|
+
* body's text. Nothing else qualifies: a 5xx, a timeout or a lost pipe leave the outcome unknown, a protocol error or a tool's own error
|
|
227
|
+
* means the server processed the call, a 400 is the protocol's word for a request that lacked its session header (a server that answers
|
|
228
|
+
* an unknown session 400 with words saying so is not read by its words), and a 404 on a connection that holds no session id is an
|
|
229
|
+
* endpoint answering, not a session ending.
|
|
230
|
+
*/
|
|
231
|
+
export declare function sessionGone(err: unknown, at: McpFailureSite): boolean;
|
|
232
|
+
/** What every face says of a lost session ({@link sessionGone}). */
|
|
233
|
+
export declare const LOST_SESSION = "the server reported the session the request was sent on gone (its HTTP endpoint answered 404 to the session id it issued)";
|
|
234
|
+
/** A failure's text, with a lost session ({@link sessionGone}) named ahead of it — for a face that renders the failure as one line. */
|
|
235
|
+
export declare function namingLostSession(err: unknown, at: McpRequestSite, text: string): string;
|