@sema-agent/core 7.17.6 → 7.18.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 +165 -13
- package/dist/agents/send-message-tool.js +1 -0
- package/dist/agents/subagent.d.ts +1 -0
- package/dist/agents/subagent.js +5 -0
- package/dist/agents/teacher.js +1 -0
- package/dist/agents/verify.js +3 -0
- package/dist/brain/route-adjudicator.d.ts +18 -0
- package/dist/brain/route-adjudicator.js +16 -0
- package/dist/core/agent-definition.d.ts +10 -0
- package/dist/core/artifact-host.d.ts +41 -4
- package/dist/core/artifact-host.js +18 -2
- package/dist/core/auto-mode.d.ts +141 -45
- package/dist/core/auto-mode.js +109 -3
- package/dist/core/checkpoint-store.d.ts +16 -2
- package/dist/core/engine-notice.d.ts +47 -1
- package/dist/core/engine-notice.js +7 -0
- package/dist/core/gate-lanes.js +2 -1
- package/dist/core/gate-outcome.d.ts +17 -2
- package/dist/core/gate-outcome.js +16 -0
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +8 -0
- package/dist/core/hook-seats.d.ts +66 -0
- package/dist/core/hook-seats.js +37 -0
- package/dist/core/runner/advertised-writable-dirs.d.ts +8 -3
- package/dist/core/runner/assemble-result.d.ts +2 -1
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/classifier-ladder.d.ts +89 -0
- package/dist/core/runner/classifier-ladder.js +65 -0
- package/dist/core/runner/contracts.d.ts +69 -13
- package/dist/core/runner/decide-continuation.d.ts +1 -3
- package/dist/core/runner/decide-continuation.js +1 -7
- package/dist/core/runner/deferral-census.d.ts +52 -0
- package/dist/core/runner/deferral-census.js +44 -0
- package/dist/core/runner/derived-route-fallback.d.ts +8 -4
- package/dist/core/runner/derived-route-fallback.js +8 -3
- package/dist/core/runner/gate-exit.d.ts +12 -0
- package/dist/core/runner/gate-exit.js +6 -3
- package/dist/core/runner/prepare-artifact.d.ts +10 -2
- package/dist/core/runner/prepare-artifact.js +5 -4
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
- package/dist/core/runner/prepare-caps-and-workflow.js +30 -31
- package/dist/core/runner/prepare-config-doors.d.ts +1 -1
- package/dist/core/runner/prepare-config-doors.js +5 -3
- package/dist/core/runner/prepare-defer-classify.d.ts +13 -19
- package/dist/core/runner/prepare-defer-classify.js +8 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +26 -0
- package/dist/core/runner/prepare-gate-stations.js +1 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +24 -7
- package/dist/core/runner/prepare-hands-readface.js +60 -24
- package/dist/core/runner/prepare-inherited-gate.d.ts +17 -4
- package/dist/core/runner/prepare-inherited-gate.js +10 -2
- package/dist/core/runner/prepare-lsp.d.ts +2 -2
- package/dist/core/runner/prepare-lsp.js +1 -1
- package/dist/core/runner/prepare-policy-chain.js +2 -0
- package/dist/core/runner/prepare-project-context.js +4 -2
- package/dist/core/runner/prepare-prompt-inputs.d.ts +4 -2
- package/dist/core/runner/prepare-prompt-inputs.js +4 -1
- package/dist/core/runner/prepare-run-refs.d.ts +9 -1
- package/dist/core/runner/prepare-run-refs.js +3 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +5 -0
- package/dist/core/runner/prepare-suspend-saga.js +5 -2
- package/dist/core/runner/prepare-task.js +18 -13
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +5 -0
- package/dist/core/runner/prepare-tool-disclosure-mount.js +10 -2
- package/dist/core/runner/prepare-turn-wiring.d.ts +8 -4
- package/dist/core/runner/prepare-turn-wiring.js +3 -2
- package/dist/core/runner/prepare-wiring-manifest.d.ts +5 -5
- package/dist/core/runner/prepare-wiring-manifest.js +5 -2
- package/dist/core/runner/resume-checkpoint-screen.js +7 -0
- package/dist/core/runner/run-harness-handlers.js +4 -1
- package/dist/core/runner/run-identity-wiring.js +6 -2
- package/dist/core/runner/run-leg.d.ts +2 -0
- package/dist/core/runner/run-leg.js +35 -41
- package/dist/core/runner/run-notification-lane.js +55 -27
- package/dist/core/runner/run-settle-and-teardown.js +1 -0
- package/dist/core/runner/run-terminal-adoption.js +16 -13
- package/dist/core/runner/run-turn-boundary.js +3 -1
- package/dist/core/runner/runtask.d.ts +6 -5
- package/dist/core/runner/runtask.js +26 -14
- package/dist/core/runner/skill-base-dir.d.ts +54 -0
- package/dist/core/runner/skill-base-dir.js +42 -0
- package/dist/core/runner/synthetic-tools.d.ts +16 -19
- package/dist/core/runner/synthetic-tools.js +18 -10
- package/dist/core/runner/tool-defer-gate.d.ts +22 -9
- package/dist/core/runner/tool-defer-gate.js +15 -5
- package/dist/core/runner/tool-disclosure.d.ts +5 -0
- package/dist/core/runner/tool-disclosure.js +2 -0
- package/dist/core/runner/tool-progress-lane.d.ts +42 -0
- package/dist/core/runner/tool-progress-lane.js +61 -0
- package/dist/core/runner-deps.d.ts +48 -7
- package/dist/core/swappable-deps.d.ts +9 -7
- package/dist/core/swappable-deps.js +7 -3
- package/dist/core/task-event.d.ts +96 -29
- package/dist/core/task-notification.d.ts +142 -16
- package/dist/core/task-notification.js +106 -0
- package/dist/core/task-result.d.ts +9 -1
- package/dist/core/task-spec.d.ts +20 -3
- package/dist/core/tighten-task-spec.js +7 -5
- package/dist/core/tool-model-gate.d.ts +1 -1
- package/dist/core/tool-search-setting.d.ts +78 -0
- package/dist/core/tool-search-setting.js +90 -0
- package/dist/core/tool-spec.d.ts +8 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.js +1 -1
- package/dist/core/wiring-manifest.d.ts +46 -0
- package/dist/core/wiring-manifest.js +9 -1
- package/dist/engine/execution-env/node-execution-env.js +10 -4
- package/dist/engine/harness/agent-harness.d.ts +42 -0
- package/dist/engine/harness/agent-harness.js +61 -29
- package/dist/engine/loop/agent-loop.d.ts +68 -3
- package/dist/engine/loop/agent-loop.js +109 -16
- package/dist/index.d.ts +10 -5
- package/dist/index.js +9 -5
- package/dist/internal/harness.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +3 -0
- package/dist/orchestration/run-workflow-tool.js +6 -1
- package/dist/orchestration/workflow-governance.d.ts +7 -1
- package/dist/orchestration/workflow-governance.js +9 -5
- package/dist/orchestration/workflow-primitives.d.ts +3 -0
- package/dist/orchestration/workflow-primitives.js +6 -1
- package/dist/orchestration/workflow-types.d.ts +48 -13
- package/dist/orchestration/workflow-types.js +1 -1
- package/dist/orchestration/workflow.js +45 -17
- package/dist/prompt-assembly/epoch.js +2 -0
- package/dist/prompt-assembly/packs/sema-default.js +2 -2
- package/dist/prompt-assembly/section-usage.d.ts +26 -0
- package/dist/prompt-assembly/section-usage.js +10 -0
- package/dist/prompt-assembly/types.d.ts +8 -6
- package/dist/prompts/default.d.ts +13 -0
- package/dist/prompts/default.js +16 -8
- package/dist/tools/artifact/artifact-text.d.ts +10 -1
- package/dist/tools/artifact/artifact-text.js +6 -3
- package/dist/tools/artifact/artifact-tool.d.ts +12 -2
- package/dist/tools/artifact/artifact-tool.js +203 -70
- package/dist/tools/artifact/conformance.d.ts +56 -0
- package/dist/tools/artifact/conformance.js +349 -0
- package/dist/tools/artifact/local-stub.js +1 -1
- package/dist/tools/artifact/reject-breaker.d.ts +28 -0
- package/dist/tools/artifact/reject-breaker.js +42 -0
- package/dist/tools/fs/bash-lexer.d.ts +132 -0
- package/dist/tools/fs/bash-lexer.js +563 -0
- package/dist/tools/fs/bash-program-position.d.ts +142 -0
- package/dist/tools/fs/bash-program-position.js +125 -0
- package/dist/tools/fs/bash-readonly-classifier.d.ts +54 -16
- package/dist/tools/fs/bash-readonly-classifier.js +375 -530
- package/dist/tools/fs/containment-face.d.ts +89 -0
- package/dist/tools/fs/containment-face.js +81 -0
- package/dist/tools/fs/fs-bash.d.ts +46 -1
- package/dist/tools/fs/fs-bash.js +158 -22
- package/dist/tools/fs/fs-read.d.ts +1 -1
- package/dist/tools/fs/fs-search-tools.d.ts +3 -3
- package/dist/tools/fs/fs-write.d.ts +4 -3
- package/dist/tools/fs/fs-write.js +9 -9
- package/dist/tools/fs/index.d.ts +24 -5
- package/dist/tools/fs/index.js +18 -6
- package/dist/tools/fs/repo-map.d.ts +2 -2
- package/dist/tools/fs/safety.d.ts +3 -3
- package/dist/tools/fs/safety.js +4 -4
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +85 -9
- package/wire-changes/core@7.17.6.json +81 -0
- package/wire-changes/core@7.17.7.json +49 -0
- package/dist/tools/fs/read-face.d.ts +0 -68
- package/dist/tools/fs/read-face.js +0 -47
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { bindPeerLaneDrain } from "../../agents/peer-session-drain.js";
|
|
2
2
|
import { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
3
3
|
import { createHookEnvCapabilities, mintHookInvocationIdentity } from "../hooks.js";
|
|
4
|
+
import { wiredHookEntries } from "../hook-seats.js";
|
|
4
5
|
import { isRemoteExecutionEnv, missingRestoreSurface } from "../remote-env.js";
|
|
5
6
|
import { isVolatileOffloadStore } from "../tool-result-store.js";
|
|
6
7
|
import { durableMandateSourceOf, isLiveApproverSeat } from "../tool-policy.js";
|
|
7
8
|
import { deliverEngineNotice } from "../types.js";
|
|
8
9
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
9
10
|
import { GLOBAL_USAGE_KEY, usageRetryAfterMs, windowsGovernCost } from "../usage-window-store.js";
|
|
10
|
-
import { countElicitOptIns, deriveWiringManifest, resolveAskSeamForm, resolveDeclaredDurability, resolveElicitSeam, resolveQuestionSeam, resolveSubagentTranscriptTier } from "../wiring-manifest.js";
|
|
11
|
+
import { LSP_CONTRACT_ID, countElicitOptIns, deriveLspSeam, deriveWiringManifest, resolveAskSeamForm, resolveDeclaredDurability, resolveElicitSeam, resolveQuestionSeam, resolveSubagentTranscriptTier } from "../wiring-manifest.js";
|
|
11
12
|
import { DEFAULT_IRREVERSIBLE_SCOPE } from "./checkpoint-scope.js";
|
|
12
13
|
export function mcpManifestEntries(entries, statuses) {
|
|
13
14
|
return (entries ?? []).map((entry) => {
|
|
@@ -110,7 +111,7 @@ function announceDurableGateUnavailable(args) {
|
|
|
110
111
|
});
|
|
111
112
|
}
|
|
112
113
|
export function prepareWiringManifest(input) {
|
|
113
|
-
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, 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 } = input;
|
|
114
|
+
const { spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, 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;
|
|
114
115
|
const onAsk = spec.onAsk ?? deps.onAsk;
|
|
115
116
|
const handWriteTools = toolRoster.entries.filter((e) => e.mountedBy === "hands" && (e.effect === "write" || e.effect === "idempotent")).map((e) => e.name);
|
|
116
117
|
const hasEffectAwareGate = Boolean(policyLayers.length > 0 || (hooks?.preToolUse !== undefined && !preToolUseObservational));
|
|
@@ -204,6 +205,8 @@ export function prepareWiringManifest(input) {
|
|
|
204
205
|
autoMode: { ...autoModeArmReason },
|
|
205
206
|
mcp: mcpManifestEntries(lockedPreflight.mcp, mcp.statuses),
|
|
206
207
|
tools: toolRoster,
|
|
208
|
+
hooks: wiredHookEntries(hooks, spec.hooks !== undefined ? "spec" : "deps", preToolUseObservational),
|
|
209
|
+
...(lspManagerWired ? { lsp: deriveLspSeam(toolRoster.entries.some((e) => e.contract.contractId === LSP_CONTRACT_ID), lspDiagnosticsLive) } : {}),
|
|
207
210
|
});
|
|
208
211
|
peerLaneRefs.askEffective = wiringManifest.ask.effective;
|
|
209
212
|
if (peerLaneActive && internals?.onTaskNotification !== undefined) {
|
|
@@ -38,6 +38,13 @@ export function resumeCheckpointScreen(input) {
|
|
|
38
38
|
? `a v${checkpointVersionOf(cp)} checkpoint must carry a well-formed read-face section (state.readFace) — this row's is missing or malformed; refusing to resume a damaged read-face row (corruption / downgrade guard), the checkpoint stays pending`
|
|
39
39
|
: `a v${checkpointVersionOf(cp)} checkpoint carries a read-face section no release of that version ever minted — refusing to honor a fabricated read-face state (corruption / forgery guard), the checkpoint stays pending`, { reason: checkpointVersionOf(cp) >= FACE_CHECKPOINT_VERSION ? "read_face_damaged" : "read_face_forged" });
|
|
40
40
|
}
|
|
41
|
+
const writeFaceSectionRaw = cp.state.writeFace;
|
|
42
|
+
if (writeFaceSectionRaw !== undefined) {
|
|
43
|
+
const c = typeof writeFaceSectionRaw === "object" && writeFaceSectionRaw !== null ? writeFaceSectionRaw : undefined;
|
|
44
|
+
if (c === undefined || !(c.face === "open" || c.face === "roots")) {
|
|
45
|
+
throw new CheckpointError("checkpoint.invalid_outcome", `this checkpoint carries a write-face section (state.writeFace) that is not well-formed — refusing to resume a damaged write-face row (corruption guard), the checkpoint stays pending`, { reason: "write_face_damaged" });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
41
48
|
}
|
|
42
49
|
if (realApprovalOrgFact(preCasGateBit) !== undefined && runner.deps.permissionRuleStore?.partitions.org !== true) {
|
|
43
50
|
throw new CheckpointError("checkpoint.unsupported_version", `this checkpoint's approval was minted under organization governance (org ${String(realApprovalOrgFact(preCasGateBit))}, routed as ${String(preCasGateBit?.origin)}) and this worker has no org adjudication wiring (its permission-rule store carries no org partition) — a governed approval may only be redeemed where governance can be enforced; the checkpoint stays pending, resume it on an org-wired worker`, { reason: "governed_unwired" });
|
|
@@ -10,7 +10,7 @@ import { hasVerifiableStructureSignal } from "./grounding-signal.js";
|
|
|
10
10
|
import { batchResponseDigest, toolEndBodyFrom } from "./tool-end-body.js";
|
|
11
11
|
export function createHarnessHandlers(input) {
|
|
12
12
|
const { prepared, stats, rs, deps } = input;
|
|
13
|
-
const { spec, queue, internals, ident, parentToolCallId, subagentName, pushContent, emitCommitted, startedToolCallIds, toolStartAt, writeFamilyOf, toolLabels, postToolBatchHook, batchArgs } = deps;
|
|
13
|
+
const { spec, queue, internals, ident, parentToolCallId, subagentName, pushContent, emitCommitted, startedToolCallIds, toolStartAt, toolProgress, writeFamilyOf, toolLabels, postToolBatchHook, batchArgs } = deps;
|
|
14
14
|
const internalsNotifier = createSafeNotifier({
|
|
15
15
|
onError: (f) => console.warn(`[sema-core] ${f.site}: run-internals activity sink threw (contained; further failures counted, not re-disclosed): ${f.error.message}`),
|
|
16
16
|
});
|
|
@@ -186,6 +186,7 @@ export function createHarnessHandlers(input) {
|
|
|
186
186
|
const startAt = Date.now();
|
|
187
187
|
toolStartAt.set(event.toolCallId, startAt);
|
|
188
188
|
startedToolCallIds.add(event.toolCallId);
|
|
189
|
+
toolProgress.noteStart(event.toolCallId, event.toolName);
|
|
189
190
|
batchArgs?.set(event.toolCallId, event.args);
|
|
190
191
|
stats.toolCalls += 1;
|
|
191
192
|
if (spec.finalVerification === true && !(rs.counters.finalVerifyInjections === 0 ? rs.counters.groundingSignalPreR9 : rs.counters.groundingSignalPostR9) && hasVerifiableStructureSignal(event.args)) {
|
|
@@ -208,6 +209,7 @@ export function createHarnessHandlers(input) {
|
|
|
208
209
|
const onToolEnd = (event) => {
|
|
209
210
|
const toolStarted = toolStartAt.get(event.toolCallId);
|
|
210
211
|
toolStartAt.delete(event.toolCallId);
|
|
212
|
+
toolProgress.noteEnd(event.toolCallId);
|
|
211
213
|
const toolNow = Date.now();
|
|
212
214
|
if (!rs.counters.wroteThisRun && (prepared.toolEffects.get(event.toolName) ?? "write") !== "read") {
|
|
213
215
|
rs.counters.wroteThisRun = true;
|
|
@@ -320,6 +322,7 @@ export function createHarnessHandlers(input) {
|
|
|
320
322
|
rs.budget.callOutputChars = 0;
|
|
321
323
|
rs.budget.lastStreamBudgetCheck = 0;
|
|
322
324
|
toolStartAt.clear();
|
|
325
|
+
toolProgress.clear();
|
|
323
326
|
if (rs.limits.effectiveMaxTurns !== undefined && rs.limits.effectiveMaxTurns > 0 && stats.turns >= rs.limits.effectiveMaxTurns) {
|
|
324
327
|
rs.limits.turnsExceeded = true;
|
|
325
328
|
if (prepared.suspendForResource === undefined) {
|
|
@@ -16,6 +16,7 @@ export function runIdentityWiring(input) {
|
|
|
16
16
|
notificationLane.ident = ident;
|
|
17
17
|
queue.push({ type: "wiring_manifest", manifest: prepared.wiringManifest, ...ident() });
|
|
18
18
|
prepared.toolRosterDeltas.subscribe((delta) => queue.push({ type: "tool_roster_delta", delta, ...ident() }));
|
|
19
|
+
prepared.toolDisclosure?.subscribe((snapshot) => queue.push({ type: "tool_disclosure", ...snapshot, ...ident() }));
|
|
19
20
|
const delegationLifecycleNotifier = createSafeNotifier({
|
|
20
21
|
onError: (f) => console.warn(`[sema-core] ${f.site}: delegation-lifecycle observer threw (contained; further failures counted, not re-disclosed): ${f.error.message}`),
|
|
21
22
|
});
|
|
@@ -44,7 +45,7 @@ export function runIdentityWiring(input) {
|
|
|
44
45
|
let userInputLostAtEnd = false;
|
|
45
46
|
prepared.harness.onUndrainedUserInputs = (counts) => {
|
|
46
47
|
userInputLostAtEnd = counts.steer + counts.followUp > 0;
|
|
47
|
-
if (prepared.pausedRef.current !== undefined) {
|
|
48
|
+
if (prepared.pausedRef.current !== undefined || prepared.undeliveredContinuationRef.current.parkedSteers.length > 0) {
|
|
48
49
|
undrainedUserAtEnd = counts;
|
|
49
50
|
return;
|
|
50
51
|
}
|
|
@@ -53,9 +54,12 @@ export function runIdentityWiring(input) {
|
|
|
53
54
|
}
|
|
54
55
|
};
|
|
55
56
|
prepared.harness.onEngineNoteConsumed = (p) => {
|
|
56
|
-
const
|
|
57
|
+
const payload = p;
|
|
58
|
+
const peer = payload?.peer;
|
|
57
59
|
if (peer !== undefined && Array.isArray(peer.hopChain))
|
|
58
60
|
peerInboundChainRef.current = [...peer.hopChain];
|
|
61
|
+
if (notificationLane.sessionId !== undefined && typeof payload?.task_id === "string" && typeof payload.status === "string")
|
|
62
|
+
pendingSessionNotifications.markDelivered(notificationLane.sessionId, taskNotificationDedupKey(payload));
|
|
59
63
|
};
|
|
60
64
|
if (notifyRef)
|
|
61
65
|
notifyRef.inject = injectTaskNotification;
|
|
@@ -38,6 +38,8 @@ export interface RunLegInput<R> {
|
|
|
38
38
|
resume: ResumeRun | undefined;
|
|
39
39
|
/** borrowed-mutable — the run's mutable state: the limit flags and the platform terminal are written by the entrance gates. */
|
|
40
40
|
rs: RunState;
|
|
41
|
+
/** borrowed-readonly — the trusted spawn-side fact the rejection boundary reads (a delegated child's bare refusal halts no batch). */
|
|
42
|
+
isDelegatedChild: boolean;
|
|
41
43
|
/** borrowed-readonly — the API-boundary attribution snapshot of the objective's actor (the objective leg's speaker envelope). */
|
|
42
44
|
entryActor: ActorAssertion | undefined;
|
|
43
45
|
/** borrowed-readonly — the effective walltime window (undefined = unbounded): `<= 0` refuses the first turn. */
|
|
@@ -16,18 +16,19 @@ import { deliverEngineNotice } from "../types.js";
|
|
|
16
16
|
import { delimitUntrusted, inlineUntrusted, REVIEWER_NOTE_MAX_BODY, sanitizeUntrustedText } from "../untrusted-text.js";
|
|
17
17
|
import { errorCodeOf } from "./assemble-result.js";
|
|
18
18
|
import { DEFAULT_PRECALL_OUTPUT_TOKENS, platformLimitTerminal } from "./clock-and-limits.js";
|
|
19
|
-
import { deepJsonEqual,
|
|
19
|
+
import { deepJsonEqual, resumeContinuation } from "./decide-continuation.js";
|
|
20
20
|
import { settleExecutionRecord } from "./execution-record.js";
|
|
21
21
|
import { mintGateOutcome } from "./gate-exit.js";
|
|
22
22
|
import { resolveGitLegDelivery, wrapGitFrame } from "./git-leg-delivery.js";
|
|
23
23
|
import { GIT_STATUS_ECHO_PREVIEW } from "./git-status-frame.js";
|
|
24
24
|
import { toImageContent } from "./image.js";
|
|
25
|
+
import { maybeHumanRejectionHalt } from "./prepare-gate-stations.js";
|
|
25
26
|
import { nextHumanInputSeq } from "./steer-admission.js";
|
|
26
27
|
import { settleTeardownLeg } from "./teardown-bounded.js";
|
|
27
28
|
import { toolEndBodyFrom, toolResultMsg } from "./tool-end-body.js";
|
|
28
29
|
import { attachmentEnvelopeTags, commitAgentListing, commitSkillsListing, reduceToolEnd, renderAgentListingDelta, renderOrphanedBackgroundTasks, renderSkillsListingDelta, stampWriteAnchor } from "./turn-attachments.js";
|
|
29
30
|
export async function runLeg(input) {
|
|
30
|
-
const { spec, queue, prepared, resume, rs, entryActor, effectiveTimeoutMs, timeout, pushContent, ident, emitCommitted, writeFamilyOf, startedToolCallIds, announceWorkspaceMove, withBrainSinks, flushGitMirror, loopLatch, notificationLane, unsubscribeTaskNotifications, unsubGitRetry, unsubBoundary, unsub, runner, next } = input;
|
|
31
|
+
const { spec, queue, prepared, resume, rs, isDelegatedChild, entryActor, effectiveTimeoutMs, timeout, pushContent, ident, emitCommitted, writeFamilyOf, startedToolCallIds, announceWorkspaceMove, withBrainSinks, flushGitMirror, loopLatch, notificationLane, unsubscribeTaskNotifications, unsubGitRetry, unsubBoundary, unsub, runner, next } = input;
|
|
31
32
|
let final;
|
|
32
33
|
let threw;
|
|
33
34
|
let abortedLive = false;
|
|
@@ -101,11 +102,12 @@ export async function runLeg(input) {
|
|
|
101
102
|
else {
|
|
102
103
|
let continuation = resumeContinuation(resume, prepared.reminderMark);
|
|
103
104
|
const bgSnapshot = resume.cp.state.runningBackgroundTasks;
|
|
105
|
+
let orphanTasks = [];
|
|
104
106
|
if (bgSnapshot !== undefined && bgSnapshot.length > 0) {
|
|
105
107
|
const alive = new Set(prepared.listBackgroundTasks().map((t) => t.id));
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
continuation += "\n\n" + formatHookFeedback(renderOrphanedBackgroundTasks(
|
|
108
|
+
orphanTasks = bgSnapshot.filter((t) => !alive.has(t.id));
|
|
109
|
+
if (orphanTasks.length > 0) {
|
|
110
|
+
continuation += "\n\n" + formatHookFeedback(renderOrphanedBackgroundTasks(orphanTasks), prepared.reminderMark);
|
|
109
111
|
}
|
|
110
112
|
}
|
|
111
113
|
let gitResumeDelivered;
|
|
@@ -128,10 +130,13 @@ export async function runLeg(input) {
|
|
|
128
130
|
}
|
|
129
131
|
}
|
|
130
132
|
const engineSegments = continuation.length > 0 ? [{ start: 0, end: continuation.length }] : [];
|
|
133
|
+
const parkedSteers = readPendingSteerQueue(resume.cp.state);
|
|
131
134
|
const resumeFrames = [
|
|
132
|
-
...
|
|
135
|
+
...parkedSteers.map((entry) => ({ entry, source: "steer" })),
|
|
133
136
|
...(resume.wakeMessage !== undefined ? [{ entry: resume.wakeMessage, source: "wake" }] : []),
|
|
134
137
|
];
|
|
138
|
+
const appliedEvents = [];
|
|
139
|
+
const withheldSteerIds = new Set();
|
|
135
140
|
for (const { entry: steer, source } of resumeFrames) {
|
|
136
141
|
if (source === "wake" && resume.wakeMessageHookContext !== undefined) {
|
|
137
142
|
const hookStart = continuation.length;
|
|
@@ -166,6 +171,8 @@ export async function runLeg(input) {
|
|
|
166
171
|
outcome = { blocked: `the screen crashed (${inlineUntrusted(err.message)}; fail-closed)` };
|
|
167
172
|
}
|
|
168
173
|
if ("blocked" in outcome) {
|
|
174
|
+
if (steer.inputId !== undefined)
|
|
175
|
+
withheldSteerIds.add(steer.inputId);
|
|
169
176
|
deliverEngineNotice(runner.deps.onNotice, {
|
|
170
177
|
code: "steering.parked_input_blocked",
|
|
171
178
|
message: "a parked steering input was withheld by the deployment's userPromptSubmit screen when this resume redelivered it: " +
|
|
@@ -207,7 +214,7 @@ export async function runLeg(input) {
|
|
|
207
214
|
(steer.trusted ? formatHookFeedback(projected, prepared.reminderMark) : delimitUntrusted("supervisor steering message", projected));
|
|
208
215
|
if (steer.trusted)
|
|
209
216
|
engineSegments.push({ start, end: continuation.length });
|
|
210
|
-
|
|
217
|
+
appliedEvents.push({
|
|
211
218
|
...buildHumanInputEvent({
|
|
212
219
|
carrier: source,
|
|
213
220
|
source,
|
|
@@ -236,7 +243,22 @@ export async function runLeg(input) {
|
|
|
236
243
|
},
|
|
237
244
|
};
|
|
238
245
|
}
|
|
239
|
-
|
|
246
|
+
const pending = resume.cp.pendingAction;
|
|
247
|
+
const rejectionHalt = pending.kind === "tool_approval" && resume.outcome.gate === "policy_ask"
|
|
248
|
+
? maybeHumanRejectionHalt({ gate: resume.outcome.gateOutcome, isDelegatedChild, toolName: pending.toolName, toolCallId: pending.toolCallId })
|
|
249
|
+
: undefined;
|
|
250
|
+
if (rejectionHalt !== undefined && pending.kind === "tool_approval")
|
|
251
|
+
prepared.batchHaltRef.current = { rejectedToolCallId: pending.toolCallId };
|
|
252
|
+
prepared.undeliveredContinuationRef.current = { parkedSteers: resumeFrames.map(({ entry }) => entry).filter((e) => !withheldSteerIds.has(e.inputId)), orphanTasks };
|
|
253
|
+
final = await withBrainSinks(() => prepared.harness.prompt(continuation, {
|
|
254
|
+
engineSegments,
|
|
255
|
+
settleUnansweredToolCalls: rejectionHalt !== undefined ? { halt: rejectionHalt } : {},
|
|
256
|
+
onDelivered: () => {
|
|
257
|
+
prepared.undeliveredContinuationRef.current = { parkedSteers: [], orphanTasks: [] };
|
|
258
|
+
for (const e of appliedEvents)
|
|
259
|
+
queue.push(e);
|
|
260
|
+
},
|
|
261
|
+
}));
|
|
240
262
|
await flushGitMirror();
|
|
241
263
|
if (prepared.gitStatusRef.announced?.pending === true)
|
|
242
264
|
await prepared.gitStatusRef.reassert?.();
|
|
@@ -452,6 +474,7 @@ export async function runLeg(input) {
|
|
|
452
474
|
finally {
|
|
453
475
|
timeout.clear();
|
|
454
476
|
prepared.lspDiagnostics?.registry.releaseRun(prepared.lspDiagnostics.runIdent);
|
|
477
|
+
prepared.toolProgressRef.current?.clear();
|
|
455
478
|
prepared.abortController.abort();
|
|
456
479
|
prepared.releaseSignal();
|
|
457
480
|
strandedHumanAnswers = prepared.settleContentAskBindings();
|
|
@@ -463,6 +486,7 @@ export async function runLeg(input) {
|
|
|
463
486
|
notificationLane.live = false;
|
|
464
487
|
unsubscribeTaskNotifications();
|
|
465
488
|
prepared.toolRosterDeltas.unsubscribe();
|
|
489
|
+
prepared.toolDisclosure?.unsubscribe();
|
|
466
490
|
unsubGitRetry();
|
|
467
491
|
unsubBoundary();
|
|
468
492
|
unsub();
|
|
@@ -491,39 +515,7 @@ async function applyResumeDecision(runner, prepared, resume, emit, emitCommitted
|
|
|
491
515
|
e.code = "resume.tool_contract_mismatch";
|
|
492
516
|
throw e;
|
|
493
517
|
}
|
|
494
|
-
|
|
495
|
-
const deferredIds = pendingAction.batchToolCallIds.filter((id) => id !== pendingAction.toolCallId && !completed.has(id));
|
|
496
|
-
const names = new Map();
|
|
497
|
-
const deferredArgs = new Map();
|
|
498
|
-
if (deferredIds.length > 0) {
|
|
499
|
-
const { messages } = await prepared.session.buildContext();
|
|
500
|
-
for (const m of messages) {
|
|
501
|
-
if (m.role === "assistant") {
|
|
502
|
-
for (const c of m.content) {
|
|
503
|
-
if (c.type === "toolCall") {
|
|
504
|
-
names.set(c.id, c.name);
|
|
505
|
-
deferredArgs.set(c.id, c.arguments);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
for (const id of pendingAction.batchToolCallIds) {
|
|
512
|
-
if (id === pendingAction.toolCallId) {
|
|
513
|
-
await resolvePendingCall(runner, prepared, resume, emit, emitCommitted, onResolvedToolSuccess, onExecuteStart);
|
|
514
|
-
}
|
|
515
|
-
else if (!completed.has(id)) {
|
|
516
|
-
const name = names.get(id) ?? "unknown";
|
|
517
|
-
const displayLabel = (() => {
|
|
518
|
-
const l = prepared.tools.find((t) => t.name === name)?.label;
|
|
519
|
-
return l !== undefined && l !== name ? { label: l } : {};
|
|
520
|
-
})();
|
|
521
|
-
emit({ type: "tool_start", toolCallId: id, toolName: name, ...displayLabel, args: deferredArgs.get(id) ?? {} });
|
|
522
|
-
emit({ type: "tool_end", toolCallId: id, toolName: name, ...displayLabel, isError: true, ...toolEndBodyFrom({ content: formatHookFeedback(DEFERRED_REISSUE, prepared.reminderMark) }, true, prepared.structuredProjector) });
|
|
523
|
-
const eid = await prepared.session.appendMessage(toolResultMsg(id, name, formatHookFeedback(DEFERRED_REISSUE, prepared.reminderMark), true));
|
|
524
|
-
emitCommitted(eid, "toolResult", id);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
518
|
+
await resolvePendingCall(runner, prepared, resume, emit, emitCommitted, onResolvedToolSuccess, onExecuteStart);
|
|
527
519
|
}
|
|
528
520
|
async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted, onResolvedToolSuccess, onExecuteStart) {
|
|
529
521
|
const { pendingAction } = resume.cp;
|
|
@@ -538,6 +530,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
538
530
|
const pendingLabel = (() => { const l = prepared.tools.find((t) => t.name === pendingAction.toolName)?.label; return l !== undefined && l !== pendingAction.toolName ? { label: l } : {}; })();
|
|
539
531
|
emit({ type: "tool_start", toolCallId: pendingAction.toolCallId, toolName: pendingAction.toolName, ...pendingLabel, args: resolvedArgs });
|
|
540
532
|
const settleEnd = async (isError, result, gate = decidedGate) => {
|
|
533
|
+
prepared.toolProgressRef.current?.noteEnd(pendingAction.toolCallId);
|
|
541
534
|
emit({ type: "tool_end", toolCallId: pendingAction.toolCallId, toolName: pendingAction.toolName, ...pendingLabel, isError, ...toolEndBodyFrom(result, isError, prepared.structuredProjector, gate) });
|
|
542
535
|
const word = await resume.recordExecutionOutcome(gate);
|
|
543
536
|
settleExecutionRecord(runner.deps.onNotice, word, { toolName: pendingAction.toolName, gate, sessionId: prepared.sessionId, runId: prepared.runId, scope: resume.cp.scope, ...(resume.cp.checkpointId !== undefined ? { checkpointId: resume.cp.checkpointId } : {}) });
|
|
@@ -676,6 +669,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
676
669
|
}
|
|
677
670
|
const args = resolvedArgs;
|
|
678
671
|
onExecuteStart?.(pendingAction.toolCallId);
|
|
672
|
+
prepared.toolProgressRef.current?.noteStart(pendingAction.toolCallId, pendingAction.toolName);
|
|
679
673
|
prepared.suspendProgressRef.executedApproved = true;
|
|
680
674
|
let res;
|
|
681
675
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createPeerInboundChainRef, createPeerSelfRef } from "../../agents/peer-admission.js";
|
|
2
2
|
import { boundInputHashOf } from "../canonical-json.js";
|
|
3
|
-
import { isDelegatedAgentTerminal, isTerminalTaskNotification, renderTaskNotificationXml,
|
|
3
|
+
import { createLiveNotificationLane, isDelegatedAgentTerminal, isTerminalTaskNotification, renderTaskNotificationXml, routeOrParkNotification, SystemInjectionQueue } from "../task-notification.js";
|
|
4
4
|
import { ToolDetachHub } from "../tool-detach.js";
|
|
5
5
|
import { pendingContentAskCallId } from "./decide-continuation.js";
|
|
6
6
|
export async function runNotificationLane(input) {
|
|
@@ -32,9 +32,13 @@ export async function runNotificationLane(input) {
|
|
|
32
32
|
let notificationLaneLive = true;
|
|
33
33
|
let notificationSessionId;
|
|
34
34
|
let descendantAnchorDisclosed = false;
|
|
35
|
-
const parkTaskNotification = (payload, priority) => {
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const parkTaskNotification = (payload, priority, onDisposition) => {
|
|
36
|
+
laneSeat.handOff(payload);
|
|
37
|
+
const ownSession = notificationSessionId;
|
|
38
|
+
if (ownSession !== undefined)
|
|
39
|
+
routeOrParkNotification(pendingSessionNotifications, ownSession, payload, priority, onDisposition);
|
|
40
|
+
else
|
|
41
|
+
onDisposition?.("parked");
|
|
38
42
|
if (!isDelegatedAgentTerminal(payload))
|
|
39
43
|
return;
|
|
40
44
|
const uplink = internals?.parentNotify;
|
|
@@ -49,12 +53,12 @@ export async function runNotificationLane(input) {
|
|
|
49
53
|
}
|
|
50
54
|
const rootAnchor = internals?.rootSessionId;
|
|
51
55
|
if (rootAnchor !== undefined && rootAnchor !== notificationSessionId) {
|
|
52
|
-
pendingSessionNotifications
|
|
56
|
+
routeOrParkNotification(pendingSessionNotifications, rootAnchor, payload, priority);
|
|
53
57
|
return;
|
|
54
58
|
}
|
|
55
59
|
if (internals?.parentSessionId !== undefined && !descendantAnchorDisclosed) {
|
|
56
60
|
descendantAnchorDisclosed = true;
|
|
57
|
-
runner.deps.onError?.(new Error(`background-agent terminal ${payload.task_id}
|
|
61
|
+
runner.deps.onError?.(new Error(`background-agent terminal ${payload.task_id} stayed on this run's own session — the delegation tree's root session is not reachable from this run (no uplink, no root anchor)`), { phase: "degraded", sessionId: notificationSessionId ?? "", classification: "descendant-terminal-unrouted" });
|
|
58
62
|
}
|
|
59
63
|
};
|
|
60
64
|
const unsubscribeTaskNotifications = taskNotificationQueue.subscribe((item) => {
|
|
@@ -70,34 +74,33 @@ export async function runNotificationLane(input) {
|
|
|
70
74
|
? notificationHarness.followUp(xml, noteOptions)
|
|
71
75
|
: notificationHarness.steer(xml, { ...noteOptions, ...(item.priority === "now" ? { immediate: true } : {}) });
|
|
72
76
|
void deliver.then(() => item.onDisposition?.("queued"), () => {
|
|
73
|
-
parkTaskNotification(item.payload, item.priority);
|
|
74
|
-
item.onDisposition?.("parked");
|
|
77
|
+
parkTaskNotification(item.payload, item.priority, item.onDisposition);
|
|
75
78
|
});
|
|
76
79
|
}
|
|
77
80
|
else {
|
|
78
|
-
parkTaskNotification(item.payload, item.priority);
|
|
79
|
-
item.onDisposition?.("parked");
|
|
81
|
+
parkTaskNotification(item.payload, item.priority, item.onDisposition);
|
|
80
82
|
}
|
|
81
83
|
});
|
|
82
84
|
const upstreamTaskNotification = internals?.onTaskNotification;
|
|
83
85
|
const deliveredAtTurnOpen = new Set();
|
|
86
|
+
const laneSeat = createLiveNotificationLane({
|
|
87
|
+
queue: taskNotificationQueue,
|
|
88
|
+
canTakeNow: () => notificationLaneLive && notificationHarness?.acceptsInjections === true,
|
|
89
|
+
isLive: () => notificationLaneLive,
|
|
90
|
+
alreadyDelivered: (key) => deliveredAtTurnOpen.has(key),
|
|
91
|
+
});
|
|
92
|
+
const takeOnThisLane = laneSeat.take;
|
|
93
|
+
const takeAsDestination = laneSeat.takeAsDestination;
|
|
84
94
|
const injectTaskNotification = (notification, opts) => {
|
|
85
|
-
|
|
86
|
-
return Promise.resolve("dropped_duplicate");
|
|
87
|
-
if (!notificationLaneLive) {
|
|
88
|
-
parkTaskNotification(notification, opts?.priority ?? "later");
|
|
89
|
-
return Promise.resolve("parked");
|
|
90
|
-
}
|
|
95
|
+
const priority = opts?.priority ?? "later";
|
|
91
96
|
return new Promise((resolve) => {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
payload: notification,
|
|
97
|
-
onDisposition: resolve,
|
|
98
|
-
});
|
|
99
|
-
if (!accepted)
|
|
97
|
+
const own = takeOnThisLane(notification, priority, resolve);
|
|
98
|
+
if (own === "duplicate")
|
|
99
|
+
resolve("dropped_duplicate");
|
|
100
|
+
else if (own === "pending")
|
|
100
101
|
resolve("queued");
|
|
102
|
+
else if (own === "unavailable")
|
|
103
|
+
parkTaskNotification(notification, priority, resolve);
|
|
101
104
|
});
|
|
102
105
|
};
|
|
103
106
|
const peerSelfRef = internals?.peerSelfRef ?? createPeerSelfRef(internals?.registryScope ?? spec.principal ?? "default");
|
|
@@ -120,9 +123,34 @@ export async function runNotificationLane(input) {
|
|
|
120
123
|
}, self, taskIdRef);
|
|
121
124
|
const notificationLane = {
|
|
122
125
|
get harness() { return notificationHarness; }, set harness(h) { notificationHarness = h; },
|
|
123
|
-
get sessionId() { return notificationSessionId; },
|
|
126
|
+
get sessionId() { return notificationSessionId; },
|
|
127
|
+
set sessionId(s) {
|
|
128
|
+
if (notificationSessionId !== undefined)
|
|
129
|
+
pendingSessionNotifications.liveLanes.unregister(notificationSessionId, takeAsDestination);
|
|
130
|
+
notificationSessionId = s;
|
|
131
|
+
if (s !== undefined && notificationLaneLive)
|
|
132
|
+
pendingSessionNotifications.liveLanes.register(s, takeAsDestination);
|
|
133
|
+
},
|
|
124
134
|
get ident() { return notificationIdent; }, set ident(f) { notificationIdent = f; },
|
|
125
|
-
get live() { return notificationLaneLive; },
|
|
135
|
+
get live() { return notificationLaneLive; },
|
|
136
|
+
set live(v) {
|
|
137
|
+
notificationLaneLive = v;
|
|
138
|
+
if (notificationSessionId === undefined)
|
|
139
|
+
return;
|
|
140
|
+
if (v) {
|
|
141
|
+
pendingSessionNotifications.liveLanes.register(notificationSessionId, takeAsDestination);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
pendingSessionNotifications.liveLanes.unregister(notificationSessionId, takeAsDestination);
|
|
145
|
+
laneSeat.release();
|
|
146
|
+
}
|
|
147
|
+
},
|
|
126
148
|
};
|
|
127
|
-
|
|
149
|
+
try {
|
|
150
|
+
return await next({ prepared, injectTaskNotification, deliveredAtTurnOpen, peerInboundChainRef, modelCatalog, notificationLane, unsubscribeTaskNotifications });
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
if (notificationSessionId !== undefined)
|
|
154
|
+
pendingSessionNotifications.liveLanes.unregister(notificationSessionId, takeAsDestination);
|
|
155
|
+
}
|
|
128
156
|
}
|
|
@@ -107,6 +107,7 @@ export async function runSettleAndTeardown(input) {
|
|
|
107
107
|
strandedHumanAnswers,
|
|
108
108
|
remoteEnvFailures: prepared.remoteEnvFailures,
|
|
109
109
|
effectiveReadFace: prepared.effectiveReadFace,
|
|
110
|
+
effectiveWriteFace: prepared.effectiveWriteFace,
|
|
110
111
|
effectiveReadDenyPatterns: prepared.effectiveReadDenyPatterns,
|
|
111
112
|
effectiveMemoryScopes: prepared.effectiveMemoryScopes,
|
|
112
113
|
effectiveReasoning: reasoningResolution.current,
|
|
@@ -3,7 +3,7 @@ import { DEFAULT_COMPACTION_SETTINGS } from "../../internal/harness.js";
|
|
|
3
3
|
import { eventDefaultOn } from "../../prompt-assembly/event-registry.js";
|
|
4
4
|
import { appendInterruptionMarker, reconcileInterruptedSession } from "../session-reconcile.js";
|
|
5
5
|
import { emitTrace } from "../trace.js";
|
|
6
|
-
import { deliverEngineNotice, undrainedUserInputNotices } from "../types.js";
|
|
6
|
+
import { deliverEngineNotice, owedUserInputCounts, undrainedUserInputNotices } from "../types.js";
|
|
7
7
|
import { answerSettled, errorCodeOf } from "./assemble-result.js";
|
|
8
8
|
import { awaitChargeWithSlowDisclosure, discloseUnevaluableWindow } from "./clock-and-limits.js";
|
|
9
9
|
import { buildWorkingFileAttachments, centerAdoptionOption, contextInstructionFilesOption, emitInputTruncated, forkContextOption } from "./compaction-call-options.js";
|
|
@@ -14,7 +14,7 @@ import { reconciledToolEndBody } from "./tool-end-body.js";
|
|
|
14
14
|
export async function runTerminalAdoption(input) {
|
|
15
15
|
const { spec, queue, prepared, rs, stats, ident, emitCommitted, startedToolCallIds, toolLabels, timeout, compactionBrain, compactionBreaker, windowSafetyOptions, undrainedUserAtEnd, userInputLostAtEnd, final, abortedLive, userInterruptedLive, runner, sessions, next } = input;
|
|
16
16
|
let { threw } = input;
|
|
17
|
-
const settled = answerSettled(final, userInputLostAtEnd.current || prepared.workCutRef.continuation || prepared.workCutRef.abortedBeforeTurnEnd);
|
|
17
|
+
const settled = answerSettled(final, userInputLostAtEnd.current || prepared.undeliveredContinuationRef.current.parkedSteers.length > 0 || prepared.workCutRef.continuation || prepared.workCutRef.abortedBeforeTurnEnd);
|
|
18
18
|
if (threw === undefined && prepared.brainCallGuardrailRef.timedOut !== undefined) {
|
|
19
19
|
threw = prepared.brainCallGuardrailRef.timedOut;
|
|
20
20
|
}
|
|
@@ -77,16 +77,24 @@ export async function runTerminalAdoption(input) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
let migratedParked = { steer: 0, followUp: 0 };
|
|
80
|
+
let carriedContinuation = 0;
|
|
80
81
|
if (committedPause !== undefined && runner.deps.checkpointStore !== undefined) {
|
|
81
82
|
const parkToken = committedPause.cause.token;
|
|
82
83
|
const parkScope = committedPause.scope;
|
|
83
84
|
const store = runner.deps.checkpointStore;
|
|
84
85
|
const carried = [];
|
|
85
|
-
|
|
86
|
+
const owed = [
|
|
87
|
+
...prepared.undeliveredContinuationRef.current.parkedSteers.map(({ seq: _seq, ...input }) => ({ input })),
|
|
88
|
+
...prepared.harness.readParkableUserInputs().map((record) => ({ input: record, live: record })),
|
|
89
|
+
];
|
|
90
|
+
for (const { input, live } of owed) {
|
|
86
91
|
try {
|
|
87
|
-
if (!(await store.setPendingSteer(parkToken, parkScope,
|
|
92
|
+
if (!(await store.setPendingSteer(parkToken, parkScope, input)))
|
|
88
93
|
break;
|
|
89
|
-
|
|
94
|
+
if (live !== undefined)
|
|
95
|
+
carried.push(live);
|
|
96
|
+
else
|
|
97
|
+
carriedContinuation += 1;
|
|
90
98
|
}
|
|
91
99
|
catch (parkErr) {
|
|
92
100
|
runner.deps.onError?.(parkErr instanceof Error ? parkErr : new Error(String(parkErr)), {
|
|
@@ -101,14 +109,9 @@ export async function runTerminalAdoption(input) {
|
|
|
101
109
|
}
|
|
102
110
|
migratedParked = prepared.harness.dropParkedUserInputs(carried);
|
|
103
111
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
followUp: Math.max(0, undrainedUserAtEnd.current.followUp - migratedParked.followUp),
|
|
108
|
-
};
|
|
109
|
-
for (const notice of undrainedUserInputNotices(remaining, spec.taskId ?? prepared.sessionId, prepared.sessionId, prepared.runId)) {
|
|
110
|
-
deliverEngineNotice(runner.deps.onNotice, notice);
|
|
111
|
-
}
|
|
112
|
+
const owed = owedUserInputCounts(undrainedUserAtEnd.current, migratedParked, { frames: prepared.undeliveredContinuationRef.current.parkedSteers, carried: carriedContinuation, rowMayReturn: committedPause === undefined && !prepared.suspendProgressRef.executedApproved });
|
|
113
|
+
for (const notice of undrainedUserInputNotices(owed, spec.taskId ?? prepared.sessionId, prepared.sessionId, prepared.runId)) {
|
|
114
|
+
deliverEngineNotice(runner.deps.onNotice, notice);
|
|
112
115
|
}
|
|
113
116
|
if (rs.attach.attachState?.postCompactPending === true && (rs.attach.attachmentsCfg?.backgroundTasks ?? eventDefaultOn("background_tasks")) === true) {
|
|
114
117
|
emitTrace(rs.telemetry.tracer, () => ({ kind: "compaction.announce_dropped", version: 1, taskId: rs.telemetry.taskId, ts: Date.now() }));
|
|
@@ -15,6 +15,7 @@ import { awaitChargeWithSlowDisclosure, discloseUnevaluableWindow, ENV_DUE_GOVER
|
|
|
15
15
|
import { gitRestateOption } from "./git-leg-delivery.js";
|
|
16
16
|
import { COMPACTION_FREED_EPSILON, COMPACTION_REGROWTH_FACTOR, MAX_CONSECUTIVE_COMPACTION_FAILURES } from "./compaction-knobs.js";
|
|
17
17
|
import { compactionHookOptions, recordCompactionReuse, seamCCompactionOptions } from "./compaction-seams.js";
|
|
18
|
+
import { contextUsageSections } from "../../prompt-assembly/section-usage.js";
|
|
18
19
|
const BATCH_CONTEXT_MIN_KEEP_BYTES = 160;
|
|
19
20
|
const BATCH_TRUNCATION_MARKER = "\n…[truncated]";
|
|
20
21
|
export function createTurnBoundary(input) {
|
|
@@ -580,7 +581,8 @@ export function createTurnBoundary(input) {
|
|
|
580
581
|
}
|
|
581
582
|
rs.counters.trimForceBackoff = nextTrimForceBackoff(rs.counters.trimForceBackoff, comp, trimPressure);
|
|
582
583
|
if (comp.contextUsage) {
|
|
583
|
-
|
|
584
|
+
const sections = contextUsageSections(prepared.promptManifest.sections);
|
|
585
|
+
queue.push({ type: "context_usage", ...comp.contextUsage, ...(sections !== undefined ? { sections } : {}), ...ident() });
|
|
584
586
|
}
|
|
585
587
|
if (comp.unevaluableWindow) {
|
|
586
588
|
discloseUnevaluableWindow(comp.unevaluableWindow, prepared, rs.telemetry.tracer, rs.telemetry.taskId, runnerHooks.onError);
|
|
@@ -91,14 +91,14 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
91
91
|
/**
|
|
92
92
|
* Hot-swap the deployment seats a running Runner may change without a restart — the ONE door for every
|
|
93
93
|
* hot-swappable seat ({@link SWAPPABLE_DEP_SEATS}: the model catalog generation `models` + its `tiers`
|
|
94
|
-
* bindings, and the deployment's
|
|
94
|
+
* bindings, and the deployment's two containment-face declarations `readFace` / `writeFace`), and the ONLY sanctioned way to
|
|
95
95
|
* change any of them after construction. It replaces the former `swapModels` verb (retired, no alias):
|
|
96
96
|
* one verb per seat restated the same laws with a list of verbs as the only record of what is swappable.
|
|
97
97
|
*
|
|
98
98
|
* The laws, stated once (see the vocabulary module for the seat-by-seat meaning):
|
|
99
99
|
* - **Screened first, written once — atomic.** The candidate is screened whole
|
|
100
100
|
* ({@link screenSwappableDeps}: the key set is the closed one, at least one seat, `tiers` rides with
|
|
101
|
-
* `models`, each seat's own value gate —
|
|
101
|
+
* `models`, each seat's own value gate — both face seats through the very `assertContainmentFaceValue` every
|
|
102
102
|
* prepare door applies) and the catalog is tier-expanded on the candidate (an illegal binding throws
|
|
103
103
|
* exactly like the constructor's boot error) BEFORE the deps object is replaced. On any throw the
|
|
104
104
|
* current deps stay in force, byte-identical.
|
|
@@ -108,14 +108,15 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
108
108
|
* redirects never re-route or re-price a task mid-run; a read-face change never re-fences a mounted
|
|
109
109
|
* band; the divergence window is exactly the in-flight legs' lifetime, by design.
|
|
110
110
|
* - **Presence is the instruction.** A key present on the candidate is replaced (an explicit
|
|
111
|
-
* `undefined` clears an optional seat: `tiers: undefined` ⇒ no bindings, `
|
|
111
|
+
* `undefined` clears an optional seat: `tiers: undefined` ⇒ no bindings, a face seat `undefined` ⇒ the
|
|
112
112
|
* engine default); a key absent is kept. `tiers` omitted beside `models` ⇒ the current bindings are
|
|
113
113
|
* re-applied over the new catalog.
|
|
114
114
|
* - **Announced per seat.** `config.models_swapped` (models/tiers counts — key material only, never the
|
|
115
115
|
* catalog itself; plus the advisory `route.base_url_changed_key_unchanged` for same-name entries
|
|
116
116
|
* whose URL moved while the Model-visible credential fingerprint did not) and
|
|
117
|
-
* `config.read_face_swapped` (`{ from, to, occurrenceId }`, the seat's
|
|
118
|
-
* = no declaration) — the table {@link SWAP_SEAT_NOTICE} binds every
|
|
117
|
+
* `config.read_face_swapped` / `config.write_face_swapped` (`{ from, to, occurrenceId }`, the seat's
|
|
118
|
+
* previous and new value, `null` = no declaration) — the table {@link SWAP_SEAT_NOTICE} binds every
|
|
119
|
+
* seat to its line.
|
|
119
120
|
*/
|
|
120
121
|
swapDeps(next: SwappableDeps): void;
|
|
121
122
|
/** one-shot brain-routed utility query (see {@link runSideQuery} for the full contract):
|