@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
package/dist/core/mcp.js
CHANGED
|
@@ -7,10 +7,13 @@ import { disposeSectionEntry, sectionAnswerWarning } from "./prompt-section-seat
|
|
|
7
7
|
import { findNamespacePrefixCollision, mintNamespacePrefix, mintNamespacedToolName, normalizeNameSegment } from "./protocol-naming.js";
|
|
8
8
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
9
9
|
import { McpConnectionPool } from "./mcp-connection-pool.js";
|
|
10
|
+
import { SessionEndingTransport, requestSite } from "./mcp-session-end.js";
|
|
11
|
+
import { mcpToolGate, UNPROVEN_GATE } from "./mcp-listing-drift.js";
|
|
12
|
+
import { ConnectionListing, Flights, IDLE_WATCHDOG_ABORT_REASON, Resendable, armMcpIdleWatchdog, callThroughLink, listingRefusal } from "./mcp-server-link.js";
|
|
13
|
+
import { underStartupBound } from "./mcp-startup-request.js";
|
|
10
14
|
import { LIST_MCP_RESOURCES, MCP_RESOURCE_LIST_ALLOW, MCP_RESOURCE_READ_ALLOW, READ_MCP_RESOURCE, READ_MCP_RESOURCE_DIR, retractInstructions, tellInstructions, toldOnDial, unretractInstructions, withdrawInstructionAdds } from "./mounted-mcp.js";
|
|
11
15
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
12
|
-
import {
|
|
13
|
-
import { classifyMcpFailure, describeHttpTransportFailure, livenessOf } from "./mcp-failure.js";
|
|
16
|
+
import { classifyMcpFailure, describeHttpTransportFailure, livenessOf, namingLostSession, sessionGone } from "./mcp-failure.js";
|
|
14
17
|
import { lstat, mkdir, writeFile } from "node:fs/promises";
|
|
15
18
|
import { tmpdir } from "node:os";
|
|
16
19
|
import { join } from "node:path";
|
|
@@ -128,33 +131,6 @@ export function mcpIdleTimeoutMs(kind) {
|
|
|
128
131
|
function idleKindOf(kind) {
|
|
129
132
|
return kind === "stdio" ? "stdio" : "http";
|
|
130
133
|
}
|
|
131
|
-
const IDLE_WATCHDOG_ABORT_REASON = Symbol("mcp-idle-watchdog-abort");
|
|
132
|
-
function armMcpIdleWatchdog(health, idleMs, outerSignal) {
|
|
133
|
-
const idleController = new AbortController();
|
|
134
|
-
let timer;
|
|
135
|
-
const rearm = () => {
|
|
136
|
-
if (timer !== undefined)
|
|
137
|
-
clearTimeout(timer);
|
|
138
|
-
const armedAt = Date.now();
|
|
139
|
-
timer = setTimeout(() => {
|
|
140
|
-
if (health.pendingElicitations > 0 || health.lastElicitationClosedAt > armedAt) {
|
|
141
|
-
rearm();
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
idleController.abort(IDLE_WATCHDOG_ABORT_REASON);
|
|
145
|
-
}, idleMs);
|
|
146
|
-
};
|
|
147
|
-
rearm();
|
|
148
|
-
return {
|
|
149
|
-
combinedSignal: outerSignal !== undefined ? AbortSignal.any([outerSignal, idleController.signal]) : idleController.signal,
|
|
150
|
-
idleSignal: idleController.signal,
|
|
151
|
-
rearm,
|
|
152
|
-
dispose: () => {
|
|
153
|
-
if (timer !== undefined)
|
|
154
|
-
clearTimeout(timer);
|
|
155
|
-
},
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
134
|
export function mcpStartupTimeoutMs(server) {
|
|
159
135
|
const fromEnv = parseEnvMs("MCP_TIMEOUT");
|
|
160
136
|
const own = server?.startupTimeoutMs;
|
|
@@ -231,7 +207,7 @@ function rethrowHonestMcpError(err, ctx) {
|
|
|
231
207
|
finish(err);
|
|
232
208
|
const serverLabel = inlineUntrusted(ctx.server);
|
|
233
209
|
const fenceServerText = (label, raw) => delimitUntrusted(label, truncateMcpErrorText(raw));
|
|
234
|
-
const failure = classifyMcpFailure(err,
|
|
210
|
+
const failure = classifyMcpFailure(err, ctx.site);
|
|
235
211
|
ctx.liveness?.observe?.(failure.kind);
|
|
236
212
|
const details = (extra) => ({ code: failure.kind, delivered: failure.delivered, server: ctx.server, ...extra });
|
|
237
213
|
switch (failure.kind) {
|
|
@@ -248,12 +224,14 @@ function rethrowHonestMcpError(err, ctx) {
|
|
|
248
224
|
case "not_mcp_response":
|
|
249
225
|
case "connect_refused":
|
|
250
226
|
case "connection_failed": {
|
|
251
|
-
const httpFailure = describeHttpTransportFailure(err);
|
|
227
|
+
const httpFailure = describeHttpTransportFailure(err, ctx.site);
|
|
252
228
|
const detail = remoteErrorText(err);
|
|
253
229
|
const fenced = `\nThe transport error follows as external/untrusted data:\n${fenceServerText(`${ctx.server} transport error`, detail)}`;
|
|
254
|
-
finish(markMcpFailure(new Error(
|
|
255
|
-
? `${ctx.what}
|
|
256
|
-
:
|
|
230
|
+
finish(markMcpFailure(new Error(sessionGone(err, ctx.site)
|
|
231
|
+
? `${ctx.what} met a lost session on MCP server "${serverLabel}": ${httpFailure.condition}; ${ctx.resent === true ? "the call was sent again once on a fresh session, and the server reported that one gone too — if the server executed it before answering, it ran twice" : "the call was not sent again — if the server executed it before answering, it ran"}. The outcome is unknown.${writeEffectWarning(ctx.writeEffect)}${fenced}`
|
|
232
|
+
: failure.delivered === "no"
|
|
233
|
+
? `${ctx.what} could not reach MCP server "${serverLabel}": ${httpFailure.condition}. The request was not delivered, so the server did not execute it. This server's tools and resources will keep failing until its endpoint is reachable again — do not retry them; use an alternative if one exists.${fenced}`
|
|
234
|
+
: `${ctx.what} failed at the transport layer of MCP server "${serverLabel}": ${httpFailure.condition}. The request may or may not have executed on the server — the outcome is unknown.${writeEffectWarning(ctx.writeEffect)}${fenced}`, { cause: err }), details(failure.httpStatus !== undefined ? { httpStatus: failure.httpStatus } : undefined)));
|
|
257
235
|
}
|
|
258
236
|
case "protocol": {
|
|
259
237
|
const code = err.code;
|
|
@@ -396,7 +374,7 @@ function buildTransport(spec, principal, kind) {
|
|
|
396
374
|
if (!("url" in t))
|
|
397
375
|
throw new Error(`MCP server "${spec.name}": transport kind "${String(kind)}" carries no url`);
|
|
398
376
|
const headers = resolveProtocolHttpHeaders(MCP_NAMESPACE.id, t, principal);
|
|
399
|
-
return new
|
|
377
|
+
return new SessionEndingTransport(new URL(t.url), {
|
|
400
378
|
requestInit: headers ? { headers } : undefined,
|
|
401
379
|
fetch: declaredEndpointFetch,
|
|
402
380
|
});
|
|
@@ -663,7 +641,7 @@ export function mcpToolSchemaProblem(schema) {
|
|
|
663
641
|
}
|
|
664
642
|
return undefined;
|
|
665
643
|
}
|
|
666
|
-
export async function materializeMcpTools(specs, principal, onElicit, imageResizer, reminderDisclosure, mcpRevocations, poolOpts, promptSections, dialable) {
|
|
644
|
+
export async function materializeMcpTools(specs, principal, onElicit, imageResizer, reminderDisclosure, mcpRevocations, poolOpts, promptSections, dialable, signal) {
|
|
667
645
|
const snapshot = snapshotMcpEntries(specs);
|
|
668
646
|
const axesRefused = new WeakMap();
|
|
669
647
|
const entries = snapshot.map((spec) => {
|
|
@@ -722,11 +700,10 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
722
700
|
const droppedTools = [];
|
|
723
701
|
let disposing = false;
|
|
724
702
|
const serverHandles = [];
|
|
725
|
-
const redialsInFlight = new Set();
|
|
726
703
|
const commitConnectedServer = (spec, s, transportKind) => {
|
|
727
704
|
const raised = [];
|
|
728
705
|
connections.push({ client: s.client, close: s.close });
|
|
729
|
-
const handle = { name: spec.name, spec, client: s.client, openListing: s.openListing, health: s.health, tools: s.tools,
|
|
706
|
+
const handle = { name: spec.name, spec, client: s.client, openListing: s.openListing, health: s.health, tools: s.tools, listing: s.listing, gatesAt: s.gatesAt, gates: () => gatesNow(handle), transportKind, announce: s.announce, instructions: s.instructions };
|
|
730
707
|
const hIdx = serverHandles.findIndex((h) => h.name === spec.name);
|
|
731
708
|
if (hIdx === -1)
|
|
732
709
|
serverHandles.push(handle);
|
|
@@ -786,9 +763,20 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
786
763
|
}
|
|
787
764
|
};
|
|
788
765
|
const dialKinds = entries.map(readDialKind);
|
|
766
|
+
const liveOf = (server) => serverHandles.find((h) => h.name === server);
|
|
767
|
+
const gatesNow = (h) => {
|
|
768
|
+
const latest = h.listing.latest();
|
|
769
|
+
if (latest.at !== h.gatesAt.at)
|
|
770
|
+
h.gatesAt = { at: latest.at, gates: intakeListedTools({ tools: [...latest.entries], unproven: latest.unproven }, h.spec, linkOf(h.name), imageResizer, mcpDisclosure, isServerRevoked, h.transportKind).gates };
|
|
771
|
+
return h.gatesAt.gates;
|
|
772
|
+
};
|
|
773
|
+
const linkOf = (server) => ({
|
|
774
|
+
live: () => liveOf(server),
|
|
775
|
+
recover: (lost) => redialFlights.running(server) ?? (liveOf(server) === lost ? redialFlights.start(server, () => redialDial(server)) : Promise.resolve()),
|
|
776
|
+
});
|
|
789
777
|
const dialServer = (spec, dialKind, dialOpts) => {
|
|
790
778
|
const refusal = axesRefused.get(spec);
|
|
791
|
-
return refusal !== undefined ? Promise.reject(refusal) : connectServer(spec, principal, onElicit, imageResizer, mcpDisclosure, isServerRevoked, dialKind, poolOpts?.pool, dialOpts);
|
|
779
|
+
return refusal !== undefined ? Promise.reject(refusal) : connectServer(spec, principal, onElicit, imageResizer, mcpDisclosure, isServerRevoked, dialKind, poolOpts?.pool, { ...dialOpts, link: linkOf(spec.name), ...(signal !== undefined ? { signal } : {}) });
|
|
792
780
|
};
|
|
793
781
|
const prefixOf = (name) => mintNamespacePrefix(MCP_NAMESPACE, name);
|
|
794
782
|
const heldCount = (name) => serverHandles.find((h) => h.name === name)?.tools.length ?? 0;
|
|
@@ -834,89 +822,87 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
834
822
|
await Promise.allSettled(settled.map((r) => (r.status === "fulfilled" && r.value !== null ? r.value.close() : Promise.resolve())));
|
|
835
823
|
throw mergeErr;
|
|
836
824
|
}
|
|
837
|
-
const
|
|
825
|
+
const declineRedial = (server, outcome, reason) => ({ server, prefix: prefixOf(server), outcome, reason, toolCount: heldCount(server), added: [], removed: [] });
|
|
826
|
+
const redialFlights = new Flights();
|
|
827
|
+
const ownerStopped = () => (disposing ? "this materialization is being disposed — the task is tearing down" : signal?.aborted === true ? "the run was aborted" : undefined);
|
|
828
|
+
const redialDial = async (server) => {
|
|
838
829
|
const prefix = prefixOf(server);
|
|
839
|
-
const declined = (outcome, reason) => (
|
|
840
|
-
|
|
841
|
-
|
|
830
|
+
const declined = (outcome, reason) => declineRedial(server, outcome, reason);
|
|
831
|
+
const stopped = ownerStopped();
|
|
832
|
+
if (stopped !== undefined)
|
|
833
|
+
return declined("refused", stopped);
|
|
842
834
|
const spec = entries.find((e) => e.name === server);
|
|
843
835
|
if (spec === undefined)
|
|
844
836
|
return declined("not_declared", `no MCP server named ${inlineUntrusted(server, 120)} is declared for this task`);
|
|
845
837
|
if (isServerRevoked(server))
|
|
846
838
|
return declined("refused", "server revoked by the operator — the re-dial did not contact it");
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
return {
|
|
880
|
-
server,
|
|
881
|
-
prefix,
|
|
882
|
-
outcome: "refused",
|
|
883
|
-
reason: inlineUntrusted(namedMcpFailureText(err), 240),
|
|
884
|
-
toolCount: 0,
|
|
885
|
-
added: [],
|
|
886
|
-
removed: priorNames,
|
|
887
|
-
tools: [],
|
|
888
|
-
axes: [],
|
|
889
|
-
dropped: [],
|
|
890
|
-
warnings: [raised.message],
|
|
891
|
-
status,
|
|
892
|
-
};
|
|
893
|
-
}
|
|
894
|
-
if (disposing) {
|
|
895
|
-
await connected.close().catch(() => undefined);
|
|
896
|
-
return declined("refused", "this materialization was disposed while the re-dial was in flight — the new connection was closed");
|
|
897
|
-
}
|
|
898
|
-
const raised = commitConnectedServer(spec, connected, dialKind);
|
|
899
|
-
reconcileInstructions(server, connected.instructions, true);
|
|
900
|
-
const newNames = connected.tools.map((t) => t.name);
|
|
839
|
+
const hIdx = serverHandles.findIndex((h) => h.name === server);
|
|
840
|
+
const prior = hIdx === -1 ? undefined : serverHandles[hIdx];
|
|
841
|
+
const priorNames = prior ? prior.tools.map((t) => t.name) : [];
|
|
842
|
+
if (prior) {
|
|
843
|
+
prior.announce.fn = undefined;
|
|
844
|
+
prior.health.observe = undefined;
|
|
845
|
+
serverHandles.splice(hIdx, 1);
|
|
846
|
+
const cIdx = connections.findIndex((c) => c.client === prior.client);
|
|
847
|
+
const priorConnection = cIdx === -1 ? undefined : connections.splice(cIdx, 1)[0];
|
|
848
|
+
await (priorConnection?.close() ?? prior.client.close()).catch(() => undefined);
|
|
849
|
+
}
|
|
850
|
+
const dialKind = readDialKind(spec);
|
|
851
|
+
const dialed = await dialServer(spec, dialKind, { fresh: true, sections: promptSections, ...(prior !== undefined ? { carried: prior.listing.latest().entries } : {}) }).then((connected) => ({ connected }), (err) => ({ err }));
|
|
852
|
+
const stoppedLate = ownerStopped();
|
|
853
|
+
if (stoppedLate !== undefined) {
|
|
854
|
+
if ("connected" in dialed)
|
|
855
|
+
await dialed.connected.close().catch(() => undefined);
|
|
856
|
+
return declined("refused", `${stoppedLate} while the re-dial was in flight — nothing new was kept or recorded`);
|
|
857
|
+
}
|
|
858
|
+
if ("err" in dialed) {
|
|
859
|
+
const err = dialed.err;
|
|
860
|
+
const { kind, delivered, httpStatus } = classifyMcpFailure(err, { phase: "connect", transport: dialKind });
|
|
861
|
+
const redialLiveness = livenessOf(kind, Date.now());
|
|
862
|
+
const status = { name: server, status: "failed", errorCode: kind, delivered, ...(httpStatus !== undefined ? { httpStatus } : {}), error: namedMcpFailureText(err), ...(redialLiveness !== undefined ? { liveness: redialLiveness } : {}) };
|
|
863
|
+
const sIdx = statuses.findIndex((st) => st.name === server);
|
|
864
|
+
if (sIdx === -1)
|
|
865
|
+
statuses.push(status);
|
|
866
|
+
else
|
|
867
|
+
statuses[sIdx] = status;
|
|
868
|
+
const raised = asServerWarning(spec, err);
|
|
869
|
+
warnings.push(raised);
|
|
870
|
+
reconcileInstructions(server, undefined, false);
|
|
901
871
|
return {
|
|
902
872
|
server,
|
|
903
873
|
prefix,
|
|
904
|
-
outcome: "
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
874
|
+
outcome: "refused",
|
|
875
|
+
reason: inlineUntrusted(namedMcpFailureText(err), 240),
|
|
876
|
+
toolCount: 0,
|
|
877
|
+
added: [],
|
|
878
|
+
removed: priorNames,
|
|
879
|
+
tools: [],
|
|
880
|
+
axes: [],
|
|
881
|
+
dropped: [],
|
|
882
|
+
warnings: [raised.message],
|
|
883
|
+
status,
|
|
914
884
|
};
|
|
915
885
|
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
886
|
+
const { connected } = dialed;
|
|
887
|
+
const raised = commitConnectedServer(spec, connected, dialKind);
|
|
888
|
+
reconcileInstructions(server, connected.instructions, true);
|
|
889
|
+
const newNames = connected.tools.map((t) => t.name);
|
|
890
|
+
return {
|
|
891
|
+
server,
|
|
892
|
+
prefix,
|
|
893
|
+
outcome: "reconnected",
|
|
894
|
+
toolCount: newNames.length,
|
|
895
|
+
added: newNames.filter((n) => !priorNames.includes(n)),
|
|
896
|
+
removed: priorNames.filter((n) => !newNames.includes(n)),
|
|
897
|
+
tools: connected.tools,
|
|
898
|
+
axes: connected.axes,
|
|
899
|
+
dropped: connected.dropped.map((d) => ({ server: inlineUntrusted(server, 160), ...d })),
|
|
900
|
+
...(raised.length > 0 ? { warnings: raised.map((w) => w.message) } : {}),
|
|
901
|
+
status: connected.status,
|
|
902
|
+
...(connected.listingIncomplete !== undefined ? { listingIncomplete: connected.listingIncomplete } : {}),
|
|
903
|
+
};
|
|
919
904
|
};
|
|
905
|
+
const redialOnce = (server) => (redialFlights.running(server) === undefined ? redialFlights.start(server, () => redialDial(server)) : Promise.resolve(declineRedial(server, "refused", "a re-dial of this server is already in flight — wait for it to settle")));
|
|
920
906
|
return {
|
|
921
907
|
tools,
|
|
922
908
|
toolAxes,
|
|
@@ -940,20 +926,25 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
940
926
|
results.push({ server: h.name, prefix: prefixOf(h.name), status: "revoked", toolCount: h.tools.length, added: [], removed: [], error: "server revoked by the operator — the refresh did not contact it" });
|
|
941
927
|
continue;
|
|
942
928
|
}
|
|
929
|
+
const site = requestSite(h.client);
|
|
943
930
|
try {
|
|
931
|
+
const at = h.listing.open();
|
|
944
932
|
const cacheTools = h.openListing();
|
|
945
933
|
const listed = await listToolsLenient(h.client);
|
|
946
|
-
const
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
934
|
+
const answered = h.listing.answer(at, listed.tools, listed.incomplete !== undefined);
|
|
935
|
+
const mergedRaw = answered.view;
|
|
936
|
+
if (!answered.recorded) {
|
|
937
|
+
results.push({ server: h.name, prefix: prefixOf(h.name), status: "failed", toolCount: h.tools.length, added: [], removed: [], error: "a later listing of this server was opened and applied while this one was in the air — this one was discarded" });
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
const { serverTools, serverAxes, gates, dropped, accepted } = intakeListedTools({ tools: [...mergedRaw], unproven: answered.unproven }, h.spec, linkOf(h.name), imageResizer, mcpDisclosure, isServerRevoked, h.transportKind);
|
|
941
|
+
cacheTools(accepted, answered.kept);
|
|
951
942
|
const priorNames = h.tools.map((t) => t.name);
|
|
952
943
|
const newNames = serverTools.map((t) => t.name);
|
|
953
944
|
const added = newNames.filter((n) => !priorNames.includes(n));
|
|
954
945
|
const removed = priorNames.filter((n) => !newNames.includes(n));
|
|
955
946
|
h.tools = serverTools;
|
|
956
|
-
h.
|
|
947
|
+
h.gatesAt = { at, gates };
|
|
957
948
|
results.push({
|
|
958
949
|
server: h.name,
|
|
959
950
|
prefix: prefixOf(h.name),
|
|
@@ -971,7 +962,7 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
971
962
|
});
|
|
972
963
|
}
|
|
973
964
|
catch (err) {
|
|
974
|
-
h.health.observe?.(classifyMcpFailure(err,
|
|
965
|
+
h.health.observe?.(classifyMcpFailure(err, site).kind);
|
|
975
966
|
results.push({
|
|
976
967
|
server: h.name,
|
|
977
968
|
prefix: prefixOf(h.name),
|
|
@@ -979,7 +970,7 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
979
970
|
toolCount: h.tools.length,
|
|
980
971
|
added: [],
|
|
981
972
|
removed: [],
|
|
982
|
-
error: inlineUntrusted(namedMcpFailureText(err), 240),
|
|
973
|
+
error: inlineUntrusted(namingLostSession(err, site, namedMcpFailureText(err)), 240),
|
|
983
974
|
});
|
|
984
975
|
}
|
|
985
976
|
}
|
|
@@ -1266,6 +1257,7 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1266
1257
|
}
|
|
1267
1258
|
const idleMs = mcpIdleTimeoutMs(rs.transportKind);
|
|
1268
1259
|
const watchdog = armMcpIdleWatchdog(rs.health, idleMs, signal);
|
|
1260
|
+
const site = requestSite(rs.client);
|
|
1269
1261
|
try {
|
|
1270
1262
|
const walk = await walkMcpListPages(async (cursor, remainingMs) => {
|
|
1271
1263
|
const page = await rs.client
|
|
@@ -1291,7 +1283,7 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1291
1283
|
throw err;
|
|
1292
1284
|
const msg = watchdog.idleSignal.reason === IDLE_WATCHDOG_ABORT_REASON
|
|
1293
1285
|
? idleWatchdogTripText(idleMs)
|
|
1294
|
-
: remoteErrorText(err);
|
|
1286
|
+
: namingLostSession(err, site, remoteErrorText(err));
|
|
1295
1287
|
errors.push({ server: rs.server, error: msg });
|
|
1296
1288
|
sections.push(`[${rs.server}] Error: could not list resources: ${inlineUntrusted(msg)}`);
|
|
1297
1289
|
}
|
|
@@ -1345,11 +1337,12 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1345
1337
|
const timeoutMs = mcpToolTimeoutMs();
|
|
1346
1338
|
const idleMs = mcpIdleTimeoutMs(rs.transportKind);
|
|
1347
1339
|
const watchdog = armMcpIdleWatchdog(rs.health, idleMs, signal);
|
|
1340
|
+
const site = requestSite(rs.client);
|
|
1348
1341
|
let res;
|
|
1349
1342
|
try {
|
|
1350
1343
|
res = await rs.client
|
|
1351
1344
|
.readResource({ uri }, { signal: watchdog.combinedSignal, timeout: timeoutMs })
|
|
1352
|
-
.catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs, writeEffect: false, signal, attributeServer: true, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1345
|
+
.catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1353
1346
|
rs.health.observe?.("completed");
|
|
1354
1347
|
}
|
|
1355
1348
|
finally {
|
|
@@ -1406,10 +1399,11 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1406
1399
|
const timeoutMs = mcpToolTimeoutMs();
|
|
1407
1400
|
const idleMs = mcpIdleTimeoutMs(rs.transportKind);
|
|
1408
1401
|
const watchdog = armMcpIdleWatchdog(rs.health, idleMs, signal);
|
|
1402
|
+
const site = requestSite(rs.client);
|
|
1409
1403
|
try {
|
|
1410
1404
|
const ext = rs.client.getServerCapabilities()?.extensions?.[MCP_SKILLS_EXTENSION];
|
|
1411
1405
|
if (ext?.directoryRead === true) {
|
|
1412
|
-
const r = await readDirViaExtension(rs, uri, signal, timeoutMs, watchdog).catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs, writeEffect: false, signal, attributeServer: true, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1406
|
+
const r = await readDirViaExtension(rs, uri, signal, timeoutMs, watchdog).catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1413
1407
|
const serverSaid = (detail) => `\nThe server's error text follows as external/untrusted data:\n${delimitUntrusted(`${server} error`, truncateMcpErrorText(detail))}`;
|
|
1414
1408
|
if (r.kind === "not_found") {
|
|
1415
1409
|
return {
|
|
@@ -1437,7 +1431,7 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1437
1431
|
const walk = await walkMcpListPages(async (cursor, remainingMs) => {
|
|
1438
1432
|
const page = await rs.client
|
|
1439
1433
|
.listResources(cursor === undefined ? undefined : { cursor }, { signal: watchdog.combinedSignal, timeout: remainingMs })
|
|
1440
|
-
.catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs: remainingMs, writeEffect: false, signal, attributeServer: true, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1434
|
+
.catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs: remainingMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1441
1435
|
rs.health.observe?.("completed");
|
|
1442
1436
|
return { items: page.resources, ...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}) };
|
|
1443
1437
|
}, { budgetMs: timeoutMs, onPage: () => watchdog.rearm(), fingerprintOf: listEntryFingerprint, ...(signal !== undefined ? { signal } : {}) });
|
|
@@ -1532,7 +1526,8 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
|
|
|
1532
1526
|
const announce = {};
|
|
1533
1527
|
const startupMs = mcpStartupTimeoutMs(spec);
|
|
1534
1528
|
const startupOpts = startupMs !== undefined ? { timeout: startupMs } : undefined;
|
|
1535
|
-
const dialClient = async () => {
|
|
1529
|
+
const dialClient = async (stop = dialOpts?.signal) => {
|
|
1530
|
+
stop?.throwIfAborted();
|
|
1536
1531
|
const client = new Client({ name: `sema-core/${spec.name}`, version: "0.1.0" }, { capabilities: elicitOn ? { elicitation: { form: {} } } : {} });
|
|
1537
1532
|
if (elicitOn) {
|
|
1538
1533
|
client.setRequestHandler(ElicitRequestSchema, async (request, extra) => {
|
|
@@ -1555,12 +1550,17 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
|
|
|
1555
1550
|
});
|
|
1556
1551
|
}
|
|
1557
1552
|
const transport = buildTransport(spec, principal, transportKind);
|
|
1553
|
+
const hangUp = () => void client.close().catch(() => undefined);
|
|
1554
|
+
stop?.addEventListener("abort", hangUp, { once: true });
|
|
1558
1555
|
try {
|
|
1559
1556
|
await client.connect(transport, startupOpts);
|
|
1560
1557
|
}
|
|
1561
1558
|
catch (err) {
|
|
1562
1559
|
await client.close().catch(() => undefined);
|
|
1563
|
-
throw err;
|
|
1560
|
+
throw stop?.aborted === true ? stop.reason : err;
|
|
1561
|
+
}
|
|
1562
|
+
finally {
|
|
1563
|
+
stop?.removeEventListener("abort", hangUp);
|
|
1564
1564
|
}
|
|
1565
1565
|
return client;
|
|
1566
1566
|
};
|
|
@@ -1580,10 +1580,13 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
|
|
|
1580
1580
|
lease.onClose(onClosed);
|
|
1581
1581
|
else
|
|
1582
1582
|
client.onclose = onClosed;
|
|
1583
|
+
const listing = lease?.listing ?? new ConnectionListing();
|
|
1584
|
+
const at = listing.open();
|
|
1583
1585
|
const cacheTools = openListing();
|
|
1584
|
-
const listed = await listToolsLenient(client,
|
|
1585
|
-
const
|
|
1586
|
-
|
|
1586
|
+
const listed = await underStartupBound(startupMs, dialOpts?.signal, (options) => listToolsLenient(client, options));
|
|
1587
|
+
const answered = listing.answer(at, listed.tools, listed.incomplete !== undefined, dialOpts.carried);
|
|
1588
|
+
const { serverTools, serverAxes, gates, dropped, advisories, accepted } = intakeListedTools({ tools: [...answered.view], unproven: answered.unproven }, spec, dialOpts.link, imageResizer, reminderDisclosure, isServerRevoked, transportKind);
|
|
1589
|
+
cacheTools(accepted, answered.kept);
|
|
1587
1590
|
const caps = client.getServerCapabilities();
|
|
1588
1591
|
const resourceInfo = caps?.resources
|
|
1589
1592
|
? {
|
|
@@ -1612,10 +1615,11 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
|
|
|
1612
1615
|
announce,
|
|
1613
1616
|
tools: serverTools,
|
|
1614
1617
|
axes: serverAxes,
|
|
1618
|
+
listing,
|
|
1619
|
+
gatesAt: { at, gates },
|
|
1615
1620
|
dropped,
|
|
1616
1621
|
schemaAdvisories: advisories,
|
|
1617
1622
|
...(listed.toolsCapabilityAbsent === true ? { toolsCapabilityAbsent: true } : {}),
|
|
1618
|
-
listedTools: listed.tools,
|
|
1619
1623
|
...(instructions ? { instructions } : {}),
|
|
1620
1624
|
...(disposed?.defect !== undefined ? { instructionsDefect: disposed.defect } : {}),
|
|
1621
1625
|
...(listed.incomplete !== undefined ? { listingIncomplete: listed.incomplete } : {}),
|
|
@@ -1627,10 +1631,11 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
|
|
|
1627
1631
|
throw err;
|
|
1628
1632
|
}
|
|
1629
1633
|
}
|
|
1630
|
-
function intakeListedTools(listed, spec,
|
|
1634
|
+
function intakeListedTools(listed, spec, link, imageResizer, reminderDisclosure, isServerRevoked, transportKind) {
|
|
1631
1635
|
const declaredContentOrigin = spec.contentOrigin;
|
|
1632
1636
|
const serverTools = [];
|
|
1633
1637
|
const serverAxes = [];
|
|
1638
|
+
const gates = new Map();
|
|
1634
1639
|
const dropped = [];
|
|
1635
1640
|
const accepted = [];
|
|
1636
1641
|
const advisories = [];
|
|
@@ -1697,6 +1702,9 @@ function intakeListedTools(listed, spec, client, health, imageResizer, reminderD
|
|
|
1697
1702
|
if (interaction.advisory !== undefined)
|
|
1698
1703
|
advisories.push({ tool: inlineUntrusted(t.name), reason: interaction.advisory });
|
|
1699
1704
|
const mcpAlwaysLoad = mcpToolMeta?.["anthropic/alwaysLoad"] === true;
|
|
1705
|
+
const gateFace = { ...(interaction.declared ? { mcpRequiresUserInteraction: true } : {}), ...(t.annotations?.readOnlyHint === true ? { mcpReadOnlyHint: true } : {}) };
|
|
1706
|
+
const gate = mcpToolGate(remoteName, axis, gateFace, taskRequired);
|
|
1707
|
+
gates.set(namespacedName, listed.unproven?.has(remoteName) === true ? UNPROVEN_GATE : gate);
|
|
1700
1708
|
const mounted = {
|
|
1701
1709
|
name: namespacedName,
|
|
1702
1710
|
description: capMcpToolDescription(effectiveDescription ?? `MCP tool ${inlineUntrusted(sanitizeMcpModelFacingText(remoteName))} from ${spec.name}`),
|
|
@@ -1704,8 +1712,8 @@ function intakeListedTools(listed, spec, client, health, imageResizer, reminderD
|
|
|
1704
1712
|
parameters: (effectiveInputSchema ?? { type: "object" }),
|
|
1705
1713
|
...(mcpMaxResultSizeChars !== undefined ? { mcpMaxResultSizeChars } : {}),
|
|
1706
1714
|
...(mcpAlwaysLoad ? { mcpAlwaysLoad: true } : {}),
|
|
1707
|
-
...
|
|
1708
|
-
mcpRemoteName: remoteName, ...boundaryFlowFace(spec.toolAxes?.[remoteName]),
|
|
1715
|
+
...gateFace,
|
|
1716
|
+
mcpRemoteName: remoteName, ...boundaryFlowFace(spec.toolAxes?.[remoteName]), permissionSeat: "passthrough",
|
|
1709
1717
|
execute: async (_toolCallId, params, signal) => {
|
|
1710
1718
|
const what = `The call to tool ${inlineUntrusted(remoteName)}`;
|
|
1711
1719
|
if (isServerRevoked?.(spec.name) === true) {
|
|
@@ -1724,38 +1732,55 @@ function intakeListedTools(listed, spec, client, health, imageResizer, reminderD
|
|
|
1724
1732
|
isError: true,
|
|
1725
1733
|
};
|
|
1726
1734
|
}
|
|
1727
|
-
if (health.dead)
|
|
1728
|
-
throwDeadServer(spec.name, what);
|
|
1729
1735
|
const timeoutMs = mcpToolTimeoutMs();
|
|
1730
1736
|
const idleMs = mcpIdleTimeoutMs(idleKindOf(transportKind));
|
|
1731
|
-
const
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1737
|
+
const send = async (conn, resent) => {
|
|
1738
|
+
const site = requestSite(conn.client);
|
|
1739
|
+
const watchdog = armMcpIdleWatchdog(conn.health, idleMs, signal);
|
|
1740
|
+
try {
|
|
1741
|
+
const res = await conn.client
|
|
1742
|
+
.callTool({ name: remoteName, arguments: (params ?? {}) }, LENIENT_CALL_TOOL_RESULT_SCHEMA, {
|
|
1743
|
+
signal: watchdog.combinedSignal,
|
|
1744
|
+
timeout: timeoutMs,
|
|
1745
|
+
resetTimeoutOnProgress: true,
|
|
1746
|
+
onprogress: () => watchdog.rearm(),
|
|
1747
|
+
maxTotalTimeout: mcpToolTotalTimeoutMs(timeoutMs),
|
|
1748
|
+
})
|
|
1749
|
+
.catch((err) => {
|
|
1750
|
+
try {
|
|
1751
|
+
return rethrowHonestMcpError(err, {
|
|
1752
|
+
server: spec.name,
|
|
1753
|
+
what,
|
|
1754
|
+
timeoutMs,
|
|
1755
|
+
writeEffect,
|
|
1756
|
+
signal,
|
|
1757
|
+
site,
|
|
1758
|
+
...(resent ? { resent: true } : {}),
|
|
1759
|
+
idle: { signal: watchdog.idleSignal, idleMs },
|
|
1760
|
+
liveness: conn.health,
|
|
1761
|
+
...(reminderDisclosure !== undefined
|
|
1762
|
+
? { reminder: { mark: reminderDisclosure.mark, outlet: "mcp", ...(reminderDisclosure.counts !== undefined ? { counts: reminderDisclosure.counts } : {}) } }
|
|
1763
|
+
: {}),
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
catch (failure) {
|
|
1767
|
+
if (sessionGone(err, site) && signal?.aborted !== true)
|
|
1768
|
+
return new Resendable(conn, failure);
|
|
1769
|
+
throw failure;
|
|
1770
|
+
}
|
|
1771
|
+
});
|
|
1772
|
+
if (res instanceof Resendable)
|
|
1773
|
+
return res;
|
|
1774
|
+
conn.health.observe?.("completed");
|
|
1775
|
+
return res;
|
|
1776
|
+
}
|
|
1777
|
+
finally {
|
|
1778
|
+
watchdog.dispose();
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
const res = await callThroughLink(link, namespacedName, gate, signal, send, () => throwDeadServer(spec.name, what));
|
|
1782
|
+
if (typeof res === "string")
|
|
1783
|
+
return listingRefusal(res, remoteName, spec.name);
|
|
1759
1784
|
const mapped = await mapContent(res.content, spec.name, imageResizer);
|
|
1760
1785
|
if (res.isError === true) {
|
|
1761
1786
|
const parts = [];
|
|
@@ -1815,7 +1840,7 @@ function intakeListedTools(listed, spec, client, health, imageResizer, reminderD
|
|
|
1815
1840
|
serverTools.push(declaredContentOrigin !== undefined ? withContentOrigin(mounted, declaredContentOrigin) : mounted);
|
|
1816
1841
|
accepted.push(t);
|
|
1817
1842
|
}
|
|
1818
|
-
return { serverTools, serverAxes, dropped, advisories, accepted };
|
|
1843
|
+
return { serverTools, serverAxes, gates, dropped, advisories, accepted };
|
|
1819
1844
|
}
|
|
1820
1845
|
function asServerWarning(spec, err) {
|
|
1821
1846
|
const warning = new Error(`mcp: server "${spec.name}" failed to connect — skipped (${namedMcpFailureText(err)})`, { cause: sanitizedCause(err) });
|
|
@@ -4,7 +4,7 @@ import type { DocumentContent, ImageContent } from "../internal/llm.js";
|
|
|
4
4
|
* Aggregate MEDIA (image) byte budget — the multimodal sibling of {@link AGGREGATE_TOOL_RESULT_BUDGET_CHARS}
|
|
5
5
|
* (which only counts TEXT, design/64 §17.2). batch-C added image reads (`Read` → `ImageContent`); each is bounded
|
|
6
6
|
* per-image (`MAX_IMAGE_READ_BYTES`), but N images accumulate ACROSS turns in the context and would otherwise grow
|
|
7
|
-
* the request unboundedly (a real gap —
|
|
7
|
+
* the request unboundedly (a real gap — the reference added the same cap, `tengu_media_byte_cap`, validating it).
|
|
8
8
|
*
|
|
9
9
|
* This caps the SUM of inline image bytes across the whole message list: while over budget, the OLDEST images are
|
|
10
10
|
* stripped (replaced with a short text marker) until it fits — recent media (most relevant) is kept. Like the text
|