@sema-agent/core 7.11.1 → 7.12.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 +41 -0
- package/dist/core/auto-mode-arming.d.ts +10 -14
- package/dist/core/auto-mode-arming.js +3 -9
- package/dist/core/auto-mode-defaults.d.ts +0 -2
- package/dist/core/auto-mode-defaults.js +0 -1
- package/dist/core/auto-mode-rebuild.d.ts +6 -13
- package/dist/core/auto-mode-rebuild.js +0 -2
- package/dist/core/auto-mode.d.ts +30 -89
- package/dist/core/auto-mode.js +12 -59
- package/dist/core/checkpoint-store.d.ts +1 -3
- package/dist/core/gate-fold.js +1 -9
- package/dist/core/gate-lanes.js +15 -9
- package/dist/core/hooks.d.ts +6 -0
- package/dist/core/runner/compaction-knobs.d.ts +45 -0
- package/dist/core/runner/compaction-knobs.js +3 -0
- package/dist/core/runner/contracts.d.ts +49 -10
- package/dist/core/runner/denial-limit-arms.d.ts +10 -13
- package/dist/core/runner/denial-limit-arms.js +9 -7
- package/dist/core/runner/gate-exit.js +9 -1
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +1 -1
- package/dist/core/runner/prepare-caps-and-workflow.js +0 -5
- package/dist/core/runner/prepare-suspend-saga.d.ts +0 -2
- package/dist/core/runner/prepare-suspend-saga.js +2 -10
- package/dist/core/runner/prepare-task.js +1 -1
- package/dist/core/runner/prepare-wiring-manifest.d.ts +1 -1
- package/dist/core/runner/prepare-wiring-manifest.js +1 -8
- package/dist/core/runner/run-attachment-seats.d.ts +22 -0
- package/dist/core/runner/run-attachment-seats.js +187 -0
- package/dist/core/runner/run-brain-sinks.d.ts +29 -0
- package/dist/core/runner/run-brain-sinks.js +61 -0
- package/dist/core/runner/run-clock-and-content.d.ts +52 -0
- package/dist/core/runner/run-clock-and-content.js +26 -0
- package/dist/core/runner/run-compaction-machinery.d.ts +35 -0
- package/dist/core/runner/run-compaction-machinery.js +98 -0
- package/dist/core/runner/run-git-lane.d.ts +64 -0
- package/dist/core/runner/run-git-lane.js +102 -0
- package/dist/core/runner/run-identity-wiring.d.ts +77 -0
- package/dist/core/runner/run-identity-wiring.js +85 -0
- package/dist/core/runner/run-leg.d.ts +106 -0
- package/dist/core/runner/run-leg.js +462 -0
- package/dist/core/runner/run-notification-lane.d.ts +55 -0
- package/dist/core/runner/run-notification-lane.js +128 -0
- package/dist/core/runner/run-reasoning-seat.d.ts +27 -0
- package/dist/core/runner/run-reasoning-seat.js +48 -0
- package/dist/core/runner/run-recovery-lanes.d.ts +54 -0
- package/dist/core/runner/run-recovery-lanes.js +180 -0
- package/dist/core/runner/run-settle-and-teardown.d.ts +109 -0
- package/dist/core/runner/run-settle-and-teardown.js +324 -0
- package/dist/core/runner/run-stop-and-final-verify.d.ts +32 -0
- package/dist/core/runner/run-stop-and-final-verify.js +159 -0
- package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +38 -0
- package/dist/core/runner/run-telemetry-and-budget-seats.js +159 -0
- package/dist/core/runner/run-terminal-adoption.d.ts +99 -0
- package/dist/core/runner/run-terminal-adoption.js +120 -0
- package/dist/core/runner/run-tool-mount-facts.d.ts +26 -0
- package/dist/core/runner/run-tool-mount-facts.js +58 -0
- package/dist/core/runner/run-turn-boundary.d.ts +0 -35
- package/dist/core/runner/run-turn-boundary.js +1 -3
- package/dist/core/runner/runtask.d.ts +14 -3
- package/dist/core/runner/runtask.js +125 -2102
- package/dist/core/runner-deps.d.ts +4 -14
- package/dist/core/store-contracts/workflow-journal-store-contract.d.ts +7 -0
- package/dist/core/store-contracts/workflow-journal-store-contract.js +85 -0
- package/dist/core/tool-policy.d.ts +37 -93
- package/dist/core/tool-policy.js +1 -11
- package/dist/core/trace.d.ts +6 -7
- package/dist/core/wiring-manifest.d.ts +5 -22
- package/dist/core/wiring-manifest.js +3 -11
- package/dist/core/workflow-journal-store.d.ts +35 -4
- package/dist/core/workflow-journal-store.js +19 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/orchestration/workflow.js +2 -0
- package/dist/stores/file/workflow-journal-store.d.ts +7 -10
- package/dist/stores/file/workflow-journal-store.js +2 -4
- package/dist/tools/fs/fs-bash.js +3 -2
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +10 -10
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/393 S5 — the run body's REASONING seat (R5), verbatim from `Runner.runLocked`: the leg-entry resolution of
|
|
3
|
+
* the requested reasoning intensity against the model's real capability, the ONE publisher that writes both faces
|
|
4
|
+
* (the `reasoning.resolved` trace frame and the `TaskResult.effectiveReasoning` seat on the backstop carrier), and
|
|
5
|
+
* the wire-facts consumer that lets the leg's FIRST committed request correct the cap-blind mint (once; foreign
|
|
6
|
+
* reports are contained at their call sites, not here).
|
|
7
|
+
*/
|
|
8
|
+
import { type ReasoningWireFacts, type ResolvedReasoning } from "../../brain/reasoning.js";
|
|
9
|
+
import type { Prepared, RunState, TaskIdRef } from "./contracts.js";
|
|
10
|
+
export interface RunReasoningSeatInput {
|
|
11
|
+
/** borrowed-readonly — the leg's prepared seat: the requested thinking level and the model. */
|
|
12
|
+
prepared: Prepared;
|
|
13
|
+
/** borrowed-readonly — the run's mutable state, read for the trace frames' tracer and task id. */
|
|
14
|
+
rs: RunState;
|
|
15
|
+
/** borrowed-mutable — the stream layer's backstop carrier: `effectiveReasoning` is published here at every mint. */
|
|
16
|
+
taskIdRef: TaskIdRef | undefined;
|
|
17
|
+
}
|
|
18
|
+
export interface RunReasoningSeatResult {
|
|
19
|
+
/** The CONSUMPTION half of {@link ReasoningWireFacts} — installed as the third brain ALS sink. */
|
|
20
|
+
observeReasoningWireFacts: (facts: ReasoningWireFacts) => void;
|
|
21
|
+
/** #327 — the leg's resolution as a READ FACE over this lane's own `let` (the leg-entry mint, then at most one
|
|
22
|
+
* first-committed-request correction): the settle lane's result assembly reads it for `effectiveReasoning`. */
|
|
23
|
+
reasoningResolution: {
|
|
24
|
+
readonly current: ResolvedReasoning | undefined;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export declare function runReasoningSeat(input: RunReasoningSeatInput): RunReasoningSeatResult;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { resolveReasoning } from "../../brain/reasoning.js";
|
|
2
|
+
import { emitTrace } from "../trace.js";
|
|
3
|
+
export function runReasoningSeat(input) {
|
|
4
|
+
const { prepared, rs, taskIdRef } = input;
|
|
5
|
+
let reasoningResolution = prepared.thinking && prepared.thinking !== "off" ? resolveReasoning(prepared.thinking, prepared.model) : undefined;
|
|
6
|
+
const publishReasoningResolution = (r) => {
|
|
7
|
+
reasoningResolution = r;
|
|
8
|
+
if (taskIdRef)
|
|
9
|
+
taskIdRef.effectiveReasoning = r;
|
|
10
|
+
emitTrace(rs.telemetry.tracer, () => ({
|
|
11
|
+
kind: "reasoning.resolved",
|
|
12
|
+
version: 1,
|
|
13
|
+
taskId: rs.telemetry.taskId,
|
|
14
|
+
model: prepared.model.id,
|
|
15
|
+
requested: r.requested,
|
|
16
|
+
effective: r.effective,
|
|
17
|
+
graded: r.graded,
|
|
18
|
+
clamped: r.clamped,
|
|
19
|
+
format: r.format,
|
|
20
|
+
endpoint: r.endpoint,
|
|
21
|
+
...(r.dropped === true ? { dropped: true } : {}),
|
|
22
|
+
ts: Date.now(),
|
|
23
|
+
}));
|
|
24
|
+
};
|
|
25
|
+
if (reasoningResolution !== undefined)
|
|
26
|
+
publishReasoningResolution(reasoningResolution);
|
|
27
|
+
let reasoningFactsConsumed = false;
|
|
28
|
+
const observeReasoningWireFacts = (facts) => {
|
|
29
|
+
if (reasoningFactsConsumed)
|
|
30
|
+
return;
|
|
31
|
+
reasoningFactsConsumed = true;
|
|
32
|
+
if (prepared.thinking === undefined || prepared.thinking === "off")
|
|
33
|
+
return;
|
|
34
|
+
const next = resolveReasoning(prepared.thinking, prepared.model, facts);
|
|
35
|
+
const current = reasoningResolution;
|
|
36
|
+
if (current !== undefined &&
|
|
37
|
+
current.effective === next.effective &&
|
|
38
|
+
current.graded === next.graded &&
|
|
39
|
+
current.clamped === next.clamped &&
|
|
40
|
+
current.format === next.format &&
|
|
41
|
+
current.endpoint === next.endpoint &&
|
|
42
|
+
current.dropped === next.dropped) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
publishReasoningResolution(next);
|
|
46
|
+
};
|
|
47
|
+
return { observeReasoningWireFacts, reasoningResolution: { get current() { return reasoningResolution; } } };
|
|
48
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Model } from "../../internal/llm.js";
|
|
2
|
+
import { type MaybeCompactOptions } from "../auto-compaction.js";
|
|
3
|
+
import type { HookInvocationIdentity } from "../hooks.js";
|
|
4
|
+
import type { PushQueue } from "../push-queue.js";
|
|
5
|
+
import type { Brain, TaskEvent, TaskSpec } from "../types.js";
|
|
6
|
+
import type { Prepared, RunnerDepsSeat, RunState } from "./contracts.js";
|
|
7
|
+
export interface RunRecoveryLanesInput {
|
|
8
|
+
/** borrowed-readonly — the task spec: the compaction settings / instructions and the key-and-headers seat. */
|
|
9
|
+
spec: TaskSpec;
|
|
10
|
+
/** borrowed-mutable — the leg's prepared seat: the loop recovery chain is installed on its harness, the arm-B seat
|
|
11
|
+
* on `microCompact.inTurnCompactionRef`, the MC-R clears on `microCompact.ledger`; the abort signal, the pause
|
|
12
|
+
* holder, the session, the compaction model and the cache-break detector are read. */
|
|
13
|
+
prepared: Prepared;
|
|
14
|
+
/** borrowed-mutable — the run's event queue: the `compacted` and `compaction_outcome` frames of both arms. */
|
|
15
|
+
queue: PushQueue<TaskEvent>;
|
|
16
|
+
/** borrowed-mutable — the run's mutable state: the anti-thrash floor (`counters.compactionFloor`) is raised and
|
|
17
|
+
* consulted, the post-compact announce latch armed and the cadence windows rebased on `attach.attachState`. */
|
|
18
|
+
rs: RunState;
|
|
19
|
+
/** borrowed-readonly — the run's event-identity mint. */
|
|
20
|
+
ident: () => {
|
|
21
|
+
eventId: string;
|
|
22
|
+
parentToolCallId?: string;
|
|
23
|
+
sourceTaskId?: string;
|
|
24
|
+
};
|
|
25
|
+
/** borrowed-readonly — the ACCOUNTED compaction brain (the compaction-machinery lane's), handed to every pass. */
|
|
26
|
+
compactionBrain: Brain;
|
|
27
|
+
/** borrowed-mutable — the shared consecutive-failure breaker: read by the gates, zeroed on a landing (and on a
|
|
28
|
+
* noop), bumped on a burned pass. */
|
|
29
|
+
compactionBreaker: {
|
|
30
|
+
failures: number;
|
|
31
|
+
};
|
|
32
|
+
/** borrowed-readonly — the window-safety option builder (the compaction-machinery lane's), per pass. */
|
|
33
|
+
windowSafetyOptions: (mainModel: Model) => Pick<MaybeCompactOptions, "fallbackBudget" | "onWindowSafety">;
|
|
34
|
+
/** borrowed-readonly — the Runner's deployment deps, read LIVE (`onError`). */
|
|
35
|
+
runner: RunnerDepsSeat;
|
|
36
|
+
/** borrowed-readonly — the Runner's three compaction methods as delegates: the Seam C reuse options, the hook
|
|
37
|
+
* option wrapper and the reuse counter. The method bodies stay the Runner's; the pass calls them as the run body did. */
|
|
38
|
+
compactionSeats: {
|
|
39
|
+
seamCCompactionOptions: (prepared: Prepared) => Pick<MaybeCompactOptions, "summaryProvider" | "onCompaction" | "maxConsecutiveProviderReuse" | "consecutiveProviderReuse"> | undefined;
|
|
40
|
+
compactionHookOptions: (spec: TaskSpec, sessionId: string, trigger: "auto" | "manual" | "forced", identity?: HookInvocationIdentity, seatBound?: {
|
|
41
|
+
timeoutMs: number;
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
}) => Pick<MaybeCompactOptions, "trigger" | "preCompact" | "postCompact">;
|
|
44
|
+
recordCompactionReuse: (prepared: Prepared, comp: {
|
|
45
|
+
compacted: boolean;
|
|
46
|
+
reused?: boolean;
|
|
47
|
+
}) => void;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Nothing comes back: the lane's products are INSTALLED on the seats it borrowed — the harness's loop recovery
|
|
51
|
+
* chain and the microCompact arm-B seat — and the shared pass is read by those two installations alone. */
|
|
52
|
+
export interface RunRecoveryLanesResult {
|
|
53
|
+
}
|
|
54
|
+
export declare function runRecoveryLanes(input: RunRecoveryLanesInput): RunRecoveryLanesResult;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { DEFAULT_COMPACTION_SETTINGS } from "../../internal/harness.js";
|
|
2
|
+
import { planRejectionClears } from "../context-edit.js";
|
|
3
|
+
import { DEFAULT_COMPACTION_INSTRUCTIONS, maybeCompact } from "../auto-compaction.js";
|
|
4
|
+
import { emitTrace } from "../trace.js";
|
|
5
|
+
import { isDegenerateCutMessage } from "../../brain/terminal-cause.js";
|
|
6
|
+
import { rebaseCadenceWindows } from "./turn-attachments.js";
|
|
7
|
+
import { buildWorkingFileAttachments, centerAdoptionOption, contextInstructionFilesOption, emitInputTruncated, forkContextOption } from "./compaction-call-options.js";
|
|
8
|
+
import { gitRestateOption } from "./git-leg-delivery.js";
|
|
9
|
+
import { COMPACTION_FREED_EPSILON, COMPACTION_REGROWTH_FACTOR, MAX_CONSECUTIVE_COMPACTION_FAILURES } from "./compaction-knobs.js";
|
|
10
|
+
export function runRecoveryLanes(input) {
|
|
11
|
+
const { spec, prepared, queue, rs, ident, compactionBrain, compactionBreaker, windowSafetyOptions, runner, compactionSeats } = input;
|
|
12
|
+
const runForcedCompactionPass = async (lane, turnSignal) => {
|
|
13
|
+
if (!(spec.compaction?.enabled ?? true))
|
|
14
|
+
return false;
|
|
15
|
+
if (compactionBreaker.failures >= MAX_CONSECUTIVE_COMPACTION_FAILURES)
|
|
16
|
+
return false;
|
|
17
|
+
const passSignal = turnSignal !== undefined ? AbortSignal.any([prepared.abortController.signal, turnSignal]) : prepared.abortController.signal;
|
|
18
|
+
try {
|
|
19
|
+
const comp = await maybeCompact({
|
|
20
|
+
session: prepared.session,
|
|
21
|
+
epochDeclaredSections: prepared.epochDeclaredSections,
|
|
22
|
+
...centerAdoptionOption(prepared),
|
|
23
|
+
model: prepared.harness.getModel(),
|
|
24
|
+
compactionModel: prepared.compModel,
|
|
25
|
+
...forkContextOption(prepared, true),
|
|
26
|
+
brain: compactionBrain,
|
|
27
|
+
getApiKeyAndHeaders: spec.getApiKeyAndHeaders,
|
|
28
|
+
thinking: prepared.thinking,
|
|
29
|
+
settings: { ...DEFAULT_COMPACTION_SETTINGS, ...spec.compaction },
|
|
30
|
+
customInstructions: spec.compaction?.instructions ?? DEFAULT_COMPACTION_INSTRUCTIONS,
|
|
31
|
+
signal: passSignal,
|
|
32
|
+
minTokens: 0,
|
|
33
|
+
force: true,
|
|
34
|
+
overheadTokens: prepared.promptOverheadTokens,
|
|
35
|
+
...(prepared.activeTools.size > 0 ? { activeTools: [...prepared.activeTools] } : {}),
|
|
36
|
+
onInputTruncated: emitInputTruncated(rs.telemetry.tracer, rs.telemetry.taskId),
|
|
37
|
+
workingFileAttachments: buildWorkingFileAttachments(spec, prepared),
|
|
38
|
+
...contextInstructionFilesOption(prepared),
|
|
39
|
+
...(prepared.onCompactionApplied ? { onApplied: prepared.onCompactionApplied } : {}),
|
|
40
|
+
...compactionSeats.seamCCompactionOptions(prepared),
|
|
41
|
+
...gitRestateOption(prepared),
|
|
42
|
+
...windowSafetyOptions(prepared.harness.getModel()),
|
|
43
|
+
...compactionSeats.compactionHookOptions(spec, prepared.sessionId, "forced", prepared.hookIdentity, { timeoutMs: prepared.hookTimeoutMs, signal: passSignal }),
|
|
44
|
+
});
|
|
45
|
+
if (comp.compacted) {
|
|
46
|
+
compactionBreaker.failures = 0;
|
|
47
|
+
compactionSeats.recordCompactionReuse(prepared, comp);
|
|
48
|
+
if ((comp.freedTokens ?? 0) >= COMPACTION_FREED_EPSILON) {
|
|
49
|
+
const postSize = comp.postTriggerTokens ?? Math.max(0, (comp.triggerTokens ?? comp.tokensBefore ?? 0) - (comp.freedTokens ?? 0));
|
|
50
|
+
rs.counters.compactionFloor = Math.ceil(postSize * COMPACTION_REGROWTH_FACTOR);
|
|
51
|
+
}
|
|
52
|
+
queue.push({
|
|
53
|
+
type: "compacted",
|
|
54
|
+
trigger: "forced",
|
|
55
|
+
tokensBefore: comp.tokensBefore ?? 0,
|
|
56
|
+
...(comp.postTriggerTokens !== undefined ? { tokensAfter: comp.postTriggerTokens } : {}),
|
|
57
|
+
...(comp.triggerTokens !== undefined ? { triggerTokensBefore: comp.triggerTokens } : {}),
|
|
58
|
+
...(comp.durationMs !== undefined ? { durationMs: comp.durationMs } : {}),
|
|
59
|
+
...(comp.phaseDurations !== undefined ? { phaseDurations: comp.phaseDurations } : {}),
|
|
60
|
+
...(comp.firstKeptEntryId !== undefined ? { preserved_segment: { firstKeptEntryId: comp.firstKeptEntryId } } : {}),
|
|
61
|
+
...(comp.attachedFiles !== undefined ? { attachedFiles: comp.attachedFiles } : {}),
|
|
62
|
+
...(comp.modelFallback ? { modelFallback: true } : {}),
|
|
63
|
+
...(comp.fallbackReason !== undefined ? { fallbackReason: comp.fallbackReason } : {}),
|
|
64
|
+
...(comp.clampedRatio !== undefined ? { clampedRatio: comp.clampedRatio } : {}),
|
|
65
|
+
...(comp.clampReason !== undefined ? { clampReason: comp.clampReason } : {}),
|
|
66
|
+
...ident(),
|
|
67
|
+
});
|
|
68
|
+
if (comp.phaseDurations !== undefined && comp.durationMs !== undefined) {
|
|
69
|
+
const pd = comp.phaseDurations;
|
|
70
|
+
const pdDur = comp.durationMs;
|
|
71
|
+
emitTrace(rs.telemetry.tracer, () => ({ kind: "compaction.phase_timings", version: 1, taskId: rs.telemetry.taskId, ...pd, durationMs: pdDur, ts: Date.now() }));
|
|
72
|
+
}
|
|
73
|
+
prepared.cacheBreakDetector?.notifyCompaction();
|
|
74
|
+
if (rs.attach.attachState !== undefined) {
|
|
75
|
+
rs.attach.attachState.postCompactPending = true;
|
|
76
|
+
rebaseCadenceWindows(rs.attach.attachState, rs.counters.cadenceTurns);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
if (comp.noop) {
|
|
81
|
+
compactionBreaker.failures = 0;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
compactionBreaker.failures += 1;
|
|
85
|
+
}
|
|
86
|
+
const declineReason = lane === "rejection" ? "prompt-too-long recovery pass did not land" : "guard-chain forced compaction pass did not land";
|
|
87
|
+
if (!comp.noop) {
|
|
88
|
+
runner.deps.onError?.(new Error(declineReason), { phase: "compaction", sessionId: prepared.sessionId });
|
|
89
|
+
}
|
|
90
|
+
queue.push({
|
|
91
|
+
type: "compaction_outcome",
|
|
92
|
+
outcome: comp.noop ? "noop" : "failed",
|
|
93
|
+
trigger: "forced",
|
|
94
|
+
reason: declineReason,
|
|
95
|
+
...ident(),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return comp.compacted === true;
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
if (turnSignal?.aborted === true && !prepared.abortController.signal.aborted) {
|
|
102
|
+
const interruptReason = lane === "rejection"
|
|
103
|
+
? "prompt-too-long recovery pass cut short by a turn interrupt"
|
|
104
|
+
: "guard-chain forced compaction cut short by a turn interrupt";
|
|
105
|
+
queue.push({ type: "compaction_outcome", outcome: "failed", trigger: "forced", reason: interruptReason, ...ident() });
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
compactionBreaker.failures += 1;
|
|
109
|
+
runner.deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "compaction", sessionId: prepared.sessionId });
|
|
110
|
+
const msg = String(err instanceof Error ? err.message : err);
|
|
111
|
+
queue.push({ type: "compaction_outcome", outcome: "failed", trigger: "forced", reason: msg.length > 512 ? `${msg.slice(0, 512)}…` : msg, ...ident() });
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
prepared.harness.setLoopRecovery({
|
|
116
|
+
truncatedOutput: {},
|
|
117
|
+
malformedToolUse: {},
|
|
118
|
+
thinkingOnly: {},
|
|
119
|
+
degenerateOutput: { detect: (m) => isDegenerateCutMessage(m) },
|
|
120
|
+
promptTooLong: {
|
|
121
|
+
recover: async (attempt, turnSignal) => {
|
|
122
|
+
if (prepared.abortController.signal.aborted || prepared.pausedRef.current !== undefined)
|
|
123
|
+
return false;
|
|
124
|
+
if (turnSignal?.aborted === true)
|
|
125
|
+
return false;
|
|
126
|
+
if (prepared.microCompact.clearOnRejection && attempt === 1) {
|
|
127
|
+
const proj = prepared.microCompact.projectionRef.current;
|
|
128
|
+
const compactionAvailable = (spec.compaction?.enabled ?? true) && compactionBreaker.failures < MAX_CONSECUTIVE_COMPACTION_FAILURES;
|
|
129
|
+
const declineArm = compactionAvailable ? "forced_compaction" : "none";
|
|
130
|
+
const plan = proj === undefined
|
|
131
|
+
? { declined: "no_candidates" }
|
|
132
|
+
: planRejectionClears(proj.messages, {
|
|
133
|
+
keyOf: proj.keyOf,
|
|
134
|
+
...(prepared.microCompact.offloadPersist ? { offload: { persist: prepared.microCompact.offloadPersist } } : {}),
|
|
135
|
+
});
|
|
136
|
+
if ("declined" in plan) {
|
|
137
|
+
emitTrace(rs.telemetry.tracer, () => ({
|
|
138
|
+
kind: "context.mc_null",
|
|
139
|
+
version: 1,
|
|
140
|
+
taskId: rs.telemetry.taskId,
|
|
141
|
+
reason: plan.declined,
|
|
142
|
+
nextArm: declineArm,
|
|
143
|
+
ts: Date.now(),
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
for (const e of plan.cleared) {
|
|
148
|
+
prepared.microCompact.ledger.entries.set(e.key, { marker: e.marker, groupCount: e.groupCount, fp: e.fp });
|
|
149
|
+
}
|
|
150
|
+
emitTrace(rs.telemetry.tracer, () => ({
|
|
151
|
+
kind: "context.mc_clear",
|
|
152
|
+
version: 1,
|
|
153
|
+
taskId: rs.telemetry.taskId,
|
|
154
|
+
clearedCount: plan.cleared.length,
|
|
155
|
+
tokensSavedEstimate: plan.tokensSavedEstimate,
|
|
156
|
+
trigger: "refusal",
|
|
157
|
+
ts: Date.now(),
|
|
158
|
+
}));
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return runForcedCompactionPass("rejection", turnSignal);
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
prepared.microCompact.inTurnCompactionRef.current = async (turnSignal, anchoredEstimate) => {
|
|
167
|
+
if (prepared.abortController.signal.aborted || prepared.pausedRef.current !== undefined)
|
|
168
|
+
return false;
|
|
169
|
+
if (turnSignal?.aborted === true)
|
|
170
|
+
return false;
|
|
171
|
+
if (anchoredEstimate !== undefined && rs.counters.compactionFloor > 0 && anchoredEstimate < rs.counters.compactionFloor) {
|
|
172
|
+
const floor = rs.counters.compactionFloor;
|
|
173
|
+
emitTrace(rs.telemetry.tracer, () => ({ kind: "compaction.suppressed", version: 1, taskId: rs.telemetry.taskId, estTokens: anchoredEstimate, floor, ts: Date.now() }));
|
|
174
|
+
queue.push({ type: "compaction_outcome", outcome: "suppressed", trigger: "forced", ...ident() });
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
return runForcedCompactionPass("guard", turnSignal);
|
|
178
|
+
};
|
|
179
|
+
return {};
|
|
180
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/393 S6 — the run body's SETTLE AND TEARDOWN (R15), verbatim from `Runner.runLocked`: the end-of-task
|
|
3
|
+
* compaction's frames and detector reset, the nested-stats fold, the prefix-cache observability and its loud
|
|
4
|
+
* mismatch / low-hit disclosures, the cross-slice cumulative spend fold, the human-review and mechanism counters,
|
|
5
|
+
* the result assembly (`assembleResult` — the one place the leg's facts become a TaskResult), the resume leg's
|
|
6
|
+
* unstarted-action reopen compensation, the read-state seal and the settle-time workspace-state write, the
|
|
7
|
+
* StopFailure observer, the delegation-lifecycle terminal, the reap-stash for a committed pause, the resumed-terminal
|
|
8
|
+
* unpin, the memory harvest, the `task.end` trace, `setResult`, the sub-agent's terminal tick, the mooted manual
|
|
9
|
+
* compaction, the forwarded-frame drain and the queue's `done` + close, the file-history boundary settle and the
|
|
10
|
+
* prompt-suggestion kickoff — then, in its finally, the four teardown legs in the order they were: the shell-lane
|
|
11
|
+
* children settle, the background-shell sweep, the registry clears / the background-agent abort / the retained
|
|
12
|
+
* child sessions, and the owned env's teardown.
|
|
13
|
+
*
|
|
14
|
+
* Async (eleven first-level awaits, all of them the same awaits at the same positions). The `queue.push("done")` and
|
|
15
|
+
* the teardown legs' order are contract (the forwarded-frame drain lands before `done`; the env is torn down after
|
|
16
|
+
* every reader of it); nothing here reorders them. Products: the result is PUBLISHED through `setResult` and the
|
|
17
|
+
* effects are installed on the borrowed seats — nothing comes back to the driver (the same empty Result the seat
|
|
18
|
+
* lanes whose products are all installations carry).
|
|
19
|
+
*/
|
|
20
|
+
import type { AssistantMessage } from "../../internal/llm.js";
|
|
21
|
+
import type { ResolvedReasoning } from "../../brain/reasoning.js";
|
|
22
|
+
import type { PushQueue } from "../push-queue.js";
|
|
23
|
+
import type { SessionStore } from "../session.js";
|
|
24
|
+
import type { CompactOutcome, DelegationLifecycleEvent, TaskEvent, TaskResult, TaskSpec } from "../types.js";
|
|
25
|
+
import { type Stats } from "./assemble-result.js";
|
|
26
|
+
import type { EndOfTaskCompaction, ManualCompactRef, Prepared, ResumeRun, RunInternals, RunnerDepsSeat, RunState, SuspendReap, TaskIdRef } from "./contracts.js";
|
|
27
|
+
export interface RunSettleAndTeardownInput {
|
|
28
|
+
/** borrowed-readonly — the task spec: the hooks slot, the suggestion opt-in, the retain / forward flags, the task id and principal. */
|
|
29
|
+
spec: TaskSpec;
|
|
30
|
+
/** borrowed-mutable — the run's event queue: the compaction / human-input / task_progress / done frames, then CLOSED here. */
|
|
31
|
+
queue: PushQueue<TaskEvent>;
|
|
32
|
+
/** borrowed-mutable — the leg's prepared seat: the settle-time seal and workspace write, the refs the result assembly reads, the env the teardown reaps. */
|
|
33
|
+
prepared: Prepared;
|
|
34
|
+
/** borrowed-readonly — the resume plan when this leg resumed a checkpoint (the reopen compensation and the unpin read it). */
|
|
35
|
+
resume: ResumeRun | undefined;
|
|
36
|
+
/** borrowed-readonly — the trusted run-scoped channel: the delegation task type, cycle seq, parent task id and the display-sink forward. */
|
|
37
|
+
internals: RunInternals | undefined;
|
|
38
|
+
/** borrowed-readonly — the run's mutable state, read for the telemetry / degrade / limits / counters the result and the frames report. */
|
|
39
|
+
rs: RunState;
|
|
40
|
+
/** borrowed-mutable — this leg's usage counters: the nested / cumulative folds, the cache-hit rate, the mechanism counters are written here. */
|
|
41
|
+
stats: Stats;
|
|
42
|
+
/** borrowed-readonly — the run's event-identity mint. */
|
|
43
|
+
ident: () => {
|
|
44
|
+
eventId: string;
|
|
45
|
+
parentToolCallId?: string;
|
|
46
|
+
sourceTaskId?: string;
|
|
47
|
+
};
|
|
48
|
+
/** borrowed-readonly — the spawning tool call's id when this task runs AS A SUB-AGENT (gates the terminal tick). */
|
|
49
|
+
parentToolCallId: string | undefined;
|
|
50
|
+
/** borrowed-readonly — the sub-agent display name for the terminal tick. */
|
|
51
|
+
subagentName: string | undefined;
|
|
52
|
+
/** borrowed-readonly — the loop-liveness latch: `userHalted` signs the result's halt seat. */
|
|
53
|
+
loopLatch: {
|
|
54
|
+
readonly userHalted: boolean;
|
|
55
|
+
};
|
|
56
|
+
/** borrowed-readonly — the hard walltime timer: `fired` and `latenessMs` ride the result and the `task.end` frame. */
|
|
57
|
+
timeout: {
|
|
58
|
+
readonly fired: boolean;
|
|
59
|
+
readonly latenessMs?: number;
|
|
60
|
+
};
|
|
61
|
+
/** borrowed-readonly — the run's own committed tail (the read-state seal). */
|
|
62
|
+
ownCommittedTailRef: {
|
|
63
|
+
readonly current: string | undefined;
|
|
64
|
+
};
|
|
65
|
+
/** borrowed-readonly — the delegation-lifecycle emission closure (the terminal station is here). */
|
|
66
|
+
emitDelegationLifecycle: (event: DelegationLifecycleEvent) => void;
|
|
67
|
+
/** borrowed-mutable — the stream layer's backstop carrier: the owed delegation terminal is cleared here. */
|
|
68
|
+
taskIdRef: TaskIdRef | undefined;
|
|
69
|
+
/** borrowed-mutable — the manual /compact seat: the parked waiters are mooted and the channel closed before `done`. */
|
|
70
|
+
manualCompactRef: ManualCompactRef;
|
|
71
|
+
/** borrowed-readonly — the boundary lane's drain of the manual-compact waiters (with the outcome every waiter receives). */
|
|
72
|
+
drainManualCompact: (outcome: CompactOutcome) => void;
|
|
73
|
+
/** borrowed-readonly — the leg lane's final assistant message (undefined on every no-prompt arm). */
|
|
74
|
+
final: AssistantMessage | undefined;
|
|
75
|
+
/** borrowed-readonly — the adopted terminal cause (the leg's throw, or what the terminal-adoption lane lifted over it). */
|
|
76
|
+
threw: unknown;
|
|
77
|
+
/** borrowed-readonly — the live-abort flag captured before the leg's release-abort. */
|
|
78
|
+
abortedLive: boolean;
|
|
79
|
+
/** borrowed-readonly — design/174: the answered-but-never-collected deliveries the leg's finally settled. */
|
|
80
|
+
strandedHumanAnswers: ReadonlyArray<{
|
|
81
|
+
deliveryId: string;
|
|
82
|
+
toolCallId: string;
|
|
83
|
+
}>;
|
|
84
|
+
/** borrowed-readonly — the reasoning seat's resolution, as the read face on its Result (the result's `effectiveReasoning`). */
|
|
85
|
+
reasoningResolution: {
|
|
86
|
+
readonly current: ResolvedReasoning | undefined;
|
|
87
|
+
};
|
|
88
|
+
/** borrowed-readonly — the end-of-task compaction's outcome (the terminal-adoption lane's `finish` call). */
|
|
89
|
+
comp: EndOfTaskCompaction;
|
|
90
|
+
/** borrowed-readonly — the stream's result setter: the assembled TaskResult is published through it exactly once. */
|
|
91
|
+
setResult: (r: TaskResult) => void;
|
|
92
|
+
/** borrowed-readonly — the stream's suggestions seat: the fire-and-forget suggestion pass's promise is handed to it. */
|
|
93
|
+
onSuggestions: (p: Promise<string[]>) => void;
|
|
94
|
+
/** borrowed-readonly — the stream's reap-stash for a committed pause (what `destroy()` reaps when the run SUSPENDED). */
|
|
95
|
+
onSuspend: (reap: SuspendReap) => void;
|
|
96
|
+
/** borrowed-readonly — the Runner's deployment deps, read LIVE (`onError`, `hooks`, `checkpointStore`, `executionEnv`, `onNotice`);
|
|
97
|
+
* the one home of why it is a seat and not a captured object is {@link RunnerDepsSeat}. */
|
|
98
|
+
runner: RunnerDepsSeat;
|
|
99
|
+
/** borrowed-readonly — the session store: the resumed-terminal leg unpins the checkpoint's session through it. */
|
|
100
|
+
sessions: SessionStore;
|
|
101
|
+
/** borrowed-readonly — the Runner's post-completion prompt-suggestion pass (its private method, as a delegate). */
|
|
102
|
+
suggestNextPrompts: (spec: TaskSpec, prepared: Prepared, result: TaskResult) => Promise<string[]>;
|
|
103
|
+
/** borrowed-readonly — the Runner's owned-env teardown (its private method, as a delegate; its gate mirrors the reap-stash's). */
|
|
104
|
+
teardownOwnedEnv: (prepared: Prepared) => Promise<void>;
|
|
105
|
+
}
|
|
106
|
+
/** Nothing comes back: the result is published through `setResult`, the queue is closed, the teardown legs ran. */
|
|
107
|
+
export interface RunSettleAndTeardownResult {
|
|
108
|
+
}
|
|
109
|
+
export declare function runSettleAndTeardown(input: RunSettleAndTeardownInput): Promise<RunSettleAndTeardownResult>;
|