@sema-agent/core 7.15.0 → 7.16.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 +29 -0
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/memory-engine/delegation-settlement.d.ts +37 -12
- package/dist/core/memory-engine/delegation-settlement.js +128 -39
- package/dist/core/memory-engine/engine.d.ts +9 -8
- package/dist/core/memory-engine/engine.js +115 -120
- package/dist/core/memory-engine/file-backend.d.ts +17 -5
- package/dist/core/memory-engine/file-backend.js +78 -34
- package/dist/core/memory-engine/index.d.ts +2 -2
- package/dist/core/memory-engine/index.js +2 -2
- package/dist/core/memory-engine/layout.d.ts +152 -54
- package/dist/core/memory-engine/layout.js +441 -104
- package/dist/core/memory-engine/types.d.ts +8 -3
- package/dist/core/memory-engine/types.js +5 -0
- package/dist/core/runner/abort-race.d.ts +3 -3
- package/dist/core/runner/active-skill-scope.d.ts +2 -2
- package/dist/core/runner/assemble-result.d.ts +29 -29
- package/dist/core/runner/checkpoint-scope.d.ts +4 -4
- package/dist/core/runner/clock-and-limits.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.d.ts +11 -11
- package/dist/core/runner/compaction-knobs.d.ts +4 -4
- package/dist/core/runner/compaction-seams.d.ts +5 -5
- package/dist/core/runner/contracts.d.ts +222 -224
- package/dist/core/runner/decide-continuation.d.ts +6 -6
- package/dist/core/runner/denial-limit-arms.d.ts +8 -8
- package/dist/core/runner/derived-route-fallback.d.ts +2 -2
- package/dist/core/runner/gate-exit.d.ts +6 -6
- package/dist/core/runner/git-status-frame.d.ts +7 -7
- package/dist/core/runner/inherited-ask-grants.d.ts +6 -6
- package/dist/core/runner/memory-capture-optout.d.ts +1 -1
- package/dist/core/runner/memory-consolidation-driver.d.ts +4 -4
- package/dist/core/runner/memory-consolidation.d.ts +6 -6
- package/dist/core/runner/park-commit.d.ts +6 -6
- package/dist/core/runner/permission-rule-lanes.d.ts +19 -19
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +4 -4
- package/dist/core/runner/prepare-ask-lane.d.ts +3 -3
- package/dist/core/runner/prepare-boundary-parks.d.ts +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +5 -5
- package/dist/core/runner/prepare-config-doors.d.ts +21 -21
- package/dist/core/runner/prepare-context-lane.d.ts +6 -6
- package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-file-history.d.ts +2 -2
- package/dist/core/runner/prepare-gate-stations.d.ts +5 -5
- package/dist/core/runner/prepare-hands-readface.d.ts +33 -33
- package/dist/core/runner/prepare-inherited-gate.d.ts +4 -4
- package/dist/core/runner/prepare-listings.d.ts +3 -3
- package/dist/core/runner/prepare-lsp.d.ts +3 -3
- package/dist/core/runner/prepare-memory-engine-session.d.ts +5 -5
- package/dist/core/runner/prepare-memory.js +6 -7
- package/dist/core/runner/prepare-offload-wrappers.d.ts +2 -2
- package/dist/core/runner/prepare-park-ask.d.ts +6 -6
- package/dist/core/runner/prepare-policy-chain.d.ts +4 -4
- package/dist/core/runner/prepare-prompt-inputs.d.ts +5 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +1 -1
- package/dist/core/runner/prepare-question-face.d.ts +4 -4
- package/dist/core/runner/prepare-run-refs.d.ts +11 -11
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-suspend-saga.d.ts +4 -4
- package/dist/core/runner/prepare-task.d.ts +12 -12
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +2 -3
- package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -4
- package/dist/core/runner/prepare-workspace-restore.d.ts +1 -1
- package/dist/core/runner/remote-env-retry.d.ts +3 -3
- package/dist/core/runner/resume-admission.d.ts +1 -1
- package/dist/core/runner/resume-claim.d.ts +1 -1
- package/dist/core/runner/resume-internals-and-config.d.ts +1 -1
- package/dist/core/runner/resume-policy-outcome.d.ts +1 -1
- package/dist/core/runner/resume-preflight.d.ts +1 -1
- package/dist/core/runner/resume-review-outcome.d.ts +1 -1
- package/dist/core/runner/run-brain-sinks.d.ts +1 -1
- package/dist/core/runner/run-clock-and-content.d.ts +4 -4
- package/dist/core/runner/run-compaction-machinery.d.ts +3 -3
- package/dist/core/runner/run-git-lane.d.ts +1 -1
- package/dist/core/runner/run-harness-handlers.d.ts +2 -2
- package/dist/core/runner/run-identity-wiring.d.ts +4 -4
- package/dist/core/runner/run-leg.d.ts +3 -3
- package/dist/core/runner/run-notification-lane.d.ts +2 -2
- package/dist/core/runner/run-reasoning-seat.d.ts +2 -2
- package/dist/core/runner/run-settle-and-teardown.d.ts +4 -4
- package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
- package/dist/core/runner/run-terminal-adoption.d.ts +5 -5
- package/dist/core/runner/runtask.d.ts +14 -14
- package/dist/core/runner/session-file-state-replay.d.ts +3 -3
- package/dist/core/runner/session-rule-policy.d.ts +2 -2
- package/dist/core/runner/steer-admission.d.ts +2 -2
- package/dist/core/runner/stream-halt-verbs.d.ts +1 -1
- package/dist/core/runner/stream-reap.d.ts +1 -1
- package/dist/core/runner/synthetic-tools.d.ts +8 -8
- package/dist/core/runner/teardown-bounded.d.ts +2 -2
- package/dist/core/runner/tool-defer-gate.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +33 -33
- package/dist/core/runner/tool-end-body.d.ts +3 -3
- package/dist/core/runner/tool-face-overlay.d.ts +2 -2
- package/dist/core/runner/tool-output-projection.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +53 -53
- package/dist/core/runner/usage-accounting.d.ts +4 -4
- package/dist/core/runner/workspace-path.d.ts +1 -1
- package/dist/engine/llm/types.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/tools/fs/bash-readonly-classifier.d.ts +40 -40
- package/dist/tools/fs/encoding.d.ts +31 -40
- package/dist/tools/fs/fs-bash.d.ts +35 -35
- package/dist/tools/fs/fs-pdf.d.ts +8 -8
- package/dist/tools/fs/fs-search-tools.d.ts +4 -4
- package/dist/tools/fs/fs-shared.d.ts +144 -158
- package/dist/tools/fs/fs-write.d.ts +8 -8
- package/dist/tools/fs/gh-rate-limit.d.ts +13 -14
- package/dist/tools/fs/index.d.ts +74 -78
- package/dist/tools/fs/notebook.d.ts +24 -25
- package/dist/tools/fs/pdf.d.ts +3 -3
- package/dist/tools/fs/read-deny.d.ts +22 -22
- package/dist/tools/fs/read-face.d.ts +21 -24
- package/dist/tools/fs/repo-map.d.ts +8 -8
- package/dist/tools/fs/safety.d.ts +116 -129
- package/dist/tools/fs/search.d.ts +63 -71
- package/package.json +5 -2
- package/test/export-surface.snapshot.json +5 -1
|
@@ -394,6 +394,10 @@ export interface MaterializedFile {
|
|
|
394
394
|
/** True when the file belongs to a read-only inherited layer (chmod-protected, never harvested as a write). */
|
|
395
395
|
readonly: boolean;
|
|
396
396
|
}
|
|
397
|
+
/** The write face's home, for a call site that has established a write face exists (`writeScope !==
|
|
398
|
+
* null`). Throws on a read-only handle: a consumer that reaches here without a write face is a
|
|
399
|
+
* defect, and a template-literal or `join` over `null` would otherwise mint a `null/…` path. */
|
|
400
|
+
export declare function writableRootOf(handle: Pick<MemorySessionHandle, "writableRoot" | "writeScope">): string;
|
|
397
401
|
/**
|
|
398
402
|
* design/138 §2.2 — the session handle `materialize` returns and `harvest`/`rebaseline` consume.
|
|
399
403
|
* `materialized` IS the harvest diff domain (plus session-new files under `writableRoot`): an entry
|
|
@@ -405,9 +409,10 @@ export interface MemorySessionHandle {
|
|
|
405
409
|
* TODO(S1b): per-scope PHYSICAL roots (project scope in-repo + user scope in the home mount in ONE
|
|
406
410
|
* session) — `fileToScope` already keys absolute paths, so only the layout mapping needs the split. */
|
|
407
411
|
memoryDir: string;
|
|
408
|
-
/** The single directory the model may write memory into
|
|
409
|
-
*
|
|
410
|
-
|
|
412
|
+
/** The single directory the model may write memory into: the writeScope's home
|
|
413
|
+
* `<memoryDir>/<label>` (canonical). `null` iff there is no write face (`writeScope === null`) —
|
|
414
|
+
* a read-only layering has no directory the model may write, and no index is read from disk. */
|
|
415
|
+
writableRoot: string | null;
|
|
411
416
|
writeScope: string | null;
|
|
412
417
|
scopes: string[];
|
|
413
418
|
/** The materialized manifest = the harvest diff domain. */
|
|
@@ -1 +1,6 @@
|
|
|
1
1
|
export const MEMORY_ORIGIN_CAUSES = ["observed", "derived", "static", "unattributed"];
|
|
2
|
+
export function writableRootOf(handle) {
|
|
3
|
+
if (handle.writableRoot === null)
|
|
4
|
+
throw new Error("memory session handle has no write face (writeScope is null) — writableRoot is not available");
|
|
5
|
+
return handle.writableRoot;
|
|
6
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* same three helpers instead of each carrying a copy. Pure: no engine state, no clock.
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* The per-call signal composition all three synchronous-wait seats share
|
|
10
10
|
* (adjudicate / resolveAsk / resolveContentAsk): `AbortSignal.any([run, call])` when the gate
|
|
11
11
|
* threaded a per-call signal, the bare run signal otherwise (host-driven gates and unthreaded emits
|
|
12
12
|
* keep the historical binding byte for byte). The run signal is ALSO composed into the loop's turn
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* (both sources outlive it), so nothing here retains across calls.
|
|
16
16
|
*/
|
|
17
17
|
export declare function composeCallSignal(runSignal: AbortSignal, callSignal: AbortSignal | undefined): AbortSignal;
|
|
18
|
-
/**
|
|
18
|
+
/** How a raced await ended. The generalized sibling of the ask-side
|
|
19
19
|
* `raceAskWaitAgainstSignal` (tool-policy.ts): same three-state form over any value domain.
|
|
20
20
|
* `aborted` means the SIGNAL settled the race — the promise may still be pending and stays the
|
|
21
21
|
* caller's to detach. `threw` reports the rejection AS a rejection, never folded into the abort
|
|
@@ -31,7 +31,7 @@ export type RacedSettlement<T> = {
|
|
|
31
31
|
} | {
|
|
32
32
|
tag: "aborted";
|
|
33
33
|
};
|
|
34
|
-
/**
|
|
34
|
+
/** Settle a raced await the moment `signal` aborts, WITHOUT waiting for the
|
|
35
35
|
* promise to notice. Pre-aborted entry answers at once; the listener is removed on settle
|
|
36
36
|
* whichever side wins (the `raceAbort` hygiene: `{once}` alone leaks a closure on the signal when
|
|
37
37
|
* the promise settles first). The mapped promise attaches BOTH handlers up front, so an abort-arm
|
|
@@ -12,7 +12,7 @@ export type ActiveSkillFrame = {
|
|
|
12
12
|
reason: string;
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
|
-
* The per-task LIFO stack of active skill frames
|
|
15
|
+
* The per-task LIFO stack of active skill frames. Owned by `prepare-task`'s closure;
|
|
16
16
|
* the injected `skill` tool pushes onto it on a successful load, and a deny-narrowing policy reads it
|
|
17
17
|
* on every tool call. A simple array is the stack — `push` on load, and the policy reads ALL frames
|
|
18
18
|
* currently on it (the intersection). v1 keeps lifetime heuristic (see module header).
|
|
@@ -29,7 +29,7 @@ export declare class ActiveSkillScope {
|
|
|
29
29
|
get size(): number;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
|
-
* Build the Gate-3 deny-narrowing policy over a live {@link ActiveSkillScope}
|
|
32
|
+
* Build the Gate-3 deny-narrowing policy over a live {@link ActiveSkillScope}. For each
|
|
33
33
|
* tool call, WHILE any skill frame is active:
|
|
34
34
|
* - DENY any tool not in the INTERSECTION of every active frame's `allowTools`.
|
|
35
35
|
* - For a WRITE tool with an `allowPaths` constraint on ANY active frame, DENY a write whose
|
|
@@ -4,34 +4,34 @@ import type { NestedUsage, PausedCause, TaskResult, TaskSpec, TerminalCause } fr
|
|
|
4
4
|
export interface Stats {
|
|
5
5
|
turns: number;
|
|
6
6
|
tokens: number;
|
|
7
|
-
/**
|
|
7
|
+
/** Total tool calls executed (one per `tool_start`). Spread into `TaskResult.stats`. */
|
|
8
8
|
toolCalls: number;
|
|
9
|
-
/**
|
|
9
|
+
/** Prompt tokens that MISSED the cache (Anthropic-protocol `input_tokens` shape). */
|
|
10
10
|
promptTokens: number;
|
|
11
11
|
cachedTokens: number;
|
|
12
12
|
cacheWriteTokens: number;
|
|
13
13
|
cacheWriteTokensLong: number;
|
|
14
14
|
outputTokens: number;
|
|
15
15
|
cacheHitRate?: number;
|
|
16
|
-
/**
|
|
16
|
+
/** Cache-INCLUSIVE prompt total (`promptTokens + cachedTokens + cacheWriteTokens*`) — the
|
|
17
17
|
* billing/window/hit-rate denominator. Required (not derived) so a new accumulation site that forgets
|
|
18
18
|
* it fails the type check instead of silently reporting a total short by its own leg. */
|
|
19
19
|
totalInputTokens: number;
|
|
20
20
|
costMicroUsd: number;
|
|
21
|
-
/**
|
|
21
|
+
/** Present (`true`) when at least one model round of this leg reported NO usage frame (the brain's
|
|
22
22
|
* own `usageMissing` mark on the assistant message: an aborted / errored / usage-less provider reply). The
|
|
23
23
|
* numeric fields stay required and stay what was COUNTED — with this key present they are a LOWER BOUND,
|
|
24
24
|
* not a measurement ("0 is unknown, not free"). Absent ⇔ every round reported usage. */
|
|
25
25
|
usageMissing?: true;
|
|
26
26
|
nested?: NestedUsage;
|
|
27
|
-
/** Post-task memory-consolidation usage
|
|
27
|
+
/** Post-task memory-consolidation usage; set after the result is assembled. Kept out of
|
|
28
28
|
* the budget gate (`overBudget` reads `costMicroUsd`/`tokens`, never this). */
|
|
29
29
|
memory?: {
|
|
30
30
|
tokens: number;
|
|
31
31
|
costMicroUsd: number;
|
|
32
32
|
applied: number;
|
|
33
33
|
};
|
|
34
|
-
/**
|
|
34
|
+
/** Human-review burden. Wall-clock approval-gate wait + count, bucketed by
|
|
35
35
|
* `gate.kind`, accumulated across resume legs. Set by the run loop from the per-task human-review
|
|
36
36
|
* accumulator (synchronous `resolveAsk` timing + durable resume latency). **NOT an LLM cost** — never
|
|
37
37
|
* folded into `costMicroUsd`/`costBreakdown`/the budget gate (same budget-excluded treatment as `memory`).
|
|
@@ -65,21 +65,21 @@ export interface Stats {
|
|
|
65
65
|
segment: string;
|
|
66
66
|
}>;
|
|
67
67
|
};
|
|
68
|
-
/**
|
|
68
|
+
/** Within-task compaction LLM cost (micro-USD), accumulated by
|
|
69
69
|
* `recordCompactionUsage` as a SEPARATE running total because that cost IS folded into `costMicroUsd`
|
|
70
70
|
* (so it can't be re-derived from `costMicroUsd` alone). The {@link costBreakdown.compactionMicroUsd}
|
|
71
71
|
* source. Run-loop internal — not a public `TaskResult.stats` field. */
|
|
72
72
|
compactionMicroUsd?: number;
|
|
73
73
|
/**
|
|
74
|
-
*
|
|
74
|
+
* A thin FINANCE TAXONOMY of the LLM-derived costs the engine actually
|
|
75
75
|
* prices, decomposing the task's spend into report categories (no new persisted structure — derived from
|
|
76
76
|
* the cost sources that already exist). CORE = LLM-token-derived ONLY; the SERVICE adds the infra axes it
|
|
77
77
|
* owns (tool-call / sandbox-walltime / egress — it has the k8s cost data) and composes them with this.
|
|
78
78
|
* Each category is ≥ 0 and the parts reconcile to the independently-summed LLM total
|
|
79
79
|
* (`llmRoot + nestedSubagent + compaction` — `memory` is a separate, budget-excluded line, see its doc).
|
|
80
80
|
* Filled in assembleResult for `llmRoot`/`nestedSubagent`/`compaction`; the `memoryConsolidation` line is
|
|
81
|
-
* permanently 0 since
|
|
82
|
-
* public stats contract; an engine-plane re-mount
|
|
81
|
+
* permanently 0 since B19 retired the runner-integrated consolidation pass (field kept — it is
|
|
82
|
+
* public stats contract; an engine-plane re-mount would fill it again).
|
|
83
83
|
*/
|
|
84
84
|
costBreakdown?: {
|
|
85
85
|
/** Root-agent LLM cost (micro-USD): `costMicroUsd` MINUS the sub-categories already folded into it
|
|
@@ -97,29 +97,29 @@ export interface Stats {
|
|
|
97
97
|
compactionMicroUsd: number;
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
|
-
/**
|
|
100
|
+
/** The two cumulative budget ceilings a task can trip. Tokens outrank cost when both are
|
|
101
101
|
* over at the same boundary. */
|
|
102
102
|
export type BudgetAxis = "tokens" | "cost";
|
|
103
103
|
/**
|
|
104
104
|
* The terminal-state flags the run loop hands {@link assembleResult} — the typed contract between the
|
|
105
|
-
* loop and result assembly (
|
|
105
|
+
* loop and result assembly (exported so it's grep-able and tests can construct it).
|
|
106
106
|
*/
|
|
107
107
|
export interface ResultFlags {
|
|
108
108
|
threw: unknown;
|
|
109
|
-
/**
|
|
109
|
+
/** The run's ENGINE-minted identity (`Prepared.runId`), echoed verbatim on
|
|
110
110
|
* `TaskResult.runId`. Pure pass-through on every terminal: assembly neither mints nor derives it
|
|
111
111
|
* (a caller reaching assembly at all has completed prepare, so the value exists), and a
|
|
112
112
|
* hand-constructed flags bag without one simply produces a result without one. */
|
|
113
113
|
runId?: string;
|
|
114
|
-
/**
|
|
114
|
+
/** The EFFECTIVE (resolved) model id that served the task — echoed on `TaskResult.model`. */
|
|
115
115
|
model?: string;
|
|
116
|
-
/**
|
|
116
|
+
/** Some spend was accounted while the serving model had NO configured price table
|
|
117
117
|
* (no `RunnerDeps.pricing` entry, no `Model.cost`). The numeric total is then a fabricated
|
|
118
118
|
* undercount — `stats.costMicroUsd`/`costBreakdown` are OMITTED from the public result instead of
|
|
119
119
|
* reporting a 0 indistinguishable from "declared free". The internal accumulator (budget gate's
|
|
120
120
|
* coordinate) is untouched. */
|
|
121
121
|
unpricedSpend?: boolean;
|
|
122
|
-
/**
|
|
122
|
+
/** Prepare-time rewind disclosures to echo on `TaskResult.rewindNotes`.
|
|
123
123
|
* Pure pass-through — assembly neither adds nor filters (a rewind that FAILED never reaches here; it
|
|
124
124
|
* throws at prepare and lands in the `threw` slot as a terminal errorCode). */
|
|
125
125
|
rewindNotes?: TaskResult["rewindNotes"];
|
|
@@ -134,7 +134,7 @@ export interface ResultFlags {
|
|
|
134
134
|
* path the terminal is `completed`, and this is what tells that completion apart from a natural
|
|
135
135
|
* one — the model did not finish; the person stopped it and the run awaits their direction). */
|
|
136
136
|
haltedOnUserRejection?: boolean;
|
|
137
|
-
/**
|
|
137
|
+
/** A `TaskStream.halt` (the bare user interrupt, CC Esc form) was accepted
|
|
138
138
|
* while the run was live; echoed on `TaskResult.haltedByUser`. Pure pass-through on every
|
|
139
139
|
* terminal (the sibling `haltedOnUserRejection` law: the fact is about the leg that ran) PLUS
|
|
140
140
|
* one status decision it owns (slot 9.7 below): a run whose ONLY stop was this halt reads
|
|
@@ -143,28 +143,28 @@ export interface ResultFlags {
|
|
|
143
143
|
* brain kept (that text IS the result). The person stopped the run, which is the verb working,
|
|
144
144
|
* not a defect. A REAL abort/limit that also fired still owns the terminal above it. */
|
|
145
145
|
userHalted?: boolean;
|
|
146
|
-
/**
|
|
146
|
+
/** Call ids of answered-but-never-collected questions, echoed on
|
|
147
147
|
* `TaskResult.strandedHumanAnswers`. Pure pass-through; empty/absent ⇒ the field is omitted. The
|
|
148
148
|
* optional `onError` alert is NOT the disclosure — this mandatory result face is. */
|
|
149
149
|
strandedHumanAnswers?: TaskResult["strandedHumanAnswers"];
|
|
150
|
-
/**
|
|
150
|
+
/** The run's remote-workspace lifecycle failures, echoed on `TaskResult.remoteEnvFailures`.
|
|
151
151
|
* Pure pass-through (assembly neither adds nor filters) and INDEPENDENT of the status/errorCode chain:
|
|
152
152
|
* a refused `suspendVM` still ends the task exactly the way it did before — this only stops the eleven
|
|
153
153
|
* distinct codes from arriving as one anonymous `limits.max_turns_exceeded`. Empty/absent ⇒ the field is omitted. */
|
|
154
154
|
remoteEnvFailures?: TaskResult["remoteEnvFailures"];
|
|
155
|
-
/**
|
|
155
|
+
/** The run's effective read posture (resolved face + normalized deny
|
|
156
156
|
* additions), echoed on `TaskResult.effectiveReadFace` / `.effectiveReadDenyPatterns`. Pure
|
|
157
157
|
* pass-through (assembly neither adds nor filters) and INDEPENDENT of the status/errorCode chain:
|
|
158
158
|
* the posture is a fact about the leg that ran, whatever terminal it reached — a post-completion
|
|
159
159
|
* spawner folds it stricter-wins into follow-on legs; every other consumer may ignore it. */
|
|
160
160
|
effectiveReadFace?: TaskResult["effectiveReadFace"];
|
|
161
161
|
effectiveReadDenyPatterns?: TaskResult["effectiveReadDenyPatterns"];
|
|
162
|
-
/**
|
|
162
|
+
/** The memory-visibility observation, echoed on
|
|
163
163
|
* `TaskResult.effectiveMemoryScopes`. Pure pass-through on every terminal, same law as the
|
|
164
164
|
* read-posture seats above: present iff prepare completed (the memory-less states are their own
|
|
165
165
|
* values — absence means only "prepare never ran to completion"). */
|
|
166
166
|
effectiveMemoryScopes?: TaskResult["effectiveMemoryScopes"];
|
|
167
|
-
/**
|
|
167
|
+
/** The leg's effective reasoning resolution, echoed on `TaskResult.effectiveReasoning`.
|
|
168
168
|
* Pure pass-through on every terminal (same law as the read-posture seats): the SAME object the
|
|
169
169
|
* `reasoning.resolved` trace frame carried (runtask resolves once per leg — two faces, one mint);
|
|
170
170
|
* absent when thinking was off/unset for the leg, so the key is omitted. */
|
|
@@ -188,7 +188,7 @@ export interface ResultFlags {
|
|
|
188
188
|
* and the run takes the completed floor. Absent/false = the abort's ordinary reading. */
|
|
189
189
|
answerSettled?: boolean;
|
|
190
190
|
budgetHit?: "exceeded" | "precall";
|
|
191
|
-
/**
|
|
191
|
+
/** Which budget ceiling the hit belongs to. Set together with {@link budgetHit} at every
|
|
192
192
|
* site that records one; it picks the terminal code (`limits.max_tokens_exceeded` vs
|
|
193
193
|
* `limits.max_cost_exceeded`), so a hit without an axis would be an unattributable terminal. */
|
|
194
194
|
budgetAxis?: BudgetAxis;
|
|
@@ -198,7 +198,7 @@ export interface ResultFlags {
|
|
|
198
198
|
* the loop folded it into a text-only failure message, so the typed code rides this flag. */
|
|
199
199
|
gitCoreOverBudget?: boolean;
|
|
200
200
|
outputInvalid?: boolean;
|
|
201
|
-
/**
|
|
201
|
+
/** A re-suspend was refused because the task already suspended `maxSuspends` times
|
|
202
202
|
* (a resume/restart loop). It aborted the run (no `threw`) but must read as `failed`/`suspend.loop`,
|
|
203
203
|
* NOT `suspended` — slotted ABOVE `suspendRef` and the aborted branches (this suspend never minted a
|
|
204
204
|
* checkpoint, so `suspendRef` is unset anyway; the ordering makes the intent explicit). */
|
|
@@ -278,13 +278,13 @@ export declare function terminalCauseOf(final: AssistantMessage | undefined, sta
|
|
|
278
278
|
/**
|
|
279
279
|
* Build the final {@link TaskResult} from the run's terminal state. **The errorCode priority chain is a
|
|
280
280
|
* public contract** (callers `switch` on these strings) — first match wins, in this exact order
|
|
281
|
-
* (
|
|
281
|
+
* (red-line #3, do not reorder):
|
|
282
282
|
* 1. `outputInvalid` → `"output.invalid"`
|
|
283
|
-
* 2. degenerate → `"output.degenerate"` + `salvagedOutput` (
|
|
283
|
+
* 2. degenerate → `"output.degenerate"` + `salvagedOutput` (wins over budget/timeout)
|
|
284
284
|
* 3. `budgetHit` → `"limits.max_tokens_exceeded"` | `"limits.max_cost_exceeded"` (by `budgetAxis`;
|
|
285
285
|
* the pre-call estimate rejection and the after-spend crossing share the code — the distinction
|
|
286
286
|
* lives in `errorMessage`, not in a second code)
|
|
287
|
-
* 3.5 `suspendLoop` → `"suspend.loop"` (
|
|
287
|
+
* 3.5 `suspendLoop` → `"suspend.loop"` (the re-suspend cap; deterministic root
|
|
288
288
|
* cause, above `threw` because it owns the abort)
|
|
289
289
|
* 4. `threw` + walltime → `"limits.max_walltime_exceeded"`
|
|
290
290
|
* 5. `threw` + turns → `"limits.max_turns_exceeded"`
|
|
@@ -293,7 +293,7 @@ export declare function terminalCauseOf(final: AssistantMessage | undefined, sta
|
|
|
293
293
|
* 8. `blockedReason` → status `"blocked"` (no errorCode)
|
|
294
294
|
* 8.5 `paused` → status by the pause's registry row (`suspended` for an approval / resource
|
|
295
295
|
* slice / platform pause, `needs_review` + `"review.pending"` for a plan or dry-run review) +
|
|
296
|
-
* checkpointToken/gate (
|
|
296
|
+
* checkpointToken/gate (a deliberate durable pause beats the abort it used, but
|
|
297
297
|
* yields to a real budget/threw failure above)
|
|
298
298
|
* 9. `abortedLive` | stopReason aborted → `"limits.max_walltime_exceeded"` | `"limits.max_turns_exceeded"` | undefined
|
|
299
299
|
* (audit A-1: hoisted ABOVE no-final — the loop exits cleanly on abort, so `final` may be a
|
|
@@ -302,7 +302,7 @@ export declare function terminalCauseOf(final: AssistantMessage | undefined, sta
|
|
|
302
302
|
* and EXCEPT when the answer had already settled (`answerSettled`: a clean `"stop"` final, not
|
|
303
303
|
* partial) — a stop landing on the run's tail cuts no work, so the run falls through to 12
|
|
304
304
|
* (`completed`, the answer as `result`, no `limits.*` code for the axis; three axes, one law)
|
|
305
|
-
* 9.7 `userHalted` + (no `final` | the halt's own aborted `final`) → status `"completed"` (
|
|
305
|
+
* 9.7 `userHalted` + (no `final` | the halt's own aborted `final`) → status `"completed"` (a
|
|
306
306
|
* bare user halt — the verb working, not a defect; below the aborts on purpose, a real
|
|
307
307
|
* abort/limit that also fired owns the terminal and the halt rides as the pass-through seat)
|
|
308
308
|
* 10. no `final` → status `"failed"`
|
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
* the driver (the restore fold) and runtask (the resume rung) reach DOWN for the same names. Pure: a constant and two
|
|
6
6
|
* string functions.
|
|
7
7
|
*/
|
|
8
|
-
/**
|
|
8
|
+
/** The multi-tenant scope used when a durable suspend fires for an IRREVERSIBLE tool in an
|
|
9
9
|
* unattended deployment that did NOT opt into `durableApproval` (so there is no caller-supplied scope). The
|
|
10
10
|
* checkpoint carries this scope; resume reads it back from the checkpoint (`cp.scope`), so it is
|
|
11
11
|
* self-consistent without needing the original `TaskSpec`. Kept distinct from any tenant key to make an
|
|
12
12
|
* unattended irreversible suspend auditable as such. */
|
|
13
13
|
export declare const DEFAULT_IRREVERSIBLE_SCOPE = "irreversible";
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* The SINGLE derivation of a durable-suspend checkpoint's scope (both gate mint
|
|
16
16
|
* sites + the bg-watcher park lane's expire compensation/arbitration consume THIS; a re-derived copy
|
|
17
17
|
* that drifted was the exact bug the park tests caught — expire against the wrong scope silently
|
|
18
18
|
* no-ops). `|| DEFAULT` (not `??`): an EMPTY-string principal must not become a shared scope bucket.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
20
|
+
* That rule is stated twice in this file and was enforced on ONE of the two
|
|
21
21
|
* inputs — the principal half used `||`, the `durableApproval.scope` half used `??`, so an empty string
|
|
22
22
|
* arriving through the scope field (a config-centre / env lookup that came back blank is the realistic
|
|
23
23
|
* source) sailed through as the literal scope `""`. Two different tenants both landed in that one bucket,
|
|
@@ -33,7 +33,7 @@ export declare function checkpointScopeOf(spec: {
|
|
|
33
33
|
principal?: string;
|
|
34
34
|
}): string;
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* The ONE spelling of the placement fields' empty-string discipline: `""` is absence
|
|
37
37
|
* wearing clothes (the resume entry's principal-rung posture), and every placement read that must
|
|
38
38
|
* treat it so — the resume rung's two sides (runtask), the restore fold's seed and the suspend
|
|
39
39
|
* stamp — goes through THIS helper, so three sites cannot drift into three readings. Deliberately
|
|
@@ -18,7 +18,7 @@ import type { PlatformLimitReason } from "../checkpoint-store.js";
|
|
|
18
18
|
import type { TaskSpec } from "../types.js";
|
|
19
19
|
import type { Prepared } from "./contracts.js";
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* The LIMIT-APPROACH frames, the successor to the retired deadline-nudge family. Two facts
|
|
22
22
|
* make them a different mechanism, not a rename:
|
|
23
23
|
* - they are measured in BUDGET (the tightest armed axis's fill ratio), not in wall-clock, so they need
|
|
24
24
|
* no throughput estimate and cannot mis-fire on a starved event loop;
|
|
@@ -36,7 +36,7 @@ export declare function limitApproachFrames(index: 0 | 1, axis: string, percent:
|
|
|
36
36
|
/**
|
|
37
37
|
* Resolve the effective turn cap. `undefined` = no turn cap; `0` (explicit) = unbounded.
|
|
38
38
|
*
|
|
39
|
-
*
|
|
39
|
+
* This is now a pure read of what the caller wrote. The two clauses it used to carry —
|
|
40
40
|
* "a wall-clock bound was set, so drop the turn cap" and "neither was set, so apply the engine's
|
|
41
41
|
* safety net" — are both gone: the axes no longer interact (each binds on its own), and there is no
|
|
42
42
|
* engine-side net to apply. A task with no `maxTurns` has no turn ceiling.
|
|
@@ -88,7 +88,7 @@ export declare function awaitChargeWithSlowDisclosure<T>(charge: Promise<T>, onS
|
|
|
88
88
|
*/
|
|
89
89
|
export declare function raceUntilDeadline<T>(p: Promise<T>, deadline: number): Promise<T | typeof GOVERNANCE_READ_STALLED>;
|
|
90
90
|
/**
|
|
91
|
-
*
|
|
91
|
+
* The TYPED terminal for an external stop cause that could NOT be suspended durably.
|
|
92
92
|
* Carried on `rs.limits.platformTerminal` and adopted as the run's `threw`, so the caller reads the cause
|
|
93
93
|
* on `TaskResult.errorCode` (`errorCodeOf` lifts `.code`) instead of the anonymous error an abort produces.
|
|
94
94
|
* `retryAfterMs` rides the error object because a wait hint has no `TaskResult` seat — a host reads it from
|
|
@@ -5,7 +5,7 @@ import type { Context } from "../../internal/llm.js";
|
|
|
5
5
|
import { type ToolResultStore } from "../tool-result-store.js";
|
|
6
6
|
import type { Prepared } from "./contracts.js";
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* The maybeCompact call arguments that MUST be assembled identically on all three
|
|
9
9
|
* of runtask's compaction lanes (turn boundary / prompt-too-long recovery / end-of-task).
|
|
10
10
|
*
|
|
11
11
|
* Those lanes carried three hand-copied assemblies whose own comments said "must not silently
|
|
@@ -30,7 +30,7 @@ import type { Prepared } from "./contracts.js";
|
|
|
30
30
|
*/
|
|
31
31
|
export declare function buildWorkingFileAttachments(spec: TaskSpec, prepared: Prepared): MaybeCompactOptions["workingFileAttachments"];
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* `MaybeCompactOptions.contextInstructionFiles`: the seat that delivers the deployment's own
|
|
34
34
|
* instruction-file content (the CLAUDE.md family) to the SUMMARIZER, assembled once here and spread
|
|
35
35
|
* on all three lanes. Without it the compaction boundary is the one place a long task loses the
|
|
36
36
|
* standing instructions every other turn has been reading — and it loses them exactly where the
|
|
@@ -123,7 +123,7 @@ export declare function buildWorkingFileAttachments(spec: TaskSpec, prepared: Pr
|
|
|
123
123
|
*/
|
|
124
124
|
export declare function contextInstructionFilesOption(prepared: Prepared): Partial<Pick<MaybeCompactOptions, "contextInstructionFiles">>;
|
|
125
125
|
/**
|
|
126
|
-
*
|
|
126
|
+
* The CC-form fork seam, assembled identically on all three lanes (REF-A2): the
|
|
127
127
|
* summary request forks the main lane's latest real request (recorded by prepare-task's provider
|
|
128
128
|
* shim) instead of re-serializing the conversation into an independent full-price request.
|
|
129
129
|
* `maybeCompact` consults the accessor per pass and only when the summary model IS the main model;
|
|
@@ -135,7 +135,7 @@ export declare function contextInstructionFilesOption(prepared: Prepared): Parti
|
|
|
135
135
|
* clearStale content blanking, the aggregate tool-result/media caps, the orphan sweep), that
|
|
136
136
|
* projection is missing history the summary would PERMANENTLY replace — measured live: a fork of a
|
|
137
137
|
* trimmed request loses the fact-survival suite's fact; a fork of a clearStale'd request summarizes
|
|
138
|
-
* `[tool result cleared …]` markers
|
|
138
|
+
* `[tool result cleared …]` markers. That guard lives at the RECORDING side
|
|
139
139
|
* (prepare-task arms `requestLossyRef` per request build; a lossy request records `undefined`), so
|
|
140
140
|
* every lane degrades to the independent form — which reads the FULL session — automatically.
|
|
141
141
|
*
|
|
@@ -145,12 +145,12 @@ export declare function contextInstructionFilesOption(prepared: Prepared): Parti
|
|
|
145
145
|
*/
|
|
146
146
|
export declare function forkContextOption(prepared: Prepared, disable: boolean): Pick<MaybeCompactOptions, "forkContext">;
|
|
147
147
|
/**
|
|
148
|
-
*
|
|
148
|
+
* Compaction-boundary center-candidate adoption. Absent (an empty object, NOT a
|
|
149
149
|
* `centerAdoption: undefined` key) = restate as before; a boundary re-pin hashes the same artifact
|
|
150
150
|
* identity on every lane.
|
|
151
151
|
*/
|
|
152
152
|
export declare function centerAdoptionOption(prepared: Prepared): Partial<Pick<MaybeCompactOptions, "centerAdoption">>;
|
|
153
|
-
/**
|
|
153
|
+
/** Defaults (object-present, field-absent). Named per the magic-number rule. */
|
|
154
154
|
export declare const STALE_OFFLOAD_DEFAULT_KEEP_RECENT_PER_TOOL = 3;
|
|
155
155
|
export declare const STALE_OFFLOAD_DEFAULT_MIN_SAVINGS_CHARS = 2000;
|
|
156
156
|
/** Resolved (validated, defaulted) knob — see {@link resolveStaleToolResultOffload}. */
|
|
@@ -159,7 +159,7 @@ export interface ResolvedStaleToolResultOffload {
|
|
|
159
159
|
minSavingsChars: number;
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
162
|
-
*
|
|
162
|
+
* Validate + default the spec knob. Fail-loud on non-finite/negative/fractional
|
|
163
163
|
* values (a computed NaN silently re-defaulting is the ||0-fold this repo's engineering code bans);
|
|
164
164
|
* `undefined` knob ⇒ `undefined` (feature completely off).
|
|
165
165
|
*/
|
|
@@ -171,14 +171,14 @@ export declare function resolveStaleToolResultOffload(knob: StaleToolResultOfflo
|
|
|
171
171
|
* crossing the staleness line as newer same-tool results arrive) rewrites that message's bytes
|
|
172
172
|
* once, invalidating the provider cache from that position for one request — a bounded,
|
|
173
173
|
* once-per-result break the `minSavingsChars` floor is there to amortize.
|
|
174
|
-
* Deliberately NOT `offloadPagebackHint` (the
|
|
174
|
+
* Deliberately NOT `offloadPagebackHint` (the preview's hint): that hint's wording is a
|
|
175
175
|
* function of the LIVE reachable-tool set, and this pointer is re-derived per request — a mid-run
|
|
176
176
|
* ToolSearch activation would flip its bytes and break the very prefix stability this file pins.
|
|
177
|
-
* The reader is named by its real mounted name (
|
|
177
|
+
* The reader is named by its real mounted name (`read_tool_result` is a
|
|
178
178
|
* retired alias — a model following it burned a rejected call first). */
|
|
179
179
|
export declare function buildStaleOffloadPointer(toolName: string, ref: string, chars: number): string;
|
|
180
180
|
/**
|
|
181
|
-
*
|
|
181
|
+
* The request-side projection: replace STALE same-tool results with byte-stable
|
|
182
182
|
* pointers. "Stale" = has ≥ `keepRecentPerTool` NEWER results of the same tool name in this request
|
|
183
183
|
* — a monotone predicate (a result never gains "recency" back), so a replacement decision made on
|
|
184
184
|
* one request holds on every later one and re-derivation is deterministic: no run-scoped mutable
|
|
@@ -194,7 +194,7 @@ export declare function buildStaleOffloadPointer(toolName: string, ref: string,
|
|
|
194
194
|
* tool-call ids carry no cross-turn uniqueness contract), readable back via `read_tool_result`.
|
|
195
195
|
*/
|
|
196
196
|
export declare function projectStaleToolResults(context: Context, cfg: ResolvedStaleToolResultOffload, store: ToolResultStore, sessionId: string,
|
|
197
|
-
/** Run-scoped cache of refs already persisted by THIS run
|
|
197
|
+
/** Run-scoped cache of refs already persisted by THIS run: without it the
|
|
198
198
|
* write-once `put` is still re-issued every request — on the file backend that is a
|
|
199
199
|
* write-then-discard round-trip per stale result per turn. Caller owns the Set's lifetime. */
|
|
200
200
|
writtenRefs: Set<string>): Promise<Context>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The run loop's three compaction knobs
|
|
2
|
+
* The run loop's three compaction knobs: the consecutive-failure breaker trip, the anti-thrash
|
|
3
3
|
* regrowth factor and the effective-compaction epsilon. They were declared at the turn-boundary lane and the driver
|
|
4
4
|
* reached DOWN for them; the recovery lane (the forced-compaction pass the prompt-too-long and guard-chain arms
|
|
5
5
|
* share) reads the same three, and a lane may not name a sibling lane — so the three values sank to the machinery
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
* lane, and the prefix would put it under the phase-api gate and the run-lanes glob.
|
|
10
10
|
*/
|
|
11
11
|
/**
|
|
12
|
-
* §17.4
|
|
12
|
+
* §17.4: stop attempting within-task compaction after this many CONSECUTIVE
|
|
13
13
|
* failures in one task — a never-recovering summary gateway must not burn an API call at every turn
|
|
14
14
|
* boundary (CC: MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3). Reset on any success; an open breaker also
|
|
15
15
|
* skips the end-of-task attempt in `finish()` (teardown unaffected). Per-task scope.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
17
|
+
* This used to say "a flaky/never-recovering gateway", and the word `flaky` was not true. Because
|
|
18
18
|
* any success zeroes the counter, a gateway that alternates never reaches three CONSECUTIVE failures and
|
|
19
19
|
* the breaker never opens; it keeps paying for a call at every failed boundary, indefinitely.
|
|
20
20
|
*
|
|
@@ -37,7 +37,7 @@ export declare const MAX_CONSECUTIVE_COMPACTION_FAILURES = 3;
|
|
|
37
37
|
*/
|
|
38
38
|
export declare const COMPACTION_REGROWTH_FACTOR = 1.5;
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
40
|
+
* A compaction that frees fewer than this many (structural) tokens is
|
|
41
41
|
* treated as NO-EFFECTIVE-COMPACTION and does NOT raise the anti-thrash floor. Guards against a reused
|
|
42
42
|
* provider summary (or a pathological LLM summary) that reclaims no headroom yet suppresses the next real
|
|
43
43
|
* summary by inflating the floor to trigger×factor.
|
|
@@ -2,17 +2,17 @@ import type { MaybeCompactOptions } from "../auto-compaction.js";
|
|
|
2
2
|
import type { TaskSpec } from "../types.js";
|
|
3
3
|
import type { Prepared, RunnerDepsSeat } from "./contracts.js";
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* The cost-optimization compaction options threaded into BOTH `maybeCompact` call
|
|
6
6
|
* sites (within-task turn boundary + `finish()`). All three fields come from `RunnerDeps` (a trusted
|
|
7
7
|
* FUNCTION seam — never `TaskSpec`, which is serializable/durable-resumable/untrusted-caller). The
|
|
8
8
|
* Runner OWNS the consecutive-reuse counter (`prepared.compactionReuseRef`) so the
|
|
9
9
|
* `maxConsecutiveProviderReuse` drift guard spans the whole task across both sites: it FEEDS the current
|
|
10
10
|
* count in as `consecutiveProviderReuse`, and {@link recordCompactionReuse} updates it from the result.
|
|
11
11
|
* Returns `undefined` when no provider is wired (so the call site spreads nothing → byte-identical to
|
|
12
|
-
* the
|
|
12
|
+
* the prior behavior).
|
|
13
13
|
*/
|
|
14
14
|
export declare function seamCCompactionOptions(runner: RunnerDepsSeat, prepared: Prepared): Pick<MaybeCompactOptions, "summaryProvider" | "onCompaction" | "maxConsecutiveProviderReuse" | "consecutiveProviderReuse"> | undefined;
|
|
15
|
-
/**
|
|
15
|
+
/** Resolve the pre/postCompact lifecycle callbacks (whole-slot `spec.hooks ??
|
|
16
16
|
* deps.hooks`, same resolution as the stop hook) and wrap each in a SWALLOW+TRACE shell before
|
|
17
17
|
* threading them into maybeCompact. The wrapper owns the observability half of the R3 MED contract
|
|
18
18
|
* (maybeCompact swallows defensively too, but has no sink): a throwing callback is reported via
|
|
@@ -20,7 +20,7 @@ export declare function seamCCompactionOptions(runner: RunnerDepsSeat, prepared:
|
|
|
20
20
|
* reported as ignored (maybeCompact enforces the ignore — blocking a compaction the provider/trim
|
|
21
21
|
* layer already demanded would kill the run). */
|
|
22
22
|
export declare function compactionHookOptions(runner: RunnerDepsSeat, spec: TaskSpec, sessionId: string, trigger: "auto" | "manual" | "forced",
|
|
23
|
-
/**
|
|
23
|
+
/** The leg's identity envelope, spread onto both compaction contexts by the wrappers
|
|
24
24
|
* below (the compaction module builds its contexts below the runner and cannot know the leg;
|
|
25
25
|
* the wrapper is the runner's seam). Every runner call site supplies `prepared.hookIdentity`;
|
|
26
26
|
* optional only so a context built without a leg stays honestly identity-less. */
|
|
@@ -33,7 +33,7 @@ seatBound?: {
|
|
|
33
33
|
timeoutMs: number;
|
|
34
34
|
signal?: AbortSignal;
|
|
35
35
|
}): Pick<MaybeCompactOptions, "trigger" | "preCompact" | "postCompact">;
|
|
36
|
-
/**
|
|
36
|
+
/** Fold a finished compaction's `reused` flag into the run-scoped consecutive-reuse
|
|
37
37
|
* counter: a reused (provider) summary increments it, a real (LLM) summary resets it to 0. A no-op
|
|
38
38
|
* compaction (`compacted:false`) leaves the counter untouched. No-op when no provider is wired. */
|
|
39
39
|
export declare function recordCompactionReuse(runner: RunnerDepsSeat, prepared: Prepared, comp: {
|