@sema-agent/core 7.21.1 → 7.23.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 +290 -1
- package/dist/agents/send-message-tool.js +1 -0
- package/dist/agents/subagent.d.ts +1 -0
- package/dist/agents/subagent.js +2 -1
- package/dist/core/ask-origin.d.ts +1 -0
- package/dist/core/ask-origin.js +3 -2
- package/dist/core/auto-compaction.d.ts +2 -2
- package/dist/core/auto-mode-rebuild.js +6 -2
- package/dist/core/auto-mode.d.ts +40 -18
- package/dist/core/auto-mode.js +63 -45
- package/dist/core/checkpoint-store.d.ts +9 -13
- package/dist/core/context-edit.js +1 -1
- package/dist/core/engine-notice.d.ts +62 -1
- package/dist/core/engine-notice.js +14 -1
- package/dist/core/gate-bounded-await.d.ts +13 -3
- package/dist/core/gate-fold.js +3 -3
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +6 -0
- package/dist/core/mcp.d.ts +65 -0
- package/dist/core/mcp.js +190 -41
- package/dist/core/memory-engine/consolidation.d.ts +5 -0
- package/dist/core/memory-engine/consolidation.js +7 -3
- package/dist/core/memory-engine/engine.d.ts +8 -0
- package/dist/core/memory-engine/engine.js +25 -19
- package/dist/core/memory-engine/layout.d.ts +47 -9
- package/dist/core/memory-engine/layout.js +157 -57
- package/dist/core/memory-engine/session-incarnation.d.ts +27 -0
- package/dist/core/memory-engine/session-incarnation.js +63 -0
- package/dist/core/parent-spec-seat.d.ts +15 -3
- package/dist/core/parent-spec-seat.js +5 -0
- package/dist/core/park-selfcheck.js +1 -1
- package/dist/core/path-identity.d.ts +11 -4
- package/dist/core/path-identity.js +5 -2
- package/dist/core/permission-rule-model.d.ts +1 -2
- package/dist/core/read-root-candidate.js +11 -1
- package/dist/core/retention.d.ts +8 -1
- package/dist/core/retention.js +2 -0
- package/dist/core/runner/assemble-result.d.ts +2 -7
- package/dist/core/runner/assemble-result.js +25 -8
- package/dist/core/runner/classifier-ladder.js +1 -0
- package/dist/core/runner/contracts.d.ts +26 -15
- package/dist/core/runner/inherited-ask-grants.d.ts +2 -7
- package/dist/core/runner/inherited-ask-grants.js +1 -0
- package/dist/core/runner/mcp-redial.d.ts +109 -0
- package/dist/core/runner/mcp-redial.js +60 -0
- package/dist/core/runner/memory-consolidation-driver.d.ts +2 -0
- package/dist/core/runner/prepare-ask-lane.js +1 -0
- package/dist/core/runner/prepare-caps-and-workflow.js +9 -12
- package/dist/core/runner/prepare-context-lane.d.ts +43 -1
- package/dist/core/runner/prepare-context-lane.js +25 -4
- package/dist/core/runner/prepare-hands-readface.d.ts +3 -0
- package/dist/core/runner/prepare-hands-readface.js +13 -3
- package/dist/core/runner/prepare-memory.js +3 -3
- package/dist/core/runner/prepare-protocol-tools.d.ts +6 -1
- package/dist/core/runner/prepare-protocol-tools.js +20 -38
- package/dist/core/runner/prepare-task.js +4 -4
- package/dist/core/runner/prepare-turn-wiring.js +2 -2
- package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -0
- package/dist/core/runner/prepare-wiring-manifest.js +2 -1
- package/dist/core/runner/run-harness-handlers.js +4 -2
- package/dist/core/runner/run-identity-wiring.d.ts +3 -1
- package/dist/core/runner/run-identity-wiring.js +4 -1
- package/dist/core/runner/run-recovery-lanes.js +6 -3
- package/dist/core/runner/run-settle-and-teardown.d.ts +3 -1
- package/dist/core/runner/run-settle-and-teardown.js +6 -2
- package/dist/core/runner/run-telemetry-and-budget-seats.js +11 -1
- package/dist/core/runner/run-terminal-adoption.d.ts +4 -1
- package/dist/core/runner/run-terminal-adoption.js +2 -6
- package/dist/core/runner/runtask.js +8 -5
- package/dist/core/runner/stream-lifecycle-verbs.d.ts +5 -1
- package/dist/core/runner/stream-lifecycle-verbs.js +23 -2
- package/dist/core/runner/write-protection-station.d.ts +7 -25
- package/dist/core/runner/write-protection-station.js +18 -0
- package/dist/core/runner-deps.d.ts +16 -7
- package/dist/core/skill-listing-budget.d.ts +5 -4
- package/dist/core/task-registry.d.ts +0 -6
- package/dist/core/task-result.d.ts +31 -12
- package/dist/core/task-spec.d.ts +2 -1
- package/dist/core/task-stream.d.ts +26 -0
- package/dist/core/tool-spec.d.ts +5 -1
- package/dist/core/trace.d.ts +5 -0
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js +1 -1
- package/dist/core/wiring-manifest.d.ts +23 -0
- package/dist/core/wiring-manifest.js +3 -0
- package/dist/core/write-protect.d.ts +64 -12
- package/dist/core/write-protect.js +88 -34
- package/dist/engine/execution-env/node-execution-env.d.ts +19 -2
- package/dist/engine/execution-env/node-execution-env.js +5 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +2 -2
- package/dist/orchestration/workflow-governance.js +1 -1
- package/dist/orchestration/workflow-primitives.d.ts +2 -2
- package/dist/tools/fs/bash-program-position.d.ts +26 -5
- package/dist/tools/fs/bash-program-position.js +63 -16
- package/dist/tools/fs/bash-readonly-classifier.d.ts +27 -17
- package/dist/tools/fs/bash-readonly-classifier.js +134 -55
- package/dist/tools/fs/fs-bash.js +43 -18
- package/dist/tools/fs/fs-read.js +2 -1
- package/dist/tools/fs/fs-shared.d.ts +33 -7
- package/dist/tools/fs/fs-shared.js +12 -1
- package/dist/tools/fs/index.d.ts +4 -2
- package/dist/tools/fs/read-deny.d.ts +25 -11
- package/dist/tools/fs/read-deny.js +5 -1
- package/dist/tools/fs/safety.d.ts +38 -4
- package/dist/tools/fs/safety.js +31 -3
- package/package.json +2 -2
- package/test/export-surface.snapshot.json +11 -1
- package/wire-changes/core@7.22.0.json +637 -0
- package/wire-changes/core@7.23.0.json +316 -0
|
@@ -7,8 +7,9 @@ import { createOffloadPersist } from "../tool-result-store.js";
|
|
|
7
7
|
import { emitTrace } from "../trace.js";
|
|
8
8
|
import { deliverEngineNotice } from "../types.js";
|
|
9
9
|
import { applyGitFrameGuard } from "./git-status-frame.js";
|
|
10
|
+
import { applyContextShrinkToReadFileState } from "../../tools/fs/index.js";
|
|
10
11
|
export function prepareContextLane(input) {
|
|
11
|
-
const { model, deps, sessionId, runId, hostTaskId, offloadStore, microCompactKnob, harness, batchHaltRef, gitStatusRef, requestLossyRef, trimPressureRef } = input;
|
|
12
|
+
const { model, deps, sessionId, runId, hostTaskId, offloadStore, microCompactKnob, harness, batchHaltRef, gitStatusRef, requestLossyRef, trimPressureRef, readFileState } = input;
|
|
12
13
|
const editAt = editBudget(model);
|
|
13
14
|
const guardAt = guardBudget(model);
|
|
14
15
|
const microCompact = buildMicroCompactState(deps, model, sessionId, runId, offloadStore, microCompactKnob);
|
|
@@ -57,12 +58,13 @@ export function prepareContextLane(input) {
|
|
|
57
58
|
: {}),
|
|
58
59
|
});
|
|
59
60
|
if (ccPass !== undefined) {
|
|
60
|
-
recordFrontierClears({ pass: ccPass, index: replay.index, edited, ledger: microCompact.ledger, tracer: deps.tracer, taskId: hostTaskId, trigger: "frontier" });
|
|
61
|
+
recordFrontierClears({ pass: ccPass, index: replay.index, edited, ledger: microCompact.ledger, tracer: deps.tracer, taskId: hostTaskId, trigger: "frontier", ...(readFileState !== undefined ? { readFileState } : {}) });
|
|
61
62
|
}
|
|
62
63
|
const chain = await runGuardChain({
|
|
63
64
|
edited, replayed, index: replay.index, microCompact, guardAt, charsPerToken, offloadStore,
|
|
64
65
|
sessionId, taskId: hostTaskId, deps, trimPressureRef, recheck, signal,
|
|
65
66
|
pendingProjectionObservations,
|
|
67
|
+
...(readFileState !== undefined ? { readFileState } : {}),
|
|
66
68
|
});
|
|
67
69
|
if ("earlyReturn" in chain) {
|
|
68
70
|
return chain.earlyReturn;
|
|
@@ -138,15 +140,34 @@ function buildMicroCompactState(deps, model, sessionId, runId, offloadStore, kno
|
|
|
138
140
|
...(offloadStore ? { offloadPersist: createOffloadPersist(offloadStore, sessionId, deps.onNotice) } : {}),
|
|
139
141
|
};
|
|
140
142
|
}
|
|
143
|
+
export function landStaleResultClears(args) {
|
|
144
|
+
const clearedToolCallIds = [];
|
|
145
|
+
for (const c of args.cleared) {
|
|
146
|
+
args.ledger.entries.set(c.key, { marker: c.marker, groupCount: c.groupCount, fp: c.fp });
|
|
147
|
+
if (c.toolCallId !== undefined)
|
|
148
|
+
clearedToolCallIds.push(c.toolCallId);
|
|
149
|
+
}
|
|
150
|
+
if (args.readFileState !== undefined) {
|
|
151
|
+
applyContextShrinkToReadFileState(args.readFileState, { kind: "tool-results-cleared", clearedToolCallIds });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
141
154
|
function recordFrontierClears(args) {
|
|
155
|
+
const landed = [];
|
|
142
156
|
for (const { index } of args.pass.clears) {
|
|
143
157
|
const at = args.index.keyAt(index);
|
|
144
158
|
const clearedMsg = args.edited[index];
|
|
145
159
|
const markerText = clearedMsg.content?.[0]?.text;
|
|
146
160
|
if (at !== undefined && typeof markerText === "string") {
|
|
147
|
-
|
|
161
|
+
landed.push({
|
|
162
|
+
key: at.key,
|
|
163
|
+
marker: markerText,
|
|
164
|
+
groupCount: at.groupCount,
|
|
165
|
+
fp: at.fp,
|
|
166
|
+
...(typeof clearedMsg.toolCallId === "string" ? { toolCallId: clearedMsg.toolCallId } : {}),
|
|
167
|
+
});
|
|
148
168
|
}
|
|
149
169
|
}
|
|
170
|
+
landStaleResultClears({ ledger: args.ledger, cleared: landed, ...(args.readFileState !== undefined ? { readFileState: args.readFileState } : {}) });
|
|
150
171
|
emitTrace(args.tracer, () => ({
|
|
151
172
|
kind: "context.mc_clear",
|
|
152
173
|
version: 1,
|
|
@@ -198,7 +219,7 @@ export async function runGuardChain(args) {
|
|
|
198
219
|
...(args.offloadStore ? { offload: { persist: createOffloadPersist(args.offloadStore, args.sessionId, deps.onNotice) } } : {}),
|
|
199
220
|
});
|
|
200
221
|
if (blockingPass !== undefined) {
|
|
201
|
-
recordFrontierClears({ pass: blockingPass, index: args.index, edited: blockingEdited, ledger: microCompact.ledger, tracer: deps.tracer, taskId, trigger: "blocking" });
|
|
222
|
+
recordFrontierClears({ pass: blockingPass, index: args.index, edited: blockingEdited, ledger: microCompact.ledger, tracer: deps.tracer, taskId, trigger: "blocking", ...(args.readFileState !== undefined ? { readFileState: args.readFileState } : {}) });
|
|
202
223
|
working = blockingEdited;
|
|
203
224
|
anchoredWorking = estimateContextTokens(working, charsPerToken).tokens;
|
|
204
225
|
}
|
|
@@ -284,6 +284,9 @@ export interface PrepareHandsReadFaceResult {
|
|
|
284
284
|
pattern: string;
|
|
285
285
|
caseSensitive: boolean;
|
|
286
286
|
}>;
|
|
287
|
+
/** owned — the built-in deny TIERS this leg MATERIALLY activated, off the same snapshot the compile
|
|
288
|
+
* judged with; empty ⇒ none. Relayed to the wiring manifest, never re-derived from `deps` there. */
|
|
289
|
+
readDenyBuiltinTiersActive: readonly string[];
|
|
287
290
|
/** write-back (D-3 hold) — the hands-LESS legs' resolved face (the read posture is a
|
|
288
291
|
* property of the RUN, not the mount). Driver assigns onto its outer `let`. */
|
|
289
292
|
handsLessResolvedFace: ContainmentFace | undefined;
|
|
@@ -3,7 +3,7 @@ import { StubExecutionEnv } from "../stub-env.js";
|
|
|
3
3
|
import { hasBackgroundShell } from "../background-shell.js";
|
|
4
4
|
import { boundaryIsTheSandbox } from "../remote-env.js";
|
|
5
5
|
import { defaultTaskRegistry } from "../task-registry.js";
|
|
6
|
-
import { bashReadBoundaryProbe, bashReversibilityProbe, compileReadDeny, createHandsToolkit, deploymentFaceClampNotice, pdfModelCapabilitiesOf,
|
|
6
|
+
import { bashReadBoundaryProbe, bashReversibilityProbe, activeReadDenyBuiltinTiers, compileReadDeny, createHandsToolkit, deploymentFaceClampNotice, pdfModelCapabilitiesOf, inheritSessionReadFileState, resolveContainmentFace, seedReadFileStateFromContext, seedReadFileStateFromTranscript, } from "../../tools/fs/index.js";
|
|
7
7
|
import { resolveKey, sha256 } from "../../tools/fs/safety.js";
|
|
8
8
|
import { normalizeFileText } from "../../tools/fs/encoding.js";
|
|
9
9
|
import { wholeFileRecordsFromTranscript } from "./session-file-state-replay.js";
|
|
@@ -98,6 +98,7 @@ export function resolveHandsLessReadFace(input) {
|
|
|
98
98
|
let handsLessResolvedFace;
|
|
99
99
|
let handsLessResolvedWriteFace;
|
|
100
100
|
let readDenyAdditionsNormalized = [];
|
|
101
|
+
let readDenyBuiltinTiersActive = [];
|
|
101
102
|
{
|
|
102
103
|
const liveFace = resolveContainmentFace({
|
|
103
104
|
kind: "read",
|
|
@@ -120,7 +121,7 @@ export function resolveHandsLessReadFace(input) {
|
|
|
120
121
|
const seedWrite = resume?.seed.writeFace;
|
|
121
122
|
handsLessResolvedWriteFace = resume !== undefined && (seedWrite === undefined || seedWrite.face === "roots") ? "roots" : liveWriteFace;
|
|
122
123
|
const denyAdditions = [...(deps.readDenyPatterns ?? []), ...(spec.readDenyPatterns ?? []), ...(seed?.denyEntries ?? [])];
|
|
123
|
-
|
|
124
|
+
readDenyBuiltinTiersActive = activeReadDenyBuiltinTiers({
|
|
124
125
|
...(deps.readDenyBuiltinTiers !== undefined ? { tiers: deps.readDenyBuiltinTiers } : {}),
|
|
125
126
|
...(deps.readDenyBuiltinExclude !== undefined ? { exclude: deps.readDenyBuiltinExclude } : {}),
|
|
126
127
|
});
|
|
@@ -139,6 +140,7 @@ export function resolveHandsLessReadFace(input) {
|
|
|
139
140
|
resolvedReadFace: undefined,
|
|
140
141
|
resolvedWriteFace: undefined,
|
|
141
142
|
readDenyAdditionsNormalized,
|
|
143
|
+
readDenyBuiltinTiersActive,
|
|
142
144
|
handsLessResolvedFace,
|
|
143
145
|
handsLessResolvedWriteFace,
|
|
144
146
|
additionalRootsCanonical: [],
|
|
@@ -168,6 +170,7 @@ export async function prepareHandsMount(input) {
|
|
|
168
170
|
let resolvedReadFace;
|
|
169
171
|
let resolvedWriteFace;
|
|
170
172
|
let readDenyAdditionsNormalized = [];
|
|
173
|
+
let readDenyBuiltinTiersActive = [];
|
|
171
174
|
let handsLessResolvedFace;
|
|
172
175
|
const handsLessResolvedWriteFace = undefined;
|
|
173
176
|
const shellGatedTools = new Set();
|
|
@@ -245,6 +248,7 @@ export async function prepareHandsMount(input) {
|
|
|
245
248
|
...(deps.readDenyBuiltinExclude !== undefined ? { exclude: [...deps.readDenyBuiltinExclude] } : {}),
|
|
246
249
|
};
|
|
247
250
|
readDenyMatcher = compileReadDeny(readDenyAdditions, "readDenyPatterns", readDenyBuiltinCfg);
|
|
251
|
+
readDenyBuiltinTiersActive = activeReadDenyBuiltinTiers(readDenyBuiltinCfg);
|
|
248
252
|
readDenyAdditionsNormalized = compileReadDeny(readDenyAdditions, "readDenyPatterns", { tiers: [] }).entries;
|
|
249
253
|
let liveReadFace = resolveContainmentFace({
|
|
250
254
|
kind: "read",
|
|
@@ -323,11 +327,16 @@ export async function prepareHandsMount(input) {
|
|
|
323
327
|
sessionSeats.reanchor(sessionId, readFileState, ownCommittedTailEntryId);
|
|
324
328
|
}
|
|
325
329
|
: undefined;
|
|
330
|
+
const compiledDeny = readDenyMatcher;
|
|
331
|
+
const denySeatJudge = compiledDeny !== undefined && compiledDeny.entries.length > 0
|
|
332
|
+
? (p) => compiledDeny.matchPath(p)?.pattern ?? null
|
|
333
|
+
: undefined;
|
|
326
334
|
const shellReadBoundary = () => ({
|
|
327
335
|
roots: [rootCanonical, ...additionalRootsCanonical, ...additionalReadRootsCanonical],
|
|
328
336
|
...(handsCwdRef?.current !== undefined ? { cwd: handsCwdRef.current } : {}),
|
|
329
337
|
...(executionEnv.homeDir !== undefined ? { homeDir: executionEnv.homeDir } : {}),
|
|
330
|
-
denyMatch:
|
|
338
|
+
...(denySeatJudge !== undefined ? { denyMatch: denySeatJudge } : {}),
|
|
339
|
+
denyEntries: (compiledDeny?.entries ?? []).map((e) => e.pattern),
|
|
331
340
|
...(resolvedReadFace !== undefined ? { face: resolvedReadFace } : {}),
|
|
332
341
|
});
|
|
333
342
|
const band = createHandsToolkit(executionEnv, readFileState, rootCanonical, {
|
|
@@ -421,6 +430,7 @@ export async function prepareHandsMount(input) {
|
|
|
421
430
|
resolvedWriteFace,
|
|
422
431
|
handsLessResolvedWriteFace,
|
|
423
432
|
readDenyAdditionsNormalized,
|
|
433
|
+
readDenyBuiltinTiersActive,
|
|
424
434
|
handsLessResolvedFace,
|
|
425
435
|
additionalRootsCanonical,
|
|
426
436
|
additionalReadRootsCanonical,
|
|
@@ -171,7 +171,7 @@ export async function prepareMemory(input) {
|
|
|
171
171
|
const choosePersonalBackend = () => typeof pinned === "string" && pinned ? new FileMemoryEngineBackend(personalMemoryDir, { controlDir: personalControlDir }) : backend;
|
|
172
172
|
const createPersonalEngine = (personalBackend) => {
|
|
173
173
|
return {
|
|
174
|
-
engine: new MemoryEngine({ backend: personalBackend, memoryDir: personalMemoryDir, controlDir: personalControlDir, onIncident: onEngineIncident, provenance: input.memoryProvenance, ...captureStoreOpt(personalBackend, personalControlDir), ...(input.deps.memoryConsolidation !== undefined ? { consolidation: input.deps.memoryConsolidation } : {}) }),
|
|
174
|
+
engine: new MemoryEngine({ backend: personalBackend, memoryDir: personalMemoryDir, controlDir: personalControlDir, onIncident: onEngineIncident, provenance: input.memoryProvenance, ...captureStoreOpt(personalBackend, personalControlDir), ...(deps.memorySessionIncarnation !== undefined ? { sessionIncarnation: deps.memorySessionIncarnation } : {}), ...(input.deps.memoryConsolidation !== undefined ? { consolidation: input.deps.memoryConsolidation } : {}) }),
|
|
175
175
|
backend: personalBackend,
|
|
176
176
|
};
|
|
177
177
|
};
|
|
@@ -359,7 +359,7 @@ export async function prepareMemory(input) {
|
|
|
359
359
|
controlDir: identityKey !== undefined ? deriveProjectControlDir(engineRoot, identityKey) : deriveRepoControlPlaneDir(engineRoot, repoRoot),
|
|
360
360
|
onIncident: onEngineIncident,
|
|
361
361
|
provenance: input.memoryProvenance,
|
|
362
|
-
...captureStoreOpt(backend, identityKey !== undefined ? deriveProjectControlDir(engineRoot, identityKey) : deriveRepoControlPlaneDir(engineRoot, repoRoot)),
|
|
362
|
+
...captureStoreOpt(backend, identityKey !== undefined ? deriveProjectControlDir(engineRoot, identityKey) : deriveRepoControlPlaneDir(engineRoot, repoRoot)), ...(deps.memorySessionIncarnation !== undefined ? { sessionIncarnation: deps.memorySessionIncarnation } : {}),
|
|
363
363
|
...(input.deps.memoryConsolidation !== undefined ? { consolidation: input.deps.memoryConsolidation } : {}),
|
|
364
364
|
});
|
|
365
365
|
const personal = createPersonalEngine(personalBackendChosen);
|
|
@@ -439,7 +439,7 @@ export async function prepareMemory(input) {
|
|
|
439
439
|
controlDir: identityKey !== undefined ? deriveProjectControlDir(engineRoot, identityKey) : deriveRepoControlPlaneDir(engineRoot, repoRoot),
|
|
440
440
|
onIncident: onEngineIncident,
|
|
441
441
|
provenance: input.memoryProvenance,
|
|
442
|
-
...captureStoreOpt(backend, identityKey !== undefined ? deriveProjectControlDir(engineRoot, identityKey) : deriveRepoControlPlaneDir(engineRoot, repoRoot)),
|
|
442
|
+
...captureStoreOpt(backend, identityKey !== undefined ? deriveProjectControlDir(engineRoot, identityKey) : deriveRepoControlPlaneDir(engineRoot, repoRoot)), ...(deps.memorySessionIncarnation !== undefined ? { sessionIncarnation: deps.memorySessionIncarnation } : {}),
|
|
443
443
|
...(input.deps.memoryConsolidation !== undefined ? { consolidation: input.deps.memoryConsolidation } : {}),
|
|
444
444
|
});
|
|
445
445
|
await armCaptureOptOut(engine);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentTool } from "../../internal/harness.js";
|
|
2
|
-
import { type MaterializedMcp, type McpDroppedTool } from "../mcp.js";
|
|
2
|
+
import { type MaterializedMcp, type McpDroppedTool, type McpReconnectResult } from "../mcp.js";
|
|
3
3
|
import { type MaterializedA2a } from "../a2a.js";
|
|
4
4
|
import type { LockedPreflight } from "../locked-config.js";
|
|
5
5
|
import type { RunnerDeps, TaskSpec, ToolEffect } from "../types.js";
|
|
@@ -90,6 +90,11 @@ export interface PrepareProtocolToolsResult {
|
|
|
90
90
|
toolCallGateArmedRef: {
|
|
91
91
|
armed: boolean;
|
|
92
92
|
};
|
|
93
|
+
/** owned — the run handle's `reconnectMcpServer` implementation, present ONLY when this leg declared
|
|
94
|
+
* MCP servers (a leg with none has nothing to re-dial, and the stream verb refuses typed rather
|
|
95
|
+
* than answering about a materialization that was never made). The driver projects it onto
|
|
96
|
+
* `Prepared.mcpRedial`, from which the run's wiring binds the verb's seat. */
|
|
97
|
+
mcpRedial?: (server: string) => Promise<McpReconnectResult>;
|
|
93
98
|
}
|
|
94
99
|
/** The M5 phase body — prepareTask's protocol-tools stretch, verbatim (see the module header). */
|
|
95
100
|
export declare function prepareProtocolTools(input: PrepareProtocolToolsInput): Promise<PrepareProtocolToolsResult>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
import { materializeMcpTools } from "../mcp.js";
|
|
3
|
+
import { applyMcpRosterDelta, commitMcpRosterChanges, redialMcpServer } from "./mcp-redial.js";
|
|
3
4
|
import { materializeA2aTools } from "../a2a.js";
|
|
4
5
|
import { deliverEngineNotice } from "../types.js";
|
|
5
6
|
import { RosterBuilder } from "../tool-roster.js";
|
|
@@ -16,7 +17,8 @@ export async function prepareProtocolTools(input) {
|
|
|
16
17
|
}
|
|
17
18
|
const mcp = lockedPreflight.mcp?.length
|
|
18
19
|
? await materializeMcpTools(lockedPreflight.mcp, spec.principal, deps.onElicit, deps.mcpImageResizer, { reminderMark, counts: reminderDisclosureCounts }, mcpRevocationWiring(deps, runId))
|
|
19
|
-
:
|
|
20
|
+
:
|
|
21
|
+
{ tools: [], toolAxes: [], warnings: [], serverInstructions: [], instructionsDelta: { pendingAdds: [], pendingRemovals: [] }, droppedTools: [], statuses: [], refresh: async () => [], reconnect: async (server) => ({ server, prefix: mintNamespacePrefix(MCP_NAMESPACE, server), outcome: "not_declared", reason: "this task declared no MCP servers", toolCount: 0, added: [], removed: [] }), dispose: async () => { } };
|
|
20
22
|
if (lockedPreflight.mcp?.length)
|
|
21
23
|
rollback.push(function mcpDispose() { return mcp.dispose(); });
|
|
22
24
|
for (const w of mcp.warnings)
|
|
@@ -58,6 +60,10 @@ export async function prepareProtocolTools(input) {
|
|
|
58
60
|
const rebuildHarnessToolsRef = {};
|
|
59
61
|
const contentOriginWrapRef = {};
|
|
60
62
|
const toolCallGateArmedRef = { armed: false };
|
|
63
|
+
const rosterApply = { toolFaceSnapshot, withFaces, remoteToolOffload, foldProtocolAxes: (axes, label) => foldProtocolAxes(axes, label), toolEffects, axisExplicitNegatives, roster };
|
|
64
|
+
const rosterCommit = { rebuildHarnessToolsRef, rosterSeat, toolCallGateArmedRef, irreversibleTools, egressTools };
|
|
65
|
+
const redialInput = { ...rosterApply, ...rosterCommit, mcp, deps, sessionId, runId, irreversibilityTier };
|
|
66
|
+
const mcpRedial = lockedPreflight.mcp?.length ? (server) => redialMcpServer(redialInput, server) : undefined;
|
|
61
67
|
if (lockedPreflight.mcp?.length) {
|
|
62
68
|
roster.mount({
|
|
63
69
|
...toolFace("refresh-mcp-tools"),
|
|
@@ -73,42 +79,20 @@ export async function prepareProtocolTools(input) {
|
|
|
73
79
|
const lines = [];
|
|
74
80
|
let changed = false;
|
|
75
81
|
let anyActiveFailure = false;
|
|
82
|
+
const excludedSet = new Set(toolFaceSnapshot.exclude ?? []);
|
|
76
83
|
for (const r of results) {
|
|
77
|
-
if (r.
|
|
84
|
+
if (r.tools === undefined) {
|
|
78
85
|
lines.push(`${r.server}: ${r.status}${r.error !== undefined ? ` (${r.error})` : ""}`);
|
|
79
86
|
if (r.status === "failed")
|
|
80
87
|
anyActiveFailure = true;
|
|
81
88
|
continue;
|
|
82
89
|
}
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const domainSnapshot = (m) => new Map([...m].filter(([name]) => name.startsWith(r.prefix)));
|
|
87
|
-
const restoreDomain = (m, snap) => {
|
|
88
|
-
for (const name of [...m.keys()])
|
|
89
|
-
if (name.startsWith(r.prefix))
|
|
90
|
-
m.delete(name);
|
|
91
|
-
for (const [name, v] of snap)
|
|
92
|
-
m.set(name, v);
|
|
93
|
-
};
|
|
94
|
-
const priorDomainEffects = domainSnapshot(toolEffects);
|
|
95
|
-
const priorDomainNegatives = domainSnapshot(axisExplicitNegatives);
|
|
96
|
-
for (const name of priorDomainEffects.keys())
|
|
97
|
-
toolEffects.delete(name);
|
|
98
|
-
for (const name of priorDomainNegatives.keys())
|
|
99
|
-
axisExplicitNegatives.delete(name);
|
|
100
|
-
try {
|
|
101
|
-
foldProtocolAxes((r.axes ?? []).filter((a) => !excludedSet.has(a.name)), "MCP");
|
|
102
|
-
}
|
|
103
|
-
catch (foldErr) {
|
|
104
|
-
restoreDomain(toolEffects, priorDomainEffects);
|
|
105
|
-
restoreDomain(axisExplicitNegatives, priorDomainNegatives);
|
|
106
|
-
lines.push(`${r.server}: failed (${foldErr instanceof Error ? foldErr.message : String(foldErr)})`);
|
|
90
|
+
const applied = applyMcpRosterDelta(rosterApply, { server: r.server, prefix: r.prefix, tools: r.tools, axes: r.axes ?? [], dropped: r.dropped ?? [] });
|
|
91
|
+
if (!applied.applied) {
|
|
92
|
+
lines.push(`${r.server}: failed (${applied.foldError})`);
|
|
107
93
|
anyActiveFailure = true;
|
|
108
94
|
continue;
|
|
109
95
|
}
|
|
110
|
-
const refreshedMounts = withFaces(pushable, r.server).map((t) => remoteToolOffload(t));
|
|
111
|
-
roster.replaceDomain(r.prefix, refreshedMounts, { source: "mcp", mountedBy: "optional", origin: { peer: r.server } });
|
|
112
96
|
changed = true;
|
|
113
97
|
const detail = [];
|
|
114
98
|
const shownAdded = r.added.filter((n) => !excludedSet.has(n));
|
|
@@ -116,18 +100,16 @@ export async function prepareProtocolTools(input) {
|
|
|
116
100
|
detail.push(`added: ${shownAdded.join(", ")}`);
|
|
117
101
|
if (r.removed.length > 0)
|
|
118
102
|
detail.push(`removed: ${r.removed.join(", ")}`);
|
|
119
|
-
if (
|
|
120
|
-
detail.push(`excluded by deployment config (not mounted): ${
|
|
103
|
+
if (applied.excluded.length > 0)
|
|
104
|
+
detail.push(`excluded by deployment config (not mounted): ${applied.excluded.join(", ")}`);
|
|
121
105
|
if ((r.dropped?.length ?? 0) > 0)
|
|
122
106
|
detail.push(`dropped: ${r.dropped.map((d) => `${d.tool} (${d.reason.length > 90 ? `${d.reason.slice(0, 90)}…` : d.reason})`).join("; ")}`);
|
|
123
|
-
lines.push(`${r.server}: refreshed — ${
|
|
107
|
+
lines.push(`${r.server}: refreshed — ${applied.pushed} tool${applied.pushed === 1 ? "" : "s"}${detail.length > 0 ? ` (${detail.join("; ")})` : ""}`);
|
|
124
108
|
}
|
|
125
|
-
if (changed)
|
|
126
|
-
await
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (changed && !toolCallGateArmedRef.armed && (irreversibleTools.size > 0 || egressTools.size > 0)) {
|
|
130
|
-
lines.push("WARNING: refreshed tools declare irreversible/egress safety hints, but this task started with no approval gate registered (no policy/hooks and no gated tools at start) — these hints cannot arm a gate mid-task (RB-46); the refreshed tools run ungated on this deployment shape.");
|
|
109
|
+
if (changed) {
|
|
110
|
+
const ungated = await commitMcpRosterChanges(rosterCommit);
|
|
111
|
+
if (ungated !== undefined)
|
|
112
|
+
lines.push(ungated);
|
|
131
113
|
}
|
|
132
114
|
const text = lines.length === 0 ? "No connected MCP servers to refresh." : lines.join("\n");
|
|
133
115
|
return {
|
|
@@ -184,7 +166,7 @@ export async function prepareProtocolTools(input) {
|
|
|
184
166
|
for (const t of a2a.tools)
|
|
185
167
|
roster.mount(remoteToolOffload(t), { source: "a2a", mountedBy: "optional", origin: { peer: A2A_NAMESPACE.parse(t.name)?.peer ?? t.name } });
|
|
186
168
|
foldProtocolAxes(a2a.toolAxes, "A2A");
|
|
187
|
-
return { mcp, a2a, rebuildHarnessToolsRef, contentOriginWrapRef, toolCallGateArmedRef };
|
|
169
|
+
return { mcp, a2a, rebuildHarnessToolsRef, contentOriginWrapRef, toolCallGateArmedRef, ...(mcpRedial !== undefined ? { mcpRedial } : {}) };
|
|
188
170
|
}
|
|
189
171
|
function mcpRevocationWiring(deps, runId) {
|
|
190
172
|
if (deps.mcpRevocations === undefined)
|
|
@@ -436,7 +436,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
436
436
|
roster.mount(createOutputTool(outputRef, spec.outputSchema, compiled.strict ? compiled.modelSchema : undefined), { source: "synthetic", mountedBy: "optional" });
|
|
437
437
|
}
|
|
438
438
|
const rosterSeat = new ToolRosterDeltaSeat();
|
|
439
|
-
const { mcp, a2a, rebuildHarnessToolsRef, contentOriginWrapRef, toolCallGateArmedRef } = await prepareProtocolTools({ lockedPreflight, spec, deps, reminderMark, reminderDisclosureCounts, runId, sessionId, onceLedger, roster, rosterSeat, remoteToolOffload, toolFaceSnapshot, toolEffects, axisExplicitNegatives, irreversibilityTier, irreversibleTools, egressTools, abortController, rollback });
|
|
439
|
+
const { mcp, a2a, rebuildHarnessToolsRef, contentOriginWrapRef, toolCallGateArmedRef, mcpRedial } = await prepareProtocolTools({ lockedPreflight, spec, deps, reminderMark, reminderDisclosureCounts, runId, sessionId, onceLedger, roster, rosterSeat, remoteToolOffload, toolFaceSnapshot, toolEffects, axisExplicitNegatives, irreversibilityTier, irreversibleTools, egressTools, abortController, rollback });
|
|
440
440
|
const callIssuedAtRef = {};
|
|
441
441
|
const workCutRef = { continuation: false, abortedBeforeTurnEnd: false };
|
|
442
442
|
const advertisedWritableDirs = handsEnabled
|
|
@@ -690,7 +690,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
690
690
|
}
|
|
691
691
|
}
|
|
692
692
|
const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, envHandToolNames, handsCwdRef, readDenyMatcher, questionToolMounted, runtimeCaps, inheritedAncestorRules, inheritedParentConstraints, seedInheritedGate, hasSkillManifest, skillScope, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
|
|
693
|
-
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtectionCheck, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace } = prepareWiringManifest({ spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, peerLaneActive, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined });
|
|
693
|
+
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtectionCheck, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace } = prepareWiringManifest({ spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, peerLaneActive, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined });
|
|
694
694
|
if (fileHistoryBoundary !== undefined) {
|
|
695
695
|
harness.on("tool_call", async () => {
|
|
696
696
|
await fileHistoryBoundary.settle();
|
|
@@ -702,11 +702,11 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
702
702
|
const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
|
|
703
703
|
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
704
704
|
prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, planModeRef, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, hookEnvFace, writeProtectionCheck, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider, autoModeDenialTracking, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash });
|
|
705
|
-
const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, microCompactKnob, harness, batchHaltRef, gitStatusRef, requestLossyRef, trimPressureRef });
|
|
705
|
+
const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, microCompactKnob, harness, batchHaltRef, gitStatusRef, requestLossyRef, trimPressureRef, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}) });
|
|
706
706
|
const preparedHolder = {};
|
|
707
707
|
const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
|
|
708
708
|
await onceLedger.settle(session, announcedListingsRef);
|
|
709
|
-
const buildPrepared = () => ({ harness, session, sessionId, runId, reminderMark, reminderDisclosureCounts, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, gitStatusRef, listBackgroundTasks, hookIdentity, hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
709
|
+
const buildPrepared = () => ({ harness, session, sessionId, runId, reminderMark, reminderDisclosureCounts, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, gitStatusRef, listBackgroundTasks, hookIdentity, hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
710
710
|
rollback.commit();
|
|
711
711
|
const prepared = buildPrepared();
|
|
712
712
|
preparedHolder.current = prepared;
|
|
@@ -6,7 +6,7 @@ import { CacheBreakDetector, toolsToFingerprintInputs } from "../cache-break-det
|
|
|
6
6
|
import { defaultTaskRegistry } from "../task-registry.js";
|
|
7
7
|
import { refuseOutOfContractDecision } from "../tool-policy.js";
|
|
8
8
|
import { decodeTextBytes } from "../../tools/fs/encoding.js";
|
|
9
|
-
import {
|
|
9
|
+
import { applyContextShrinkToReadFileState, isReadDedupStubResult } from "../../tools/fs/index.js";
|
|
10
10
|
import { resolveKey } from "../../tools/fs/safety.js";
|
|
11
11
|
import { PROMPT_HASH_SALT } from "./prompt-hash-salt.js";
|
|
12
12
|
import { CHANGED_FILES_MTIME_EPS_MS } from "./turn-attachments.js";
|
|
@@ -98,7 +98,7 @@ export function prepareTurnWiring(input) {
|
|
|
98
98
|
.map(([path]) => path)
|
|
99
99
|
: undefined;
|
|
100
100
|
const onCompactionApplied = handsEnabled && readFileStateForCheckpoint
|
|
101
|
-
? (attachedComplete, preserveReadState) =>
|
|
101
|
+
? (attachedComplete, preserveReadState) => applyContextShrinkToReadFileState(readFileStateForCheckpoint, { kind: "summarized", attachedComplete, ...(preserveReadState !== undefined ? { preserveKeys: preserveReadState } : {}) })
|
|
102
102
|
: undefined;
|
|
103
103
|
const changedFilesReadDenied = denyNarrowingPolicy === undefined
|
|
104
104
|
? undefined
|
|
@@ -108,6 +108,10 @@ export interface PrepareWiringManifestInput {
|
|
|
108
108
|
/** borrowed-readonly — the leg's minted tool roster: rides the manifest's `tools` section and is the
|
|
109
109
|
* source of the hand band's write-capable names for the ungated-write warning (what actually MOUNTED). */
|
|
110
110
|
toolRoster: ToolRoster;
|
|
111
|
+
/** borrowed-readonly — from the read-face phase: the built-in read-deny TIERS that leg's own
|
|
112
|
+
* resolution materially activated; relayed onto the manifest (present iff non-empty), never
|
|
113
|
+
* re-derived from `deps` here (which by this phase sits past that phase's await). */
|
|
114
|
+
readDenyBuiltinTiersActive: readonly string[];
|
|
111
115
|
/** borrowed-readonly — from the LSP phase's manager fold: gates the manifest's LSP section (absent ⇒ byte-identical manifest). */ lspManagerWired: boolean;
|
|
112
116
|
/** borrowed-readonly — from the LSP phase: is the diagnostics lane live? The `lane` word's only input. */ lspDiagnosticsLive: boolean;
|
|
113
117
|
/** borrowed-readonly — the arming outcome the caps phase minted (the manifest's auto-mode face). */
|
|
@@ -113,7 +113,7 @@ function announceDurableGateUnavailable(args) {
|
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
export function prepareWiringManifest(input) {
|
|
116
|
-
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, peerLaneActive, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, lspManagerWired, lspDiagnosticsLive } = input;
|
|
116
|
+
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, lockedPreflight, peerLaneRefs, peerLaneActive, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive } = input;
|
|
117
117
|
const onAsk = spec.onAsk ?? deps.onAsk;
|
|
118
118
|
const handWriteTools = toolRoster.entries.filter((e) => e.mountedBy === "hands" && (e.effect === "write" || e.effect === "idempotent")).map((e) => e.name);
|
|
119
119
|
const hasEffectAwareGate = Boolean(policyLayers.length > 0 || (hooks?.preToolUse !== undefined && !preToolUseObservational));
|
|
@@ -208,6 +208,7 @@ export function prepareWiringManifest(input) {
|
|
|
208
208
|
autoMode: { ...autoModeArmReason },
|
|
209
209
|
mcp: mcpManifestEntries(lockedPreflight.mcp, mcp.statuses),
|
|
210
210
|
...(writeProtection !== undefined ? { writeProtectionTargetView: writeProtection.targetView } : {}),
|
|
211
|
+
readDenyBuiltinTiersActive,
|
|
211
212
|
autoConsolidationOnRecommendation: autoRunOnRecommendationEffective(deps),
|
|
212
213
|
tools: toolRoster,
|
|
213
214
|
hooks: wiredHookEntries(hooks, spec.hooks !== undefined ? "spec" : "deps", preToolUseObservational),
|
|
@@ -2,6 +2,7 @@ import { createSafeNotifier, observeThenableRejection } from "../safe-notify.js"
|
|
|
2
2
|
import { forwardSafely } from "./forward-sink.js";
|
|
3
3
|
import { emitTrace } from "../trace.js";
|
|
4
4
|
import { primaryActivityArg } from "../arg-summary.js";
|
|
5
|
+
import { redactSecrets } from "../untrusted-egress.js";
|
|
5
6
|
import { readDegradation } from "../../brain/degrading.js";
|
|
6
7
|
import { OUTPUT_TOOL_NAME } from "./synthetic-tools.js";
|
|
7
8
|
import { usageCostMicroUsd } from "./usage-accounting.js";
|
|
@@ -157,8 +158,9 @@ export function createHarnessHandlers(input) {
|
|
|
157
158
|
rs.counters.repetitionCuts += 1;
|
|
158
159
|
else
|
|
159
160
|
rs.counters.repetitionSpared += 1;
|
|
161
|
+
const segment = redactSecrets(e.segment);
|
|
160
162
|
if (rs.counters.repetitionEvents.length < rs.counters.REPETITION_EVENTS_CAP) {
|
|
161
|
-
rs.counters.repetitionEvents.push({ turn: stats.turns + 1, action, rule: e.rule, period: e.period, reps: e.reps, segment
|
|
163
|
+
rs.counters.repetitionEvents.push({ turn: stats.turns + 1, action, rule: e.rule, period: e.period, reps: e.reps, segment });
|
|
162
164
|
}
|
|
163
165
|
emitTrace(rs.telemetry.tracer, () => ({
|
|
164
166
|
kind: "repetition.detected",
|
|
@@ -169,7 +171,7 @@ export function createHarnessHandlers(input) {
|
|
|
169
171
|
rule: e.rule,
|
|
170
172
|
period: e.period,
|
|
171
173
|
reps: e.reps,
|
|
172
|
-
segment
|
|
174
|
+
segment,
|
|
173
175
|
ts: Date.now(),
|
|
174
176
|
}));
|
|
175
177
|
}
|
|
@@ -3,7 +3,7 @@ import { type PendingSessionNotifications, type SystemInjectionPriority, type Ta
|
|
|
3
3
|
import type { PushQueue } from "../push-queue.js";
|
|
4
4
|
import type { TaskEvent, TaskSpec } from "../types.js";
|
|
5
5
|
import type { Stats } from "./assemble-result.js";
|
|
6
|
-
import type { CaptureOptOutRef, LiveHandle, ManualCompactRef, NotificationLaneBindings, NotifyRef, Prepared, RunInternals, RunnerDepsSeat, TaskIdRef } from "./contracts.js";
|
|
6
|
+
import type { CaptureOptOutRef, LiveHandle, ManualCompactRef, McpRedialRef, NotificationLaneBindings, NotifyRef, Prepared, RunInternals, RunnerDepsSeat, TaskIdRef } from "./contracts.js";
|
|
7
7
|
export interface RunIdentityWiringInput {
|
|
8
8
|
/** borrowed-readonly — the task spec: the task id and the memory / notification seats it names. */
|
|
9
9
|
spec: TaskSpec;
|
|
@@ -27,6 +27,8 @@ export interface RunIdentityWiringInput {
|
|
|
27
27
|
notifyRef: NotifyRef | undefined;
|
|
28
28
|
/** borrowed-mutable — the capture opt-out bridge: `flip` is bound here when a memory session mounted. */
|
|
29
29
|
captureOptOutRef: CaptureOptOutRef | undefined;
|
|
30
|
+
/** borrowed-mutable — the MCP re-dial bridge: `redial` is bound here when the leg declared MCP servers. */
|
|
31
|
+
mcpRedialRef: McpRedialRef | undefined;
|
|
30
32
|
/** borrowed-readonly — the notification lane's ONE injection entry (the R0 lane's). */
|
|
31
33
|
injectTaskNotification: (notification: TaskNotificationPayload, opts?: {
|
|
32
34
|
priority?: SystemInjectionPriority;
|
|
@@ -3,7 +3,7 @@ import { createSafeNotifier } from "../safe-notify.js";
|
|
|
3
3
|
import { discloseDroppedPending, renderTaskNotificationXml, taskNotificationDedupKey } from "../task-notification.js";
|
|
4
4
|
import { deliverDelegationLifecycle, deliverEngineNotice, undrainedUserInputNotices } from "../types.js";
|
|
5
5
|
export function runIdentityWiring(input) {
|
|
6
|
-
const { spec, queue, prepared, internals, taskIdRef, onReady, manualCompactRef, notifyRef, captureOptOutRef, injectTaskNotification, deliveredAtTurnOpen, peerInboundChainRef, notificationLane, pendingSessionNotifications, runner } = input;
|
|
6
|
+
const { spec, queue, prepared, internals, taskIdRef, onReady, manualCompactRef, notifyRef, captureOptOutRef, mcpRedialRef, injectTaskNotification, deliveredAtTurnOpen, peerInboundChainRef, notificationLane, pendingSessionNotifications, runner } = input;
|
|
7
7
|
notificationLane.harness = prepared.harness;
|
|
8
8
|
notificationLane.sessionId = prepared.sessionId;
|
|
9
9
|
if (taskIdRef)
|
|
@@ -66,6 +66,9 @@ export function runIdentityWiring(input) {
|
|
|
66
66
|
if (captureOptOutRef && prepared.memoryEngineSession?.captureOptOut !== undefined) {
|
|
67
67
|
captureOptOutRef.flip = prepared.memoryEngineSession.captureOptOut.flip;
|
|
68
68
|
}
|
|
69
|
+
if (mcpRedialRef && prepared.mcpRedial !== undefined) {
|
|
70
|
+
mcpRedialRef.redial = prepared.mcpRedial;
|
|
71
|
+
}
|
|
69
72
|
try {
|
|
70
73
|
internals?.onNotifyInjectorReady?.(injectTaskNotification);
|
|
71
74
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_COMPACTION_SETTINGS } from "../../internal/harness.js";
|
|
2
2
|
import { planRejectionClears } from "../context-edit.js";
|
|
3
|
+
import { landStaleResultClears } from "./prepare-context-lane.js";
|
|
3
4
|
import { DEFAULT_COMPACTION_INSTRUCTIONS, maybeCompact } from "../auto-compaction.js";
|
|
4
5
|
import { emitTrace } from "../trace.js";
|
|
5
6
|
import { isDegenerateCutMessage } from "../../brain/terminal-cause.js";
|
|
@@ -145,9 +146,11 @@ export function runRecoveryLanes(input) {
|
|
|
145
146
|
}));
|
|
146
147
|
}
|
|
147
148
|
else {
|
|
148
|
-
|
|
149
|
-
prepared.microCompact.ledger
|
|
150
|
-
|
|
149
|
+
landStaleResultClears({
|
|
150
|
+
ledger: prepared.microCompact.ledger,
|
|
151
|
+
cleared: plan.cleared,
|
|
152
|
+
...(prepared.readFileState !== undefined ? { readFileState: prepared.readFileState } : {}),
|
|
153
|
+
});
|
|
151
154
|
emitTrace(rs.telemetry.tracer, () => ({
|
|
152
155
|
kind: "context.mc_clear",
|
|
153
156
|
version: 1,
|
|
@@ -23,7 +23,7 @@ import type { AssistantMessage } from "../../internal/llm.js";
|
|
|
23
23
|
import type { ResolvedReasoning } from "../../brain/reasoning.js";
|
|
24
24
|
import type { PushQueue } from "../push-queue.js";
|
|
25
25
|
import type { SessionStore } from "../session.js";
|
|
26
|
-
import { type CompactOutcome, type DelegationLifecycleEvent, type TaskEvent, type TaskResult, type TaskSpec } from "../types.js";
|
|
26
|
+
import { type CompactOutcome, type DelegationLifecycleEvent, type OwedUserInputAccount, type TaskEvent, type TaskResult, type TaskSpec } from "../types.js";
|
|
27
27
|
import { type Stats } from "./assemble-result.js";
|
|
28
28
|
import type { EndOfTaskCompaction, InstallingPhaseResult, ManualCompactRef, Prepared, ResumeRun, RunInternals, RunnerDepsSeat, RunState, SuspendReap, TaskIdRef } from "./contracts.js";
|
|
29
29
|
export interface RunSettleAndTeardownInput {
|
|
@@ -94,6 +94,8 @@ export interface RunSettleAndTeardownInput {
|
|
|
94
94
|
};
|
|
95
95
|
/** borrowed-readonly — the end-of-task compaction's outcome (the terminal-adoption lane's `finish` call). */
|
|
96
96
|
comp: EndOfTaskCompaction;
|
|
97
|
+
/** borrowed-readonly — the adoption lane's unsettled undrained-input account, closed below (after the reopen). */
|
|
98
|
+
owedUserInput: OwedUserInputAccount;
|
|
97
99
|
/** borrowed-readonly — the stream's result setter: the assembled TaskResult is published through it exactly once. */
|
|
98
100
|
setResult: (r: TaskResult) => void;
|
|
99
101
|
/** borrowed-readonly — the stream's suggestions seat: the fire-and-forget suggestion pass's promise is handed to it. */
|
|
@@ -9,7 +9,7 @@ import { hasDestroy, isIsolated } from "../remote-env.js";
|
|
|
9
9
|
import { resolveTaskModel } from "../roles.js";
|
|
10
10
|
import { defaultTaskRegistry } from "../task-registry.js";
|
|
11
11
|
import { emitTrace } from "../trace.js";
|
|
12
|
-
import { deliverEngineNotice } from "../types.js";
|
|
12
|
+
import { deliverEngineNotice, settleOwedUserInput } from "../types.js";
|
|
13
13
|
import { assembleResult } from "./assemble-result.js";
|
|
14
14
|
import { discloseUnconsumedHalt } from "./halt-attribution.js";
|
|
15
15
|
import { forwardSafely } from "./forward-sink.js";
|
|
@@ -21,7 +21,7 @@ import { settleTeardownLeg } from "./teardown-bounded.js";
|
|
|
21
21
|
import { autoRunConsolidationFromRecommendation, autoRunOnRecommendationEffective, scopeHasUnconsumedRecommendation } from "./memory-consolidation-driver.js";
|
|
22
22
|
import { amendTerminal, terminalProjection } from "./terminal-projection.js";
|
|
23
23
|
export async function runSettleAndTeardown(input) {
|
|
24
|
-
const { spec, queue, prepared, resume, internals, rs, stats, ident, parentToolCallId, subagentName, loopLatch, timeout, ownCommittedTailRef, emitDelegationLifecycle, taskIdRef, manualCompactRef, drainManualCompact, final, threw, abortedLive, userInterruptedLive, answerSettled, strandedHumanAnswers, reasoningResolution, comp, setResult, onSuggestions, onSuspend, runner, sessions } = input;
|
|
24
|
+
const { spec, queue, prepared, resume, internals, rs, stats, ident, parentToolCallId, subagentName, loopLatch, timeout, ownCommittedTailRef, emitDelegationLifecycle, taskIdRef, manualCompactRef, drainManualCompact, final, threw, abortedLive, userInterruptedLive, answerSettled, strandedHumanAnswers, reasoningResolution, comp, owedUserInput, setResult, onSuggestions, onSuspend, runner, sessions } = input;
|
|
25
25
|
try {
|
|
26
26
|
if (comp?.compacted) {
|
|
27
27
|
queue.push({
|
|
@@ -141,6 +141,7 @@ export async function runSettleAndTeardown(input) {
|
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
143
|
discloseUnconsumedHalt({ accepted: loopLatch.userHalted, consumption: prepared.harness.haltConsumption(), onNotice: runner.deps.onNotice, sessionId: prepared.sessionId, runId: rs.telemetry.runId, taskId: spec.taskId });
|
|
144
|
+
let rowReturned = false;
|
|
144
145
|
if (resume !== undefined &&
|
|
145
146
|
resume.pendingActionStarted !== true &&
|
|
146
147
|
result.terminal.kind !== "completed" &&
|
|
@@ -149,12 +150,14 @@ export async function runSettleAndTeardown(input) {
|
|
|
149
150
|
resume.onEnvRestoreFailed !== undefined) {
|
|
150
151
|
try {
|
|
151
152
|
await resume.onEnvRestoreFailed("env_failed");
|
|
153
|
+
rowReturned = true;
|
|
152
154
|
amendTerminal(result, "resume.reopened_unstarted", (m) => `${m ?? "the resume leg did not complete"} — the approved action never started, so the checkpoint was REOPENED (pending): the same approval can be resumed again, do not ask for a fresh one`);
|
|
153
155
|
}
|
|
154
156
|
catch {
|
|
155
157
|
amendTerminal(result, "resume.reopen_failed_unstarted", (m) => `${m ?? "the resume leg did not complete"} — the approved action never started, and reopening the checkpoint FAILED: its state is unprovable from here. Re-read it before deciding; do NOT issue a fresh approval on the assumption the old one is dead`);
|
|
156
158
|
}
|
|
157
159
|
}
|
|
160
|
+
settleOwedUserInput(owedUserInput, rowReturned, { taskId: spec.taskId ?? prepared.sessionId, sessionId: prepared.sessionId, runId: prepared.runId }, runner.deps.onNotice);
|
|
158
161
|
prepared.sealReadStateSeat?.(ownCommittedTailRef.current);
|
|
159
162
|
{
|
|
160
163
|
const wss = prepared.workspaceStateSettle;
|
|
@@ -299,6 +302,7 @@ export async function runSettleAndTeardown(input) {
|
|
|
299
302
|
}
|
|
300
303
|
}
|
|
301
304
|
finally {
|
|
305
|
+
settleOwedUserInput(owedUserInput, !prepared.suspendProgressRef.executedApproved, { taskId: spec.taskId ?? prepared.sessionId, sessionId: prepared.sessionId, runId: prepared.runId }, runner.deps.onNotice);
|
|
302
306
|
const ownedEnvDying = prepared.ownedEnv !== undefined &&
|
|
303
307
|
hasDestroy(prepared.ownedEnv) &&
|
|
304
308
|
isIsolated(prepared.ownedEnv) &&
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { primaryActivityArg } from "../arg-summary.js";
|
|
1
2
|
import { remainingBudgetMicroUsd, remainingTokens } from "../checkpoint-store.js";
|
|
2
3
|
import { computeCostMicroUsd, isModelPriced, malformedPricingField, modelCostToPricing } from "../pricing.js";
|
|
3
4
|
import { resolveModel } from "../roles.js";
|
|
@@ -19,7 +20,16 @@ export function runTelemetryAndBudgetSeats(input) {
|
|
|
19
20
|
prepared.humanReviewRef.count += 1;
|
|
20
21
|
prepared.humanReviewRef.totalWaitMs += waitMs;
|
|
21
22
|
const gateToolName = "toolName" in resume.cp.gate ? resume.cp.gate.toolName : undefined;
|
|
22
|
-
|
|
23
|
+
const gatedCall = resume.cp.pendingAction.kind === "tool_approval" ? resume.cp.pendingAction : undefined;
|
|
24
|
+
const gateToolArg = gatedCall === undefined ? undefined : primaryActivityArg(gatedCall.args);
|
|
25
|
+
prepared.humanReviewRef.gates.push({
|
|
26
|
+
kind: resume.cp.gate.kind,
|
|
27
|
+
waitMs,
|
|
28
|
+
...(decision !== undefined ? { decision } : {}),
|
|
29
|
+
...(gateToolName !== undefined ? { toolName: gateToolName } : {}),
|
|
30
|
+
...(gatedCall !== undefined ? { toolCallId: gatedCall.toolCallId } : {}),
|
|
31
|
+
...(gateToolArg !== undefined ? { toolArg: gateToolArg } : {}),
|
|
32
|
+
});
|
|
23
33
|
}
|
|
24
34
|
if (resume !== undefined && resume.outcome.gate === "plan_review" && resume.outcome.decision === "reject") {
|
|
25
35
|
prepared.planModeRef.active = true;
|