@sema-agent/core 5.26.0 → 5.28.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 +113 -0
- package/dist/agents/agent-transcript-tool.d.ts +5 -2
- package/dist/agents/agent-transcript-tool.js +2 -1
- package/dist/agents/send-message-tool.d.ts +4 -1
- package/dist/agents/subagent.d.ts +5 -2
- package/dist/core/checkpoint-store.d.ts +7 -2
- package/dist/core/hooks.d.ts +61 -4
- package/dist/core/hooks.js +37 -15
- package/dist/core/memory-engine/engine.d.ts +8 -5
- package/dist/core/memory-engine/engine.js +18 -6
- package/dist/core/memory-engine/file-backend.d.ts +144 -4
- package/dist/core/memory-engine/file-backend.js +304 -36
- package/dist/core/memory-engine/layout.d.ts +31 -2
- package/dist/core/memory-engine/layout.js +132 -8
- package/dist/core/memory-engine/types.d.ts +9 -1
- package/dist/core/memory-vector.d.ts +6 -1
- package/dist/core/memory-vector.js +14 -4
- package/dist/core/memory.js +1 -6
- package/dist/core/permission-rule-consent.d.ts +82 -8
- package/dist/core/permission-rule-consent.js +92 -1
- package/dist/core/permission-rule-model.d.ts +87 -6
- package/dist/core/permission-rule-model.js +79 -0
- package/dist/core/permission-rule-org.d.ts +22 -3
- package/dist/core/permission-rule-org.js +67 -20
- package/dist/core/permission-rule-store.js +2 -2
- package/dist/core/permission-rule-sync.d.ts +15 -1
- package/dist/core/permission-rule-sync.js +89 -47
- package/dist/core/runner/prepare-memory.js +14 -9
- package/dist/core/runner/prepare-task.d.ts +9 -3
- package/dist/core/runner/prepare-task.js +37 -11
- package/dist/core/runner/runtask.d.ts +8 -1
- package/dist/core/runner/runtask.js +8 -1
- package/dist/core/task-registry-agent.d.ts +13 -3
- package/dist/core/task-registry-agent.js +51 -21
- package/dist/core/task-registry-monitor.js +1 -1
- package/dist/core/task-registry-shared.d.ts +9 -0
- package/dist/core/task-registry.d.ts +6 -3
- package/dist/core/tool-policy.d.ts +44 -4
- package/dist/core/tool-policy.js +37 -3
- package/dist/core/tool-result-store.d.ts +108 -7
- package/dist/core/tool-result-store.js +95 -15
- package/dist/core/types.d.ts +115 -17
- package/dist/core/types.js +30 -1
- package/dist/engine/loop/types.d.ts +10 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +5 -3
- package/dist/orchestration/workflow.d.ts +9 -6
- package/dist/stores/file/checkpoint-store.d.ts +2 -1
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/tool-result-store.d.ts +41 -1
- package/dist/stores/file/tool-result-store.js +107 -19
- package/dist/tools/fs/fs-bash.d.ts +7 -0
- package/dist/tools/fs/fs-shared.d.ts +5 -0
- package/dist/tools/fs/fs-shared.js +11 -7
- package/dist/tools/fs/index.d.ts +6 -0
- package/dist/tools/fs/index.js +2 -0
- package/package.json +1 -1
|
@@ -48,8 +48,10 @@ export interface ToolResultStore {
|
|
|
48
48
|
* (session, tool call) is legitimately written by two different tasks of one session — the
|
|
49
49
|
* Runner shares one store across its tasks on purpose, and a BYOM brain may mint the same
|
|
50
50
|
* tool-call id in both — so stamping a `taskId` there would turn a designed sharing case into a
|
|
51
|
-
* refusal.
|
|
52
|
-
*
|
|
51
|
+
* refusal. Every engine write site therefore states the session only (#167) — including the
|
|
52
|
+
* background-agent and monitor spills, whose ref DOES carry the registry handle id: that id is
|
|
53
|
+
* an addressing segment of the ref, not an ownership coordinate a read-face caller can present
|
|
54
|
+
* (see {@link ToolResultProvenance.taskId} for the namespace rule);
|
|
53
55
|
* - an entry stored **without** provenance (written by an older engine, or by a call site that has
|
|
54
56
|
* none) stays UNOWNED: `put` never back-fills an owner onto it (that would be adoption by a party
|
|
55
57
|
* that cannot prove it wrote it) and {@link ownerOf} keeps answering `undefined`, which a read face
|
|
@@ -72,12 +74,77 @@ export interface ToolResultStore {
|
|
|
72
74
|
* that cannot answer this cannot back a host read face at all.
|
|
73
75
|
*/
|
|
74
76
|
ownerOf?(ref: string): Promise<ToolResultProvenance | undefined> | ToolResultProvenance | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Erase every entry this store recorded as belonging to `sessionId` — the DELETE half of the same
|
|
79
|
+
* ownership coordinate {@link ownerOf} answers on. Without it a durable backend keeps a deleted
|
|
80
|
+
* session's offloaded and spilled results on its media indefinitely: `put`/`get` alone give a
|
|
81
|
+
* deployment no way to complete a session deletion, and the engine ships no scheduler that would
|
|
82
|
+
* eventually collect them.
|
|
83
|
+
*
|
|
84
|
+
* Rules every implementation follows:
|
|
85
|
+
* - **selection is by RECORDED PROVENANCE, never by parsing the ref.** A ref is an opaque handle:
|
|
86
|
+
* its session segment may be folded ({@link buildToolResultRef}), refs minted before the
|
|
87
|
+
* injective form decompose two ways (`tr_team_blue_x` is both ("team","blue_x") and
|
|
88
|
+
* ("team_blue","x")), and a caller may mint its own. Prefix-matching a ref therefore both
|
|
89
|
+
* misses rows and reaches rows of a NEIGHBOURING session, and over-deletion here destroys a
|
|
90
|
+
* live session's readable bytes. The owner recorded at the winning write is the one coordinate
|
|
91
|
+
* that means exactly one thing, and it is the same one a read face authorizes against;
|
|
92
|
+
* - **`taskId` is ignored in the match.** A stored `{sessionId, taskId}` is a NARROWING of the
|
|
93
|
+
* same session, not a different owner — write sites stamped one before the namespace rule
|
|
94
|
+
* settled the shape (#167), and such rows still belong to the session being deleted;
|
|
95
|
+
* - **an UNOWNED entry is never deleted.** A row whose write stated no provenance (an older
|
|
96
|
+
* engine, a call site that has none, or a two-object backend interrupted between publishing
|
|
97
|
+
* content and owner) belongs to no session this sweep can name, and it is still READABLE via
|
|
98
|
+
* `get` — deleting it on a guess would destroy another session's output. It is counted instead
|
|
99
|
+
* ({@link ToolResultDeletionReport.unattributable}) so the caller learns the deletion was
|
|
100
|
+
* incomplete rather than being told a clean "done";
|
|
101
|
+
* - **idempotent**: deleting a session with no entries is a no-op, and a repeat call after a
|
|
102
|
+
* partial (loudly failed) sweep resumes it;
|
|
103
|
+
* - **concurrency-tolerant**: an entry that disappears between enumeration and removal is honest
|
|
104
|
+
* absence, not an error.
|
|
105
|
+
*
|
|
106
|
+
* Typed OPTIONAL, and deliberately NOT part of the published contract kit
|
|
107
|
+
* (`toolResultStoreContract`): unlike `ownerOf`, a backend that cannot enumerate by owner is still
|
|
108
|
+
* a usable offload store, so its absence must stay a checkable fact rather than a contract breach.
|
|
109
|
+
* Present ⇒ the store can complete a session deletion; absent ⇒ the deployment owns that gap.
|
|
110
|
+
*
|
|
111
|
+
* Implementing it does NOT make a store `retention: "managed"` — that declaration promises the whole
|
|
112
|
+
* {@link import("./retention.js").ManagedRetentionCapability} (domain enumeration, tombstones,
|
|
113
|
+
* audit receipts, scheduled execution), of which this is one caller-driven erase.
|
|
114
|
+
*/
|
|
115
|
+
deleteBySession?(sessionId: string): Promise<ToolResultDeletionReport> | ToolResultDeletionReport;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* What a {@link ToolResultStore.deleteBySession} sweep actually did. A count, not a `void`, because the
|
|
119
|
+
* sweep has a documented INCOMPLETE outcome (unowned entries it must not delete) and a caller running a
|
|
120
|
+
* session-deletion face has to be able to tell "the session's results are gone" from "some rows survive
|
|
121
|
+
* that no session can clear".
|
|
122
|
+
*/
|
|
123
|
+
export interface ToolResultDeletionReport {
|
|
124
|
+
/** Entries removed by THIS call. A retry of an already-swept session reports `0`, not an error. */
|
|
125
|
+
readonly deleted: number;
|
|
126
|
+
/**
|
|
127
|
+
* Entries the sweep could not attribute to ANY session and therefore left in place: stored without
|
|
128
|
+
* provenance, or with an owner record that is present but unreadable. Store-wide, not
|
|
129
|
+
* session-specific — an unowned row may or may not have been this session's, which is precisely why
|
|
130
|
+
* it cannot be deleted — so the same figure recurs on every session's sweep until a migration or an
|
|
131
|
+
* operator clears those rows.
|
|
132
|
+
*/
|
|
133
|
+
readonly unattributable: number;
|
|
75
134
|
}
|
|
76
135
|
/**
|
|
77
136
|
* Backlog #119 — WHO a stored tool result belongs to. Structured (not a single opaque string) because
|
|
78
137
|
* the read face authorizes by COMPARING fields it already knows; `taskId` is present when the write site
|
|
79
138
|
* has one (it is a narrowing of the session, never a substitute for it).
|
|
80
139
|
*
|
|
140
|
+
* #167 (namespace rule): a stamped `taskId` must name a coordinate the read face's CALLER presents —
|
|
141
|
+
* the host's own task/run id — never an engine-internal registry handle id. A handle id lives in a
|
|
142
|
+
* namespace only the engine's in-memory registry can resolve, so an owner stamped with one compares
|
|
143
|
+
* unequal to every caller coordinate forever: the entry becomes readable by NOBODY across the wire
|
|
144
|
+
* (fail-closed, but pointlessly — the disclosure text tells the caller to read it back). The engine's
|
|
145
|
+
* own write sites all state the session only; the handle id, where a ref needs it, is an ADDRESSING
|
|
146
|
+
* segment of the ref, not part of the owner.
|
|
147
|
+
*
|
|
81
148
|
* Deliberately NOT part of it: `toolCallId`. It is a retention/addressing coordinate, not an ownership
|
|
82
149
|
* one — two different tool calls in one session are the same owner.
|
|
83
150
|
*/
|
|
@@ -262,6 +329,12 @@ export declare class InMemoryToolResultStore implements ToolResultStore {
|
|
|
262
329
|
/** #119 — the owner recorded at the winning write; `undefined` for unknown AND for unowned entries,
|
|
263
330
|
* which a read face treats identically (fail-closed). */
|
|
264
331
|
ownerOf(ref: string): ToolResultProvenance | undefined;
|
|
332
|
+
/** Erase this session's entries, selected on the owner recorded at the winning write (the interface
|
|
333
|
+
* states the rules). Implemented here as well as on the durable backends so the bundled pair does
|
|
334
|
+
* not answer the same operation two ways: the entry holds content and owner as ONE value, so the
|
|
335
|
+
* same provenance match applies with none of the file backend's two-object bookkeeping. Deleting
|
|
336
|
+
* from a Map while iterating it is defined (a removed key is simply not revisited). */
|
|
337
|
+
deleteBySession(sessionId: string): ToolResultDeletionReport;
|
|
265
338
|
/** design/80 D-2: true when NOTHING has been offloaded — a durable suspend can then proceed safely even on
|
|
266
339
|
* this in-memory store, because a cross-replica resume has no offloaded result to deref to null. */
|
|
267
340
|
isEmpty(): boolean;
|
|
@@ -316,12 +389,35 @@ export declare function isVolatileOffloadStore(store: ToolResultStore): boolean;
|
|
|
316
389
|
export declare const OFFLOAD_TOOL_NAME = "ReadToolResult";
|
|
317
390
|
/**
|
|
318
391
|
* RB-469-d — the runner's clear-with-offload persist, as ONE construction point (the closure used to
|
|
319
|
-
* live inline in prepare-task). Fire-and-forget by design (the caller returns the ref synchronously)
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
392
|
+
* live inline in prepare-task). Fire-and-forget by design (the caller returns the ref synchronously).
|
|
393
|
+
*
|
|
394
|
+
* #167 (A-025.17) — a failed put REPORTS the loss, it never writes under the ref. The previous arm
|
|
395
|
+
* wrote a lost-marker row under the SAME ref "so the page-back face reports the true cause", and that
|
|
396
|
+
* one write carried two defects:
|
|
397
|
+
* - **revival**: the put and a session purge can race. When the put loses, the marker write lands
|
|
398
|
+
* AFTER the purge — re-inserting a row into a session the deployment just deleted, alive until the
|
|
399
|
+
* backend's own TTL. A failure arm must not be able to out-write a deletion;
|
|
400
|
+
* - **retry poisoning**: the per-request re-clear legitimately re-invokes this persist with the same
|
|
401
|
+
* (toolCallId, fullText) — the write-once retry path. With a marker occupying the ref, that
|
|
402
|
+
* retry's put of the REAL bytes hit the write-once no-op (same owner ⇒ keep what is there), so a
|
|
403
|
+
* transient first failure served the marker forever even though the full text was still in hand.
|
|
404
|
+
* Now the failure arm writes NOTHING (a later persist call retries the real bytes against an empty
|
|
405
|
+
* ref) and announces the failed write loudly instead: through the deployment's structured notice sink
|
|
406
|
+
* when one is wired, else `console.warn` (the loud-bad-value announcement dialect — a silent catch
|
|
407
|
+
* here would be a silent data loss). The announcement claims only what this arm can know: THIS
|
|
408
|
+
* attempt stored nothing — the same (toolCallId, fullText) persist recurs per request (write-once
|
|
409
|
+
* idempotent re-put), so an EARLIER attempt may already have landed the row and a rejected re-put is
|
|
410
|
+
* then no loss at all; declaring "the ref is empty" here would fabricate a data-loss incident on a
|
|
411
|
+
* transient outage. Page-back of a ref no attempt ever landed serves the generic miss, which is
|
|
412
|
+
* honest: nothing is stored under it.
|
|
323
413
|
*/
|
|
324
|
-
export declare function createOffloadPersist(store: ToolResultStore, sessionId: string
|
|
414
|
+
export declare function createOffloadPersist(store: ToolResultStore, sessionId: string,
|
|
415
|
+
/** Structured sink for the loss announcement, delivered through the shared guarded form
|
|
416
|
+
* (`deliverEngineNotice`, #170): a wired FUNCTION seat REPLACES the console line, swallow-guarded
|
|
417
|
+
* (a throwing/rejecting sink never turns an announcement into a failure); a present NON-function
|
|
418
|
+
* seat falls back to `console.warn` plus the once-per-process seat-defect announcement; absent ⇒
|
|
419
|
+
* `console.warn`. */
|
|
420
|
+
onNotice?: (notice: import("./types.js").EngineNotice) => void): (toolCallId: string, fullText: string) => string;
|
|
325
421
|
/** Backlog #119 — build the provenance a write site records, from the two coordinates every write site
|
|
326
422
|
* already has in hand. `taskId` is omitted (not `undefined`-valued) when the run declares none, so the
|
|
327
423
|
* stored shape compares equal across a durable round-trip. */
|
|
@@ -388,6 +484,11 @@ export declare function buildPreview(full: string, ref: string, sizes?: {
|
|
|
388
484
|
* wake needs a durable store (the default in-memory store loses the full text — the preview still stands).
|
|
389
485
|
* Image blocks are left untouched; only text is offloaded. Forwards the `onUpdate` progress callback so a
|
|
390
486
|
* wrapped (e.g. MCP) streaming tool isn't broken.
|
|
487
|
+
*
|
|
488
|
+
* Backlog #175 — a failing store NEVER turns the wrapped tool's success into a failure: the content face
|
|
489
|
+
* falls back to the original (un-offloaded) result, and the `details` walk to a ref-free notice per lost
|
|
490
|
+
* member (see the two arms for why the degrades differ). The wrapper adds a storage step to a tool that
|
|
491
|
+
* has already run; it must not be able to invalidate that run.
|
|
391
492
|
*/
|
|
392
493
|
export declare function withToolResultOffload(tool: AgentTool, store: ToolResultStore, thresholdChars: number, sessionId: string,
|
|
393
494
|
/** RB-374① — LIVE accessor for the session's currently CALLABLE tool set (evaluated per offload,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
import { defineTool, errorResult } from "./tools.js";
|
|
4
|
+
import { deliverEngineNotice } from "./types.js";
|
|
4
5
|
import { TOOL_SEARCH_NAME } from "./runner/tool-disclosure.js";
|
|
5
6
|
export const TOOL_RESULT_REF_CONFLICT_CODE = "tool_result.ref_conflict";
|
|
6
7
|
export class ToolResultRefConflictError extends Error {
|
|
@@ -94,6 +95,22 @@ export class InMemoryToolResultStore {
|
|
|
94
95
|
ownerOf(ref) {
|
|
95
96
|
return this.map.get(ref)?.provenance;
|
|
96
97
|
}
|
|
98
|
+
deleteBySession(sessionId) {
|
|
99
|
+
let deleted = 0;
|
|
100
|
+
let unattributable = 0;
|
|
101
|
+
for (const [ref, entry] of this.map) {
|
|
102
|
+
if (entry.provenance === undefined) {
|
|
103
|
+
unattributable++;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (entry.provenance.sessionId !== sessionId)
|
|
107
|
+
continue;
|
|
108
|
+
this.map.delete(ref);
|
|
109
|
+
this.totalChars -= entry.content.length;
|
|
110
|
+
deleted++;
|
|
111
|
+
}
|
|
112
|
+
return { deleted, unattributable };
|
|
113
|
+
}
|
|
97
114
|
isEmpty() {
|
|
98
115
|
return this.map.size === 0;
|
|
99
116
|
}
|
|
@@ -152,14 +169,23 @@ export function isVolatileOffloadStore(store) {
|
|
|
152
169
|
return store instanceof InMemoryToolResultStore;
|
|
153
170
|
}
|
|
154
171
|
export const OFFLOAD_TOOL_NAME = "ReadToolResult";
|
|
155
|
-
export function createOffloadPersist(store, sessionId) {
|
|
172
|
+
export function createOffloadPersist(store, sessionId, onNotice) {
|
|
156
173
|
const provenance = toolResultProvenanceOf(sessionId);
|
|
157
174
|
return (toolCallId, fullText) => {
|
|
158
175
|
const ref = buildToolResultRef(sessionId, toolCallId, toolResultContentSegment(fullText));
|
|
159
|
-
|
|
176
|
+
const reportFailedWrite = (err) => {
|
|
160
177
|
const cause = err instanceof Error ? err.message : String(err);
|
|
161
|
-
|
|
162
|
-
|
|
178
|
+
const message = `tool-result offload: persisting ref "${ref}" failed (${cause}) — this write attempt stored nothing; ` +
|
|
179
|
+
`unless an earlier attempt already stored this ref, the inline preview is all that survived. ` +
|
|
180
|
+
`A later re-clear of the same result retries the write.`;
|
|
181
|
+
deliverEngineNotice(onNotice, { code: "tool_result.offload_put_failed", message, detail: { ref, sessionId, cause } });
|
|
182
|
+
};
|
|
183
|
+
try {
|
|
184
|
+
void Promise.resolve(store.put(ref, fullText, provenance)).catch(reportFailedWrite);
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
reportFailedWrite(err);
|
|
188
|
+
}
|
|
163
189
|
return ref;
|
|
164
190
|
};
|
|
165
191
|
}
|
|
@@ -236,7 +262,12 @@ export function withToolResultOffload(tool, store, thresholdChars, sessionId, re
|
|
|
236
262
|
if (full.length <= PREVIEW_HEAD_CHARS + PREVIEW_TAIL_CHARS)
|
|
237
263
|
return withDetails(res);
|
|
238
264
|
const ref = buildToolResultRef(sessionId, toolCallId, toolResultContentSegment(full));
|
|
239
|
-
|
|
265
|
+
try {
|
|
266
|
+
await store.put(ref, full, provenance);
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
return withDetails(res);
|
|
270
|
+
}
|
|
240
271
|
const images = res.content.filter((b) => b.type !== "text");
|
|
241
272
|
return withDetails({ ...res, content: [{ type: "text", text: buildPreview(full, ref, undefined, reachableTools?.()) }, ...images] });
|
|
242
273
|
};
|
|
@@ -249,19 +280,34 @@ export function isOffloadedDetailReplacement(s) {
|
|
|
249
280
|
return s.includes(`\n${OFFLOADED_DETAIL_NOTICE_PREFIX}`);
|
|
250
281
|
}
|
|
251
282
|
async function offloadOversizedDetailStrings(details, store, thresholdChars, sessionId, toolCallId, provenance) {
|
|
252
|
-
const puts = [];
|
|
253
|
-
const onStack = new Set();
|
|
254
283
|
const isPlainObject = (v) => {
|
|
255
284
|
if (typeof v !== "object" || v === null)
|
|
256
285
|
return false;
|
|
257
286
|
const p = Object.getPrototypeOf(v);
|
|
258
287
|
return p === Object.prototype || p === null;
|
|
259
288
|
};
|
|
289
|
+
const onStack = new Set();
|
|
290
|
+
const pending = [];
|
|
291
|
+
const rebuilt = new Set();
|
|
260
292
|
const replace = (full, path) => {
|
|
261
293
|
const detailRef = buildToolResultRef(sessionId, toolCallId, path, toolResultContentSegment(full));
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
294
|
+
let done;
|
|
295
|
+
try {
|
|
296
|
+
done = Promise.resolve(store.put(detailRef, full, provenance));
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
done = Promise.reject(err);
|
|
300
|
+
}
|
|
301
|
+
const marker = {};
|
|
302
|
+
pending.push({
|
|
303
|
+
marker,
|
|
304
|
+
done,
|
|
305
|
+
render: (stored) => `${full.slice(0, OFFLOADED_DETAIL_HEAD_CHARS)}\n${OFFLOADED_DETAIL_NOTICE_PREFIX}${full.length} chars total; ` +
|
|
306
|
+
(stored
|
|
307
|
+
? `ref "${detailRef}"; the remainder is retained in this run's tool-result store and reads back through the deployment's tool-results face]`
|
|
308
|
+
: `persisting the remainder to this run's tool-result store failed or went unconfirmed, so no ref is offered — the text above is all this field carries]`),
|
|
309
|
+
});
|
|
310
|
+
return marker;
|
|
265
311
|
};
|
|
266
312
|
const memo = new Map();
|
|
267
313
|
const walk = (v, segs) => {
|
|
@@ -275,14 +321,21 @@ async function offloadOversizedDetailStrings(details, store, thresholdChars, ses
|
|
|
275
321
|
return done;
|
|
276
322
|
onStack.add(v);
|
|
277
323
|
let changed = false;
|
|
278
|
-
const
|
|
324
|
+
const len = v.length;
|
|
325
|
+
const next = new Array(len);
|
|
326
|
+
for (let i = 0; i < len; i++) {
|
|
327
|
+
if (!(i in v))
|
|
328
|
+
continue;
|
|
329
|
+
const item = v[i];
|
|
279
330
|
const w = walk(item, [...segs, i]);
|
|
280
331
|
if (w !== item)
|
|
281
332
|
changed = true;
|
|
282
|
-
|
|
283
|
-
}
|
|
333
|
+
Object.defineProperty(next, i, { value: w, enumerable: true, writable: true, configurable: true });
|
|
334
|
+
}
|
|
284
335
|
onStack.delete(v);
|
|
285
336
|
const result = changed ? next : v;
|
|
337
|
+
if (changed)
|
|
338
|
+
rebuilt.add(next);
|
|
286
339
|
memo.set(v, result);
|
|
287
340
|
return result;
|
|
288
341
|
}
|
|
@@ -303,14 +356,41 @@ async function offloadOversizedDetailStrings(details, store, thresholdChars, ses
|
|
|
303
356
|
}
|
|
304
357
|
onStack.delete(v);
|
|
305
358
|
const result = changed ? next : v;
|
|
359
|
+
if (changed)
|
|
360
|
+
rebuilt.add(next);
|
|
306
361
|
memo.set(v, result);
|
|
307
362
|
return result;
|
|
308
363
|
}
|
|
309
364
|
return v;
|
|
310
365
|
};
|
|
311
366
|
const value = walk(details, []);
|
|
312
|
-
await Promise.
|
|
313
|
-
|
|
367
|
+
const settled = await Promise.allSettled(pending.map((p) => p.done));
|
|
368
|
+
const notices = new Map();
|
|
369
|
+
pending.forEach((p, i) => void notices.set(p.marker, p.render(settled[i].status === "fulfilled")));
|
|
370
|
+
const seen = new Set();
|
|
371
|
+
const finalize = (node) => {
|
|
372
|
+
if (typeof node !== "object" || node === null)
|
|
373
|
+
return node;
|
|
374
|
+
const notice = notices.get(node);
|
|
375
|
+
if (notice !== undefined)
|
|
376
|
+
return notice;
|
|
377
|
+
if (!rebuilt.has(node) || seen.has(node))
|
|
378
|
+
return node;
|
|
379
|
+
seen.add(node);
|
|
380
|
+
if (Array.isArray(node)) {
|
|
381
|
+
for (let i = 0; i < node.length; i++) {
|
|
382
|
+
if (!Object.hasOwn(node, i))
|
|
383
|
+
continue;
|
|
384
|
+
Object.defineProperty(node, i, { value: finalize(node[i]), enumerable: true, writable: true, configurable: true });
|
|
385
|
+
}
|
|
386
|
+
return node;
|
|
387
|
+
}
|
|
388
|
+
const obj = node;
|
|
389
|
+
for (const k of Object.keys(obj))
|
|
390
|
+
Object.defineProperty(obj, k, { value: finalize(obj[k]), enumerable: true, writable: true, configurable: true });
|
|
391
|
+
return node;
|
|
392
|
+
};
|
|
393
|
+
return { value: finalize(value) };
|
|
314
394
|
}
|
|
315
395
|
export function createReadToolResultTool(store) {
|
|
316
396
|
return defineTool({
|
package/dist/core/types.d.ts
CHANGED
|
@@ -855,8 +855,11 @@ export interface ToolExecuteContext {
|
|
|
855
855
|
* `RunInternals.onForwardEvent`) to receive a SUBAGENT's live `task_progress` ticks that otherwise stay in the
|
|
856
856
|
* child's ISOLATED stream. A delegation tool threads it to the child so nested progress bubbles to one sink. This
|
|
857
857
|
* is a DISPLAY channel ONLY — the child stream is NEVER merged into the parent's MODEL context, and nothing
|
|
858
|
-
* security-relevant consumes a forwarded event. Present ONLY when the deployment opted in
|
|
859
|
-
*
|
|
858
|
+
* security-relevant consumes a forwarded event. Present ONLY when the deployment opted in. The tool-ctx wrapper
|
|
859
|
+
* passes `task_progress` unconditionally and — when the deployment sets `forwardSubagentEvents: true` — the
|
|
860
|
+
* transcript classes too (text_delta/reasoning_delta/tool_start/tool_end); other event types never cross it.
|
|
861
|
+
* The delegation lane's OWN tap is trusted and forwards the child's FULL event stream (bg frames tagged
|
|
862
|
+
* with bgAgentId). ⚠️ Forwarded ticks are UNTRUSTED display hints — any
|
|
860
863
|
* tool holding this ctx could forge one, so a consumer validates `parentTaskId` against its known runs.
|
|
861
864
|
*/
|
|
862
865
|
forwardEvent?: (event: TaskEvent) => void;
|
|
@@ -1731,6 +1734,11 @@ export interface TaskSpec {
|
|
|
1731
1734
|
* surfaced to the operator as a config-phase warning. Protocol tools (MCP/A2A) can never collide
|
|
1732
1735
|
* here: their wire names are namespaced (`mcp__<server>__…`) and a caller name containing `__`
|
|
1733
1736
|
* is rejected at prepare.
|
|
1737
|
+
*
|
|
1738
|
+
* Mount point: the roster (with `defer`/`excludeTools`/`deferTools`) lives on this PER-TASK spec —
|
|
1739
|
+
* the Runner constructor's deps carry no tool roster. Plain-JS callers beware: an unrecognized key
|
|
1740
|
+
* passed to the constructor is dropped by ordinary object semantics (TypeScript callers get an
|
|
1741
|
+
* excess-property error), so a roster placed there never mounts and its `defer` flags never apply.
|
|
1734
1742
|
*/
|
|
1735
1743
|
tools?: ToolSpec[];
|
|
1736
1744
|
/**
|
|
@@ -1871,7 +1879,9 @@ export interface TaskSpec {
|
|
|
1871
1879
|
* write-capable fs tools (CC's same gate); zero cost/behavior change otherwise. `false` opts out.
|
|
1872
1880
|
*/
|
|
1873
1881
|
lspDiagnostics?: boolean;
|
|
1874
|
-
/** In-process hooks
|
|
1882
|
+
/** In-process hooks for this task — the full `Hooks` lifecycle seam (tool pre/post/failure/batch
|
|
1883
|
+
* interception, prompt gating, stop pushback, compaction taps, permission-denied observation; each
|
|
1884
|
+
* member's contract is on the interface). Overrides `RunnerDeps.hooks`. */
|
|
1875
1885
|
hooks?: import("./hooks.js").Hooks;
|
|
1876
1886
|
/**
|
|
1877
1887
|
* design/45 **durable suspend-on-approval** (F4). When set AND a `CheckpointStore` is wired
|
|
@@ -2745,9 +2755,11 @@ export interface TaskResult {
|
|
|
2745
2755
|
* How long (milliseconds) until the deployment usage window that stopped this task frees up — the wait
|
|
2746
2756
|
* hint a scheduler needs to decide WHEN to re-submit, rather than polling.
|
|
2747
2757
|
*
|
|
2748
|
-
* **In-presence condition:** set on exactly
|
|
2749
|
-
* (either moment: the entry refusal that ran nothing, or the running terminal that could not suspend)
|
|
2750
|
-
*
|
|
2758
|
+
* **In-presence condition:** set on exactly two terminals — `errorCode === "usage.window_exhausted"`
|
|
2759
|
+
* (either moment: the entry refusal that ran nothing, or the running terminal that could not suspend)
|
|
2760
|
+
* and `errorCode === "memory.admission_required"` (the prepare-throw path sets it there too — see
|
|
2761
|
+
* assemble-result's accepted-code pair). Absent everywhere else, INCLUDING when a usage window did
|
|
2762
|
+
* stop the run but a higher-ranked terminal
|
|
2751
2763
|
* named the result (a budget ceiling crossed on the same turn): the reported cause is then that other
|
|
2752
2764
|
* code, and a wait filed under it would describe something the code does not name.
|
|
2753
2765
|
*
|
|
@@ -3260,13 +3272,16 @@ export type TaskEvent = ({
|
|
|
3260
3272
|
*/
|
|
3261
3273
|
structured?: unknown;
|
|
3262
3274
|
/**
|
|
3263
|
-
* Present iff {@link isError} is true AND the harness result's `details` carried a string
|
|
3264
|
-
*
|
|
3265
|
-
*
|
|
3266
|
-
*
|
|
3267
|
-
*
|
|
3268
|
-
*
|
|
3269
|
-
*
|
|
3275
|
+
* Present iff {@link isError} is true AND the harness result's `details` carried a string
|
|
3276
|
+
* discriminator — read as `details.code` first, falling back to `details.errorKind` (each must be
|
|
3277
|
+
* a string; `code` wins when both are present, as the deliberate tool-chosen spelling). The
|
|
3278
|
+
* `errorKind` leg is what makes a LOOP-THROWN error's frame classifiable: the loop's thrown-error
|
|
3279
|
+
* fold and the resume legs write the discriminator under that name. Lifted so a consumer never
|
|
3280
|
+
* has to parse the (contract-stable) result text. Engine-minted vocabulary today includes
|
|
3281
|
+
* `"tool.not_found"` (unknown tool name) and `"gate.parked"` (an abort short-circuit poisoned
|
|
3282
|
+
* this call because a durable gate parked the batch — the "Operation aborted" family). Additive:
|
|
3283
|
+
* absent on error frames minted before this field existed, and on error results whose details
|
|
3284
|
+
* carry no string discriminator under either name.
|
|
3270
3285
|
*/
|
|
3271
3286
|
errorCode?: string;
|
|
3272
3287
|
/**
|
|
@@ -4156,6 +4171,51 @@ export interface ProjectMemoryLoad {
|
|
|
4156
4171
|
contentHash: string | null;
|
|
4157
4172
|
}>;
|
|
4158
4173
|
}
|
|
4174
|
+
/**
|
|
4175
|
+
* A structured operator-facing notice ({@link RunnerDeps.onNotice}) — a fact the engine announces that
|
|
4176
|
+
* is neither an error nor part of the task result: today, a configured value that was discarded in
|
|
4177
|
+
* favor of another (the loud-bad-value discipline's announcement dialect). Structured so a host can
|
|
4178
|
+
* FORWARD it to its own user surface instead of losing it in process stderr.
|
|
4179
|
+
*/
|
|
4180
|
+
export interface EngineNotice {
|
|
4181
|
+
/** Stable machine-readable family, dot-namespaced. Current families:
|
|
4182
|
+
* - `"config.env_timeout_discarded"` — a Bash timeout knob (option or env) held a value that is not
|
|
4183
|
+
* the value in force; `detail: { knob, raw, usedMs }`.
|
|
4184
|
+
* - `"config.materialize_env_discarded"` — `SEMA_TOOL_MATERIALIZE_STRATEGY` held a value outside the
|
|
4185
|
+
* closed set in a seat where it is not in force; `detail: { raw, specStrategy? }`.
|
|
4186
|
+
* - `"tool_result.offload_put_failed"` (#167) — a clear-with-offload persist's fire-and-forget put
|
|
4187
|
+
* failed; THIS attempt stored nothing (the failure arm reports, it never re-inserts under the
|
|
4188
|
+
* ref) — an earlier attempt of the same idempotent re-put may already have stored the row, so
|
|
4189
|
+
* the notice claims a failed write, not an empty ref; `detail: { ref, sessionId, cause }`.
|
|
4190
|
+
* Per-occurrence, not per-process-deduplicated: each failed write is a distinct fact. */
|
|
4191
|
+
code: string;
|
|
4192
|
+
/** The exact human-readable line the unwired build prints via `console.warn` — same words, one text. */
|
|
4193
|
+
message: string;
|
|
4194
|
+
/** Machine-readable facts of the notice (knob names, arriving values, values in force). */
|
|
4195
|
+
detail?: Record<string, unknown>;
|
|
4196
|
+
}
|
|
4197
|
+
/** Test seam (mirrors `__resetBashTimeoutAnnouncements`): never called by production code. */
|
|
4198
|
+
export declare function __resetMalformedNoticeSeatAnnouncement(): void;
|
|
4199
|
+
/**
|
|
4200
|
+
* The ONE delivery form behind every {@link RunnerDeps.onNotice} emission point (#170: the form was
|
|
4201
|
+
* triplicated across the emission stations, and every copy judged the seat with `!== undefined` — so a
|
|
4202
|
+
* PRESENT non-function seat (null, a config typo, an untyped host's JSON wiring) entered the wired arm,
|
|
4203
|
+
* threw `TypeError` on the call, and the swallow guard silenced BOTH channels at once). Contract:
|
|
4204
|
+
* · a FUNCTION seat REPLACES the console line (a host forwarding notices to its own surface must not
|
|
4205
|
+
* show every fact twice), swallow-guarded against both failure shapes the void-typed seat admits —
|
|
4206
|
+
* a synchronous throw and an async sink's rejected promise (unhandled, that rejection is a
|
|
4207
|
+
* process-level fault): a notice sink must never turn an announcement into a failure. Deliberately
|
|
4208
|
+
* NO console fallback on sink failure: loudness ownership transfers with the wiring, and a console
|
|
4209
|
+
* echo of a transient sink failure would double-send the fact. Corollary kept as-is: stations that
|
|
4210
|
+
* de-duplicate ledger the line BEFORE this call, so a true-function sink that throws can in
|
|
4211
|
+
* principle lose a ledgered line for the process lifetime — un-ledgering after the fact would race
|
|
4212
|
+
* an async sink's late rejection and re-announce (double-send) on transient failures.
|
|
4213
|
+
* · a PRESENT NON-function seat is a bad deployment value, and #123 (loud-bad-value law) forbids
|
|
4214
|
+
* folding it to silence: the notice itself falls back to `console.warn` (no line is lost), and the
|
|
4215
|
+
* seat defect — the one fact every fallback would otherwise repeat — is announced once per process.
|
|
4216
|
+
* · an ABSENT seat prints the historic `console.warn` line verbatim (byte-compat loudness).
|
|
4217
|
+
*/
|
|
4218
|
+
export declare function deliverEngineNotice(onNotice: ((notice: EngineNotice) => void) | undefined, notice: EngineNotice): void;
|
|
4159
4219
|
/** Runtime dependencies shared across tasks. */
|
|
4160
4220
|
export interface RunnerDeps {
|
|
4161
4221
|
brain: Brain;
|
|
@@ -4729,10 +4789,15 @@ export interface RunnerDeps {
|
|
|
4729
4789
|
* task's own `lspManager` overrides this. Unset ⇒ no `lsp` tool. */
|
|
4730
4790
|
lspManager?: import("./lsp.js").LspServerManager;
|
|
4731
4791
|
/**
|
|
4732
|
-
* Default in-process hooks for all tasks (design/37)
|
|
4733
|
-
*
|
|
4734
|
-
*
|
|
4735
|
-
*
|
|
4792
|
+
* Default in-process hooks for all tasks (design/37) — the FULL lifecycle seam of the `Hooks`
|
|
4793
|
+
* interface, not just the tool-call trio: `preToolUse` (rewrite/restrict args + inject context),
|
|
4794
|
+
* `postToolUse` (rewrite output + inject context), `userPromptSubmit` (block/inject before the
|
|
4795
|
+
* objective becomes a message), plus `stop` (push back when the run would otherwise end and continue
|
|
4796
|
+
* it), `postToolUseFailure` / `postToolBatch` / `permissionDenied` (failure, batch-boundary and
|
|
4797
|
+
* deny observers), `preCompact` / `postCompact` (compaction gate + observer), `stopFailure`
|
|
4798
|
+
* (API-error terminal observer) and the `preToolUseObservational` declaration flag — each member's
|
|
4799
|
+
* contract is documented on the `Hooks` interface itself. A task's own `hooks` overrides this. A
|
|
4800
|
+
* PreToolUse hook's `allow` never bypasses `toolPolicy` — the policy is always the final say.
|
|
4736
4801
|
*/
|
|
4737
4802
|
hooks?: import("./hooks.js").Hooks;
|
|
4738
4803
|
/**
|
|
@@ -4750,12 +4815,30 @@ export interface RunnerDeps {
|
|
|
4750
4815
|
* - `"prompt-constitution"` — a `stableSystem` provider returned an ALREADY-assembled prompt
|
|
4751
4816
|
* (constitution anchor found); core passed it through un-doubled. Upgrade the provider to return
|
|
4752
4817
|
* only the role base (or set `replaceAll: true` to own the whole base).
|
|
4818
|
+
* - `"degraded"` — the task kept running with a capability quietly reduced: a question auto-answered
|
|
4819
|
+
* with no human present, a skipped env git snapshot, a lost checkpoint-put confirmation, an
|
|
4820
|
+
* unroutable descendant notification, and similar best-effort arms. The run proceeds; the reduced
|
|
4821
|
+
* arm is what is being disclosed (`classification` names it).
|
|
4822
|
+
* - `"config"` — a deployment-wiring problem detected while preparing or tearing down a task: tool
|
|
4823
|
+
* mount conflicts, refused/ignored knob values, gate-off notices, store/env teardown legs. The
|
|
4824
|
+
* broadest class by call-site count — most misconfigurations announce here rather than failing
|
|
4825
|
+
* the task.
|
|
4753
4826
|
* - `"memory"` — a post-task memory-consolidation pass failed or skipped a malformed reconcile
|
|
4754
4827
|
* decision (design/41). Best-effort: the notes the model saved are kept; the task still succeeds.
|
|
4755
4828
|
* - `"mcp"` — an MCP server failed to connect / list its tools and was skipped (fail-open, design/29);
|
|
4756
4829
|
* the task runs with the remaining servers' tools. One call per failed server.
|
|
4757
4830
|
* - `"a2a"` — the A2A sibling of `"mcp"`: a declared peer's agent card could not be fetched/read, or it
|
|
4758
4831
|
* advertises no transport this client speaks, so the peer was skipped. One call per skipped peer.
|
|
4832
|
+
* - `"interrupt-reconcile"` — repairing an interrupted session's transcript on re-entry (synthesizing
|
|
4833
|
+
* tool results for orphaned calls, flushing held session writes) failed; the run proceeds on the
|
|
4834
|
+
* unrepaired transcript.
|
|
4835
|
+
* - `"suggestions"` — the best-effort follow-up-suggestions pass failed or timed out; the result
|
|
4836
|
+
* simply carries no suggestions.
|
|
4837
|
+
* - `"rewind"` — the per-turn working-tree snapshot backing file rewind failed or was skipped (e.g. a
|
|
4838
|
+
* too-large root inside its cooldown window); turns without a snapshot cannot be rewound to.
|
|
4839
|
+
* - `"hook"` — a deployment hook misbehaved: a callback threw, or returned a verdict it was not
|
|
4840
|
+
* allowed to (e.g. a declared-observational hook). The engine applies the hook's own documented
|
|
4841
|
+
* fallback (swallow, or fail-closed deny, per its contract) and reports the fact here.
|
|
4759
4842
|
*/
|
|
4760
4843
|
onError?: (err: unknown, context: {
|
|
4761
4844
|
phase: "compaction" | "prompt-cache" | "prompt-constitution" | "degraded" | "config" | "memory" | "mcp" | "a2a" | "interrupt-reconcile" | "suggestions" | "rewind" | "hook";
|
|
@@ -4769,6 +4852,21 @@ export interface RunnerDeps {
|
|
|
4769
4852
|
*/
|
|
4770
4853
|
classification?: string;
|
|
4771
4854
|
}) => void;
|
|
4855
|
+
/**
|
|
4856
|
+
* Structured sink for operator-facing NOTICES ({@link EngineNotice}) — announcements that are not
|
|
4857
|
+
* errors and do not affect the run, which the engine otherwise prints via `console.warn` (e.g. a
|
|
4858
|
+
* configured timeout/env value discarded in favor of another). When wired, a notice goes HERE
|
|
4859
|
+
* INSTEAD of `console.warn` (structured replaces the console line — a host forwarding notices to
|
|
4860
|
+
* its own surface must not show every fact twice); when absent, the historic `console.warn` line
|
|
4861
|
+
* is printed verbatim, so an unwired build keeps its exact loudness. Swallow-guarded at every
|
|
4862
|
+
* emission point (`onError`/`tracer` posture): neither a throwing sink nor an async sink's
|
|
4863
|
+
* rejected promise ever affects the run. A PRESENT NON-function value (an untyped host wiring
|
|
4864
|
+
* null/junk) is a bad deployment value, not a wired sink: every notice then falls back to the
|
|
4865
|
+
* `console.warn` line and the seat defect itself is announced once per process (#170 — a bad seat
|
|
4866
|
+
* must not silence both channels). Per-process announcement de-duplication is unchanged and
|
|
4867
|
+
* sits BEFORE the sink branch — a deduplicated repeat reaches neither channel.
|
|
4868
|
+
*/
|
|
4869
|
+
onNotice?: (notice: EngineNotice) => void;
|
|
4772
4870
|
/** Best-effort fire-and-forget trace sink (task/turn/brain/tool); `TaskSpec.tracer` overrides per task. */
|
|
4773
4871
|
tracer?: import("./trace.js").TracerHook;
|
|
4774
4872
|
/**
|
package/dist/core/types.js
CHANGED
|
@@ -1 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
let malformedNoticeSeatAnnounced = false;
|
|
2
|
+
export function __resetMalformedNoticeSeatAnnouncement() {
|
|
3
|
+
malformedNoticeSeatAnnounced = false;
|
|
4
|
+
}
|
|
5
|
+
export function deliverEngineNotice(onNotice, notice) {
|
|
6
|
+
if (typeof onNotice === "function") {
|
|
7
|
+
try {
|
|
8
|
+
const r = onNotice(notice);
|
|
9
|
+
if (typeof r?.then === "function") {
|
|
10
|
+
r.then(undefined, () => {
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
}
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (onNotice !== undefined) {
|
|
19
|
+
if (!malformedNoticeSeatAnnounced) {
|
|
20
|
+
malformedNoticeSeatAnnounced = true;
|
|
21
|
+
try {
|
|
22
|
+
console.warn(`The structured notice sink (RunnerDeps.onNotice) holds ${onNotice === null ? "null" : typeof onNotice} — not a ` +
|
|
23
|
+
`function. Notices fall back to console.warn until the wiring is fixed (omit the key, or wire a function).`);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
console.warn(notice.message);
|
|
30
|
+
}
|
|
@@ -23,7 +23,11 @@ export type ToolExecutionMode = "sequential" | "parallel";
|
|
|
23
23
|
* Controls how many queued user messages are injected when the agent loop reaches a queue drain point.
|
|
24
24
|
*
|
|
25
25
|
* - "all": drain and inject every queued message at that point.
|
|
26
|
-
* - "one-at-a-time": drain and inject only the oldest queued message, leaving the rest queued for later
|
|
26
|
+
* - "one-at-a-time": drain and inject only the oldest queued message, leaving the rest queued for later
|
|
27
|
+
* drain points. Exception: when the oldest frame is an engine note (a task-notification sidecar
|
|
28
|
+
* payload), every consecutive engine-note frame behind it drains with it as ONE batch, stopping at
|
|
29
|
+
* the first non-note frame (e.g. a real user steer) — N buffered completion notices are one
|
|
30
|
+
* boundary's worth of frames, not N sequential turns.
|
|
27
31
|
*/
|
|
28
32
|
export type QueueMode = "all" | "one-at-a-time";
|
|
29
33
|
/** A single tool call content block emitted by an assistant message. */
|
|
@@ -394,8 +398,11 @@ export interface AgentLoopConfig extends SimpleStreamOptions {
|
|
|
394
398
|
}
|
|
395
399
|
/**
|
|
396
400
|
* Thinking/reasoning level for models that support it.
|
|
397
|
-
* Note: "xhigh" is only supported by selected model families.
|
|
398
|
-
*
|
|
401
|
+
* Note: "xhigh" is only supported by selected model families. Per-model/per-endpoint support is
|
|
402
|
+
* declared in this package's model metadata (`src/engine/llm/types.ts`): the compat blocks'
|
|
403
|
+
* accepted-tier sets (`reasoningEffortLevels` on the OpenAI-family compats, `effortLevels` on the
|
|
404
|
+
* Anthropic Messages compat — a requested tier above the declared set clamps down rather than
|
|
405
|
+
* erroring), and `Model.thinkingLevelMap`, where `null` marks a level as unsupported.
|
|
399
406
|
*/
|
|
400
407
|
export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
401
408
|
export interface BashExecutionMessage {
|
package/dist/index.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ export type { InvariantKind, FunctionContract, Invariant, InvariantViolation, Ch
|
|
|
87
87
|
export { HAND_TOOL_EFFECTS, bashReversibilityProbe, BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName, classifyCompoundReadonly, MAX_EDIT_BYTES } from "./tools/fs/index.js";
|
|
88
88
|
export { classifyCompoundReadonlyDetailed, formatOutOfRootReadApprovalOption, type BashReadonlyRootBoundary, type CompoundReadonlyVerdict, } from "./tools/fs/index.js";
|
|
89
89
|
export { resolveBashTimeoutCaps } from "./tools/fs/index.js";
|
|
90
|
-
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, buildToolResultRef, MAX_MINTED_TOOL_RESULT_REF_CHARS, type ToolResultProvenance, assertToolResultProvenanceMatch, normalizeToolResultProvenance, toolResultProvenanceOf, ToolResultRefConflictError, TOOL_RESULT_REF_CONFLICT_CODE, type ToolResultStore, type ToolResultSlice, } from "./core/tool-result-store.js";
|
|
90
|
+
export { InMemoryToolResultStore, OFFLOAD_TOOL_NAME, DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, assertSafeToolResultRef, buildToolResultRef, toolResultContentSegment, MAX_MINTED_TOOL_RESULT_REF_CHARS, type ToolResultProvenance, assertToolResultProvenanceMatch, normalizeToolResultProvenance, toolResultProvenanceOf, ToolResultRefConflictError, TOOL_RESULT_REF_CONFLICT_CODE, type ToolResultStore, type ToolResultSlice, type ToolResultDeletionReport, } from "./core/tool-result-store.js";
|
|
91
91
|
export { InMemoryCheckpointStore, CheckpointError, mintCheckpointToken, checkpointVersionOf, CURRENT_CHECKPOINT_VERSION, MAX_SUPPORTED_CHECKPOINT_VERSION, ORG_ADMISSION_CHECKPOINT_VERSION, F012_CHECKPOINT_VERSION, REAL_APPROVAL_CHECKPOINT_VERSION, RESOURCE_CHECKPOINT_VERSION, TOKEN_CHECKPOINT_VERSION, debitLedger, remainingBudgetMicroUsd, remainingTokens, winnerFromOutcome, validatePendingSteer, readPendingSteerQueue, appendPendingSteer, MAX_PENDING_STEER_CHARS, MAX_PENDING_STEER_ENTRIES, PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES, PENDING_STEER_FROZEN_FIELDS, ACTOR_ASSERTION_FROZEN_FIELDS, MAX_ACTOR_FIELD_CHARS, MAX_STEER_INPUT_ID_CHARS, LEGACY_PENDING_STEER_INPUT_ID, type ActorAssertion, type PendingSteerEntry, type PendingSteerInput, riskSeverity, buildRiskDescriptor, summarizeCheckpoint, type RiskDescriptor, type CheckpointStore, type CheckpointSummary, type Checkpoint, type CheckpointToken, type CheckpointGate, type CheckpointState, type SerializedCheckpointState, type CheckpointFaultMode, type PendingAction, type ResumeOutcome, type ResolvedOutcome, type ReopenReason, type ResolveExpectation, type SafetyAxis, type RealApprovalGateBit, type ResourceLedger, type ResourceLimitReason, type PlatformLimitReason, } from "./core/checkpoint-store.js";
|
|
92
92
|
export { InMemoryUsageWindowStore, GLOBAL_USAGE_KEY, EMPTY_USAGE_WINDOW_RECORD, chargeUsageRecord, readUsageRecord, usageRetryAfterMs, resolveUsageWindows, type UsageWindow, type UsageWindowStore, type UsageWindowReading, type UsageWindowRecord, type UsageSlot, type UsageBucketRow, } from "./core/usage-window-store.js";
|
|
93
93
|
export { FileUsageWindowStore } from "./stores/file/usage-window-store.js";
|
|
@@ -250,7 +250,7 @@ export { retryBackoffMs, parseRetryAfter } from "./brain/retry.js";
|
|
|
250
250
|
export { type BrainTimeoutConfig } from "./brain/timeout.js";
|
|
251
251
|
export { createAssistantMessageEventStream } from "./internal/llm.js";
|
|
252
252
|
export type { AssistantMessage, AssistantMessageEvent, CompleteSimpleFn, Context, DocumentContent, ImageContent, Message, StopReason, StreamFn, TextContent, ThinkingContent, ToolCall, ToolResultMessage, Usage, UserMessage, } from "./internal/llm.js";
|
|
253
|
-
export type { AgentDefinition, BeforeWriteHook, BeforeWriteRequest, BeforeWriteResult, HandsBandOptions, Brain, BrainStatus, BrainStatusPhase, BrainRetryErrClass, ImageInput, McpElicitRequest, McpElicitResponse, McpServerSpec, A2aServerSpec, OnElicit, Model, ModelRef, ProjectMemoryLoad, RunnerDeps, RuntimeCaps, BackgroundChildEvent, SkillManifest, SkillSpec, TaskEvent, TaskEventIdentity, ToolActivity, TaskLimits, StaleToolResultOffloadOptions, TaskResult, RemoteEnvFailureNote, TaskSpec, TaskStatus, TaskStream, CompactOutcome, ThinkingLevel, ToolExecuteContext, ToolReturn, ToolSpec, ToolEffect, ToolContentOrigin, WorkflowGovernanceBaseline, DelegationTaskType, } from "./core/types.js";
|
|
253
|
+
export type { AgentDefinition, BeforeWriteHook, BeforeWriteRequest, BeforeWriteResult, HandsBandOptions, Brain, BrainStatus, BrainStatusPhase, BrainRetryErrClass, ImageInput, McpElicitRequest, McpElicitResponse, McpServerSpec, A2aServerSpec, OnElicit, Model, ModelRef, ProjectMemoryLoad, RunnerDeps, EngineNotice, RuntimeCaps, BackgroundChildEvent, SkillManifest, SkillSpec, TaskEvent, TaskEventIdentity, ToolActivity, TaskLimits, StaleToolResultOffloadOptions, TaskResult, RemoteEnvFailureNote, TaskSpec, TaskStatus, TaskStream, CompactOutcome, ThinkingLevel, ToolExecuteContext, ToolReturn, ToolSpec, ToolEffect, ToolContentOrigin, WorkflowGovernanceBaseline, DelegationTaskType, } from "./core/types.js";
|
|
254
254
|
export { Type } from "typebox";
|
|
255
255
|
export type { TSchema, Static } from "typebox";
|
|
256
256
|
export { explainPromptAssembly, describeDefaultPack, type DefaultPackDescription, type ExplainInput } from "./prompt-assembly/explain.js";
|