@sema-agent/core 5.37.0 → 5.38.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 +67 -0
- package/dist/agents/subagent.js +6 -0
- package/dist/agents/teacher.js +3 -0
- package/dist/agents/team.d.ts +7 -1
- package/dist/agents/team.js +11 -9
- package/dist/agents/verify.js +3 -0
- package/dist/core/auto-mode-prompt-assets.d.ts +5 -3
- package/dist/core/auto-mode-prompt-assets.js +1 -1
- package/dist/core/checkpoint-store.d.ts +26 -1
- package/dist/core/hooks.d.ts +129 -2
- package/dist/core/hooks.js +20 -3
- package/dist/core/runner/prepare-config-doors.d.ts +17 -0
- package/dist/core/runner/prepare-config-doors.js +33 -2
- package/dist/core/runner/prepare-task.d.ts +17 -2
- package/dist/core/runner/prepare-task.js +124 -41
- package/dist/core/runner/runtask.js +46 -11
- package/dist/core/tool-model-gate.d.ts +125 -0
- package/dist/core/tool-model-gate.js +303 -0
- package/dist/core/tool-policy.d.ts +1 -1
- package/dist/core/types.d.ts +189 -1
- package/dist/core/types.js +21 -0
- package/dist/core/untrusted-text.d.ts +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/dist/orchestration/builtin-workflows.d.ts +68 -6
- package/dist/orchestration/builtin-workflows.js +26 -9
- package/dist/orchestration/run-workflow-tool.d.ts +10 -1
- package/dist/orchestration/run-workflow-tool.js +70 -27
- package/dist/orchestration/workflow-script-store.d.ts +8 -3
- package/dist/prompts/coordinator.d.ts +4 -1
- package/dist/prompts/coordinator.js +8 -0
- package/dist/prompts/default.d.ts +14 -4
- package/dist/prompts/default.js +2 -1
- package/dist/scenarios/full-body.d.ts +5 -0
- package/dist/scenarios/full-body.js +8 -4
- package/dist/tools/fs/fs-shared.d.ts +3 -2
- package/dist/tools/fs/fs-shared.js +19 -9
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +12 -1
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
export function modelIdTail(id) {
|
|
2
|
+
return id.toLowerCase().split("/").pop() ?? "";
|
|
3
|
+
}
|
|
4
|
+
export const TOOL_MODEL_GATE_CLASSES = Object.freeze({
|
|
5
|
+
"task-scaffold": Object.freeze({
|
|
6
|
+
floors: Object.freeze([
|
|
7
|
+
Object.freeze(["opus", Object.freeze([4, 8])]),
|
|
8
|
+
Object.freeze(["sonnet", Object.freeze([5])]),
|
|
9
|
+
Object.freeze(["fable", Object.freeze([5])]),
|
|
10
|
+
Object.freeze(["mythos", Object.freeze([5])]),
|
|
11
|
+
]),
|
|
12
|
+
}),
|
|
13
|
+
});
|
|
14
|
+
const CLAUDE_ID_RE = /^claude-([a-z]+)-(\d+(?:-\d+)*)$/;
|
|
15
|
+
function versionTupleGte(version, floor) {
|
|
16
|
+
const n = Math.max(version.length, floor.length);
|
|
17
|
+
for (let i = 0; i < n; i++) {
|
|
18
|
+
const v = version[i] ?? 0;
|
|
19
|
+
const f = floor[i] ?? 0;
|
|
20
|
+
if (v > f)
|
|
21
|
+
return true;
|
|
22
|
+
if (v < f)
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
export function isModelGatedForClass(modelId, rule) {
|
|
28
|
+
const tail = modelIdTail(modelId);
|
|
29
|
+
if (rule.modelIds !== undefined) {
|
|
30
|
+
for (const row of rule.modelIds) {
|
|
31
|
+
if (typeof row === "string" && tail === row.toLowerCase())
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (rule.floors !== undefined) {
|
|
36
|
+
const m = CLAUDE_ID_RE.exec(tail);
|
|
37
|
+
if (m !== null) {
|
|
38
|
+
const family = m[1] ?? "";
|
|
39
|
+
const version = (m[2] ?? "").split("-").map(Number);
|
|
40
|
+
for (const row of rule.floors) {
|
|
41
|
+
if (!Array.isArray(row) || row.length !== 2)
|
|
42
|
+
continue;
|
|
43
|
+
const [fam, floor] = row;
|
|
44
|
+
if (typeof fam !== "string" || fam.toLowerCase() !== family)
|
|
45
|
+
continue;
|
|
46
|
+
if (Array.isArray(floor) && versionTupleGte(version, floor))
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
function gateConfigError(message) {
|
|
54
|
+
const e = new Error(message);
|
|
55
|
+
e.code = "config.tool_model_gate_invalid";
|
|
56
|
+
return e;
|
|
57
|
+
}
|
|
58
|
+
export function assertRestoreGatedToolsValue(value) {
|
|
59
|
+
if (value === undefined || value === true)
|
|
60
|
+
return;
|
|
61
|
+
if (Array.isArray(value)) {
|
|
62
|
+
const entries = value;
|
|
63
|
+
for (const entry of entries) {
|
|
64
|
+
if (typeof entry !== "string") {
|
|
65
|
+
throw gateConfigError(`TaskSpec.restoreGatedTools entries must be strings (got ${describeValue(entry)}) — an unevaluable selector must not silently restore nothing.`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
throw gateConfigError(`TaskSpec.restoreGatedTools must be \`true\` or an array of tool names (got ${describeValue(value)}).`);
|
|
71
|
+
}
|
|
72
|
+
const isPlainObject = (v) => {
|
|
73
|
+
if (typeof v !== "object" || v === null || Array.isArray(v))
|
|
74
|
+
return false;
|
|
75
|
+
const proto = Object.getPrototypeOf(v);
|
|
76
|
+
return proto === Object.prototype || proto === null;
|
|
77
|
+
};
|
|
78
|
+
const describeValue = (v) => {
|
|
79
|
+
try {
|
|
80
|
+
const s = JSON.stringify(v);
|
|
81
|
+
return s === undefined ? String(v) : s;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return typeof v === "bigint" ? `${String(v)}n` : "[unserializable value]";
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
function mergeToolModelGateClasses(depsSeat) {
|
|
88
|
+
const merged = new Map();
|
|
89
|
+
for (const [cls, rule] of Object.entries(TOOL_MODEL_GATE_CLASSES))
|
|
90
|
+
merged.set(cls, rule);
|
|
91
|
+
if (depsSeat === undefined)
|
|
92
|
+
return merged;
|
|
93
|
+
if (!isPlainObject(depsSeat)) {
|
|
94
|
+
throw gateConfigError(`RunnerDeps.toolModelGate must be \`false\` or a plain object — prototype included (got ${Array.isArray(depsSeat) ? "an array" : describeValue(depsSeat)}).`);
|
|
95
|
+
}
|
|
96
|
+
for (const key of Object.keys(depsSeat)) {
|
|
97
|
+
if (key !== "classes") {
|
|
98
|
+
throw gateConfigError(`RunnerDeps.toolModelGate has unknown key ${JSON.stringify(key)} — the only legal key is "classes".`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const classes = Object.hasOwn(depsSeat, "classes") ? depsSeat.classes : undefined;
|
|
102
|
+
if (classes === undefined)
|
|
103
|
+
return merged;
|
|
104
|
+
if (!isPlainObject(classes)) {
|
|
105
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes must be a plain object (got ${Array.isArray(classes) ? "an array" : describeValue(classes)}).`);
|
|
106
|
+
}
|
|
107
|
+
for (const [cls, row] of Object.entries(classes)) {
|
|
108
|
+
if (cls === "")
|
|
109
|
+
throw gateConfigError("RunnerDeps.toolModelGate.classes has an empty-string class name.");
|
|
110
|
+
if (row === undefined)
|
|
111
|
+
continue;
|
|
112
|
+
if (!isPlainObject(row)) {
|
|
113
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}] must be a plain object (got ${Array.isArray(row) ? "an array" : describeValue(row)}).`);
|
|
114
|
+
}
|
|
115
|
+
for (const key of Object.keys(row)) {
|
|
116
|
+
if (key !== "floors" && key !== "modelIds") {
|
|
117
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}] has unknown key ${JSON.stringify(key)} — legal keys: "floors", "modelIds".`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
let floors;
|
|
121
|
+
if (row.floors !== undefined) {
|
|
122
|
+
if (!Array.isArray(row.floors)) {
|
|
123
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].floors must be an array (got ${describeValue(row.floors)}).`);
|
|
124
|
+
}
|
|
125
|
+
const seen = new Set();
|
|
126
|
+
const out = [];
|
|
127
|
+
const rows = row.floors;
|
|
128
|
+
for (const entry of rows) {
|
|
129
|
+
if (!Array.isArray(entry) || entry.length !== 2) {
|
|
130
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].floors rows must be [family, floor] pairs (got ${describeValue(entry)}).`);
|
|
131
|
+
}
|
|
132
|
+
const famRaw = entry[0];
|
|
133
|
+
const floorRaw = entry[1];
|
|
134
|
+
if (typeof famRaw !== "string" || famRaw.length === 0) {
|
|
135
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].floors family must be a non-empty string (got ${describeValue(famRaw)}).`);
|
|
136
|
+
}
|
|
137
|
+
const fam = famRaw.toLowerCase();
|
|
138
|
+
if (!/^[a-z]+$/.test(fam)) {
|
|
139
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].floors family ${JSON.stringify(famRaw)} cannot ever match — the canonical id shape only admits letters. Refused rather than kept as a dead row.`);
|
|
140
|
+
}
|
|
141
|
+
if (seen.has(fam)) {
|
|
142
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].floors lists family ${JSON.stringify(fam)} twice.`);
|
|
143
|
+
}
|
|
144
|
+
seen.add(fam);
|
|
145
|
+
const floorNums = [];
|
|
146
|
+
if (Array.isArray(floorRaw)) {
|
|
147
|
+
const floorEntries = floorRaw;
|
|
148
|
+
for (const n of floorEntries) {
|
|
149
|
+
if (typeof n === "number" && Number.isSafeInteger(n) && n >= 0)
|
|
150
|
+
floorNums.push(n);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (!Array.isArray(floorRaw) || floorRaw.length === 0 || floorNums.length !== floorRaw.length) {
|
|
154
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].floors floor for ${JSON.stringify(fam)} must be a non-empty array of non-negative safe integers (got ${describeValue(floorRaw)}).`);
|
|
155
|
+
}
|
|
156
|
+
out.push([fam, floorNums]);
|
|
157
|
+
}
|
|
158
|
+
floors = out;
|
|
159
|
+
}
|
|
160
|
+
let modelIds;
|
|
161
|
+
if (row.modelIds !== undefined) {
|
|
162
|
+
if (!Array.isArray(row.modelIds)) {
|
|
163
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].modelIds must be an array (got ${describeValue(row.modelIds)}).`);
|
|
164
|
+
}
|
|
165
|
+
const seen = new Set();
|
|
166
|
+
const out = [];
|
|
167
|
+
const ids = row.modelIds;
|
|
168
|
+
for (const entry of ids) {
|
|
169
|
+
if (typeof entry !== "string" || entry.length === 0) {
|
|
170
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].modelIds entries must be non-empty strings (got ${describeValue(entry)}).`);
|
|
171
|
+
}
|
|
172
|
+
const folded = entry.toLowerCase();
|
|
173
|
+
if (folded.includes("/")) {
|
|
174
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].modelIds entry ${JSON.stringify(entry)} contains "/" — matching is against the id's TAIL segment, so a prefixed row can never fire. Write the bare id.`);
|
|
175
|
+
}
|
|
176
|
+
if (seen.has(folded)) {
|
|
177
|
+
throw gateConfigError(`RunnerDeps.toolModelGate.classes[${JSON.stringify(cls)}].modelIds lists ${JSON.stringify(folded)} twice (case-folded).`);
|
|
178
|
+
}
|
|
179
|
+
seen.add(folded);
|
|
180
|
+
out.push(folded);
|
|
181
|
+
}
|
|
182
|
+
modelIds = out;
|
|
183
|
+
}
|
|
184
|
+
const base = merged.get(cls);
|
|
185
|
+
merged.set(cls, {
|
|
186
|
+
...(floors !== undefined ? { floors } : base?.floors !== undefined ? { floors: base.floors } : {}),
|
|
187
|
+
...(modelIds !== undefined ? { modelIds } : base?.modelIds !== undefined ? { modelIds: base.modelIds } : {}),
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return merged;
|
|
191
|
+
}
|
|
192
|
+
const ENV_OFF = new Set(["off", "0", "false"]);
|
|
193
|
+
const ENV_ON = new Set(["on", "1", "true"]);
|
|
194
|
+
export function applyToolModelGate(input) {
|
|
195
|
+
const noop = (discardedEnvRaw) => ({
|
|
196
|
+
survivors: undefined,
|
|
197
|
+
removedByClass: new Map(),
|
|
198
|
+
unknownClasses: [],
|
|
199
|
+
discardedEnvRaw,
|
|
200
|
+
});
|
|
201
|
+
let merged;
|
|
202
|
+
try {
|
|
203
|
+
if (input.depsSeat !== false && input.depsSeat !== undefined && !isPlainObject(input.depsSeat)) {
|
|
204
|
+
throw gateConfigError(`RunnerDeps.toolModelGate must be \`false\` or a plain object — prototype included (got ${describeValue(input.depsSeat)}).`);
|
|
205
|
+
}
|
|
206
|
+
merged = input.depsSeat === false ? undefined : mergeToolModelGateClasses(input.depsSeat);
|
|
207
|
+
}
|
|
208
|
+
catch (e) {
|
|
209
|
+
let code;
|
|
210
|
+
try {
|
|
211
|
+
code = e?.code;
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
code = undefined;
|
|
215
|
+
}
|
|
216
|
+
if (code !== undefined)
|
|
217
|
+
throw e;
|
|
218
|
+
let msg;
|
|
219
|
+
try {
|
|
220
|
+
msg = e instanceof Error ? e.message : String(e);
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
msg = "[unreportable throw]";
|
|
224
|
+
}
|
|
225
|
+
throw gateConfigError(`RunnerDeps.toolModelGate could not be read (${msg}) — a config seat whose reads throw is a bad value, refused rather than passed.`);
|
|
226
|
+
}
|
|
227
|
+
const raw = input.envRaw;
|
|
228
|
+
let envVerdict;
|
|
229
|
+
if (raw === undefined)
|
|
230
|
+
envVerdict = "absent";
|
|
231
|
+
else {
|
|
232
|
+
const tok = raw.toLowerCase();
|
|
233
|
+
envVerdict = ENV_OFF.has(tok) ? "off" : ENV_ON.has(tok) ? "on" : "invalid";
|
|
234
|
+
}
|
|
235
|
+
const invalidRaw = envVerdict === "invalid" ? raw : undefined;
|
|
236
|
+
if (merged === undefined)
|
|
237
|
+
return noop(invalidRaw);
|
|
238
|
+
if (envVerdict === "off")
|
|
239
|
+
return noop();
|
|
240
|
+
const tools = input.tools ?? [];
|
|
241
|
+
const stamped = [];
|
|
242
|
+
for (const entry of tools) {
|
|
243
|
+
if (entry.modelGate !== undefined)
|
|
244
|
+
stamped.push({ entry, cls: entry.modelGate });
|
|
245
|
+
}
|
|
246
|
+
if (stamped.length === 0)
|
|
247
|
+
return noop(invalidRaw);
|
|
248
|
+
const restoredClasses = new Set();
|
|
249
|
+
if (input.restoreGated === true) {
|
|
250
|
+
for (const s of stamped)
|
|
251
|
+
restoredClasses.add(s.cls);
|
|
252
|
+
}
|
|
253
|
+
else if (input.restoreGated !== undefined) {
|
|
254
|
+
const names = new Set(input.restoreGated);
|
|
255
|
+
for (const s of stamped)
|
|
256
|
+
if (names.has(s.entry.name))
|
|
257
|
+
restoredClasses.add(s.cls);
|
|
258
|
+
}
|
|
259
|
+
const unknownClasses = [];
|
|
260
|
+
const unknownSeen = new Set();
|
|
261
|
+
const removed = new Set();
|
|
262
|
+
const removedByClass = new Map();
|
|
263
|
+
for (const { entry, cls } of stamped) {
|
|
264
|
+
const rule = merged.get(cls);
|
|
265
|
+
if (rule === undefined) {
|
|
266
|
+
if (!unknownSeen.has(cls)) {
|
|
267
|
+
unknownSeen.add(cls);
|
|
268
|
+
unknownClasses.push(cls);
|
|
269
|
+
}
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (rule.floors === undefined && rule.modelIds === undefined)
|
|
273
|
+
continue;
|
|
274
|
+
if (restoredClasses.has(cls))
|
|
275
|
+
continue;
|
|
276
|
+
if (!isModelGatedForClass(input.modelId, rule))
|
|
277
|
+
continue;
|
|
278
|
+
removed.add(entry);
|
|
279
|
+
const list = removedByClass.get(cls) ?? [];
|
|
280
|
+
if (!list.includes(entry.name))
|
|
281
|
+
list.push(entry.name);
|
|
282
|
+
removedByClass.set(cls, list);
|
|
283
|
+
}
|
|
284
|
+
if (invalidRaw !== undefined) {
|
|
285
|
+
if (removed.size > 0) {
|
|
286
|
+
const e = new Error(`SEMA_TOOL_MODEL_GATE=${JSON.stringify(invalidRaw)} is not in the closed set (on|1|true|off|0|false, case-insensitive) and IS in force on this task (the model gate would remove default-mounted tool(s)). Refused rather than guessed — "off" mistyped must not silently keep the trim armed.`);
|
|
287
|
+
e.code = "config.tool_model_gate_env_invalid";
|
|
288
|
+
throw e;
|
|
289
|
+
}
|
|
290
|
+
return { survivors: undefined, removedByClass: new Map(), unknownClasses, discardedEnvRaw: invalidRaw };
|
|
291
|
+
}
|
|
292
|
+
if (removed.size === 0) {
|
|
293
|
+
return { survivors: undefined, removedByClass: new Map(), unknownClasses, discardedEnvRaw: undefined };
|
|
294
|
+
}
|
|
295
|
+
for (const list of removedByClass.values())
|
|
296
|
+
list.sort();
|
|
297
|
+
return {
|
|
298
|
+
survivors: tools.filter((t) => !removed.has(t)),
|
|
299
|
+
removedByClass,
|
|
300
|
+
unknownClasses,
|
|
301
|
+
discardedEnvRaw: undefined,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
@@ -866,7 +866,7 @@ export interface AskRequest {
|
|
|
866
866
|
* run's model: a parent-thread run is told to stop and wait for the user (its transcript has a
|
|
867
867
|
* user turn coming), a delegated child is told to adapt or report the limitation. A fork is
|
|
868
868
|
* deliberately IN: it inherits the parent's authority (design/110 — which is why the RB-330
|
|
869
|
-
* `
|
|
869
|
+
* non-fork facet of `effectiveDelegationFacts`, serving the authority/context faces, excludes it), but
|
|
870
870
|
* its interaction contract is one-shot — "report once and stop … no waiting for the user"
|
|
871
871
|
* (FORK_DIRECTIVE_FRAME) — so a stop-and-wait refusal would instruct it to do the impossible
|
|
872
872
|
* (codex adversarial round, confirmed). NOT the same fact as {@link fromSubagent} either: that is
|
package/dist/core/types.d.ts
CHANGED
|
@@ -381,6 +381,25 @@ export interface ToolSpec<TParams extends TSchema = TSchema> {
|
|
|
381
381
|
* Exclusion still wins ({@link TaskSpec.excludeTools} unmounts — nothing left to keep inline).
|
|
382
382
|
*/
|
|
383
383
|
alwaysLoad?: boolean;
|
|
384
|
+
/**
|
|
385
|
+
* design/277 — model-gate CLASS tag (open vocabulary; the built-in table is
|
|
386
|
+
* {@link import("./tool-model-gate.js").TOOL_MODEL_GATE_CLASSES}, v1 vocabulary =
|
|
387
|
+
* `"task-scaffold"`). A tagged entry declares "I am a default-mounted scaffold of this class":
|
|
388
|
+
* at prepare, when the task's RESOLVED model id matches the class's rule, THIS entry is dropped
|
|
389
|
+
* from the roster (true unmount, entry-level — a same-name untagged entry is untouched; the
|
|
390
|
+
* removed entry stops occupying its name on every downstream surface). Untagged = never gated.
|
|
391
|
+
* The default-bundle assemblers stamp their default arms only; an EXPLICITLY composed tool is
|
|
392
|
+
* not tagged (user asked ⇒ user gets) — so don't stamp hand-mounted factories. FAIL-OPEN: an id
|
|
393
|
+
* the merged table knows nothing about is never gated (BYOM open set — the table encodes
|
|
394
|
+
* positive knowledge only), and a tag naming an unknown class is inert + announced
|
|
395
|
+
* (`config.tool_model_gate_unknown_class`). Restore channels: explicit composition (no tag),
|
|
396
|
+
* {@link TaskSpec.restoreGatedTools}, env `SEMA_TOOL_MODEL_GATE=off`,
|
|
397
|
+
* `RunnerDeps.toolModelGate: false`; {@link TaskSpec.excludeTools} always wins regardless.
|
|
398
|
+
* The materialized `AgentTool` face does NOT carry this field (`defineTool` is a whitelist
|
|
399
|
+
* constructor) — the decision completes on the ToolSpec face inside `prepareConfigDoors`,
|
|
400
|
+
* before any conversion.
|
|
401
|
+
*/
|
|
402
|
+
modelGate?: string;
|
|
384
403
|
/**
|
|
385
404
|
* Tool contract identity (campaign S2, prompt-assembly protocol §7): declares the EXECUTION
|
|
386
405
|
* CONTRACT this tool implements, independent of its presentation text. `defineTool` attaches it
|
|
@@ -751,6 +770,13 @@ export interface ToolExecuteContext {
|
|
|
751
770
|
* X arrives deferred, the exemption having been dropped in transit — which is the one outcome the
|
|
752
771
|
* parent explicitly ruled out. Children merge this with their own spec value. */
|
|
753
772
|
alwaysLoadTools?: readonly string[];
|
|
773
|
+
/** design/277 — the model-gate restore selector ({@link TaskSpec.restoreGatedTools}), inherited
|
|
774
|
+
* down the delegation tree on the same trusted seat as the three tool-face controls above
|
|
775
|
+
* (Runner-filled, read-only, frozen snapshot). Restoration is a TASK-TREE intent ("this work
|
|
776
|
+
* wants the scaffold back") and each child re-judges the gate under its OWN resolved model —
|
|
777
|
+
* dropping the selector in transit would trim a same-model child's roster in a way nobody
|
|
778
|
+
* chose (the gate is a default, not a policy; there is no tighten-only axis to protect). */
|
|
779
|
+
restoreGatedTools?: readonly string[] | true;
|
|
754
780
|
/** R2 双形轴 — the parent's resolved prompt profile, inherited down the delegation tree like the
|
|
755
781
|
* tool-face controls (Runner-filled): a classic-profile parent's children speak classic too
|
|
756
782
|
* unless the child spec says otherwise (child spec wins — profile is presentation, not policy). */
|
|
@@ -1867,6 +1893,24 @@ export interface TaskSpec {
|
|
|
1867
1893
|
* wins — an unmounted tool has no schema to keep inline).
|
|
1868
1894
|
*/
|
|
1869
1895
|
alwaysLoadTools?: string[];
|
|
1896
|
+
/**
|
|
1897
|
+
* design/277 — per-task restore valve for the tool-registration MODEL GATE. The gate trims
|
|
1898
|
+
* default-mounted scaffold entries (tagged via {@link ToolSpec.modelGate}) from the roster when
|
|
1899
|
+
* the task's resolved model id matches the gate table — this valve opts the task (and its whole
|
|
1900
|
+
* delegation tree — the selector inherits down like `excludeTools`) back in:
|
|
1901
|
+
* · an ARRAY of wire names — naming ANY tagged tool restores that tool's WHOLE class for this
|
|
1902
|
+
* task (CC parity: opting into any member of the family restores the family). Judged against
|
|
1903
|
+
* the full stamp set, so a name that `excludeTools` also lists still works as a class
|
|
1904
|
+
* SELECTOR — while the exclusion itself still wins for that name (exclusion is the final
|
|
1905
|
+
* valve; no restore channel resurrects an excluded name). Unknown names are inert (a
|
|
1906
|
+
* center-distributed list may be a superset), same posture as `excludeTools`.
|
|
1907
|
+
* · literal `true` — every gate class restored for this task (the shortest "this task wants
|
|
1908
|
+
* all its scaffolding" spelling for center-distributed specs).
|
|
1909
|
+
* A malformed value refuses at prepare (`config.tool_model_gate_invalid`, #123) — garbage must
|
|
1910
|
+
* not silently read as "restore nothing" in the trimming direction. Absent = the gate's verdict
|
|
1911
|
+
* stands. Explicit composition needs no valve: a hand-mounted (untagged) tool is never gated.
|
|
1912
|
+
*/
|
|
1913
|
+
restoreGatedTools?: string[] | true;
|
|
1870
1914
|
/**
|
|
1871
1915
|
* RB-403 — whether a schema-VALID call on a still-deferred tool runs the real tool directly
|
|
1872
1916
|
* (activating it as a side effect). Default `true`, matching the upstream posture where the
|
|
@@ -4440,6 +4484,93 @@ export interface BackgroundChildEvent {
|
|
|
4440
4484
|
costMicroUsd?: number;
|
|
4441
4485
|
};
|
|
4442
4486
|
}
|
|
4487
|
+
/**
|
|
4488
|
+
* #281 件B — one lifecycle phase of a DELEGATED child leg, delivered to the process-level
|
|
4489
|
+
* {@link RunnerDeps.onDelegationLifecycle} observer: the public, deps-level home of the delegation
|
|
4490
|
+
* lifecycle that previously lived only on the trusted RunInternals third parameter
|
|
4491
|
+
* (`onSubagentSpawn` — sync lane, a steer handle whose `settled` is a void promise) and on the
|
|
4492
|
+
* background-lane-only {@link BackgroundChildEvent}. A deployment wired ONLY through `RunnerDeps`
|
|
4493
|
+
* now sees every delegation lane through one seat.
|
|
4494
|
+
*
|
|
4495
|
+
* EMISSION CHOKEPOINT (the reason this seat covers every lane at once): frames are minted by the
|
|
4496
|
+
* RUNNER at the child LEG itself — spawn right after the leg's `wiring_manifest` (prepared, nothing
|
|
4497
|
+
* run yet), terminal when the leg's `TaskResult` assembles — not by the individual spawn lanes. Every
|
|
4498
|
+
* delegation lane (sync/steer/background/fork/revive, workflow-spawned agents) runs its child through
|
|
4499
|
+
* this chokepoint, so none of them needs its own emission and none can drift.
|
|
4500
|
+
*
|
|
4501
|
+
* PER-LEG semantics, deliberately: a durable park + resume, or a retained child's revive, is a NEW
|
|
4502
|
+
* leg — each emits its own spawn/terminal pair, and `identity.legKind` (`"resume"`) says which cycle
|
|
4503
|
+
* a frame belongs to. Consumers correlate legs of one delegation by `identity.taskId` /
|
|
4504
|
+
* `identity.parentToolCallId` (stable across cycles).
|
|
4505
|
+
*
|
|
4506
|
+
* HONEST ABSENCES (recorded, not gaps to fix silently):
|
|
4507
|
+
* · a child whose PREPARE throws emits neither frame (there is no leg identity to report);
|
|
4508
|
+
* · the ROOT leg emits nothing here — the deployment called `runTask` itself and holds the result;
|
|
4509
|
+
* this seat is the delegation observer, not a run observer;
|
|
4510
|
+
* · a deps-only resume (`resume(token, outcome, config)` — no trusted internals re-supplied) of a
|
|
4511
|
+
* checkpoint minted BEFORE the delegation axis was persisted
|
|
4512
|
+
* ({@link import("./checkpoint-store.js").CheckpointState.isDelegatedChild}) emits neither frame:
|
|
4513
|
+
* the row carries no evidence the parked leg was a delegated child, and fabricating the axis
|
|
4514
|
+
* would stamp delegation frames onto host-resumed root tasks. Rows minted WITH the axis resume
|
|
4515
|
+
* with their spawn/terminal pair even deps-only; a resume that re-supplies trusted internals
|
|
4516
|
+
* (every in-engine lane does) was never affected.
|
|
4517
|
+
* PAIRING (codex r2-D2 closed the one hole): a spawn frame is always closed by a terminal frame —
|
|
4518
|
+
* the ordinary path emits it where the `TaskResult` assembles, and a POST-SPAWN throw that the
|
|
4519
|
+
* stream layer converts into a synthesized failed result (e.g. `resume.tool_unavailable` re-thrown
|
|
4520
|
+
* past the run tail) emits the failed terminal from that backstop, gated on a carrier that is set
|
|
4521
|
+
* only after the spawn emission and cleared by the ordinary terminal (so the two sites can never
|
|
4522
|
+
* both fire for one leg). A leg whose PROCESS dies mid-flight is the only unpaired spawn.
|
|
4523
|
+
*
|
|
4524
|
+
* OBSERVATION ONLY (matrix §5.2 Q3: frame-rate lifecycle facts ride an observer seat, never
|
|
4525
|
+
* onNotice): no return capability, and delivery can never alter the child run —
|
|
4526
|
+
* {@link deliverDelegationLifecycle} contains a throwing sink and an async sink's rejection alike.
|
|
4527
|
+
*
|
|
4528
|
+
* FRAME OBJECT SHAPE (consumer contract, not an implementation detail): every delivered frame is
|
|
4529
|
+
* FROZEN and carries a NULL PROTOTYPE — re-minted at the one delivery point so a forged member
|
|
4530
|
+
* cannot ride a frame through a writable `Object.prototype`, the same rule (and the same trade) as
|
|
4531
|
+
* the {@link import("./hooks.js").HookInvocationIdentity} envelope inside it. `Object.keys`, spread,
|
|
4532
|
+
* JSON serialization and direct member reads (`frame.status`) all behave normally, but
|
|
4533
|
+
* `frame instanceof Object` is `false` and inherited methods are ABSENT — probe optional members
|
|
4534
|
+
* with `Object.hasOwn(frame, "errorCode")` or `"errorCode" in frame`, never
|
|
4535
|
+
* `frame.hasOwnProperty(...)` (throws) or implicit string coercion (`` `${frame}` `` throws).
|
|
4536
|
+
*/
|
|
4537
|
+
export type DelegationLifecycleEvent = {
|
|
4538
|
+
phase: "spawn";
|
|
4539
|
+
/** The child LEG's identity envelope (#281 件A — the same frozen object that leg's own hook
|
|
4540
|
+
* invocations carry). `isDelegatedChild` is `true` by construction on every frame here. */
|
|
4541
|
+
identity: import("./hooks.js").HookInvocationIdentity;
|
|
4542
|
+
} | {
|
|
4543
|
+
phase: "terminal";
|
|
4544
|
+
/** Same envelope as the leg's spawn frame (one mint per leg). */
|
|
4545
|
+
identity: import("./hooks.js").HookInvocationIdentity;
|
|
4546
|
+
/** The leg's settled status — the `TaskResult.status` the spawning lane receives, verbatim
|
|
4547
|
+
* (the sync lane's previously-void `settled` payload, made public). `"suspended"` means a
|
|
4548
|
+
* durable park: expect a later `"resume"`-leg spawn/terminal pair if it is redeemed. */
|
|
4549
|
+
status: TaskResult["status"];
|
|
4550
|
+
/** Turns the leg completed. */
|
|
4551
|
+
turns: number;
|
|
4552
|
+
/** The leg's `TaskResult.errorCode`, when one was stamped. */
|
|
4553
|
+
errorCode?: string;
|
|
4554
|
+
};
|
|
4555
|
+
/** Test seam (mirrors `__resetMalformedNoticeSeatAnnouncement`): never called by production code. */
|
|
4556
|
+
export declare function __resetMalformedDelegationSeatAnnouncement(): void;
|
|
4557
|
+
/**
|
|
4558
|
+
* The ONE delivery form behind every {@link RunnerDeps.onDelegationLifecycle} emission point (both
|
|
4559
|
+
* runner stations — spawn and terminal — call this; a second spelling of the swallow/announce rules
|
|
4560
|
+
* would be the #170 triplication reborn). Contract:
|
|
4561
|
+
* · a FUNCTION seat is invoked with the frame FROZEN (a mutating observer must not rewrite what a
|
|
4562
|
+
* later frame consumer — or the shared identity envelope's other readers — see), contained in the
|
|
4563
|
+
* caller's {@link SafeNotifier} against BOTH failure shapes the void-typed seat admits: a
|
|
4564
|
+
* synchronous throw ({@link SafeNotifier.notify}) and an async sink's rejected promise
|
|
4565
|
+
* ({@link observeThenableRejection} routes it back through the same notifier/site — the #253
|
|
4566
|
+
* three-station form). A broken observer never faults the child run.
|
|
4567
|
+
* · a PRESENT NON-function seat is a bad deployment value; #123 forbids folding it to silence. There
|
|
4568
|
+
* is no per-frame console fallback (this is a frame-rate observer stream, not an announcement
|
|
4569
|
+
* channel — an unwired seat means UNOBSERVED, and echoing every spawn to stderr would flood), so
|
|
4570
|
+
* the loud exit is the seat DEFECT itself: announced via `console.warn` once per process.
|
|
4571
|
+
* · an ABSENT seat is a plain no-op (the deployment chose not to observe).
|
|
4572
|
+
*/
|
|
4573
|
+
export declare function deliverDelegationLifecycle(seat: RunnerDeps["onDelegationLifecycle"], event: DelegationLifecycleEvent, notifier: import("./safe-notify.js").SafeNotifier, site: string): void;
|
|
4443
4574
|
/**
|
|
4444
4575
|
* parity-204 — structured `RunnerDeps.loadProjectMemory` return (backward-compatible: a bare
|
|
4445
4576
|
* `string | null` keeps its exact historical meaning). Adds the CC 2.1.204 `seededFromContext`
|
|
@@ -4519,6 +4650,24 @@ export interface EngineNotice {
|
|
|
4519
4650
|
* a library-direct `createHandsToolkit` mount announces at toolkit creation (one per mount,
|
|
4520
4651
|
* through the band-local `HandsToolkitOptions.onNotice` seat, absent ⇒ `console.warn`);
|
|
4521
4652
|
* `detail: { seat, declared, inForce, cause }`.
|
|
4653
|
+
* - `"config.tool_model_gate_removed"` (design/277) — the model gate trimmed default-mounted
|
|
4654
|
+
* scaffold entries from a task's roster. One notice per (model, class), de-duplicated once per
|
|
4655
|
+
* `onNotice` SINK on the (modelId, class, canonical sorted removed-name set) line (same unit
|
|
4656
|
+
* as `config.read_face_deployment_clamped`: two deployments hosted in one process each hear
|
|
4657
|
+
* their own trim; unwired console arm once per process) — same class with a different removal
|
|
4658
|
+
* shape is a distinct fact and announces again;
|
|
4659
|
+
* `detail: { modelId, gateClass, removed, restore }` (`restore` names the three valves).
|
|
4660
|
+
* - `"config.tool_model_gate_unknown_class"` (design/277) — a `ToolSpec.modelGate` tag names a
|
|
4661
|
+
* class the merged gate table has no row for: the tag is inert (fail-open — the tool stays
|
|
4662
|
+
* mounted) and this is its loud half (a tag typo must not silently become "never gated" with
|
|
4663
|
+
* nobody told). Once per `onNotice` sink per class (console arm once per process);
|
|
4664
|
+
* `detail: { gateClass }`.
|
|
4665
|
+
* - `"config.tool_model_gate_env_invalid"` (design/277, the NOTICE dialect of the same fact the
|
|
4666
|
+
* refusal code carries) — `SEMA_TOOL_MODEL_GATE` holds a value outside `on|1|true|off|0|false`
|
|
4667
|
+
* in a seat where it is NOT in force (nothing this prepare would gate): announced once per
|
|
4668
|
+
* `onNotice` sink per value (console arm once per process) instead of lying in wait; where the
|
|
4669
|
+
* value IS in force the prepare refuses with the same code as `TaskResult.errorCode` (one
|
|
4670
|
+
* fact, one code, two loudness dialects); `detail: { raw }`.
|
|
4522
4671
|
*
|
|
4523
4672
|
* Deliberately NOT a notice family: brain retry/reconnect liveness (a rate limit, a 5xx, a
|
|
4524
4673
|
* transient network failure being retried). Those are per-attempt liveness frames with their own
|
|
@@ -4874,6 +5023,23 @@ export interface RunnerDeps {
|
|
|
4874
5023
|
* completion pushes from it. Observability only — a throwing observer is swallowed, never faults a run.
|
|
4875
5024
|
*/
|
|
4876
5025
|
onBackgroundChildEvent?: (event: BackgroundChildEvent) => void;
|
|
5026
|
+
/**
|
|
5027
|
+
* #281 件B — PROCESS-level observer for EVERY delegated child leg's lifecycle (`spawn`/`terminal`),
|
|
5028
|
+
* all delegation lanes at once: synchronous and steer-handle delegations (whose spawn/settle
|
|
5029
|
+
* previously reached only the trusted `RunInternals.onSubagentSpawn` third parameter — and whose
|
|
5030
|
+
* `settled` is a void promise), background/fork/revive children (whose {@link BackgroundChildEvent}
|
|
5031
|
+
* family this seat complements, not replaces — BCE stays the fleet-row lane with registry `a*`
|
|
5032
|
+
* handles and ticks; this seat is the leg-identity lane), and workflow-spawned agents. Frames are
|
|
5033
|
+
* minted at the child leg's own runner chokepoint and carry the #281 件A identity envelope plus a
|
|
5034
|
+
* terminal status summary — see {@link DelegationLifecycleEvent} for the emission points, the
|
|
5035
|
+
* per-leg semantics and the recorded honest absences. Wire it once at Runner construction; a
|
|
5036
|
+
* deployment needs NO RunInternals access to observe delegation any more. Observation only — a
|
|
5037
|
+
* throwing or rejecting observer is contained ({@link deliverDelegationLifecycle}) and never
|
|
5038
|
+
* faults the child run; a PRESENT non-function value here is announced once per process and the
|
|
5039
|
+
* frames are simply not delivered (#123 — a bad seat must be loud, and this stream's loud exit is
|
|
5040
|
+
* the seat defect, not a per-frame console flood).
|
|
5041
|
+
*/
|
|
5042
|
+
onDelegationLifecycle?: (event: DelegationLifecycleEvent) => void;
|
|
4877
5043
|
/**
|
|
4878
5044
|
* design/98 (S8) — the HARD sandbox seam for LLM-AUTHORED workflow scripts (`TaskSpec.selfOrchestration`).
|
|
4879
5045
|
* A deployment supplies an isolated-vm / separate-process runner whose `safeForUntrustedScripts === true`;
|
|
@@ -4961,7 +5127,7 @@ export interface RunnerDeps {
|
|
|
4961
5127
|
* resolves a saved workflow, and a registration's `defaultArgs` merge under the call-time args. Opt-in
|
|
4962
5128
|
* (absent ⇒ inline `script` + built-in names only). */
|
|
4963
5129
|
workflowScriptStore?: import("../orchestration/workflow-script-store.js").WorkflowScriptStore;
|
|
4964
|
-
/** design/140 §6 1c — `false` removes the BUILT-IN named workflows (`
|
|
5130
|
+
/** design/140 §6 1c — `false` removes the BUILT-IN named workflows (`discussion`, …) from the
|
|
4965
5131
|
* auto-mounted run_workflow tool (the `builtinAgents:false` analog; default ON). A deployment
|
|
4966
5132
|
* `workflowScriptStore` registration of the same name shadows a built-in regardless. */
|
|
4967
5133
|
builtinWorkflows?: boolean;
|
|
@@ -5142,6 +5308,28 @@ export interface RunnerDeps {
|
|
|
5142
5308
|
mcpImageResizer?: import("./mcp.js").McpImageResizer;
|
|
5143
5309
|
/** Default tool-call gate for all tasks (a task's own `toolPolicy` overrides this). */
|
|
5144
5310
|
toolPolicy?: import("./tool-policy.js").ToolPolicy;
|
|
5311
|
+
/**
|
|
5312
|
+
* design/277 — the deployment seat of the tool-registration MODEL GATE (default ON; the gate
|
|
5313
|
+
* itself only ever touches entries tagged via {@link ToolSpec.modelGate}, so an untagged roster
|
|
5314
|
+
* is byte-identical under any value here):
|
|
5315
|
+
* · `false` — deployment kill switch: the gate never trims anything.
|
|
5316
|
+
* · `{ classes }` — per-class rule rows merged into the built-in table
|
|
5317
|
+
* ({@link import("./tool-model-gate.js").TOOL_MODEL_GATE_CLASSES}) PER AXIS: a present
|
|
5318
|
+
* `floors`/`modelIds` axis REPLACES that axis, an absent axis INHERITS the built-in one — so
|
|
5319
|
+
* a row adding only `modelIds` (the BYOM channel for gating a deployment's own strong model)
|
|
5320
|
+
* keeps the built-in claude floors armed. `floors: []` / `modelIds: []` are the EXPLICIT
|
|
5321
|
+
* per-axis clears; a class whose merged rule has both axes empty gates nothing (legal
|
|
5322
|
+
* per-class off). New class names extend the open vocabulary for deployment-authored tags.
|
|
5323
|
+
* The legality set is CLOSED (#123): any other shape — array/null/true seat, unknown keys at
|
|
5324
|
+
* either level, malformed floors/modelIds rows, families that can never match the canonical id
|
|
5325
|
+
* grammar, duplicate families/ids, `/`-prefixed ids — refuses the prepare loudly
|
|
5326
|
+
* (`config.tool_model_gate_invalid`), never folds to a guess. Process-level counterpart: env
|
|
5327
|
+
* `SEMA_TOOL_MODEL_GATE=off`. Removals are announced per (model, class) through `onNotice`
|
|
5328
|
+
* (`config.tool_model_gate_removed`) — a silent default-face trim is forbidden (#237).
|
|
5329
|
+
*/
|
|
5330
|
+
toolModelGate?: false | {
|
|
5331
|
+
classes?: Record<string, import("./tool-model-gate.js").ToolModelGateRule>;
|
|
5332
|
+
};
|
|
5145
5333
|
/** Deployment default for {@link TaskSpec.basePolicyForResumeEdit} (#93 / F-012 L3): the resume-edit
|
|
5146
5334
|
* re-adjudication override. Resolution: `spec.basePolicyForResumeEdit ?? THIS ?? (spec.toolPolicy ??
|
|
5147
5335
|
* deps.toolPolicy)` — absence falls back to the caller policy, never to a silent skip. */
|
package/dist/core/types.js
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
import { observeThenableRejection } from "./safe-notify.js";
|
|
2
|
+
let malformedDelegationSeatAnnounced = false;
|
|
3
|
+
export function __resetMalformedDelegationSeatAnnouncement() {
|
|
4
|
+
malformedDelegationSeatAnnounced = false;
|
|
5
|
+
}
|
|
6
|
+
export function deliverDelegationLifecycle(seat, event, notifier, site) {
|
|
7
|
+
if (typeof seat === "function") {
|
|
8
|
+
const frame = Object.freeze(Object.assign(Object.create(null), event));
|
|
9
|
+
notifier.notify(() => observeThenableRejection(seat(frame), notifier, site), site);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (seat !== undefined && !malformedDelegationSeatAnnounced) {
|
|
13
|
+
malformedDelegationSeatAnnounced = true;
|
|
14
|
+
try {
|
|
15
|
+
console.warn(`The delegation-lifecycle sink (RunnerDeps.onDelegationLifecycle) holds ${seat === null ? "null" : typeof seat} — not a ` +
|
|
16
|
+
`function. Delegation spawn/terminal frames are NOT delivered until the wiring is fixed (omit the key, or wire a function).`);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
1
22
|
let malformedNoticeSeatAnnounced = false;
|
|
2
23
|
export function __resetMalformedNoticeSeatAnnouncement() {
|
|
3
24
|
malformedNoticeSeatAnnounced = false;
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* model-facing instructions. Always neutralizes `<system-reminder>` / `</system-reminder>` (the codebase's
|
|
22
22
|
* elevated-authority wrapper) by inserting a zero-width space after the leading `<`. Pass `extraTags` to also
|
|
23
23
|
* neutralize a CALLER's own data-framing tags — e.g. `team.ts` embeds member output inside `<statement>` /
|
|
24
|
-
* `<
|
|
24
|
+
* `<discussion>`, so an untrusted member could emit `</statement>` to break out (search [46] BUG2);
|
|
25
25
|
* the caller passes those tag names. Tag names must be literal (alphanumeric/hyphen) — they are code-supplied
|
|
26
26
|
* wrapper names, never untrusted input. Idempotent for prompt assembly (a defused tag no longer matches).
|
|
27
27
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { createWebFetchTool, webFetchToolSpec, htmlToText, type WebFetchConfig,
|
|
|
21
21
|
export { createTodoWriteTool } from "./tools/todo.js";
|
|
22
22
|
export { createTaskListTools, createMemoryTaskListStore, assertJsonMetadata, type TaskListItem, type TaskListStore } from "./tools/task-list.js";
|
|
23
23
|
export { assembleCodeTools, type CodeToolsConfig, CODE_ROLE } from "./scenarios/full-body.js";
|
|
24
|
+
export { TOOL_MODEL_GATE_CLASSES, isModelGatedForClass, type ToolModelGateRule } from "./core/tool-model-gate.js";
|
|
24
25
|
export { capAggregateToolResults, AGGREGATE_TOOL_RESULT_BUDGET_CHARS, DEFAULT_BUDGET_EXEMPT_TOOLS, type AggregateBudgetOptions, } from "./core/tool-result-budget.js";
|
|
25
26
|
export { capAggregateMediaBytes, AGGREGATE_MEDIA_BUDGET_BYTES, type MediaStripInfo } from "./core/media-byte-cap.js";
|
|
26
27
|
export { createAskUserQuestionTool, createDurableQuestionPolicy, QUESTION_AWAITS_RESUME, isQuestionUnavailable, type OnQuestionOutcome, type QuestionUnavailable, type OnQuestion, type AskQuestion, type AskQuestionOption, type AskQuestionRequest, type QuestionAnswer, type QuestionAnswerItem, type AskQuestionCardDetails, type AskUserQuestionToolOptions, type AskAnswerContinuationSource, type SyntheticContinuationReason, } from "./core/ask-question.js";
|
|
@@ -162,7 +163,7 @@ export { FilePermissionRuleStoreProvider } from "./stores/file/permission-rule-s
|
|
|
162
163
|
export { adoptFilePermissionRuleStore, type AdoptFileRuleStoreResult } from "./stores/file/permission-rule-adopt.js";
|
|
163
164
|
export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootAdoptionFile, ROOT_ADOPTION_FILE, type AdoptionErrorCode, type AdoptionSource, type AdoptionReport, type AdoptionReceipt, type AdoptionLegReport, type AffectedDeploymentConfig, type RootAdoptionFile, } from "./stores/file/adoption/marker.js";
|
|
164
165
|
export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, type AdoptionStatus, type AdoptLocalDataRootOptions, type AdoptLocalDataRootResult, type AdoptionCarriageLeg, type AdoptionCarriageLegContext, type AdoptionConfigWitnessReceipt, } from "./stores/file/adoption/adopt.js";
|
|
165
|
-
export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, type PersistedRuleHit, type PersistedRuleUnreadable, type PersistedRuleAnswer, normalizePersistedRuleHit, type Hooks, type HookToolContext, type HookEnvCapabilities, type HookToolOutput, type PreToolUseResult, type PostToolUseResult, type UserPromptSubmitResult, type HookToolFailure, type PostToolUseFailureResult, type PostToolBatchCall, type PostToolBatchResult, type PreCompactContext, type PreCompactResult, type PostCompactContext, type StopFailureContext, type PermissionDeniedPayload, type PermissionDeniedSource, } from "./core/hooks.js";
|
|
166
|
+
export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, type PersistedRuleHit, type PersistedRuleUnreadable, type PersistedRuleAnswer, normalizePersistedRuleHit, type Hooks, type HookToolContext, type HookInvocationIdentity, type UserPromptSubmitContext, type PostToolBatchContext, type HookEnvCapabilities, type HookToolOutput, type PreToolUseResult, type PostToolUseResult, type UserPromptSubmitResult, type HookToolFailure, type PostToolUseFailureResult, type PostToolBatchCall, type PostToolBatchResult, type PreCompactContext, type PreCompactResult, type PostCompactContext, type StopFailureContext, type PermissionDeniedPayload, type PermissionDeniedSource, } from "./core/hooks.js";
|
|
166
167
|
export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, type NormalizedMemorySpec, type MemorySpecInput, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, type Embedder, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, type UtilityGate, type MemoryStore, type MemoryVectorMode, type ScoredMemory, type MemoryNoteHeader, type MemoryNoteRecord, type MemoryNoteType, type StructuredNoteInput, } from "./core/memory.js";
|
|
167
168
|
export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, type MemoryBackendContractHooks, buildMemoryInstruction, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_PREFERENCE_DISCIPLINE, MEMORY_READONLY_NOTICE, readV2HeaderHints, type V2HeaderHints, LINEAGE_FILE, CHALLENGES_FILE, CHALLENGED_HISTORY_FILE, CHALLENGE_LEDGER_MAX_EVENTS, rebuildStrictControlPlaneLedger, type ControlPlaneRebuildReceipt, type StrictControlPlaneLedger, type ChallengeAssignment, type ChallengeEvent, type ChallengedHistoryRow, type LineagePendingTxn, type LineagePromotion, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, type MemorySearchDetails, type MemorySearchHit, type MemoryGetDetails, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, type MemoryAnnouncement, type ScanFinding, type MemoryEngineOptions, type MemoryInjection, type EntryProvenanceAccount, type TransferEvidence, type CommittedBinding, type CommittedEntrySnapshot, type CommittedScopeSnapshots, type EntryCustodyReport, erasureSelectHash, type EraseMemoryEntriesInput, type ErasureSelect, type ErasedBinding, type MemoryErasureAttestation, type MemoryBackend, type MemoryEntry, type MemoryEntryFrontmatter, type MemoryEntryHeader, type ScoredMemoryEntry, type NotePatch, type PatchReport, type MaterializedFile, type MemorySessionHandle, type HarvestReport, type HarvestRejection, type HarvestRejectionCode, type ParsedEntryFile, type ScannedEntryFile, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, type ParsedScopeKey, migrateScope, type MigrateScopeReport, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, type RemoteMemoryFile, type RemoteMemoryBaseline, type RemoteMaterialization, type RemoteHarvestResult, type InboundEntryFinding, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, type MemorySyncCursor, type MemorySyncConflict, type MemorySyncPlan, type RecallSource, syncMemoryScope, type MemorySyncTransport, type MemorySyncRequestBody, type MemorySyncResponseBody, type MemorySyncClientConflict, type SyncMemoryScopeOptions, type MemorySyncClientResult, } from "./core/memory-engine/index.js";
|
|
168
169
|
export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, type SharedMemoryStoreProvider, type SharedMemoryStoreReader, type SharedMemoryPagedList, type SharedMemoryStoreInfo, type SharedMemoryDocumentEntry, type SharedMemorySnapshot, type SharedMemoryRequestContext, type MemoryListDetails, type MemoryReadDetails, } from "./core/shared-memory/types.js";
|
|
@@ -201,7 +202,7 @@ export { assertWorkflowSandboxConformance, assertWorkflowPrimitivesWiring, asser
|
|
|
201
202
|
export { WorkflowModelNotAllowedError, type WorkflowAgentSpec } from "./orchestration/workflow-governance.js";
|
|
202
203
|
export { WorkflowMaxAgentsError, WorkflowResultTooLargeError } from "./orchestration/workflow.js";
|
|
203
204
|
export { createFileWorkflowScriptStore, mergeWorkflowArgs, type WorkflowScriptStore, type NamedWorkflowResolution, type NamedWorkflowListing, } from "./orchestration/workflow-script-store.js";
|
|
204
|
-
export { TEAM_DISCUSSION_WORKFLOW_NAME, TEAM_DISCUSSION_SCRIPT, builtinWorkflowDefinitions, builtinWorkflowListings, resolveBuiltinWorkflow, type BuiltinWorkflowDefinition, } from "./orchestration/builtin-workflows.js";
|
|
205
|
+
export { DISCUSSION_WORKFLOW_NAME, DISCUSSION_SCRIPT, TEAM_DISCUSSION_WORKFLOW_NAME, TEAM_DISCUSSION_SCRIPT, canonicalWorkflowName, retiredWorkflowNameAliases, builtinWorkflowDefinitions, builtinWorkflowListings, resolveBuiltinWorkflow, type BuiltinWorkflowDefinition, } from "./orchestration/builtin-workflows.js";
|
|
205
206
|
export { WORKFLOW_AGENT_STALL_MS, WORKFLOW_AGENT_MAX_RETRIES, WORKFLOW_AGENT_THROTTLE_BACKOFF_MS } from "./orchestration/workflow.js";
|
|
206
207
|
export { createRunWorkflowTool, RUN_WORKFLOW_TOOL_NAME, workflowWhenToUseText, renderNamedWorkflowListing, type WorkflowCompletionNotifier, type WorkflowLimits, type RunWorkflowToolDeps, } from "./orchestration/run-workflow-tool.js";
|
|
207
208
|
export { runSideQuery, type SideQuerySpec, type SideQueryResult, type SideQueryToolDef, type SideQueryDeps, type SideQueryMessage } from "./core/side-query.js";
|
|
@@ -254,7 +255,7 @@ export { retryBackoffMs, parseRetryAfter } from "./brain/retry.js";
|
|
|
254
255
|
export { type BrainTimeoutConfig } from "./brain/timeout.js";
|
|
255
256
|
export { createAssistantMessageEventStream } from "./internal/llm.js";
|
|
256
257
|
export type { AssistantMessage, AssistantMessageEvent, CompleteSimpleFn, Context, DocumentContent, ImageContent, Message, StopReason, StreamFn, TextContent, ThinkingContent, ToolCall, ToolResultMessage, Usage, UserMessage, } from "./internal/llm.js";
|
|
257
|
-
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, EffectiveMemoryScopes, RemoteEnvFailureNote, TaskSpec, TaskStatus, TaskStream, CompactOutcome, ThinkingLevel, ToolExecuteContext, ToolReturn, ToolSpec, ReversibilityVerdict, ToolEffect, ToolContentOrigin, WorkflowGovernanceBaseline, DelegationTaskType, } from "./core/types.js";
|
|
258
|
+
export type { AgentDefinition, BeforeWriteHook, BeforeWriteRequest, BeforeWriteResult, HandsBandOptions, Brain, BrainStatus, BrainStatusPhase, BrainRetryErrClass, ImageInput, McpElicitRequest, McpElicitResponse, McpServerSpec, A2aServerSpec, OnElicit, Model, ModelRef, ProjectMemoryLoad, RunnerDeps, EngineNotice, RuntimeCaps, BackgroundChildEvent, DelegationLifecycleEvent, SkillManifest, SkillSpec, TaskEvent, TaskEventIdentity, ToolActivity, TaskLimits, StaleToolResultOffloadOptions, TaskResult, EffectiveMemoryScopes, RemoteEnvFailureNote, TaskSpec, TaskStatus, TaskStream, CompactOutcome, ThinkingLevel, ToolExecuteContext, ToolReturn, ToolSpec, ReversibilityVerdict, ToolEffect, ToolContentOrigin, WorkflowGovernanceBaseline, DelegationTaskType, } from "./core/types.js";
|
|
258
259
|
export { Type } from "typebox";
|
|
259
260
|
export type { TSchema, Static } from "typebox";
|
|
260
261
|
export { explainPromptAssembly, describeDefaultPack, type DefaultPackDescription, type ExplainInput } from "./prompt-assembly/explain.js";
|