@wrongstack/core 0.10.3 → 0.31.1
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/{agent-subagent-runner-DuRtZmhl.d.ts → agent-subagent-runner-DpZTLdBe.d.ts} +1 -1
- package/dist/{config-CJXBka2r.d.ts → config-BUEGM4JP.d.ts} +2 -0
- package/dist/coordination/index.d.ts +6 -6
- package/dist/coordination/index.js +414 -71
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +8 -8
- package/dist/defaults/index.js +388 -57
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +5 -5
- package/dist/execution/index.js +47 -5
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +2 -2
- package/dist/{index-DnBHrz2y.d.ts → index-pXJdVLe0.d.ts} +1 -1
- package/dist/{index-DAHEM_II.d.ts → index-ysfO_DlX.d.ts} +1 -1
- package/dist/index.d.ts +13 -13
- package/dist/index.js +635 -242
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +2 -2
- package/dist/infrastructure/index.js +2 -1
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +2 -2
- package/dist/{mcp-servers-BgINZzuo.d.ts → mcp-servers-BzB3r7_c.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-CjG-FZKj.d.ts → multi-agent-coordinator-DOXSgtom.d.ts} +5 -1
- package/dist/{null-fleet-bus-B3WdVY9i.d.ts → null-fleet-bus-CAQDGsKc.d.ts} +59 -3
- package/dist/{plan-templates-BUP4o-ds.d.ts → plan-templates-BZMi-VpU.d.ts} +1 -1
- package/dist/sdd/index.d.ts +3 -3
- package/dist/sdd/index.js +40 -3
- package/dist/sdd/index.js.map +1 -1
- package/dist/storage/index.d.ts +2 -2
- package/dist/{tool-executor-D87-_5Of.d.ts → tool-executor-BAi4WI2d.d.ts} +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +2 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +76 -1
- package/dist/utils/index.js +171 -5
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/dist/defaults/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import * as crypto2 from 'crypto';
|
|
|
2
2
|
import { randomBytes, randomUUID, createCipheriv, createDecipheriv, createHash } from 'crypto';
|
|
3
3
|
import * as fsp from 'fs/promises';
|
|
4
4
|
import * as path15 from 'path';
|
|
5
|
+
import { isAbsolute, resolve } from 'path';
|
|
5
6
|
import * as fs5 from 'fs';
|
|
6
7
|
import * as os from 'os';
|
|
7
8
|
import { execFile } from 'child_process';
|
|
@@ -51,8 +52,8 @@ async function atomicWrite(targetPath, content, opts = {}) {
|
|
|
51
52
|
}
|
|
52
53
|
let mode;
|
|
53
54
|
try {
|
|
54
|
-
const
|
|
55
|
-
mode =
|
|
55
|
+
const stat5 = await fsp.stat(targetPath);
|
|
56
|
+
mode = stat5.mode & 511;
|
|
56
57
|
} catch {
|
|
57
58
|
mode = opts.mode;
|
|
58
59
|
}
|
|
@@ -88,7 +89,7 @@ async function renameWithRetry(from, to) {
|
|
|
88
89
|
if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {
|
|
89
90
|
throw err;
|
|
90
91
|
}
|
|
91
|
-
await new Promise((
|
|
92
|
+
await new Promise((resolve4) => setTimeout(resolve4, delays[i]));
|
|
92
93
|
}
|
|
93
94
|
}
|
|
94
95
|
throw lastErr;
|
|
@@ -446,8 +447,8 @@ var DefaultSessionStore = class {
|
|
|
446
447
|
return JSON.parse(raw);
|
|
447
448
|
} catch {
|
|
448
449
|
const full = this.sessionPath(id, ".jsonl");
|
|
449
|
-
const
|
|
450
|
-
const summary = await this.summarize(id,
|
|
450
|
+
const stat5 = await fsp.stat(full);
|
|
451
|
+
const summary = await this.summarize(id, stat5.mtime.toISOString());
|
|
451
452
|
await atomicWrite(manifest, JSON.stringify(summary), { mode: 384 }).catch((err) => {
|
|
452
453
|
console.warn(
|
|
453
454
|
`[session-store] Failed to write manifest for "${id}":`,
|
|
@@ -4297,8 +4298,8 @@ async function streamProviderToResponse(provider, req, signal, ctx, events) {
|
|
|
4297
4298
|
try {
|
|
4298
4299
|
await Promise.race([
|
|
4299
4300
|
Promise.resolve(iter.return?.()),
|
|
4300
|
-
new Promise((
|
|
4301
|
-
drainTimer = setTimeout(
|
|
4301
|
+
new Promise((resolve4) => {
|
|
4302
|
+
drainTimer = setTimeout(resolve4, 500);
|
|
4302
4303
|
})
|
|
4303
4304
|
]);
|
|
4304
4305
|
} finally {
|
|
@@ -4359,7 +4360,7 @@ async function runProviderWithRetry(opts) {
|
|
|
4359
4360
|
description
|
|
4360
4361
|
});
|
|
4361
4362
|
}
|
|
4362
|
-
await new Promise((
|
|
4363
|
+
await new Promise((resolve4, reject) => {
|
|
4363
4364
|
let settled = false;
|
|
4364
4365
|
const onAbort = () => {
|
|
4365
4366
|
if (settled) return;
|
|
@@ -4372,7 +4373,7 @@ async function runProviderWithRetry(opts) {
|
|
|
4372
4373
|
settled = true;
|
|
4373
4374
|
clearTimeout(t);
|
|
4374
4375
|
signal.removeEventListener("abort", onAbort);
|
|
4375
|
-
|
|
4376
|
+
resolve4();
|
|
4376
4377
|
}, delay);
|
|
4377
4378
|
if (signal.aborted) {
|
|
4378
4379
|
onAbort();
|
|
@@ -4466,13 +4467,18 @@ function estimateRequestTokens(messages, systemPrompt, tools) {
|
|
|
4466
4467
|
for (const t of tools) {
|
|
4467
4468
|
toolsTokens += estimateToolDefTokens(t);
|
|
4468
4469
|
}
|
|
4470
|
+
const total = messagesTokens + systemTokens + toolsTokens;
|
|
4469
4471
|
return {
|
|
4470
4472
|
messages: messagesTokens,
|
|
4471
4473
|
systemPrompt: systemTokens,
|
|
4472
4474
|
tools: toolsTokens,
|
|
4473
|
-
total
|
|
4475
|
+
total
|
|
4474
4476
|
};
|
|
4475
4477
|
}
|
|
4478
|
+
function estimateRequestTokensCalibrated(messages, systemPrompt, tools) {
|
|
4479
|
+
const result = estimateRequestTokens(messages, systemPrompt, tools);
|
|
4480
|
+
return result;
|
|
4481
|
+
}
|
|
4476
4482
|
|
|
4477
4483
|
// src/execution/compactor.ts
|
|
4478
4484
|
var HybridCompactor = class {
|
|
@@ -5368,7 +5374,7 @@ var AutoCompactionMiddleware = class _AutoCompactionMiddleware {
|
|
|
5368
5374
|
}
|
|
5369
5375
|
handler() {
|
|
5370
5376
|
return async (ctx, next) => {
|
|
5371
|
-
const tokens = this._estimator ? this._estimator(ctx) :
|
|
5377
|
+
const tokens = this._estimator ? this._estimator(ctx) : estimateRequestTokensCalibrated(ctx.messages, ctx.systemPrompt, ctx.tools ?? []).total;
|
|
5372
5378
|
const load = tokens / this._maxContext;
|
|
5373
5379
|
const policy = this.policyProvider?.(ctx);
|
|
5374
5380
|
const thresholds = policy?.thresholds ?? {
|
|
@@ -6740,7 +6746,7 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
6740
6746
|
}
|
|
6741
6747
|
};
|
|
6742
6748
|
function sleep(ms) {
|
|
6743
|
-
return new Promise((
|
|
6749
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
6744
6750
|
}
|
|
6745
6751
|
|
|
6746
6752
|
// src/coordination/subagent-budget.ts
|
|
@@ -6956,12 +6962,12 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
6956
6962
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
6957
6963
|
return Promise.resolve("stop");
|
|
6958
6964
|
}
|
|
6959
|
-
return new Promise((
|
|
6965
|
+
return new Promise((resolve4) => {
|
|
6960
6966
|
let resolved = false;
|
|
6961
6967
|
const respond = (d) => {
|
|
6962
6968
|
if (resolved) return;
|
|
6963
6969
|
resolved = true;
|
|
6964
|
-
|
|
6970
|
+
resolve4(d);
|
|
6965
6971
|
};
|
|
6966
6972
|
const fallback = setTimeout(
|
|
6967
6973
|
() => respond("stop"),
|
|
@@ -9898,6 +9904,10 @@ var NICKNAME_POOL = {
|
|
|
9898
9904
|
"pasteur": { name: "Pasteur", domain: "biology" },
|
|
9899
9905
|
"hawking": { name: "Hawking", domain: "cosmology" },
|
|
9900
9906
|
"sagan": { name: "Sagan", domain: "cosmology" },
|
|
9907
|
+
// Exploration & navigation
|
|
9908
|
+
"columbus": { name: "Columbus", domain: "exploration" },
|
|
9909
|
+
"polo": { name: "Polo", domain: "exploration" },
|
|
9910
|
+
"magellan": { name: "Magellan", domain: "exploration" },
|
|
9901
9911
|
// Chemistry / materials
|
|
9902
9912
|
"lavoisier": { name: "Lavoisier", domain: "chemistry" },
|
|
9903
9913
|
"mendeleev": { name: "Mendeleev", domain: "chemistry" }
|
|
@@ -9952,7 +9962,7 @@ function formatRole(role) {
|
|
|
9952
9962
|
}
|
|
9953
9963
|
|
|
9954
9964
|
// src/coordination/multi-agent-coordinator.ts
|
|
9955
|
-
var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
9965
|
+
var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends EventEmitter {
|
|
9956
9966
|
coordinatorId;
|
|
9957
9967
|
config;
|
|
9958
9968
|
runner;
|
|
@@ -9967,8 +9977,12 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9967
9977
|
* names) to memorable ones here — that's what surfaces in the fleet monitor.
|
|
9968
9978
|
*/
|
|
9969
9979
|
usedNicknames = /* @__PURE__ */ new Set();
|
|
9980
|
+
/** Maps subagentId → nickname key (e.g. 'einstein'). Used to free the slot on remove(). */
|
|
9981
|
+
subagentNicknames = /* @__PURE__ */ new Map();
|
|
9970
9982
|
pendingTasks = [];
|
|
9971
9983
|
completedResults = [];
|
|
9984
|
+
/** Prevents completedResults from growing unbounded in long-running coordinators. */
|
|
9985
|
+
static MAX_COMPLETED_RESULTS = 1e4;
|
|
9972
9986
|
totalIterations = 0;
|
|
9973
9987
|
inFlight = 0;
|
|
9974
9988
|
/**
|
|
@@ -10023,7 +10037,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
10023
10037
|
* Explicit, human-chosen names — including nicknames already assigned by
|
|
10024
10038
|
* `Director.spawn()` — are left untouched, so this never double-assigns.
|
|
10025
10039
|
*/
|
|
10026
|
-
withNickname(subagent) {
|
|
10040
|
+
withNickname(subagent, subagentId) {
|
|
10027
10041
|
const role = subagent.role ?? "subagent";
|
|
10028
10042
|
const name = subagent.name?.trim() ?? "";
|
|
10029
10043
|
const isPlaceholder = name === "" || name.toLowerCase() === role.toLowerCase() || name === "subagent" || name === "adhoc" || name === "generic" || /^slot-/.test(name);
|
|
@@ -10031,11 +10045,12 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
10031
10045
|
const nickname = assignNickname(role, this.usedNicknames);
|
|
10032
10046
|
const baseKey = nickname.split(" ")[0].toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
10033
10047
|
this.usedNicknames.add(baseKey);
|
|
10048
|
+
this.subagentNicknames.set(subagentId, baseKey);
|
|
10034
10049
|
return { ...subagent, name: nickname };
|
|
10035
10050
|
}
|
|
10036
10051
|
async spawn(subagent) {
|
|
10037
|
-
subagent = this.withNickname(subagent);
|
|
10038
10052
|
const id = subagent.id || randomUUID();
|
|
10053
|
+
subagent = this.withNickname(subagent, id);
|
|
10039
10054
|
if (this.subagents.has(id)) {
|
|
10040
10055
|
throw new Error(`Subagent id "${id}" already exists \u2014 refusing to overwrite`);
|
|
10041
10056
|
}
|
|
@@ -10179,7 +10194,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
10179
10194
|
taskIds.map((id) => {
|
|
10180
10195
|
const cached = this.completedResults.find((r) => r.taskId === id);
|
|
10181
10196
|
if (cached) return cached;
|
|
10182
|
-
return new Promise((
|
|
10197
|
+
return new Promise((resolve4, reject) => {
|
|
10183
10198
|
const timeout = setTimeout(() => {
|
|
10184
10199
|
this.off("task.completed", handler);
|
|
10185
10200
|
reject(new Error(`awaitTasks timed out waiting for task "${id}"`));
|
|
@@ -10188,7 +10203,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
10188
10203
|
if (result.taskId === id) {
|
|
10189
10204
|
clearTimeout(timeout);
|
|
10190
10205
|
this.off("task.completed", handler);
|
|
10191
|
-
|
|
10206
|
+
resolve4(result);
|
|
10192
10207
|
}
|
|
10193
10208
|
};
|
|
10194
10209
|
this.on("task.completed", handler);
|
|
@@ -10477,6 +10492,12 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
10477
10492
|
}
|
|
10478
10493
|
recordCompletion(result) {
|
|
10479
10494
|
this.completedResults.push(result);
|
|
10495
|
+
if (this.completedResults.length > _DefaultMultiAgentCoordinator.MAX_COMPLETED_RESULTS) {
|
|
10496
|
+
this.completedResults.splice(
|
|
10497
|
+
0,
|
|
10498
|
+
this.completedResults.length - _DefaultMultiAgentCoordinator.MAX_COMPLETED_RESULTS
|
|
10499
|
+
);
|
|
10500
|
+
}
|
|
10480
10501
|
this.totalIterations += result.iterations;
|
|
10481
10502
|
if (this.inFlight > 0) {
|
|
10482
10503
|
this.inFlight--;
|
|
@@ -10546,7 +10567,29 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
10546
10567
|
}
|
|
10547
10568
|
this.subagents.delete(subagentId);
|
|
10548
10569
|
this.terminating.delete(subagentId);
|
|
10570
|
+
const nicknameKey = this.subagentNicknames.get(subagentId);
|
|
10571
|
+
if (nicknameKey) {
|
|
10572
|
+
this.usedNicknames.delete(nicknameKey);
|
|
10573
|
+
this.subagentNicknames.delete(subagentId);
|
|
10574
|
+
}
|
|
10575
|
+
const orphaned = this.pendingTasks.filter((t) => t.subagentId === subagentId);
|
|
10549
10576
|
this.pendingTasks = this.pendingTasks.filter((t) => t.subagentId !== subagentId);
|
|
10577
|
+
for (const t of orphaned) {
|
|
10578
|
+
const synthetic = {
|
|
10579
|
+
subagentId,
|
|
10580
|
+
taskId: t.id,
|
|
10581
|
+
status: "stopped",
|
|
10582
|
+
error: {
|
|
10583
|
+
kind: "aborted_by_parent",
|
|
10584
|
+
message: `Subagent "${subagentId}" was removed while task "${t.id}" was pending`,
|
|
10585
|
+
retryable: false
|
|
10586
|
+
},
|
|
10587
|
+
iterations: 0,
|
|
10588
|
+
toolCalls: 0,
|
|
10589
|
+
durationMs: 0
|
|
10590
|
+
};
|
|
10591
|
+
this.recordCompletion(synthetic);
|
|
10592
|
+
}
|
|
10550
10593
|
this.fleetBus?.emit({
|
|
10551
10594
|
subagentId,
|
|
10552
10595
|
ts: Date.now(),
|
|
@@ -10663,7 +10706,7 @@ function providerErrorToSubagentError(err, message, cause) {
|
|
|
10663
10706
|
|
|
10664
10707
|
// src/execution/parallel-eternal-engine.ts
|
|
10665
10708
|
function sleep2(ms) {
|
|
10666
|
-
return new Promise((
|
|
10709
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
10667
10710
|
}
|
|
10668
10711
|
var GOAL_COMPLETE_MARKER2 = /^\s*\[goal[_\s-]?complete\]\s*$/im;
|
|
10669
10712
|
var ParallelEternalEngine = class {
|
|
@@ -11161,6 +11204,80 @@ function buildGoalPreamble(goal) {
|
|
|
11161
11204
|
// src/coordination/director.ts
|
|
11162
11205
|
init_atomic_write();
|
|
11163
11206
|
|
|
11207
|
+
// src/coordination/large-answer-store.ts
|
|
11208
|
+
var LargeAnswerStore = class {
|
|
11209
|
+
/**
|
|
11210
|
+
* Responses above this size (in characters) are stored out-of-context.
|
|
11211
|
+
* Below this, the full answer is returned inline (no overhead).
|
|
11212
|
+
* Default: 2000 chars ≈ 400-600 tokens.
|
|
11213
|
+
*/
|
|
11214
|
+
sizeThreshold;
|
|
11215
|
+
store = /* @__PURE__ */ new Map();
|
|
11216
|
+
constructor(sizeThreshold = 2e3) {
|
|
11217
|
+
this.sizeThreshold = sizeThreshold;
|
|
11218
|
+
}
|
|
11219
|
+
/**
|
|
11220
|
+
* Store a value, returning a summary + key for inline use.
|
|
11221
|
+
* If the value is below sizeThreshold, returns it as-is (no store entry).
|
|
11222
|
+
*/
|
|
11223
|
+
storeAnswer(value) {
|
|
11224
|
+
if (value === void 0 || value === null) {
|
|
11225
|
+
return { summary: String(value), inline: true };
|
|
11226
|
+
}
|
|
11227
|
+
const serialized = typeof value === "string" ? value : JSON.stringify(value);
|
|
11228
|
+
const size = serialized.length;
|
|
11229
|
+
if (size <= this.sizeThreshold) {
|
|
11230
|
+
return { summary: serialized.slice(0, 500), inline: true };
|
|
11231
|
+
}
|
|
11232
|
+
const key = `a-${hashStr(serialized)}`;
|
|
11233
|
+
this.store.set(key, {
|
|
11234
|
+
key,
|
|
11235
|
+
value,
|
|
11236
|
+
size,
|
|
11237
|
+
storedAt: Date.now()
|
|
11238
|
+
});
|
|
11239
|
+
return {
|
|
11240
|
+
key,
|
|
11241
|
+
summary: `[stored: ${size} chars \u2014 use roll_up or ask_result tool to retrieve, key=${key}]`,
|
|
11242
|
+
inline: false
|
|
11243
|
+
};
|
|
11244
|
+
}
|
|
11245
|
+
/**
|
|
11246
|
+
* Retrieve a previously stored answer by its key.
|
|
11247
|
+
* Returns undefined if the key is unknown or the store was cleared.
|
|
11248
|
+
*/
|
|
11249
|
+
retrieveAnswer(key) {
|
|
11250
|
+
return this.store.get(key)?.value;
|
|
11251
|
+
}
|
|
11252
|
+
/**
|
|
11253
|
+
* Check if a key exists in the store.
|
|
11254
|
+
*/
|
|
11255
|
+
hasAnswer(key) {
|
|
11256
|
+
return this.store.has(key);
|
|
11257
|
+
}
|
|
11258
|
+
/** Number of stored entries. */
|
|
11259
|
+
get size() {
|
|
11260
|
+
return this.store.size;
|
|
11261
|
+
}
|
|
11262
|
+
/** Total characters stored. */
|
|
11263
|
+
get totalChars() {
|
|
11264
|
+
let total = 0;
|
|
11265
|
+
for (const e of this.store.values()) total += e.size;
|
|
11266
|
+
return total;
|
|
11267
|
+
}
|
|
11268
|
+
/** Clear all stored entries. Call at the end of a director run. */
|
|
11269
|
+
clear() {
|
|
11270
|
+
this.store.clear();
|
|
11271
|
+
}
|
|
11272
|
+
};
|
|
11273
|
+
function hashStr(s) {
|
|
11274
|
+
let h = 5381;
|
|
11275
|
+
for (let i = 0; i < s.length; i++) {
|
|
11276
|
+
h = h * 33 ^ s.charCodeAt(i);
|
|
11277
|
+
}
|
|
11278
|
+
return (h >>> 0).toString(36);
|
|
11279
|
+
}
|
|
11280
|
+
|
|
11164
11281
|
// src/coordination/in-memory-transport.ts
|
|
11165
11282
|
var InMemoryBridgeTransport = class {
|
|
11166
11283
|
subs = /* @__PURE__ */ new Map();
|
|
@@ -11258,7 +11375,7 @@ var InMemoryAgentBridge = class {
|
|
|
11258
11375
|
);
|
|
11259
11376
|
}
|
|
11260
11377
|
this.inflightGuards.add(correlationId);
|
|
11261
|
-
return new Promise((
|
|
11378
|
+
return new Promise((resolve4, reject) => {
|
|
11262
11379
|
const timer = setTimeout(() => {
|
|
11263
11380
|
this.inflightGuards.delete(correlationId);
|
|
11264
11381
|
this.pendingRequests.delete(correlationId);
|
|
@@ -11270,7 +11387,7 @@ var InMemoryAgentBridge = class {
|
|
|
11270
11387
|
return;
|
|
11271
11388
|
}
|
|
11272
11389
|
this.pendingRequests.set(correlationId, {
|
|
11273
|
-
resolve:
|
|
11390
|
+
resolve: resolve4,
|
|
11274
11391
|
reject,
|
|
11275
11392
|
timer
|
|
11276
11393
|
});
|
|
@@ -11592,9 +11709,12 @@ function makeSpawnTool(director, roster) {
|
|
|
11592
11709
|
provider: { type: "string", description: 'Provider id (e.g. "anthropic", "openai"). Defaults to the leader provider when omitted.' },
|
|
11593
11710
|
model: { type: "string", description: "Model id within the provider. Defaults to the leader model when omitted." },
|
|
11594
11711
|
systemPromptOverride: { type: "string", description: "Extra prompt text appended after the role-base prompt." },
|
|
11595
|
-
maxIterations: { type: "number" },
|
|
11596
|
-
maxToolCalls: { type: "number" },
|
|
11597
|
-
maxCostUsd: { type: "number" }
|
|
11712
|
+
maxIterations: { type: "number", minimum: 1 },
|
|
11713
|
+
maxToolCalls: { type: "number", minimum: 1 },
|
|
11714
|
+
maxCostUsd: { type: "number", minimum: 0 },
|
|
11715
|
+
timeoutMs: { type: "number", minimum: 1, description: "Hard wall-clock cap in milliseconds. Defaults to none (idle timeout is the default reaper)." },
|
|
11716
|
+
idleTimeoutMs: { type: "number", minimum: 1, description: "Idle timeout in ms: reap the subagent after this long with no activity. Resets on every iteration/tool call. Default is role/coordinator-specific." },
|
|
11717
|
+
maxTokens: { type: "number", minimum: 1, description: "Maximum total tokens (input + output) the subagent may use." }
|
|
11598
11718
|
},
|
|
11599
11719
|
required: []
|
|
11600
11720
|
};
|
|
@@ -11640,6 +11760,9 @@ function makeSpawnTool(director, roster) {
|
|
|
11640
11760
|
if (typeof i.maxIterations === "number") cfg.maxIterations = i.maxIterations;
|
|
11641
11761
|
if (typeof i.maxToolCalls === "number") cfg.maxToolCalls = i.maxToolCalls;
|
|
11642
11762
|
if (typeof i.maxCostUsd === "number") cfg.maxCostUsd = i.maxCostUsd;
|
|
11763
|
+
if (typeof i.timeoutMs === "number") cfg.timeoutMs = i.timeoutMs;
|
|
11764
|
+
if (typeof i.idleTimeoutMs === "number") cfg.idleTimeoutMs = i.idleTimeoutMs;
|
|
11765
|
+
if (typeof i.maxTokens === "number") cfg.maxTokens = i.maxTokens;
|
|
11643
11766
|
try {
|
|
11644
11767
|
const subagentId = await director.spawn(cfg);
|
|
11645
11768
|
return { subagentId, provider: cfg.provider, model: cfg.model, name: cfg.name, role: cfg.role };
|
|
@@ -11667,10 +11790,10 @@ function makeAssignTool(director) {
|
|
|
11667
11790
|
const inputSchema = {
|
|
11668
11791
|
type: "object",
|
|
11669
11792
|
properties: {
|
|
11670
|
-
subagentId: { type: "string", description: "Target subagent id. Required." },
|
|
11671
|
-
description: { type: "string", description: "The task in natural language \u2014 what you want this subagent to do." },
|
|
11672
|
-
maxToolCalls: { type: "number", description: "Optional per-task tool-call budget override." },
|
|
11673
|
-
timeoutMs: { type: "number", description: "Optional per-task timeout in ms." }
|
|
11793
|
+
subagentId: { type: "string", minLength: 1, description: "Target subagent id. Required." },
|
|
11794
|
+
description: { type: "string", minLength: 1, description: "The task in natural language \u2014 what you want this subagent to do." },
|
|
11795
|
+
maxToolCalls: { type: "number", minimum: 1, description: "Optional per-task tool-call budget override." },
|
|
11796
|
+
timeoutMs: { type: "number", minimum: 1, description: "Optional per-task timeout in ms." }
|
|
11674
11797
|
},
|
|
11675
11798
|
required: ["subagentId", "description"]
|
|
11676
11799
|
};
|
|
@@ -11711,9 +11834,9 @@ function makeAskTool(director) {
|
|
|
11711
11834
|
inputSchema: {
|
|
11712
11835
|
type: "object",
|
|
11713
11836
|
properties: {
|
|
11714
|
-
subagentId: { type: "string", description: "Subagent to ask. Must be a previously spawned id." },
|
|
11715
|
-
question: { type: "string", description: "The question or instruction." },
|
|
11716
|
-
timeoutMs: { type: "number", description: "Optional timeout in ms (default 30s)." }
|
|
11837
|
+
subagentId: { type: "string", minLength: 1, description: "Subagent to ask. Must be a previously spawned id." },
|
|
11838
|
+
question: { type: "string", minLength: 1, description: "The question or instruction." },
|
|
11839
|
+
timeoutMs: { type: "number", minimum: 1, description: "Optional timeout in ms (default 30s)." }
|
|
11717
11840
|
},
|
|
11718
11841
|
required: ["subagentId", "question"]
|
|
11719
11842
|
},
|
|
@@ -11721,13 +11844,49 @@ function makeAskTool(director) {
|
|
|
11721
11844
|
const i = input;
|
|
11722
11845
|
try {
|
|
11723
11846
|
const answer = await director.ask(i.subagentId, { question: i.question }, i.timeoutMs);
|
|
11724
|
-
|
|
11847
|
+
const stored = director.largeAnswerStore.storeAnswer(answer);
|
|
11848
|
+
if (stored.inline) {
|
|
11849
|
+
return { ok: true, answer: stored.summary };
|
|
11850
|
+
}
|
|
11851
|
+
return {
|
|
11852
|
+
ok: true,
|
|
11853
|
+
answer: stored.summary,
|
|
11854
|
+
_answerKey: stored.key,
|
|
11855
|
+
_hint: "Response was large and stored. Use ask_result with the key to retrieve it."
|
|
11856
|
+
};
|
|
11725
11857
|
} catch (err) {
|
|
11726
11858
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
11727
11859
|
}
|
|
11728
11860
|
}
|
|
11729
11861
|
};
|
|
11730
11862
|
}
|
|
11863
|
+
function makeAskResultTool(director) {
|
|
11864
|
+
return {
|
|
11865
|
+
name: "ask_result",
|
|
11866
|
+
description: "Retrieve a large `ask_subagent` response that was stored out-of-context (>2K chars). Returns the full stored value.",
|
|
11867
|
+
permission: "auto",
|
|
11868
|
+
mutating: false,
|
|
11869
|
+
inputSchema: {
|
|
11870
|
+
type: "object",
|
|
11871
|
+
properties: {
|
|
11872
|
+
key: {
|
|
11873
|
+
type: "string",
|
|
11874
|
+
minLength: 1,
|
|
11875
|
+
description: "The `_answerKey` returned by `ask_subagent` for a large response."
|
|
11876
|
+
}
|
|
11877
|
+
},
|
|
11878
|
+
required: ["key"]
|
|
11879
|
+
},
|
|
11880
|
+
async execute(input) {
|
|
11881
|
+
const i = input;
|
|
11882
|
+
const value = director.largeAnswerStore.retrieveAnswer(i.key);
|
|
11883
|
+
if (value === void 0) {
|
|
11884
|
+
return { ok: false, error: `No stored answer found for key "${i.key}" \u2014 it may have been cleared or the key is invalid.` };
|
|
11885
|
+
}
|
|
11886
|
+
return { ok: true, value };
|
|
11887
|
+
}
|
|
11888
|
+
};
|
|
11889
|
+
}
|
|
11731
11890
|
function makeRollUpTool(director) {
|
|
11732
11891
|
return {
|
|
11733
11892
|
name: "roll_up",
|
|
@@ -11881,6 +12040,7 @@ function makeCollabDebugTool(director) {
|
|
|
11881
12040
|
},
|
|
11882
12041
|
timeoutMs: {
|
|
11883
12042
|
type: "number",
|
|
12043
|
+
minimum: 1,
|
|
11884
12044
|
description: "Timeout in ms. Default: 600000 (10 minutes)."
|
|
11885
12045
|
}
|
|
11886
12046
|
},
|
|
@@ -11960,6 +12120,122 @@ function makeWorkCompleteTool(director) {
|
|
|
11960
12120
|
}
|
|
11961
12121
|
};
|
|
11962
12122
|
}
|
|
12123
|
+
var GLOB_CHARS = /* @__PURE__ */ new Set(["*", "?", "["]);
|
|
12124
|
+
var IS_WINDOWS = process.platform === "win32";
|
|
12125
|
+
var SEP = IS_WINDOWS ? "\\" : "/";
|
|
12126
|
+
function isGlob(p) {
|
|
12127
|
+
for (const c of p) {
|
|
12128
|
+
if (GLOB_CHARS.has(c)) return true;
|
|
12129
|
+
}
|
|
12130
|
+
return false;
|
|
12131
|
+
}
|
|
12132
|
+
function globToRegex(pat) {
|
|
12133
|
+
let i = 0, re = "^";
|
|
12134
|
+
while (i < pat.length) {
|
|
12135
|
+
const c = pat[i];
|
|
12136
|
+
if (c === "*") {
|
|
12137
|
+
if (pat[i + 1] === "*") {
|
|
12138
|
+
re += ".*";
|
|
12139
|
+
i += 2;
|
|
12140
|
+
if (pat[i] === "/") i++;
|
|
12141
|
+
} else {
|
|
12142
|
+
re += "[^/\\\\]*";
|
|
12143
|
+
i++;
|
|
12144
|
+
}
|
|
12145
|
+
} else if (c === "?") {
|
|
12146
|
+
re += "[^/\\\\]";
|
|
12147
|
+
i++;
|
|
12148
|
+
} else if (c === "[") {
|
|
12149
|
+
let cls = "[";
|
|
12150
|
+
i++;
|
|
12151
|
+
if (pat[i] === "!" || pat[i] === "^") {
|
|
12152
|
+
cls += "^";
|
|
12153
|
+
i++;
|
|
12154
|
+
}
|
|
12155
|
+
while (i < pat.length && pat[i] !== "]") {
|
|
12156
|
+
const ch = pat[i] ?? "";
|
|
12157
|
+
if (ch === "\\") cls += "\\\\";
|
|
12158
|
+
else if (ch === "]" || ch === "^") cls += `\\${ch}`;
|
|
12159
|
+
else cls += ch;
|
|
12160
|
+
i++;
|
|
12161
|
+
}
|
|
12162
|
+
cls += "]";
|
|
12163
|
+
re += cls;
|
|
12164
|
+
i++;
|
|
12165
|
+
} else {
|
|
12166
|
+
re += c.replace(/[.+^${}()|\\]/g, "\\$&");
|
|
12167
|
+
i++;
|
|
12168
|
+
}
|
|
12169
|
+
}
|
|
12170
|
+
return new RegExp(re + "$");
|
|
12171
|
+
}
|
|
12172
|
+
function baseDir(pat) {
|
|
12173
|
+
let i = pat.length - 1;
|
|
12174
|
+
while (i >= 0 && !GLOB_CHARS.has(pat[i]) && pat[i] !== SEP && pat[i] !== "/") i--;
|
|
12175
|
+
const cut = i >= 0 ? pat.lastIndexOf(SEP, i) : pat.lastIndexOf("/", i);
|
|
12176
|
+
return cut < 0 ? "." : pat.slice(0, cut);
|
|
12177
|
+
}
|
|
12178
|
+
async function expandGlob(pattern) {
|
|
12179
|
+
if (!isGlob(pattern)) return [pattern];
|
|
12180
|
+
const results = /* @__PURE__ */ new Set();
|
|
12181
|
+
const abs = isAbsolute(pattern);
|
|
12182
|
+
const base = abs ? baseDir(pattern) : baseDir(pattern);
|
|
12183
|
+
const relPat = base === "." ? pattern : pattern.slice(base.length + 1);
|
|
12184
|
+
async function walk4(dir, pat) {
|
|
12185
|
+
let entries;
|
|
12186
|
+
try {
|
|
12187
|
+
entries = await fsp.readdir(dir);
|
|
12188
|
+
} catch {
|
|
12189
|
+
return;
|
|
12190
|
+
}
|
|
12191
|
+
const firstGlob = pat.search(/[*?[\[]/);
|
|
12192
|
+
if (firstGlob < 0) {
|
|
12193
|
+
const re = globToRegex(pat);
|
|
12194
|
+
for (const e of entries) {
|
|
12195
|
+
if (re.test(e)) {
|
|
12196
|
+
const full = `${dir}${SEP}${e}`;
|
|
12197
|
+
results.add(abs ? resolve(full) : full);
|
|
12198
|
+
}
|
|
12199
|
+
}
|
|
12200
|
+
return;
|
|
12201
|
+
}
|
|
12202
|
+
const before = pat.slice(0, firstGlob);
|
|
12203
|
+
const rest = pat.slice(firstGlob);
|
|
12204
|
+
if (before.endsWith("**")) {
|
|
12205
|
+
await walk4(dir, rest);
|
|
12206
|
+
for (const e of entries) {
|
|
12207
|
+
const full = `${dir}${SEP}${e}`;
|
|
12208
|
+
try {
|
|
12209
|
+
const stat5 = await fsp.stat(full);
|
|
12210
|
+
if (stat5.isDirectory()) await walk4(full, rest);
|
|
12211
|
+
} catch {
|
|
12212
|
+
}
|
|
12213
|
+
}
|
|
12214
|
+
} else if (before === "") {
|
|
12215
|
+
const re = globToRegex(rest);
|
|
12216
|
+
for (const e of entries) {
|
|
12217
|
+
if (re.test(e)) {
|
|
12218
|
+
const full = `${dir}${SEP}${e}`;
|
|
12219
|
+
results.add(abs ? resolve(full) : full);
|
|
12220
|
+
}
|
|
12221
|
+
}
|
|
12222
|
+
} else {
|
|
12223
|
+
const seg = before.replace(/[*?[\]]/g, "").replace(/\/$/, "");
|
|
12224
|
+
if (entries.includes(seg)) {
|
|
12225
|
+
const full = `${dir}${SEP}${seg}`;
|
|
12226
|
+
try {
|
|
12227
|
+
const stat5 = await fsp.stat(full);
|
|
12228
|
+
if (stat5.isDirectory()) await walk4(full, rest);
|
|
12229
|
+
} catch {
|
|
12230
|
+
}
|
|
12231
|
+
}
|
|
12232
|
+
}
|
|
12233
|
+
}
|
|
12234
|
+
await walk4(base === "." ? "." : base, relPat);
|
|
12235
|
+
return [...results];
|
|
12236
|
+
}
|
|
12237
|
+
|
|
12238
|
+
// src/coordination/collab-debug.ts
|
|
11963
12239
|
var CollabSession = class extends EventEmitter {
|
|
11964
12240
|
sessionId;
|
|
11965
12241
|
options;
|
|
@@ -12018,7 +12294,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
12018
12294
|
}
|
|
12019
12295
|
async buildSnapshot() {
|
|
12020
12296
|
if (this.snapshot.files.length > 0) return this.snapshot;
|
|
12021
|
-
for (const filePath of this.options.targetPaths) {
|
|
12297
|
+
for (const filePath of (await Promise.all(this.options.targetPaths.map((p) => expandGlob(p)))).flat()) {
|
|
12022
12298
|
try {
|
|
12023
12299
|
const content = await fsp.readFile(filePath, "utf8");
|
|
12024
12300
|
const ext = filePath.split(".").pop() ?? "";
|
|
@@ -12074,7 +12350,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
12074
12350
|
reject(new Error(`CollabSession timed out after ${this.timeoutMs}ms`));
|
|
12075
12351
|
}, this.timeoutMs);
|
|
12076
12352
|
});
|
|
12077
|
-
let results;
|
|
12353
|
+
let results = null;
|
|
12078
12354
|
try {
|
|
12079
12355
|
results = await Promise.race([
|
|
12080
12356
|
Promise.all([
|
|
@@ -12505,7 +12781,7 @@ var FleetContextOverflowError = class extends Error {
|
|
|
12505
12781
|
this.observed = observed;
|
|
12506
12782
|
}
|
|
12507
12783
|
};
|
|
12508
|
-
var Director = class {
|
|
12784
|
+
var Director = class _Director {
|
|
12509
12785
|
/** Alias for the ICoordinator contract. `id` is retained for backward compatibility. */
|
|
12510
12786
|
get coordinatorId() {
|
|
12511
12787
|
return this.id;
|
|
@@ -12563,6 +12839,8 @@ var Director = class {
|
|
|
12563
12839
|
* coordinator already fired the event — `awaitTasks(['t-1'])` after
|
|
12564
12840
|
* t-1 finished should resolve immediately, not hang. */
|
|
12565
12841
|
completed = /* @__PURE__ */ new Map();
|
|
12842
|
+
/** Prevents the completed Map from growing unbounded in long-running directors. */
|
|
12843
|
+
static MAX_COMPLETED = 1e4;
|
|
12566
12844
|
/** Per-subagent provider/model metadata, captured at spawn time so the
|
|
12567
12845
|
* FleetUsageAggregator's metaLookup can surface readable rows. */
|
|
12568
12846
|
subagentMeta = /* @__PURE__ */ new Map();
|
|
@@ -12642,6 +12920,8 @@ var Director = class {
|
|
|
12642
12920
|
_leaderBtwNotes = [];
|
|
12643
12921
|
/** Active collab sessions tracked by sessionId (see spawnCollab). */
|
|
12644
12922
|
_activeCollabSessions = /* @__PURE__ */ new Map();
|
|
12923
|
+
/** Prevents large `ask_subagent` answers from bloating the leader's context window. */
|
|
12924
|
+
largeAnswerStore;
|
|
12645
12925
|
constructor(opts) {
|
|
12646
12926
|
this.id = opts.config.coordinatorId || randomUUID();
|
|
12647
12927
|
this.manifestPath = opts.manifestPath;
|
|
@@ -12702,6 +12982,11 @@ var Director = class {
|
|
|
12702
12982
|
this.taskCompletedListener = (payload) => {
|
|
12703
12983
|
const r = payload.result;
|
|
12704
12984
|
this.completed.set(r.taskId, r);
|
|
12985
|
+
if (this.completed.size > _Director.MAX_COMPLETED) {
|
|
12986
|
+
const toDelete = this.completed.size - _Director.MAX_COMPLETED;
|
|
12987
|
+
const keys = [...this.completed.keys()].slice(0, toDelete);
|
|
12988
|
+
for (const k of keys) this.completed.delete(k);
|
|
12989
|
+
}
|
|
12705
12990
|
const waiter = this.taskWaiters.get(r.taskId);
|
|
12706
12991
|
if (waiter) {
|
|
12707
12992
|
waiter.resolve(r);
|
|
@@ -12808,6 +13093,7 @@ var Director = class {
|
|
|
12808
13093
|
payload.extend(extra);
|
|
12809
13094
|
});
|
|
12810
13095
|
});
|
|
13096
|
+
this.largeAnswerStore = new LargeAnswerStore(2e3);
|
|
12811
13097
|
}
|
|
12812
13098
|
/**
|
|
12813
13099
|
* Record a granted budget extension and broadcast it on the FleetBus so
|
|
@@ -13288,11 +13574,11 @@ var Director = class {
|
|
|
13288
13574
|
if (cached) return cached;
|
|
13289
13575
|
const existing = this.taskWaiters.get(id);
|
|
13290
13576
|
if (existing) return existing.promise;
|
|
13291
|
-
let
|
|
13577
|
+
let resolve4;
|
|
13292
13578
|
const promise = new Promise((res) => {
|
|
13293
|
-
|
|
13579
|
+
resolve4 = res;
|
|
13294
13580
|
});
|
|
13295
|
-
this.taskWaiters.set(id, { promise, resolve:
|
|
13581
|
+
this.taskWaiters.set(id, { promise, resolve: resolve4 });
|
|
13296
13582
|
return promise;
|
|
13297
13583
|
})
|
|
13298
13584
|
);
|
|
@@ -13305,7 +13591,24 @@ var Director = class {
|
|
|
13305
13591
|
}
|
|
13306
13592
|
async remove(subagentId) {
|
|
13307
13593
|
await this.coordinator.remove(subagentId);
|
|
13594
|
+
const bridge = this.subagentBridges.get(subagentId);
|
|
13595
|
+
if (bridge) {
|
|
13596
|
+
await bridge.stop();
|
|
13597
|
+
this.subagentBridges.delete(subagentId);
|
|
13598
|
+
}
|
|
13308
13599
|
this.usage.removeSubagent(subagentId);
|
|
13600
|
+
if (this.fleetManager) {
|
|
13601
|
+
this.fleetManager.removeSubagent(subagentId);
|
|
13602
|
+
} else {
|
|
13603
|
+
const entry = this.manifestEntries.get(subagentId);
|
|
13604
|
+
if (entry?.name) {
|
|
13605
|
+
const nicknameKey = entry.name.split(" ")[0].toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
13606
|
+
this._usedNicknames.delete(nicknameKey);
|
|
13607
|
+
}
|
|
13608
|
+
}
|
|
13609
|
+
this.manifestEntries.delete(subagentId);
|
|
13610
|
+
this.taskOwners.delete(subagentId);
|
|
13611
|
+
this.taskDescriptions.delete(subagentId);
|
|
13309
13612
|
}
|
|
13310
13613
|
status() {
|
|
13311
13614
|
const base = this.coordinator.getStatus();
|
|
@@ -13467,6 +13770,7 @@ var Director = class {
|
|
|
13467
13770
|
makeAssignTool(this),
|
|
13468
13771
|
makeAwaitTasksTool(this),
|
|
13469
13772
|
makeAskTool(this),
|
|
13773
|
+
makeAskResultTool(this),
|
|
13470
13774
|
makeRollUpTool(this),
|
|
13471
13775
|
makeTerminateTool(this),
|
|
13472
13776
|
makeTerminateAllTool(this),
|
|
@@ -13549,15 +13853,33 @@ function createDelegateTool(opts) {
|
|
|
13549
13853
|
},
|
|
13550
13854
|
timeoutMs: {
|
|
13551
13855
|
type: "number",
|
|
13856
|
+
minimum: 1,
|
|
13552
13857
|
description: `Wall-clock budget for this delegate in milliseconds. No hard cap \u2014 set as high as the task realistically needs (a monorepo audit can take hours, a single-file lint takes seconds). Default ${Math.round(defaultTimeoutMs / 1e3 / 60)} minutes.`
|
|
13553
13858
|
},
|
|
13554
13859
|
maxIterations: {
|
|
13555
13860
|
type: "number",
|
|
13861
|
+
minimum: 1,
|
|
13556
13862
|
description: "Maximum LLM iterations the subagent may take. Unset = use the role/coordinator default. Raise this for tasks with many tool-think-tool cycles (deep code analysis, multi-file refactors)."
|
|
13557
13863
|
},
|
|
13558
13864
|
maxToolCalls: {
|
|
13559
13865
|
type: "number",
|
|
13866
|
+
minimum: 1,
|
|
13560
13867
|
description: "Maximum number of tool invocations the subagent may make. Unset = use the role/coordinator default. Raise this for tasks that touch many files (large grep + read + report)."
|
|
13868
|
+
},
|
|
13869
|
+
idleTimeoutMs: {
|
|
13870
|
+
type: "number",
|
|
13871
|
+
minimum: 1,
|
|
13872
|
+
description: "Idle timeout in ms: reap the subagent after this long with no activity. Resets on every iteration/tool call. Unset = use the role/coordinator default."
|
|
13873
|
+
},
|
|
13874
|
+
maxTokens: {
|
|
13875
|
+
type: "number",
|
|
13876
|
+
minimum: 1,
|
|
13877
|
+
description: "Maximum total tokens (input + output) the subagent may use. Unset = use the role/coordinator default."
|
|
13878
|
+
},
|
|
13879
|
+
maxCostUsd: {
|
|
13880
|
+
type: "number",
|
|
13881
|
+
minimum: 0,
|
|
13882
|
+
description: "Maximum estimated USD cost the subagent may incur. Unset = use the role/coordinator default."
|
|
13561
13883
|
}
|
|
13562
13884
|
},
|
|
13563
13885
|
required: ["task"]
|
|
@@ -13615,12 +13937,21 @@ function createDelegateTool(opts) {
|
|
|
13615
13937
|
};
|
|
13616
13938
|
cfg = applyRosterBudget({ ...cfg, name: i.name });
|
|
13617
13939
|
}
|
|
13618
|
-
if (typeof i.maxIterations === "number"
|
|
13940
|
+
if (typeof i.maxIterations === "number") {
|
|
13619
13941
|
cfg.maxIterations = i.maxIterations;
|
|
13620
13942
|
}
|
|
13621
|
-
if (typeof i.maxToolCalls === "number"
|
|
13943
|
+
if (typeof i.maxToolCalls === "number") {
|
|
13622
13944
|
cfg.maxToolCalls = i.maxToolCalls;
|
|
13623
13945
|
}
|
|
13946
|
+
if (typeof i.idleTimeoutMs === "number") {
|
|
13947
|
+
cfg.idleTimeoutMs = i.idleTimeoutMs;
|
|
13948
|
+
}
|
|
13949
|
+
if (typeof i.maxTokens === "number") {
|
|
13950
|
+
cfg.maxTokens = i.maxTokens;
|
|
13951
|
+
}
|
|
13952
|
+
if (typeof i.maxCostUsd === "number") {
|
|
13953
|
+
cfg.maxCostUsd = i.maxCostUsd;
|
|
13954
|
+
}
|
|
13624
13955
|
const SUBAGENT_TIMEOUT_BUFFER_MS = opts.subagentTimeoutBufferMs ?? 6e4;
|
|
13625
13956
|
if (!cfg.timeoutMs) {
|
|
13626
13957
|
cfg.timeoutMs = Math.max(3e4, timeoutMs - SUBAGENT_TIMEOUT_BUFFER_MS);
|
|
@@ -13632,7 +13963,7 @@ function createDelegateTool(opts) {
|
|
|
13632
13963
|
subagentId
|
|
13633
13964
|
});
|
|
13634
13965
|
const dir = director;
|
|
13635
|
-
const result = await new Promise((
|
|
13966
|
+
const result = await new Promise((resolve4) => {
|
|
13636
13967
|
let settled = false;
|
|
13637
13968
|
let timer;
|
|
13638
13969
|
const finish = (value) => {
|
|
@@ -13642,7 +13973,7 @@ function createDelegateTool(opts) {
|
|
|
13642
13973
|
offTool();
|
|
13643
13974
|
offIter();
|
|
13644
13975
|
offProgress();
|
|
13645
|
-
|
|
13976
|
+
resolve4(value);
|
|
13646
13977
|
};
|
|
13647
13978
|
const arm = () => {
|
|
13648
13979
|
if (timer) clearTimeout(timer);
|
|
@@ -14554,8 +14885,8 @@ async function loadProjectModes(modesDir) {
|
|
|
14554
14885
|
for (const entry of entries) {
|
|
14555
14886
|
if (!entry.endsWith(".md") && !entry.endsWith(".txt")) continue;
|
|
14556
14887
|
const filePath = path15.join(modesDir, entry);
|
|
14557
|
-
const
|
|
14558
|
-
if (!
|
|
14888
|
+
const stat5 = await fsp.stat(filePath);
|
|
14889
|
+
if (!stat5.isFile()) continue;
|
|
14559
14890
|
const content = await fsp.readFile(filePath, "utf8");
|
|
14560
14891
|
const id = path15.basename(entry, path15.extname(entry));
|
|
14561
14892
|
modes.push({
|
|
@@ -15898,10 +16229,10 @@ var AISpecBuilder = class {
|
|
|
15898
16229
|
async saveSession() {
|
|
15899
16230
|
if (!this.sessionPath) return;
|
|
15900
16231
|
try {
|
|
15901
|
-
const
|
|
16232
|
+
const fsp16 = await import('fs/promises');
|
|
15902
16233
|
const path18 = await import('path');
|
|
15903
16234
|
const { atomicWrite: atomicWrite2 } = await Promise.resolve().then(() => (init_atomic_write(), atomic_write_exports));
|
|
15904
|
-
await
|
|
16235
|
+
await fsp16.mkdir(path18.dirname(this.sessionPath), { recursive: true });
|
|
15905
16236
|
await atomicWrite2(this.sessionPath, JSON.stringify(this.session, null, 2));
|
|
15906
16237
|
} catch {
|
|
15907
16238
|
}
|
|
@@ -15910,8 +16241,8 @@ var AISpecBuilder = class {
|
|
|
15910
16241
|
async loadSession() {
|
|
15911
16242
|
if (!this.sessionPath) return false;
|
|
15912
16243
|
try {
|
|
15913
|
-
const
|
|
15914
|
-
const raw = await
|
|
16244
|
+
const fsp16 = await import('fs/promises');
|
|
16245
|
+
const raw = await fsp16.readFile(this.sessionPath, "utf8");
|
|
15915
16246
|
const loaded = JSON.parse(raw);
|
|
15916
16247
|
if (loaded?.id && loaded?.phase && loaded?.title) {
|
|
15917
16248
|
this.session = loaded;
|
|
@@ -15925,8 +16256,8 @@ var AISpecBuilder = class {
|
|
|
15925
16256
|
async deleteSession() {
|
|
15926
16257
|
if (!this.sessionPath) return;
|
|
15927
16258
|
try {
|
|
15928
|
-
const
|
|
15929
|
-
await
|
|
16259
|
+
const fsp16 = await import('fs/promises');
|
|
16260
|
+
await fsp16.unlink(this.sessionPath);
|
|
15930
16261
|
} catch {
|
|
15931
16262
|
}
|
|
15932
16263
|
}
|
|
@@ -17412,9 +17743,9 @@ var DefaultHealthRegistry = class {
|
|
|
17412
17743
|
}
|
|
17413
17744
|
async runOne(check) {
|
|
17414
17745
|
let timer = null;
|
|
17415
|
-
const timeout = new Promise((
|
|
17746
|
+
const timeout = new Promise((resolve4) => {
|
|
17416
17747
|
timer = setTimeout(
|
|
17417
|
-
() =>
|
|
17748
|
+
() => resolve4({ status: "unhealthy", detail: `timeout after ${this.timeoutMs}ms` }),
|
|
17418
17749
|
this.timeoutMs
|
|
17419
17750
|
);
|
|
17420
17751
|
});
|
|
@@ -17653,14 +17984,14 @@ async function startMetricsServer(opts) {
|
|
|
17653
17984
|
const { createServer } = await import('http');
|
|
17654
17985
|
server = createServer(listener);
|
|
17655
17986
|
}
|
|
17656
|
-
await new Promise((
|
|
17987
|
+
await new Promise((resolve4, reject) => {
|
|
17657
17988
|
const onError = (err) => {
|
|
17658
17989
|
server.off("listening", onListening);
|
|
17659
17990
|
reject(err);
|
|
17660
17991
|
};
|
|
17661
17992
|
const onListening = () => {
|
|
17662
17993
|
server.off("error", onError);
|
|
17663
|
-
|
|
17994
|
+
resolve4();
|
|
17664
17995
|
};
|
|
17665
17996
|
server.once("error", onError);
|
|
17666
17997
|
server.once("listening", onListening);
|
|
@@ -17672,8 +18003,8 @@ async function startMetricsServer(opts) {
|
|
|
17672
18003
|
return {
|
|
17673
18004
|
port: boundPort,
|
|
17674
18005
|
url: `${protocol}://${host}:${boundPort}${path18}`,
|
|
17675
|
-
close: () => new Promise((
|
|
17676
|
-
server.close((err) => err ? reject(err) :
|
|
18006
|
+
close: () => new Promise((resolve4, reject) => {
|
|
18007
|
+
server.close((err) => err ? reject(err) : resolve4());
|
|
17677
18008
|
})
|
|
17678
18009
|
};
|
|
17679
18010
|
}
|