@sema-agent/core 5.57.0 → 5.59.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 +96 -0
- package/dist/agents/cascade.d.ts +1 -1
- package/dist/agents/cumulative-stats.d.ts +1 -1
- package/dist/agents/observer.d.ts +2 -2
- package/dist/agents/peer-admission.d.ts +1 -1
- package/dist/agents/retain-ledger.d.ts +2 -2
- package/dist/agents/roster-store.d.ts +8 -8
- package/dist/agents/send-message-tool.d.ts +2 -2
- package/dist/agents/subagent-steps.d.ts +1 -1
- package/dist/agents/subagent.d.ts +13 -13
- package/dist/agents/team.d.ts +5 -5
- package/dist/agents/tool-filter.d.ts +2 -2
- package/dist/agents/verify.d.ts +1 -1
- package/dist/bench/metrics.d.ts +35 -35
- package/dist/brain/degrading.d.ts +1 -1
- package/dist/brain/errors.d.ts +3 -3
- package/dist/brain/reasoning.d.ts +2 -2
- package/dist/brain/repetition.d.ts +1 -1
- package/dist/brain/route-adjudicator.d.ts +8 -1
- package/dist/brain/route-adjudicator.js +8 -1
- package/dist/brain/status-sink.d.ts +2 -2
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/config/catalog.d.ts +5 -5
- package/dist/core/arg-summary.d.ts +4 -4
- package/dist/core/ask-class.d.ts +2 -2
- package/dist/core/ask-question.d.ts +1 -1
- package/dist/core/auto-compaction.d.ts +15 -15
- package/dist/core/auto-mode.d.ts +5 -5
- package/dist/core/background-agent-store.d.ts +20 -20
- package/dist/core/background-shell.d.ts +4 -4
- package/dist/core/checkpoint-store.d.ts +35 -27
- package/dist/core/context-edit.d.ts +1 -1
- package/dist/core/context-guard.d.ts +1 -1
- package/dist/core/exec-output-tail.d.ts +6 -6
- package/dist/core/file-snapshot-store.d.ts +8 -8
- package/dist/core/git-worktree-env.d.ts +3 -3
- package/dist/core/governance-codes.d.ts +37 -10
- package/dist/core/governance-codes.js +54 -1
- package/dist/core/hooks.d.ts +73 -33
- package/dist/core/hooks.js +87 -25
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/locked-config.d.ts +1 -1
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mailbox-store.d.ts +1 -1
- package/dist/core/mcp.d.ts +3 -3
- package/dist/core/memory-engine/consolidation-driver.d.ts +211 -0
- package/dist/core/memory-engine/consolidation-driver.js +427 -0
- package/dist/core/memory-engine/consolidation.d.ts +119 -3
- package/dist/core/memory-engine/consolidation.js +22 -1
- package/dist/core/memory-engine/data-plane.d.ts +1 -1
- package/dist/core/memory-engine/distiller.d.ts +550 -0
- package/dist/core/memory-engine/distiller.js +598 -0
- package/dist/core/memory-engine/dual-root.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +143 -10
- package/dist/core/memory-engine/engine.js +149 -23
- package/dist/core/memory-engine/file-backend.d.ts +14 -2
- package/dist/core/memory-engine/file-backend.js +3 -0
- package/dist/core/memory-engine/index.d.ts +6 -3
- package/dist/core/memory-engine/index.js +4 -2
- package/dist/core/memory-engine/layout.js +20 -6
- package/dist/core/memory-engine/origin-clearance.d.ts +1 -1
- package/dist/core/memory-engine/scope-contract.d.ts +4 -4
- package/dist/core/memory-engine/sync-client.d.ts +16 -16
- package/dist/core/memory-engine/sync.d.ts +4 -4
- package/dist/core/memory-engine/types.d.ts +17 -0
- package/dist/core/memory-recall.d.ts +1 -1
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/permission-rule-consent.d.ts +185 -36
- package/dist/core/permission-rule-consent.js +219 -44
- package/dist/core/permission-rule-model.d.ts +235 -31
- package/dist/core/permission-rule-model.js +105 -35
- package/dist/core/permission-rules.d.ts +9 -9
- package/dist/core/remote-env.d.ts +8 -8
- package/dist/core/roles.d.ts +3 -3
- package/dist/core/roles.js +1 -0
- package/dist/core/runner/assemble-result.d.ts +2 -2
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/memory-consolidation-driver.d.ts +49 -0
- package/dist/core/runner/memory-consolidation-driver.js +60 -0
- package/dist/core/runner/memory-consolidation.d.ts +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +3 -3
- package/dist/core/runner/prepare-task.d.ts +21 -21
- package/dist/core/runner/prepare-task.js +24 -17
- package/dist/core/runner/prepare-workspace-restore.d.ts +2 -2
- package/dist/core/runner/runtask.d.ts +11 -11
- package/dist/core/runner/runtask.js +4 -4
- package/dist/core/runner/session-rule-policy.d.ts +1 -1
- package/dist/core/runner/teardown-bounded.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +11 -11
- package/dist/core/scheduler.d.ts +5 -5
- package/dist/core/secret-env.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/session-policy-store.d.ts +2 -2
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +3 -3
- package/dist/core/session.d.ts +1 -1
- package/dist/core/shutdown-debug.d.ts +2 -2
- package/dist/core/side-query.d.ts +2 -2
- package/dist/core/spec-contract.d.ts +1 -1
- package/dist/core/store-contracts/contract-harness.d.ts +2 -2
- package/dist/core/store-contracts/contract-kit-version.d.ts +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +1 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +1 -1
- package/dist/core/task-notification.d.ts +5 -5
- package/dist/core/task-registry-agent.d.ts +12 -12
- package/dist/core/task-registry-monitor.d.ts +1 -1
- package/dist/core/task-registry-shared.d.ts +41 -41
- package/dist/core/task-registry.d.ts +12 -12
- package/dist/core/tool-detach.d.ts +2 -2
- package/dist/core/tool-errors.d.ts +3 -3
- package/dist/core/tool-policy.d.ts +113 -28
- package/dist/core/tool-policy.js +80 -1
- package/dist/core/tool-result-budget.d.ts +1 -1
- package/dist/core/tool-result-store.d.ts +2 -2
- package/dist/core/tools.d.ts +1 -1
- package/dist/core/trace.d.ts +26 -23
- package/dist/core/types.d.ts +164 -86
- package/dist/core/types.js +4 -3
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +7 -7
- package/dist/core/wiring-manifest.d.ts +5 -5
- package/dist/core/workflow-journal-store.d.ts +14 -14
- package/dist/core/workflow-run-store-contract.d.ts +1 -1
- package/dist/core/workflow-run-store-contract.js +1 -1
- package/dist/core/workflow-run-store.d.ts +4 -4
- package/dist/engine/compaction/compaction.d.ts +3 -3
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/execution-env/kill-tree.d.ts +1 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +8 -8
- package/dist/engine/harness/agent-harness.d.ts +6 -6
- package/dist/engine/harness/messages.d.ts +1 -1
- package/dist/engine/harness/types.d.ts +10 -10
- package/dist/engine/llm/types.d.ts +14 -14
- package/dist/engine/loop/agent-loop.d.ts +3 -3
- package/dist/engine/loop/types.d.ts +4 -4
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.d.ts +1 -1
- package/dist/engine/session/log-digest.d.ts +1 -1
- package/dist/engine/session/memory-repo.d.ts +2 -2
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/fixtures/index.d.ts +4 -4
- package/dist/index.d.ts +6 -5
- package/dist/index.js +5 -4
- package/dist/orchestration/goal.d.ts +1 -1
- package/dist/orchestration/run-spec.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +12 -12
- package/dist/orchestration/workflow-governance.d.ts +4 -4
- package/dist/orchestration/workflow-observe.d.ts +1 -1
- package/dist/orchestration/workflow-script-runner.d.ts +1 -1
- package/dist/orchestration/workflow-script-store.d.ts +9 -9
- package/dist/orchestration/workflow-size-guideline.d.ts +1 -1
- package/dist/orchestration/workflow-types.d.ts +5 -5
- package/dist/orchestration/workflow.d.ts +10 -10
- package/dist/prompt-assembly/artifact-store.d.ts +1 -1
- package/dist/prompt-assembly/artifact.d.ts +1 -1
- package/dist/prompt-assembly/assemble.d.ts +1 -1
- package/dist/prompt-assembly/composer.d.ts +2 -2
- package/dist/prompt-assembly/epoch.d.ts +2 -2
- package/dist/prompt-assembly/event-registry.d.ts +1 -1
- package/dist/prompt-assembly/explain.d.ts +3 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +1 -1
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -4
- package/dist/prompt-assembly/types.d.ts +12 -12
- package/dist/prompts/coordinator.d.ts +1 -1
- package/dist/prompts/default.d.ts +8 -8
- package/dist/prompts/simple-sections.d.ts +3 -3
- package/dist/prompts/supervisor.d.ts +2 -2
- package/dist/scenarios/full-body.d.ts +3 -3
- package/dist/scenarios/scenario-registry.d.ts +1 -1
- package/dist/stores/cc/sidecar-transcript.d.ts +3 -3
- package/dist/stores/file/fs-atomic.d.ts +2 -2
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/session-store.d.ts +2 -2
- package/dist/stores/file/workflow-journal-store.d.ts +4 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/encoding.d.ts +4 -4
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-pdf.d.ts +1 -1
- package/dist/tools/fs/fs-shared.d.ts +6 -6
- package/dist/tools/fs/index.d.ts +2 -2
- package/dist/tools/fs/notebook.d.ts +1 -1
- package/dist/tools/fs/pdf.d.ts +1 -1
- package/dist/tools/fs/read-deny.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +2 -2
- package/dist/tools/monitor.d.ts +3 -3
- package/dist/tools/task-list.d.ts +2 -2
- package/dist/tools/web.d.ts +4 -4
- package/dist/tools/worktree.d.ts +5 -5
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +1826 -3
package/dist/core/types.js
CHANGED
|
@@ -52,22 +52,23 @@ export function deliverEngineNotice(onNotice, notice) {
|
|
|
52
52
|
}
|
|
53
53
|
console.warn(notice.message);
|
|
54
54
|
}
|
|
55
|
-
export function undrainedUserInputNotices(counts, taskId) {
|
|
55
|
+
export function undrainedUserInputNotices(counts, taskId, sessionId) {
|
|
56
56
|
const tid = taskId !== undefined ? { taskId } : {};
|
|
57
|
+
const sid = sessionId !== undefined ? { sessionId } : {};
|
|
57
58
|
const tail = `accepted as "queued" were never consumed — the run ended first. They are NOT redelivered; re-send against a live run if still wanted.`;
|
|
58
59
|
const out = [];
|
|
59
60
|
if (counts.steer > 0) {
|
|
60
61
|
out.push({
|
|
61
62
|
code: "task.user_steer_undrained",
|
|
62
63
|
message: `${counts.steer} user steer(s) ${tail}`,
|
|
63
|
-
detail: { steer: counts.steer, ...tid },
|
|
64
|
+
detail: { steer: counts.steer, ...tid, ...sid },
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
if (counts.followUp > 0) {
|
|
67
68
|
out.push({
|
|
68
69
|
code: "task.user_followup_undrained",
|
|
69
70
|
message: `${counts.followUp} user follow-up(s) ${tail}`,
|
|
70
|
-
detail: { followUp: counts.followUp, ...tid },
|
|
71
|
+
detail: { followUp: counts.followUp, ...tid, ...sid },
|
|
71
72
|
});
|
|
72
73
|
}
|
|
73
74
|
return out;
|
|
@@ -5,7 +5,7 @@ export declare function redactSecrets(s: string, report?: RedactionReport): stri
|
|
|
5
5
|
export declare function redactHostLeaks(s: string, report?: RedactionReport): string;
|
|
6
6
|
/** Secret-redact + size-bound (NO injection fence) — the SAME-PRINCIPAL tier: workflow outputs/results/errors
|
|
7
7
|
* riding back to the launching model/script, run rows behind scope-gated observe. Paths/URLs survive
|
|
8
|
-
* (
|
|
8
|
+
* (the assertion pattern depends on them); secrets never do. */
|
|
9
9
|
export declare function boundedRedactedSummary(value: unknown, max: number): string;
|
|
10
10
|
/**
|
|
11
11
|
* The FULL untrusted-egress transform (design/97 CORE-2): full host-leak redaction + size-bound + FENCE. Use
|
|
@@ -236,7 +236,7 @@ export declare function defuseExactMarkInSegments(segments: readonly string[], m
|
|
|
236
236
|
*/
|
|
237
237
|
export declare function sanitizeUntrustedText(text: string, extraTags?: string[]): string;
|
|
238
238
|
/**
|
|
239
|
-
* [c209-C]
|
|
239
|
+
* [c209-C] 收口 C1/C2 (metadata-driven, replaces the shape-anchored
|
|
240
240
|
* `stripLeadingSystemReminders`) — cut the engine-prepended prefix off a user-lane message using the
|
|
241
241
|
* EXACT length recorded on the message at mint time (`UserMessage.enginePrefixChars`, stamped where
|
|
242
242
|
* the engine concatenated first-frame listing reminders / a UserPromptSubmit additionalContext
|
|
@@ -246,7 +246,7 @@ export declare function sanitizeUntrustedText(text: string, extraTags?: string[]
|
|
|
246
246
|
* summarizer input) must not let them (a) impersonate user authority or (b) evict the real
|
|
247
247
|
* objective from a head-truncated excerpt.
|
|
248
248
|
*
|
|
249
|
-
* The old helper GUESSED by reminder shape, which mis-fired in both directions (
|
|
249
|
+
* The old helper GUESSED by reminder shape, which mis-fired in both directions (收口轮): a
|
|
250
250
|
* same-line engine mint (`<system-reminder>[deadline] …</system-reminder>`) was NOT recognized and
|
|
251
251
|
* entered the window under `[user]` authority, while a user who legitimately opened their own
|
|
252
252
|
* prompt with a byte-exact reminder block WAS stripped. Metadata removes the guess entirely:
|
|
@@ -270,7 +270,7 @@ export interface EngineSegment {
|
|
|
270
270
|
end: number;
|
|
271
271
|
}
|
|
272
272
|
/**
|
|
273
|
-
* [c209-C] R5
|
|
273
|
+
* [c209-C] R5 — the three-state result of {@link normalizeEngineSegments}. `absent`
|
|
274
274
|
* and `malformed` are DIFFERENT states on purpose (R4 #1): a message whose `engineSegments` field
|
|
275
275
|
* is present-but-malformed must render WHOLLY verbatim — the metadata family is suspect, so a
|
|
276
276
|
* co-present `enginePrefixChars` must NOT get a second chance to cut (absent metadata is the only
|
|
@@ -285,7 +285,7 @@ export type NormalizedEngineSegments = {
|
|
|
285
285
|
readonly segments: ReadonlyArray<EngineSegment>;
|
|
286
286
|
};
|
|
287
287
|
/**
|
|
288
|
-
* [c209-C] R4
|
|
288
|
+
* [c209-C] R4 终判 (R5: three-state + exception-safe over `unknown`) — validate
|
|
289
289
|
* `UserMessage.engineSegments` against the text it indexes into.
|
|
290
290
|
* - `absent`: the field is `undefined` (or an empty array — it claims no engine bytes), so the
|
|
291
291
|
* `enginePrefixChars` sugar MAY still apply.
|
|
@@ -303,7 +303,7 @@ export type NormalizedEngineSegments = {
|
|
|
303
303
|
*/
|
|
304
304
|
export declare function normalizeEngineSegments(text: string, segments: unknown): NormalizedEngineSegments;
|
|
305
305
|
/**
|
|
306
|
-
* [c209-C] R4
|
|
306
|
+
* [c209-C] R4 终判 — the SEGMENT sibling of {@link cutEnginePrefix}: remove every
|
|
307
307
|
* engine-trusted `[start, end)` segment from a user-lane message, keeping the bytes OUTSIDE the
|
|
308
308
|
* segments verbatim (the caller/operator-authored content that derived views may present under
|
|
309
309
|
* `[user]`/`[User]:` authority). Unlike the prefix cut, segments can sit mid-message: the resume
|
|
@@ -311,7 +311,7 @@ export declare function normalizeEngineSegments(text: string, segments: unknown)
|
|
|
311
311
|
* ResumeOutcome/ResumeRun contract), so a trusted engine frame may legally follow an untrusted
|
|
312
312
|
* fenced one.
|
|
313
313
|
*
|
|
314
|
-
* [c209-C] R5
|
|
314
|
+
* [c209-C] R5 — the result distinguishes WHY nothing was cut: `malformed:true`
|
|
315
315
|
* means the field was PRESENT but bad (per {@link normalizeEngineSegments}) — the caller must
|
|
316
316
|
* render the whole message verbatim and MUST NOT fall through to `enginePrefixChars` (segments
|
|
317
317
|
* exist ⇒ they own the message; malformed ⇒ the metadata family is suspect wholesale). Only
|
|
@@ -323,7 +323,7 @@ export declare function cutEngineSegments(text: string, segments: unknown): {
|
|
|
323
323
|
malformed: boolean;
|
|
324
324
|
};
|
|
325
325
|
/**
|
|
326
|
-
* [c209-C] R5
|
|
326
|
+
* [c209-C] R5 — the ONE flatten under which `engineSegments`/`enginePrefixChars`
|
|
327
327
|
* offsets are DEFINED: a user-lane message qualifies only when its content is a plain string or a
|
|
328
328
|
* SINGLE text block (whose text is that same string). Multi-block / image-bearing content returns
|
|
329
329
|
* `undefined` and consumers render the message VERBATIM with their own local flatten — the two
|
|
@@ -36,7 +36,7 @@ export type WiringLegKind = "root" | "child" | "resume";
|
|
|
36
36
|
/** The shape of the resolved permission-ask seat (`spec.onAsk ?? deps.onAsk`): a live approver
|
|
37
37
|
* callback, a blanket `"allow"`/`"deny"` policy setting, or nothing at all. `"deny"` (a deliberate
|
|
38
38
|
* policy) and `"absent"` (a degrade to the headless auto-deny default) are DISTINCT on purpose —
|
|
39
|
-
* design/173
|
|
39
|
+
* design/173 */
|
|
40
40
|
export type AskSeamForm = "callback" | "allow" | "deny" | "absent";
|
|
41
41
|
/** What a policy `ask` actually reaches under this assembly. `"unresolved"` = not computable from
|
|
42
42
|
* the facts at hand (the static half's park-dependent arm). */
|
|
@@ -106,7 +106,7 @@ export interface WiringManifest {
|
|
|
106
106
|
serversOptedIn: number;
|
|
107
107
|
};
|
|
108
108
|
parkLane: {
|
|
109
|
-
/** A checkpoint store is wired (capability — design/173
|
|
109
|
+
/** A checkpoint store is wired (capability — design/173: capability and current policy
|
|
110
110
|
* are reported separately). */
|
|
111
111
|
capable: boolean;
|
|
112
112
|
/** capable ∧ (durableApproval opt-in ∨ forceDurableGate entitlement ∨ armed safety-tool
|
|
@@ -114,7 +114,7 @@ export interface WiringManifest {
|
|
|
114
114
|
* vocabulary are prepare-time facts). */
|
|
115
115
|
effective: boolean | "unresolved";
|
|
116
116
|
/** Why `effective` is `false`/`"unresolved"` — empty when `true`. The derivation chain an
|
|
117
|
-
* operator follows from `static unresolved` to `effective park unavailable
|
|
117
|
+
* operator follows from `static unresolved` to `effective park unavailable`. */
|
|
118
118
|
reasons: readonly ParkLaneReason[];
|
|
119
119
|
/** design/173 §8.4 (opus R7): the DECLARED durability of the resolved checkpoint store — an
|
|
120
120
|
* armed park lane over a process-local store is the "armed but memory-backed" degrade shape
|
|
@@ -159,7 +159,7 @@ export interface WiringManifest {
|
|
|
159
159
|
};
|
|
160
160
|
/**
|
|
161
161
|
* Governance surfaces (presence facts only). `audience: "operator"` is the MACHINE-READABLE
|
|
162
|
-
* projection classification (design/173
|
|
162
|
+
* projection classification (design/173): a serving layer forwarding this event to a
|
|
163
163
|
* multi-tenant/shared stream MUST project this section for operators only — and when it does no
|
|
164
164
|
* projection, the default is to NOT disclose the section, never to leak it.
|
|
165
165
|
*/
|
|
@@ -263,7 +263,7 @@ export declare function resolveSubagentTranscriptTier(agentStoreWired: boolean,
|
|
|
263
263
|
};
|
|
264
264
|
} | undefined): SubagentTranscriptTier;
|
|
265
265
|
/**
|
|
266
|
-
* The ONE `ask.effective` derivation (design/173
|
|
266
|
+
* The ONE `ask.effective` derivation (design/173) — shared by the effective manifest AND
|
|
267
267
|
* the posture door (`config.interaction_posture`), so "what does the door require" and "what does
|
|
268
268
|
* the manifest report" can never disagree:
|
|
269
269
|
* - a live approver callback ⇒ `human_reachable` (regardless of the park lane);
|
|
@@ -29,13 +29,13 @@ export interface ResumeClaimArgs {
|
|
|
29
29
|
* run's journal whose recorded scope equals the requested `scope` (a cross-scope `resumeFromRunId` resolves to an
|
|
30
30
|
* EMPTY journal → the resume safely diverges to a live re-run, never disclosing another tenant's results).
|
|
31
31
|
*
|
|
32
|
-
* SESSION-axis RULING (
|
|
32
|
+
* SESSION-axis RULING (ruled 2026-07-22):
|
|
33
33
|
* `load` is deliberately SCOPE-only, PERMANENTLY — same-scope callers from a different session may
|
|
34
34
|
* replay a run's journal. Rationale: (a) same-scope = same trust domain (the task-list store
|
|
35
35
|
* records the same posture) and a runId is engine-minted, not enumerable; (b) cross-session resume
|
|
36
36
|
* is `resumeFromRunId`'s CORE legitimate use — a fresh session picking up yesterday's run has a new
|
|
37
37
|
* taskId AND a new sessionId by construction, so ANY engine-side session/owner clamp on this face
|
|
38
|
-
* refuses exactly the contract the tool teaches (the
|
|
38
|
+
* refuses exactly the contract the tool teaches (the prefix-replay pins are the regression
|
|
39
39
|
* proof; a γ-batch recheck attempt was reverted on them). Layering: the ENGINE owns the scope
|
|
40
40
|
* hard-wall (this WHERE); the SESSION acceptance arm belongs to the SERVING layer, which has a
|
|
41
41
|
* session-bound connection to adjudicate against (server 1.247's wire-face soft acceptance). This
|
|
@@ -48,13 +48,13 @@ export interface WorkflowJournalStore {
|
|
|
48
48
|
/** Record one agent's result under `(runId, scope)`. MUST be idempotent per `(runId, ordinal)` — a resumed run
|
|
49
49
|
* re-appends the cached results of its replayed prefix, so a second append for the same ordinal overwrites. */
|
|
50
50
|
append(runId: string, scope: string, entry: WorkflowJournalEntry): Promise<void>;
|
|
51
|
-
/**
|
|
51
|
+
/** (CC diagnostics parity, additive): a HUMAN/MODEL-readable coordinate for this run's journal —
|
|
52
52
|
* the file store returns the on-disk jsonl path (CC "Read journal.jsonl" local form); a service store
|
|
53
53
|
* returns its API route (cloud form). `undefined`/absent ⇒ the completion notification's diagnostics
|
|
54
54
|
* line teaches only the TaskOutput route (which is always live). Engine-facing string, never parsed. */
|
|
55
55
|
locator?(runId: string, scope: string): string | undefined;
|
|
56
56
|
/**
|
|
57
|
-
* RB-242 (
|
|
57
|
+
* RB-242 (ruled 2026-07-30) — ADMISSION for a resume, so two concurrent
|
|
58
58
|
* `resumeFromRunId` legs off ONE source run cannot fork its execution.
|
|
59
59
|
*
|
|
60
60
|
* Why a store seam at all: the engine's own mutex is in-process only (`startWorkflow` refuses a duplicate
|
|
@@ -65,7 +65,7 @@ export interface WorkflowJournalStore {
|
|
|
65
65
|
* shared durable layer, i.e. here.
|
|
66
66
|
*
|
|
67
67
|
* OPTIONAL, and absence is a first-class state: a store that does NOT implement this has NO STORE-LEVEL lease
|
|
68
|
-
* semantics. RB-367 (
|
|
68
|
+
* semantics. RB-367 (dual-process probe): a store without the hook is no longer completely
|
|
69
69
|
* unguarded, though — `runWorkflow`'s engine falls back to a process-local admission table for exactly this
|
|
70
70
|
* shape, so a same-process double `resumeFromRunId` off one source is still refused even against a store
|
|
71
71
|
* that never implements this member. That fallback cannot see a SECOND process, which is the one thing a
|
|
@@ -83,13 +83,13 @@ export interface WorkflowJournalStore {
|
|
|
83
83
|
* and is charset-clamped before it lands in a message.
|
|
84
84
|
* - IDEMPOTENT for the same holder: a re-claim by the SAME `newRunId` on a claim it already holds MUST be
|
|
85
85
|
* granted (a retry must not deadlock a run against itself).
|
|
86
|
-
* - `scope` is the journal scope passed through VERBATIM
|
|
86
|
+
* - `scope` is the journal scope passed through VERBATIM. A claim is keyed by `(sourceRunId, scope)`,
|
|
87
87
|
* NOT by `sourceRunId` alone: a cross-scope caller already resolves to an EMPTY journal (the CORE-9 wall
|
|
88
88
|
* above) so it cannot fork anything, and letting it take a global claim would hand any tenant a
|
|
89
89
|
* denial-of-resume lever over another's runs.
|
|
90
90
|
* - THROWING is a store failure, not a refusal — it propagates and fails the resume. Return `{granted:false}`
|
|
91
91
|
* to refuse.
|
|
92
|
-
* - A GRANT MEANS POSSESSION (RB-356
|
|
92
|
+
* - A GRANT MEANS POSSESSION (RB-356①). `granted: true` may only be returned once
|
|
93
93
|
* the claim is RECORDED where every other contender will see it; a store that cannot tell whether it holds
|
|
94
94
|
* the claim must refuse, with `holder` omitted if it cannot attribute the winner. The asymmetry is the
|
|
95
95
|
* reason: an unearned refusal fails one resume loudly and is recoverable, an unearned grant forks a run
|
|
@@ -101,7 +101,7 @@ export interface WorkflowJournalStore {
|
|
|
101
101
|
* "an incomplete record is dead, take it over" is only safe if an in-flight acquisition can never look
|
|
102
102
|
* incomplete.
|
|
103
103
|
*
|
|
104
|
-
* TWO INVALIDATION DOMAINS, each covering what the other cannot
|
|
104
|
+
* TWO INVALIDATION DOMAINS, each covering what the other cannot:
|
|
105
105
|
* 1. ENGINE release — the normal path, prompt, covers every terminal outcome of a live engine.
|
|
106
106
|
* 2. STORE TTL — the backstop for an engine that DIED holding a claim (crash/kill/replica loss): it never
|
|
107
107
|
* reaches its `finally`, so only a store-side expiry can ever free that row. Server's SQL twins land this
|
|
@@ -113,7 +113,7 @@ export interface WorkflowJournalStore {
|
|
|
113
113
|
holder?: string;
|
|
114
114
|
}>;
|
|
115
115
|
/**
|
|
116
|
-
* RB-242
|
|
116
|
+
* RB-242 — release the claim {@link resumeClaim} granted to `newRunId` on `(sourceRunId, scope)`.
|
|
117
117
|
* Called by the engine at the resuming run's TERMINAL boundary (in a `finally`, so abort/error/abandon are
|
|
118
118
|
* covered), and ONLY when the matching claim was actually granted.
|
|
119
119
|
*
|
|
@@ -124,7 +124,7 @@ export interface WorkflowJournalStore {
|
|
|
124
124
|
* A throw here is swallowed by the engine — a release failure must never replace the run's real outcome, and
|
|
125
125
|
* the store's TTL is the standing backstop for the row it left behind.
|
|
126
126
|
*
|
|
127
|
-
* RB-355
|
|
127
|
+
* RB-355: the engine's terminal boundary now BOUNDS this call (and its wait on
|
|
128
128
|
* the {@link resumeClaim} verdict) by a timeout — a store that hangs would otherwise keep the run's `done`
|
|
129
129
|
* promise pending forever, after the outcome is already decided. A release that outlives that bound is
|
|
130
130
|
* treated exactly like one that throws: swallowed, with the TTL as the backstop. Implementations should not
|
|
@@ -139,18 +139,18 @@ export declare const MAX_JOURNAL_RESULT_BYTES: number;
|
|
|
139
139
|
/** True when a serialized journal result is too large to store (UTF-8 byte length over {@link MAX_JOURNAL_RESULT_BYTES}). */
|
|
140
140
|
export declare function oversizeJournalResult(serialized: string): boolean;
|
|
141
141
|
export declare function callKeyOrdinal(callKey: string): number;
|
|
142
|
-
/** RB-243
|
|
142
|
+
/** RB-243: the errorCode a journal OVERSIZE TOMBSTONE carries — the resume path recognizes it to
|
|
143
143
|
* say WHY an ordinal never replays. `failed` + this code lands on the T2A-4 no-replay arm, so replay
|
|
144
144
|
* behavior is identical to the entry simply being absent (the pre-tombstone shape). */
|
|
145
145
|
export declare const JOURNAL_OVERSIZE_ERROR_CODE = "workflow.journal_oversize";
|
|
146
|
-
/** RB-243
|
|
146
|
+
/** RB-243: mint the tiny FAILED entry the ENGINE journals in place of an oversize result. The
|
|
147
147
|
* tombstone is minted in the engine, NOT in a store — the stores' skip semantics are unchanged (the
|
|
148
148
|
* §4.1 backend-parity pin depends on that layering; a store-side tombstone would re-create the RB-168
|
|
149
149
|
* dialect divergence). Never copies `result.result`/`structuredOutput` (the oversize payload); keeps
|
|
150
150
|
* taskId/sessionId/stats so the journal read-face still shows the session handle and the paid spend. */
|
|
151
151
|
export declare function journalOversizeTombstone(result: TaskResult, bytes: number): TaskResult;
|
|
152
152
|
/**
|
|
153
|
-
* RB-367 (
|
|
153
|
+
* RB-367 (dual-process probe, core-side judgment) — the TTL a resume claim {@link
|
|
154
154
|
* InMemoryWorkflowJournalStore} grants survives WITHOUT an engine release: the backstop for an engine that
|
|
155
155
|
* abandoned a granted claim without ever reaching the terminal `finally` that releases it (a bug, not the
|
|
156
156
|
* normal path — the normal path releases promptly). Same VALUE as the file store's `RESUME_CLAIM_TTL_MS`
|
|
@@ -169,7 +169,7 @@ export declare const IN_MEMORY_RESUME_CLAIM_TTL_MS: number;
|
|
|
169
169
|
* store WITHOUT the seam — its own header said so). Left unimplemented, the DEFAULT deployment (no
|
|
170
170
|
* `journalStore` supplied, or this store supplied explicitly) had NO protection against two same-process
|
|
171
171
|
* `resumeFromRunId` calls off one source forking its execution — the class of bug RB-242 exists to close, and
|
|
172
|
-
* a
|
|
172
|
+
* a dual-process probe found it wide open on the default path while the file store's half already
|
|
173
173
|
* worked. A single-process store's promise is necessarily single-process: this implementation gives no
|
|
174
174
|
* cross-process guarantee (there is no shared medium to publish a claim on), so a multi-process deployment
|
|
175
175
|
* still needs a store that IS durable/shared (the file or SQL stores) for the seam to mean anything beyond
|
|
@@ -21,7 +21,7 @@ export declare function createWorkflowRun(over?: Partial<WorkflowRun>): Workflow
|
|
|
21
21
|
* runner). The DEFAULT runs the cases inline and sequentially (so `service` can call
|
|
22
22
|
* `await workflowRunStoreContract(make)` with no harness at all).
|
|
23
23
|
*
|
|
24
|
-
* ⚠️ Binding note
|
|
24
|
+
* ⚠️ Binding note: the cases are REGISTERED eagerly and awaited via `Promise.all` — an async
|
|
25
25
|
* `runAssertion` that schedules work concurrently will interleave cases. Bindings whose stores share state
|
|
26
26
|
* (e.g. SQL twins on one table) must CHAIN the assertions themselves (serialize inside `runAssertion`).
|
|
27
27
|
*/
|
|
@@ -56,7 +56,7 @@ export async function workflowRunStoreContract(make, runAssertion = defaultSeque
|
|
|
56
56
|
assert.equal((await store.get(r.id)).status, "completed");
|
|
57
57
|
assert.equal(await store.update("ghost", r.scope, createWorkflowRun({ id: "ghost" })), false);
|
|
58
58
|
});
|
|
59
|
-
run("the key id is authoritative — a payload with a mismatched id never poisons the projection
|
|
59
|
+
run("the key id is authoritative — a payload with a mismatched id never poisons the projection", async () => {
|
|
60
60
|
const store = make();
|
|
61
61
|
const r = createWorkflowRun({ id: "real", status: "running" });
|
|
62
62
|
await store.put("real", { ...r, id: "spoofed" });
|
|
@@ -7,7 +7,7 @@ import type { WorkflowRun, WorkflowRunStatus } from "../orchestration/workflow.j
|
|
|
7
7
|
*
|
|
8
8
|
* **Distinct from the four load-bearing durable seams** (session / checkpoint / memory / tool-result): those
|
|
9
9
|
* are the engine's suspend/resume命脉, so core ships PG adapters for them. A WorkflowRunStore is an
|
|
10
|
-
* **observation layer — opt-in, non-engine-critical** — so per design/97 §D.8 (
|
|
10
|
+
* **observation layer — opt-in, non-engine-critical** — so per design/97 §D.8 (2026-06-22 拍) core
|
|
11
11
|
* ships ONLY: this interface + {@link InMemoryWorkflowRunStore} (process-local / default / tests) +
|
|
12
12
|
* `FileWorkflowRunStore` (zero-dependency, TOC-local persistence — `src/stores/file/workflow-run-store.ts`).
|
|
13
13
|
* **The PG backend lives in service (TOB), implementing THIS interface** when it needs cross-replica
|
|
@@ -34,7 +34,7 @@ export interface WorkflowRunSummary {
|
|
|
34
34
|
id: string;
|
|
35
35
|
/** The tenant / grouping key this run lives in ({@link WorkflowRun.scope}). */
|
|
36
36
|
scope: string;
|
|
37
|
-
/**
|
|
37
|
+
/** The ORIGINATING session id ({@link WorkflowRun.originatingSessionId}),
|
|
38
38
|
* projected so a serving layer's LIST face can apply its session acceptance/filter arm without an
|
|
39
39
|
* N+1 `get` of the full run. Absent for a direct `runWorkflow` call / sessionless deployment. */
|
|
40
40
|
originatingSessionId?: string;
|
|
@@ -117,10 +117,10 @@ export interface WorkflowRunStore {
|
|
|
117
117
|
* core query. Newest first (`createdAt` DESC). `opts.status` filters to one lifecycle state; `opts.limit`
|
|
118
118
|
* caps the result count (applied AFTER the sort, so it keeps the newest N). An empty scope returns `[]`.
|
|
119
119
|
*/
|
|
120
|
-
/** `opts.session
|
|
120
|
+
/** `opts.session`: STORE-side push-down filter on
|
|
121
121
|
* `originatingSessionId` — strict equality, rows WITHOUT the field excluded (filter semantics,
|
|
122
122
|
* deliberately unlike the per-id acceptance arm's absent-pass). Applied BEFORE limit, so the
|
|
123
|
-
* serving layer's "this session's workflows" is FULL-history, not page-window (
|
|
123
|
+
* serving layer's "this session's workflows" is FULL-history, not page-window (cli note). */
|
|
124
124
|
listByScope(scope: string, opts?: WorkflowRunListByScopeOptions): Promise<WorkflowRunSummary[]>;
|
|
125
125
|
/**
|
|
126
126
|
* Retention sweep: delete OLD **terminal** runs in `scope` (a `running` run is NEVER deleted — design/97
|
|
@@ -26,7 +26,7 @@ export interface CompactionDetails {
|
|
|
26
26
|
*/
|
|
27
27
|
invokedSkills?: InvokedSkillRetention[];
|
|
28
28
|
/**
|
|
29
|
-
* RB-398-b
|
|
29
|
+
* RB-398-b①: CUMULATIVE count of transcript messages this compaction's summary stands in
|
|
30
30
|
* for (this range's folded messages + the previous compaction's carried count). WRITE-side
|
|
31
31
|
* accounting on purpose: deriving the count at render time from the branch walk broke the F3
|
|
32
32
|
* "bounded wake equals full wake" invariant (a floored storage cannot see below the floor, so the
|
|
@@ -52,7 +52,7 @@ export interface CompactionDetails {
|
|
|
52
52
|
*/
|
|
53
53
|
unsummarizedMessages?: number;
|
|
54
54
|
/**
|
|
55
|
-
* RB-398-c
|
|
55
|
+
* RB-398-c: `<persisted-output ref="…">` handles found in the COMPACTED range
|
|
56
56
|
* (merged over the previous compaction's retained set, oldest-first, capped at
|
|
57
57
|
* {@link PERSISTED_OUTPUT_REFS_MAX_ENTRIES} newest). The offloaded blobs outlive the preview that
|
|
58
58
|
* carried their only address — without this channel the handle survived only if the summarizer
|
|
@@ -62,7 +62,7 @@ export interface CompactionDetails {
|
|
|
62
62
|
*/
|
|
63
63
|
persistedOutputRefs?: string[];
|
|
64
64
|
/**
|
|
65
|
-
* RB-402
|
|
65
|
+
* RB-402: the activated deferred-tool names LIVE at the
|
|
66
66
|
* moment this compaction landed — the design/36 activation state whose transcript carriers
|
|
67
67
|
* (the ToolSearch toolCall parts, and since RB-431 the successful direct calls, that
|
|
68
68
|
* `extractDiscoveredToolNames` replays at every task boundary)
|
|
@@ -98,8 +98,8 @@ export declare function readElidedMessages(details: unknown): number | undefined
|
|
|
98
98
|
* {@link readElidedMessages} — a non-negative safe integer, else absent (pre-field sessions /
|
|
99
99
|
* foreign shapes ⇒ no uncovered-scale clause, byte-identical wrapper). */
|
|
100
100
|
export declare function readUnsummarizedMessages(details: unknown): number | undefined;
|
|
101
|
-
/** Defensive reader for persisted `CompactionDetails.activeTools` (RB-402
|
|
102
|
-
*
|
|
101
|
+
/** Defensive reader for persisted `CompactionDetails.activeTools` (RB-402):
|
|
102
|
+
* the ToolSearch activation snapshot each landed compaction restates. details is
|
|
103
103
|
* `unknown` on the wire — pre-field sessions and foreign shapes yield an empty list; non-string/
|
|
104
104
|
* empty members are dropped (the consumer additionally intersects with the current leg's deferred
|
|
105
105
|
* registry, so an unknown name is inert either way). */
|
|
@@ -14,7 +14,7 @@ export type KillProcessTreeOptions = {
|
|
|
14
14
|
* handle with `exitCode === null && signalCode === null`); the pid probe remains only an
|
|
15
15
|
* auxiliary check. Absent ⇒ the pre-existing pid-only behavior (callers without a process handle).
|
|
16
16
|
*
|
|
17
|
-
*
|
|
17
|
+
* (1.296.1) — `false` cancels the DIRECT-pid escalation (that is where pid-reuse risk
|
|
18
18
|
* lives), but on the group-kill lane it no longer cancels the GROUP leg: the anchor only knows
|
|
19
19
|
* the LEADER — a detached shell that honors SIGTERM and exits while its TERM-ignoring descendants
|
|
20
20
|
* (run89's build workers) keep the group alive. While ANY original member lives, POSIX reserves
|
|
@@ -6,12 +6,12 @@ import type { SchedulerCapability, ScheduledIntent, SchedulerContext, ScheduledT
|
|
|
6
6
|
import { SchedulerError } from "../../core/scheduler.js";
|
|
7
7
|
/** Convert user-facing timeout seconds into a positive, timer-safe millisecond delay. */
|
|
8
8
|
export declare function resolveExecTimeoutMs(timeoutSeconds: unknown): number | undefined;
|
|
9
|
-
/**
|
|
9
|
+
/** review finding (win32): `where bash.exe` can resolve to `System32\bash.exe` — the
|
|
10
10
|
* WSL LAUNCHER, not a native shell. Running it drops into a Linux subsystem where Windows cwd/paths
|
|
11
11
|
* do not exist; silently adopting it is exactly the "wrong shell, false green" failure D1 forbids.
|
|
12
12
|
* Filter it (and the WindowsApps alias) out of PATH discovery; Git-Bash candidates are tried first. */
|
|
13
13
|
export declare function isWslBashLauncher(p: string): boolean;
|
|
14
|
-
/** Shell discovery for the platform (
|
|
14
|
+
/** Shell discovery for the platform (ask ①: exported as the single SDK source so a host
|
|
15
15
|
* adapter does not mirror the platform logic). Explicit `customShellPath` wins (missing → err);
|
|
16
16
|
* win32 = Git-Bash discovery (ProgramFiles → PATH, WSL launcher filtered) with fail-loud
|
|
17
17
|
* `shell_unavailable` (never a silent cmd.exe fallback); POSIX = /bin/bash → PATH bash → sh. */
|
|
@@ -21,7 +21,7 @@ export declare function getShellConfig(customShellPath?: string): Promise<Result
|
|
|
21
21
|
}, ExecutionError>>;
|
|
22
22
|
/** test seam (mirrors the notice-seat announce reset): the once-per-process fallback latches. */
|
|
23
23
|
export declare function __resetSecretScrubAnnouncement(): void;
|
|
24
|
-
/** RB-235
|
|
24
|
+
/** RB-235: the spool-reclaim decision, extracted PURE so every rule is unit-pinnable.
|
|
25
25
|
* Both reclaim sites (foreground `reclaimSpool`, background `syncSpool`) route through this one
|
|
26
26
|
* function so they cannot drift apart.
|
|
27
27
|
*
|
|
@@ -65,7 +65,7 @@ export declare function decideSpoolReclaim(args: {
|
|
|
65
65
|
reclaim: true;
|
|
66
66
|
skippedBytes: number;
|
|
67
67
|
};
|
|
68
|
-
/** design/128 T1-1
|
|
68
|
+
/** design/128 T1-1: open the spool file pair ALL-OR-NOTHING — a failure opening the
|
|
69
69
|
* second file must close the first fd before rethrowing (the caller's catch only clears its references, so
|
|
70
70
|
* a half-open pair would leak fdOut for the env's lifetime). `wx` + 0600 (never follow / never reuse an
|
|
71
71
|
* existing path). Exported for direct fault-injection tests (pre-create a path → EEXIST). `a` (not
|
|
@@ -132,14 +132,14 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
|
|
|
132
132
|
abortSignal?: AbortSignal;
|
|
133
133
|
}): Promise<Result<string[], FileError>>;
|
|
134
134
|
readBinaryFile(path: string, abortSignal?: AbortSignal): Promise<Result<Uint8Array, FileError>>;
|
|
135
|
-
/** RB-221
|
|
135
|
+
/** RB-221: whole-file replace via same-directory staging + fsync + rename (CC 2.1.220 `Q5`,
|
|
136
136
|
* pretty220.js:60808). The former single-step `writeFile` was an in-place O_TRUNC: an abort mid-write
|
|
137
137
|
* (Esc during a large Write — ctx.signal reaches here directly), ENOSPC, or a crash left the target as
|
|
138
138
|
* a torn prefix of the NEW content with the original unrecoverable. Post-fix contract: the target is
|
|
139
139
|
* either fully old or fully new; `aborted` means it was never touched. Known semantic change (same as
|
|
140
140
|
* CC): rename breaks a hard link — the other link keeps the old content. */
|
|
141
141
|
writeFile(path: string, content: string | Uint8Array, abortSignal?: AbortSignal): Promise<Result<void, FileError>>;
|
|
142
|
-
/** RB-221
|
|
142
|
+
/** RB-221: the historical single-step in-place overwrite — kept for targets where
|
|
143
143
|
* staging+rename would change node identity (symlink chains, non-regular files) and as the
|
|
144
144
|
* CC-parity fallback for filesystems where the rename cannot work. NOT atomic by design. */
|
|
145
145
|
private writeFileInPlace;
|
|
@@ -180,11 +180,11 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
|
|
|
180
180
|
/** design/128 T1-1: incrementally read a retained shell's spool files into the in-memory tails, so
|
|
181
181
|
* pollBackground serves the same cursor semantics whether stdio came over pipes or spool files.
|
|
182
182
|
* Bounded single read per stream per poll (the tail keeps only its rolling window anyway).
|
|
183
|
-
*
|
|
183
|
+
* reads are positioned by spool.fileCursor (the FILE offset — rotation truncates
|
|
184
184
|
* the file), while poll slicing keeps using the logical stream totalBytes; the two advance in
|
|
185
185
|
* lockstep here but are NOT interchangeable after a rotation. */
|
|
186
186
|
private syncSpool;
|
|
187
|
-
/**
|
|
187
|
+
/** +: reclaim an EPHEMERAL spool (detach-adopted, or any non-retain bg
|
|
188
188
|
* spawn — the whole unix bg lane is spool-backed now) — fold the final residue into the tails,
|
|
189
189
|
* unlink both files, and drop the spool reference (later syncs become no-ops). Idempotent;
|
|
190
190
|
* never touches design/128 retain-lane spools (no `ephemeral` flag). A still-writing detached
|
|
@@ -2,7 +2,7 @@ import type { ActorAssertion, AssistantMessage, ImageContent, Model } from "../l
|
|
|
2
2
|
import type { AgentMessage, AgentTool, LoopMalformedToolUseRecovery, LoopThinkingOnlyRecovery, LoopTruncatedOutputRecovery, QueueMode, ThinkingLevel } from "../loop/types.js";
|
|
3
3
|
import { type EngineSegment } from "../../core/untrusted-text.js";
|
|
4
4
|
import type { AbortResult, AgentHarnessEvent, AgentHarnessEventResultMap, AgentHarnessOptions, AgentHarnessOwnEvent, AgentHarnessResources, AgentHarnessStreamOptions, ExecutionEnv, PromptTemplate, Skill } from "./types.js";
|
|
5
|
-
/** [c209-C]
|
|
5
|
+
/** [c209-C] 收口 C1/C2 — engine-provenance metadata a caller can stamp on the user message it
|
|
6
6
|
* mints (see the field docs on {@link UserMessage}). Threaded from `prompt`/`steer`/`followUp`/
|
|
7
7
|
* `nextTurn` options into the persisted message so derived views (auto-mode window, compaction
|
|
8
8
|
* serializer) work from METADATA, never from reminder-shape guessing. */
|
|
@@ -93,7 +93,7 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
93
93
|
* hand a queued frame to the model once the run is unwinding, and — crucially — none may SPLICE one
|
|
94
94
|
* out of the queue either (that would delete the terminal undrained account the abort path owes it). */
|
|
95
95
|
private aborting;
|
|
96
|
-
/** backlog #389 (
|
|
96
|
+
/** backlog #389 (HIGH-1) — frames a boundary has REMOVED from a queue but that
|
|
97
97
|
* have not yet entered the model's context.
|
|
98
98
|
*
|
|
99
99
|
* The abort latch alone leaves a real window: `drainQueuedMessages` splices first and then awaits
|
|
@@ -147,7 +147,7 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
147
147
|
* gated: its splice opens a NEW run (idle-park redelivery), and a halt belongs to the run that
|
|
148
148
|
* minted it. */
|
|
149
149
|
engineInjectionsHeld?: () => boolean;
|
|
150
|
-
/** RB-30
|
|
150
|
+
/** RB-30: shared recovery sweep — collects engine-note payloads from the given queues
|
|
151
151
|
* in DELIVERY order (steer before followUp, each queue forward — the live loop serves steering
|
|
152
152
|
* first, so the recovered redelivery must not present "later" frames ahead of "now/next"),
|
|
153
153
|
* removes those entries, and hands the payloads to the runner sink. Called from BOTH terminal
|
|
@@ -243,16 +243,16 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
|
|
|
243
243
|
prompt(text: string, options?: {
|
|
244
244
|
images?: ImageContent[];
|
|
245
245
|
} & UserMessageProvenance): Promise<AssistantMessage>;
|
|
246
|
-
/**
|
|
246
|
+
/** R2-③: an empty/whitespace-only injection with no images carries ZERO information — it
|
|
247
247
|
* must not mint a user frame (strict endpoints reject empty user content, and an empty follow-up would
|
|
248
248
|
* pointlessly extend the run by one turn). No-op, not a throw: injection callers are fire-and-
|
|
249
249
|
* forget lanes (wakeups, reminders) and a shell bug upstream must not crash the run. */
|
|
250
250
|
private static emptyInjection;
|
|
251
|
-
/** REF-B6 — the ONE injection enqueue behind steer
|
|
251
|
+
/** REF-B6 — the ONE injection enqueue behind steer/followUp/nextTurn: the R2-③ empty-injection
|
|
252
252
|
* short circuit, the user frame, the RB-30 engine-payload SIDECAR (a WeakMap entry, never a message field —
|
|
253
253
|
* pre-prompt exits recover these too), the queue push, and the broadcast. All three lanes ship in ONE
|
|
254
254
|
* `queue_update` event (see emitQueueUpdate), so they are one protocol contract and must stay one
|
|
255
|
-
* implementation:
|
|
255
|
+
* implementation: R2-③ and RB-30 each had to be patched in three places.
|
|
256
256
|
*
|
|
257
257
|
* The idle check is deliberately NOT here: its message differs per lane, and nextTurn() legitimately has
|
|
258
258
|
* none (queueing the NEXT prompt while idle is exactly what it is for). */
|
|
@@ -20,7 +20,7 @@ export declare function createCustomMessage(customType: string, content: string
|
|
|
20
20
|
* product, not authored content. */
|
|
21
21
|
export declare const NORMALIZED_CONTENT_PREFIX = "[invalid content block normalized to text]";
|
|
22
22
|
/**
|
|
23
|
-
* Fail-soft salvage for a possibly-contaminated LLM message (
|
|
23
|
+
* Fail-soft salvage for a possibly-contaminated LLM message (件b): any structurally-invalid
|
|
24
24
|
* `content` shape (bare object as the whole field, or a typeless/unknown-type block in the array) is
|
|
25
25
|
* normalized to a prefixed text block. Legal messages are returned BY REFERENCE, untouched. Shared by
|
|
26
26
|
* `convertToLlm` (provider leg) and `serializeConversation` (compaction leg) — one helper, two mouths.
|
|
@@ -226,7 +226,7 @@ export interface ExecutionEnvExecOptions {
|
|
|
226
226
|
/** Called with stderr chunks as they are produced. */
|
|
227
227
|
onStderr?: (chunk: string) => void;
|
|
228
228
|
/**
|
|
229
|
-
* VENDORED EDIT (design/116 detach,
|
|
229
|
+
* VENDORED EDIT (design/116 detach, [C]): when fired mid-run, an env that supports detach ADOPTS the
|
|
230
230
|
* running child as a background process (its handle never leaves the env) and settles the exec with a
|
|
231
231
|
* `detached` marker instead of killing it. Envs without detach support ignore this (the exec runs on).
|
|
232
232
|
*/
|
|
@@ -269,7 +269,7 @@ export interface FileSystem {
|
|
|
269
269
|
/** Read a binary file. */
|
|
270
270
|
readBinaryFile(path: string, abortSignal?: AbortSignal): Promise<Result<Uint8Array, FileError>>;
|
|
271
271
|
/** Create or overwrite a file, creating parent directories when supported. Implementation note
|
|
272
|
-
* (RB-221
|
|
272
|
+
* (RB-221): the Node env replaces the file as a WHOLE (same-directory staging + fsync +
|
|
273
273
|
* rename; `aborted` ⇒ target untouched), falling back to an in-place rewrite where rename cannot
|
|
274
274
|
* apply (cross-device, symlink chains, non-regular targets, read-only parent dir). Atomicity is an
|
|
275
275
|
* implementation quality, NOT an interface-level contract — a remote/transport env may only have a
|
|
@@ -455,7 +455,7 @@ export interface LeafEntry extends SessionTreeEntryBase {
|
|
|
455
455
|
targetId: string | null;
|
|
456
456
|
}
|
|
457
457
|
/**
|
|
458
|
-
* Prompt-epoch pin (
|
|
458
|
+
* Prompt-epoch pin (stage S3, prompt-assembly protocol §9.2) — a FIRST-CLASS typed entry (not a
|
|
459
459
|
* forgeable generic `custom` entry): which prompt-pack artifact this session is pinned to. Written
|
|
460
460
|
* at session start (before the first conversation entry) and on legacy migration; every compaction
|
|
461
461
|
* RESTATES the then-current descriptor inside its own `details.promptEpoch` (same-CAS atomicity,
|
|
@@ -482,7 +482,7 @@ export interface AnnouncedListingEntry extends SessionTreeEntryBase {
|
|
|
482
482
|
models?: string[];
|
|
483
483
|
}
|
|
484
484
|
/**
|
|
485
|
-
* REF-D3/D4 merge target: the active EnterWorktree session (M22 live-CC anchor
|
|
485
|
+
* REF-D3/D4 merge target: the active EnterWorktree session (M22 live-CC anchor —
|
|
486
486
|
* plain strings only, no closures, so it survives a durable suspend into `CheckpointState.activeWorktree`
|
|
487
487
|
* verbatim). Canonical definition — `tools/worktree.ts` (the tool pair that owns this durably) re-exports
|
|
488
488
|
* this type rather than declaring its own copy: the harness layer must never import FROM `tools/`
|
|
@@ -512,7 +512,7 @@ export interface WorkspaceState {
|
|
|
512
512
|
activeWorktree?: ActiveWorktreeSession;
|
|
513
513
|
}
|
|
514
514
|
/**
|
|
515
|
-
* design/155
|
|
515
|
+
* design/155: the session's WORKSPACE STATE at a task settle — the tracked logical cwd
|
|
516
516
|
* and the active EnterWorktree session. Ordinary continuation turns (a new task on the same
|
|
517
517
|
* `spec.sessionId`) have NO checkpoint seed, so without this entry both refs silently reset to the
|
|
518
518
|
* task root every turn (cd doesn't stick, ExitWorktree no-ops, the worktree leaks). Restore ladder
|
|
@@ -711,7 +711,7 @@ export interface SessionStorage<TMetadata extends SessionMetadata = SessionMetad
|
|
|
711
711
|
getPathToRoot(leafId: string | null): Promise<SessionTreeEntry[]>;
|
|
712
712
|
getEntries(): Promise<SessionTreeEntry[]>;
|
|
713
713
|
/**
|
|
714
|
-
*
|
|
714
|
+
* S3 / RB-14 seam (joint verdict): OPTIONAL epoch anchor for
|
|
715
715
|
* bounded-tail backends. A durable backend that loads only `firstKeptEntryId..leaf` cannot show
|
|
716
716
|
* the branch walk an epoch carrier when a rewind cuts BEFORE the latest compaction's restatement
|
|
717
717
|
* (window: firstKept ≤ cut < compactionEntry) — `Session.getPromptEpoch()` falls back to this
|
|
@@ -848,7 +848,7 @@ export interface SessionRepo<TMetadata extends SessionMetadata = SessionMetadata
|
|
|
848
848
|
delete(metadata: TMetadata): Promise<void>;
|
|
849
849
|
fork(source: TMetadata, options: SessionForkOptions & TCreateOptions): Promise<Session<TMetadata>>;
|
|
850
850
|
/**
|
|
851
|
-
* 2c session-sync
|
|
851
|
+
* 2c session-sync: the FULL durable entry log for `sessionId`, oldest-first, with
|
|
852
852
|
* `id`/`parentId` VERBATIM and BYPASSING any compaction floor — NOT `getEntries()`, which on a durable
|
|
853
853
|
* backend that woke with a bounded F3 window returns only the tail (silently truncating pre-floor history).
|
|
854
854
|
* Optional — a backend that supports cross-backend session export/migration implements it.
|
|
@@ -1114,7 +1114,7 @@ export interface AgentHarnessOptions<TSkill extends Skill = Skill, TPromptTempla
|
|
|
1114
1114
|
resources: AgentHarnessResources<TSkill, TPromptTemplate>;
|
|
1115
1115
|
}) => string | Promise<string>);
|
|
1116
1116
|
/**
|
|
1117
|
-
*
|
|
1117
|
+
* S4 (ADDITIVE): physical system blocks for block-aware Brains. Static per leg (same
|
|
1118
1118
|
* freeze semantics as a string `systemPrompt`). When present it MUST correspond to the same
|
|
1119
1119
|
* bytes as `systemPrompt` (the M13 projection duty is on the producer — prepare-task). Brains
|
|
1120
1120
|
* that ignore it read `systemPrompt` and lose nothing.
|
|
@@ -1158,13 +1158,13 @@ export interface AgentHarnessOptions<TSkill extends Skill = Skill, TPromptTempla
|
|
|
1158
1158
|
*/
|
|
1159
1159
|
abortResultDetails?: () => Record<string, unknown> | undefined;
|
|
1160
1160
|
/**
|
|
1161
|
-
*
|
|
1161
|
+
* C2: the loop's recovery/terminal trace sink, forwarded to `runAgentLoop`'s trace
|
|
1162
1162
|
* parameter (previously test-only — never passed in production, so the loop's six self-heal
|
|
1163
1163
|
* recoveries were invisible outside display:false nudge messages). Must not throw; hot path.
|
|
1164
1164
|
*/
|
|
1165
1165
|
loopTrace?: (step: import("../loop/agent-loop.js").LoopStep) => void;
|
|
1166
1166
|
/**
|
|
1167
|
-
* design/131 (
|
|
1167
|
+
* design/131 (拍): per-task resilience intent flags, forwarded to every provider
|
|
1168
1168
|
* call (`StreamOptions.resilience`) so the deployment's decorator stack (degrading / failover /
|
|
1169
1169
|
* breaker) can stand aside for this task. Absent ⇒ today's behavior.
|
|
1170
1170
|
*/
|