@wrongstack/core 0.3.1 → 0.3.2
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/dist/{compactor-BUU6Zm_3.d.ts → compactor-DpJBI1YH.d.ts} +7 -1
- package/dist/{config-CKLYPkCi.d.ts → config-D2qvAxVd.d.ts} +38 -1
- package/dist/coordination/index.d.ts +3 -3
- package/dist/coordination/index.js +283 -244
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +7 -7
- package/dist/defaults/index.js +803 -524
- package/dist/defaults/index.js.map +1 -1
- package/dist/{events-CNB9PALO.d.ts → events-BHIQs4o1.d.ts} +7 -0
- package/dist/execution/index.d.ts +10 -7
- package/dist/execution/index.js +166 -18
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +3 -3
- package/dist/extension/index.js +14 -7
- package/dist/extension/index.js.map +1 -1
- package/dist/{index-BDb0cAMP.d.ts → index-hWNybrNZ.d.ts} +3 -5
- package/dist/index.d.ts +12 -12
- package/dist/index.js +629 -299
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +5 -5
- package/dist/infrastructure/index.js +191 -20
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +4 -4
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-DR35ojJZ.d.ts → mcp-servers-C2OopXOn.d.ts} +20 -4
- package/dist/observability/index.d.ts +1 -1
- package/dist/{path-resolver-Cl_q0u-R.d.ts → path-resolver--59rCou3.d.ts} +1 -1
- package/dist/{provider-runner-BXuADQqQ.d.ts → provider-runner-B39miKRw.d.ts} +1 -1
- package/dist/sdd/index.d.ts +1 -1
- package/dist/storage/index.d.ts +4 -3
- package/dist/storage/index.js +180 -13
- package/dist/storage/index.js.map +1 -1
- package/dist/{tool-executor-DKu4A6nB.d.ts → tool-executor-HsBLGRaA.d.ts} +2 -2
- package/dist/types/index.d.ts +7 -7
- package/dist/types/index.js +206 -9
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +23 -2
- package/dist/utils/index.js +93 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { a0 as Context } from './context-IovtuTf8.js';
|
|
2
2
|
|
|
3
|
+
interface CompactRepairReport {
|
|
4
|
+
removedToolUses: string[];
|
|
5
|
+
removedToolResults: string[];
|
|
6
|
+
removedMessages: number;
|
|
7
|
+
}
|
|
3
8
|
interface CompactReport {
|
|
4
9
|
before: number;
|
|
5
10
|
after: number;
|
|
@@ -7,6 +12,7 @@ interface CompactReport {
|
|
|
7
12
|
phase: 'elision' | 'summary' | 'selective';
|
|
8
13
|
saved: number;
|
|
9
14
|
}[];
|
|
15
|
+
repaired?: CompactRepairReport;
|
|
10
16
|
}
|
|
11
17
|
interface Compactor {
|
|
12
18
|
compact(ctx: Context, opts?: {
|
|
@@ -14,4 +20,4 @@ interface Compactor {
|
|
|
14
20
|
}): Promise<CompactReport>;
|
|
15
21
|
}
|
|
16
22
|
|
|
17
|
-
export type {
|
|
23
|
+
export type { CompactReport as C, Compactor as a };
|
|
@@ -1,7 +1,44 @@
|
|
|
1
1
|
import { W as WireFamily } from './models-registry-Y2xbog0E.js';
|
|
2
2
|
import { P as Permission } from './context-IovtuTf8.js';
|
|
3
3
|
|
|
4
|
+
type ContextWindowModeId = 'balanced' | 'frugal' | 'deep' | 'archival';
|
|
5
|
+
type ContextWindowAggressiveOn = 'hard' | 'soft' | 'warn';
|
|
6
|
+
interface ContextWindowThresholds {
|
|
7
|
+
warn: number;
|
|
8
|
+
soft: number;
|
|
9
|
+
hard: number;
|
|
10
|
+
}
|
|
11
|
+
interface ContextWindowMode {
|
|
12
|
+
id: ContextWindowModeId;
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
thresholds: ContextWindowThresholds;
|
|
16
|
+
aggressiveOn: ContextWindowAggressiveOn;
|
|
17
|
+
preserveK: number;
|
|
18
|
+
eliseThreshold: number;
|
|
19
|
+
targetLoad: number;
|
|
20
|
+
}
|
|
21
|
+
interface ContextWindowPolicy extends ContextWindowMode {
|
|
22
|
+
}
|
|
23
|
+
interface ContextWindowConfigLike {
|
|
24
|
+
mode?: ContextWindowModeId | string;
|
|
25
|
+
warnThreshold?: number;
|
|
26
|
+
softThreshold?: number;
|
|
27
|
+
hardThreshold?: number;
|
|
28
|
+
preserveK?: number;
|
|
29
|
+
eliseThreshold?: number;
|
|
30
|
+
}
|
|
31
|
+
declare const DEFAULT_CONTEXT_WINDOW_MODE_ID: ContextWindowModeId;
|
|
32
|
+
declare const CONTEXT_WINDOW_MODES: readonly ContextWindowMode[];
|
|
33
|
+
declare function listContextWindowModes(): ContextWindowMode[];
|
|
34
|
+
declare function getContextWindowMode(id: string | null | undefined): ContextWindowMode | null;
|
|
35
|
+
declare function isContextWindowModeId(id: string): id is ContextWindowModeId;
|
|
36
|
+
declare function resolveContextWindowPolicy(config?: ContextWindowConfigLike, overrideMode?: string | null): ContextWindowPolicy;
|
|
37
|
+
declare function formatContextWindowModeList(activeId?: string | null): string;
|
|
38
|
+
|
|
4
39
|
interface ContextConfig {
|
|
40
|
+
/** Context-window policy mode. Controls compaction thresholds and preservation depth. */
|
|
41
|
+
mode?: ContextWindowModeId;
|
|
5
42
|
warnThreshold: number;
|
|
6
43
|
softThreshold: number;
|
|
7
44
|
hardThreshold: number;
|
|
@@ -190,4 +227,4 @@ interface ConfigStore {
|
|
|
190
227
|
watch(cb: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;
|
|
191
228
|
}
|
|
192
229
|
|
|
193
|
-
export
|
|
230
|
+
export { CONTEXT_WINDOW_MODES as C, DEFAULT_CONTEXT_WINDOW_MODE_ID as D, type FeaturesConfig as F, type LogConfig as L, type MCPServerConfig as M, type PluginConfig as P, type ToolsConfig as T, type Config as a, type ConfigLoader as b, type ConfigStore as c, type ContextConfig as d, type ContextWindowAggressiveOn as e, type ContextWindowConfigLike as f, type ContextWindowMode as g, type ContextWindowModeId as h, type ContextWindowPolicy as i, type ContextWindowThresholds as j, type ProviderApiKey as k, type ProviderConfig as l, formatContextWindowModeList as m, getContextWindowMode as n, isContextWindowModeId as o, listContextWindowModes as p, resolveContextWindowPolicy as r };
|
|
@@ -3,14 +3,14 @@ export { n as BudgetExceededError, o as BudgetKind, p as BudgetLimits, q as Budg
|
|
|
3
3
|
import { q as SessionWriter, u as Tool, o as SessionStore } from '../context-IovtuTf8.js';
|
|
4
4
|
import { I as InMemoryAgentBridge } from '../agent-bridge-C3DUGjSb.js';
|
|
5
5
|
export { a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-C3DUGjSb.js';
|
|
6
|
-
import { E as EventBus } from '../events-
|
|
6
|
+
import { E as EventBus } from '../events-BHIQs4o1.js';
|
|
7
7
|
import { EventEmitter } from 'node:events';
|
|
8
|
-
import { r as Agent, u as AgentInput } from '../index-
|
|
8
|
+
import { r as Agent, u as AgentInput } from '../index-hWNybrNZ.js';
|
|
9
9
|
import '../logger-BMQgxvdy.js';
|
|
10
10
|
import '../system-prompt-Dk1qm8ey.js';
|
|
11
11
|
import '../observability-BhnVLBLS.js';
|
|
12
12
|
import '../secret-scrubber-CgG2tV2B.js';
|
|
13
|
-
import '../config-
|
|
13
|
+
import '../config-D2qvAxVd.js';
|
|
14
14
|
import '../models-registry-Y2xbog0E.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -290,6 +290,7 @@ var InMemoryAgentBridge = class {
|
|
|
290
290
|
this.stopped = true;
|
|
291
291
|
for (const [, p] of this.pendingRequests) {
|
|
292
292
|
clearTimeout(p.timer);
|
|
293
|
+
p.reject(new Error("Bridge stopped"));
|
|
293
294
|
}
|
|
294
295
|
this.pendingRequests.clear();
|
|
295
296
|
this.inflightGuards.clear();
|
|
@@ -1201,6 +1202,179 @@ function providerErrorToSubagentError(err, message, cause) {
|
|
|
1201
1202
|
}
|
|
1202
1203
|
return { kind: "unknown", message, retryable: err.retryable, cause };
|
|
1203
1204
|
}
|
|
1205
|
+
function makeSpawnTool(director, roster) {
|
|
1206
|
+
const inputSchema = {
|
|
1207
|
+
type: "object",
|
|
1208
|
+
properties: {
|
|
1209
|
+
role: { type: "string", description: "Roster role id (preferred). When set, the spawn uses the matching config from the roster and ignores other fields." },
|
|
1210
|
+
name: { type: "string", description: "Display name for the subagent. Required when not using roster." },
|
|
1211
|
+
provider: { type: "string", description: 'Provider id (e.g. "anthropic", "openai"). Defaults to the leader provider when omitted.' },
|
|
1212
|
+
model: { type: "string", description: "Model id within the provider. Defaults to the leader model when omitted." },
|
|
1213
|
+
systemPromptOverride: { type: "string", description: "Extra prompt text appended after the role-base prompt." },
|
|
1214
|
+
maxIterations: { type: "number" },
|
|
1215
|
+
maxToolCalls: { type: "number" },
|
|
1216
|
+
maxCostUsd: { type: "number" }
|
|
1217
|
+
},
|
|
1218
|
+
required: []
|
|
1219
|
+
};
|
|
1220
|
+
return {
|
|
1221
|
+
name: "spawn_subagent",
|
|
1222
|
+
description: "Create a new subagent under this director. Returns the subagent id.",
|
|
1223
|
+
usageHint: "Either pass `role` (matches the roster) OR pass `name` + optional `provider`/`model`. Returns `{ subagentId }`.",
|
|
1224
|
+
permission: "auto",
|
|
1225
|
+
mutating: false,
|
|
1226
|
+
inputSchema,
|
|
1227
|
+
async execute(input) {
|
|
1228
|
+
const i = input ?? {};
|
|
1229
|
+
const role = typeof i.role === "string" ? i.role : void 0;
|
|
1230
|
+
const base = role && roster ? roster[role] : void 0;
|
|
1231
|
+
if (role && !base) {
|
|
1232
|
+
return { error: `unknown role "${role}". roster has: ${roster ? Object.keys(roster).join(", ") : "(empty)"}` };
|
|
1233
|
+
}
|
|
1234
|
+
const cfg = { ...base ?? { name: i.name ?? "subagent" } };
|
|
1235
|
+
if (typeof i.name === "string") cfg.name = i.name;
|
|
1236
|
+
if (typeof i.provider === "string") cfg.provider = i.provider;
|
|
1237
|
+
if (typeof i.model === "string") cfg.model = i.model;
|
|
1238
|
+
if (typeof i.systemPromptOverride === "string") cfg.systemPromptOverride = i.systemPromptOverride;
|
|
1239
|
+
if (typeof i.maxIterations === "number") cfg.maxIterations = i.maxIterations;
|
|
1240
|
+
if (typeof i.maxToolCalls === "number") cfg.maxToolCalls = i.maxToolCalls;
|
|
1241
|
+
if (typeof i.maxCostUsd === "number") cfg.maxCostUsd = i.maxCostUsd;
|
|
1242
|
+
try {
|
|
1243
|
+
const subagentId = await director.spawn(cfg);
|
|
1244
|
+
return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name };
|
|
1245
|
+
} catch (err) {
|
|
1246
|
+
if (err instanceof DirectorBudgetError) {
|
|
1247
|
+
return { error: err.message, kind: err.kind, limit: err.limit, observed: err.observed };
|
|
1248
|
+
}
|
|
1249
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
function makeAssignTool(director) {
|
|
1255
|
+
const inputSchema = {
|
|
1256
|
+
type: "object",
|
|
1257
|
+
properties: {
|
|
1258
|
+
subagentId: { type: "string", description: "Target subagent id. Required." },
|
|
1259
|
+
description: { type: "string", description: "The task in natural language \u2014 what you want this subagent to do." },
|
|
1260
|
+
maxToolCalls: { type: "number", description: "Optional per-task tool-call budget override." },
|
|
1261
|
+
timeoutMs: { type: "number", description: "Optional per-task timeout in ms." }
|
|
1262
|
+
},
|
|
1263
|
+
required: ["subagentId", "description"]
|
|
1264
|
+
};
|
|
1265
|
+
return {
|
|
1266
|
+
name: "assign_task",
|
|
1267
|
+
description: "Hand a task to a previously spawned subagent. Returns the task id.",
|
|
1268
|
+
permission: "auto",
|
|
1269
|
+
mutating: false,
|
|
1270
|
+
inputSchema,
|
|
1271
|
+
async execute(input) {
|
|
1272
|
+
const i = input;
|
|
1273
|
+
const task = { id: randomUUID(), description: i.description, subagentId: i.subagentId, maxToolCalls: i.maxToolCalls, timeoutMs: i.timeoutMs };
|
|
1274
|
+
const taskId = await director.assign(task);
|
|
1275
|
+
return { taskId, subagentId: i.subagentId };
|
|
1276
|
+
}
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
function makeAwaitTasksTool(director) {
|
|
1280
|
+
return {
|
|
1281
|
+
name: "await_tasks",
|
|
1282
|
+
description: "Block until every named task completes. Returns the array of TaskResult.",
|
|
1283
|
+
permission: "auto",
|
|
1284
|
+
mutating: false,
|
|
1285
|
+
inputSchema: { type: "object", properties: { taskIds: { type: "array", items: { type: "string" }, description: "One or more task ids returned by `assign_task`." } }, required: ["taskIds"] },
|
|
1286
|
+
async execute(input) {
|
|
1287
|
+
const i = input;
|
|
1288
|
+
const results = await director.awaitTasks(i.taskIds);
|
|
1289
|
+
return { results };
|
|
1290
|
+
}
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
function makeAskTool(director) {
|
|
1294
|
+
return {
|
|
1295
|
+
name: "ask_subagent",
|
|
1296
|
+
description: "Synchronously ask a subagent a question. Blocks until the subagent replies via the bridge.",
|
|
1297
|
+
permission: "auto",
|
|
1298
|
+
mutating: false,
|
|
1299
|
+
inputSchema: {
|
|
1300
|
+
type: "object",
|
|
1301
|
+
properties: {
|
|
1302
|
+
subagentId: { type: "string", description: "Subagent to ask. Must be a previously spawned id." },
|
|
1303
|
+
question: { type: "string", description: "The question or instruction." },
|
|
1304
|
+
timeoutMs: { type: "number", description: "Optional timeout in ms (default 30s)." }
|
|
1305
|
+
},
|
|
1306
|
+
required: ["subagentId", "question"]
|
|
1307
|
+
},
|
|
1308
|
+
async execute(input) {
|
|
1309
|
+
const i = input;
|
|
1310
|
+
try {
|
|
1311
|
+
const answer = await director.ask(i.subagentId, { question: i.question }, i.timeoutMs);
|
|
1312
|
+
return { ok: true, answer };
|
|
1313
|
+
} catch (err) {
|
|
1314
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
function makeRollUpTool(director) {
|
|
1320
|
+
return {
|
|
1321
|
+
name: "roll_up",
|
|
1322
|
+
description: "Aggregate completed task results into a single formatted summary.",
|
|
1323
|
+
permission: "auto",
|
|
1324
|
+
mutating: false,
|
|
1325
|
+
inputSchema: {
|
|
1326
|
+
type: "object",
|
|
1327
|
+
properties: {
|
|
1328
|
+
taskIds: { type: "array", items: { type: "string" }, description: "Completed task ids to aggregate." },
|
|
1329
|
+
style: { type: "string", enum: ["markdown", "json"], description: "Output flavor \u2014 markdown (default) or json." }
|
|
1330
|
+
},
|
|
1331
|
+
required: ["taskIds"]
|
|
1332
|
+
},
|
|
1333
|
+
async execute(input) {
|
|
1334
|
+
const i = input;
|
|
1335
|
+
const summary = director.rollUp(i.taskIds, i.style ?? "markdown");
|
|
1336
|
+
return { summary, count: i.taskIds.length };
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
function makeTerminateTool(director) {
|
|
1341
|
+
return {
|
|
1342
|
+
name: "terminate_subagent",
|
|
1343
|
+
description: "Forcibly abort a subagent.",
|
|
1344
|
+
permission: "auto",
|
|
1345
|
+
mutating: true,
|
|
1346
|
+
inputSchema: { type: "object", properties: { subagentId: { type: "string", description: "Subagent to abort." } }, required: ["subagentId"] },
|
|
1347
|
+
async execute(input) {
|
|
1348
|
+
const i = input;
|
|
1349
|
+
await director.terminate(i.subagentId);
|
|
1350
|
+
return { ok: true };
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
function makeFleetStatusTool(director) {
|
|
1355
|
+
return {
|
|
1356
|
+
name: "fleet_status",
|
|
1357
|
+
description: "Snapshot of the fleet \u2014 every subagent's current status, pending vs. completed task counts.",
|
|
1358
|
+
permission: "auto",
|
|
1359
|
+
mutating: false,
|
|
1360
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
1361
|
+
async execute() {
|
|
1362
|
+
return director.status();
|
|
1363
|
+
}
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
function makeFleetUsageTool(director) {
|
|
1367
|
+
return {
|
|
1368
|
+
name: "fleet_usage",
|
|
1369
|
+
description: "Token + cost breakdown across the fleet, per-subagent and totals.",
|
|
1370
|
+
permission: "auto",
|
|
1371
|
+
mutating: false,
|
|
1372
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
1373
|
+
async execute() {
|
|
1374
|
+
return director.snapshot();
|
|
1375
|
+
}
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1204
1378
|
|
|
1205
1379
|
// src/coordination/director.ts
|
|
1206
1380
|
var DirectorBudgetError = class extends Error {
|
|
@@ -1759,242 +1933,6 @@ var Director = class {
|
|
|
1759
1933
|
return t;
|
|
1760
1934
|
}
|
|
1761
1935
|
};
|
|
1762
|
-
function makeSpawnTool(director, roster) {
|
|
1763
|
-
const inputSchema = {
|
|
1764
|
-
type: "object",
|
|
1765
|
-
properties: {
|
|
1766
|
-
role: {
|
|
1767
|
-
type: "string",
|
|
1768
|
-
description: "Roster role id (preferred). When set, the spawn uses the matching config from the roster and ignores other fields."
|
|
1769
|
-
},
|
|
1770
|
-
name: {
|
|
1771
|
-
type: "string",
|
|
1772
|
-
description: "Display name for the subagent. Required when not using roster."
|
|
1773
|
-
},
|
|
1774
|
-
provider: {
|
|
1775
|
-
type: "string",
|
|
1776
|
-
description: 'Provider id (e.g. "anthropic", "openai"). Defaults to the leader provider when omitted.'
|
|
1777
|
-
},
|
|
1778
|
-
model: {
|
|
1779
|
-
type: "string",
|
|
1780
|
-
description: "Model id within the provider. Defaults to the leader model when omitted."
|
|
1781
|
-
},
|
|
1782
|
-
systemPromptOverride: {
|
|
1783
|
-
type: "string",
|
|
1784
|
-
description: "Extra prompt text appended after the role-base prompt."
|
|
1785
|
-
},
|
|
1786
|
-
maxIterations: { type: "number" },
|
|
1787
|
-
maxToolCalls: { type: "number" },
|
|
1788
|
-
maxCostUsd: { type: "number" }
|
|
1789
|
-
},
|
|
1790
|
-
required: []
|
|
1791
|
-
};
|
|
1792
|
-
return {
|
|
1793
|
-
name: "spawn_subagent",
|
|
1794
|
-
description: "Create a new subagent under this director. Returns the subagent id. Use this when you need a worker with a specific provider, model, or role to handle a piece of the plan.",
|
|
1795
|
-
usageHint: "Either pass `role` (matches the roster) OR pass `name` + optional `provider`/`model`. Returns `{ subagentId }`.",
|
|
1796
|
-
permission: "auto",
|
|
1797
|
-
mutating: false,
|
|
1798
|
-
inputSchema,
|
|
1799
|
-
async execute(input) {
|
|
1800
|
-
const i = input ?? {};
|
|
1801
|
-
const role = typeof i.role === "string" ? i.role : void 0;
|
|
1802
|
-
const base = role && roster ? roster[role] : void 0;
|
|
1803
|
-
if (role && !base) {
|
|
1804
|
-
return {
|
|
1805
|
-
error: `unknown role "${role}". roster has: ${roster ? Object.keys(roster).join(", ") : "(empty)"}`
|
|
1806
|
-
};
|
|
1807
|
-
}
|
|
1808
|
-
const cfg = {
|
|
1809
|
-
...base ?? { name: i.name ?? "subagent" }
|
|
1810
|
-
};
|
|
1811
|
-
if (typeof i.name === "string") cfg.name = i.name;
|
|
1812
|
-
if (typeof i.provider === "string") cfg.provider = i.provider;
|
|
1813
|
-
if (typeof i.model === "string") cfg.model = i.model;
|
|
1814
|
-
if (typeof i.systemPromptOverride === "string")
|
|
1815
|
-
cfg.systemPromptOverride = i.systemPromptOverride;
|
|
1816
|
-
if (typeof i.maxIterations === "number") cfg.maxIterations = i.maxIterations;
|
|
1817
|
-
if (typeof i.maxToolCalls === "number") cfg.maxToolCalls = i.maxToolCalls;
|
|
1818
|
-
if (typeof i.maxCostUsd === "number") cfg.maxCostUsd = i.maxCostUsd;
|
|
1819
|
-
try {
|
|
1820
|
-
const subagentId = await director.spawn(cfg);
|
|
1821
|
-
return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name };
|
|
1822
|
-
} catch (err) {
|
|
1823
|
-
if (err instanceof DirectorBudgetError) {
|
|
1824
|
-
return { error: err.message, kind: err.kind, limit: err.limit, observed: err.observed };
|
|
1825
|
-
}
|
|
1826
|
-
return { error: err instanceof Error ? err.message : String(err) };
|
|
1827
|
-
}
|
|
1828
|
-
}
|
|
1829
|
-
};
|
|
1830
|
-
}
|
|
1831
|
-
function makeAssignTool(director) {
|
|
1832
|
-
const inputSchema = {
|
|
1833
|
-
type: "object",
|
|
1834
|
-
properties: {
|
|
1835
|
-
subagentId: { type: "string", description: "Target subagent id. Required." },
|
|
1836
|
-
description: {
|
|
1837
|
-
type: "string",
|
|
1838
|
-
description: "The task in natural language \u2014 what you want this subagent to do."
|
|
1839
|
-
},
|
|
1840
|
-
maxToolCalls: { type: "number", description: "Optional per-task tool-call budget override." },
|
|
1841
|
-
timeoutMs: { type: "number", description: "Optional per-task timeout in ms." }
|
|
1842
|
-
},
|
|
1843
|
-
required: ["subagentId", "description"]
|
|
1844
|
-
};
|
|
1845
|
-
return {
|
|
1846
|
-
name: "assign_task",
|
|
1847
|
-
description: "Hand a task to a previously spawned subagent. Returns the task id \u2014 pass it to `await_tasks` to block on completion.",
|
|
1848
|
-
permission: "auto",
|
|
1849
|
-
mutating: false,
|
|
1850
|
-
inputSchema,
|
|
1851
|
-
async execute(input) {
|
|
1852
|
-
const i = input;
|
|
1853
|
-
const task = {
|
|
1854
|
-
id: randomUUID(),
|
|
1855
|
-
description: i.description,
|
|
1856
|
-
subagentId: i.subagentId,
|
|
1857
|
-
maxToolCalls: i.maxToolCalls,
|
|
1858
|
-
timeoutMs: i.timeoutMs
|
|
1859
|
-
};
|
|
1860
|
-
const taskId = await director.assign(task);
|
|
1861
|
-
return { taskId, subagentId: i.subagentId };
|
|
1862
|
-
}
|
|
1863
|
-
};
|
|
1864
|
-
}
|
|
1865
|
-
function makeAwaitTasksTool(director) {
|
|
1866
|
-
const inputSchema = {
|
|
1867
|
-
type: "object",
|
|
1868
|
-
properties: {
|
|
1869
|
-
taskIds: {
|
|
1870
|
-
type: "array",
|
|
1871
|
-
items: { type: "string" },
|
|
1872
|
-
description: "One or more task ids returned by `assign_task`. The call blocks until every id resolves."
|
|
1873
|
-
}
|
|
1874
|
-
},
|
|
1875
|
-
required: ["taskIds"]
|
|
1876
|
-
};
|
|
1877
|
-
return {
|
|
1878
|
-
name: "await_tasks",
|
|
1879
|
-
description: "Block until every named task completes. Returns the array of TaskResult \u2014 use this to gather subagent output before deciding the next step.",
|
|
1880
|
-
permission: "auto",
|
|
1881
|
-
mutating: false,
|
|
1882
|
-
inputSchema,
|
|
1883
|
-
async execute(input) {
|
|
1884
|
-
const i = input;
|
|
1885
|
-
const results = await director.awaitTasks(i.taskIds);
|
|
1886
|
-
return { results };
|
|
1887
|
-
}
|
|
1888
|
-
};
|
|
1889
|
-
}
|
|
1890
|
-
function makeAskTool(director) {
|
|
1891
|
-
const inputSchema = {
|
|
1892
|
-
type: "object",
|
|
1893
|
-
properties: {
|
|
1894
|
-
subagentId: {
|
|
1895
|
-
type: "string",
|
|
1896
|
-
description: "Subagent to ask. Must be a previously spawned id."
|
|
1897
|
-
},
|
|
1898
|
-
question: {
|
|
1899
|
-
type: "string",
|
|
1900
|
-
description: "The question or instruction. Sent as the bridge message payload."
|
|
1901
|
-
},
|
|
1902
|
-
timeoutMs: { type: "number", description: "Optional timeout in ms (default 30s)." }
|
|
1903
|
-
},
|
|
1904
|
-
required: ["subagentId", "question"]
|
|
1905
|
-
};
|
|
1906
|
-
return {
|
|
1907
|
-
name: "ask_subagent",
|
|
1908
|
-
description: "Synchronously ask a subagent a question. Blocks until the subagent replies via the bridge (or the timeout fires). Use this when you need a one-shot answer without spawning a fresh task.",
|
|
1909
|
-
permission: "auto",
|
|
1910
|
-
mutating: false,
|
|
1911
|
-
inputSchema,
|
|
1912
|
-
async execute(input) {
|
|
1913
|
-
const i = input;
|
|
1914
|
-
try {
|
|
1915
|
-
const answer = await director.ask(i.subagentId, { question: i.question }, i.timeoutMs);
|
|
1916
|
-
return { ok: true, answer };
|
|
1917
|
-
} catch (err) {
|
|
1918
|
-
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
};
|
|
1922
|
-
}
|
|
1923
|
-
function makeRollUpTool(director) {
|
|
1924
|
-
const inputSchema = {
|
|
1925
|
-
type: "object",
|
|
1926
|
-
properties: {
|
|
1927
|
-
taskIds: {
|
|
1928
|
-
type: "array",
|
|
1929
|
-
items: { type: "string" },
|
|
1930
|
-
description: "Completed task ids to aggregate. Pass the ids returned by previous `assign_task` calls."
|
|
1931
|
-
},
|
|
1932
|
-
style: {
|
|
1933
|
-
type: "string",
|
|
1934
|
-
enum: ["markdown", "json"],
|
|
1935
|
-
description: "Output flavor \u2014 markdown (default) for in-prompt summarization, json for structured downstream processing."
|
|
1936
|
-
}
|
|
1937
|
-
},
|
|
1938
|
-
required: ["taskIds"]
|
|
1939
|
-
};
|
|
1940
|
-
return {
|
|
1941
|
-
name: "roll_up",
|
|
1942
|
-
description: "Aggregate completed task results into a single formatted summary. Use this after `await_tasks` to fold subagent outputs back into the director's context before deciding the next step.",
|
|
1943
|
-
permission: "auto",
|
|
1944
|
-
mutating: false,
|
|
1945
|
-
inputSchema,
|
|
1946
|
-
async execute(input) {
|
|
1947
|
-
const i = input;
|
|
1948
|
-
const summary = director.rollUp(i.taskIds, i.style ?? "markdown");
|
|
1949
|
-
return { summary, count: i.taskIds.length };
|
|
1950
|
-
}
|
|
1951
|
-
};
|
|
1952
|
-
}
|
|
1953
|
-
function makeTerminateTool(director) {
|
|
1954
|
-
const inputSchema = {
|
|
1955
|
-
type: "object",
|
|
1956
|
-
properties: {
|
|
1957
|
-
subagentId: { type: "string", description: "Subagent to abort." }
|
|
1958
|
-
},
|
|
1959
|
-
required: ["subagentId"]
|
|
1960
|
-
};
|
|
1961
|
-
return {
|
|
1962
|
-
name: "terminate_subagent",
|
|
1963
|
-
description: 'Forcibly abort a subagent. Use sparingly \u2014 prefer waiting on the natural budget to expire. The current task (if any) ends with status "stopped".',
|
|
1964
|
-
permission: "auto",
|
|
1965
|
-
mutating: true,
|
|
1966
|
-
inputSchema,
|
|
1967
|
-
async execute(input) {
|
|
1968
|
-
const i = input;
|
|
1969
|
-
await director.terminate(i.subagentId);
|
|
1970
|
-
return { ok: true };
|
|
1971
|
-
}
|
|
1972
|
-
};
|
|
1973
|
-
}
|
|
1974
|
-
function makeFleetStatusTool(director) {
|
|
1975
|
-
return {
|
|
1976
|
-
name: "fleet_status",
|
|
1977
|
-
description: "Snapshot of the fleet \u2014 every subagent's current status, pending vs. completed task counts, and the running total iteration count. Cheap; call freely.",
|
|
1978
|
-
permission: "auto",
|
|
1979
|
-
mutating: false,
|
|
1980
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
1981
|
-
async execute() {
|
|
1982
|
-
return director.status();
|
|
1983
|
-
}
|
|
1984
|
-
};
|
|
1985
|
-
}
|
|
1986
|
-
function makeFleetUsageTool(director) {
|
|
1987
|
-
return {
|
|
1988
|
-
name: "fleet_usage",
|
|
1989
|
-
description: "Token + cost breakdown across the fleet, per-subagent and totals. Use this to reason about which workers to assign costly tasks to or when to wrap up to stay within budget.",
|
|
1990
|
-
permission: "auto",
|
|
1991
|
-
mutating: false,
|
|
1992
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
1993
|
-
async execute() {
|
|
1994
|
-
return director.snapshot();
|
|
1995
|
-
}
|
|
1996
|
-
};
|
|
1997
|
-
}
|
|
1998
1936
|
function createDelegateTool(opts) {
|
|
1999
1937
|
const defaultTimeoutMs = opts.defaultTimeoutMs ?? 4 * 60 * 60 * 1e3;
|
|
2000
1938
|
const rosterIds = opts.roster ? Object.keys(opts.roster) : [];
|
|
@@ -2357,6 +2295,100 @@ function makeAgentSubagentRunner(opts) {
|
|
|
2357
2295
|
function defaultFormatTaskInput(task) {
|
|
2358
2296
|
return task.description ?? "";
|
|
2359
2297
|
}
|
|
2298
|
+
|
|
2299
|
+
// src/utils/message-invariants.ts
|
|
2300
|
+
function repairToolUseAdjacency(messages) {
|
|
2301
|
+
const removedToolUses = [];
|
|
2302
|
+
const removedToolResults = [];
|
|
2303
|
+
let removedMessages = 0;
|
|
2304
|
+
let changed = false;
|
|
2305
|
+
const out = [];
|
|
2306
|
+
for (let i = 0; i < messages.length; i++) {
|
|
2307
|
+
const original = messages[i];
|
|
2308
|
+
let msg = original;
|
|
2309
|
+
if (hasToolUse(msg)) {
|
|
2310
|
+
const nextIds = toolResultIds(messages[i + 1]);
|
|
2311
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
2312
|
+
const next = [];
|
|
2313
|
+
for (const block of blocks) {
|
|
2314
|
+
if (block.type === "tool_use" && !nextIds.has(block.id)) {
|
|
2315
|
+
removedToolUses.push(block.id);
|
|
2316
|
+
changed = true;
|
|
2317
|
+
continue;
|
|
2318
|
+
}
|
|
2319
|
+
next.push(block);
|
|
2320
|
+
}
|
|
2321
|
+
return next;
|
|
2322
|
+
});
|
|
2323
|
+
msg = filtered ?? msg;
|
|
2324
|
+
}
|
|
2325
|
+
if (hasToolResult(msg)) {
|
|
2326
|
+
const allowed = toolUseIds(out[out.length - 1]);
|
|
2327
|
+
const filtered = mapContent(msg, (blocks) => {
|
|
2328
|
+
const next = [];
|
|
2329
|
+
for (const block of blocks) {
|
|
2330
|
+
if (block.type === "tool_result" && !allowed.has(block.tool_use_id)) {
|
|
2331
|
+
removedToolResults.push(block.tool_use_id);
|
|
2332
|
+
changed = true;
|
|
2333
|
+
continue;
|
|
2334
|
+
}
|
|
2335
|
+
next.push(block);
|
|
2336
|
+
}
|
|
2337
|
+
return next;
|
|
2338
|
+
});
|
|
2339
|
+
msg = filtered ?? msg;
|
|
2340
|
+
}
|
|
2341
|
+
if (isEmptyMessage(msg)) {
|
|
2342
|
+
removedMessages++;
|
|
2343
|
+
changed = true;
|
|
2344
|
+
continue;
|
|
2345
|
+
}
|
|
2346
|
+
out.push(msg);
|
|
2347
|
+
}
|
|
2348
|
+
return {
|
|
2349
|
+
messages: changed ? out : messages,
|
|
2350
|
+
report: { changed, removedToolUses, removedToolResults, removedMessages }
|
|
2351
|
+
};
|
|
2352
|
+
}
|
|
2353
|
+
function hasToolUse(msg) {
|
|
2354
|
+
return contentBlocks(msg).some((b) => b.type === "tool_use");
|
|
2355
|
+
}
|
|
2356
|
+
function hasToolResult(msg) {
|
|
2357
|
+
return contentBlocks(msg).some((b) => b.type === "tool_result");
|
|
2358
|
+
}
|
|
2359
|
+
function toolUseIds(msg) {
|
|
2360
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2361
|
+
if (!msg || msg.role !== "assistant") return ids;
|
|
2362
|
+
for (const block of contentBlocks(msg)) {
|
|
2363
|
+
if (block.type === "tool_use") ids.add(block.id);
|
|
2364
|
+
}
|
|
2365
|
+
return ids;
|
|
2366
|
+
}
|
|
2367
|
+
function toolResultIds(msg) {
|
|
2368
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2369
|
+
if (!msg || msg.role !== "user") return ids;
|
|
2370
|
+
for (const block of contentBlocks(msg)) {
|
|
2371
|
+
if (block.type === "tool_result") ids.add(block.tool_use_id);
|
|
2372
|
+
}
|
|
2373
|
+
return ids;
|
|
2374
|
+
}
|
|
2375
|
+
function contentBlocks(msg) {
|
|
2376
|
+
return msg && Array.isArray(msg.content) ? msg.content : [];
|
|
2377
|
+
}
|
|
2378
|
+
function mapContent(msg, fn) {
|
|
2379
|
+
if (!Array.isArray(msg.content)) return msg;
|
|
2380
|
+
const next = fn(msg.content);
|
|
2381
|
+
if (next.length === msg.content.length && next.every((b, idx) => b === msg.content[idx])) {
|
|
2382
|
+
return msg;
|
|
2383
|
+
}
|
|
2384
|
+
return { ...msg, content: next };
|
|
2385
|
+
}
|
|
2386
|
+
function isEmptyMessage(msg) {
|
|
2387
|
+
if (typeof msg.content === "string") return msg.content.trim().length === 0;
|
|
2388
|
+
return msg.content.length === 0;
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
// src/storage/session-store.ts
|
|
2360
2392
|
var DefaultSessionStore = class {
|
|
2361
2393
|
dir;
|
|
2362
2394
|
events;
|
|
@@ -2558,11 +2590,17 @@ var DefaultSessionStore = class {
|
|
|
2558
2590
|
if (openToolUses.size > 0) {
|
|
2559
2591
|
this.events?.emit("session.damaged", {
|
|
2560
2592
|
sessionId,
|
|
2561
|
-
detail: `${openToolUses.size} tool_use blocks without matching results
|
|
2593
|
+
detail: `${openToolUses.size} tool_use blocks without matching results - replay repaired`
|
|
2562
2594
|
});
|
|
2563
|
-
return { messages, usage };
|
|
2564
2595
|
}
|
|
2565
|
-
|
|
2596
|
+
const repaired = repairToolUseAdjacency(messages);
|
|
2597
|
+
if (repaired.report.changed) {
|
|
2598
|
+
this.events?.emit("session.damaged", {
|
|
2599
|
+
sessionId,
|
|
2600
|
+
detail: `Repaired replay adjacency: removed ${repaired.report.removedToolUses.length} tool_use, ${repaired.report.removedToolResults.length} tool_result, ${repaired.report.removedMessages} empty messages`
|
|
2601
|
+
});
|
|
2602
|
+
}
|
|
2603
|
+
return { messages: repaired.messages, usage };
|
|
2566
2604
|
}
|
|
2567
2605
|
};
|
|
2568
2606
|
var FileSessionWriter = class {
|
|
@@ -2588,6 +2626,7 @@ var FileSessionWriter = class {
|
|
|
2588
2626
|
startedAt;
|
|
2589
2627
|
meta;
|
|
2590
2628
|
closed = false;
|
|
2629
|
+
closing = false;
|
|
2591
2630
|
manifestFile;
|
|
2592
2631
|
summary;
|
|
2593
2632
|
tokenIn = 0;
|
|
@@ -2603,9 +2642,7 @@ var FileSessionWriter = class {
|
|
|
2603
2642
|
resumed;
|
|
2604
2643
|
appendFailCount = 0;
|
|
2605
2644
|
lastAppendWarnAt = 0;
|
|
2606
|
-
async
|
|
2607
|
-
if (this.initDone || this.closed) return;
|
|
2608
|
-
this.initDone = true;
|
|
2645
|
+
async writeSessionStartLazy() {
|
|
2609
2646
|
const record = `${JSON.stringify({
|
|
2610
2647
|
type: this.resumed ? "session_resumed" : "session_start",
|
|
2611
2648
|
ts: this.startedAt,
|
|
@@ -2624,7 +2661,8 @@ var FileSessionWriter = class {
|
|
|
2624
2661
|
async append(event) {
|
|
2625
2662
|
if (this.closed) return;
|
|
2626
2663
|
if (!this.initDone) {
|
|
2627
|
-
|
|
2664
|
+
this.initDone = true;
|
|
2665
|
+
await this.writeSessionStartLazy();
|
|
2628
2666
|
}
|
|
2629
2667
|
this.observeForSummary(event);
|
|
2630
2668
|
try {
|
|
@@ -2665,7 +2703,8 @@ var FileSessionWriter = class {
|
|
|
2665
2703
|
}
|
|
2666
2704
|
}
|
|
2667
2705
|
async close() {
|
|
2668
|
-
if (this.
|
|
2706
|
+
if (this.closing) return;
|
|
2707
|
+
this.closing = true;
|
|
2669
2708
|
this.closed = true;
|
|
2670
2709
|
if (this.manifestFile) {
|
|
2671
2710
|
try {
|