@sema-agent/core 5.47.0 → 5.48.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 +52 -0
- package/dist/agents/agent-transcript-tool.d.ts +4 -0
- package/dist/agents/agent-transcript-tool.js +10 -3
- package/dist/agents/send-message-tool.d.ts +43 -1
- package/dist/agents/send-message-tool.js +50 -11
- package/dist/agents/subagent.d.ts +18 -0
- package/dist/agents/subagent.js +102 -2
- package/dist/config/defaults.d.ts +20 -0
- package/dist/config/defaults.js +5 -0
- package/dist/core/background-agent-store.d.ts +1 -0
- package/dist/core/background-agent-store.js +13 -0
- package/dist/core/mcp.d.ts +6 -1
- package/dist/core/mcp.js +34 -7
- package/dist/core/reminder-disclosure.d.ts +90 -0
- package/dist/core/reminder-disclosure.js +64 -0
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +6 -0
- package/dist/core/runner/prepare-acquire-reconcile.js +1 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +4 -0
- package/dist/core/runner/prepare-hands-readface.js +1 -0
- package/dist/core/runner/prepare-task.d.ts +15 -0
- package/dist/core/runner/prepare-task.js +48 -30
- package/dist/core/runner/runtask.js +3 -1
- package/dist/core/session-store.d.ts +59 -1
- package/dist/core/session-store.js +82 -14
- package/dist/core/session.d.ts +83 -1
- package/dist/core/task-registry-agent.d.ts +28 -0
- package/dist/core/task-registry-agent.js +63 -2
- package/dist/core/task-registry.d.ts +21 -0
- package/dist/core/task-registry.js +4 -1
- package/dist/core/types.d.ts +60 -0
- package/dist/core/untrusted-text.d.ts +63 -0
- package/dist/core/untrusted-text.js +48 -0
- package/dist/core/wiring-manifest.d.ts +35 -0
- package/dist/core/wiring-manifest.js +21 -1
- package/dist/engine/harness/types.d.ts +36 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/internal/harness-types.d.ts +1 -0
- package/dist/stores/file/index.d.ts +19 -3
- package/dist/stores/file/index.js +24 -1
- package/dist/stores/file/session-store.d.ts +18 -4
- package/dist/stores/file/session-store.js +73 -12
- package/dist/tools/fs/fs-pdf.d.ts +12 -1
- package/dist/tools/fs/fs-pdf.js +17 -3
- package/dist/tools/fs/fs-read.d.ts +2 -1
- package/dist/tools/fs/fs-read.js +33 -5
- package/dist/tools/fs/fs-shared.d.ts +6 -2
- package/dist/tools/fs/index.d.ts +7 -0
- package/dist/tools/fs/index.js +1 -1
- package/dist/tools/web.js +21 -2
- package/package.json +3 -2
- package/test/export-surface.snapshot.json +15 -1
|
@@ -16,6 +16,69 @@
|
|
|
16
16
|
* own (instructions and data share one channel). The real boundary is decorrelation + reading the objective
|
|
17
17
|
* artifact (the diff / working tree) rather than the worker's self-report (design/53 §3, design/54 §3).
|
|
18
18
|
*/
|
|
19
|
+
/** design/319 (B ticket) — what one reminder-shaped scan of an external projection found. */
|
|
20
|
+
export interface ReminderShapedScan {
|
|
21
|
+
/** ≥1 reminder-shaped tag (open or close; attribute/case/whitespace tolerant) is present. */
|
|
22
|
+
hit: boolean;
|
|
23
|
+
/** Some reminder-shaped TAG's own bytes contain the session's exact mark value — the strongest
|
|
24
|
+
* verdict (a full scan decides this, never the first match: a bare decoy ahead of a marked
|
|
25
|
+
* forgery must still be judged marked). `false` whenever `mark` is `undefined`. */
|
|
26
|
+
hadCurrentMark: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* design/319 (B ticket) — the ONE detection predicate for reminder-shaped text in EXTERNAL data
|
|
30
|
+
* (the Read/notebook/PDF/MCP disclosure trailers and the MCP/web exact-mark defuse all judge with
|
|
31
|
+
* THIS scan). It reads the same {@link SYSTEM_REMINDER} regex the neutralizer rewrites with, so
|
|
32
|
+
* "what gets defused on contained lanes" and "what gets disclosed on verbatim lanes" can never
|
|
33
|
+
* drift apart — do not hand-copy the tag pattern anywhere else (same single-source discipline as
|
|
34
|
+
* {@link defuseFenceMarkers}). Attribute-tolerant / case-insensitive / tag-internal whitespace
|
|
35
|
+
* tolerant by construction; a tag the regex does not recognize is NOT a hit (the residual gap
|
|
36
|
+
* between this grammar and what a model might read as authority is an accepted, documented
|
|
37
|
+
* residual — same class as the Unicode-lookalike note on {@link defuseFenceMarkers}).
|
|
38
|
+
*
|
|
39
|
+
* The scan is read-only over the FINALIZED projection (post concatenation/truncation, pre any
|
|
40
|
+
* trusted tail) — callers must scan BEFORE any byte-changing transform (design/319 §3e four-step
|
|
41
|
+
* order): a defused/neutralized projection no longer carries the exact mark, so scanning after
|
|
42
|
+
* would misreport a marked forgery as the bare form (the lying-disclosure shape).
|
|
43
|
+
*/
|
|
44
|
+
export declare function scanReminderShaped(text: string, mark: string | undefined): ReminderShapedScan;
|
|
45
|
+
/**
|
|
46
|
+
* design/319 §3b (B ticket) — EXACT-MARK defuse for the MCP-success/web outlets: insert a ZWSP
|
|
47
|
+
* inside every occurrence of the session's exact mark value so the bytes no longer spell the
|
|
48
|
+
* current mark. This is the ONE sanctioned byte change on those lanes (their zero-byte-change
|
|
49
|
+
* invariant's single exception): a server/page legitimately producing the 22-char session mark has
|
|
50
|
+
* definitionally zero probability — the value lives only in this session's prompt and checkpoint —
|
|
51
|
+
* so an occurrence is either a forgery or a leak echo, and defusing it turns a silent authority
|
|
52
|
+
* forgery into a visible mismatch (the accepted failure direction; a legitimate round-trip echo of
|
|
53
|
+
* a leaked mark defuses too, and the next hop then fails loudly instead of re-arming the forgery).
|
|
54
|
+
* NEVER applied on Read/Bash/Grep (the strong quote-back lanes stay verbatim — ruled, observation
|
|
55
|
+
* seat only). Idempotent: the rewritten text no longer contains the exact mark (ZWSP is not a
|
|
56
|
+
* base64url character, so the insertion can also never synthesize a new occurrence).
|
|
57
|
+
*/
|
|
58
|
+
export declare function defuseExactMark(text: string, mark: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* design/319 §3b — the SEGMENT form of {@link defuseExactMark} (adversarial round: a server can
|
|
61
|
+
* split the mark across adjacent MCP text blocks; the block seam is invisible in the model-facing
|
|
62
|
+
* concatenation, so a per-segment defuse would be a bypass). Judged over the JOINED projection and
|
|
63
|
+
* the ZWSP insertion mapped back into the owning segment, so the post-defuse concatenation NEVER
|
|
64
|
+
* contains the exact mark — including occurrences that straddle one or more seams (one ZWSP inside
|
|
65
|
+
* the occurrence's span breaks it wherever the split fell). Returns the same array (`changed:
|
|
66
|
+
* false`) when the joined projection has no occurrence; otherwise fresh segment strings whose
|
|
67
|
+
* concatenation equals the single-string form's output byte for byte (it IS the single-string
|
|
68
|
+
* form's implementation).
|
|
69
|
+
*
|
|
70
|
+
* OVERLAP-AWARE (adversarial round 2): a BORDERED mark (first character = last character — ~1/64
|
|
71
|
+
* random mints) admits overlapping occurrences (`mark + mark.slice(1)` carries two, one starting on
|
|
72
|
+
* the other's final character), so enumeration advances ONE character per match, never by the mark
|
|
73
|
+
* length — a skip-by-length walk defused the first and left the second exact while the trailer
|
|
74
|
+
* claimed neutralization. Every enumerated occurrence gets a ZWSP inside its own span; ZWSP is not
|
|
75
|
+
* a base64url character, so insertions can never synthesize a new occurrence and the result is
|
|
76
|
+
* idempotent (no exact mark survives ⇒ a second pass is byte-identical).
|
|
77
|
+
*/
|
|
78
|
+
export declare function defuseExactMarkInSegments(segments: readonly string[], mark: string): {
|
|
79
|
+
segments: string[];
|
|
80
|
+
changed: boolean;
|
|
81
|
+
};
|
|
19
82
|
/**
|
|
20
83
|
* Neutralize structural break-out sequences in UNTRUSTED text so it can't escape its framing into
|
|
21
84
|
* model-facing instructions. Always neutralizes `<system-reminder>` / `</system-reminder>` (the codebase's
|
|
@@ -12,6 +12,54 @@ function breakoutRe(extraTags) {
|
|
|
12
12
|
}
|
|
13
13
|
return re;
|
|
14
14
|
}
|
|
15
|
+
export function scanReminderShaped(text, mark) {
|
|
16
|
+
let hit = false;
|
|
17
|
+
let hadCurrentMark = false;
|
|
18
|
+
for (const m of text.matchAll(SYSTEM_REMINDER)) {
|
|
19
|
+
hit = true;
|
|
20
|
+
if (mark !== undefined && m[0].includes(mark)) {
|
|
21
|
+
hadCurrentMark = true;
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
if (mark === undefined)
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
return { hit, hadCurrentMark };
|
|
28
|
+
}
|
|
29
|
+
export function defuseExactMark(text, mark) {
|
|
30
|
+
return defuseExactMarkInSegments([text], mark).segments[0];
|
|
31
|
+
}
|
|
32
|
+
export function defuseExactMarkInSegments(segments, mark) {
|
|
33
|
+
const joined = segments.join("");
|
|
34
|
+
if (mark.length === 0 || !joined.includes(mark))
|
|
35
|
+
return { segments: [...segments], changed: false };
|
|
36
|
+
const positions = [];
|
|
37
|
+
for (let at = joined.indexOf(mark); at !== -1; at = joined.indexOf(mark, at + 1))
|
|
38
|
+
positions.push(at + 1);
|
|
39
|
+
const out = [];
|
|
40
|
+
let start = 0;
|
|
41
|
+
let pi = 0;
|
|
42
|
+
for (const seg of segments) {
|
|
43
|
+
const end = start + seg.length;
|
|
44
|
+
if (pi >= positions.length || positions[pi] > end) {
|
|
45
|
+
out.push(seg);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
const parts = [];
|
|
49
|
+
let prev = 0;
|
|
50
|
+
while (pi < positions.length && positions[pi] > start && positions[pi] <= end) {
|
|
51
|
+
const local = positions[pi] - start;
|
|
52
|
+
parts.push(seg.slice(prev, local), ZWSP);
|
|
53
|
+
prev = local;
|
|
54
|
+
pi++;
|
|
55
|
+
}
|
|
56
|
+
parts.push(seg.slice(prev));
|
|
57
|
+
out.push(parts.join(""));
|
|
58
|
+
}
|
|
59
|
+
start = end;
|
|
60
|
+
}
|
|
61
|
+
return { segments: out, changed: true };
|
|
62
|
+
}
|
|
15
63
|
export function sanitizeUntrustedText(text, extraTags = []) {
|
|
16
64
|
return text.replace(breakoutRe(extraTags), (m) => m.replace("<", "<" + ZWSP));
|
|
17
65
|
}
|
|
@@ -126,9 +126,18 @@ export interface WiringManifest {
|
|
|
126
126
|
session: {
|
|
127
127
|
store: ManifestDurability;
|
|
128
128
|
};
|
|
129
|
+
/** `subagentTranscripts` — subagent transcript persistence: the deployment-level delegation-
|
|
130
|
+
* transcript durability TIER, a pure declaration read ({@link resolveSubagentTranscriptTier}):
|
|
131
|
+
* `none` = no agent-row store (pre-151 in-memory lifecycle); `rows` = rows + terminal snapshots
|
|
132
|
+
* survive a restart, transcripts follow the session store's fate; `full` = the C18 promise —
|
|
133
|
+
* a completed/failed/killed(non-user) subagent minted through the deps-visible assembly is
|
|
134
|
+
* continuable across a process restart. A statement about the DEPS-VISIBLE assembly only: a
|
|
135
|
+
* caller-mounted Agent tool over its own runner is outside this manifest's sight (per-read
|
|
136
|
+
* honest degrade + the integrity notice own that case, never a fabricated tier). */
|
|
129
137
|
fleet: {
|
|
130
138
|
backgroundAgentStore: boolean;
|
|
131
139
|
hostChildEventSink: boolean;
|
|
140
|
+
subagentTranscripts: SubagentTranscriptTier;
|
|
132
141
|
};
|
|
133
142
|
/** design/179 — the persisted allow-rule seam. The ONE loosening seam in the assembly, so its presence
|
|
134
143
|
* is a fact an operator has to be able to read off the manifest rather than infer. `false` on a
|
|
@@ -201,6 +210,11 @@ export interface WiringFacts {
|
|
|
201
210
|
checkpointDurability?: StoreDurability;
|
|
202
211
|
sessionDurability: StoreDurability;
|
|
203
212
|
backgroundAgentStoreWired: boolean;
|
|
213
|
+
/** Subagent transcript persistence — the declared delegation-transcript tier (see
|
|
214
|
+
* {@link WiringManifest.fleet}). Optional for external `deriveWiringManifest` callers: absent
|
|
215
|
+
* derives fail-closed from `backgroundAgentStoreWired` alone (`rows`/`none` — under-promise,
|
|
216
|
+
* never `full`); the engine's own halves always pass the resolved value. */
|
|
217
|
+
subagentTranscriptTier?: SubagentTranscriptTier;
|
|
204
218
|
/** design/179 — a persisted allow-rule store provider is wired. */
|
|
205
219
|
permissionRuleStoreWired: boolean;
|
|
206
220
|
/** design/182 §9 — the deployment declared that it drives cloud sync for that store. */
|
|
@@ -227,6 +241,27 @@ export type StaticWiringSpec = Pick<TaskSpec, "onAsk" | "onQuestion" | "checkpoi
|
|
|
227
241
|
export declare function resolveDeclaredDurability(store: {
|
|
228
242
|
readonly durability?: StoreDurability;
|
|
229
243
|
} | undefined, storeName: string): StoreDurability;
|
|
244
|
+
/** Subagent transcript persistence — the deployment-level delegation-transcript durability tier
|
|
245
|
+
* (see {@link WiringManifest.fleet}). */
|
|
246
|
+
export type SubagentTranscriptTier = "none" | "rows" | "full";
|
|
247
|
+
/**
|
|
248
|
+
* Subagent transcript persistence — the ONE deployment-level tier derivation (pure declaration
|
|
249
|
+
* read, no probing, no class-name sniffing — the wiring-manifest posture): `none` without an
|
|
250
|
+
* agent-row store; with one, `full` iff the session store DECLARES its subagent placement
|
|
251
|
+
* partition durable, else `rows`. A junk placement declaration is refused loudly
|
|
252
|
+
* (`config.store_durability_invalid` — the resolveDeclaredDurability rule: an unparseable
|
|
253
|
+
* declaration silently folded to either arm would make the manifest lie in whichever direction the
|
|
254
|
+
* fold picked). This is the DEPLOYMENT-level judgment only; the per-handle "did this row's
|
|
255
|
+
* transcript actually land" question belongs to `durableAgentRowProbe` (the S1b release-flip gate)
|
|
256
|
+
* — two different questions, deliberately two named faces (do not merge them back into one).
|
|
257
|
+
*/
|
|
258
|
+
export declare function resolveSubagentTranscriptTier(agentStoreWired: boolean, sessionStore: {
|
|
259
|
+
readonly placements?: {
|
|
260
|
+
subagent?: {
|
|
261
|
+
durability: StoreDurability;
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
} | undefined): SubagentTranscriptTier;
|
|
230
265
|
/**
|
|
231
266
|
* The ONE `ask.effective` derivation (design/173 codex 5) — shared by the effective manifest AND
|
|
232
267
|
* the posture door (`config.interaction_posture`), so "what does the door require" and "what does
|
|
@@ -14,6 +14,21 @@ export function resolveDeclaredDurability(store, storeName) {
|
|
|
14
14
|
throw e;
|
|
15
15
|
}
|
|
16
16
|
const manifestDurabilityOf = (d) => (d === "durable" ? "declared_durable" : "process_local");
|
|
17
|
+
export function resolveSubagentTranscriptTier(agentStoreWired, sessionStore) {
|
|
18
|
+
if (!agentStoreWired)
|
|
19
|
+
return "none";
|
|
20
|
+
const declared = sessionStore?.placements?.subagent?.durability;
|
|
21
|
+
if (declared === undefined)
|
|
22
|
+
return "rows";
|
|
23
|
+
if (declared === "durable")
|
|
24
|
+
return "full";
|
|
25
|
+
if (declared === "process-local")
|
|
26
|
+
return "rows";
|
|
27
|
+
const e = new Error(`sessionStore.placements.subagent.durability declares ${JSON.stringify(declared)} — not a recognized ` +
|
|
28
|
+
`StoreDurability ("durable" | "process-local"). Fix the declaration; an unparseable durability cannot be folded to either arm.`);
|
|
29
|
+
e.code = "config.store_durability_invalid";
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
17
32
|
export function deriveAskEffective(form, parkEffective) {
|
|
18
33
|
switch (form) {
|
|
19
34
|
case "callback":
|
|
@@ -85,7 +100,11 @@ export function deriveWiringManifest(facts) {
|
|
|
85
100
|
elicit: { seamWired: facts.elicitSeamWired, serversOptedIn: facts.elicitServersOptedIn },
|
|
86
101
|
parkLane,
|
|
87
102
|
session: { store: manifestDurabilityOf(facts.sessionDurability) },
|
|
88
|
-
fleet: {
|
|
103
|
+
fleet: {
|
|
104
|
+
backgroundAgentStore: facts.backgroundAgentStoreWired,
|
|
105
|
+
hostChildEventSink: facts.hostChildEventSinkWired,
|
|
106
|
+
subagentTranscripts: facts.subagentTranscriptTier ?? (facts.backgroundAgentStoreWired ? "rows" : "none"),
|
|
107
|
+
},
|
|
89
108
|
permissionRules: {
|
|
90
109
|
storeWired: facts.permissionRuleStoreWired,
|
|
91
110
|
syncWired: facts.permissionRuleSyncWired,
|
|
@@ -182,6 +201,7 @@ export function describeStaticWiring(deps, spec = {}) {
|
|
|
182
201
|
...(capable ? { checkpointDurability: resolveDeclaredDurability(checkpointStore, "checkpointStore") } : {}),
|
|
183
202
|
sessionDurability: resolveDeclaredDurability(deps.sessionStore, "sessionStore"),
|
|
184
203
|
backgroundAgentStoreWired: deps.backgroundAgentStore !== undefined,
|
|
204
|
+
subagentTranscriptTier: resolveSubagentTranscriptTier(deps.backgroundAgentStore !== undefined, deps.sessionStore),
|
|
185
205
|
permissionRuleStoreWired: deps.permissionRuleStore !== undefined,
|
|
186
206
|
permissionRuleSyncWired: deps.permissionRuleSyncWired === true,
|
|
187
207
|
permissionRuleOrgGoverned: deps.permissionRuleOrg !== undefined,
|
|
@@ -157,7 +157,7 @@ export declare class CompactionError extends Error {
|
|
|
157
157
|
code: CompactionErrorCode;
|
|
158
158
|
constructor(code: CompactionErrorCode, message: string, cause?: Error);
|
|
159
159
|
}
|
|
160
|
-
export type SessionErrorCode = "not_found" | "invalid_session" | "invalid_entry" | "invalid_fork_target" | "storage" | "conflict" | "unknown";
|
|
160
|
+
export type SessionErrorCode = "not_found" | "invalid_session" | "invalid_entry" | "invalid_fork_target" | "storage" | "conflict" | "placement_refused" | "unknown";
|
|
161
161
|
/** Error thrown by session storage, repositories, and session tree operations. */
|
|
162
162
|
export declare class SessionError extends Error {
|
|
163
163
|
/** Session subsystem error code. */
|
|
@@ -170,6 +170,30 @@ export declare class AgentHarnessError extends Error {
|
|
|
170
170
|
code: AgentHarnessErrorCode;
|
|
171
171
|
constructor(code: AgentHarnessErrorCode, message: string, cause?: Error);
|
|
172
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* The PERSISTED placement tuple of a session created into a placement partition (subagent
|
|
175
|
+
* transcript persistence — the durable half of the delegation continuation contract). Written ONCE
|
|
176
|
+
* at creation (first-write immutable: a later acquire never rewrites it) and carried on
|
|
177
|
+
* {@link SessionMetadata.placement}. The FULL tuple is persisted, not just a tag: `scope`+`handle`
|
|
178
|
+
* are the row-store join key the retention orchestration needs after a restart (a bare label could
|
|
179
|
+
* not tell "no row" from "a row in another tenant"), and `placedAt` anchors the age-based GC arm.
|
|
180
|
+
* A tuple missing either join half is treated by consumers as INCOMPLETE (fail-closed: never
|
|
181
|
+
* age-reaped, reported as such by placed listings).
|
|
182
|
+
*/
|
|
183
|
+
export interface SessionPlacementRecord {
|
|
184
|
+
/** The one placement kind this contract defines today. */
|
|
185
|
+
kind: "subagent";
|
|
186
|
+
/** Tenant scope of the owning durable agent row (row-store join key half 1). */
|
|
187
|
+
scope?: string;
|
|
188
|
+
/** The spawning host session (partition/retrieval metadata — authorization stays on the row predicate). */
|
|
189
|
+
parentSessionId?: string;
|
|
190
|
+
/** The delegation tree's root host session (fixed point; enumeration anchor). */
|
|
191
|
+
rootSessionId?: string;
|
|
192
|
+
/** The durable agent row key (`a…` handle; row-store join key half 2). */
|
|
193
|
+
handle?: string;
|
|
194
|
+
/** Epoch ms the placement was created (stamped by the store at creation). */
|
|
195
|
+
placedAt: number;
|
|
196
|
+
}
|
|
173
197
|
/** Metadata for one filesystem object in a {@link FileSystem}. */
|
|
174
198
|
export interface FileInfo {
|
|
175
199
|
/** Basename of {@link path}. */
|
|
@@ -644,6 +668,10 @@ export interface SessionMetadata {
|
|
|
644
668
|
* fork lineage (e.g. reap forks whose parent is gone/expired). Absent on a non-forked session and on
|
|
645
669
|
* forked sessions persisted before this field shipped. */
|
|
646
670
|
forkedFrom?: string;
|
|
671
|
+
/** Subagent transcript persistence — the placement tuple this session was CREATED into (see
|
|
672
|
+
* {@link SessionPlacementRecord}). Absent on every ordinary (host-lane) session; a repo that does
|
|
673
|
+
* not understand placement never surfaces it (additive, old readers tolerate). */
|
|
674
|
+
placement?: SessionPlacementRecord;
|
|
647
675
|
}
|
|
648
676
|
export interface JsonlSessionMetadata extends SessionMetadata {
|
|
649
677
|
cwd: string;
|
|
@@ -796,6 +824,13 @@ export interface Session<TMetadata extends SessionMetadata = SessionMetadata> {
|
|
|
796
824
|
}
|
|
797
825
|
export interface SessionCreateOptions {
|
|
798
826
|
id?: string;
|
|
827
|
+
/** Subagent transcript persistence — create this session INTO a placement partition. The repo
|
|
828
|
+
* stamps `placedAt` and persists the tuple on its meta record (first-write immutable). A repo
|
|
829
|
+
* that does not understand placement IGNORES this key (legal degrade — the session is then an
|
|
830
|
+
* ordinary one; the store-level `placements` declaration is what promises understanding). */
|
|
831
|
+
placement?: Omit<SessionPlacementRecord, "placedAt"> & {
|
|
832
|
+
placedAt?: number;
|
|
833
|
+
};
|
|
799
834
|
}
|
|
800
835
|
export interface SessionForkOptions {
|
|
801
836
|
entryId?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -64,7 +64,7 @@ export { GOVERNANCE_CODES, governanceRetryClass, type GovernanceCode, type Gover
|
|
|
64
64
|
export { NOTICE_AUDIENCE, noticeAudienceOf } from "./core/governance-codes.js";
|
|
65
65
|
export { TtlSessionStore, type TtlSessionStoreOptions, type EvictPolicy } from "./core/session-store.js";
|
|
66
66
|
export { reconcileInterruptedSession, findOrphanToolCalls, type OrphanToolCall, type ReconcileReport, } from "./core/session-reconcile.js";
|
|
67
|
-
export { StoredSession, InMemorySessionRepo, InMemorySessionStorage, BaseSessionStorage, leafIdAfterEntry, validateEntriesForImport, StreamingImportValidator, boundedTail, SessionError, isSessionConflict, hasSessionFork, uuidv7, type Session, type SessionStore, type AcquiredSession, type SessionStoreSummary, type SessionStorage, type SessionRepo, type SessionMetadata, type SessionTreeEntry, type SessionWriteOptions, } from "./core/session.js";
|
|
67
|
+
export { StoredSession, InMemorySessionRepo, InMemorySessionStorage, BaseSessionStorage, leafIdAfterEntry, validateEntriesForImport, StreamingImportValidator, boundedTail, SessionError, isSessionConflict, hasSessionFork, uuidv7, type Session, type SessionStore, type AcquiredSession, type SessionStoreSummary, type SessionStorage, type SessionRepo, type SessionMetadata, type SessionTreeEntry, type SessionWriteOptions, type SessionPlacement, type SessionPlacementRecord, type PlacedSessionRow, } from "./core/session.js";
|
|
68
68
|
export { warmResume } from "./core/warm-resume.js";
|
|
69
69
|
export { StubExecutionEnv } from "./core/stub-env.js";
|
|
70
70
|
export { NodeExecutionEnv, FileError, ExecutionError } from "./internal/harness.js";
|
|
@@ -111,7 +111,7 @@ export { createFsWriteGatePolicy, type FsWriteGatePolicyOptions } from "./core/f
|
|
|
111
111
|
export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
|
|
112
112
|
export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
|
|
113
113
|
export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, } from "./core/task-notification.js";
|
|
114
|
-
export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, type WiringManifest, type WiringFacts, type WiringLegKind, type AskSeamForm, type AskEffective, type QuestionChannelState, type SeamProvenance, type ParkLaneReason, type ManifestDurability, type StaticWiringDeps, type StaticWiringSpec, } from "./core/wiring-manifest.js";
|
|
114
|
+
export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, type SubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, type WiringManifest, type WiringFacts, type WiringLegKind, type AskSeamForm, type AskEffective, type QuestionChannelState, type SeamProvenance, type ParkLaneReason, type ManifestDurability, type StaticWiringDeps, type StaticWiringSpec, } from "./core/wiring-manifest.js";
|
|
115
115
|
export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, type ParkSelfCheckResult, type ParkProbeFinding, type ParkProbeFindingCode, } from "./core/park-selfcheck.js";
|
|
116
116
|
export { type StoreDurability } from "./core/checkpoint-store.js";
|
|
117
117
|
export { type StoreFidelity } from "./core/checkpoint-store.js";
|
|
@@ -234,10 +234,11 @@ export { summarizeRedactions } from "./core/untrusted-egress.js";
|
|
|
234
234
|
export { MemoryRosterStore, FileRosterStore, type RosterStore, type RosterEntry, type RosterAccess, type RosterGcOptions } from "./agents/roster-store.js";
|
|
235
235
|
export { CONFIG_CATALOG_VERSION, describeConfigCatalog, resolveEffectiveConfig, type ConfigKnob, type ConfigOverrideDeclaration, type ConfigProvenance, type EffectiveConfigField, } from "./config/catalog.js";
|
|
236
236
|
export { normalizeAgentName } from "./core/task-registry.js";
|
|
237
|
+
export { DELEGATION_MAX_CONCURRENT_DEFAULT, DELEGATION_MAX_PER_SESSION_DEFAULT, ORPHAN_ADOPT_WINDOW_MS_DEFAULT, ORPHAN_ADOPT_MAX_DEFAULT, SUBAGENT_TRANSCRIPT_RETENTION_DAYS_DEFAULT, } from "./config/defaults.js";
|
|
237
238
|
export { COORDINATOR_ROLE_PROMPT, TEAMMATE_COMMUNICATION_ADDENDUM, TEAMMATE_TASK_LIST_ADDENDUM } from "./prompts/coordinator.js";
|
|
238
|
-
export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE, agentWhenToUseText, FORK_DIRECTIVE_FRAME, SUBAGENT_SYSTEM_NOTE, type SubagentToolOptions, type SubagentSpawnContext, type SubagentSteerHandle, type SubagentStep, type SubagentEditedFile, } from "./agents/subagent.js";
|
|
239
|
+
export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE, agentWhenToUseText, FORK_DIRECTIVE_FRAME, SUBAGENT_SYSTEM_NOTE, type SubagentToolOptions, resolveDelegationEntryCaps, type ResolvedDelegationEntryCaps, type SubagentSpawnContext, type SubagentSteerHandle, type SubagentStep, type SubagentEditedFile, } from "./agents/subagent.js";
|
|
239
240
|
export { getSessionRetainLedger, releaseSessionRetainLedger, } from "./agents/retain-ledger.js";
|
|
240
|
-
export { createSendMessageTool, SEND_MESSAGE_TOOL_NAME, type SendMessageToolOptions } from "./agents/send-message-tool.js";
|
|
241
|
+
export { createSendMessageTool, createAgentContinuationVerb, SEND_MESSAGE_TOOL_NAME, type SendMessageToolOptions, type AgentContinuationReceipt } from "./agents/send-message-tool.js";
|
|
241
242
|
export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerAdmissionConfig, PEER_ADMISSION_DEFAULTS, PEER_HOP_CHAIN_WINDOW, PEER_MESSAGE_NOTICE, createPeerSelfRef, createPeerInboundChainRef, peerAxisToken, appendHopToken, type PeerAdmission, type PeerAdmissionConfig, type PeerAdmissionOptions, type PeerAdmissionRequest, type PeerAdmissionVerdict, type PeerAdmissionRefusal, type PeerRefusalCode, type PeerAxisTag, type PeerIdentity, type PeerSelfRef, type PeerInboundChainRef, } from "./agents/peer-admission.js";
|
|
242
243
|
export { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME, type AgentTranscriptToolOptions, } from "./agents/agent-transcript-tool.js";
|
|
243
244
|
export { defineAgent } from "./agents/agent-definition.js";
|
package/dist/index.js
CHANGED
|
@@ -90,7 +90,7 @@ export { createFsWriteGatePolicy } from "./core/fs-write-gate-policy.js";
|
|
|
90
90
|
export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
|
|
91
91
|
export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
|
|
92
92
|
export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, SystemInjectionQueue, } from "./core/task-notification.js";
|
|
93
|
-
export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, } from "./core/wiring-manifest.js";
|
|
93
|
+
export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, } from "./core/wiring-manifest.js";
|
|
94
94
|
export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, } from "./core/park-selfcheck.js";
|
|
95
95
|
export {} from "./core/checkpoint-store.js";
|
|
96
96
|
export {} from "./core/checkpoint-store.js";
|
|
@@ -193,10 +193,11 @@ export { summarizeRedactions } from "./core/untrusted-egress.js";
|
|
|
193
193
|
export { MemoryRosterStore, FileRosterStore } from "./agents/roster-store.js";
|
|
194
194
|
export { CONFIG_CATALOG_VERSION, describeConfigCatalog, resolveEffectiveConfig, } from "./config/catalog.js";
|
|
195
195
|
export { normalizeAgentName } from "./core/task-registry.js";
|
|
196
|
+
export { DELEGATION_MAX_CONCURRENT_DEFAULT, DELEGATION_MAX_PER_SESSION_DEFAULT, ORPHAN_ADOPT_WINDOW_MS_DEFAULT, ORPHAN_ADOPT_MAX_DEFAULT, SUBAGENT_TRANSCRIPT_RETENTION_DAYS_DEFAULT, } from "./config/defaults.js";
|
|
196
197
|
export { COORDINATOR_ROLE_PROMPT, TEAMMATE_COMMUNICATION_ADDENDUM, TEAMMATE_TASK_LIST_ADDENDUM } from "./prompts/coordinator.js";
|
|
197
|
-
export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE, agentWhenToUseText, FORK_DIRECTIVE_FRAME, SUBAGENT_SYSTEM_NOTE, } from "./agents/subagent.js";
|
|
198
|
+
export { createSubagentTool, FORK_SUBAGENT_TYPE, GENERAL_PURPOSE_SUBAGENT_TYPE, agentWhenToUseText, FORK_DIRECTIVE_FRAME, SUBAGENT_SYSTEM_NOTE, resolveDelegationEntryCaps, } from "./agents/subagent.js";
|
|
198
199
|
export { getSessionRetainLedger, releaseSessionRetainLedger, } from "./agents/retain-ledger.js";
|
|
199
|
-
export { createSendMessageTool, SEND_MESSAGE_TOOL_NAME } from "./agents/send-message-tool.js";
|
|
200
|
+
export { createSendMessageTool, createAgentContinuationVerb, SEND_MESSAGE_TOOL_NAME } from "./agents/send-message-tool.js";
|
|
200
201
|
export { createPeerAdmission, peerAdmissionFor, judgePeerAdmission, resolvePeerAdmissionConfig, PEER_ADMISSION_DEFAULTS, PEER_HOP_CHAIN_WINDOW, PEER_MESSAGE_NOTICE, createPeerSelfRef, createPeerInboundChainRef, peerAxisToken, appendHopToken, } from "./agents/peer-admission.js";
|
|
201
202
|
export { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME, } from "./agents/agent-transcript-tool.js";
|
|
202
203
|
export { defineAgent } from "./agents/agent-definition.js";
|
|
@@ -14,3 +14,4 @@ export type { SessionWriteOptions, CompactionEntry } from "../engine/harness/typ
|
|
|
14
14
|
export type { ActiveWorktreeSession, WorkspaceState } from "../engine/harness/types.js";
|
|
15
15
|
export type { GitAnnouncementKind, GitAnnouncementState } from "../engine/harness/types.js";
|
|
16
16
|
export type { SessionForkOptions } from "../engine/harness/types.js";
|
|
17
|
+
export type { SessionPlacementRecord, SessionCreateOptions } from "../engine/harness/types.js";
|
|
@@ -4,6 +4,9 @@ import type { ToolResultStore } from "../../core/tool-result-store.js";
|
|
|
4
4
|
import { type EvictPolicy } from "../../core/session-store.js";
|
|
5
5
|
import type { SessionStore } from "../../core/session.js";
|
|
6
6
|
import { type FileCheckpointStoreOptions } from "./checkpoint-store.js";
|
|
7
|
+
import type { BackgroundAgentStore } from "../../core/background-agent-store.js";
|
|
8
|
+
import type { MailboxStore } from "../../core/mailbox-store.js";
|
|
9
|
+
import type { RosterStore } from "../../agents/roster-store.js";
|
|
7
10
|
import type { SessionPolicyStore } from "../../core/session-policy-store.js";
|
|
8
11
|
import type { FileSnapshotStore } from "../../core/file-snapshot-store.js";
|
|
9
12
|
import type { WorkflowJournalStore } from "../../core/workflow-journal-store.js";
|
|
@@ -76,9 +79,8 @@ export interface FileStorageBackendOptions {
|
|
|
76
79
|
* Reach TODAY: {@link FileStorageBackend.sessionPolicyStore} (rules read as ABSENT ⇒ an unconstrained
|
|
77
80
|
* task), {@link FileStorageBackend.sessionStore}'s repo (a session listing that silently omits what it
|
|
78
81
|
* could not read) and {@link FileStorageBackend.fileSnapshotStore} (a snapshot/scope read as missing,
|
|
79
|
-
* and a blob GC that aborted). The roster and
|
|
80
|
-
*
|
|
81
|
-
* the same constructor.
|
|
82
|
+
* and a blob GC that aborted). The aggregated roster and mailbox stores receive the same sink. A
|
|
83
|
+
* store that grows the seat later is wired here in the same constructor.
|
|
82
84
|
*
|
|
83
85
|
* The payload is the UNION shape ({@link FileStorageCorruptReadInfo}): `path` + `reason` always,
|
|
84
86
|
* with the session-policy face's `sessionId`/`principal` present only when the reading store keys by
|
|
@@ -125,6 +127,18 @@ export declare class FileStorageBackend {
|
|
|
125
127
|
* `RunnerDeps.usageWindowStore` so a deployment's `usageWindows` survive a restart (an in-memory
|
|
126
128
|
* ledger silently re-grants every allowance on every boot). */
|
|
127
129
|
readonly usageWindowStore: UsageWindowStore;
|
|
130
|
+
/** design/151 S1a / subagent transcript persistence — the durable background-agent execution
|
|
131
|
+
* ledger over the same data root. Wire into BOTH `RunnerDeps.backgroundAgentStore` AND (for a
|
|
132
|
+
* deployment-composed Agent tool) `SubagentToolOptions.background.agentStore` — SAME instance
|
|
133
|
+
* (the RB-37 pairing discipline). Aggregated here so the TOC full-persistence assembly is one
|
|
134
|
+
* constructor, the same reason the session/checkpoint/tool-result trio are. */
|
|
135
|
+
readonly backgroundAgentStore: BackgroundAgentStore;
|
|
136
|
+
/** design/151 §7 S3c — the durable SendMessage mailbox (tier-3 parking lane), same data root.
|
|
137
|
+
* Wire into `RunnerDeps.mailboxStore` (single-instance pairing, same as above). */
|
|
138
|
+
readonly mailboxStore: MailboxStore;
|
|
139
|
+
/** design/147 S1c — the durable name→agent roster (layer 0.5 resolution), `root/roster.json`.
|
|
140
|
+
* Wire into `RunnerDeps.rosterStore` so name-addressing survives a restart alongside the rows. */
|
|
141
|
+
readonly rosterStore: RosterStore;
|
|
128
142
|
/**
|
|
129
143
|
* design/84 Seam B (TOC) — the per-scope consolidation lock for `consolidateScope`'s `acquire` injection
|
|
130
144
|
* point: `consolidateScope(scope, { store: backend.memoryStore, llm, acquire: backend.consolidationLock })`.
|
|
@@ -133,6 +147,8 @@ export declare class FileStorageBackend {
|
|
|
133
147
|
*/
|
|
134
148
|
readonly consolidationLock: (scope: string) => (() => void) | undefined;
|
|
135
149
|
private readonly lock;
|
|
150
|
+
private readonly fileAgentRows;
|
|
151
|
+
private readonly fileMailbox;
|
|
136
152
|
private readonly fileCheckpoints;
|
|
137
153
|
private readonly fileMemory;
|
|
138
154
|
private readonly ttl;
|
|
@@ -11,6 +11,9 @@ import { FileSessionPolicyStore } from "./session-policy-store.js";
|
|
|
11
11
|
import { FileFileSnapshotStore } from "./file-snapshot-store.js";
|
|
12
12
|
import { FileWorkflowJournalStore } from "./workflow-journal-store.js";
|
|
13
13
|
import { FileUsageWindowStore } from "./usage-window-store.js";
|
|
14
|
+
import { FileBackgroundAgentStore } from "./background-agent-store.js";
|
|
15
|
+
import { FileMailboxStore } from "./mailbox-store.js";
|
|
16
|
+
import { FileRosterStore } from "../../agents/roster-store.js";
|
|
14
17
|
export { FileCheckpointStore } from "./checkpoint-store.js";
|
|
15
18
|
export { FileMemoryStore } from "./memory-store.js";
|
|
16
19
|
export { FileSessionRepo } from "./session-store.js";
|
|
@@ -33,8 +36,13 @@ export class FileStorageBackend {
|
|
|
33
36
|
fileSnapshotStore;
|
|
34
37
|
workflowJournalStore;
|
|
35
38
|
usageWindowStore;
|
|
39
|
+
backgroundAgentStore;
|
|
40
|
+
mailboxStore;
|
|
41
|
+
rosterStore;
|
|
36
42
|
consolidationLock;
|
|
37
43
|
lock;
|
|
44
|
+
fileAgentRows;
|
|
45
|
+
fileMailbox;
|
|
38
46
|
fileCheckpoints;
|
|
39
47
|
fileMemory;
|
|
40
48
|
ttl;
|
|
@@ -49,7 +57,7 @@ export class FileStorageBackend {
|
|
|
49
57
|
const corruptRead = opts.onCorruptRead !== undefined ? { onCorruptRead: opts.onCorruptRead } : undefined;
|
|
50
58
|
const repo = new FileSessionRepo(this.root, corruptRead);
|
|
51
59
|
this.fileSessions = repo;
|
|
52
|
-
this.ttl = new TtlSessionStore({ repo, evict: opts.evict ?? "forget", durability: "durable" });
|
|
60
|
+
this.ttl = new TtlSessionStore({ repo, evict: opts.evict ?? "forget", durability: "durable", placements: { subagent: { durability: "durable" } } });
|
|
53
61
|
this.sessionStore = this.ttl;
|
|
54
62
|
this.fileCheckpoints = new FileCheckpointStore(this.root, opts.checkpoint);
|
|
55
63
|
this.checkpointStore = this.fileCheckpoints;
|
|
@@ -61,6 +69,11 @@ export class FileStorageBackend {
|
|
|
61
69
|
this.fileWorkflowJournal = new FileWorkflowJournalStore(this.root);
|
|
62
70
|
this.workflowJournalStore = this.fileWorkflowJournal;
|
|
63
71
|
this.usageWindowStore = new FileUsageWindowStore(this.root);
|
|
72
|
+
this.fileAgentRows = new FileBackgroundAgentStore(this.root);
|
|
73
|
+
this.backgroundAgentStore = this.fileAgentRows;
|
|
74
|
+
this.fileMailbox = new FileMailboxStore(this.root, corruptRead ?? {});
|
|
75
|
+
this.mailboxStore = this.fileMailbox;
|
|
76
|
+
this.rosterStore = new FileRosterStore(join(this.root, "roster.json"), corruptRead ?? {});
|
|
64
77
|
this.consolidationLock = createFileConsolidationLock(join(this.root, "consolidation-locks"));
|
|
65
78
|
}
|
|
66
79
|
catch (err) {
|
|
@@ -87,6 +100,16 @@ export class FileStorageBackend {
|
|
|
87
100
|
}
|
|
88
101
|
this.fileMemory.close();
|
|
89
102
|
this.fileWorkflowJournal.dispose();
|
|
103
|
+
try {
|
|
104
|
+
this.fileAgentRows.close();
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
this.fileMailbox.close();
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
}
|
|
90
113
|
this.lock.release();
|
|
91
114
|
}
|
|
92
115
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Session, SessionForkOptions, SessionMetadata, SessionRepo, SessionTreeEntry } from "../../internal/harness.js";
|
|
1
|
+
import type { Session, SessionCreateOptions, SessionForkOptions, SessionMetadata, SessionPlacementRecord, SessionRepo, SessionTreeEntry } from "../../internal/harness.js";
|
|
2
|
+
import type { PlacedSessionRow } from "../../core/session.js";
|
|
2
3
|
export interface FileSessionRepoOptions {
|
|
3
4
|
/**
|
|
4
5
|
* Disclosure sink for a durable read this repo treats as ABSENT (ruled 2026-08-03). Same name and
|
|
@@ -47,11 +48,24 @@ export declare class FileSessionRepo implements SessionRepo {
|
|
|
47
48
|
* means a stale holder can never revoke the rebuilt entry.
|
|
48
49
|
*/
|
|
49
50
|
dispose(): Promise<void>;
|
|
50
|
-
create(options?:
|
|
51
|
-
id?: string;
|
|
52
|
-
}): Promise<Session>;
|
|
51
|
+
create(options?: SessionCreateOptions): Promise<Session>;
|
|
53
52
|
open(metadata: SessionMetadata): Promise<Session>;
|
|
54
53
|
list(): Promise<SessionMetadata[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Subagent transcript persistence — the PLACED partition's own enumeration (the joint reap's
|
|
56
|
+
* partition-leg input; `TtlSessionStore` re-exposes it verbatim). Age (`olderThanMs`) is judged on
|
|
57
|
+
* the session FILE's mtime — the transcript's last append — falling back to `placedAt` when the
|
|
58
|
+
* stat fails (mtime is also the CC orphan-adoption window's basis, so the two age reads agree).
|
|
59
|
+
* Rows missing either `(scope, handle)` join half return the honest `tupleIncomplete` variant
|
|
60
|
+
* (consumers fail closed on it — never age-reaped, see the SessionStore contract).
|
|
61
|
+
*/
|
|
62
|
+
listPlaced(kind: "subagent", opts?: {
|
|
63
|
+
olderThanMs?: number;
|
|
64
|
+
scope?: string;
|
|
65
|
+
}): Promise<PlacedSessionRow[]>;
|
|
66
|
+
/** Cheap placement probe for one id (the TtlSessionStore's cold-cache release consults it so the
|
|
67
|
+
* placed real-deletion obligation holds after a restart). `undefined` = missing file OR unplaced. */
|
|
68
|
+
placementOf(sessionId: string): Promise<SessionPlacementRecord | undefined>;
|
|
55
69
|
delete(metadata: SessionMetadata): Promise<void>;
|
|
56
70
|
fork(sourceMetadata: SessionMetadata, options?: SessionForkOptions): Promise<Session>;
|
|
57
71
|
/** 2c session-sync ([275], the FILE half of [266]②): the FULL oldest-first log for export. The file backend
|