@sema-agent/core 7.55.0 → 7.56.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 +513 -0
- package/dist/agents/cascade.js +1 -1
- package/dist/agents/cc-peer-directory.js +1 -0
- package/dist/agents/child-model-seat.d.ts +0 -11
- package/dist/agents/child-model-seat.js +0 -3
- package/dist/agents/list-agents-tool.d.ts +3 -1
- package/dist/agents/list-agents-tool.js +7 -7
- package/dist/agents/peer-directory.d.ts +22 -4
- package/dist/agents/peer-directory.js +24 -2
- package/dist/agents/peer-session-drain.js +2 -2
- package/dist/agents/repair-loop.js +2 -2
- package/dist/agents/send-message-tool.js +4 -4
- package/dist/agents/subagent.d.ts +6 -4
- package/dist/agents/subagent.js +64 -60
- package/dist/agents/tool-filter.d.ts +7 -5
- package/dist/agents/tool-filter.js +12 -9
- package/dist/agents/verify.d.ts +3 -2
- package/dist/agents/verify.js +3 -3
- package/dist/brain/anthropic.js +30 -73
- package/dist/brain/media-degrade.d.ts +18 -7
- package/dist/brain/media-degrade.js +13 -2
- package/dist/brain/model-capability.d.ts +37 -0
- package/dist/brain/model-capability.js +34 -0
- package/dist/brain/model-presets.d.ts +2 -8
- package/dist/brain/model-presets.js +1 -6
- package/dist/brain/open-responses.js +13 -26
- package/dist/brain/openai.js +14 -87
- package/dist/brain/reasoning-request.d.ts +96 -0
- package/dist/brain/reasoning-request.js +174 -0
- package/dist/brain/reasoning.d.ts +11 -11
- package/dist/brain/reasoning.js +4 -3
- package/dist/brain/request-params.d.ts +7 -4
- package/dist/brain/request-params.js +7 -4
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/core/a2a.d.ts +2 -1
- package/dist/core/a2a.js +19 -13
- package/dist/core/agent-definition.d.ts +10 -0
- package/dist/core/allow-entry.d.ts +20 -13
- package/dist/core/allow-entry.js +26 -22
- package/dist/core/allow-rule-shadow.d.ts +3 -3
- package/dist/core/ask-origin.d.ts +64 -18
- package/dist/core/ask-origin.js +63 -23
- package/dist/core/ask-question.d.ts +51 -8
- package/dist/core/ask-question.js +3 -4
- package/dist/core/ask-unresolvable-notice.d.ts +8 -3
- package/dist/core/ask-unresolvable-notice.js +16 -2
- package/dist/core/checkpoint-generation.d.ts +53 -0
- package/dist/core/checkpoint-generation.js +35 -0
- package/dist/core/checkpoint-queries.d.ts +180 -0
- package/dist/core/checkpoint-queries.js +272 -0
- package/dist/core/checkpoint-requirements.d.ts +13 -1
- package/dist/core/checkpoint-requirements.js +4 -0
- package/dist/core/checkpoint-store.d.ts +88 -24
- package/dist/core/checkpoint-store.js +24 -9
- package/dist/core/cross-boundary-taint.d.ts +6 -5
- package/dist/core/cross-boundary-taint.js +1 -3
- package/dist/core/decision-receipt.d.ts +37 -3
- package/dist/core/decision-receipt.js +17 -17
- package/dist/core/delegation-not-started.d.ts +6 -0
- package/dist/core/delegation-not-started.js +17 -0
- package/dist/core/engine-attestation.d.ts +93 -0
- package/dist/core/engine-attestation.js +70 -0
- package/dist/core/engine-capabilities.d.ts +4 -1
- package/dist/core/engine-capabilities.js +1 -1
- package/dist/core/engine-notice.d.ts +30 -11
- package/dist/core/file-history-store.d.ts +90 -14
- package/dist/core/file-history-store.js +23 -15
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +22 -10
- package/dist/core/gate-lanes.js +73 -64
- package/dist/core/gate-outcome.d.ts +26 -5
- package/dist/core/gate-outcome.js +26 -0
- package/dist/core/governance-codes.d.ts +5 -1
- package/dist/core/governance-codes.js +6 -0
- package/dist/core/hooks.d.ts +17 -16
- package/dist/core/hooks.js +3 -1
- package/dist/core/host-floor.d.ts +128 -0
- package/dist/core/host-floor.js +206 -0
- package/dist/core/host-target.d.ts +38 -3
- package/dist/core/host-target.js +38 -5
- package/dist/core/mcp.d.ts +5 -1
- package/dist/core/mcp.js +67 -41
- package/dist/core/memory-engine/delegation-settlement.js +15 -24
- package/dist/core/memory-engine/engine.js +4 -4
- package/dist/core/memory-engine/layout.d.ts +60 -8
- package/dist/core/memory-engine/layout.js +65 -6
- package/dist/core/model-seat.d.ts +10 -3
- package/dist/core/mods/classic-events.d.ts +67 -0
- package/dist/core/mods/classic-events.js +1 -0
- package/dist/core/mods/dollar.d.ts +13 -0
- package/dist/core/mods/extension-call.d.ts +31 -0
- package/dist/core/mods/extension-call.js +43 -0
- package/dist/core/mods/kernel/dispatch.d.ts +20 -3
- package/dist/core/mods/kernel/dispatch.js +140 -69
- package/dist/core/mods/kernel/events.d.ts +47 -11
- package/dist/core/mods/kernel/events.js +66 -42
- package/dist/core/mods/kernel/index.d.ts +4 -4
- package/dist/core/mods/kernel/index.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +39 -5
- package/dist/core/mods/kernel/receive.js +290 -17
- package/dist/core/mods/kernel/registration.d.ts +33 -2
- package/dist/core/mods/kernel/registration.js +6 -7
- package/dist/core/mods/kernel/site-rules.d.ts +44 -16
- package/dist/core/mods/kernel/site-rules.js +24 -42
- package/dist/core/mods/spec-seats.d.ts +69 -0
- package/dist/core/mods/spec-seats.js +114 -0
- package/dist/core/mods/stations.d.ts +28 -8
- package/dist/core/mods/stations.js +29 -13
- package/dist/core/mods/tool-call.d.ts +79 -0
- package/dist/core/mods/tool-call.js +152 -0
- package/dist/core/namespaced-rule-name.d.ts +32 -38
- package/dist/core/namespaced-rule-name.js +29 -36
- package/dist/core/parent-spec-seat.d.ts +6 -1
- package/dist/core/parent-spec-seat.js +2 -0
- package/dist/core/park-selfcheck.js +1 -0
- package/dist/core/permission-rule-consent.d.ts +19 -0
- package/dist/core/permission-rule-consent.js +116 -26
- package/dist/core/permission-rule-model.d.ts +14 -3
- package/dist/core/permission-rule-model.js +39 -24
- package/dist/core/permission-rule-org.d.ts +6 -2
- package/dist/core/permission-rule-org.js +7 -3
- package/dist/core/permission-rule-provider.d.ts +5 -2
- package/dist/core/permission-rule-provider.js +41 -11
- package/dist/core/permission-rule-store.d.ts +3 -2
- package/dist/core/permission-rule-store.js +11 -2
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/permission-rule-syntax.d.ts +5 -4
- package/dist/core/permission-rule-syntax.js +2 -2
- package/dist/core/permission-rules.d.ts +4 -4
- package/dist/core/permission-rules.js +11 -20
- package/dist/core/persisted-rule-arms.d.ts +2 -2
- package/dist/core/persisted-rule-arms.js +10 -12
- package/dist/core/principal-name.d.ts +20 -0
- package/dist/core/principal-name.js +22 -0
- package/dist/core/prompt-section-seat.js +4 -6
- package/dist/core/protocol-http-auth.d.ts +26 -5
- package/dist/core/protocol-http-auth.js +137 -4
- package/dist/core/retired-keys.d.ts +16 -0
- package/dist/core/retired-keys.js +16 -4
- package/dist/core/rewrite-rejudge.d.ts +60 -0
- package/dist/core/rewrite-rejudge.js +36 -0
- package/dist/core/roles.d.ts +28 -1
- package/dist/core/roles.js +31 -19
- package/dist/core/rule-lane-reads.d.ts +20 -15
- package/dist/core/rule-lane-reads.js +45 -17
- package/dist/core/rule-owner.d.ts +3 -3
- package/dist/core/rule-owner.js +3 -2
- package/dist/core/runner/announce-once-ledger.d.ts +14 -0
- package/dist/core/runner/announce-once-ledger.js +5 -0
- package/dist/core/runner/assemble-result.d.ts +1 -0
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/call-hook-stations.d.ts +3 -2
- package/dist/core/runner/caller-roster.d.ts +16 -4
- package/dist/core/runner/caller-roster.js +33 -6
- package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
- package/dist/core/runner/capability-withheld-seat.js +24 -0
- package/dist/core/runner/classifier-ladder.d.ts +7 -9
- package/dist/core/runner/classifier-ladder.js +3 -3
- package/dist/core/runner/construction-doors.js +3 -0
- package/dist/core/runner/contracts.d.ts +28 -25
- package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
- package/dist/core/runner/cross-boundary-lane.js +40 -27
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/denial-limit-arms.js +1 -1
- package/dist/core/runner/file-history-request.d.ts +18 -0
- package/dist/core/runner/file-history-request.js +21 -13
- package/dist/core/runner/file-history-restore.d.ts +45 -0
- package/dist/core/runner/file-history-restore.js +46 -0
- package/dist/core/runner/gate-exit.d.ts +3 -3
- package/dist/core/runner/gate-exit.js +4 -3
- package/dist/core/runner/image.d.ts +7 -17
- package/dist/core/runner/image.js +9 -60
- package/dist/core/runner/permission-rule-lanes.d.ts +4 -4
- package/dist/core/runner/permission-rule-lanes.js +26 -10
- package/dist/core/runner/person-path-rows.d.ts +12 -9
- package/dist/core/runner/person-path-rows.js +18 -7
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
- package/dist/core/runner/prepare-ask-lane.js +5 -2
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
- package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
- package/dist/core/runner/prepare-config-doors.d.ts +29 -38
- package/dist/core/runner/prepare-config-doors.js +42 -25
- package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
- package/dist/core/runner/prepare-defer-classify.js +7 -8
- package/dist/core/runner/prepare-file-history.d.ts +48 -8
- package/dist/core/runner/prepare-file-history.js +7 -39
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
- package/dist/core/runner/prepare-gate-stations.js +10 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
- package/dist/core/runner/prepare-hands-readface.js +15 -14
- package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
- package/dist/core/runner/prepare-inherited-gate.js +5 -3
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.js +5 -5
- package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
- package/dist/core/runner/prepare-policy-chain.js +65 -72
- package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
- package/dist/core/runner/prepare-prompt-assembly.js +10 -8
- package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
- package/dist/core/runner/prepare-prompt-inputs.js +3 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
- package/dist/core/runner/prepare-protocol-tools.js +3 -3
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-safety-scan.js +0 -17
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
- package/dist/core/runner/prepare-suspend-saga.js +5 -6
- package/dist/core/runner/prepare-task.d.ts +1 -1
- package/dist/core/runner/prepare-task.js +29 -20
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
- package/dist/core/runner/prepare-tool-disclosure-mount.js +20 -16
- package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
- package/dist/core/runner/prepare-turn-wiring.js +2 -7
- package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
- package/dist/core/runner/prepare-wiring-manifest.js +3 -3
- package/dist/core/runner/resume-admission.js +1 -1
- package/dist/core/runner/resume-apply.js +11 -12
- package/dist/core/runner/resume-checkpoint-screen.js +3 -0
- package/dist/core/runner/resume-claim.d.ts +4 -2
- package/dist/core/runner/resume-claim.js +15 -8
- package/dist/core/runner/retired-runner-deps.js +1 -0
- package/dist/core/runner/rewind-files.d.ts +15 -0
- package/dist/core/runner/rewind-files.js +132 -0
- package/dist/core/runner/run-attachment-seats.js +2 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -1
- package/dist/core/runner/run-brain-sinks.js +4 -2
- package/dist/core/runner/run-harness-handlers.js +12 -4
- package/dist/core/runner/run-leg.d.ts +1 -1
- package/dist/core/runner/run-leg.js +30 -18
- package/dist/core/runner/run-settle-and-teardown.js +2 -1
- package/dist/core/runner/run-turn-boundary.js +1 -10
- package/dist/core/runner/runtask.d.ts +3 -0
- package/dist/core/runner/runtask.js +8 -9
- package/dist/core/runner/session-read-file-states.d.ts +15 -0
- package/dist/core/runner/session-read-file-states.js +28 -0
- package/dist/core/runner/session-rule-policy.js +4 -3
- package/dist/core/runner/shell-env-withheld.d.ts +33 -0
- package/dist/core/runner/shell-env-withheld.js +51 -0
- package/dist/core/runner/skills-seat.js +6 -2
- package/dist/core/runner/stream-settle-backstop.js +1 -1
- package/dist/core/runner/sub-agent-deny-lists.js +4 -7
- package/dist/core/runner/synthetic-tools.d.ts +6 -0
- package/dist/core/runner/synthetic-tools.js +4 -1
- package/dist/core/runner/tool-disclosure.d.ts +10 -12
- package/dist/core/runner/tool-disclosure.js +1 -3
- package/dist/core/runner/tool-end-body.d.ts +1 -1
- package/dist/core/runner/tool-end-body.js +10 -9
- package/dist/core/runner/tool-not-executed.d.ts +5 -0
- package/dist/core/runner/tool-not-executed.js +11 -0
- package/dist/core/runner/tool-occurrence.d.ts +8 -0
- package/dist/core/runner/tool-occurrence.js +7 -0
- package/dist/core/runner/turn-attachments.d.ts +33 -15
- package/dist/core/runner/turn-attachments.js +62 -37
- package/dist/core/runner-deps.d.ts +5 -5
- package/dist/core/safety-axis-vocab.d.ts +6 -4
- package/dist/core/safety-axis-vocab.js +6 -5
- package/dist/core/safety-merge-corpus.js +11 -3
- package/dist/core/secret-env.d.ts +26 -3
- package/dist/core/secret-env.js +44 -8
- package/dist/core/select-model.js +3 -3
- package/dist/core/session-policy-store.d.ts +27 -15
- package/dist/core/session-policy-store.js +156 -36
- package/dist/core/session-store.d.ts +29 -10
- package/dist/core/session-store.js +51 -19
- package/dist/core/session.d.ts +82 -16
- package/dist/core/session.js +53 -0
- package/dist/core/shell-read-silence.d.ts +11 -12
- package/dist/core/shell-read-silence.js +9 -5
- package/dist/core/shell-run-candidates.js +3 -1
- package/dist/core/shell-wrapper-projection.js +1 -1
- package/dist/core/shell-wrapper-table.d.ts +14 -7
- package/dist/core/shell-wrapper-table.js +5 -4
- package/dist/core/side-query.js +10 -1
- package/dist/core/skill-grant.d.ts +7 -2
- package/dist/core/skill-grant.js +5 -0
- package/dist/core/skills-directory.js +6 -2
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +140 -2
- package/dist/core/store-contracts/file-history-store-contract.js +31 -1
- package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
- package/dist/core/store-contracts/peer-directory-contract.js +14 -2
- package/dist/core/store-contracts/session-repo-contract.js +51 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
- package/dist/core/store-contracts/session-store-contract.js +150 -14
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +3 -3
- package/dist/core/task-event.d.ts +32 -4
- package/dist/core/task-notification.d.ts +16 -12
- package/dist/core/task-registry.d.ts +9 -0
- package/dist/core/task-registry.js +11 -1
- package/dist/core/task-result.d.ts +18 -0
- package/dist/core/task-spec.d.ts +18 -13
- package/dist/core/tighten-task-spec.js +2 -1
- package/dist/core/tool-catalog-entries.d.ts +17 -0
- package/dist/core/tool-catalog-entries.js +13 -2
- package/dist/core/tool-check-reading.d.ts +11 -0
- package/dist/core/tool-check-reading.js +11 -6
- package/dist/core/tool-model-gate.d.ts +2 -2
- package/dist/core/tool-name-aliases.d.ts +16 -16
- package/dist/core/tool-name-aliases.js +13 -19
- package/dist/core/tool-name-readings.d.ts +5 -35
- package/dist/core/tool-name-readings.js +1 -9
- package/dist/core/tool-policy.d.ts +68 -198
- package/dist/core/tool-policy.js +149 -198
- package/dist/core/tool-result-store.js +3 -0
- package/dist/core/tool-roster.d.ts +14 -19
- package/dist/core/tool-roster.js +11 -44
- package/dist/core/tool-spec-members.js +7 -2
- package/dist/core/tool-spec.d.ts +19 -11
- package/dist/core/tools.js +49 -9
- package/dist/core/trace.d.ts +2 -2
- package/dist/core/types.d.ts +1 -1
- package/dist/core/user-attachment.d.ts +8 -1
- package/dist/core/user-attachment.js +64 -4
- package/dist/core/wiring-manifest.d.ts +9 -0
- package/dist/core/wiring-manifest.js +1 -0
- package/dist/core/workflow-journal-store.js +1 -1
- package/dist/engine/compaction/compaction.js +3 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
- package/dist/engine/execution-env/node-execution-env.js +11 -2
- package/dist/engine/harness/agent-harness.d.ts +25 -1
- package/dist/engine/harness/agent-harness.js +54 -7
- package/dist/engine/harness/types.d.ts +29 -2
- package/dist/engine/llm/types.d.ts +28 -11
- package/dist/engine/loop/agent-loop.d.ts +22 -0
- package/dist/engine/loop/agent-loop.js +16 -26
- package/dist/engine/loop/types.d.ts +16 -6
- package/dist/engine/session/memory-repo.d.ts +9 -2
- package/dist/engine/session/memory-repo.js +11 -1
- package/dist/engine/session/repo-utils.d.ts +6 -5
- package/dist/engine/session/repo-utils.js +14 -6
- package/dist/index.d.ts +22 -10
- package/dist/index.js +15 -7
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/llm.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +6 -4
- package/dist/orchestration/run-workflow-tool.js +5 -3
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +36 -18
- package/dist/prompt-assembly/artifact.d.ts +2 -2
- package/dist/prompt-assembly/artifact.js +5 -3
- package/dist/prompt-assembly/assemble.d.ts +3 -2
- package/dist/prompt-assembly/assemble.js +1 -1
- package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
- package/dist/prompt-assembly/catalog/schema.js +34 -2
- package/dist/prompt-assembly/catalog/sections.js +0 -1
- package/dist/prompt-assembly/composer.d.ts +3 -1
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/event-registry.js +1 -0
- package/dist/prompt-assembly/overlay.js +3 -3
- package/dist/prompt-assembly/renderers.d.ts +1 -1
- package/dist/prompt-assembly/renderers.js +0 -3
- package/dist/prompt-assembly/role-base.d.ts +15 -0
- package/dist/prompt-assembly/role-base.js +9 -0
- package/dist/prompt-assembly/select.d.ts +39 -14
- package/dist/prompt-assembly/select.js +47 -16
- package/dist/prompt-assembly/sugar.d.ts +17 -11
- package/dist/prompt-assembly/sugar.js +8 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
- package/dist/prompt-assembly/tool-catalog.js +114 -4
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
- package/dist/prompt-assembly/turn-snapshot.js +0 -3
- package/dist/prompt-assembly/types.d.ts +0 -7
- package/dist/scenarios/full-body.d.ts +11 -11
- package/dist/scenarios/full-body.js +4 -3
- package/dist/shell/lex.js +10 -1
- package/dist/stores/file/adoption/adopt.js +4 -3
- package/dist/stores/file/adoption/marker.js +3 -2
- package/dist/stores/file/checkpoint-store.d.ts +21 -0
- package/dist/stores/file/checkpoint-store.js +38 -6
- package/dist/stores/file/file-history-store.js +6 -7
- package/dist/stores/file/index.js +2 -1
- package/dist/stores/file/permission-rule-adopt.js +4 -3
- package/dist/stores/file/permission-rule-store.js +11 -5
- package/dist/stores/file/session-store.d.ts +29 -6
- package/dist/stores/file/session-store.js +42 -50
- package/dist/tools/artifact/artifact-tool.js +3 -2
- package/dist/tools/fs/bash-program-position.d.ts +19 -2
- package/dist/tools/fs/bash-program-position.js +56 -9
- package/dist/tools/fs/fs-bash.js +5 -5
- package/dist/tools/fs/fs-glob.d.ts +86 -0
- package/dist/tools/fs/fs-glob.js +226 -0
- package/dist/tools/fs/fs-read.js +14 -14
- package/dist/tools/fs/fs-search-tools.js +7 -7
- package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
- package/dist/tools/fs/pattern-kill-guard.js +397 -0
- package/dist/tools/fs/pdf.d.ts +9 -6
- package/dist/tools/fs/pdf.js +3 -3
- package/dist/tools/fs/program-read-model.d.ts +57 -7
- package/dist/tools/fs/program-read-model.js +11 -1
- package/dist/tools/fs/program-read-model.rows.js +78 -21
- package/dist/tools/fs/read-deny-home.js +3 -2
- package/dist/tools/fs/removal-targets.d.ts +17 -7
- package/dist/tools/fs/removal-targets.js +47 -20
- package/dist/tools/fs/search.d.ts +10 -0
- package/dist/tools/fs/search.js +20 -26
- package/dist/tools/fs/shell-read-argv.js +89 -12
- package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
- package/dist/tools/fs/shell-read-bindings.js +41 -0
- package/dist/tools/fs/shell-read-check.js +6 -19
- package/dist/tools/fs/shell-read-environment.d.ts +5 -1
- package/dist/tools/fs/shell-read-environment.js +3 -2
- package/dist/tools/fs/shell-read-establish.d.ts +15 -0
- package/dist/tools/fs/shell-read-establish.js +19 -20
- package/dist/tools/fs/shell-read-plan.js +24 -16
- package/dist/tools/fs/shell-read-start.d.ts +6 -1
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
- package/dist/tools/fs/shell-read-write-targets.js +2 -3
- package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
- package/dist/tools/fs/shell-reentry-text.js +40 -2
- package/dist/tools/todo.js +63 -63
- package/dist/tools/web.d.ts +19 -14
- package/dist/tools/web.js +38 -55
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +143 -5
- package/wire-changes/core@7.56.0.json +3891 -0
- package/wire-changes/mods-kernel@7.56.0.json +303 -0
package/dist/core/mcp.js
CHANGED
|
@@ -2,7 +2,7 @@ import { egressText } from "./untrusted-egress.js";
|
|
|
2
2
|
import { __resetEnvKnobAnnouncements } from "./env-knob-announce.js";
|
|
3
3
|
import { resolveEnvBudget } from "./env-budget.js";
|
|
4
4
|
import { MCP_NAMESPACE } from "./protocol-table.js";
|
|
5
|
-
import { resolveProtocolHttpHeaders } from "./protocol-http-auth.js";
|
|
5
|
+
import { declaredHeaderValues, resolveProtocolHttpHeaders, scrubRequestEcho } from "./protocol-http-auth.js";
|
|
6
6
|
import { disposeSectionEntry, sectionAnswerWarning } from "./prompt-section-seat.js";
|
|
7
7
|
import { findNamespacePrefixCollision, mintNamespacePrefix, mintNamespacedToolName, normalizeNameSegment } from "./protocol-naming.js";
|
|
8
8
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
@@ -22,6 +22,7 @@ import { DEFAULT_REQUEST_TIMEOUT_MSEC } from "@modelcontextprotocol/sdk/shared/p
|
|
|
22
22
|
import { MCP_IMAGE_MAX_BASE64, sharpImageResizer } from "./image-downsample.js";
|
|
23
23
|
import { sliceHeadSafe, sliceTailSafe } from "./surrogate-safe-slice.js";
|
|
24
24
|
import { truncateError } from "./tool-errors.js";
|
|
25
|
+
import { peerRequestRefusal } from "./host-floor.js";
|
|
25
26
|
import { delimitUntrusted, inlineUntrusted, sanitizeUntrustedText } from "./untrusted-text.js";
|
|
26
27
|
import { discloseReminderShaped, observeReminderMarkEcho } from "./reminder-disclosure.js";
|
|
27
28
|
import { MARKED_BLOCK_AFTER_DATA } from "./reminder-mint.js";
|
|
@@ -161,21 +162,24 @@ export function collapseMcpErrorPrefix(message) {
|
|
|
161
162
|
out = out.slice(m[0].length);
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
|
-
function sanitizeMcpErrorTextInPlace(err) {
|
|
165
|
+
function sanitizeMcpErrorTextInPlace(err, declared) {
|
|
165
166
|
if (!(err instanceof Error))
|
|
166
167
|
return;
|
|
167
|
-
const sanitized =
|
|
168
|
+
const sanitized = mcpRemoteText(err instanceof McpError ? collapseMcpErrorPrefix(err.message) : err.message, declared);
|
|
168
169
|
if (sanitized !== err.message)
|
|
169
170
|
err.message = sanitized;
|
|
170
171
|
}
|
|
171
|
-
function namedMcpFailureText(err) {
|
|
172
|
-
const detail = remoteErrorText(err, { collapse: true });
|
|
172
|
+
function namedMcpFailureText(err, declared) {
|
|
173
|
+
const detail = remoteErrorText(err, declared, { collapse: true });
|
|
173
174
|
const condition = thrownIs(err, McpError) ? describeMcpSpecErrorCode(readMember(err, "code")) : undefined;
|
|
174
175
|
return condition !== undefined ? `${condition}: ${detail}` : detail;
|
|
175
176
|
}
|
|
176
|
-
function remoteErrorText(err, opts) {
|
|
177
|
+
function remoteErrorText(err, declared, opts) {
|
|
177
178
|
const raw = thrownText(err);
|
|
178
|
-
return
|
|
179
|
+
return mcpRemoteText(opts?.collapse === true ? collapseMcpErrorPrefix(raw) : raw, declared);
|
|
180
|
+
}
|
|
181
|
+
function mcpRemoteText(text, declared) {
|
|
182
|
+
return egressText("same-principal", scrubRequestEcho(text, declared));
|
|
179
183
|
}
|
|
180
184
|
function writeEffectWarning(writeEffect) {
|
|
181
185
|
return writeEffect
|
|
@@ -194,7 +198,7 @@ function rethrowHonestMcpError(err, ctx) {
|
|
|
194
198
|
}
|
|
195
199
|
throw e;
|
|
196
200
|
};
|
|
197
|
-
sanitizeMcpErrorTextInPlace(err);
|
|
201
|
+
sanitizeMcpErrorTextInPlace(err, ctx.declared);
|
|
198
202
|
if (ctx.idle?.signal.reason === IDLE_WATCHDOG_ABORT_REASON) {
|
|
199
203
|
ctx.liveness?.observe?.("timeout");
|
|
200
204
|
const serverLabel = inlineUntrusted(ctx.server);
|
|
@@ -225,7 +229,7 @@ function rethrowHonestMcpError(err, ctx) {
|
|
|
225
229
|
case "connect_refused":
|
|
226
230
|
case "connection_failed": {
|
|
227
231
|
const httpFailure = describeHttpTransportFailure(err, ctx.site);
|
|
228
|
-
const detail = remoteErrorText(err);
|
|
232
|
+
const detail = remoteErrorText(err, ctx.declared);
|
|
229
233
|
const fenced = `\nThe transport error follows as external/untrusted data:\n${fenceServerText(`${ctx.server} transport error`, detail)}`;
|
|
230
234
|
finish(markMcpFailure(new Error(sessionGone(err, ctx.site)
|
|
231
235
|
? `${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}`
|
|
@@ -240,7 +244,7 @@ function rethrowHonestMcpError(err, ctx) {
|
|
|
240
244
|
finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" was rejected with MCP protocol error ${code} — ${condition}. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, err.message)}`, { cause: err }), details({ specErrorCode: code })));
|
|
241
245
|
}
|
|
242
246
|
if (ctx.attributeServer) {
|
|
243
|
-
finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" failed. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, remoteErrorText(err))}`, { cause: err }), details()));
|
|
247
|
+
finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" failed. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, remoteErrorText(err, ctx.declared))}`, { cause: err }), details()));
|
|
244
248
|
}
|
|
245
249
|
finish(markMcpFailure(err, details()));
|
|
246
250
|
}
|
|
@@ -248,7 +252,7 @@ function rethrowHonestMcpError(err, ctx) {
|
|
|
248
252
|
case "invalid_config":
|
|
249
253
|
case "unknown": {
|
|
250
254
|
if (ctx.attributeServer) {
|
|
251
|
-
finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" failed. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, remoteErrorText(err))}`, { cause: err }), details()));
|
|
255
|
+
finish(markMcpFailure(new Error(`${ctx.what} on MCP server "${serverLabel}" failed. The server's error text follows as external/untrusted data:\n${fenceServerText(`${ctx.server} error`, remoteErrorText(err, ctx.declared))}`, { cause: err }), details()));
|
|
252
256
|
}
|
|
253
257
|
if (err instanceof Error)
|
|
254
258
|
finish(markMcpFailure(err, details()));
|
|
@@ -641,7 +645,7 @@ export function mcpToolSchemaProblem(schema) {
|
|
|
641
645
|
}
|
|
642
646
|
return undefined;
|
|
643
647
|
}
|
|
644
|
-
export async function materializeMcpTools(specs, principal, onElicit, imageResizer, reminderDisclosure, mcpRevocations, poolOpts, promptSections, dialable, signal) {
|
|
648
|
+
export async function materializeMcpTools(specs, principal, onElicit, imageResizer, reminderDisclosure, mcpRevocations, poolOpts, promptSections, dialable, signal, hostFloor) {
|
|
645
649
|
const snapshot = snapshotMcpEntries(specs);
|
|
646
650
|
const axesRefused = new WeakMap();
|
|
647
651
|
const entries = snapshot.map((spec) => {
|
|
@@ -767,18 +771,33 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
767
771
|
const gatesNow = (h) => {
|
|
768
772
|
const latest = h.listing.latest();
|
|
769
773
|
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 };
|
|
774
|
+
h.gatesAt = { at: latest.at, gates: intakeListedTools({ tools: [...latest.entries], unproven: latest.unproven }, h.spec, linkOf(h.name), echoOf(h.spec), imageResizer, mcpDisclosure, isServerRevoked, h.transportKind).gates };
|
|
771
775
|
return h.gatesAt.gates;
|
|
772
776
|
};
|
|
773
777
|
const linkOf = (server) => ({
|
|
774
778
|
live: () => liveOf(server),
|
|
775
779
|
recover: (lost) => redialFlights.running(server) ?? (liveOf(server) === lost ? redialFlights.start(server, () => redialDial(server)) : Promise.resolve()),
|
|
776
780
|
});
|
|
781
|
+
const endpointRefusal = (spec, dialKind) => {
|
|
782
|
+
const transport = spec.transport;
|
|
783
|
+
const raw = dialKind !== "stdio" && typeof transport === "object" && transport !== null && "url" in transport ? transport.url : undefined;
|
|
784
|
+
let url;
|
|
785
|
+
try {
|
|
786
|
+
if (typeof raw !== "string")
|
|
787
|
+
return undefined;
|
|
788
|
+
url = new URL(raw);
|
|
789
|
+
}
|
|
790
|
+
catch {
|
|
791
|
+
return undefined;
|
|
792
|
+
}
|
|
793
|
+
return peerRequestRefusal(`mcp: server "${inlineUntrusted(spec.name, 120)}"`, url, hostFloor);
|
|
794
|
+
};
|
|
777
795
|
const dialServer = (spec, dialKind, dialOpts) => {
|
|
778
|
-
const refusal = axesRefused.get(spec);
|
|
796
|
+
const refusal = axesRefused.get(spec) ?? endpointRefusal(spec, dialKind);
|
|
779
797
|
return refusal !== undefined ? Promise.reject(refusal) : connectServer(spec, principal, onElicit, imageResizer, mcpDisclosure, isServerRevoked, dialKind, poolOpts?.pool, { ...dialOpts, link: linkOf(spec.name), ...(signal !== undefined ? { signal } : {}) });
|
|
780
798
|
};
|
|
781
799
|
const prefixOf = (name) => mintNamespacePrefix(MCP_NAMESPACE, name);
|
|
800
|
+
const echoOf = (spec) => declaredHeaderValues(spec.transport, principal);
|
|
782
801
|
const heldCount = (name) => serverHandles.find((h) => h.name === name)?.tools.length ?? 0;
|
|
783
802
|
const reconcileInstructions = (name, after, connected) => {
|
|
784
803
|
if (!connected)
|
|
@@ -808,10 +827,11 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
808
827
|
commitConnectedServer(spec, s, dialKinds[i]);
|
|
809
828
|
}
|
|
810
829
|
else {
|
|
811
|
-
|
|
830
|
+
const declared = echoOf(spec);
|
|
831
|
+
warnings.push(asServerWarning(spec, r.reason, declared));
|
|
812
832
|
const { kind, delivered, httpStatus } = classifyMcpFailure(r.reason, { phase: "connect", transport: dialKinds[i] });
|
|
813
833
|
const liveness = livenessOf(kind, Date.now());
|
|
814
|
-
statuses.push({ name: spec.name, status: "failed", errorCode: kind, delivered, ...(httpStatus !== undefined ? { httpStatus } : {}), error: namedMcpFailureText(r.reason), ...(liveness !== undefined ? { liveness } : {}) });
|
|
834
|
+
statuses.push({ name: spec.name, status: "failed", errorCode: kind, delivered, ...(httpStatus !== undefined ? { httpStatus } : {}), error: namedMcpFailureText(r.reason, declared), ...(liveness !== undefined ? { liveness } : {}) });
|
|
815
835
|
}
|
|
816
836
|
}
|
|
817
837
|
const resourceTools = buildResourceTools(resourceServers, isServerRevoked);
|
|
@@ -859,20 +879,22 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
859
879
|
const err = dialed.err;
|
|
860
880
|
const { kind, delivered, httpStatus } = classifyMcpFailure(err, { phase: "connect", transport: dialKind });
|
|
861
881
|
const redialLiveness = livenessOf(kind, Date.now());
|
|
862
|
-
const
|
|
882
|
+
const declared = echoOf(spec);
|
|
883
|
+
const failure = namedMcpFailureText(err, declared);
|
|
884
|
+
const status = { name: server, status: "failed", errorCode: kind, delivered, ...(httpStatus !== undefined ? { httpStatus } : {}), error: failure, ...(redialLiveness !== undefined ? { liveness: redialLiveness } : {}) };
|
|
863
885
|
const sIdx = statuses.findIndex((st) => st.name === server);
|
|
864
886
|
if (sIdx === -1)
|
|
865
887
|
statuses.push(status);
|
|
866
888
|
else
|
|
867
889
|
statuses[sIdx] = status;
|
|
868
|
-
const raised = asServerWarning(spec, err);
|
|
890
|
+
const raised = asServerWarning(spec, err, declared);
|
|
869
891
|
warnings.push(raised);
|
|
870
892
|
reconcileInstructions(server, undefined, false);
|
|
871
893
|
return {
|
|
872
894
|
server,
|
|
873
895
|
prefix,
|
|
874
896
|
outcome: "refused",
|
|
875
|
-
reason: inlineUntrusted(
|
|
897
|
+
reason: inlineUntrusted(failure, 240),
|
|
876
898
|
toolCount: 0,
|
|
877
899
|
added: [],
|
|
878
900
|
removed: priorNames,
|
|
@@ -930,14 +952,14 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
930
952
|
try {
|
|
931
953
|
const at = h.listing.open();
|
|
932
954
|
const cacheTools = h.openListing();
|
|
933
|
-
const listed = await listToolsLenient(h.client);
|
|
955
|
+
const listed = await listToolsLenient(h.client, undefined, echoOf(h.spec));
|
|
934
956
|
const answered = h.listing.answer(at, listed.tools, listed.incomplete !== undefined);
|
|
935
957
|
const mergedRaw = answered.view;
|
|
936
958
|
if (!answered.recorded) {
|
|
937
959
|
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
960
|
continue;
|
|
939
961
|
}
|
|
940
|
-
const { serverTools, serverAxes, gates, dropped, accepted } = intakeListedTools({ tools: [...mergedRaw], unproven: answered.unproven }, h.spec, linkOf(h.name), imageResizer, mcpDisclosure, isServerRevoked, h.transportKind);
|
|
962
|
+
const { serverTools, serverAxes, gates, dropped, accepted } = intakeListedTools({ tools: [...mergedRaw], unproven: answered.unproven }, h.spec, linkOf(h.name), echoOf(h.spec), imageResizer, mcpDisclosure, isServerRevoked, h.transportKind);
|
|
941
963
|
cacheTools(accepted, answered.kept);
|
|
942
964
|
const priorNames = h.tools.map((t) => t.name);
|
|
943
965
|
const newNames = serverTools.map((t) => t.name);
|
|
@@ -970,7 +992,7 @@ export async function materializeMcpTools(specs, principal, onElicit, imageResiz
|
|
|
970
992
|
toolCount: h.tools.length,
|
|
971
993
|
added: [],
|
|
972
994
|
removed: [],
|
|
973
|
-
error: inlineUntrusted(namingLostSession(err, site, namedMcpFailureText(err)), 240),
|
|
995
|
+
error: inlineUntrusted(namingLostSession(err, site, namedMcpFailureText(err, echoOf(h.spec))), 240),
|
|
974
996
|
});
|
|
975
997
|
}
|
|
976
998
|
}
|
|
@@ -1085,7 +1107,7 @@ export async function walkMcpListPages(fetchPage, opts) {
|
|
|
1085
1107
|
catch (err) {
|
|
1086
1108
|
if (pages === 0 || opts.signal?.aborted)
|
|
1087
1109
|
throw err;
|
|
1088
|
-
return { items, incomplete: { reason: "page_error", pages, error: remoteErrorText(err) } };
|
|
1110
|
+
return { items, incomplete: { reason: "page_error", pages, error: remoteErrorText(err, opts.declared ?? []) } };
|
|
1089
1111
|
}
|
|
1090
1112
|
opts.onPage?.();
|
|
1091
1113
|
const pageStart = items.length;
|
|
@@ -1168,13 +1190,13 @@ async function readDirViaExtension(rs, uri, signal, timeoutMs, watchdog) {
|
|
|
1168
1190
|
if (err instanceof McpError && err.code === ErrorCode.InvalidParams) {
|
|
1169
1191
|
if (pages > 0)
|
|
1170
1192
|
return { kind: "ok", resources, cursorInvalid: true };
|
|
1171
|
-
const detail = remoteErrorText(err, { collapse: true });
|
|
1193
|
+
const detail = remoteErrorText(err, rs.declared, { collapse: true });
|
|
1172
1194
|
return { kind: classifyDirReadInvalidParams(detail), detail };
|
|
1173
1195
|
}
|
|
1174
1196
|
if (err instanceof McpError && err.code === ErrorCode.MethodNotFound)
|
|
1175
1197
|
return { kind: "unsupported" };
|
|
1176
1198
|
if (pages > 0 && !signal?.aborted) {
|
|
1177
|
-
return { kind: "ok", resources, incomplete: remoteErrorText(err) };
|
|
1199
|
+
return { kind: "ok", resources, incomplete: remoteErrorText(err, rs.declared) };
|
|
1178
1200
|
}
|
|
1179
1201
|
throw err;
|
|
1180
1202
|
}
|
|
@@ -1266,7 +1288,7 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1266
1288
|
throw watchdog.idleSignal.reason === IDLE_WATCHDOG_ABORT_REASON ? new Error(idleWatchdogTripText(idleMs)) : err;
|
|
1267
1289
|
});
|
|
1268
1290
|
return { items: page.resources, ...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}) };
|
|
1269
|
-
}, { budgetMs: mcpToolTimeoutMs(), onPage: () => watchdog.rearm(), fingerprintOf: listEntryFingerprint, ...(signal !== undefined ? { signal } : {}) });
|
|
1291
|
+
}, { budgetMs: mcpToolTimeoutMs(), onPage: () => watchdog.rearm(), fingerprintOf: listEntryFingerprint, declared: rs.declared, ...(signal !== undefined ? { signal } : {}) });
|
|
1270
1292
|
all.push(...walk.items.map((r) => ({ server: rs.server, ...r })));
|
|
1271
1293
|
const lines = walk.items.map((r) => resourceLine(r));
|
|
1272
1294
|
const body = lines.length ? lines.join("\n") : "(no resources)";
|
|
@@ -1279,11 +1301,12 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1279
1301
|
}
|
|
1280
1302
|
}
|
|
1281
1303
|
catch (err) {
|
|
1304
|
+
sanitizeMcpErrorTextInPlace(err, rs.declared);
|
|
1282
1305
|
if (signal?.aborted)
|
|
1283
1306
|
throw err;
|
|
1284
1307
|
const msg = watchdog.idleSignal.reason === IDLE_WATCHDOG_ABORT_REASON
|
|
1285
1308
|
? idleWatchdogTripText(idleMs)
|
|
1286
|
-
: namingLostSession(err, site, remoteErrorText(err));
|
|
1309
|
+
: namingLostSession(err, site, remoteErrorText(err, rs.declared));
|
|
1287
1310
|
errors.push({ server: rs.server, error: msg });
|
|
1288
1311
|
sections.push(`[${rs.server}] Error: could not list resources: ${inlineUntrusted(msg)}`);
|
|
1289
1312
|
}
|
|
@@ -1342,7 +1365,7 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1342
1365
|
try {
|
|
1343
1366
|
res = await rs.client
|
|
1344
1367
|
.readResource({ uri }, { signal: watchdog.combinedSignal, timeout: timeoutMs })
|
|
1345
|
-
.catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1368
|
+
.catch((err) => rethrowHonestMcpError(err, { server, declared: rs.declared, what, timeoutMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1346
1369
|
rs.health.observe?.("completed");
|
|
1347
1370
|
}
|
|
1348
1371
|
finally {
|
|
@@ -1403,7 +1426,7 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1403
1426
|
try {
|
|
1404
1427
|
const ext = rs.client.getServerCapabilities()?.extensions?.[MCP_SKILLS_EXTENSION];
|
|
1405
1428
|
if (ext?.directoryRead === true) {
|
|
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 }));
|
|
1429
|
+
const r = await readDirViaExtension(rs, uri, signal, timeoutMs, watchdog).catch((err) => rethrowHonestMcpError(err, { server, declared: rs.declared, what, timeoutMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1407
1430
|
const serverSaid = (detail) => `\nThe server's error text follows as external/untrusted data:\n${delimitUntrusted(`${server} error`, truncateMcpErrorText(detail))}`;
|
|
1408
1431
|
if (r.kind === "not_found") {
|
|
1409
1432
|
return {
|
|
@@ -1431,10 +1454,10 @@ function buildResourceTools(resourceServers, isServerRevoked = () => false) {
|
|
|
1431
1454
|
const walk = await walkMcpListPages(async (cursor, remainingMs) => {
|
|
1432
1455
|
const page = await rs.client
|
|
1433
1456
|
.listResources(cursor === undefined ? undefined : { cursor }, { signal: watchdog.combinedSignal, timeout: remainingMs })
|
|
1434
|
-
.catch((err) => rethrowHonestMcpError(err, { server, what, timeoutMs: remainingMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1457
|
+
.catch((err) => rethrowHonestMcpError(err, { server, declared: rs.declared, what, timeoutMs: remainingMs, writeEffect: false, signal, attributeServer: true, site, idle: { signal: watchdog.idleSignal, idleMs }, liveness: rs.health }));
|
|
1435
1458
|
rs.health.observe?.("completed");
|
|
1436
1459
|
return { items: page.resources, ...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {}) };
|
|
1437
|
-
}, { budgetMs: timeoutMs, onPage: () => watchdog.rearm(), fingerprintOf: listEntryFingerprint, ...(signal !== undefined ? { signal } : {}) });
|
|
1460
|
+
}, { budgetMs: timeoutMs, onPage: () => watchdog.rearm(), fingerprintOf: listEntryFingerprint, declared: rs.declared, ...(signal !== undefined ? { signal } : {}) });
|
|
1438
1461
|
const dirPrefix = uri.endsWith("/") ? uri : `${uri}/`;
|
|
1439
1462
|
const children = walk.items.filter((r) => typeof r.uri === "string" && r.uri !== uri && r.uri.startsWith(dirPrefix));
|
|
1440
1463
|
return renderDirChildren(server, uri, children, walk.incomplete ? { listing: walk.incomplete } : undefined);
|
|
@@ -1499,7 +1522,7 @@ export function parseCallToolResultLenient(data) {
|
|
|
1499
1522
|
return { success: true, data: { ...parsed.data, structuredContent } };
|
|
1500
1523
|
}
|
|
1501
1524
|
const LENIENT_CALL_TOOL_RESULT_SCHEMA = { safeParse: parseCallToolResultLenient };
|
|
1502
|
-
async function listToolsLenient(client, options) {
|
|
1525
|
+
async function listToolsLenient(client, options, declared) {
|
|
1503
1526
|
if (!client.getServerCapabilities()?.tools)
|
|
1504
1527
|
return { tools: [], toolsCapabilityAbsent: true };
|
|
1505
1528
|
const walk = await walkMcpListPages(async (cursor, remainingMs) => {
|
|
@@ -1512,6 +1535,7 @@ async function listToolsLenient(client, options) {
|
|
|
1512
1535
|
}, {
|
|
1513
1536
|
budgetMs: options?.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC,
|
|
1514
1537
|
fingerprintOf: listEntryFingerprint,
|
|
1538
|
+
declared,
|
|
1515
1539
|
...(options?.signal !== undefined ? { signal: options.signal } : {}),
|
|
1516
1540
|
});
|
|
1517
1541
|
return { tools: walk.items, ...(walk.incomplete !== undefined ? { incomplete: walk.incomplete } : {}) };
|
|
@@ -1583,9 +1607,10 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
|
|
|
1583
1607
|
const listing = lease?.listing ?? new ConnectionListing();
|
|
1584
1608
|
const at = listing.open();
|
|
1585
1609
|
const cacheTools = openListing();
|
|
1586
|
-
const
|
|
1610
|
+
const declared = declaredHeaderValues(spec.transport, principal);
|
|
1611
|
+
const listed = await underStartupBound(startupMs, dialOpts?.signal, (options) => listToolsLenient(client, options, declared));
|
|
1587
1612
|
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);
|
|
1613
|
+
const { serverTools, serverAxes, gates, dropped, advisories, accepted } = intakeListedTools({ tools: [...answered.view], unproven: answered.unproven }, spec, dialOpts.link, declared, imageResizer, reminderDisclosure, isServerRevoked, transportKind);
|
|
1589
1614
|
cacheTools(accepted, answered.kept);
|
|
1590
1615
|
const caps = client.getServerCapabilities();
|
|
1591
1616
|
const resourceInfo = caps?.resources
|
|
@@ -1623,7 +1648,7 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
|
|
|
1623
1648
|
...(instructions ? { instructions } : {}),
|
|
1624
1649
|
...(disposed?.defect !== undefined ? { instructionsDefect: disposed.defect } : {}),
|
|
1625
1650
|
...(listed.incomplete !== undefined ? { listingIncomplete: listed.incomplete } : {}),
|
|
1626
|
-
...(resourceInfo && (resourceInfo.listAllowed || resourceInfo.readAllowed) ? { resourceServer: { server: spec.name, client, health, transportKind: idleKindOf(transportKind), ...resourceInfo } } : {}),
|
|
1651
|
+
...(resourceInfo && (resourceInfo.listAllowed || resourceInfo.readAllowed) ? { resourceServer: { server: spec.name, client, health, transportKind: idleKindOf(transportKind), declared, ...resourceInfo } } : {}),
|
|
1627
1652
|
};
|
|
1628
1653
|
}
|
|
1629
1654
|
catch (err) {
|
|
@@ -1631,7 +1656,7 @@ async function connectServer(spec, principal, onElicit, imageResizer, reminderDi
|
|
|
1631
1656
|
throw err;
|
|
1632
1657
|
}
|
|
1633
1658
|
}
|
|
1634
|
-
function intakeListedTools(listed, spec, link, imageResizer, reminderDisclosure, isServerRevoked, transportKind) {
|
|
1659
|
+
function intakeListedTools(listed, spec, link, declared, imageResizer, reminderDisclosure, isServerRevoked, transportKind) {
|
|
1635
1660
|
const declaredContentOrigin = spec.contentOrigin;
|
|
1636
1661
|
const serverTools = [];
|
|
1637
1662
|
const serverAxes = [];
|
|
@@ -1750,6 +1775,7 @@ function intakeListedTools(listed, spec, link, imageResizer, reminderDisclosure,
|
|
|
1750
1775
|
try {
|
|
1751
1776
|
return rethrowHonestMcpError(err, {
|
|
1752
1777
|
server: spec.name,
|
|
1778
|
+
declared,
|
|
1753
1779
|
what,
|
|
1754
1780
|
timeoutMs,
|
|
1755
1781
|
writeEffect,
|
|
@@ -1793,7 +1819,7 @@ function intakeListedTools(listed, spec, link, imageResizer, reminderDisclosure,
|
|
|
1793
1819
|
const errScLine = structuredContentErrorLine(res.structuredContent, parts.join("\n"));
|
|
1794
1820
|
if (errScLine !== undefined)
|
|
1795
1821
|
parts.push(errScLine);
|
|
1796
|
-
const body = truncateMcpErrorText(
|
|
1822
|
+
const body = truncateMcpErrorText(mcpRemoteText(parts.join("\n").trim(), declared));
|
|
1797
1823
|
const msg = body
|
|
1798
1824
|
? `MCP tool ${inlineUntrusted(remoteName)} reported an error. The server's error content follows as external/untrusted data:\n${delimitUntrusted(`${spec.name} tool error`, body)}`
|
|
1799
1825
|
: `MCP tool ${inlineUntrusted(remoteName)} reported an error`;
|
|
@@ -1842,8 +1868,8 @@ function intakeListedTools(listed, spec, link, imageResizer, reminderDisclosure,
|
|
|
1842
1868
|
}
|
|
1843
1869
|
return { serverTools, serverAxes, gates, dropped, advisories, accepted };
|
|
1844
1870
|
}
|
|
1845
|
-
function asServerWarning(spec, err) {
|
|
1846
|
-
const warning = new Error(`mcp: server "${spec.name}" failed to connect — skipped (${namedMcpFailureText(err)})`, { cause: sanitizedCause(err) });
|
|
1871
|
+
function asServerWarning(spec, err, declared) {
|
|
1872
|
+
const warning = new Error(`mcp: server "${spec.name}" failed to connect — skipped (${namedMcpFailureText(err, declared)})`, { cause: sanitizedCause(err, declared) });
|
|
1847
1873
|
warning.code = "mcp.server_unavailable";
|
|
1848
1874
|
return warning;
|
|
1849
1875
|
}
|
|
@@ -1868,8 +1894,8 @@ function dialDecision(dialable, spec) {
|
|
|
1868
1894
|
}
|
|
1869
1895
|
throw Object.assign(new Error(`MCP materialization refused: the dialable seat could not decide whether to dial server "${inlineUntrusted(spec.name, 120)}" — ${inlineUntrusted(why, 240)}. No server was dialed.`, cause), { code: "config.mcp_dialable_failed" });
|
|
1870
1896
|
}
|
|
1871
|
-
function sanitizedCause(err) {
|
|
1872
|
-
const copy = new Error(namedMcpFailureText(err));
|
|
1897
|
+
function sanitizedCause(err, declared) {
|
|
1898
|
+
const copy = new Error(namedMcpFailureText(err, declared));
|
|
1873
1899
|
const name = thrownName(err);
|
|
1874
1900
|
if (name !== undefined) {
|
|
1875
1901
|
if (name !== "")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { closeSync, existsSync, fsyncSync, linkSync, lstatSync, openSync, readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { basename, dirname, join } from "node:path";
|
|
4
|
-
import { QUARANTINE_DIR, appendChallengeEvents, enqueueMemoryAnnouncement, ensureDirExists, v1MemoryPathKeyResolver, lineageContributionsOfSession, lockedStrictUpdate, markSessionPolluted, readProjectionDebts, readSessionPollution, readStrictSidecar, ControlPlaneCorruptError } from "./layout.js";
|
|
4
|
+
import { QUARANTINE_DIR, appendChallengeEvents, claimStaging, enqueueMemoryAnnouncement, ensureDirExists, isSameFile, mintStagingName, stagingNamePattern, v1MemoryPathKeyResolver, lineageContributionsOfSession, lockedStrictUpdate, markSessionPolluted, readProjectionDebts, readSessionPollution, readStrictSidecar, ControlPlaneCorruptError } from "./layout.js";
|
|
5
5
|
import { thrownText } from "../thrown-value.js";
|
|
6
6
|
export const DELEGATION_SETTLEMENT_FILE = "delegation-settlement.json";
|
|
7
7
|
function reqStr(v) {
|
|
@@ -495,25 +495,6 @@ export function readHolds(controlDir) {
|
|
|
495
495
|
function sha256(buf) {
|
|
496
496
|
return createHash("sha256").update(buf).digest("hex");
|
|
497
497
|
}
|
|
498
|
-
let stagingSeq = 0;
|
|
499
|
-
function uniqueStagingName(holdId, now) {
|
|
500
|
-
stagingSeq += 1;
|
|
501
|
-
return `${holdId}.staging-${now()}-${process.pid}-${stagingSeq}`;
|
|
502
|
-
}
|
|
503
|
-
function stagingGenerationPattern(holdId) {
|
|
504
|
-
return new RegExp(`^${holdId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.staging-\\d+-\\d+-\\d+(?:\\.claim-\\d+-\\d+)*$`);
|
|
505
|
-
}
|
|
506
|
-
function claimStaging(stagingPath) {
|
|
507
|
-
stagingSeq += 1;
|
|
508
|
-
const claimed = `${stagingPath}.claim-${process.pid}-${stagingSeq}`;
|
|
509
|
-
try {
|
|
510
|
-
renameSync(stagingPath, claimed);
|
|
511
|
-
return claimed;
|
|
512
|
-
}
|
|
513
|
-
catch {
|
|
514
|
-
return stagingPath;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
498
|
function dropStaging(claimedPath) {
|
|
518
499
|
try {
|
|
519
500
|
unlinkSync(claimedPath);
|
|
@@ -638,7 +619,7 @@ export function openInstructionHold(controlDir, input) {
|
|
|
638
619
|
if (!writeCustodyVerified(join(holdDir, captureName), buf)) {
|
|
639
620
|
return refuse("hold capture verification failed (the custody copy could not be written, made durable, or hashed back to the captured digest)", "capture_lost");
|
|
640
621
|
}
|
|
641
|
-
const stagingName =
|
|
622
|
+
const stagingName = mintStagingName(holdId, input.now);
|
|
642
623
|
const stagingPath = stagingPathBeside(input.absPath, stagingName);
|
|
643
624
|
try {
|
|
644
625
|
renameSync(input.absPath, stagingPath);
|
|
@@ -695,7 +676,7 @@ export function reconcileHolds(controlDir, input) {
|
|
|
695
676
|
}
|
|
696
677
|
};
|
|
697
678
|
const finishRemoval = (row, plane) => {
|
|
698
|
-
const stagingName =
|
|
679
|
+
const stagingName = mintStagingName(row.holdId, input.now);
|
|
699
680
|
renameSync(plane, stagingPathBeside(plane, stagingName));
|
|
700
681
|
const staging = claimStaging(stagingPathBeside(plane, stagingName));
|
|
701
682
|
if (sha256(readFileSync(staging)) === row.contentDigest) {
|
|
@@ -726,7 +707,14 @@ export function reconcileHolds(controlDir, input) {
|
|
|
726
707
|
};
|
|
727
708
|
const sweepStagingGenerations = (row, plane, custody) => {
|
|
728
709
|
const seatDir = dirname(plane);
|
|
729
|
-
const pattern =
|
|
710
|
+
const pattern = stagingNamePattern(row.holdId);
|
|
711
|
+
let seat;
|
|
712
|
+
try {
|
|
713
|
+
seat = lstatSync(plane);
|
|
714
|
+
}
|
|
715
|
+
catch {
|
|
716
|
+
seat = undefined;
|
|
717
|
+
}
|
|
730
718
|
for (const name of listSeat(seatDir)) {
|
|
731
719
|
if (!pattern.test(name))
|
|
732
720
|
continue;
|
|
@@ -746,7 +734,10 @@ export function reconcileHolds(controlDir, input) {
|
|
|
746
734
|
continue;
|
|
747
735
|
}
|
|
748
736
|
}
|
|
749
|
-
|
|
737
|
+
const onSeat = seat !== undefined && isSameFile(staged, seat);
|
|
738
|
+
const retired = retireStagingToCustody(staged, holdDir, name);
|
|
739
|
+
if (!(onSeat && retired.settled && isSameFile(plane, seat)))
|
|
740
|
+
discloseStranded(row.holdId, row.rel, retired.at);
|
|
750
741
|
}
|
|
751
742
|
};
|
|
752
743
|
const rows = readHolds(controlDir).filter((r) => r.status === "capturing");
|
|
@@ -19,7 +19,7 @@ import { landedUndecided, layerDigest, layerObservationLookup, readOnlyLayerCand
|
|
|
19
19
|
import { markOriginClearanceTombstoned, openOriginClearance, readOriginClearances, settleOriginClearance } from "./origin-clearance.js";
|
|
20
20
|
import { DEFAULT_MAX_ENTRY_DEPTH, MEMORY_INDEX_FILENAME, captureErasureInput, erasureRequestInvalid, erasureSelectHash, scanEntryFiles, } from "./file-backend.js";
|
|
21
21
|
import { assembleMemoryExportBundle, computeMemoryBundleHash, memoryBundleInvalid, } from "./export-bundle.js";
|
|
22
|
-
import { QUARANTINE_DIR, SCAN_FUSE_THRESHOLD, quarantineAndTombstone, restoreContainedBaseline, indexLineIsStale, readIndexRevs, writeIndexRevs, bumpScanFuse, scanFuseKey, canonicalize, anchorStoreRoot, landingPathOf, landsOutsideStore, storeActRefusal, storeRootMovedRefusal, adoptRootScopeLayout, clearScanFuse, effectiveControlRootOf, drainMemoryAnnouncements, enqueueMemoryAnnouncement, ensureDirExists, markSessionPolluted, readSessionPollution, fileSessionCaptureRecordStore, recordRetrievedAccount, writeFileNoFollow, withPermissionRemedy, permissionRemedyOf, readRetrievedAccount, registerScope, registeredScopes, scopeDirFor, appendChallengeEvents, appendLineageAudit, rebuildStrictControlPlaneLedger, isStrictControlPlaneLedgerCorrupt, CHALLENGE_LEDGER_MAX_EVENTS, adjudicateLineagePending, challengedEntryIds, clearLineageForEntries, discardLineagePending, lineageAccountOfEntry, lineageContributionsOfSession, lineageLatchedIds, promoteLineagePending, readChallengeEvents, readChallengedHistory, readLineageRecord, recordChallengedHistory, recordLineageCredential, reconcileLineage, readProjectionDebts, resolveChallengeEvent, settleProjectionDebts, stageLineagePending, stageProjectionDebts, } from "./layout.js";
|
|
22
|
+
import { QUARANTINE_DIR, SCAN_FUSE_THRESHOLD, quarantineAndTombstone, restoreContainedBaseline, mintStagingName, indexLineIsStale, readIndexRevs, writeIndexRevs, bumpScanFuse, scanFuseKey, canonicalize, anchorStoreRoot, landingPathOf, landsOutsideStore, storeActRefusal, storeRootMovedRefusal, adoptRootScopeLayout, clearScanFuse, effectiveControlRootOf, drainMemoryAnnouncements, enqueueMemoryAnnouncement, ensureDirExists, markSessionPolluted, readSessionPollution, fileSessionCaptureRecordStore, recordRetrievedAccount, writeFileNoFollow, writeFileNoReplace, withPermissionRemedy, permissionRemedyOf, readRetrievedAccount, registerScope, registeredScopes, scopeDirFor, appendChallengeEvents, appendLineageAudit, rebuildStrictControlPlaneLedger, isStrictControlPlaneLedgerCorrupt, CHALLENGE_LEDGER_MAX_EVENTS, adjudicateLineagePending, challengedEntryIds, clearLineageForEntries, discardLineagePending, lineageAccountOfEntry, lineageContributionsOfSession, lineageLatchedIds, promoteLineagePending, readChallengeEvents, readChallengedHistory, readLineageRecord, recordChallengedHistory, recordLineageCredential, reconcileLineage, readProjectionDebts, resolveChallengeEvent, settleProjectionDebts, stageLineagePending, stageProjectionDebts, } from "./layout.js";
|
|
23
23
|
import { createSessionIncarnationSeat, recalledForAnyIdentity, recalledForIdentity, rememberForIdentity } from "./session-incarnation.js";
|
|
24
24
|
import { scanMemoryFileName, scanMemoryWrite, scanRemediation } from "./scan.js";
|
|
25
25
|
import { writableRootOf } from "./types.js";
|
|
@@ -1516,7 +1516,7 @@ export class MemoryEngine {
|
|
|
1516
1516
|
}
|
|
1517
1517
|
let restoredCommitted = false;
|
|
1518
1518
|
if (captured) {
|
|
1519
|
-
const stagingName =
|
|
1519
|
+
const stagingName = mintStagingName(captureName, this.now);
|
|
1520
1520
|
const stagingPath = stagingPathBeside(canonical, stagingName);
|
|
1521
1521
|
try {
|
|
1522
1522
|
this.refuseOutsideStore(canonical, "containing session residue");
|
|
@@ -2475,8 +2475,8 @@ export class MemoryEngine {
|
|
|
2475
2475
|
if (committed !== undefined) {
|
|
2476
2476
|
try {
|
|
2477
2477
|
this.refuseOutsideStore(f.canonical, "restoring a held entry's committed content", handle);
|
|
2478
|
-
|
|
2479
|
-
|
|
2478
|
+
if (writeFileNoReplace(f.canonical, committed) === "written")
|
|
2479
|
+
report.restored.push(rel);
|
|
2480
2480
|
}
|
|
2481
2481
|
catch (err) {
|
|
2482
2482
|
report.warnings.push(`${rel}: the committed content could not be restored after the hold captured this session's edit — the entry is unavailable on the plane until release or the next restore: ${this.writeFailureText(err)}`);
|
|
@@ -513,13 +513,21 @@ export interface QuarantineOutcome {
|
|
|
513
513
|
* without native bindings. What this buys is the leaf variant, which is the cheap one; the ancestor
|
|
514
514
|
* variant stays open and is recorded with the rest of the family rather than papered over.
|
|
515
515
|
*
|
|
516
|
-
* Throws like `writeFileSync`, including ELOOP when the final component IS a symlink
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
* the
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
*
|
|
516
|
+
* Throws like `writeFileSync`, including ELOOP when the final component IS a symlink, and EACCES for a
|
|
517
|
+
* file whose own bits refuse the write. A write changes only the NAME it writes. A file with one name is
|
|
518
|
+
* rewritten in place (its inode and mode stay). A HARD link is the same tamper as a symlink by other
|
|
519
|
+
* means — the file's bytes live under a second name, possibly outside the store, and an in-place write
|
|
520
|
+
* would change them there too — so a file the open finds with more names is never written in place.
|
|
521
|
+
* One such name is the engine's own: a staging name a no-replace restore stopped between its `link` and
|
|
522
|
+
* its `unlink` left beside the file; it is removed first ({@link dropStagingSecondNames}), the interrupted
|
|
523
|
+
* restore's last step. A file that still has another name gets a new file under THIS name, written the
|
|
524
|
+
* way the store commits a file ({@link atomicWriteFileSync}: an exclusive no-follow sibling, 0o600,
|
|
525
|
+
* renamed over this name); the other names keep their file, its bytes and its mode. Residual: a path
|
|
526
|
+
* replaced by another file between the open and that rename is replaced again (the window every
|
|
527
|
+
* rename-based store write has). The in-place write goes through `writeFileSync` on the open descriptor,
|
|
528
|
+
* which writes every byte or throws — a bare `writeSync` may short-write, and reporting a truncated
|
|
529
|
+
* restore as contained (after the truncation already destroyed the destination) is the failure this
|
|
530
|
+
* guard exists to prevent.
|
|
523
531
|
*/
|
|
524
532
|
export declare function writeFileNoFollow(path: string, content: string): void;
|
|
525
533
|
/** {@link writeFileNoFollow}'s NO-REPLACE twin: write `content` only if nothing is at `path`. `"written"`
|
|
@@ -529,6 +537,48 @@ export declare function writeFileNoFollow(path: string, content: string): void;
|
|
|
529
537
|
* it refuses a symlink at the final component on its own (POSIX `EEXIST` on a link, dangling or not),
|
|
530
538
|
* so the twin's no-follow property is kept without a second check. */
|
|
531
539
|
export declare function writeFileNoReplace(path: string, content: string): "written" | "kept";
|
|
540
|
+
/** THE minter of every staging name the engine puts beside a plane file while it is displaced:
|
|
541
|
+
* `<owner>.staging-<ms>-<pid>-<seq>`. One grammar for every site, so one recognizer
|
|
542
|
+
* ({@link stagingNamePattern}) knows the names the engine can have left beside a seat. */
|
|
543
|
+
export declare function mintStagingName(owner: string, now: () => number): string;
|
|
544
|
+
/** The grammar {@link mintStagingName} and {@link claimStaging} write, as a recognizer — of ONE owner's
|
|
545
|
+
* generations when `owner` is given; otherwise of every staging name an engine has minted beside a seat,
|
|
546
|
+
* for the two owners it mints them for: an instruction hold (`hold-<ms>-<12 hex>`) and a crash-residue
|
|
547
|
+
* capture (`<ms>-residue-<entry id>.md`), whose `<ms>-residue-<id>.md.staging` of 7.55.0 and earlier is
|
|
548
|
+
* included (a name already on disk does not lose its owner with an upgrade). A prefix or a bare
|
|
549
|
+
* `.staging-` suffix would adopt any name a writer chose on the strength of its spelling. Minted and
|
|
550
|
+
* recognised side by side so the two cannot drift. */
|
|
551
|
+
export declare function stagingNamePattern(owner?: string): RegExp;
|
|
552
|
+
/** Take exclusive hold of a staged name by an atomic same-directory rename to a name minted HERE: the
|
|
553
|
+
* staged name lives in a WRITABLE directory, so a plain read-then-unlink could delete a replacement that
|
|
554
|
+
* landed between the two while reporting success over the earlier bytes. After the claim, what the rename
|
|
555
|
+
* moved is what every later read and unlink addresses. Returns the claim when it took, the original when
|
|
556
|
+
* the directory refused it (a hardening, not a precondition — a caller that removes on the strength of
|
|
557
|
+
* the claim checks which one it got). Residual: a writer enumerating the directory can still replace the
|
|
558
|
+
* CLAIM name before it is read — nothing Node's `fs` closes that, and the window is narrower than the one
|
|
559
|
+
* it replaces. */
|
|
560
|
+
export declare function claimStaging(stagingPath: string): string;
|
|
561
|
+
/** Whether `path` names the file `ref` describes: a regular file on the same device with the same inode,
|
|
562
|
+
* read without following a link at `path`. */
|
|
563
|
+
export declare function isSameFile(path: string, ref: {
|
|
564
|
+
readonly dev: number;
|
|
565
|
+
readonly ino: number;
|
|
566
|
+
}): boolean;
|
|
567
|
+
/**
|
|
568
|
+
* Remove every staging name an engine minted ({@link stagingNamePattern}) beside `seat` that is another
|
|
569
|
+
* name of the file `opened` describes — the un-dropped half of a no-replace restore stopped between its
|
|
570
|
+
* `link` and its `unlink`. Called by a write about to replace that file's bytes: removing the name loses
|
|
571
|
+
* nothing the write itself does not overwrite, and touches only names in the engine's staging grammar (a name
|
|
572
|
+
* is read as the engine's own by its spelling and by being the same file, so a hard link someone made and
|
|
573
|
+
* spelled that way goes too; every other hard-link copy, snapshot name and planted link stays, with its file).
|
|
574
|
+
* Not claimed first: a claim is a `rename`, which replaces whatever already stands at the claim name.
|
|
575
|
+
* Residual: a file put at that minted name between the check and the removal is removed — only a writer of
|
|
576
|
+
* this directory can put it there, and it can remove the name itself. Answers how many names went.
|
|
577
|
+
*/
|
|
578
|
+
export declare function dropStagingSecondNames(seat: string, opened: {
|
|
579
|
+
readonly dev: number;
|
|
580
|
+
readonly ino: number;
|
|
581
|
+
}): number;
|
|
532
582
|
/**
|
|
533
583
|
* The ONE way a committed baseline goes back after {@link quarantineAndTombstone} emptied its seat —
|
|
534
584
|
* the inverse half of that function, beside it so the removal word and its readers stay in one module.
|
|
@@ -1272,7 +1322,9 @@ export declare function writeAllSync(fd: number, data: string): void;
|
|
|
1272
1322
|
* is not fsync'd (stores/file/fs-atomic.ts has the dir-fsync variant for stores that need it), so
|
|
1273
1323
|
* a crash in that window can resurface the old content. Sidecars tolerate that (they are rebuilt
|
|
1274
1324
|
* or re-derived); do not route data that can't through here. Throws on failure (fail-closed: a
|
|
1275
|
-
* sidecar that cannot be written must not be silently skipped).
|
|
1325
|
+
* sidecar that cannot be written must not be silently skipped). The tmp file is created EXCLUSIVELY and
|
|
1326
|
+
* no-follow: a name already standing there (a link or a file somebody placed) is an `EEXIST` refusal,
|
|
1327
|
+
* never a file this write truncates or writes through. */
|
|
1276
1328
|
export declare function atomicWriteFileSync(path: string, data: string): void;
|
|
1277
1329
|
/** Content-gated {@link atomicWriteFileSync} for a DERIVED/control-plane file: a byte-identical
|
|
1278
1330
|
* rewrite (the common case on a repeat mount over an unchanged store) is skipped entirely, so the
|