@sema-agent/core 7.52.0 → 7.53.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 +194 -0
- 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 -5
- package/dist/agents/peer-session-drain.js +271 -180
- package/dist/agents/read-inbox-tool.d.ts +7 -0
- package/dist/agents/read-inbox-tool.js +5 -1
- package/dist/agents/subagent.d.ts +3 -0
- package/dist/agents/subagent.js +99 -72
- package/dist/agents/tool-filter.d.ts +18 -0
- package/dist/agents/tool-filter.js +6 -0
- 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 +30 -13
- package/dist/core/allow-entry.d.ts +2 -1
- package/dist/core/allow-entry.js +2 -2
- package/dist/core/auto-compaction.d.ts +57 -0
- package/dist/core/auto-compaction.js +28 -2
- package/dist/core/checkpoint-store.d.ts +29 -20
- package/dist/core/checkpoint-store.js +3 -3
- package/dist/core/compliance.js +3 -1
- package/dist/core/effective-path-target.d.ts +25 -6
- package/dist/core/effective-path-target.js +24 -2
- package/dist/core/engine-notice.d.ts +13 -2
- package/dist/core/gate-fold.js +3 -2
- package/dist/core/gate-lanes.js +11 -13
- package/dist/core/gate-outcome.d.ts +11 -6
- package/dist/core/governance-codes.d.ts +3 -1
- package/dist/core/governance-codes.js +3 -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 +7 -5
- package/dist/core/hooks.js +5 -3
- package/dist/core/locked-config.d.ts +84 -32
- package/dist/core/locked-config.js +128 -42
- package/dist/core/mcp-probe.js +1 -1
- package/dist/core/mcp-server-spec.d.ts +88 -10
- package/dist/core/mcp-server-spec.js +183 -33
- package/dist/core/mcp.d.ts +21 -14
- package/dist/core/mcp.js +55 -51
- package/dist/core/memory-engine/engine.d.ts +14 -19
- package/dist/core/memory-engine/engine.js +7 -5
- package/dist/core/mode-policy.d.ts +3 -18
- package/dist/core/mode-policy.js +2 -16
- 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 +39 -10
- package/dist/core/mods/kernel/receive.js +119 -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 +2 -2
- package/dist/core/permission-rule-model.d.ts +58 -9
- package/dist/core/permission-rule-model.js +81 -7
- package/dist/core/permission-rule-org.d.ts +163 -33
- package/dist/core/permission-rule-org.js +205 -71
- package/dist/core/permission-rules.d.ts +7 -1
- package/dist/core/permission-rules.js +37 -8
- 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/contracts.d.ts +1 -0
- package/dist/core/runner/gate-exit.js +4 -3
- 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 +3 -1
- package/dist/core/runner/person-path-rows.js +2 -2
- package/dist/core/runner/prepare-config-doors.d.ts +48 -2
- package/dist/core/runner/prepare-config-doors.js +161 -145
- package/dist/core/runner/prepare-defer-classify.js +4 -7
- package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.js +7 -5
- package/dist/core/runner/prepare-hands-readface.d.ts +1 -1
- package/dist/core/runner/prepare-hands-readface.js +2 -1
- package/dist/core/runner/prepare-inherited-gate.js +2 -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-policy-chain.d.ts +1 -1
- package/dist/core/runner/prepare-policy-chain.js +12 -12
- 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-task.js +10 -10
- package/dist/core/runner/prepare-wiring-manifest.d.ts +8 -3
- package/dist/core/runner/prepare-wiring-manifest.js +8 -5
- package/dist/core/runner/resume-admission.d.ts +4 -1
- package/dist/core/runner/resume-admission.js +7 -5
- 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/retired-runner-deps.d.ts +5 -6
- package/dist/core/runner/retired-runner-deps.js +1 -4
- package/dist/core/runner/run-leg.js +42 -12
- package/dist/core/runner/run-recovery-lanes.js +5 -3
- package/dist/core/runner/run-terminal-adoption.js +6 -5
- package/dist/core/runner/run-turn-boundary.js +9 -3
- package/dist/core/runner/runtask.js +1 -1
- package/dist/core/runner/skills-seat.d.ts +15 -0
- package/dist/core/runner/skills-seat.js +57 -0
- 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-deps.d.ts +29 -14
- package/dist/core/session-policy-store.d.ts +19 -0
- package/dist/core/session-policy-store.js +22 -2
- package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
- package/dist/core/task-event.d.ts +38 -2
- package/dist/core/task-notification.js +2 -2
- package/dist/core/task-spec.d.ts +1 -1
- package/dist/core/tool-policy.d.ts +3 -0
- package/dist/core/tool-policy.js +10 -4
- package/dist/core/types.d.ts +2 -2
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-text.d.ts +16 -0
- package/dist/core/untrusted-text.js +7 -2
- package/dist/core/user-attachment.d.ts +13 -2
- package/dist/core/user-attachment.js +47 -41
- package/dist/core/wiring-manifest.d.ts +4 -2
- package/dist/engine/harness/agent-harness.js +2 -1
- package/dist/engine/harness/types.d.ts +3 -0
- 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/index.d.ts +15 -9
- package/dist/index.js +12 -6
- package/dist/internal/harness.d.ts +1 -0
- package/dist/internal/harness.js +1 -0
- package/dist/orchestration/goal.d.ts +24 -1
- package/dist/orchestration/goal.js +3 -2
- 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 +16 -2
- 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 +55 -17
- package/dist/prompt-assembly/select.d.ts +21 -6
- package/dist/prompt-assembly/select.js +39 -2
- package/dist/prompts/default.d.ts +0 -11
- package/dist/prompts/default.js +0 -3
- 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 +4 -3
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +65 -5
- package/wire-changes/core@7.53.0.json +1946 -0
|
@@ -3,17 +3,23 @@ import { assertContainmentFaceValue } from "../../tools/fs/index.js";
|
|
|
3
3
|
import { MICRO_COMPACT_MACHINES } from "../context-edit.js";
|
|
4
4
|
import { assertAddOnlySeats } from "../child-clamp-seats.js";
|
|
5
5
|
import { assertNoRetiredRunnerDeps } from "./retired-runner-deps.js";
|
|
6
|
-
import { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
6
|
+
import { recordedModeSeed, resolveCheckpointStore } from "../checkpoint-store.js";
|
|
7
|
+
import { asResumeConfigRefusal, refusePermissionModeDoors } from "../mode-policy.js";
|
|
8
|
+
import { resolveOutputStyleFrame } from "../output-style.js";
|
|
9
|
+
import { screenUserAttachments } from "../user-attachment.js";
|
|
10
|
+
import { screenUserInvokedSkills } from "../skill-grant.js";
|
|
11
|
+
import { readSkillsSeat } from "./skills-seat.js";
|
|
12
|
+
import { screenHandsBandOptions } from "../hands-band-screen.js";
|
|
7
13
|
import { assertAutoConsolidationWirable } from "./memory-consolidation-driver.js";
|
|
8
14
|
import { isModelPriced, malformedPricingField, modelCostToPricing } from "../pricing.js";
|
|
9
|
-
import { preflightLockedConfig } from "../locked-config.js";
|
|
15
|
+
import { ENTER_AS_IS, preflightLockedConfig } from "../locked-config.js";
|
|
10
16
|
import { assertRetentionCapability } from "../retention.js";
|
|
11
17
|
import { resolveModel, resolveTaskModel, roleModelIfSet } from "../roles.js";
|
|
12
18
|
import { resolveSkillListingBudget } from "../skill-listing-budget.js";
|
|
13
19
|
import { describeRejectedValue } from "../tool-search-setting.js";
|
|
14
20
|
import { applyToolModelGate, assertRestoreGatedToolsValue, modelIdTail } from "../tool-model-gate.js";
|
|
15
21
|
import { resolveUsageWindows } from "../usage-window-store.js";
|
|
16
|
-
import { deriveAskEffective, resolveAskSeat, resolveQuestionSeam } from "../wiring-manifest.js";
|
|
22
|
+
import { deriveAskEffective, resolveAskSeat, resolveQuestionSeam, screenApprovalReach } from "../wiring-manifest.js";
|
|
17
23
|
import { resolveHost } from "../../prompt-assembly/select.js";
|
|
18
24
|
import { resolvePromptBinding } from "../../prompt-assembly/overlay.js";
|
|
19
25
|
import { assertPeerPresenceValue } from "../../agents/peer-directory.js";
|
|
@@ -48,8 +54,8 @@ export function limitConfigError(code, message) {
|
|
|
48
54
|
export function resolveTaskLimits(limits) {
|
|
49
55
|
if (limits === undefined)
|
|
50
56
|
return undefined;
|
|
51
|
-
if (typeof limits !== "object" || Array.isArray(limits)) {
|
|
52
|
-
throw limitConfigError("config.limit_invalid", `TaskSpec.limits must be an object (got ${Array.isArray(limits) ? "an array" : typeof limits})`);
|
|
57
|
+
if (typeof limits !== "object" || limits === null || Array.isArray(limits)) {
|
|
58
|
+
throw limitConfigError("config.limit_invalid", `TaskSpec.limits must be an object (got ${limits === null ? "null" : Array.isArray(limits) ? "an array" : typeof limits})`);
|
|
53
59
|
}
|
|
54
60
|
const raw = limits;
|
|
55
61
|
const legal = TASK_LIMIT_KEYS;
|
|
@@ -66,13 +72,13 @@ export function resolveTaskLimits(limits) {
|
|
|
66
72
|
if (value === undefined)
|
|
67
73
|
continue;
|
|
68
74
|
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
69
|
-
throw limitConfigError("config.limit_invalid", `TaskSpec.limits.${key} must be a finite, non-negative number (got ${
|
|
75
|
+
throw limitConfigError("config.limit_invalid", `TaskSpec.limits.${key} must be a finite, non-negative number (got ${describeRejectedValue(value)}) — an unevaluable ceiling is not a ceiling, and folding it to a default would run the task under a limit nobody chose.`);
|
|
70
76
|
}
|
|
71
77
|
}
|
|
72
78
|
const notice = raw.approachNotice;
|
|
73
79
|
if (notice !== undefined && notice !== false) {
|
|
74
80
|
if (typeof notice !== "object" || notice === null || Array.isArray(notice)) {
|
|
75
|
-
throw limitConfigError("config.limit_invalid", `TaskSpec.limits.approachNotice must be \`false\` or { at?: [first, second] } (got ${
|
|
81
|
+
throw limitConfigError("config.limit_invalid", `TaskSpec.limits.approachNotice must be \`false\` or { at?: [first, second] } (got ${describeRejectedValue(notice)})`);
|
|
76
82
|
}
|
|
77
83
|
const at = notice.at;
|
|
78
84
|
if (at !== undefined) {
|
|
@@ -147,34 +153,51 @@ function resolveClearOnRejection(bag) {
|
|
|
147
153
|
}
|
|
148
154
|
return declared ?? true;
|
|
149
155
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const
|
|
156
|
+
function deploymentWord(raw, seat, words, absent, code, why) {
|
|
157
|
+
if (raw === undefined)
|
|
158
|
+
return absent;
|
|
159
|
+
const word = words.find((w) => w === raw);
|
|
160
|
+
if (word !== undefined)
|
|
161
|
+
return word;
|
|
162
|
+
const got = typeof raw === "string" ? JSON.stringify(raw.length > 64 ? `${raw.slice(0, 64)}…` : raw) : raw === null ? "null" : Array.isArray(raw) ? "an array" : typeof raw;
|
|
163
|
+
const spelled = words.map((w) => `"${w}"`);
|
|
164
|
+
throw limitConfigError(code, `RunnerDeps.${seat} must be ${spelled.slice(0, -1).join(", ")} or ${spelled.at(-1)} when present (got ${got}) — ${why}`);
|
|
165
|
+
}
|
|
166
|
+
export const checkpointStoreSeat = (spec) => (spec.checkpointStore !== undefined ? "taskConfig" : "deps");
|
|
167
|
+
export function assertResumeConfigRecord(config) {
|
|
168
|
+
if (config === null || typeof config !== "object" || Array.isArray(config)) {
|
|
169
|
+
throw limitConfigError("config.invalid_argument", `the resume's taskConfig must be an object — the TaskSpec the run suspended with (got ${config === null ? "null" : Array.isArray(config) ? "an array" : typeof config})`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
export function configValueDoors(input, enter = ENTER_AS_IS) {
|
|
173
|
+
const { spec, deps, resumeLeg, sessions } = input;
|
|
174
|
+
enter("deps", () => assertNoRetiredRunnerDeps(deps));
|
|
175
|
+
enter("taskConfig", () => assertPeerPresenceValue(spec.peerPresence));
|
|
176
|
+
enter("taskConfig", () => assertRestoreGatedToolsValue(spec.restoreGatedTools));
|
|
177
|
+
const microCompactKnob = enter("deps", () => resolveMicroCompactKnob(deps.microCompact));
|
|
178
|
+
const toolFaceListRefusal = (message, reason) => {
|
|
179
|
+
const e = new Error(message);
|
|
180
|
+
e.code = "config.tool_face_control";
|
|
181
|
+
e.detail = { reason };
|
|
182
|
+
return e;
|
|
183
|
+
};
|
|
157
184
|
const assertToolNameListValue = (value, seat) => {
|
|
158
185
|
if (value === undefined)
|
|
159
186
|
return;
|
|
160
187
|
if (!Array.isArray(value)) {
|
|
161
|
-
|
|
162
|
-
e.code = "config.tool_face_control";
|
|
163
|
-
throw e;
|
|
188
|
+
throw toolFaceListRefusal(`TaskSpec.${seat} must be an array of tool names or absent (got ${value === null ? "null" : typeof value}) — a garbage list must refuse loudly, never be read as "no ${seat}".`, "not_a_list");
|
|
164
189
|
}
|
|
165
190
|
const entries = value;
|
|
166
191
|
for (const entry of entries) {
|
|
167
192
|
if (typeof entry !== "string") {
|
|
168
|
-
|
|
169
|
-
e.code = "config.tool_face_control";
|
|
170
|
-
throw e;
|
|
193
|
+
throw toolFaceListRefusal(`TaskSpec.${seat} entries must be strings (got ${entry === null ? "null" : typeof entry}).`, "not_a_string");
|
|
171
194
|
}
|
|
172
195
|
}
|
|
173
196
|
};
|
|
174
|
-
assertToolNameListValue(spec.allowTools, "allowTools");
|
|
175
|
-
assertToolNameListValue(spec.excludeTools, "excludeTools");
|
|
176
|
-
assertToolNameListValue(spec.deferTools, "deferTools");
|
|
177
|
-
assertToolNameListValue(spec.alwaysLoadTools, "alwaysLoadTools");
|
|
197
|
+
enter("taskConfig", () => assertToolNameListValue(spec.allowTools, "allowTools"));
|
|
198
|
+
enter("taskConfig", () => assertToolNameListValue(spec.excludeTools, "excludeTools"));
|
|
199
|
+
enter("taskConfig", () => assertToolNameListValue(spec.deferTools, "deferTools"));
|
|
200
|
+
enter("taskConfig", () => assertToolNameListValue(spec.alwaysLoadTools, "alwaysLoadTools"));
|
|
178
201
|
const toolFaceLists = {
|
|
179
202
|
allow: spec.allowTools ? Object.freeze([...spec.allowTools]) : undefined,
|
|
180
203
|
exclude: spec.excludeTools ? Object.freeze([...spec.excludeTools]) : undefined,
|
|
@@ -186,116 +209,131 @@ export function prepareConfigDoors(input) {
|
|
|
186
209
|
? Object.freeze([...spec.restoreGatedTools])
|
|
187
210
|
: undefined,
|
|
188
211
|
};
|
|
189
|
-
const
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
212
|
+
const promptHost = enter("taskConfig", () => resolveHost(spec));
|
|
213
|
+
const promptBinding = enter("taskConfig", () => resolvePromptBinding(spec));
|
|
214
|
+
if (spec.resumeAt !== undefined)
|
|
215
|
+
enter("taskConfig", () => {
|
|
216
|
+
if (resumeLeg) {
|
|
217
|
+
const e = new Error("resumeAt cannot be combined with a durable resume");
|
|
218
|
+
e.code = "resume_at.conflicts_resume";
|
|
219
|
+
throw e;
|
|
220
|
+
}
|
|
221
|
+
if (!spec.sessionId) {
|
|
222
|
+
const e = new Error("resumeAt requires a sessionId (the session to branch)");
|
|
223
|
+
e.code = "resume_at.no_session";
|
|
224
|
+
throw e;
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
enter("taskConfig", () => assertContainmentFaceValue(spec.readFace, "read", "spec"));
|
|
228
|
+
enter("deps", () => assertContainmentFaceValue(deps.readFace, "read", "deps"));
|
|
229
|
+
enter("taskConfig", () => assertContainmentFaceValue(spec.writeFace, "write", "spec"));
|
|
230
|
+
enter("deps", () => assertContainmentFaceValue(deps.writeFace, "write", "deps"));
|
|
231
|
+
enter("taskConfig", () => assertAddOnlySeats(spec));
|
|
232
|
+
const memoryDelegationEvidence = enter("deps", () => deploymentWord(deps.memoryDelegationEvidence, "memoryDelegationEvidence", ["static-face", "attested-only"], "static-face", "config.memory_delegation_evidence", "an unevaluable evidence standard is refused loudly, never folded to either standard."));
|
|
233
|
+
const memoryProvenance = enter("deps", () => deploymentWord(deps.memoryProvenance, "memoryProvenance", ["off", "carry"], "carry", "config.memory_provenance", "an unevaluable provenance mode is refused loudly, never folded to either mode."));
|
|
234
|
+
const memoryCapturePolicy = enter("deps", () => deploymentWord(deps.memoryCapturePolicy, "memoryCapturePolicy", ["open", "governed", "capture-required"], "open", "config.memory_capture_policy", "an unevaluable capture posture is refused loudly, never folded to any posture (the fault arms differ per posture, so a guess would pick a polarity nobody configured)."));
|
|
235
|
+
enter("deps", () => assertAutoConsolidationWirable(deps));
|
|
236
|
+
if (spec.resumeAtMode !== undefined)
|
|
237
|
+
enter("taskConfig", () => {
|
|
238
|
+
if (spec.resumeAt === undefined) {
|
|
239
|
+
const e = new Error(`resumeAtMode ${describeRejectedValue(spec.resumeAtMode)} requires resumeAt (there is no branch target to position against)`);
|
|
240
|
+
e.code = "resume_at.mode_without_target";
|
|
241
|
+
throw e;
|
|
242
|
+
}
|
|
243
|
+
if (spec.resumeAtMode !== "at" && spec.resumeAtMode !== "before") {
|
|
244
|
+
const e = new Error(`resumeAtMode ${describeRejectedValue(spec.resumeAtMode)} is invalid — expected "at" (inclusive branch, the default) or "before" (exclusive branch)`);
|
|
245
|
+
e.code = "resume_at.invalid_mode";
|
|
246
|
+
throw e;
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
if (spec.toolMaterializeStrategy !== undefined && spec.toolMaterializeStrategy !== "swap" && spec.toolMaterializeStrategy !== "static")
|
|
250
|
+
enter("taskConfig", () => {
|
|
251
|
+
const e = new Error(`toolMaterializeStrategy must be "swap" or "static" (got ${JSON.stringify(spec.toolMaterializeStrategy)}).`);
|
|
252
|
+
e.code = "config.tool_materialize_invalid";
|
|
196
253
|
throw e;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
e
|
|
254
|
+
});
|
|
255
|
+
if (spec.memoryPersistenceCapable !== undefined && typeof spec.memoryPersistenceCapable !== "boolean")
|
|
256
|
+
enter("taskConfig", () => {
|
|
257
|
+
const e = new Error(`memoryPersistenceCapable must be a boolean when present (got ${JSON.stringify(spec.memoryPersistenceCapable)}) — a non-boolean would silently read as capable.`);
|
|
258
|
+
e.code = "config.memory_persistence_invalid";
|
|
201
259
|
throw e;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const memoryDelegationEvidenceRaw = deps.memoryDelegationEvidence;
|
|
210
|
-
if (memoryDelegationEvidenceRaw !== undefined && memoryDelegationEvidenceRaw !== "static-face" && memoryDelegationEvidenceRaw !== "attested-only") {
|
|
211
|
-
const evidence = memoryDelegationEvidenceRaw;
|
|
212
|
-
const got = typeof evidence === "string"
|
|
213
|
-
? JSON.stringify(evidence.length > 64 ? `${evidence.slice(0, 64)}…` : evidence)
|
|
214
|
-
: evidence === null
|
|
215
|
-
? "null"
|
|
216
|
-
: Array.isArray(evidence)
|
|
217
|
-
? "an array"
|
|
218
|
-
: typeof evidence;
|
|
219
|
-
const e = new Error(`RunnerDeps.memoryDelegationEvidence must be "static-face" or "attested-only" when present (got ${got}) — ` +
|
|
220
|
-
`an unevaluable evidence standard is refused loudly, never folded to either standard.`);
|
|
221
|
-
e.code = "config.memory_delegation_evidence";
|
|
222
|
-
throw e;
|
|
223
|
-
}
|
|
224
|
-
const memoryDelegationEvidence = memoryDelegationEvidenceRaw === "attested-only" ? "attested-only" : "static-face";
|
|
225
|
-
const memoryProvenanceRaw = deps.memoryProvenance;
|
|
226
|
-
if (memoryProvenanceRaw !== undefined && memoryProvenanceRaw !== "off" && memoryProvenanceRaw !== "carry") {
|
|
227
|
-
const got = typeof memoryProvenanceRaw === "string"
|
|
228
|
-
? JSON.stringify(memoryProvenanceRaw.length > 64 ? `${memoryProvenanceRaw.slice(0, 64)}…` : memoryProvenanceRaw)
|
|
229
|
-
: memoryProvenanceRaw === null
|
|
230
|
-
? "null"
|
|
231
|
-
: Array.isArray(memoryProvenanceRaw)
|
|
232
|
-
? "an array"
|
|
233
|
-
: typeof memoryProvenanceRaw;
|
|
234
|
-
const e = new Error(`RunnerDeps.memoryProvenance must be "off" or "carry" when present (got ${got}) — ` + `an unevaluable provenance mode is refused loudly, never folded to either mode.`);
|
|
235
|
-
e.code = "config.memory_provenance";
|
|
236
|
-
throw e;
|
|
237
|
-
}
|
|
238
|
-
const memoryProvenance = memoryProvenanceRaw === "off" ? "off" : "carry";
|
|
239
|
-
const memoryCapturePolicyRaw = deps.memoryCapturePolicy;
|
|
240
|
-
if (memoryCapturePolicyRaw !== undefined && memoryCapturePolicyRaw !== "open" && memoryCapturePolicyRaw !== "governed" && memoryCapturePolicyRaw !== "capture-required") {
|
|
241
|
-
const got = typeof memoryCapturePolicyRaw === "string"
|
|
242
|
-
? JSON.stringify(memoryCapturePolicyRaw.length > 64 ? `${memoryCapturePolicyRaw.slice(0, 64)}…` : memoryCapturePolicyRaw)
|
|
243
|
-
: memoryCapturePolicyRaw === null
|
|
244
|
-
? "null"
|
|
245
|
-
: Array.isArray(memoryCapturePolicyRaw)
|
|
246
|
-
? "an array"
|
|
247
|
-
: typeof memoryCapturePolicyRaw;
|
|
248
|
-
const e = new Error(`RunnerDeps.memoryCapturePolicy must be "open", "governed" or "capture-required" when present (got ${got}) — ` +
|
|
249
|
-
`an unevaluable capture posture is refused loudly, never folded to any posture (the fault arms differ per posture, so a guess would pick a polarity nobody configured).`);
|
|
250
|
-
e.code = "config.memory_capture_policy";
|
|
251
|
-
throw e;
|
|
252
|
-
}
|
|
253
|
-
const memoryCapturePolicy = memoryCapturePolicyRaw === "governed" ? "governed" : memoryCapturePolicyRaw === "capture-required" ? "capture-required" : "open";
|
|
254
|
-
assertAutoConsolidationWirable(deps);
|
|
255
|
-
if (spec.resumeAtMode !== undefined) {
|
|
256
|
-
if (spec.resumeAt === undefined) {
|
|
257
|
-
const e = new Error(`resumeAtMode "${spec.resumeAtMode}" requires resumeAt (there is no branch target to position against)`);
|
|
258
|
-
e.code = "resume_at.mode_without_target";
|
|
260
|
+
});
|
|
261
|
+
if (spec.toolMaterializeStrategy === "static" && spec.deferSelfResolve === false)
|
|
262
|
+
enter("taskConfig", () => {
|
|
263
|
+
const e = new Error(`toolMaterializeStrategy "static" cannot be combined with deferSelfResolve: false — with the direct-call ` +
|
|
264
|
+
`lane disabled a placeholder is never swapped and never self-resolves, so no deferred tool could ever be ` +
|
|
265
|
+
`called. Use "swap", or leave deferSelfResolve on.`);
|
|
266
|
+
e.code = "config.tool_materialize_unreachable";
|
|
259
267
|
throw e;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const e = new Error(`resumeAtMode "${String(spec.resumeAtMode)}" is invalid — expected "at" (inclusive branch, the default) or "before" (exclusive branch)`);
|
|
263
|
-
e.code = "resume_at.invalid_mode";
|
|
264
|
-
throw e;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
if (spec.toolMaterializeStrategy !== undefined && spec.toolMaterializeStrategy !== "swap" && spec.toolMaterializeStrategy !== "static") {
|
|
268
|
-
const e = new Error(`toolMaterializeStrategy must be "swap" or "static" (got ${JSON.stringify(spec.toolMaterializeStrategy)}).`);
|
|
269
|
-
e.code = "config.tool_materialize_invalid";
|
|
270
|
-
throw e;
|
|
271
|
-
}
|
|
272
|
-
if (spec.memoryPersistenceCapable !== undefined && typeof spec.memoryPersistenceCapable !== "boolean") {
|
|
273
|
-
const e = new Error(`memoryPersistenceCapable must be a boolean when present (got ${JSON.stringify(spec.memoryPersistenceCapable)}) — a non-boolean would silently read as capable.`);
|
|
274
|
-
e.code = "config.memory_persistence_invalid";
|
|
275
|
-
throw e;
|
|
276
|
-
}
|
|
277
|
-
if (spec.toolMaterializeStrategy === "static" && spec.deferSelfResolve === false) {
|
|
278
|
-
const e = new Error(`toolMaterializeStrategy "static" cannot be combined with deferSelfResolve: false — with the direct-call ` +
|
|
279
|
-
`lane disabled a placeholder is never swapped and never self-resolves, so no deferred tool could ever be ` +
|
|
280
|
-
`called. Use "swap", or leave deferSelfResolve on.`);
|
|
281
|
-
e.code = "config.tool_materialize_unreachable";
|
|
282
|
-
throw e;
|
|
283
|
-
}
|
|
284
|
-
if (resume === undefined && spec.objective.trim().length === 0) {
|
|
268
|
+
});
|
|
269
|
+
if (!resumeLeg && (spec.objective ?? "").trim().length === 0) {
|
|
285
270
|
const e = new Error("TaskSpec.objective is empty — a task needs an instruction (an empty user message is rejected by strict model endpoints and would fail every later request of the session).");
|
|
286
271
|
e.code = "config.empty_objective";
|
|
287
272
|
throw e;
|
|
288
273
|
}
|
|
289
|
-
const lockedPreflight = preflightLockedConfig(spec, deps);
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
274
|
+
const lockedPreflight = preflightLockedConfig(spec, deps, enter);
|
|
275
|
+
const declaredSkills = spec.skills;
|
|
276
|
+
const skills = declaredSkills === undefined ? undefined : enter("taskConfig", () => readSkillsSeat(declaredSkills));
|
|
277
|
+
enter("deps", () => screenHandsBandOptions(deps.hands));
|
|
278
|
+
const skillListingSeats = { fraction: spec.skillListingBudgetFraction, maxDescChars: spec.skillListingMaxDescChars };
|
|
279
|
+
enter("taskConfig", () => resolveSkillListingBudget(skillListingSeats));
|
|
280
|
+
enter("taskConfig", () => resolveTaskLimits(spec.limits));
|
|
281
|
+
enter("taskConfig", () => resolveAttachmentsConfig(spec.attachments));
|
|
282
|
+
if (spec.resourceSuspend !== undefined)
|
|
283
|
+
enter("taskConfig", () => {
|
|
284
|
+
const declared = spec.resourceSuspend;
|
|
285
|
+
if (typeof declared !== "object" || declared === null || Array.isArray(declared)) {
|
|
286
|
+
throw limitConfigError("config.limit_invalid", `TaskSpec.resourceSuspend must be an object carrying a non-empty \`scope\` (got ${declared === null ? "null" : Array.isArray(declared) ? "an array" : typeof declared}) — it is the allocation every resource checkpoint is filed under.`);
|
|
287
|
+
}
|
|
288
|
+
const rsus = declared;
|
|
289
|
+
if (typeof rsus.scope !== "string" || rsus.scope === "") {
|
|
290
|
+
throw limitConfigError("config.limit_invalid", `TaskSpec.resourceSuspend.scope must be a non-empty string (got ${describeRejectedValue(rsus.scope)}) — it is the multi-tenant isolation key every resource checkpoint is filed under.`);
|
|
291
|
+
}
|
|
292
|
+
for (const key of ["totalBudgetUsd", "totalTokens", "maxSlices", "ttlMs"]) {
|
|
293
|
+
const value = rsus[key];
|
|
294
|
+
if (value === undefined)
|
|
295
|
+
continue;
|
|
296
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
297
|
+
throw limitConfigError("config.limit_invalid", `TaskSpec.resourceSuspend.${key} must be a finite, non-negative number (got ${describeRejectedValue(value)}) — an unevaluable allocation is not an allocation, and a NaN here blinds even the validated per-slice window.`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
const usageWindows = enter("deps", () => resolveUsageWindows(deps.usageWindows));
|
|
302
|
+
const taskGuardrail = spec.limits?.brainCallGuardrailMs;
|
|
303
|
+
const brainCallGuardrailMs = enter(taskGuardrail != null ? "taskConfig" : "deps", () => resolveBrainCallGuardrailMs(taskGuardrail ?? deps.brainCallGuardrailMs));
|
|
304
|
+
const checkpointStore = enter(checkpointStoreSeat(spec), () => resolveCheckpointStore(spec, deps));
|
|
305
|
+
const taskStore = checkpointStoreSeat(spec) === "taskConfig" ? checkpointStore : undefined;
|
|
306
|
+
const retention = { policy: deps.retentionPolicy, locked: lockedPreflight.lockedKeys.has("retentionPolicy") };
|
|
307
|
+
enter("deps", () => assertRetentionCapability({
|
|
308
|
+
...retention,
|
|
293
309
|
stores: [
|
|
294
310
|
{ name: "sessionStore", store: sessions },
|
|
295
|
-
{ name: "checkpointStore", store:
|
|
311
|
+
{ name: "checkpointStore", store: taskStore === undefined ? checkpointStore : undefined },
|
|
296
312
|
{ name: "toolResultStore", store: deps.toolResultStore },
|
|
297
313
|
],
|
|
314
|
+
}));
|
|
315
|
+
if (taskStore !== undefined)
|
|
316
|
+
enter("taskConfig", () => assertRetentionCapability({ ...retention, stores: [{ name: "checkpointStore", store: taskStore }] }));
|
|
317
|
+
return { toolFaceLists, promptHost, promptBinding, lockedPreflight, skillListingSeats, skills, microCompactKnob, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailMs };
|
|
318
|
+
}
|
|
319
|
+
export function refuseResumeDoors(config, recordedGate, deps, sessions) {
|
|
320
|
+
asResumeConfigRefusal("taskConfig", () => {
|
|
321
|
+
refusePermissionModeDoors(config);
|
|
322
|
+
resolveOutputStyleFrame(config.outputStyle);
|
|
323
|
+
screenApprovalReach(config.approvalReach);
|
|
324
|
+
screenUserInvokedSkills(config);
|
|
325
|
+
screenUserAttachments(config.userAttachments, { resumeLeg: true });
|
|
298
326
|
});
|
|
327
|
+
const { lockedPreflight, skills } = configValueDoors({ spec: config, deps, resumeLeg: true, sessions }, asResumeConfigRefusal);
|
|
328
|
+
asResumeConfigRefusal("inheritedGate", () => void recordedModeSeed(recordedGate));
|
|
329
|
+
return { ...config, ...(config.mcp !== undefined ? { mcp: lockedPreflight.mcp ?? [] } : {}), ...(config.a2a !== undefined ? { a2a: lockedPreflight.a2a ?? [] } : {}), skills };
|
|
330
|
+
}
|
|
331
|
+
export function prepareConfigDoors(input) {
|
|
332
|
+
const { deps, sessions, resume, internals } = input;
|
|
333
|
+
let spec = input.spec;
|
|
334
|
+
const { toolFaceLists, promptHost, promptBinding, lockedPreflight, skillListingSeats, skills, microCompactKnob, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailMs } = configValueDoors({ spec, deps, resumeLeg: resume !== undefined, sessions });
|
|
335
|
+
spec = Object.create(Object.getPrototypeOf(spec), { ...Object.getOwnPropertyDescriptors(spec), skills: { value: skills, enumerable: skills !== undefined, writable: false, configurable: false } });
|
|
336
|
+
const promptProfile = resolveModelPromptTraits({ id: "" }, spec, internals).promptProfile;
|
|
299
337
|
const resolvedInteractionPosture = spec.interactionPosture ?? internals?.parentInteractionPosture ?? deps.interactionPosture;
|
|
300
338
|
const askSeat = resolveAskSeat(spec, deps);
|
|
301
339
|
{
|
|
@@ -344,25 +382,7 @@ export function prepareConfigDoors(input) {
|
|
|
344
382
|
}
|
|
345
383
|
}
|
|
346
384
|
}
|
|
347
|
-
resolveTaskLimits(spec.limits);
|
|
348
|
-
resolveAttachmentsConfig(spec.attachments);
|
|
349
|
-
if (spec.resourceSuspend !== undefined) {
|
|
350
|
-
const rsus = spec.resourceSuspend;
|
|
351
|
-
if (typeof rsus.scope !== "string" || rsus.scope === "") {
|
|
352
|
-
throw limitConfigError("config.limit_invalid", `TaskSpec.resourceSuspend.scope must be a non-empty string (got ${String(rsus.scope)}) — it is the multi-tenant isolation key every resource checkpoint is filed under.`);
|
|
353
|
-
}
|
|
354
|
-
for (const key of ["totalBudgetUsd", "totalTokens", "maxSlices", "ttlMs"]) {
|
|
355
|
-
const value = rsus[key];
|
|
356
|
-
if (value === undefined)
|
|
357
|
-
continue;
|
|
358
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
359
|
-
throw limitConfigError("config.limit_invalid", `TaskSpec.resourceSuspend.${key} must be a finite, non-negative number (got ${String(value)}) — an unevaluable allocation is not an allocation, and a NaN here blinds even the validated per-slice window.`);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
const usageWindows = resolveUsageWindows(deps.usageWindows);
|
|
364
385
|
const brainCallGuardrailRef = {};
|
|
365
|
-
const brainCallGuardrailMs = resolveBrainCallGuardrailMs(spec.limits?.brainCallGuardrailMs ?? deps.brainCallGuardrailMs);
|
|
366
386
|
const mountedRoster = spec.tools;
|
|
367
387
|
if (spec.agents !== undefined && spec.agents.length > 0) {
|
|
368
388
|
const pool = spec.tools ?? [];
|
|
@@ -427,11 +447,7 @@ export function prepareConfigDoors(input) {
|
|
|
427
447
|
if (gateDecision.survivors !== undefined) {
|
|
428
448
|
spec = { ...spec, tools: gateDecision.survivors };
|
|
429
449
|
}
|
|
430
|
-
const skillListingBudget = resolveSkillListingBudget({
|
|
431
|
-
fraction: spec.skillListingBudgetFraction,
|
|
432
|
-
maxDescChars: spec.skillListingMaxDescChars,
|
|
433
|
-
model,
|
|
434
|
-
});
|
|
450
|
+
const skillListingBudget = resolveSkillListingBudget({ ...skillListingSeats, model });
|
|
435
451
|
const modelGate = Object.freeze({
|
|
436
452
|
removedByClass: gateDecision.removedByClass,
|
|
437
453
|
unknownClasses: gateDecision.unknownClasses,
|
|
@@ -9,6 +9,7 @@ import { classifyDeferredWithGate } from "./tool-defer-gate.js";
|
|
|
9
9
|
import { TOOL_SEARCH_NAME } from "./tool-disclosure.js";
|
|
10
10
|
import { resolveToolSearch, toolSearchSettingOf } from "../tool-search-setting.js";
|
|
11
11
|
import { RosterBuilder } from "../tool-roster.js";
|
|
12
|
+
import { valveLeaves } from "../../agents/tool-filter.js";
|
|
12
13
|
function explicitlyDeferredMemoryTrio(mounted, roster, callerDeferNames) {
|
|
13
14
|
return mounted ? MEMORY_ENGINE_TOOL_NAMES.filter((n) => roster.some((t) => t.name === n) && (callerDeferNames ?? []).includes(n)) : [];
|
|
14
15
|
}
|
|
@@ -19,12 +20,8 @@ export function prepareDeferClassify(input) {
|
|
|
19
20
|
const { spec, deps, roster, toolFaceSnapshot, handsEnabled, fullShellReachable, promptProfile, model, mcp, a2a, sharedMemoryPairMounted, memoryEnginePairMounted, memoryRecallSegment, onceLedger, sessionId } = input;
|
|
20
21
|
const tools = roster.tools;
|
|
21
22
|
let memoryBlock = input.memoryBlock;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
roster.unmountWhere((t) => !toolFaceSnapshot.selector.admits(t));
|
|
27
|
-
}
|
|
23
|
+
const leaves = valveLeaves(spec, toolFaceSnapshot.selector);
|
|
24
|
+
roster.unmountWhere((t) => !leaves(t));
|
|
28
25
|
if (handsEnabled) {
|
|
29
26
|
const fullShellOnRoster = tools.some((t) => t.name === "Bash" && getToolContract(t, "core").contractId === FULL_SHELL_CONTRACT_ID);
|
|
30
27
|
if (fullShellOnRoster !== fullShellReachable) {
|
|
@@ -48,7 +45,7 @@ export function prepareDeferClassify(input) {
|
|
|
48
45
|
.map((t) => t.name);
|
|
49
46
|
const resolvedToolSearch = resolveToolSearch(deps.toolSearch);
|
|
50
47
|
const toolSearchSeat = toolSearchSettingOf(resolvedToolSearch);
|
|
51
|
-
const toolSearchAdmitted =
|
|
48
|
+
const toolSearchAdmitted = leaves({ name: TOOL_SEARCH_NAME });
|
|
52
49
|
const classifyDeferredOverFace = (face, builtinDeferNames) => {
|
|
53
50
|
const mounted = new Set(face.map((t) => t.name));
|
|
54
51
|
const classified = classifyDeferredWithGate({
|
|
@@ -30,11 +30,11 @@ export interface PrepareDelegationSurfaceInput {
|
|
|
30
30
|
/** borrowed-readonly — the REBOUND spec. Read: `tools` (the shadow checks and the revival spawner's delegation-tool
|
|
31
31
|
* lookup), `oneShot` (the read/kill faces' completion promises), `retainBackgroundProcesses` (the Monitor receipt),
|
|
32
32
|
* `handsReadOnly` is NOT read here (the hands mount decided the surface). Never mutated. */
|
|
33
|
-
spec: Pick<TaskSpec, "tools" | "oneShot" | "retainBackgroundProcesses">;
|
|
33
|
+
spec: Pick<TaskSpec, "tools" | "oneShot" | "retainBackgroundProcesses" | "excludeAllTools">;
|
|
34
34
|
/** borrowed-readonly — the deployment seats the mounts read: `workflowRunStore` / `backgroundAgentStore` / `mailboxStore` (the
|
|
35
35
|
* read/kill faces and the tier-3 revival seams), `rosterStore`, `peerLane`, `peerDirectory`, `onNotice`,
|
|
36
36
|
* `onBackgroundChildEvent`, `tracer`. */
|
|
37
|
-
deps: Pick<RunnerDeps, "workflowRunStore" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "peerLane" | "peerDirectory" | "onNotice" | "onBackgroundChildEvent" | "tracer">;
|
|
37
|
+
deps: Pick<RunnerDeps, "workflowRunStore" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "peerLane" | "peerDirectory" | "principalInboxConsumer" | "onNotice" | "onBackgroundChildEvent" | "tracer">;
|
|
38
38
|
/** borrowed-readonly — the trusted spawn-side channel: `parentNotify` (the delegated-child door), the uplink / sibling /
|
|
39
39
|
* identity seats the SendMessage mount forwards, `onTaskNotification`, `onSubagentSpawn`. Never mutated. */
|
|
40
40
|
internals: Pick<RunInternals, "parentNotify" | "parentPeerRef" | "uplinkSessionId" | "parentRetainLedger" | "explicitAgentName" | "parentTaskId" | "parentSessionId" | "peerSelfRef" | "peerInboundChainRef" | "onTaskNotification" | "onSubagentSpawn"> | undefined;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME } from "../../agents/agent-transcript-tool.js";
|
|
2
2
|
import { createSendMessageTool, SEND_MESSAGE_TOOL_NAME } from "../../agents/send-message-tool.js";
|
|
3
|
-
import { listAgentsMountable, mountListAgents, peerLaneSendMessageSeats } from "../../agents/peer-session-drain.js";
|
|
3
|
+
import { listAgentsMountable, mountListAgents, peerLaneSendMessageSeats, terminalsDrainPrincipalInbox } from "../../agents/peer-session-drain.js";
|
|
4
4
|
import { resolvePeerLaneConfig } from "../../agents/peer-admission.js";
|
|
5
5
|
import { createReadInboxTool, READ_INBOX_TOOL_NAME } from "../../agents/read-inbox-tool.js";
|
|
6
|
+
import { valveLeaves } from "../../agents/tool-filter.js";
|
|
6
7
|
import { createMonitorTool } from "../../tools/monitor.js";
|
|
7
8
|
import { createWorktreeTools } from "../../tools/worktree.js";
|
|
8
9
|
import { createTaskOutputTool, createTaskStopTool, defaultTaskRegistry } from "../task-registry.js";
|
|
@@ -15,6 +16,7 @@ export function prepareDelegationSurface(input) {
|
|
|
15
16
|
const { spec, deps, internals, resume, sessionId, hostTaskId, taskScope, taskRootFinal, taskRootCanonical, executionEnv, runnerSelf, backgroundTaskToolsActive, workflowToolsActive, peerLaneActive, peerSendMessageBuiltIn, peerLaneRefs, sessionBox, roster, toolEffects, axisExplicitNegatives, envHandToolNames, toolFaceSnapshot, firstPartyOffload, offloadStore, subagentRetain, enrichSpecToolCtx, checkpointSeat, handsCwdRef, wsSnapshot, rebaseWsPath, rebaseRestoredPath, workspaceStateSettle } = input;
|
|
16
17
|
let worktreeSessionRef;
|
|
17
18
|
const delegationSurfaceActive = backgroundTaskToolsActive || workflowToolsActive;
|
|
19
|
+
const leaves = valveLeaves(spec, toolFaceSnapshot.selector);
|
|
18
20
|
let sendMessageTier;
|
|
19
21
|
if (delegationSurfaceActive || internals?.parentNotify !== undefined || peerLaneActive) {
|
|
20
22
|
if (delegationSurfaceActive) {
|
|
@@ -54,7 +56,7 @@ export function prepareDelegationSurface(input) {
|
|
|
54
56
|
...(deps.backgroundAgentStore !== undefined ? { agentStore: deps.backgroundAgentStore } : {}),
|
|
55
57
|
...(deps.mailboxStore !== undefined ? { mailbox: deps.mailboxStore } : {}),
|
|
56
58
|
...(reviveSpawn !== undefined ? { reviveSpawn } : {}),
|
|
57
|
-
...(peerLaneActive ? peerLaneSendMessageSeats({ peerDirectory: deps.peerDirectory, sessionId, scope: taskScope, ...(internals?.explicitAgentName !== undefined ? { name: internals.explicitAgentName } : {}), refs: peerLaneRefs, listingMounted: listAgentsMountable({
|
|
59
|
+
...(peerLaneActive ? peerLaneSendMessageSeats({ peerDirectory: deps.peerDirectory, sessionId, scope: taskScope, ...(internals?.explicitAgentName !== undefined ? { name: internals.explicitAgentName } : {}), refs: peerLaneRefs, listingMounted: listAgentsMountable({ leaves, specTools: spec.tools ?? [] }) }) : {}),
|
|
58
60
|
onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId: hostTaskId, site: f.site, message: f.error.message, ts: Date.now() })),
|
|
59
61
|
onTranscriptIntegrityGap: (handle, scope) => deliverEngineNotice(deps.onNotice, {
|
|
60
62
|
code: "delegation.transcript_integrity",
|
|
@@ -80,11 +82,11 @@ export function prepareDelegationSurface(input) {
|
|
|
80
82
|
}
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
|
-
if (sessionBox !== undefined && internals?.onTaskNotification !== undefined &&
|
|
85
|
+
if (sessionBox !== undefined && internals?.onTaskNotification !== undefined && leaves({ name: READ_INBOX_TOOL_NAME }) && !(spec.tools ?? []).some((t) => t.name === READ_INBOX_TOOL_NAME)) {
|
|
84
86
|
toolEffects.set(READ_INBOX_TOOL_NAME, "read");
|
|
85
|
-
roster.mount(firstPartyOffload(createReadInboxTool({ pull: () => peerLaneRefs.pull })), { source: "builtin", mountedBy: "peerLane" });
|
|
87
|
+
roster.mount(firstPartyOffload(createReadInboxTool({ pull: () => peerLaneRefs.pull, ...(terminalsDrainPrincipalInbox(deps) ? { coversPrincipalInbox: true } : {}) })), { source: "builtin", mountedBy: "peerLane" });
|
|
86
88
|
}
|
|
87
|
-
const listAgents = (peerLaneActive || delegationSurfaceActive) && peerSendMessageBuiltIn && listAgentsMountable({
|
|
89
|
+
const listAgents = (peerLaneActive || delegationSurfaceActive) && peerSendMessageBuiltIn && listAgentsMountable({ leaves, specTools: spec.tools ?? [] }) ? mountListAgents({ ...(peerLaneActive ? { peerDirectory: deps.peerDirectory } : {}), freshWindowMs: resolvePeerLaneConfig(deps.peerLane, deps.onNotice).listingFreshWindowMs, sessionId, scope: taskScope, hostTaskId, ...(internals?.parentTaskId !== undefined ? { parentTaskId: internals.parentTaskId } : {}), ...(internals?.parentSessionId !== undefined ? { parentSessionId: internals.parentSessionId } : {}), registry: defaultTaskRegistry, ...(deps.rosterStore !== undefined ? { roster: deps.rosterStore } : {}), ...(sendMessageTier !== undefined ? { continuationTier: sendMessageTier } : {}), ...(checkpointSeat !== undefined ? { readSeats: { checkpointSeat } } : {}), specTools: spec.tools ?? [], toolEffects }) : undefined;
|
|
88
90
|
if (listAgents !== undefined)
|
|
89
91
|
roster.mount(firstPartyOffload(listAgents), { source: "builtin", mountedBy: "peerLane" });
|
|
90
92
|
if (backgroundTaskToolsActive) {
|
|
@@ -88,7 +88,7 @@ export interface PrepareHandsReadFaceInput {
|
|
|
88
88
|
/** borrowed-readonly — the task-spec seats this phase reads, as a Pick over the SAME spec object
|
|
89
89
|
* (R-4). `tools` feeds only the band shadow check; `envFacts` only the advertised scratchpad;
|
|
90
90
|
* `retainBackgroundProcesses` only the band's retain lane (Bash's lifetime sentence + row stamp). */
|
|
91
|
-
spec: Pick<TaskSpec, "additionalDirectories" | "additionalReadDirectories" | "envFacts" | "handsReadOnly" | "readDenyPatterns" | "readFace" | "writeFace" | "oneShot" | "resumeAt" | "retainBackgroundProcesses" | "sessionId" | "tools">;
|
|
91
|
+
spec: Pick<TaskSpec, "additionalDirectories" | "additionalReadDirectories" | "envFacts" | "handsReadOnly" | "readDenyPatterns" | "readFace" | "writeFace" | "oneShot" | "resumeAt" | "retainBackgroundProcesses" | "sessionId" | "tools" | "excludeAllTools">;
|
|
92
92
|
/** borrowed-readonly — the deployment seats this phase reads, as a Pick over the SAME deps
|
|
93
93
|
* object (R-4: `deps.onError?.()` keeps its receiver; a new deps read must widen this Pick).
|
|
94
94
|
* `readDenyBuiltinTiers`/`readDenyBuiltinExclude` are SNAPSHOTTED before the first await that
|
|
@@ -21,6 +21,7 @@ import { RosterBuilder } from "../tool-roster.js";
|
|
|
21
21
|
import { unionAddOnly } from "../child-clamp-seats.js";
|
|
22
22
|
import { assertStringArraySeat } from "../read-face-seats.js";
|
|
23
23
|
import { modePolicyOf } from "../mode-policy.js";
|
|
24
|
+
import { valveLeaves } from "../../agents/tool-filter.js";
|
|
24
25
|
const faceClampAnnouncedSinks = { read: new WeakSet(), write: new WeakSet() };
|
|
25
26
|
const faceClampConsoleAnnounced = { read: false, write: false };
|
|
26
27
|
function announceDeploymentFaceClamp(kind, sink) {
|
|
@@ -370,7 +371,7 @@ export async function prepareHandsMount(input) {
|
|
|
370
371
|
return memoryWriteGate?.(w);
|
|
371
372
|
},
|
|
372
373
|
mountBackgroundTaskTools: false,
|
|
373
|
-
monitorToolActive: backgroundTaskToolsActive && toolFaceSnapshot.selector
|
|
374
|
+
monitorToolActive: backgroundTaskToolsActive && valveLeaves(spec, toolFaceSnapshot.selector)({ name: "Monitor" }),
|
|
374
375
|
});
|
|
375
376
|
{
|
|
376
377
|
const bandNames = new Set(band.flatMap((t) => [t.name, ...(t.aliases ?? [])]));
|
|
@@ -14,6 +14,7 @@ import { SessionModeSeats } from "./session-mode-seats.js";
|
|
|
14
14
|
import { recordedModeSeed } from "../checkpoint-store.js";
|
|
15
15
|
import { frozenSkillGrants } from "../skill-grant.js";
|
|
16
16
|
import { attachRebuiltDenialTrackers, createDenialLimitStop } from "./denial-limit-arms.js";
|
|
17
|
+
import { valveLeaves } from "../../agents/tool-filter.js";
|
|
17
18
|
export function prepareInheritedGate(input) {
|
|
18
19
|
const { spec, deps, askSeat, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, pathRuleAnchors, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun } = input;
|
|
19
20
|
const liveInheritedGate = internals?.inheritedGate;
|
|
@@ -192,8 +193,7 @@ export function prepareInheritedGate(input) {
|
|
|
192
193
|
const fullShellReachable = handsEnabled &&
|
|
193
194
|
!(executionEnv instanceof StubExecutionEnv) &&
|
|
194
195
|
spec.handsReadOnly !== true &&
|
|
195
|
-
spec.
|
|
196
|
-
toolFaceSnapshot.selector.admits({ name: "Bash" });
|
|
196
|
+
valveLeaves(spec, toolFaceSnapshot.selector)({ name: "Bash" });
|
|
197
197
|
const { gateStopRef, stopForDenialLimit } = createDenialLimitStop({ sessionId, runId, onNotice: deps.onNotice, abort: abortRun });
|
|
198
198
|
const delegationEntryCapsResolved = resolveDelegationEntryCaps(deps.delegationEntryCaps);
|
|
199
199
|
const enrichSpecToolCtx = (ctx) => {
|
|
@@ -5,7 +5,7 @@ import type { ResolvedSkillListingBudget } from "../skill-listing-budget.js";
|
|
|
5
5
|
export interface PrepareListingsInput {
|
|
6
6
|
/** borrowed-readonly — the REBOUND spec (`spec′`). Read: `tools` (the roster-bearing delegation tool, by its `agentListing`
|
|
7
7
|
* marker), `sessionId` (continuation ⇒ seeded/removal projections), `attachments` (the two opt-outs). Never mutated. */
|
|
8
|
-
spec: Pick<TaskSpec, "agents" | "tools" | "sessionId" | "attachments">;
|
|
8
|
+
spec: Pick<TaskSpec, "agents" | "tools" | "sessionId" | "attachments" | "excludeAllTools">;
|
|
9
9
|
/** borrowed-readonly — the once-per-session ledger: its deduplicated operator sink (`onError`) and
|
|
10
10
|
* the whole announced snapshot (`arms()`) the mirror is seeded from. */
|
|
11
11
|
onceLedger: AnnounceOnceSink & {
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { formatLocalDate } from "../../prompts/default.js";
|
|
2
|
+
import { valveLeaves } from "../../agents/tool-filter.js";
|
|
2
3
|
import { SKILL_TOOL_NAME } from "./synthetic-tools.js";
|
|
3
4
|
import { renderAgentListingDelta } from "./turn-attachments.js";
|
|
4
5
|
export function prepareListings(input) {
|
|
5
6
|
const { spec, onceLedger, sessionId, toolFaceSnapshot, activeTools, deferred, resume, skillsListing, listingBudget, listingRideRef, renderWithDate, envFacts, tzValid, userTz, dateAnchor } = input;
|
|
6
7
|
const rosterBearingSpec = (spec.tools ?? []).find((t) => t.agentListing !== undefined && t.agentListing.length > 0);
|
|
8
|
+
const leaves = valveLeaves(spec, toolFaceSnapshot.selector);
|
|
7
9
|
const rosterFaceDeferred = rosterBearingSpec !== undefined &&
|
|
8
|
-
|
|
10
|
+
leaves(rosterBearingSpec) &&
|
|
9
11
|
(toolFaceSnapshot.defer?.includes(rosterBearingSpec.name) ?? false) &&
|
|
10
12
|
deferred.has(rosterBearingSpec.name) &&
|
|
11
13
|
!activeTools.has(rosterBearingSpec.name);
|
|
12
14
|
const agentListingSpec = rosterBearingSpec !== undefined &&
|
|
13
15
|
!rosterFaceDeferred &&
|
|
14
|
-
|
|
16
|
+
leaves(rosterBearingSpec)
|
|
15
17
|
? rosterBearingSpec
|
|
16
18
|
: undefined;
|
|
17
19
|
const agentListing = agentListingSpec
|
|
@@ -12,12 +12,8 @@
|
|
|
12
12
|
* installs, which run at tool-call time), so the phase adds no yield between the deferred classification before it
|
|
13
13
|
* and the prompt assembly after it (a stretch with no await is extracted as a sync function).
|
|
14
14
|
* Read-stability of the host handles for the call: {@link RunInternals} (`@contract prepare.deps-read-stable`).
|
|
15
|
-
*
|
|
16
|
-
* One read changed spelling and nothing else: the declared-class announcement read `mcp?.statuses` while `mcp` had
|
|
17
|
-
* long been the protocol-tools phase's non-null handle; the optional chain was dead and is now the plain member read.
|
|
18
15
|
*/
|
|
19
16
|
import type { LockedPreflight } from "../locked-config.js";
|
|
20
|
-
import type { MaterializedMcp } from "../mcp.js";
|
|
21
17
|
import { type DelegationContentSafety } from "../memory-engine/delegation-provenance.js";
|
|
22
18
|
import type { RunnerDeps, TaskSpec } from "../types.js";
|
|
23
19
|
import type { Prepared, RunInternals } from "./contracts.js";
|
|
@@ -40,8 +36,6 @@ export interface PrepareMemoryEngineSessionInput {
|
|
|
40
36
|
lockedPreflight: Pick<LockedPreflight, "mcp">;
|
|
41
37
|
/** borrowed-readonly — the run's MCP mount, read at call time (present iff the run declared a server): the children a delegation tool spawns inherit it, so its tools are rows of their pool. */
|
|
42
38
|
mountedMcp?: () => import("../mounted-mcp.js").MountedMcp;
|
|
43
|
-
/** borrowed-readonly — the materialized MCP handle; only `statuses` (the announcement's mounted-tool count). */
|
|
44
|
-
mcp: Pick<MaterializedMcp, "statuses">;
|
|
45
39
|
/** borrowed-readonly — the acquired session id (notice detail). */
|
|
46
40
|
sessionId: string;
|
|
47
41
|
/** borrowed-readonly — the run's invocation id (notice detail; the once-per-leg claims are per-RUN claims). */
|