@sema-agent/core 7.52.0 → 7.54.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 +470 -0
- package/LICENSE +3 -1
- package/README.md +3 -1
- package/dist/agents/cross-session-envelope.d.ts +8 -0
- package/dist/agents/cross-session-envelope.js +6 -0
- package/dist/agents/cross-session-judge.d.ts +21 -1
- package/dist/agents/cross-session-judge.js +8 -0
- package/dist/agents/cross-session-ref.d.ts +5 -0
- package/dist/agents/cross-session-ref.js +1 -0
- package/dist/agents/org-delivery-gate.d.ts +122 -0
- package/dist/agents/org-delivery-gate.js +69 -0
- package/dist/agents/peer-held-queue.d.ts +9 -4
- package/dist/agents/peer-held-queue.js +6 -5
- package/dist/agents/peer-session-drain.d.ts +35 -6
- package/dist/agents/peer-session-drain.js +271 -182
- package/dist/agents/read-inbox-tool.d.ts +7 -0
- package/dist/agents/read-inbox-tool.js +5 -1
- package/dist/agents/send-message-tool.js +3 -4
- package/dist/agents/subagent.d.ts +6 -5
- package/dist/agents/subagent.js +117 -83
- package/dist/agents/tool-filter.d.ts +25 -4
- package/dist/agents/tool-filter.js +13 -3
- package/dist/brain/anthropic.d.ts +6 -1
- package/dist/brain/anthropic.js +4 -4
- package/dist/brain/model-presets.js +2 -1
- package/dist/brain/route-adjudicator.d.ts +6 -0
- package/dist/brain/routing.d.ts +24 -1
- package/dist/brain/routing.js +54 -19
- package/dist/brain/timeout.js +5 -4
- package/dist/core/a2a.d.ts +5 -2
- package/dist/core/a2a.js +33 -14
- package/dist/core/allow-entry.d.ts +3 -1
- package/dist/core/allow-entry.js +3 -2
- package/dist/core/approval-object.d.ts +87 -0
- package/dist/core/approval-object.js +85 -0
- package/dist/core/arg-summary.d.ts +3 -2
- package/dist/core/arg-summary.js +17 -11
- package/dist/core/ask-origin.d.ts +43 -27
- package/dist/core/ask-origin.js +20 -11
- package/dist/core/ask-question.d.ts +0 -1
- package/dist/core/ask-question.js +4 -67
- package/dist/core/ask-unresolvable-notice.d.ts +3 -2
- package/dist/core/auto-compaction.d.ts +106 -50
- package/dist/core/auto-compaction.js +69 -53
- package/dist/core/auto-mode-prompt.d.ts +4 -2
- package/dist/core/auto-mode-prompt.js +4 -3
- package/dist/core/canonical-json.d.ts +69 -0
- package/dist/core/canonical-json.js +130 -8
- package/dist/core/checkpoint-requirements.d.ts +13 -7
- package/dist/core/checkpoint-requirements.js +4 -1
- package/dist/core/checkpoint-store.d.ts +60 -36
- package/dist/core/checkpoint-store.js +7 -6
- package/dist/core/child-clamp-seats.d.ts +45 -6
- package/dist/core/child-clamp-seats.js +56 -4
- package/dist/core/compliance.js +3 -1
- package/dist/core/consolidate-scope.d.ts +1 -1
- package/dist/core/cross-boundary-taint.d.ts +213 -0
- package/dist/core/cross-boundary-taint.js +196 -0
- package/dist/core/decision-receipt.d.ts +44 -1
- package/dist/core/decision-receipt.js +16 -0
- package/dist/core/effective-path-target.d.ts +28 -6
- package/dist/core/effective-path-target.js +28 -2
- package/dist/core/engine-notice.d.ts +47 -4
- package/dist/core/engine-notice.js +17 -1
- package/dist/core/engine-storage-backend.d.ts +73 -0
- package/dist/core/engine-storage-backend.js +1 -0
- package/dist/core/file-history-store.d.ts +6 -2
- package/dist/core/file-history-store.js +1 -0
- package/dist/core/gate-fold.js +13 -4
- package/dist/core/gate-lanes.js +41 -34
- package/dist/core/gate-outcome.d.ts +18 -9
- package/dist/core/governance-codes.d.ts +9 -2
- package/dist/core/governance-codes.js +9 -0
- package/dist/core/hands-band-screen.d.ts +7 -0
- package/dist/core/hands-band-screen.js +32 -0
- package/dist/core/hooks.d.ts +21 -19
- package/dist/core/hooks.js +6 -5
- package/dist/core/locked-config.d.ts +110 -31
- package/dist/core/locked-config.js +155 -42
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mcp-probe.js +1 -1
- package/dist/core/mcp-server-spec.d.ts +152 -17
- package/dist/core/mcp-server-spec.js +223 -40
- package/dist/core/mcp.d.ts +21 -14
- package/dist/core/mcp.js +59 -54
- package/dist/core/memory-engine/engine.d.ts +14 -19
- package/dist/core/memory-engine/engine.js +9 -6
- package/dist/core/memory-engine/export-bundle.d.ts +1 -1
- package/dist/core/memory-engine/export-bundle.js +1 -1
- package/dist/core/memory-engine/file-backend.d.ts +2 -6
- package/dist/core/memory-engine/file-backend.js +1 -12
- package/dist/core/memory.d.ts +3 -3
- package/dist/core/mode-policy.d.ts +16 -26
- package/dist/core/mode-policy.js +5 -18
- package/dist/core/mods/kernel/dispatch.js +13 -15
- package/dist/core/mods/kernel/events.d.ts +9 -6
- package/dist/core/mods/kernel/events.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +41 -11
- package/dist/core/mods/kernel/receive.js +124 -54
- package/dist/core/mods/kernel/site-rules.d.ts +80 -15
- package/dist/core/mods/kernel/site-rules.js +232 -40
- package/dist/core/mods/stations.d.ts +0 -6
- package/dist/core/mods/stations.js +0 -7
- package/dist/core/mounted-mcp.d.ts +57 -0
- package/dist/core/mounted-mcp.js +71 -2
- package/dist/core/own-property-receipt.d.ts +13 -0
- package/dist/core/own-property-receipt.js +3 -1
- package/dist/core/parent-spec-seat.d.ts +12 -15
- package/dist/core/parent-spec-seat.js +14 -6
- package/dist/core/pause-registry.d.ts +35 -1
- package/dist/core/pause-registry.js +10 -0
- package/dist/core/permission-rule-consent.d.ts +18 -5
- package/dist/core/permission-rule-consent.js +13 -8
- package/dist/core/permission-rule-model.d.ts +87 -15
- package/dist/core/permission-rule-model.js +87 -8
- package/dist/core/permission-rule-org.d.ts +200 -33
- package/dist/core/permission-rule-org.js +217 -91
- package/dist/core/permission-rule-session.js +2 -2
- package/dist/core/permission-rule-store.d.ts +8 -0
- package/dist/core/permission-rule-store.js +1 -0
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/permission-rules.d.ts +7 -1
- package/dist/core/permission-rules.js +37 -8
- package/dist/core/read-only-shell.d.ts +1 -1
- package/dist/core/read-only-shell.js +30 -9
- package/dist/core/remote-env.d.ts +41 -1
- package/dist/core/remote-env.js +18 -0
- package/dist/core/resume-startup-cause.d.ts +18 -0
- package/dist/core/resume-startup-cause.js +12 -0
- package/dist/core/retention.js +7 -2
- package/dist/core/retired-keys.d.ts +8 -2
- package/dist/core/retired-keys.js +12 -1
- package/dist/core/roles.js +60 -10
- package/dist/core/rule-lane-reads.js +1 -1
- package/dist/core/runner/approval-feedback.d.ts +46 -0
- package/dist/core/runner/approval-feedback.js +41 -0
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.js +2 -2
- package/dist/core/runner/contracts.d.ts +34 -41
- package/dist/core/runner/cross-boundary-lane.d.ts +87 -0
- package/dist/core/runner/cross-boundary-lane.js +190 -0
- package/dist/core/runner/decide-continuation.d.ts +4 -4
- package/dist/core/runner/decide-continuation.js +3 -1
- package/dist/core/runner/gate-exit.d.ts +32 -12
- package/dist/core/runner/gate-exit.js +77 -34
- package/dist/core/runner/inherited-ask-grants.js +2 -2
- package/dist/core/runner/mcp-redial.d.ts +52 -10
- package/dist/core/runner/mcp-redial.js +38 -9
- package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
- package/dist/core/runner/permission-rule-lanes.js +22 -10
- package/dist/core/runner/person-path-rows.d.ts +5 -3
- package/dist/core/runner/person-path-rows.js +2 -2
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -4
- package/dist/core/runner/prepare-acquire-reconcile.js +3 -3
- package/dist/core/runner/prepare-ask-lane.js +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +6 -5
- package/dist/core/runner/prepare-caps-and-workflow.js +3 -3
- package/dist/core/runner/prepare-config-doors.d.ts +58 -15
- package/dist/core/runner/prepare-config-doors.js +167 -146
- package/dist/core/runner/prepare-context-lane.js +6 -3
- package/dist/core/runner/prepare-defer-classify.js +4 -7
- package/dist/core/runner/prepare-delegation-surface.d.ts +5 -4
- package/dist/core/runner/prepare-delegation-surface.js +8 -7
- package/dist/core/runner/prepare-execution-env.d.ts +1 -2
- package/dist/core/runner/prepare-execution-env.js +2 -1
- package/dist/core/runner/prepare-gate-stations.d.ts +2 -0
- package/dist/core/runner/prepare-gate-stations.js +4 -3
- package/dist/core/runner/prepare-hands-readface.d.ts +3 -3
- package/dist/core/runner/prepare-hands-readface.js +3 -2
- package/dist/core/runner/prepare-inherited-gate.d.ts +2 -0
- package/dist/core/runner/prepare-inherited-gate.js +3 -2
- package/dist/core/runner/prepare-listings.d.ts +1 -1
- package/dist/core/runner/prepare-listings.js +4 -2
- package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
- package/dist/core/runner/prepare-memory-engine-session.js +19 -6
- package/dist/core/runner/prepare-memory.d.ts +3 -2
- package/dist/core/runner/prepare-memory.js +6 -2
- package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
- package/dist/core/runner/prepare-offload-wrappers.js +2 -1
- package/dist/core/runner/prepare-park-ask.d.ts +1 -1
- package/dist/core/runner/prepare-park-ask.js +9 -3
- package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
- package/dist/core/runner/prepare-policy-chain.js +14 -19
- package/dist/core/runner/prepare-project-context.d.ts +1 -1
- package/dist/core/runner/prepare-project-context.js +6 -4
- package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
- package/dist/core/runner/prepare-prompt-assembly.js +20 -16
- package/dist/core/runner/prepare-prompt-inputs.d.ts +12 -6
- package/dist/core/runner/prepare-prompt-inputs.js +6 -3
- package/dist/core/runner/prepare-protocol-tools.d.ts +7 -5
- package/dist/core/runner/prepare-protocol-tools.js +19 -12
- package/dist/core/runner/prepare-question-face.d.ts +4 -2
- package/dist/core/runner/prepare-question-face.js +4 -3
- package/dist/core/runner/prepare-safety-scan.d.ts +7 -2
- package/dist/core/runner/prepare-safety-scan.js +34 -27
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -2
- package/dist/core/runner/prepare-suspend-saga.js +6 -2
- package/dist/core/runner/prepare-task.js +22 -19
- package/dist/core/runner/prepare-turn-wiring.d.ts +10 -5
- package/dist/core/runner/prepare-turn-wiring.js +14 -49
- package/dist/core/runner/prepare-wiring-manifest.d.ts +10 -5
- package/dist/core/runner/prepare-wiring-manifest.js +9 -6
- package/dist/core/runner/prepare-workspace-restore.js +2 -2
- package/dist/core/runner/resume-admission.d.ts +4 -1
- package/dist/core/runner/resume-admission.js +16 -14
- package/dist/core/runner/resume-apply.js +4 -4
- package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
- package/dist/core/runner/resume-internals-and-config.js +3 -8
- package/dist/core/runner/resume-policy-outcome.d.ts +2 -2
- package/dist/core/runner/resume-policy-outcome.js +18 -15
- package/dist/core/runner/resume-preflight.js +2 -2
- package/dist/core/runner/resume-review-outcome.js +3 -3
- package/dist/core/runner/retired-runner-deps.d.ts +5 -6
- package/dist/core/runner/retired-runner-deps.js +1 -4
- package/dist/core/runner/run-leg.js +97 -43
- package/dist/core/runner/run-recovery-lanes.js +5 -3
- package/dist/core/runner/run-settle-and-teardown.js +2 -0
- package/dist/core/runner/run-terminal-adoption.js +21 -9
- package/dist/core/runner/run-turn-boundary.js +9 -3
- package/dist/core/runner/runtask.js +1 -1
- package/dist/core/runner/session-file-state-replay.d.ts +5 -2
- package/dist/core/runner/session-file-state-replay.js +3 -2
- package/dist/core/runner/skills-seat.d.ts +15 -0
- package/dist/core/runner/skills-seat.js +57 -0
- package/dist/core/runner/stream-steer-verb.js +2 -2
- package/dist/core/runner/sub-agent-deny-lists.d.ts +13 -11
- package/dist/core/runner/sub-agent-deny-lists.js +7 -5
- package/dist/core/runner/synthetic-tools.d.ts +5 -2
- package/dist/core/runner/synthetic-tools.js +2 -12
- package/dist/core/runner/tool-face-overlay.d.ts +24 -6
- package/dist/core/runner/tool-face-overlay.js +24 -15
- package/dist/core/runner-deps.d.ts +37 -22
- package/dist/core/session-policy-store.d.ts +19 -0
- package/dist/core/session-policy-store.js +22 -2
- package/dist/core/session-store.d.ts +35 -16
- package/dist/core/session-store.js +20 -12
- package/dist/core/{shell-lexer.d.ts → shell-run-candidates.d.ts} +36 -12
- package/dist/core/{shell-lexer.js → shell-run-candidates.js} +145 -225
- package/dist/core/shell-wrapper-table.d.ts +5 -3
- package/dist/core/shell-wrapper-table.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +49 -0
- package/dist/core/store-contracts/session-store-contract.js +639 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +12 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +5 -2
- package/dist/core/task-event.d.ts +44 -6
- package/dist/core/task-notification.js +2 -2
- package/dist/core/task-registry-agent.js +1 -0
- package/dist/core/task-registry-shared.d.ts +5 -0
- package/dist/core/task-registry.d.ts +7 -0
- package/dist/core/task-registry.js +17 -0
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +7 -7
- package/dist/core/tighten-task-spec.d.ts +6 -4
- package/dist/core/tighten-task-spec.js +2 -2
- package/dist/core/tool-catalog-entries.d.ts +1 -1
- package/dist/core/tool-catalog-entries.js +52 -52
- package/dist/core/tool-face-reader.d.ts +49 -0
- package/dist/core/tool-face-reader.js +94 -0
- package/dist/core/tool-face.d.ts +17 -8
- package/dist/core/tool-face.js +1 -0
- package/dist/core/tool-policy.d.ts +67 -23
- package/dist/core/tool-policy.js +72 -60
- package/dist/core/tool-roster.d.ts +46 -28
- package/dist/core/tool-roster.js +91 -14
- package/dist/core/tool-spec-members.js +2 -2
- package/dist/core/tool-spec.d.ts +20 -4
- package/dist/core/tools.js +2 -0
- package/dist/core/trace.d.ts +24 -2
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-text.d.ts +23 -0
- package/dist/core/untrusted-text.js +10 -10
- package/dist/core/user-attachment.d.ts +56 -2
- package/dist/core/user-attachment.js +139 -56
- package/dist/core/wiring-manifest.d.ts +4 -2
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/harness/agent-harness.js +2 -1
- package/dist/engine/harness/types.d.ts +10 -4
- package/dist/engine/llm/types.d.ts +7 -2
- package/dist/engine/llm/types.js +2 -1
- package/dist/engine/loop/agent-loop.d.ts +12 -1
- package/dist/engine/loop/agent-loop.js +17 -5
- package/dist/engine/loop/types.d.ts +7 -1
- package/dist/engine/session/repo-utils.d.ts +5 -0
- package/dist/engine/session/repo-utils.js +9 -0
- package/dist/engine/session/storage-base.js +2 -2
- package/dist/index.d.ts +37 -17
- package/dist/index.js +31 -14
- package/dist/internal/harness.d.ts +1 -0
- package/dist/internal/harness.js +1 -0
- package/dist/internal/llm.d.ts +1 -1
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/goal.d.ts +24 -1
- package/dist/orchestration/goal.js +3 -2
- package/dist/orchestration/run-workflow-tool.d.ts +3 -0
- package/dist/orchestration/run-workflow-tool.js +1 -0
- package/dist/orchestration/workflow-governance.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +2 -1
- package/dist/prompt-assembly/artifact-store.d.ts +44 -9
- package/dist/prompt-assembly/artifact-store.js +38 -12
- package/dist/prompt-assembly/artifact.d.ts +12 -11
- package/dist/prompt-assembly/artifact.js +52 -21
- package/dist/prompt-assembly/assemble.d.ts +2 -0
- package/dist/prompt-assembly/assemble.js +2 -1
- package/dist/prompt-assembly/catalog/index.js +2 -1
- package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
- package/dist/prompt-assembly/catalog/memory.js +6 -0
- package/dist/prompt-assembly/catalog/schema.d.ts +19 -2
- package/dist/prompt-assembly/catalog/schema.js +3 -0
- package/dist/prompt-assembly/composer.d.ts +2 -0
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/overlay.d.ts +21 -11
- package/dist/prompt-assembly/overlay.js +57 -19
- package/dist/prompt-assembly/select.d.ts +21 -6
- package/dist/prompt-assembly/select.js +41 -4
- package/dist/prompts/default.d.ts +1 -12
- package/dist/prompts/default.js +0 -3
- package/dist/shell/lex.d.ts +87 -8
- package/dist/shell/lex.js +283 -49
- package/dist/stores/file/index.d.ts +8 -6
- package/dist/stores/file/permission-rule-store.d.ts +1 -1
- package/dist/stores/file/permission-rule-store.js +2 -1
- package/dist/tools/artifact/artifact-tool.js +14 -3
- package/dist/tools/fs/bash-program-position.d.ts +3 -15
- package/dist/tools/fs/bash-program-position.js +3 -10
- package/dist/tools/fs/bash-readonly-classifier.js +2 -0
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-bash.js +72 -101
- package/dist/tools/fs/fs-read.d.ts +12 -0
- package/dist/tools/fs/fs-read.js +10 -9
- package/dist/tools/fs/fs-shared.d.ts +27 -31
- package/dist/tools/fs/fs-shared.js +12 -15
- package/dist/tools/fs/fs-write.js +1 -1
- package/dist/tools/fs/index.js +2 -2
- package/dist/tools/fs/read-deny-home.d.ts +1 -1
- package/dist/tools/fs/read-deny-home.js +5 -4
- package/dist/tools/fs/read-deny.d.ts +16 -3
- package/dist/tools/fs/read-deny.js +12 -9
- package/dist/tools/fs/safety.d.ts +7 -6
- package/dist/tools/fs/shell-read-bindings.d.ts +5 -3
- package/dist/tools/fs/shell-read-bindings.js +15 -16
- package/dist/tools/fs/shell-read-device.js +1 -1
- package/dist/tools/fs/shell-read-plan.js +36 -47
- package/dist/tools/fs/shell-read-word.d.ts +1 -6
- package/dist/tools/fs/shell-read-word.js +2 -20
- package/dist/tools/fs/shell-reentry-text.js +1 -1
- package/dist/tools/web.d.ts +2 -2
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +5651 -5457
- package/wire-changes/core@7.53.0.json +1968 -0
- package/wire-changes/core@7.54.0.json +2870 -0
- package/dist/core/shell-scan.d.ts +0 -60
- package/dist/core/shell-scan.js +0 -183
|
@@ -1,12 +1,194 @@
|
|
|
1
1
|
import { describe } from "./events.js";
|
|
2
2
|
import { describeFault, isPlainRecord, MODS_PAYLOAD_MODE, receive } from "./receive.js";
|
|
3
|
+
export const MODS_VALUE_DEPTH = 1_000;
|
|
4
|
+
const HANDED_MODE = Object.freeze({ ...MODS_PAYLOAD_MODE, depth: MODS_VALUE_DEPTH + 1, past: "refuse" });
|
|
3
5
|
function payloadMode(isProxy) {
|
|
4
|
-
return isProxy === undefined ?
|
|
6
|
+
return isProxy === undefined ? HANDED_MODE : Object.freeze({ ...HANDED_MODE, isProxy });
|
|
7
|
+
}
|
|
8
|
+
const TOO_DEEP_TO_COMPARE = `too deep to compare (nested past ${MODS_VALUE_DEPTH} levels)`;
|
|
9
|
+
function faultClause(fault) {
|
|
10
|
+
if (fault.kind !== "too-deep")
|
|
11
|
+
return describeFault(fault);
|
|
12
|
+
return `a value nested past ${MODS_VALUE_DEPTH} levels${fault.path.length > 0 ? ` under "${fault.path[0]}"` : ""}`;
|
|
5
13
|
}
|
|
6
14
|
export const MOD_FAILURE_CAUSES = Object.freeze(["threw", "timeout", "violation", "reentry"]);
|
|
7
15
|
export const NEXT_IN_FLIGHT = Object.freeze({ inFlight: true });
|
|
16
|
+
const TOO_DEEP = Object.freeze({ tooDeep: true });
|
|
17
|
+
const OPEN = "open";
|
|
18
|
+
function sameModValue(a0, b0, paired, depth0, homes) {
|
|
19
|
+
const stack = [];
|
|
20
|
+
const named = (r) => Object.keys(r).filter((k) => r[k] !== undefined);
|
|
21
|
+
const meet = (a, b, depth) => {
|
|
22
|
+
if (a === b || (Number.isNaN(a) && Number.isNaN(b)))
|
|
23
|
+
return 0;
|
|
24
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null)
|
|
25
|
+
return false;
|
|
26
|
+
let row = paired.get(a);
|
|
27
|
+
const met = row?.get(b);
|
|
28
|
+
if (met !== undefined) {
|
|
29
|
+
const height = met === OPEN ? 1 : met;
|
|
30
|
+
if (depth + height - 1 > MODS_VALUE_DEPTH)
|
|
31
|
+
throw TOO_DEEP;
|
|
32
|
+
return height;
|
|
33
|
+
}
|
|
34
|
+
if (depth > MODS_VALUE_DEPTH)
|
|
35
|
+
throw TOO_DEEP;
|
|
36
|
+
if (row === undefined)
|
|
37
|
+
paired.set(a, (row = new Map()));
|
|
38
|
+
row.set(b, OPEN);
|
|
39
|
+
if (!homes.has(b))
|
|
40
|
+
homes.set(b, a);
|
|
41
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
42
|
+
if (!Array.isArray(a) || !Array.isArray(b) || Object.getPrototypeOf(a) !== Array.prototype || Object.getPrototypeOf(b) !== Array.prototype || a.length !== b.length)
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
else if (!isPlainRecord(a) || !isPlainRecord(b))
|
|
46
|
+
return false;
|
|
47
|
+
const ra = a;
|
|
48
|
+
const rb = b;
|
|
49
|
+
const names = named(ra);
|
|
50
|
+
if (names.length !== named(rb).length)
|
|
51
|
+
return false;
|
|
52
|
+
stack.push({ a: ra, b: rb, row, names, depth, next: 0, height: 1 });
|
|
53
|
+
return undefined;
|
|
54
|
+
};
|
|
55
|
+
const top = meet(a0, b0, depth0);
|
|
56
|
+
if (top !== undefined)
|
|
57
|
+
return top;
|
|
58
|
+
for (;;) {
|
|
59
|
+
const f = stack[stack.length - 1];
|
|
60
|
+
if (f.next < f.names.length) {
|
|
61
|
+
const k = f.names[f.next++];
|
|
62
|
+
if (!Object.hasOwn(f.b, k))
|
|
63
|
+
return false;
|
|
64
|
+
const below = meet(f.a[k], f.b[k], f.depth + 1);
|
|
65
|
+
if (below === false)
|
|
66
|
+
return false;
|
|
67
|
+
if (below !== undefined)
|
|
68
|
+
f.height = Math.max(f.height, below + 1);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
f.row.set(f.b, f.height);
|
|
72
|
+
stack.pop();
|
|
73
|
+
const holder = stack[stack.length - 1];
|
|
74
|
+
if (holder === undefined)
|
|
75
|
+
return f.height;
|
|
76
|
+
holder.height = Math.max(holder.height, f.height + 1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
8
79
|
export function pinnedKeyChanged(pinned, received, passed) {
|
|
9
|
-
|
|
80
|
+
const compared = comparePinned(pinned, received, passed);
|
|
81
|
+
return "broke" in compared ? compared.broke : undefined;
|
|
82
|
+
}
|
|
83
|
+
function comparePinned(pinned, received, passed) {
|
|
84
|
+
const paired = new Map();
|
|
85
|
+
const homes = new Map();
|
|
86
|
+
for (const key of pinned) {
|
|
87
|
+
try {
|
|
88
|
+
if (sameModValue(received[key], passed[key], paired, 1, homes) === false)
|
|
89
|
+
return { broke: { key } };
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
return { broke: { key, unproven: err === TOO_DEEP ? TOO_DEEP_TO_COMPARE : "the comparison could not walk it to the end" } };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return { homes };
|
|
96
|
+
}
|
|
97
|
+
function engineObjects(held) {
|
|
98
|
+
const found = new Set();
|
|
99
|
+
const stack = Object.values(held);
|
|
100
|
+
while (stack.length > 0) {
|
|
101
|
+
const v = stack.pop();
|
|
102
|
+
if (typeof v !== "object" || v === null || found.has(v) || !Object.isFrozen(v))
|
|
103
|
+
continue;
|
|
104
|
+
if (!isPlainRecord(v) && !(Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype))
|
|
105
|
+
continue;
|
|
106
|
+
found.add(v);
|
|
107
|
+
for (const k of Object.keys(v))
|
|
108
|
+
stack.push(v[k]);
|
|
109
|
+
}
|
|
110
|
+
return found;
|
|
111
|
+
}
|
|
112
|
+
export function engineObjectsOnce(held) {
|
|
113
|
+
let found;
|
|
114
|
+
return () => (found ??= engineObjects(held));
|
|
115
|
+
}
|
|
116
|
+
const unprovenCopy = (key, why) => `next() handed on a copy of the pinned key "${key}" that is ${why}; a copy is taken only when proven the same`;
|
|
117
|
+
export function handedOn(pinned, held, passed, engines, isProxy) {
|
|
118
|
+
const received = receiveRecord(passed, payloadMode(isProxy), engines);
|
|
119
|
+
if ("refusal" in received) {
|
|
120
|
+
const key = received.fault?.kind === "too-deep" ? received.fault.path[0] : undefined;
|
|
121
|
+
return { violation: key !== undefined && pinned.includes(key) ? unprovenCopy(key, TOO_DEEP_TO_COMPARE) : `next() takes the event object: ${received.refusal}` };
|
|
122
|
+
}
|
|
123
|
+
return pinnedHandOn(pinned, held, received.payload, engines);
|
|
124
|
+
}
|
|
125
|
+
export function pinnedHandOn(pinned, held, passed, engines) {
|
|
126
|
+
const compared = comparePinned(pinned, held, passed);
|
|
127
|
+
if ("broke" in compared) {
|
|
128
|
+
return { violation: compared.broke.unproven === undefined ? `next() changed the pinned key "${compared.broke.key}"` : unprovenCopy(compared.broke.key, compared.broke.unproven) };
|
|
129
|
+
}
|
|
130
|
+
if (pinned.every((k) => Object.hasOwn(passed, k) === Object.hasOwn(held, k) && Object.is(passed[k], held[k])))
|
|
131
|
+
return { payload: passed };
|
|
132
|
+
return { payload: rehomed(pinned, held, passed, compared.homes, engines ?? engineObjects(held)) };
|
|
133
|
+
}
|
|
134
|
+
function rehomed(pinned, held, passed, homes, engines) {
|
|
135
|
+
const swap = new Map();
|
|
136
|
+
for (const [copy, home] of homes)
|
|
137
|
+
if (copy !== passed && !engines.has(copy))
|
|
138
|
+
swap.set(copy, home);
|
|
139
|
+
const isContainer = (v) => typeof v === "object" && v !== null && !engines.has(v) && !swap.has(v) && (isPlainRecord(v) || (Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype));
|
|
140
|
+
const holders = new Map();
|
|
141
|
+
const walked = new Set([passed]);
|
|
142
|
+
const stack = [passed];
|
|
143
|
+
while (stack.length > 0) {
|
|
144
|
+
const node = stack.pop();
|
|
145
|
+
for (const k of Object.keys(node)) {
|
|
146
|
+
if (node === passed && pinned.includes(k))
|
|
147
|
+
continue;
|
|
148
|
+
const v = node[k];
|
|
149
|
+
if (v !== passed && !swap.has(v) && !isContainer(v))
|
|
150
|
+
continue;
|
|
151
|
+
const by = holders.get(v);
|
|
152
|
+
if (by === undefined)
|
|
153
|
+
holders.set(v, [node]);
|
|
154
|
+
else
|
|
155
|
+
by.push(node);
|
|
156
|
+
if (isContainer(v) && !walked.has(v)) {
|
|
157
|
+
walked.add(v);
|
|
158
|
+
stack.push(v);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const twins = new Map([[passed, {}]]);
|
|
163
|
+
const reach = [passed, ...swap.keys()];
|
|
164
|
+
while (reach.length > 0) {
|
|
165
|
+
for (const h of holders.get(reach.pop()) ?? []) {
|
|
166
|
+
if (twins.has(h))
|
|
167
|
+
continue;
|
|
168
|
+
twins.set(h, Array.isArray(h) ? [] : {});
|
|
169
|
+
reach.push(h);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const put = (to, k, v) => void Object.defineProperty(to, k, { value: v, enumerable: true, writable: true, configurable: true });
|
|
173
|
+
const moved = (v) => (typeof v !== "object" || v === null ? v : swap.has(v) ? swap.get(v) : (twins.get(v) ?? v));
|
|
174
|
+
for (const [from, to] of twins) {
|
|
175
|
+
const r = from;
|
|
176
|
+
for (const k of Object.keys(r)) {
|
|
177
|
+
if (from !== passed || !pinned.includes(k))
|
|
178
|
+
put(to, k, moved(r[k]));
|
|
179
|
+
else if (Object.hasOwn(held, k))
|
|
180
|
+
put(to, k, held[k]);
|
|
181
|
+
}
|
|
182
|
+
if (from === passed)
|
|
183
|
+
for (const k of pinned)
|
|
184
|
+
if (Object.hasOwn(held, k) && !Object.hasOwn(to, k))
|
|
185
|
+
put(to, k, held[k]);
|
|
186
|
+
if (Array.isArray(from) && Array.isArray(to))
|
|
187
|
+
to.length = from.length;
|
|
188
|
+
}
|
|
189
|
+
for (const to of twins.values())
|
|
190
|
+
Object.freeze(to);
|
|
191
|
+
return twins.get(passed);
|
|
10
192
|
}
|
|
11
193
|
export function answerViolation(answer, check, e, by, below) {
|
|
12
194
|
if (answer === undefined)
|
|
@@ -49,13 +231,21 @@ export function matcherMatches(m, e) {
|
|
|
49
231
|
return true;
|
|
50
232
|
return Object.entries(m).every(([k, v]) => Object.prototype.hasOwnProperty.call(e, k) && e[k] === v);
|
|
51
233
|
}
|
|
52
|
-
|
|
53
|
-
if (isProxy !== undefined && typeof v === "object" && v !== null && isProxy(v))
|
|
234
|
+
function receiveRecord(v, mode, held) {
|
|
235
|
+
if (mode.isProxy !== undefined && typeof v === "object" && v !== null && mode.isProxy(v))
|
|
54
236
|
return { refusal: "the payload is a Proxy (refused before any of its traps runs)" };
|
|
55
237
|
if (!isPlainRecord(v))
|
|
56
238
|
return { refusal: `an event payload is a plain object, not ${describe(v)}` };
|
|
57
|
-
const r = receive(v,
|
|
58
|
-
return r.ok ? { payload: Object.freeze(r.value) } : { refusal: `the payload holds ${
|
|
239
|
+
const r = receive(v, mode, held);
|
|
240
|
+
return r.ok ? { payload: Object.freeze(r.value) } : { refusal: `the payload holds ${faultClause(r.fault)}`, fault: r.fault };
|
|
241
|
+
}
|
|
242
|
+
export function receivePayload(v, isProxy, held) {
|
|
243
|
+
const r = receiveRecord(v, payloadMode(isProxy), held);
|
|
244
|
+
return "refusal" in r ? { refusal: r.refusal } : r;
|
|
245
|
+
}
|
|
246
|
+
export function receiveEvent(e) {
|
|
247
|
+
const r = receiveRecord(e, MODS_PAYLOAD_MODE);
|
|
248
|
+
return "refusal" in r ? { refusal: r.refusal } : r;
|
|
59
249
|
}
|
|
60
250
|
export function answerUpward(v) {
|
|
61
251
|
if (typeof v !== "object" || v === null || Object.isFrozen(v))
|
|
@@ -64,41 +254,43 @@ export function answerUpward(v) {
|
|
|
64
254
|
return Object.freeze([...v]);
|
|
65
255
|
return isPlainRecord(v) ? Object.freeze({ ...v }) : v;
|
|
66
256
|
}
|
|
67
|
-
export function receiveAnswer(answer, isProxy) {
|
|
68
|
-
const r = receive(answer, payloadMode(isProxy));
|
|
69
|
-
return r.ok ? { answer: r.value } : { refusal: `answered ${
|
|
257
|
+
export function receiveAnswer(answer, engines, isProxy) {
|
|
258
|
+
const r = receive(answer, payloadMode(isProxy), engines);
|
|
259
|
+
return r.ok ? { answer: r.value } : { refusal: `answered ${faultClause(r.fault)}` };
|
|
70
260
|
}
|
|
261
|
+
const DETACHED_MODE = Object.freeze({ accessors: "refuse", depth: Infinity, others: "as-is" });
|
|
71
262
|
export function detachedCopy(e) {
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
263
|
+
const r = receive(e, DETACHED_MODE);
|
|
264
|
+
if (!r.ok)
|
|
265
|
+
throw new Error(`the observer's copy of the event could not be made: ${describeFault(r.fault)}`);
|
|
266
|
+
const copy = r.value;
|
|
267
|
+
const clones = new Map();
|
|
268
|
+
const walked = new Set([copy]);
|
|
269
|
+
const stack = [copy];
|
|
270
|
+
while (stack.length > 0) {
|
|
271
|
+
const node = stack.pop();
|
|
272
|
+
for (const k of Object.keys(node)) {
|
|
273
|
+
const v = node[k];
|
|
274
|
+
if (typeof v !== "object" || v === null)
|
|
275
|
+
continue;
|
|
276
|
+
if (isPlainRecord(v) || (Array.isArray(v) && Object.getPrototypeOf(v) === Array.prototype)) {
|
|
277
|
+
if (!walked.has(v)) {
|
|
278
|
+
walked.add(v);
|
|
279
|
+
stack.push(v);
|
|
280
|
+
}
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (!clones.has(v)) {
|
|
284
|
+
let own = v;
|
|
285
|
+
try {
|
|
286
|
+
own = structuredClone(v);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
}
|
|
290
|
+
clones.set(v, own);
|
|
291
|
+
}
|
|
292
|
+
Object.defineProperty(node, k, { value: clones.get(v), enumerable: true, writable: true, configurable: true });
|
|
293
|
+
}
|
|
96
294
|
}
|
|
97
|
-
|
|
98
|
-
return v;
|
|
99
|
-
const obj = {};
|
|
100
|
-
seen.set(v, obj);
|
|
101
|
-
for (const [k, x] of Object.entries(v))
|
|
102
|
-
Object.defineProperty(obj, k, { value: detachedValue(x, seen), enumerable: true, writable: true, configurable: true });
|
|
103
|
-
return obj;
|
|
295
|
+
return copy;
|
|
104
296
|
}
|
|
@@ -32,12 +32,6 @@ export declare function agentIdOf(identity: HookInvocationIdentity | undefined):
|
|
|
32
32
|
* leg's kind reads `"resume"` whoever it runs as.
|
|
33
33
|
*/
|
|
34
34
|
export declare function stopEventOf(identity: Pick<HookInvocationIdentity, "isDelegatedChild"> | undefined): "classic.Stop" | "classic.SubagentStop";
|
|
35
|
-
/**
|
|
36
|
-
* The args as an observation carries them: the kernel's detached copy (a structured clone, or a shallow copy for a
|
|
37
|
-
* graph the clone refuses), so an observer editing what it was handed cannot move the live args later frames and audit
|
|
38
|
-
* records share. A non-object value (immutable) is handed as is.
|
|
39
|
-
*/
|
|
40
|
-
export declare function detachedArgsOf(args: unknown): unknown;
|
|
41
35
|
/**
|
|
42
36
|
* The args as a judging handler receives them: the gate pass's own immutable value ({@link ownArgs} — the value itself when
|
|
43
37
|
* the gate already took it, which is every call the gate raises an event over), so the bytes a handler judges are the bytes
|
|
@@ -8,7 +8,6 @@ import { askApproverIdentity, describeThrown, ownArgs } from "../tool-policy.js"
|
|
|
8
8
|
import { admitMods, expandModPattern } from "./kernel/index.js";
|
|
9
9
|
import { validateOverlay } from "../../prompt-assembly/overlay.js";
|
|
10
10
|
import { modsInvalid } from "./kernel/registration.js";
|
|
11
|
-
import { detachedCopy } from "./kernel/site-rules.js";
|
|
12
11
|
import { isPlainRecord } from "./kernel/receive.js";
|
|
13
12
|
import { engineMethodBottoms } from "./dollar.js";
|
|
14
13
|
import { modSeatsOf, modsReportToOnError, registrationRefusedNotice } from "./host.js";
|
|
@@ -22,12 +21,6 @@ export function agentIdOf(identity) {
|
|
|
22
21
|
export function stopEventOf(identity) {
|
|
23
22
|
return identity?.isDelegatedChild === true ? "classic.SubagentStop" : "classic.Stop";
|
|
24
23
|
}
|
|
25
|
-
export function detachedArgsOf(args) {
|
|
26
|
-
return isRecord(args) ? detachedCopy(args) : args;
|
|
27
|
-
}
|
|
28
|
-
function isRecord(v) {
|
|
29
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
30
|
-
}
|
|
31
24
|
export function judgedInputOf(args) {
|
|
32
25
|
const owned = ownArgs(args);
|
|
33
26
|
return owned.ok ? owned.value : args;
|
|
@@ -10,9 +10,58 @@
|
|
|
10
10
|
import type { McpServerSpec } from "./mcp-server-spec.js";
|
|
11
11
|
import type { ToolContentOrigin } from "./tool-spec.js";
|
|
12
12
|
import type { McpConnectionPool } from "./mcp-connection-pool.js";
|
|
13
|
+
import type { McpInstructionsEntry } from "./prompt-section-seat.js";
|
|
13
14
|
/** The two names a server's `allowTools` carries to let the cross-server resource readers reach its resources (a server whose allowlist omits one is left out of that reader). */
|
|
14
15
|
export declare const MCP_RESOURCE_LIST_ALLOW = "list_resources";
|
|
15
16
|
export declare const MCP_RESOURCE_READ_ALLOW = "read_resource";
|
|
17
|
+
/** The canonical names of the resource tools (the trio: list-all / read-one / list-under-a-directory). They belong to no one server: each aggregates the resources of every connected server that advertises them. */
|
|
18
|
+
export declare const LIST_MCP_RESOURCES = "ListMcpResourcesTool";
|
|
19
|
+
export declare const READ_MCP_RESOURCE = "ReadMcpResourceTool";
|
|
20
|
+
export declare const READ_MCP_RESOURCE_DIR = "ReadMcpResourceDirTool";
|
|
21
|
+
/** Does the valve (`leaves`: its one predicate) leave at least one of the cross-server resource tools? While it does, a connected server may contribute to them whatever it lists. */
|
|
22
|
+
export declare function resourceFacesLeft(leaves: (tool: {
|
|
23
|
+
readonly name: string;
|
|
24
|
+
}) => boolean): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Are a server's instructions about something the run holds? Yes when the run's roster (`held`) holds a tool of the server's prefix
|
|
27
|
+
* domain the valve leaves, or a cross-server resource tool the valve leaves (the aggregates exist only if some connected server
|
|
28
|
+
* advertised resources, and which one is not recorded, so a held face keeps the instructions of every server); a server whose own
|
|
29
|
+
* listing (`listed` — any superset of it) has no tool at all (instructions only) is taught while any resource face is left. Read off
|
|
30
|
+
* the roster, a tool the deployment's `toolFaces` overlay refused counts as what it is — not held. A server the run holds nothing of
|
|
31
|
+
* is not taught: its instructions describe tools the model will not hold.
|
|
32
|
+
*
|
|
33
|
+
* The one answer to "should the model be taught them": the initial instructions block and the delta lane's adds after a roster change read
|
|
34
|
+
* it. Whether the model HOLDS them is the ledger's ({@link instructionsTold}), which the disconnect line reads.
|
|
35
|
+
*/
|
|
36
|
+
export declare function instructionsTaught(leaves: (tool: {
|
|
37
|
+
readonly name: string;
|
|
38
|
+
readonly aliases?: readonly string[];
|
|
39
|
+
}) => boolean, serverName: string, held: ReadonlyArray<{
|
|
40
|
+
readonly name: string;
|
|
41
|
+
readonly aliases?: readonly string[];
|
|
42
|
+
}>, listed: ReadonlyArray<{
|
|
43
|
+
readonly name: string;
|
|
44
|
+
}>): boolean;
|
|
45
|
+
/** A materialization's instructions delta lane (`MaterializedMcp.instructionsDelta`): what the run drains at its next boundary. */
|
|
46
|
+
export interface InstructionsLane {
|
|
47
|
+
pendingAdds: McpInstructionsEntry[];
|
|
48
|
+
pendingRemovals: string[];
|
|
49
|
+
}
|
|
50
|
+
/** Are this server's instructions in the model's context now? */
|
|
51
|
+
export declare function instructionsTold(lane: InstructionsLane, server: string): boolean;
|
|
52
|
+
/** A dial's default: the server's instructions are taught (a materialization alone takes every entry it returns as taught, until a run states its block). */
|
|
53
|
+
export declare function toldOnDial(lane: InstructionsLane, server: string): void;
|
|
54
|
+
/** The run's start: the stable block is what the model is told. A removal already queued for a server outside the block names instructions the model
|
|
55
|
+
* never held, so it is withdrawn; a server inside the block with a removal queued is not in context (the frame will retract it). */
|
|
56
|
+
export declare function toldAtStart(lane: InstructionsLane, servers: ReadonlySet<string>): void;
|
|
57
|
+
/** Take this server's unread adds off the lane; a first copy that never reached the model leaves the ledger with it. */
|
|
58
|
+
export declare function withdrawInstructionAdds(lane: InstructionsLane, server: string): void;
|
|
59
|
+
/** Queue this server's current text (superseding an unread copy). In context already ⇒ stays so; otherwise a first copy, queued. */
|
|
60
|
+
export declare function tellInstructions(lane: InstructionsLane, entry: McpInstructionsEntry): void;
|
|
61
|
+
/** The server's connection is gone: unread adds are withdrawn, and the model is told its instructions no longer apply only if it holds them. */
|
|
62
|
+
export declare function retractInstructions(lane: InstructionsLane, server: string): void;
|
|
63
|
+
/** A re-dial that connected: a retraction still unread never reached the model, so it is withdrawn and the text the model holds stands. */
|
|
64
|
+
export declare function unretractInstructions(lane: InstructionsLane, server: string): void;
|
|
16
65
|
/** One declared MCP server and its mounted tools. */
|
|
17
66
|
export interface MountedMcpServer {
|
|
18
67
|
readonly server: McpServerSpec;
|
|
@@ -33,6 +82,14 @@ interface RosterEntry {
|
|
|
33
82
|
readonly name: string;
|
|
34
83
|
readonly mcpRemoteName?: string;
|
|
35
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* The names among `names` that belong to the declared server `serverName`: those under its prefix domain (`mcp__<server>__`), which
|
|
87
|
+
* is the roster's own definition of a server's tools (the live roster swaps a server's tools by it). Handed a roster's names, it is
|
|
88
|
+
* the ONE answer to "how many tools of this server does the run hold" — the re-dial's receipt and notice, the content-class
|
|
89
|
+
* declaration line, the wiring manifest's per-server count and {@link mountedMcpOf} all read it, so no two of them can count
|
|
90
|
+
* differently. Handed a server's own listing it answers what the server offers, which is not a mount count.
|
|
91
|
+
*/
|
|
92
|
+
export declare function toolNamesOfServer(names: Iterable<string>, serverName: string): string[];
|
|
36
93
|
/**
|
|
37
94
|
* Read the run's MCP surface off its roster. `declared` is the run's frozen server declarations; `aggregateNames` the names of the
|
|
38
95
|
* tools its materialization minted that no server owns. A tool is a server's when its wire name sits under the server's prefix
|
package/dist/core/mounted-mcp.js
CHANGED
|
@@ -2,10 +2,79 @@ import { mintNamespacePrefix } from "./protocol-naming.js";
|
|
|
2
2
|
import { MCP_NAMESPACE } from "./protocol-table.js";
|
|
3
3
|
export const MCP_RESOURCE_LIST_ALLOW = "list_resources";
|
|
4
4
|
export const MCP_RESOURCE_READ_ALLOW = "read_resource";
|
|
5
|
+
export const LIST_MCP_RESOURCES = "ListMcpResourcesTool";
|
|
6
|
+
export const READ_MCP_RESOURCE = "ReadMcpResourceTool";
|
|
7
|
+
export const READ_MCP_RESOURCE_DIR = "ReadMcpResourceDirTool";
|
|
8
|
+
const MCP_RESOURCE_FACES = [LIST_MCP_RESOURCES, READ_MCP_RESOURCE, READ_MCP_RESOURCE_DIR];
|
|
9
|
+
export function resourceFacesLeft(leaves) {
|
|
10
|
+
return MCP_RESOURCE_FACES.some((name) => leaves({ name }));
|
|
11
|
+
}
|
|
12
|
+
export function instructionsTaught(leaves, serverName, held, listed) {
|
|
13
|
+
const own = new Set(toolNamesOfServer(held.map((t) => t.name), serverName));
|
|
14
|
+
return held.some((t) => (own.has(t.name) || MCP_RESOURCE_FACES.includes(t.name)) && leaves(t)) || (toolNamesOfServer(listed.map((t) => t.name), serverName).length === 0 && resourceFacesLeft(leaves));
|
|
15
|
+
}
|
|
16
|
+
const ledgers = new WeakMap();
|
|
17
|
+
function ledgerOf(lane) {
|
|
18
|
+
let ledger = ledgers.get(lane);
|
|
19
|
+
if (ledger === undefined)
|
|
20
|
+
ledgers.set(lane, (ledger = new Map()));
|
|
21
|
+
return ledger;
|
|
22
|
+
}
|
|
23
|
+
const queuedFor = (lane, server) => lane.pendingAdds.some((e) => e.server === server);
|
|
24
|
+
export function instructionsTold(lane, server) {
|
|
25
|
+
const state = ledgerOf(lane).get(server);
|
|
26
|
+
return state === "context" || (state === "queued" && !queuedFor(lane, server));
|
|
27
|
+
}
|
|
28
|
+
export function toldOnDial(lane, server) {
|
|
29
|
+
ledgerOf(lane).set(server, "context");
|
|
30
|
+
}
|
|
31
|
+
export function toldAtStart(lane, servers) {
|
|
32
|
+
const ledger = ledgerOf(lane);
|
|
33
|
+
ledger.clear();
|
|
34
|
+
for (let i = lane.pendingRemovals.length - 1; i >= 0; i--)
|
|
35
|
+
if (!servers.has(lane.pendingRemovals[i]))
|
|
36
|
+
lane.pendingRemovals.splice(i, 1);
|
|
37
|
+
for (const server of servers)
|
|
38
|
+
if (!lane.pendingRemovals.includes(server))
|
|
39
|
+
ledger.set(server, "context");
|
|
40
|
+
}
|
|
41
|
+
export function withdrawInstructionAdds(lane, server) {
|
|
42
|
+
const told = instructionsTold(lane, server);
|
|
43
|
+
for (let i = lane.pendingAdds.length - 1; i >= 0; i--)
|
|
44
|
+
if (lane.pendingAdds[i].server === server)
|
|
45
|
+
lane.pendingAdds.splice(i, 1);
|
|
46
|
+
if (!told)
|
|
47
|
+
ledgerOf(lane).delete(server);
|
|
48
|
+
}
|
|
49
|
+
export function tellInstructions(lane, entry) {
|
|
50
|
+
const told = instructionsTold(lane, entry.server);
|
|
51
|
+
withdrawInstructionAdds(lane, entry.server);
|
|
52
|
+
lane.pendingAdds.push(entry);
|
|
53
|
+
ledgerOf(lane).set(entry.server, told ? "context" : "queued");
|
|
54
|
+
}
|
|
55
|
+
export function retractInstructions(lane, server) {
|
|
56
|
+
const told = instructionsTold(lane, server);
|
|
57
|
+
withdrawInstructionAdds(lane, server);
|
|
58
|
+
if (told && !lane.pendingRemovals.includes(server))
|
|
59
|
+
lane.pendingRemovals.push(server);
|
|
60
|
+
ledgerOf(lane).delete(server);
|
|
61
|
+
}
|
|
62
|
+
export function unretractInstructions(lane, server) {
|
|
63
|
+
if (!lane.pendingRemovals.includes(server))
|
|
64
|
+
return;
|
|
65
|
+
for (let i = lane.pendingRemovals.length - 1; i >= 0; i--)
|
|
66
|
+
if (lane.pendingRemovals[i] === server)
|
|
67
|
+
lane.pendingRemovals.splice(i, 1);
|
|
68
|
+
ledgerOf(lane).set(server, "context");
|
|
69
|
+
}
|
|
70
|
+
export function toolNamesOfServer(names, serverName) {
|
|
71
|
+
const prefix = mintNamespacePrefix(MCP_NAMESPACE, serverName);
|
|
72
|
+
return [...names].filter((name) => name.startsWith(prefix));
|
|
73
|
+
}
|
|
5
74
|
export function mountedMcpOf(input) {
|
|
6
75
|
const servers = (input.declared ?? []).map((server) => {
|
|
7
|
-
const
|
|
8
|
-
const tools = input.roster.flatMap((t) => (t.name
|
|
76
|
+
const owned = new Set(toolNamesOfServer(input.roster.map((t) => t.name), server.name));
|
|
77
|
+
const tools = input.roster.flatMap((t) => (owned.has(t.name) && typeof t.mcpRemoteName === "string" ? [{ name: t.name, remoteName: t.mcpRemoteName }] : []));
|
|
9
78
|
return { server, tools };
|
|
10
79
|
});
|
|
11
80
|
const aggregate = input.roster.filter((t) => input.aggregateNames.has(t.name)).map((t) => t.name);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ReceiptMode } from "./mods/kernel/receive.js";
|
|
1
2
|
/** How a refusal names the object being received. */
|
|
2
3
|
export interface OwnPropertyReceiptWords {
|
|
3
4
|
/** The object, e.g. `RunnerDeps`. */
|
|
@@ -14,5 +15,17 @@ export declare function receiptRefusal(message: string): Error & {
|
|
|
14
15
|
/** The receipt's first look, before ANY reflection on the object (a door that must look at the caller's object before
|
|
15
16
|
* the receipt — a retired-name door reading its prototype chain — calls this first): a Proxy is refused. */
|
|
16
17
|
export declare function refuseProxy(given: object, words: OwnPropertyReceiptWords): void;
|
|
18
|
+
/** The configuration receipt's mode of the one receipt: the top record read, each getter once, its members as given (a declared list's
|
|
19
|
+
* own read too: the list itself, each element once, the elements as given). */
|
|
20
|
+
export declare const CONFIG_RECEIPT_MODE: ReceiptMode;
|
|
21
|
+
/**
|
|
22
|
+
* The declaration receipt's mode of the one receipt — a declaration the engine judges and then holds (an MCP server's or an A2A peer's
|
|
23
|
+
* entry, a `toolAxes` record, a lock declaration) received as plain data held to the engine's one depth for a caller's value,
|
|
24
|
+
* {@link MODS_VALUE_DEPTH} levels of records and lists below the declaration itself (the bound a mods handler's answer is held to): every
|
|
25
|
+
* own string-keyed member read once off its captured descriptor (a getter called once, enumerable or not), every level copied, anything
|
|
26
|
+
* that is not data refused (a Proxy at any level, a function, a bigint, an object of another prototype, a structure that contains
|
|
27
|
+
* itself, a container nested deeper — a shared one measured where it sits each time it is met), every copied container frozen.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DECLARATION_RECEIPT_MODE: ReceiptMode;
|
|
17
30
|
/** Read `given` by the receipt law (module note): the plain copy, every own member taken once from its captured descriptor. */
|
|
18
31
|
export declare function receiveOwnProperties<T extends object>(given: T, words: OwnPropertyReceiptWords): T;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { types } from "node:util";
|
|
2
2
|
import { describeFault, isPlainRecord, receive } from "./mods/kernel/receive.js";
|
|
3
|
+
import { MODS_VALUE_DEPTH } from "./mods/kernel/site-rules.js";
|
|
3
4
|
export function receiptRefusal(message) {
|
|
4
5
|
const e = new Error(message);
|
|
5
6
|
e.code = "config.invalid_argument";
|
|
@@ -9,7 +10,8 @@ export function refuseProxy(given, words) {
|
|
|
9
10
|
if (types.isProxy(given))
|
|
10
11
|
throw receiptRefusal(`${words.subject} must be a plain object, not a Proxy: its ${words.unit}s are read once off its own descriptors, and a Proxy would run its traps in that read — refused rather than wired through it`);
|
|
11
12
|
}
|
|
12
|
-
const CONFIG_RECEIPT_MODE = Object.freeze({ accessors: "call-once", depth: 1, others: "as-is", isProxy: (v) => types.isProxy(v) });
|
|
13
|
+
export const CONFIG_RECEIPT_MODE = Object.freeze({ accessors: "call-once", depth: 1, others: "as-is", isProxy: (v) => types.isProxy(v) });
|
|
14
|
+
export const DECLARATION_RECEIPT_MODE = Object.freeze({ accessors: "call-once", depth: MODS_VALUE_DEPTH + 1, others: "refuse", freeze: true, isProxy: (v) => types.isProxy(v) });
|
|
13
15
|
export function receiveOwnProperties(given, words) {
|
|
14
16
|
refuseProxy(given, words);
|
|
15
17
|
if (!isPlainRecord(given)) {
|
|
@@ -35,8 +35,9 @@ export type ParentSpecSeatFields = Pick<TaskSpec, "principal" | "oneShot" | "cli
|
|
|
35
35
|
* · `envFacts` — the sandbox facts (profile / egress / scratchpad).
|
|
36
36
|
* · `memoryPersistenceCapable` — the deployment's DECLARED persistence statement: `false` is a REMOVAL (floor),
|
|
37
37
|
* `true` a default a child's own declaration may narrow.
|
|
38
|
-
* · `
|
|
39
|
-
*
|
|
38
|
+
* · `memory` — the request-level "memory is off" FACT, `{ enabled: false }` and nothing else of the declaration (the clamp
|
|
39
|
+
* table's `memory.enabled` row; present only when the parent stated `enabled: false`): a REMOVAL (floor) that
|
|
40
|
+
* REWRITES the one member on the child's own memory declaration — its scopes and knobs are the child's.
|
|
40
41
|
* · `compaction` — the request's CONTEXT-MANAGEMENT settings (enabled / withinTask / reserve / keepRecent /
|
|
41
42
|
* instructions / attachWorkingFiles / staleToolResultOffload / clampTolerance). One set of settings for the
|
|
42
43
|
* whole delegation tree, measured per leg against the leg's OWN window: the numbers are repaired against the
|
|
@@ -52,8 +53,8 @@ export type ParentSpecSeatFields = Pick<TaskSpec, "principal" | "oneShot" | "cli
|
|
|
52
53
|
* · `promptForm` — the host form of the system prompt (`"minimal"`, its only word: the core-behavior band is out). A
|
|
53
54
|
* host's product choice for the whole delegation tree, so every engine-built child (both delegation lanes and the
|
|
54
55
|
* observer sidecar) composes the same set of sections. An ORDINARY member (fill law).
|
|
55
|
-
* · `promptBinding` — the
|
|
56
|
-
* artifact, so
|
|
56
|
+
* · `promptBinding` — the binding (a deployment's scenario name), a prompt selector value. A child composes its
|
|
57
|
+
* parent's center artifact, so its overlays' `when.binding` reads the same binding. An ORDINARY member (fill law).
|
|
57
58
|
*/
|
|
58
59
|
export interface ParentSpecSeat {
|
|
59
60
|
readonly principal?: string;
|
|
@@ -65,7 +66,9 @@ export interface ParentSpecSeat {
|
|
|
65
66
|
readonly additionalReadDirectories?: readonly string[];
|
|
66
67
|
readonly envFacts?: TaskSpec["envFacts"];
|
|
67
68
|
readonly memoryPersistenceCapable?: boolean;
|
|
68
|
-
readonly
|
|
69
|
+
readonly memory?: {
|
|
70
|
+
readonly enabled: false;
|
|
71
|
+
};
|
|
69
72
|
readonly compaction?: TaskSpec["compaction"];
|
|
70
73
|
readonly skillListingBudgetFraction?: number;
|
|
71
74
|
readonly skillListingMaxDescChars?: number;
|
|
@@ -73,13 +76,16 @@ export interface ParentSpecSeat {
|
|
|
73
76
|
readonly promptForm?: "minimal";
|
|
74
77
|
readonly promptBinding?: string;
|
|
75
78
|
}
|
|
79
|
+
/** Refuse (by name, `config.deps_retired_key`) a seat that still carries a retired member. Read at every door a seat enters
|
|
80
|
+
* by hand: the ctx reader, the apply, and the send lane's waker clamps. */
|
|
81
|
+
export declare function assertParentSpecSeatCurrent(seat: object | undefined): void;
|
|
76
82
|
/** Mint the seat off the parent's REBOUND spec and its frozen question face (spec over deps — the caller resolves it once,
|
|
77
83
|
* the same value the parent's own question routing reads). Absent fields stay absent; `oneShot` only when `true`. */
|
|
78
84
|
export declare function parentSpecSeatOf(spec: Omit<ParentSpecSeatFields, "onQuestion">, frozenOnQuestion: OnQuestion | undefined): ParentSpecSeat;
|
|
79
85
|
/**
|
|
80
86
|
* Apply the seat to a child spec — ONE law for every member, both lanes:
|
|
81
87
|
* a value the child spec already carries WINS; the seat FILLS an unset one; the three REMOVAL values
|
|
82
|
-
* (`oneShot: true`, `memoryPersistenceCapable: false`, `
|
|
88
|
+
* (`oneShot: true`, `memoryPersistenceCapable: false`, `memory: { enabled: false }`) land UNCONDITIONALLY.
|
|
83
89
|
* "Already carries" is the child's own authorship — a deployment baseline, a trusted script, an agent definition's
|
|
84
90
|
* fold (the Task lane folds the definition's `memoryPersistenceCapable` before applying; the workflow lane applies at
|
|
85
91
|
* the launch site AFTER the agentType fold) — so a definition may narrow a parent `true` to `false`, a baseline-pinned
|
|
@@ -88,15 +94,6 @@ export declare function parentSpecSeatOf(spec: Omit<ParentSpecSeatFields, "onQue
|
|
|
88
94
|
* No seat (a tool running outside a Runner task) ⇒ the child spec is returned as is.
|
|
89
95
|
*/
|
|
90
96
|
export declare function applyParentSpecSeat<S extends ParentSpecSeatFields>(child: S, seat: ParentSpecSeat | undefined): S;
|
|
91
|
-
/** The ONE way the memory-off floor is written onto a spec — the seat's apply above and the resume lane's
|
|
92
|
-
* clamp fold both call it: keep every field the spec authored (scopes, write scope, content-safety knobs)
|
|
93
|
-
* and state `enabled: false` over them. Returning a value rather than deleting the key IS the mechanism:
|
|
94
|
-
* the next seat mint reads `spec.memory.enabled === false`, so a spec whose `memory` was removed would end
|
|
95
|
-
* the floor one level down. A spec that declared nothing gets the bare `{ enabled: false }`, which the
|
|
96
|
-
* normalizer reads as "no usable scopes" — identical to the absent declaration it replaces. */
|
|
97
|
-
export declare function memoryTurnedOff(memory: TaskSpec["memory"]): NonNullable<TaskSpec["memory"]> & {
|
|
98
|
-
enabled: false;
|
|
99
|
-
};
|
|
100
97
|
/** The ctx keys that restate a seat member as THIS run's own fact (tools read them for scope / receipts / clamps). */
|
|
101
98
|
declare const SEAT_FACTS_ON_CTX: readonly ["principal", "oneShot", "onQuestion", "memoryPersistenceCapable"];
|
|
102
99
|
/**
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import { applyClampSeats, clampFieldSeatsOf } from "./child-clamp-seats.js";
|
|
2
|
+
import { assertNoRetiredKeys } from "./retired-keys.js";
|
|
3
|
+
const RETIRED_PARENT_SPEC_SEAT_KEYS = Object.freeze({
|
|
4
|
+
memoryOff: "the request-level memory-off fact is the clamp table's `memory` row now — carry `memory: { enabled: false }`",
|
|
5
|
+
});
|
|
6
|
+
export function assertParentSpecSeatCurrent(seat) {
|
|
7
|
+
if (seat !== undefined)
|
|
8
|
+
assertNoRetiredKeys(seat, RETIRED_PARENT_SPEC_SEAT_KEYS, "ParentSpecSeat");
|
|
9
|
+
}
|
|
1
10
|
export function parentSpecSeatOf(spec, frozenOnQuestion) {
|
|
2
11
|
return Object.freeze({
|
|
3
12
|
...(spec.principal !== undefined ? { principal: spec.principal } : {}),
|
|
@@ -15,14 +24,15 @@ export function parentSpecSeatOf(spec, frozenOnQuestion) {
|
|
|
15
24
|
...(spec.fileHistory !== undefined ? { fileHistory: spec.fileHistory } : {}),
|
|
16
25
|
...(spec.promptForm !== undefined ? { promptForm: spec.promptForm } : {}),
|
|
17
26
|
...(spec.promptBinding !== undefined ? { promptBinding: spec.promptBinding } : {}),
|
|
18
|
-
...(spec
|
|
27
|
+
...clampFieldSeatsOf(spec),
|
|
19
28
|
});
|
|
20
29
|
}
|
|
21
30
|
export function applyParentSpecSeat(child, seat) {
|
|
22
31
|
if (seat === undefined)
|
|
23
32
|
return child;
|
|
33
|
+
assertParentSpecSeatCurrent(seat);
|
|
24
34
|
const fill = (key, value) => child[key] === undefined && value !== undefined ? { [key]: value } : {};
|
|
25
|
-
|
|
35
|
+
const landed = {
|
|
26
36
|
...child,
|
|
27
37
|
...fill("principal", seat.principal),
|
|
28
38
|
...fill("clientContext", seat.clientContext),
|
|
@@ -39,15 +49,13 @@ export function applyParentSpecSeat(child, seat) {
|
|
|
39
49
|
...fill("promptBinding", seat.promptBinding),
|
|
40
50
|
...(seat.oneShot === true ? { oneShot: true } : {}),
|
|
41
51
|
...(seat.memoryPersistenceCapable === false ? { memoryPersistenceCapable: false } : fill("memoryPersistenceCapable", seat.memoryPersistenceCapable)),
|
|
42
|
-
...(seat.memoryOff === true ? { memory: memoryTurnedOff(child.memory) } : {}),
|
|
43
52
|
};
|
|
44
|
-
|
|
45
|
-
export function memoryTurnedOff(memory) {
|
|
46
|
-
return { ...(memory ?? {}), enabled: false };
|
|
53
|
+
return applyClampSeats(landed, clampFieldSeatsOf(seat));
|
|
47
54
|
}
|
|
48
55
|
const SEAT_FACTS_ON_CTX = ["principal", "oneShot", "onQuestion", "memoryPersistenceCapable"];
|
|
49
56
|
export function parentSpecSeatOfCtx(ctx) {
|
|
50
57
|
const seat = ctx.parentSpecSeat;
|
|
58
|
+
assertParentSpecSeatCurrent(seat);
|
|
51
59
|
const facts = SEAT_FACTS_ON_CTX.filter((k) => ctx[k] !== undefined);
|
|
52
60
|
if (seat === undefined) {
|
|
53
61
|
if (facts.length === 0)
|