@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
|
@@ -6,7 +6,7 @@ import { classicEventBase, failedHandlerClause, screenUserPrompt } from "../mods
|
|
|
6
6
|
import { buildHumanInputEvent, frameMidTurnUserInput, projectHumanInput } from "../human-input-projection.js";
|
|
7
7
|
import { injectionLaneOf, isSystemInjectionPriority, steerPriorityOf, SYSTEM_INJECTION_PRIORITIES } from "../task-notification.js";
|
|
8
8
|
import { deliverEngineNotice } from "../types.js";
|
|
9
|
-
import { inlineUntrusted, sanitizeUntrustedText } from "../untrusted-text.js";
|
|
9
|
+
import { inlineUntrusted, sanitizeUntrustedText, sentinelTagRefusal } from "../untrusted-text.js";
|
|
10
10
|
import { announceAcceptance, armAcceptance, nextHumanInputSeq } from "./steer-admission.js";
|
|
11
11
|
import { steerReplayRefusal } from "../steer-replay.js";
|
|
12
12
|
export function streamSteerVerb(input) {
|
|
@@ -18,7 +18,7 @@ export function streamSteerVerb(input) {
|
|
|
18
18
|
}
|
|
19
19
|
const trusted = options?.trusted ? true : false;
|
|
20
20
|
if (trusted && sanitizeUntrustedText(text) !== text) {
|
|
21
|
-
throw steeringError("trusted steering text
|
|
21
|
+
throw steeringError(sentinelTagRefusal("trusted steering text"), "steering.invalid_content");
|
|
22
22
|
}
|
|
23
23
|
const inputId = options?.inputId;
|
|
24
24
|
if (inputId !== undefined) {
|
|
@@ -34,8 +34,9 @@
|
|
|
34
34
|
* another spelling of a tool of the universe) — synchronous, like the phase that calls it.
|
|
35
35
|
*/
|
|
36
36
|
import type { AgentTool } from "../../internal/harness.js";
|
|
37
|
+
import { valveLeaves } from "../../agents/tool-filter.js";
|
|
37
38
|
import { type ProtocolId } from "../protocol-table.js";
|
|
38
|
-
import type { ToolLegKind,
|
|
39
|
+
import type { ToolLegKind, ToolSelectorLayer } from "../tool-face.js";
|
|
39
40
|
import { type ConstraintChainEntry } from "../tool-policy.js";
|
|
40
41
|
import type { TaskSpec } from "../types.js";
|
|
41
42
|
import type { CheckpointErrorReason } from "../checkpoint-store.js";
|
|
@@ -65,14 +66,15 @@ export declare function renamedDelegationMountSentence(...rosters: unknown[]): s
|
|
|
65
66
|
*/
|
|
66
67
|
export declare function refuseRenamedDelegationMounts(...rosters: unknown[]): void;
|
|
67
68
|
/**
|
|
68
|
-
* THE reading of what the delegation tools a run mounts hand their children, read after the run's own
|
|
69
|
-
* tool the
|
|
70
|
-
* unlistable pool of it belong to any universe. The tools themselves, every pool tool's name and alias (a declared
|
|
71
|
-
* roster included), and whether every one of those pools can be listed: a delegation tool whose factory injects tools
|
|
72
|
-
* declared roster has no listable pool (the static `tools` it was given included), so a name outside the listed ones
|
|
73
|
-
* own. This is the one place the pool side of both universes is defined; the list judgment below and the policy name
|
|
69
|
+
* THE reading of what the delegation tools a run mounts hand their children, read after the run's own tool valve: only a delegation
|
|
70
|
+
* tool the valve leaves (`leaves`, the valve's one reading — `valveLeaves`) counts — one it takes out hands nobody anything, and neither
|
|
71
|
+
* its pool names nor an unlistable pool of it belong to any universe. The tools themselves, every pool tool's name and alias (a declared
|
|
72
|
+
* `extraToolNames` roster included), and whether every one of those pools can be listed: a delegation tool whose factory injects tools
|
|
73
|
+
* per spawn with no declared roster has no listable pool (the static `tools` it was given included), so a name outside the listed ones
|
|
74
|
+
* may be one of its own. This is the one place the pool side of both universes is defined; the list judgment below and the policy name
|
|
75
|
+
* audit ask it.
|
|
74
76
|
*/
|
|
75
|
-
export declare function delegationPoolReading(callerTools: NonNullable<TaskSpec["tools"]>,
|
|
77
|
+
export declare function delegationPoolReading(callerTools: NonNullable<TaskSpec["tools"]>, leaves: ReturnType<typeof valveLeaves>): DelegationPoolReading;
|
|
76
78
|
/** The arms of this module's `config.tool_face_control` refusal that a resume carries before the claim as `detail.reason` of a `checkpoint.config_refused` — the same words
|
|
77
79
|
* ({@link CheckpointErrorReason}): a list the row recorded that is not a list / has a member that is not a string / has a spelling no tool name can have / is not in the
|
|
78
80
|
* spelling a row records, a record that is not one, a renamed delegation mount, an occupied table of declared names. */
|
|
@@ -123,8 +125,8 @@ export declare function boundOwnToolLists(record: unknown, own: {
|
|
|
123
125
|
readonly exclude: readonly string[] | undefined;
|
|
124
126
|
}): RunInternals["ownToolLists"];
|
|
125
127
|
export interface RunToolListsInput {
|
|
126
|
-
/** borrowed-readonly — the REBOUND spec: `agents` (the task's definitions)
|
|
127
|
-
spec: Pick<TaskSpec, "agents" | "tools">;
|
|
128
|
+
/** borrowed-readonly — the REBOUND spec: `agents` (the task's definitions), `tools` (the caller's tools and the mounted delegation tools) and `excludeAllTools` (the valve's whole-face switch, which takes the delegation tools out too). */
|
|
129
|
+
spec: Pick<TaskSpec, "agents" | "tools" | "excludeAllTools">;
|
|
128
130
|
/** borrowed-readonly — the assembled mount array BEFORE the selector's valve (names + aliases = the roster half of the universe). */
|
|
129
131
|
tools: ReadonlyArray<AgentTool>;
|
|
130
132
|
/** borrowed-readonly — the peers the task declares, per protocol of the protocol table (its MCP servers, its A2A peers): a namespaced
|
|
@@ -170,5 +172,5 @@ export declare function judgeRunToolLists(input: RunToolListsInput): void;
|
|
|
170
172
|
* `detail.reason: "near_miss"`) rather than kept as a deny that hides nothing. A name no tool answers to stays kept (a tool of that
|
|
171
173
|
* name may be mounted later), unannounced: the host wrote no spec this leg could name the list of.
|
|
172
174
|
*/
|
|
173
|
-
export declare function judgeHostToolCeiling(layers: readonly ToolSelectorLayer[], agent: Pick<TaskSpec, "tools" | "allowTools" | "excludeTools">, above?: readonly ToolSelectorLayer[]): void;
|
|
175
|
+
export declare function judgeHostToolCeiling(layers: readonly ToolSelectorLayer[], agent: Pick<TaskSpec, "tools" | "allowTools" | "excludeTools" | "excludeAllTools">, above?: readonly ToolSelectorLayer[]): void;
|
|
174
176
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { compileToolSelector, deniedProtocolTools, delegationListWhere, isCanonicalToolName, isToolSelectorLayer, listReaches, notAListSentence, toolListsDigest, notAStringSentence, readAllowedToolList, readDeniedEntry, readDeniedToolList } from "../../agents/tool-filter.js";
|
|
1
|
+
import { compileToolSelector, valveLeaves, deniedProtocolTools, delegationListWhere, isCanonicalToolName, isToolSelectorLayer, listReaches, notAListSentence, toolListsDigest, notAStringSentence, readAllowedToolList, readDeniedEntry, readDeniedToolList } from "../../agents/tool-filter.js";
|
|
2
2
|
import { readToolNameList, valueTypeLabel } from "../tool-name-list.js";
|
|
3
3
|
import { compileAllowList, inertEntryPhrase, renderListEntry, rootFacingToolNames } from "../allow-entry.js";
|
|
4
4
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
@@ -37,8 +37,8 @@ export function refuseRenamedDelegationMounts(...rosters) {
|
|
|
37
37
|
function poolOf(tools) {
|
|
38
38
|
return { tools, names: mountedToolNames([...tools.map((t) => ({ name: t.name })), ...tools.flatMap((t) => t.agentToolPool ?? [])]), complete: tools.every((t) => t.agentToolPool !== undefined) };
|
|
39
39
|
}
|
|
40
|
-
export function delegationPoolReading(callerTools,
|
|
41
|
-
return poolOf(callerTools.filter((t) => t.agentToolFaces !== undefined &&
|
|
40
|
+
export function delegationPoolReading(callerTools, leaves) {
|
|
41
|
+
return poolOf(callerTools.filter((t) => t.agentToolFaces !== undefined && leaves(t)));
|
|
42
42
|
}
|
|
43
43
|
function peersOf(known, declaredPeers) {
|
|
44
44
|
const peers = new Set(PROTOCOL_TABLE.flatMap((ns) => (declaredPeers[ns.id] ?? []).map((p) => mintNamespacePrefix(ns, p.name))));
|
|
@@ -275,7 +275,8 @@ export function judgeRunToolLists(input) {
|
|
|
275
275
|
const by = [...deniedBy(true, ownWhere ?? "this run's own excludeTools"), ...deniedBy(false, "an inherited list (the spawning run's excludeTools, or one it inherits)")];
|
|
276
276
|
throw refused(`This kind of leg (${input.legs.join(", ")}) relies on ${names.join(", ")}, but ${by.join(" and ")} — the leg cannot work without ${one ? "it" : "them"}. Remove the entry from the list that names it.`, "config.tool_face_control", "protocol_denied");
|
|
277
277
|
}
|
|
278
|
-
const
|
|
278
|
+
const selector = compileToolSelector(input.layers, input.legs);
|
|
279
|
+
const pool = delegationPoolReading(spec.tools ?? [], valveLeaves(spec, selector));
|
|
279
280
|
const mounted = mountedToolNames([...tools, ...(spec.tools ?? [])]);
|
|
280
281
|
if (!input.judgedUpstream) {
|
|
281
282
|
const root = rootFacingUniverse(input.ownBy !== undefined ? new Set([...mounted, input.ownBy.toolName]) : mounted, pool, input.declaredPeers);
|
|
@@ -310,7 +311,8 @@ export function judgeHostToolCeiling(layers, agent, above = []) {
|
|
|
310
311
|
layers.forEach((layer, i) => readSelectorLayer(layer, where(i), () => where(i), false));
|
|
311
312
|
const callerTools = agent.tools ?? [];
|
|
312
313
|
const own = { ...(agent.allowTools != null ? { allow: agent.allowTools } : {}), deny: agent.excludeTools ?? [] };
|
|
313
|
-
const
|
|
314
|
+
const selector = compileToolSelector([...above, ...layers, own], ["delegated"]);
|
|
315
|
+
const pool = delegationPoolReading(callerTools, valveLeaves(agent, selector));
|
|
314
316
|
const universe = rootFacingUniverse(mountedToolNames(callerTools), pool, { mcp: undefined, a2a: undefined });
|
|
315
317
|
const unannounced = () => undefined;
|
|
316
318
|
layers.forEach((layer, i) => {
|
|
@@ -110,8 +110,11 @@ export interface SkillListingEntry {
|
|
|
110
110
|
* and the tool, so what the prompt promises is exactly what the tool serves. Each field is READ ONCE, BY NAME, and
|
|
111
111
|
* both consumers see the copy: the gate screens this list while the invoke substitutes from it, so a `get baseDir()`
|
|
112
112
|
* answering those two reads differently passed a screen that measured a value the model never received — and a rest
|
|
113
|
-
* copy would silently drop an INHERITED or non-enumerable list. The two tables are read by {@link readSkillTable}.
|
|
114
|
-
|
|
113
|
+
* copy would silently drop an INHERITED or non-enumerable list. The two tables are read by {@link readSkillTable}.
|
|
114
|
+
*
|
|
115
|
+
* The sorted view of {@link readSkillsSeat} (skills-seat.ts), which holds the seat's one reading — total over what a caller can
|
|
116
|
+
* hand it, and once. */
|
|
117
|
+
export declare function normalizeSkills(skills: unknown): SkillLike[];
|
|
115
118
|
/** [c209-C] The skills listing's lead line — single-sourced so the run loop's durable-resume
|
|
116
119
|
* transcript probe (MED-3② skills arm, runtask) matches EXACTLY what the initial frame carries
|
|
117
120
|
* (probing the bare `<skills>` fence would be more collision-prone in model-quoted text). */
|
|
@@ -5,6 +5,7 @@ import { SKILL_LISTING_DEFAULT_BUDGET, SKILL_LISTING_DESC_MAX_CHARS_DEFAULT } fr
|
|
|
5
5
|
import { readSkillTable, skillNamedBy } from "../skill-grant.js";
|
|
6
6
|
import { toolFace } from "../tool-catalog-entries.js";
|
|
7
7
|
import { substituteSkillRoot, substituteSkillRootBounded } from "./skill-base-dir.js";
|
|
8
|
+
import { readSkillsSeat } from "./skills-seat.js";
|
|
8
9
|
import { foldListingWithin } from "./listing-fold.js";
|
|
9
10
|
export const OUTPUT_TOOL_NAME = "StructuredOutput";
|
|
10
11
|
export const REPORT_BLOCKED_TOOL_NAME = "ReportBlocked";
|
|
@@ -109,18 +110,7 @@ function skillFilesSuffix(files) {
|
|
|
109
110
|
return ` [files: ${shown.join(", ")}${more > 0 ? `, +${more} more` : ""}]`;
|
|
110
111
|
}
|
|
111
112
|
export function normalizeSkills(skills) {
|
|
112
|
-
|
|
113
|
-
const out = [];
|
|
114
|
-
for (const s of skills ?? []) {
|
|
115
|
-
if (!seen.has(s.name)) {
|
|
116
|
-
seen.add(s.name);
|
|
117
|
-
const { name, description, content, allowedTools, disallowedTools, files, baseDir, ...rest } = s;
|
|
118
|
-
void rest;
|
|
119
|
-
const [allowed, denied] = [readSkillTable(allowedTools), readSkillTable(disallowedTools)];
|
|
120
|
-
out.push({ name, description, content, ...(allowed !== undefined ? { allowedTools: allowed } : {}), ...(denied !== undefined ? { disallowedTools: denied } : {}), ...(files !== undefined ? { files } : {}), ...(baseDir !== undefined ? { baseDir } : {}) });
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return out.toSorted((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
113
|
+
return readSkillsSeat(skills).toSorted((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
124
114
|
}
|
|
125
115
|
export const SKILLS_LISTING_PROBE_HEADER = "The following skills are available for this task.";
|
|
126
116
|
export function skillListingLine(s, descMaxChars = SKILL_LISTING_DESC_MAX_CHARS_DEFAULT) {
|
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
* tool name like `allowTools` / `toolAxes`). Validated against the MATERIALIZED schema at every listing
|
|
5
5
|
* (the first mount and every RefreshMcpTools): `pathTarget.param` must be a top-level property; an
|
|
6
6
|
* `approvalCard` must find the keys the card needs; a `ruleFace` may only name scalar keys; `family`
|
|
7
|
-
* must be a member of the closed set
|
|
7
|
+
* must be a member of the closed set; every `resultCards` entry must live under the tool's own card namespace.
|
|
8
|
+
* A failing overlay does NOT mount — the tool mounts BARE (no
|
|
8
9
|
* face) and the leg announces `config.tool_face_invalid` once per tool; a `toolFaces` key naming a
|
|
9
10
|
* tool the listing does not carry announces `config.tool_face_undeclared` once per name. Never a
|
|
10
11
|
* silent partial application: an overlay is one declaration, applied whole or not at all.
|
|
11
12
|
*
|
|
12
13
|
* Prepare-path machinery (layer 1): pure over the tool objects and the server specs; the notice sink
|
|
13
|
-
* is a parameter.
|
|
14
|
+
* is a parameter. The declaration itself is read once, by `readToolFaces` (`core/tool-face-reader.ts`), at the preparation door and at the
|
|
15
|
+
* materialization entrance; the specs this file consumes carry that reader's copy, never the caller's object.
|
|
14
16
|
*/
|
|
15
17
|
import type { AgentTool } from "../../internal/harness-types.js";
|
|
16
18
|
import type { McpServerSpec } from "../mcp-server-spec.js";
|
|
@@ -20,10 +22,24 @@ import { type EngineNotice } from "../engine-notice.js";
|
|
|
20
22
|
* card's full schema; this is the pre-filter the overlay is validated against). */
|
|
21
23
|
export declare const APPROVAL_CARD_REQUIRED_KEYS: Readonly<Record<ToolApprovalCard, readonly string[]>>;
|
|
22
24
|
export type McpToolFace = NonNullable<McpServerSpec["toolFaces"]>[string];
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
+
/** The tool a face rides on, as far as the judge needs to know it: its name (a reserved approval card belongs to the engine's own tool of that
|
|
26
|
+
* name) and, when the caller holds the tool's card namespace, the `cardId` its `resultCards` must live under (`<cardId>/<card>`). */
|
|
27
|
+
export interface FaceTool {
|
|
25
28
|
readonly toolName: string;
|
|
26
|
-
|
|
29
|
+
readonly cardId?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Why an overlay is refused — a closed reason list, each a distinct declaration mistake. */
|
|
32
|
+
export declare function toolFaceProblem(face: McpToolFace, schema: AgentTool["parameters"], tool?: FaceTool): string | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* The one judge of a face. With the tool's materialized `schema` it is {@link toolFaceProblem}: the declaration against the
|
|
35
|
+
* schema it rides on. With no schema it is the same judge over the DECLARATION ALONE (`readToolFaces`, `core/tool-face-reader.ts`): every
|
|
36
|
+
* check that needs the schema's keys (a path target's `param` / `patternParam`, an approval card's required keys, the names a summary or a
|
|
37
|
+
* rule face lists) waits for the listing; the closed words, the bounds and the cross-member rules do not need it and are the same
|
|
38
|
+
* checks, in the same order, with the same sentences. A face this judges is a well-typed one (the reader types it first). A tool that
|
|
39
|
+
* holds its card namespace (`tool.cardId`) has its `resultCards` held to it here too, so a caller's face and a server's face are
|
|
40
|
+
* judged by this one function, not by a rule beside it.
|
|
41
|
+
*/
|
|
42
|
+
export declare function faceProblem(face: McpToolFace, schema: AgentTool["parameters"] | undefined, tool?: FaceTool): string | undefined;
|
|
27
43
|
export interface ApplyToolFacesInput {
|
|
28
44
|
/** The materialized tools of ONE server (namespaced names). */
|
|
29
45
|
tools: readonly AgentTool[];
|
|
@@ -38,5 +54,7 @@ export interface ApplyToolFacesInput {
|
|
|
38
54
|
* untyped carry `defineTool` uses, so the roster reads it off the instance). A face that does NOT fit the materialized
|
|
39
55
|
* schema is a bad declaration: the tool is NOT mounted on this leg (announced once, `config.tool_face_invalid`) —
|
|
40
56
|
* mounting it bare would silently drop the write protection the operator declared for it (an MCP name has no catalog
|
|
41
|
-
* floor), and a schema refresh that invalidates only a display hint must fail loud, never open.
|
|
57
|
+
* floor), and a schema refresh that invalidates only a display hint must fail loud, never open. The faces it reads are the
|
|
58
|
+
* server entry's own: the reader's copy of the declaration (`readToolFaces`), put there by the preparation door or the
|
|
59
|
+
* materialization entrance, never a caller's object. */
|
|
42
60
|
export declare function applyMcpToolFaces(input: ApplyToolFacesInput): AgentTool[];
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { MCP_NAMESPACE } from "../protocol-table.js";
|
|
2
2
|
import { mintNamespacePrefix } from "../protocol-naming.js";
|
|
3
3
|
import { RESERVED_APPROVAL_CARDS, TOOL_APPROVAL_CARDS, TOOL_FAMILIES, TOOL_PATH_ABSENCES, TOOL_PATH_ACCESSES, TOOL_PATH_BASES, RENDER_HINT_ACTIVITY_MAX_CHARS, RENDER_HINT_MAX_CHARS, RENDER_HINT_MAX_LIST, TOOL_KEY_MAX_CHARS, } from "../tool-face.js";
|
|
4
|
-
import { engineCardOf, inputKeysOf } from "../tool-roster.js";
|
|
4
|
+
import { engineCardOf, inputKeysOf, offendingResultCard, protocolToolOf, rosterCardId } from "../tool-roster.js";
|
|
5
|
+
import { engineCardTypes } from "../tool-registry.js";
|
|
5
6
|
import { deliverEngineNotice } from "../engine-notice.js";
|
|
6
7
|
export const APPROVAL_CARD_REQUIRED_KEYS = Object.freeze({
|
|
7
8
|
"file-edit": ["file_path"],
|
|
@@ -14,17 +15,20 @@ export const APPROVAL_CARD_REQUIRED_KEYS = Object.freeze({
|
|
|
14
15
|
generic: [],
|
|
15
16
|
});
|
|
16
17
|
export function toolFaceProblem(face, schema, tool) {
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
return faceProblem(face, schema, tool);
|
|
19
|
+
}
|
|
20
|
+
export function faceProblem(face, schema, tool) {
|
|
21
|
+
const bound = schema === undefined ? undefined : inputKeysOf(schema);
|
|
22
|
+
const top = bound === undefined ? undefined : new Set(bound.keys.map((k) => k.name));
|
|
19
23
|
if (face.family !== undefined && !TOOL_FAMILIES.includes(face.family))
|
|
20
24
|
return `family ${JSON.stringify(face.family)} is outside the closed set`;
|
|
21
25
|
const overlong = (label, values) => {
|
|
22
26
|
const k = values.find((v) => v.length > TOOL_KEY_MAX_CHARS);
|
|
23
27
|
return k === undefined ? undefined : `${label} ${JSON.stringify(k.slice(0, 40) + "…")} is ${k.length} characters; a roster key is at most ${TOOL_KEY_MAX_CHARS}`;
|
|
24
28
|
};
|
|
25
|
-
const vocabulary = new Set(scalar);
|
|
29
|
+
const vocabulary = new Set(bound?.scalar);
|
|
26
30
|
if (face.pathTarget !== undefined) {
|
|
27
|
-
if (typeof face.pathTarget.param !== "string" || !top.has(face.pathTarget.param))
|
|
31
|
+
if (top !== undefined && (typeof face.pathTarget.param !== "string" || !top.has(face.pathTarget.param)))
|
|
28
32
|
return `pathTarget.param ${JSON.stringify(face.pathTarget.param)} is not a top-level property of the tool's schema`;
|
|
29
33
|
if (!TOOL_PATH_ACCESSES.includes(face.pathTarget.access))
|
|
30
34
|
return `pathTarget.access ${JSON.stringify(face.pathTarget.access)} is outside the closed set`;
|
|
@@ -40,7 +44,7 @@ export function toolFaceProblem(face, schema, tool) {
|
|
|
40
44
|
return `pathTarget.absent "base" needs pathTarget.access "read" — it says the call is about the whole base directory when the slot is empty, which is a search SCOPE; a write with no path names no file, and the containment fences judge a write on its own target`;
|
|
41
45
|
const patternParam = face.pathTarget.patternParam;
|
|
42
46
|
if (patternParam !== undefined) {
|
|
43
|
-
if (typeof patternParam !== "string" || !top.has(patternParam))
|
|
47
|
+
if (top !== undefined && (typeof patternParam !== "string" || !top.has(patternParam)))
|
|
44
48
|
return `pathTarget.patternParam ${JSON.stringify(patternParam)} is not a top-level property of the tool's schema`;
|
|
45
49
|
if (absent !== "base")
|
|
46
50
|
return `pathTarget.patternParam ${JSON.stringify(patternParam)} is declared but pathTarget.absent is ${JSON.stringify(absent ?? "none")} — the pattern base is only ever read for an absent slot, so this declaration would be inert`;
|
|
@@ -62,7 +66,7 @@ export function toolFaceProblem(face, schema, tool) {
|
|
|
62
66
|
return `renderHints.approvalCard ${JSON.stringify(card)} is outside the closed set`;
|
|
63
67
|
if (RESERVED_APPROVAL_CARDS.includes(card) && (tool === undefined || engineCardOf(tool) !== card))
|
|
64
68
|
return `renderHints.approvalCard ${JSON.stringify(card)} is reserved for the engine's own tool that owns it; a declared tool takes another card or none`;
|
|
65
|
-
const missing = APPROVAL_CARD_REQUIRED_KEYS[card].filter((k) => !top.has(k));
|
|
69
|
+
const missing = top === undefined ? [] : APPROVAL_CARD_REQUIRED_KEYS[card].filter((k) => !top.has(k));
|
|
66
70
|
if (missing.length > 0)
|
|
67
71
|
return `renderHints.approvalCard ${JSON.stringify(card)} needs ${missing.join(", ")} on the tool's schema`;
|
|
68
72
|
}
|
|
@@ -77,16 +81,21 @@ export function toolFaceProblem(face, schema, tool) {
|
|
|
77
81
|
const long = overlong("renderHints.summaryParams", hints.summaryParams ?? []) ?? overlong("renderHints.resultCards", hints.resultCards ?? []);
|
|
78
82
|
if (long !== undefined)
|
|
79
83
|
return long;
|
|
80
|
-
const
|
|
84
|
+
const foreignCard = tool?.cardId === undefined ? undefined : offendingResultCard(hints, tool.cardId, engineCardTypes());
|
|
85
|
+
if (foreignCard !== undefined)
|
|
86
|
+
return `renderHints.resultCards names ${JSON.stringify(foreignCard.slice(0, 80))}, outside the tool's own card namespace "${tool.cardId}/<card>" (engine cards and other contracts' namespaces are reserved)`;
|
|
87
|
+
const stray = top === undefined ? undefined : (hints.summaryParams ?? []).find((p) => !top.has(p));
|
|
81
88
|
if (stray !== undefined)
|
|
82
89
|
return `renderHints.summaryParams names ${JSON.stringify(stray)}, which is not a top-level property`;
|
|
83
90
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
if (top !== undefined) {
|
|
92
|
+
for (const p of face.ruleFace?.params ?? [])
|
|
93
|
+
if (!vocabulary.has(p))
|
|
94
|
+
return `ruleFace.params names ${JSON.stringify(p)}, which is neither a scalar top-level property nor the declared path target`;
|
|
95
|
+
for (const p of face.ruleFace?.primaryParams ?? [])
|
|
96
|
+
if (!vocabulary.has(p))
|
|
97
|
+
return `ruleFace.primaryParams names ${JSON.stringify(p)}, which is neither a top-level property nor the declared path target`;
|
|
98
|
+
}
|
|
90
99
|
const long = overlong("ruleFace.params", face.ruleFace?.params ?? []) ?? overlong("ruleFace.primaryParams", face.ruleFace?.primaryParams ?? []);
|
|
91
100
|
if (long !== undefined)
|
|
92
101
|
return long;
|
|
@@ -121,7 +130,7 @@ export function applyMcpToolFaces(input) {
|
|
|
121
130
|
if (raw === undefined || face === undefined)
|
|
122
131
|
return t;
|
|
123
132
|
const hit = { raw, face };
|
|
124
|
-
const problem = toolFaceProblem(hit.face, t.parameters, { toolName: t.name });
|
|
133
|
+
const problem = toolFaceProblem(hit.face, t.parameters, { toolName: t.name, cardId: rosterCardId("mcp", t.name, input.server.name, protocolToolOf(t.name), "") });
|
|
125
134
|
if (problem !== undefined) {
|
|
126
135
|
const key = `invalid:${t.name}`;
|
|
127
136
|
if (!input.announced.has(key)) {
|
|
@@ -14,7 +14,7 @@ import type { OnElicit } from "./mcp-server-spec.js";
|
|
|
14
14
|
import type { Brain, ModelRef, ModelRoles } from "./model-seat.js";
|
|
15
15
|
import type { RuntimeCaps, WorkflowGovernanceBaseline } from "./runtime-caps.js";
|
|
16
16
|
/**
|
|
17
|
-
* parity-204 — structured `RunnerDeps.loadProjectMemory` return (backward-compatible: a bare
|
|
17
|
+
* parity-204 — structured `RunnerDeps.loadProjectMemory` return (backward-compatible, RL-1336-project-memory-bare: a bare
|
|
18
18
|
* `string | null` keeps its exact historical meaning). Adds the CC 2.1.204 `seededFromContext`
|
|
19
19
|
* seam (cc204-bundle @17917159: CC preloads readFileState for CLAUDE.md/nested-memory files it
|
|
20
20
|
* placed in context, and a DEFAULT whole-file Read of an unchanged seeded file answers with the
|
|
@@ -73,8 +73,8 @@ export interface ResumePreflightInfo {
|
|
|
73
73
|
* the resume entry's identity-continuity rung already refused a contradicting supplied principal
|
|
74
74
|
* before this hook runs, so a present value IS the resumed leg's identity. */
|
|
75
75
|
principal?: string;
|
|
76
|
-
/** provider / deviceId / mountPath — the placement facts. */
|
|
77
|
-
workspaceHandle?: import("./remote-env.js").WorkspaceHandle
|
|
76
|
+
/** provider / deviceId / mountPath — the placement facts: the row handle's one frozen copy (as `resumeWorkspace`, `priorHandle`). */
|
|
77
|
+
workspaceHandle?: Readonly<import("./remote-env.js").WorkspaceHandle>;
|
|
78
78
|
gateKind: import("./checkpoint-store.js").CheckpointGate["kind"];
|
|
79
79
|
}
|
|
80
80
|
/** design/380 O2 — a {@link RunnerDeps.resumePreflight} answer. */
|
|
@@ -141,10 +141,8 @@ export interface RunnerDeps {
|
|
|
141
141
|
* probe must not brick every MCP call) with a once-per-MATERIALIZATION `mcp.revocation_probe_failed`
|
|
142
142
|
* notice (a resume re-materializes and may announce again — the standing condition is re-news at
|
|
143
143
|
* each fresh mount, never per-call). The notice is a deployment wiring fact: `detail: { message }`
|
|
144
|
-
* only, no session attribution, `"operator"` audience by its explicit {@link NOTICE_AUDIENCE}
|
|
145
|
-
*
|
|
146
|
-
* audience-defaulted any more) — a
|
|
147
|
-
* wire projector forwards it operator-tier and needs no per-session de-duplication of its own.
|
|
144
|
+
* only, no session attribution, `"operator"` audience by its explicit {@link NOTICE_AUDIENCE} row — a wire projector
|
|
145
|
+
* forwards it operator-tier and needs no per-session de-duplication of its own.
|
|
148
146
|
* The probe's second argument, `{ fingerprint }`, is passed exactly when the server's declaration carries one.
|
|
149
147
|
*/
|
|
150
148
|
mcpRevocations?: import("./mcp-server-spec.js").McpRevocationLedger;
|
|
@@ -159,10 +157,11 @@ export interface RunnerDeps {
|
|
|
159
157
|
*/
|
|
160
158
|
rosterStore?: import("../agents/roster-store.js").RosterStore;
|
|
161
159
|
/**
|
|
162
|
-
* The center prompt-artifact source (artifact
|
|
163
|
-
* candidate a top-level session adopts at session start and at a compaction; `get(digest)` resolves a PINNED center
|
|
160
|
+
* The center prompt-artifact source (artifact v3 only — a v2 body is refused `schema`, INTEGRATION-CORE §12.11).
|
|
161
|
+
* `current()` supplies the verified candidate a top-level session adopts at session start and at a compaction; `get(digest)` resolves a PINNED center
|
|
164
162
|
* layer on resume (a miss is fail-loud `prompt.snapshot_unavailable` — core never recomposes a hybrid from newer
|
|
165
|
-
* content
|
|
163
|
+
* content; a copy the engine refuses is told apart from a missing one, in the failure's sentence and on `onError`);
|
|
164
|
+
* `sourceState()` is the tri-state every adoption decision keys on. What a source hands a run is re-checked
|
|
166
165
|
* before it is adopted. Core bundles `CenterPromptSource` (+ memory/file artifact & source-state stores); a server
|
|
167
166
|
* feeds it published artifacts via `applySnapshot`. Omitted = no center layer.
|
|
168
167
|
*/
|
|
@@ -341,6 +340,9 @@ export interface RunnerDeps {
|
|
|
341
340
|
* to CONTINUE instead — zero capture and zero out-of-policy running, availability paid).
|
|
342
341
|
*/
|
|
343
342
|
memoryCapturePolicy?: "open" | "governed" | "capture-required";
|
|
343
|
+
/** The deployment's cross-boundary posture, one of {@link import("./cross-boundary-taint.js").CROSS_BOUNDARY_POSTURES} (who is hurt when a tree that
|
|
344
|
+
* executes on a target device reaches past it). Absent reads `"single_user"`; any other value refuses the prepare, and a resume before its claim (`config.cross_boundary_posture`). */
|
|
345
|
+
crossBoundaryPosture?: "single_user" | "multi_tenant";
|
|
344
346
|
/**
|
|
345
347
|
* design/383 §2.1b — an optional host-supplied carrier for the session capture opt-out record
|
|
346
348
|
* (per memory plane, keyed by that plane's control dir). Absent = the control-plane file trio
|
|
@@ -961,6 +963,19 @@ export interface RunnerDeps {
|
|
|
961
963
|
* everywhere (mode parity, the CC default). Inert without {@link peerDirectory}.
|
|
962
964
|
*/
|
|
963
965
|
crossSessionInbound?: import("../agents/cross-session-judge.js").CrossSessionInboundSettingLayers | (() => import("../agents/cross-session-judge.js").CrossSessionInboundSettingLayers);
|
|
966
|
+
/**
|
|
967
|
+
* WHO consumes this deployment's principal inbox (`principal.inbox`, where the
|
|
968
|
+
* organization's delivery gate appends cross-principal letters; the mailbox contract's fourth chain).
|
|
969
|
+
* Absent = no consumer, no lane (byte for byte as before); a deployment that mounts a gate DECLARES
|
|
970
|
+
* `{ assistant: "<agent handle>" }` (the scope's assistant is the only consumer; no terminal leg touches the
|
|
971
|
+
* box). `"terminals"` (each terminal drains the box as a second lane) is refused until held decisions are
|
|
972
|
+
* shared across terminals (`detail.reason: "terminals_unsupported"`). Letters are judged on the principal's
|
|
973
|
+
* `crossSessionInbound` layers (managed, user), held when unset. ANY other value fails the prepare of a leg
|
|
974
|
+
* that drains a session box with `config.principal_inbox_consumer_invalid` (`detail.reason: "malformed"`).
|
|
975
|
+
*/
|
|
976
|
+
principalInboxConsumer?: "terminals" | {
|
|
977
|
+
assistant: string;
|
|
978
|
+
};
|
|
964
979
|
/**
|
|
965
980
|
* design/385 §4.4 (slice 4) — this deployment's `dialogExpiry` (CC settings key, verbatim vocabulary
|
|
966
981
|
* `"60s" | "5m" | "10m" | "never"`, default `"5m"`): how long a HELD cross-session message whose cause
|
|
@@ -1286,18 +1301,18 @@ export interface RunnerDeps {
|
|
|
1286
1301
|
* summaries) is invisible without this and lets a session grow until it tops the window.
|
|
1287
1302
|
* - `"prompt-cache"` — a prefix-cache hazard on the wire: a detected cache break (design/31), or a
|
|
1288
1303
|
* mis-declared/mismatched `promptCacheFamily`. The prefix cache will miss. Log/alert on both.
|
|
1289
|
-
* - `"prompt-constitution"` — a prompt overlay did not take effect as written: a later source (or a later
|
|
1290
|
-
*
|
|
1291
|
-
*
|
|
1292
|
-
*
|
|
1293
|
-
*
|
|
1294
|
-
*
|
|
1295
|
-
*
|
|
1296
|
-
*
|
|
1297
|
-
* -
|
|
1298
|
-
*
|
|
1299
|
-
* broadest class by call-site count — most
|
|
1300
|
-
* the task.
|
|
1304
|
+
* - `"prompt-constitution"` — a prompt overlay did not take effect as written: a later source (or a later declaration in the same source) superseded
|
|
1305
|
+
* it on the same target, its target was not in this run's prompt, or a mods handler's `prompt.compose` answer was skipped (it rewrote another's
|
|
1306
|
+
* overlay, or wrote what the band table does not grant its seat); each overlay is named once per run. The center prompt too: a pinned session's
|
|
1307
|
+
* stored artifact refused or unreadable (it fails `prompt.snapshot_unavailable`), a fresh session's candidate that does not verify, and a
|
|
1308
|
+
* `CenterPromptSource` boot restore with no usable copy (`sessionId: ""`, `classification: "center-source-restore"`) — that last line only when the
|
|
1309
|
+
* host passes this same sink to `CenterPromptSource` as its own `onError` (the source restores at boot, apart from any Runner; given none, it is silent).
|
|
1310
|
+
* - `"degraded"` — the task kept running with a capability quietly reduced: a question auto-answered with no human
|
|
1311
|
+
* present, a skipped env git snapshot, a lost checkpoint-put confirmation, an unroutable descendant notification, and
|
|
1312
|
+
* similar best-effort arms. The run proceeds; the reduced arm is what is being disclosed (`classification` names it).
|
|
1313
|
+
* - `"config"` — a deployment-wiring problem detected while preparing or tearing down a task: tool mount conflicts,
|
|
1314
|
+
* refused/ignored knob values, gate-off notices, store/env teardown legs. The broadest class by call-site count — most
|
|
1315
|
+
* misconfigurations announce here rather than failing the task.
|
|
1301
1316
|
* - `"memory"` — a post-task memory-consolidation pass failed or skipped a malformed reconcile
|
|
1302
1317
|
* decision (design/41). Best-effort: the notes the model saved are kept; the task still succeeds.
|
|
1303
1318
|
* - `"mcp"` — an MCP server failed to connect / list its tools and was skipped (fail-open, design/29);
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* chain); the real isolation boundary is the executionEnv, never these rules.
|
|
28
28
|
*/
|
|
29
29
|
import { compileAllowList, type AllowEntryInert, type AllowEntryInertDetail, type AllowEntryInertReason } from "./allow-entry.js";
|
|
30
|
+
import type { EngineNotice } from "./engine-notice.js";
|
|
30
31
|
/** The per-session rules. All optional; an absent bucket imposes no constraint of that kind. */
|
|
31
32
|
export interface SessionPermissionRules {
|
|
32
33
|
/** If set, ONLY the calls these entries admit are allowed — a narrowing allowlist: a call no entry admits is refused.
|
|
@@ -244,6 +245,24 @@ export declare function compileSessionRuleBucket(rules: SessionRulesInGrammar, f
|
|
|
244
245
|
* to make a parenthesized one the rule it now spells, or (`*`, which is no allow rule in any grammar) to leave it out.
|
|
245
246
|
*/
|
|
246
247
|
export declare function earlierGrammarAdvisory(sessionId: string, entries: readonly string[], field: SessionRuleEntryField, grammar: number): string;
|
|
248
|
+
/** The reader's word for one entry an earlier grammar reads as nothing: `no_rule` — this engine's rule grammar reads it as no
|
|
249
|
+
* rule; `named_no_tool` — a grammar-0 allow entry the bare-name comparison of its day read as naming no tool. */
|
|
250
|
+
export type EarlierGrammarReader = "no_rule" | "named_no_tool";
|
|
251
|
+
/**
|
|
252
|
+
* The notice for the entries of one bucket a stored row's earlier grammar reads as nothing (`config.session_rules_earlier_grammar`,
|
|
253
|
+
* audience `user` — the session's rules are what the person's calls are judged by): the message is {@link earlierGrammarAdvisory}
|
|
254
|
+
* verbatim, and `detail` carries the same facts for a machine — `bucket` (the field), `storedGrammar` (the row's), `entries` (every
|
|
255
|
+
* entry, each as `noticeRuleText` hands rule text to a notice, with its reader's word), `rewrite` (the way out: an operator write of
|
|
256
|
+
* a new value without the stored row's rev, which stamps `stampsGrammar`), `rulesSessionId` (whose rules — an ancestor's on a
|
|
257
|
+
* delegated child's inherited layer) and `sessionId` (the run that read them).
|
|
258
|
+
*/
|
|
259
|
+
export declare function earlierGrammarNotice(input: {
|
|
260
|
+
rulesSessionId: string;
|
|
261
|
+
sessionId: string;
|
|
262
|
+
entries: readonly string[];
|
|
263
|
+
field: SessionRuleEntryField;
|
|
264
|
+
grammar: number;
|
|
265
|
+
}): EngineNotice;
|
|
247
266
|
/** The clause a run-time refusal carries when the allowlist it judged by holds entries its earlier grammar reads as nothing
|
|
248
267
|
* ({@link compileSessionRuleBucket}; `grammar` = the row's): the grammar the rules are stored in, then which entries name no tool
|
|
249
268
|
* there (grammar 0: `*` by its spelling, the parenthesized ones counted) and how many this engine's grammar reads as no rule —
|
|
@@ -4,6 +4,7 @@ import { NAMESPACED_NAME_SHAPES } from "./protocol-table.js";
|
|
|
4
4
|
import { callerToolNameProblem } from "./caller-tool-name.js";
|
|
5
5
|
import { compileAllowList, compiledEntryName, inertEntryPhrase, readRuleEntry, renderListEntry, rootFacingToolNames } from "./allow-entry.js";
|
|
6
6
|
import { valueTypeLabel } from "./tool-name-list.js";
|
|
7
|
+
import { noticeRuleText } from "./permission-rule-model.js";
|
|
7
8
|
const SESSION_RULE_BUCKETS = { toolAllow: "allow", toolDeny: "deny", allowDirs: "dirs" };
|
|
8
9
|
const BUCKETS = Object.keys(SESSION_RULE_BUCKETS);
|
|
9
10
|
const ENTRY_FIELDS = BUCKETS.filter((f) => SESSION_RULE_BUCKETS[f] !== "dirs");
|
|
@@ -162,11 +163,30 @@ function shownEntries(entries, render) {
|
|
|
162
163
|
}
|
|
163
164
|
const REWRITE_THROUGH = `through this engine (an operator write of a new value without the stored row's rev; the write stamps grammar ${SESSION_RULES_GRAMMAR})`;
|
|
164
165
|
export function earlierGrammarAdvisory(sessionId, entries, field, grammar) {
|
|
165
|
-
const
|
|
166
|
-
const
|
|
166
|
+
const read = earlierGrammarReadings(entries, field);
|
|
167
|
+
const noRule = read.filter((r) => r.reader === "no_rule").map((r) => r.entry);
|
|
168
|
+
const namedNoTool = read.filter((r) => r.reader === "named_no_tool").map((r) => r.entry);
|
|
167
169
|
const sentences = [...(namedNoTool.length > 0 ? [namedNoToolInGrammar0(namedNoTool)] : []), ...(noRule.length > 0 ? [noRuleInThisGrammar(noRule, field, grammar)] : [])];
|
|
168
170
|
return `session permission rules of session ${JSON.stringify(sessionId)}: ${sentences.join(" ")}`;
|
|
169
171
|
}
|
|
172
|
+
function earlierGrammarReadings(entries, field) {
|
|
173
|
+
return entries.map((entry) => ({ entry, reader: readsAsNoRule(entry, field) ? "no_rule" : "named_no_tool" }));
|
|
174
|
+
}
|
|
175
|
+
export function earlierGrammarNotice(input) {
|
|
176
|
+
const { rulesSessionId, sessionId, entries, field, grammar } = input;
|
|
177
|
+
return {
|
|
178
|
+
code: "config.session_rules_earlier_grammar",
|
|
179
|
+
message: earlierGrammarAdvisory(rulesSessionId, entries, field, grammar),
|
|
180
|
+
detail: {
|
|
181
|
+
bucket: field,
|
|
182
|
+
storedGrammar: grammar,
|
|
183
|
+
entries: earlierGrammarReadings(entries, field).map((r) => ({ entry: noticeRuleText(r.entry), reader: r.reader })),
|
|
184
|
+
rewrite: { by: "operator_write_without_rev", stampsGrammar: SESSION_RULES_GRAMMAR },
|
|
185
|
+
rulesSessionId,
|
|
186
|
+
sessionId,
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
170
190
|
function namedNoToolInGrammar0(entries) {
|
|
171
191
|
const one = entries.length === 1;
|
|
172
192
|
const wildcard = entries.some(readsAsWildcard);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SessionRepo } from "../internal/harness.js";
|
|
1
|
+
import { type SessionPlacementRecord, type SessionRepo } from "../internal/harness.js";
|
|
2
2
|
import { type AcquiredSession, type PlacedSessionRow, type SessionPlacement, type SessionStore, type SessionStoreSummary } from "./session.js";
|
|
3
3
|
import type { StoreDurability } from "./checkpoint-store.js";
|
|
4
4
|
import { SESSION_DEFAULT_TTL_DAYS } from "../config/defaults.js";
|
|
@@ -52,6 +52,37 @@ export interface TtlSessionStoreOptions {
|
|
|
52
52
|
};
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* The one placement admission of a session store's `acquire` — every backend that declares the placement partition
|
|
57
|
+
* judges each resolved session through it (this module's {@link TtlSessionStore} on its four resolution paths: cache
|
|
58
|
+
* hit, pending-promise inherit, open, idempotent re-create), so no backend writes the two directions a second time.
|
|
59
|
+
*
|
|
60
|
+
* Placement obligation 6 (claim closure): an EXISTING placed session refuses the claim-form
|
|
61
|
+
* acquire — no `requireExisting` (the read/revive form, obligation 5) and no creation placement
|
|
62
|
+
* (the trusted-internals form; the creating call and its dedup/retry re-acquires stay legal, and
|
|
63
|
+
* placement immutability means the argument can never REWRITE anything — the persisted tuple wins).
|
|
64
|
+
*
|
|
65
|
+
* …and the MIRROR direction (the pre-claim SQUAT race): the child session id is
|
|
66
|
+
* published on the spawn frame BEFORE the child's prepare creates the session, so a concurrent
|
|
67
|
+
* claim-form acquire could win first creation and hand the trusted placement caller an ORDINARY
|
|
68
|
+
* session — host-listable, never really-deleted, the declared full tier falsified in silence. On
|
|
69
|
+
* a store that DECLARES the partition (`capability.subagentPlacement`; an ignoring store legally drops
|
|
70
|
+
* placements), an acquire carrying a placement must therefore come back with a PERSISTED tuple whose
|
|
71
|
+
* join identity matches the declaration — a missing or foreign tuple refuses loudly.
|
|
72
|
+
*
|
|
73
|
+
* @param persisted the tuple the backend holds for `sessionId` as resolved (`undefined`: an unplaced session).
|
|
74
|
+
* @param request the `acquire` options the caller passed.
|
|
75
|
+
* @param capability whether the store declares the subagent placement partition. `subagentPlacement` is read once,
|
|
76
|
+
* and only when the mirror direction is judged (a placement request that is not the read form, after `request`'s
|
|
77
|
+
* members are read), so a store may pass a getter over its live declaration.
|
|
78
|
+
* @throws SessionError `placement_refused` on either direction; returns nothing when admitted.
|
|
79
|
+
*/
|
|
80
|
+
export declare function admitSessionPlacement(sessionId: string, persisted: SessionPlacementRecord | undefined, request: {
|
|
81
|
+
requireExisting?: boolean;
|
|
82
|
+
placement?: SessionPlacement;
|
|
83
|
+
}, capability: {
|
|
84
|
+
subagentPlacement: boolean;
|
|
85
|
+
}): void;
|
|
55
86
|
/**
|
|
56
87
|
* TTL-cached {@link SessionStore} over a pluggable {@link SessionRepo}.
|
|
57
88
|
*
|
|
@@ -120,21 +151,9 @@ export declare class TtlSessionStore implements SessionStore {
|
|
|
120
151
|
requireExisting?: boolean;
|
|
121
152
|
placement?: SessionPlacement;
|
|
122
153
|
}): Promise<AcquiredSession>;
|
|
123
|
-
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* (the trusted-internals form; the creating call and its dedup/retry re-acquires stay legal, and
|
|
127
|
-
* placement immutability means the argument can never REWRITE anything — the persisted tuple wins).
|
|
128
|
-
*
|
|
129
|
-
* …and the MIRROR direction (the pre-claim SQUAT race): the child session id is
|
|
130
|
-
* published on the spawn frame BEFORE the child's prepare creates the session, so a concurrent
|
|
131
|
-
* claim-form acquire could win first creation and hand the trusted placement caller an ORDINARY
|
|
132
|
-
* session — host-listable, never really-deleted, the declared full tier falsified in silence. On
|
|
133
|
-
* a store that DECLARES the partition (an ignoring store legally drops placements), an acquire
|
|
134
|
-
* carrying a placement must therefore come back with a PERSISTED tuple whose join identity
|
|
135
|
-
* matches the declaration — a missing or foreign tuple refuses loudly, on every resolution path
|
|
136
|
-
* (cache hit, pending-promise inherit, open, idempotent re-create).
|
|
137
|
-
*/
|
|
154
|
+
/** The placement admission ({@link admitSessionPlacement}) for this store, judged on every resolution path. The
|
|
155
|
+
* partition declaration is a getter over this store's live field, so it is read where the admission judges the
|
|
156
|
+
* mirror direction (after the request's own members, and only then) — never captured at construction. */
|
|
138
157
|
private assertPlacementAdmission;
|
|
139
158
|
/** Resume an existing session from the repo, or create it if the backend has no such id (unless
|
|
140
159
|
* `requireExisting`, in which case a genuinely-missing id fails loud instead — design/114 Phase3). */
|
|
@@ -4,6 +4,20 @@ import { readMember } from "./thrown-value.js";
|
|
|
4
4
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
5
5
|
import { SESSION_DEFAULT_TTL_DAYS } from "../config/defaults.js";
|
|
6
6
|
export { SESSION_DEFAULT_TTL_DAYS };
|
|
7
|
+
export function admitSessionPlacement(sessionId, persisted, request, capability) {
|
|
8
|
+
if (persisted !== undefined && request.requireExisting !== true && request.placement === undefined) {
|
|
9
|
+
throw new SessionError("placement_refused", `session ${sessionId} belongs to the ${persisted.kind} placement partition — a claim-form acquire cannot attach to it (read it with requireExisting, or address the agent through its a* handle)`);
|
|
10
|
+
}
|
|
11
|
+
if (request.placement !== undefined && request.requireExisting !== true && capability.subagentPlacement) {
|
|
12
|
+
const want = request.placement;
|
|
13
|
+
if (persisted === undefined) {
|
|
14
|
+
throw new SessionError("placement_refused", `session ${sessionId} exists OUTSIDE the ${want.kind} placement partition it was declared into — refusing to run a subagent transcript on it (a concurrent claim-form create won this id, or the repo dropped the tuple)`);
|
|
15
|
+
}
|
|
16
|
+
if (persisted.kind !== want.kind || persisted.scope !== want.scope || persisted.handle !== want.handle) {
|
|
17
|
+
throw new SessionError("placement_refused", `session ${sessionId}'s persisted placement does not match the declared one (persisted ${persisted.kind}/${persisted.scope ?? "-"}/${persisted.handle ?? "-"} vs declared ${want.kind}/${want.scope ?? "-"}/${want.handle ?? "-"}) — refusing a cross-tuple attach`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
7
21
|
export class TtlSessionStore {
|
|
8
22
|
retention = "none";
|
|
9
23
|
durability;
|
|
@@ -74,18 +88,12 @@ export class TtlSessionStore {
|
|
|
74
88
|
return { session, sessionId: meta.id };
|
|
75
89
|
}
|
|
76
90
|
assertPlacementAdmission(sessionId, placement, opts) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
throw new SessionError("placement_refused", `session ${sessionId} exists OUTSIDE the ${want.kind} placement partition it was declared into — refusing to run a subagent transcript on it (a concurrent claim-form create won this id, or the repo dropped the tuple)`);
|
|
84
|
-
}
|
|
85
|
-
if (placement.kind !== want.kind || placement.scope !== want.scope || placement.handle !== want.handle) {
|
|
86
|
-
throw new SessionError("placement_refused", `session ${sessionId}'s persisted placement does not match the declared one (persisted ${placement.kind}/${placement.scope ?? "-"}/${placement.handle ?? "-"} vs declared ${want.kind}/${want.scope ?? "-"}/${want.handle ?? "-"}) — refusing a cross-tuple attach`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
91
|
+
const store = this;
|
|
92
|
+
admitSessionPlacement(sessionId, placement, opts ?? {}, {
|
|
93
|
+
get subagentPlacement() {
|
|
94
|
+
return store.placements?.subagent !== undefined;
|
|
95
|
+
},
|
|
96
|
+
});
|
|
89
97
|
}
|
|
90
98
|
async openOrCreate(id, requireExisting = false, placement) {
|
|
91
99
|
try {
|