@wrongstack/core 0.7.5 → 0.7.6
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-BOBYkW_r.d.ts +174 -0
- package/dist/coordination/index.d.ts +5 -4
- package/dist/defaults/index.d.ts +8 -7
- package/dist/defaults/index.js +324 -38
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +4 -3
- package/dist/execution/index.js +11 -9
- package/dist/execution/index.js.map +1 -1
- package/dist/{goal-store-HHgaq5ue.d.ts → goal-store-C7jcumEh.d.ts} +2 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.js +344 -53
- package/dist/index.js.map +1 -1
- package/dist/{multi-agent-coordinator-D8PLzfz6.d.ts → multi-agent-coordinator-3Ypfg-hr.d.ts} +2 -173
- package/dist/{null-fleet-bus-Bkk3gafb.d.ts → null-fleet-bus-JdTSYJv9.d.ts} +2 -1
- package/dist/permission-policy-D5Gj1o2K.d.ts +111 -0
- package/dist/{plan-templates-DWbEIJvV.d.ts → plan-templates-C-IOLJ8Q.d.ts} +1 -1
- package/dist/sdd/index.d.ts +173 -2
- package/dist/sdd/index.js +3619 -1
- package/dist/sdd/index.js.map +1 -1
- package/dist/security/index.d.ts +6 -109
- package/dist/security/index.js +35 -11
- package/dist/security/index.js.map +1 -1
- package/dist/storage/index.d.ts +3 -3
- package/dist/storage/index.js +5 -4
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.js +25 -10
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +6 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-BGu2INTm.d.ts → wstack-paths-gCrJ631C.d.ts} +10 -0
- package/package.json +1 -1
package/dist/defaults/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as crypto2 from 'crypto';
|
|
2
|
-
import { randomBytes, randomUUID, createCipheriv, createDecipheriv } from 'crypto';
|
|
2
|
+
import { randomBytes, randomUUID, createCipheriv, createDecipheriv, createHash } from 'crypto';
|
|
3
3
|
import * as fsp from 'fs/promises';
|
|
4
4
|
import * as path3 from 'path';
|
|
5
5
|
import * as fs5 from 'fs';
|
|
@@ -88,7 +88,7 @@ async function renameWithRetry(from, to) {
|
|
|
88
88
|
if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {
|
|
89
89
|
throw err;
|
|
90
90
|
}
|
|
91
|
-
await new Promise((
|
|
91
|
+
await new Promise((resolve3) => setTimeout(resolve3, delays[i]));
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
throw lastErr;
|
|
@@ -1225,7 +1225,7 @@ function walk(node, vault, transform) {
|
|
|
1225
1225
|
if (Array.isArray(node)) {
|
|
1226
1226
|
return node.map((item) => walk(item, vault, transform));
|
|
1227
1227
|
}
|
|
1228
|
-
const out =
|
|
1228
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
1229
1229
|
for (const [k, v] of Object.entries(node)) {
|
|
1230
1230
|
if (typeof v === "string" && isSecretField(k)) {
|
|
1231
1231
|
out[k] = transform(v, k);
|
|
@@ -2752,7 +2752,9 @@ var DefaultSecretVault = class {
|
|
|
2752
2752
|
try {
|
|
2753
2753
|
const buf = fs5.readFileSync(this.keyFile);
|
|
2754
2754
|
if (buf.length !== KEY_BYTES) {
|
|
2755
|
-
throw new Error(
|
|
2755
|
+
throw new Error(
|
|
2756
|
+
`SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key.`
|
|
2757
|
+
);
|
|
2756
2758
|
}
|
|
2757
2759
|
this.key = buf;
|
|
2758
2760
|
return this.key;
|
|
@@ -2767,7 +2769,9 @@ var DefaultSecretVault = class {
|
|
|
2767
2769
|
if (err.code !== "EEXIST") throw err;
|
|
2768
2770
|
const buf = fs5.readFileSync(this.keyFile);
|
|
2769
2771
|
if (buf.length !== KEY_BYTES) {
|
|
2770
|
-
throw new Error(
|
|
2772
|
+
throw new Error(
|
|
2773
|
+
`SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES}). Remove it manually to generate a new key.`
|
|
2774
|
+
);
|
|
2771
2775
|
}
|
|
2772
2776
|
this.key = buf;
|
|
2773
2777
|
return this.key;
|
|
@@ -2828,10 +2832,7 @@ async function rewriteConfigEncrypted(configPath, vault, patch) {
|
|
|
2828
2832
|
const encrypted = encryptConfigSecrets(merged, vault);
|
|
2829
2833
|
await fsp.mkdir(path3.dirname(configPath), { recursive: true });
|
|
2830
2834
|
await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
2831
|
-
|
|
2832
|
-
await fsp.chmod(configPath, 384);
|
|
2833
|
-
} catch {
|
|
2834
|
-
}
|
|
2835
|
+
await restrictFilePermissions(configPath);
|
|
2835
2836
|
}
|
|
2836
2837
|
async function migratePlaintextSecrets(configPath, vault) {
|
|
2837
2838
|
let raw;
|
|
@@ -2850,12 +2851,26 @@ async function migratePlaintextSecrets(configPath, vault) {
|
|
|
2850
2851
|
const migrated = walkCount(parsed, vault, counter);
|
|
2851
2852
|
if (counter.n === 0) return { migrated: 0, file: configPath };
|
|
2852
2853
|
await atomicWrite(configPath, JSON.stringify(migrated, null, 2), { mode: 384 });
|
|
2853
|
-
|
|
2854
|
-
await fsp.chmod(configPath, 384);
|
|
2855
|
-
} catch {
|
|
2856
|
-
}
|
|
2854
|
+
await restrictFilePermissions(configPath);
|
|
2857
2855
|
return { migrated: counter.n, file: configPath };
|
|
2858
2856
|
}
|
|
2857
|
+
async function restrictFilePermissions(filePath) {
|
|
2858
|
+
if (process.platform === "win32") {
|
|
2859
|
+
try {
|
|
2860
|
+
const { execFile: execFile2 } = await import('child_process');
|
|
2861
|
+
const { promisify: promisify2 } = await import('util');
|
|
2862
|
+
const execFileAsync = promisify2(execFile2);
|
|
2863
|
+
await execFileAsync("icacls", [filePath, "/inheritance:r", "/grant:r", `${process.env.USERNAME}:(F)`]);
|
|
2864
|
+
} catch {
|
|
2865
|
+
console.warn(`[secret-vault] Could not restrict permissions on ${filePath} \u2014 config file may be readable by other users on this system.`);
|
|
2866
|
+
}
|
|
2867
|
+
} else {
|
|
2868
|
+
try {
|
|
2869
|
+
await fsp.chmod(filePath, 384);
|
|
2870
|
+
} catch {
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2859
2874
|
function walkCount(node, vault, counter) {
|
|
2860
2875
|
if (node === null || node === void 0) return node;
|
|
2861
2876
|
if (typeof node !== "object") return node;
|
|
@@ -3822,8 +3837,8 @@ async function streamProviderToResponse(provider, req, signal, ctx, events) {
|
|
|
3822
3837
|
try {
|
|
3823
3838
|
await Promise.race([
|
|
3824
3839
|
Promise.resolve(iter.return?.()),
|
|
3825
|
-
new Promise((
|
|
3826
|
-
drainTimer = setTimeout(
|
|
3840
|
+
new Promise((resolve3) => {
|
|
3841
|
+
drainTimer = setTimeout(resolve3, 500);
|
|
3827
3842
|
})
|
|
3828
3843
|
]);
|
|
3829
3844
|
} finally {
|
|
@@ -3884,7 +3899,7 @@ async function runProviderWithRetry(opts) {
|
|
|
3884
3899
|
description
|
|
3885
3900
|
});
|
|
3886
3901
|
}
|
|
3887
|
-
await new Promise((
|
|
3902
|
+
await new Promise((resolve3, reject) => {
|
|
3888
3903
|
let settled = false;
|
|
3889
3904
|
const onAbort = () => {
|
|
3890
3905
|
if (settled) return;
|
|
@@ -3897,7 +3912,7 @@ async function runProviderWithRetry(opts) {
|
|
|
3897
3912
|
settled = true;
|
|
3898
3913
|
clearTimeout(t);
|
|
3899
3914
|
signal.removeEventListener("abort", onAbort);
|
|
3900
|
-
|
|
3915
|
+
resolve3();
|
|
3901
3916
|
}, delay);
|
|
3902
3917
|
if (signal.aborted) {
|
|
3903
3918
|
onAbort();
|
|
@@ -5417,7 +5432,8 @@ var AutonomousRunner = class {
|
|
|
5417
5432
|
init_atomic_write();
|
|
5418
5433
|
var MAX_JOURNAL_ENTRIES = 500;
|
|
5419
5434
|
function goalFilePath(projectRoot) {
|
|
5420
|
-
|
|
5435
|
+
const hash = createHash("sha256").update(path3.resolve(projectRoot)).digest("hex").slice(0, 12);
|
|
5436
|
+
return path3.join(os.homedir(), ".wrongstack", "projects", hash, "goal.json");
|
|
5421
5437
|
}
|
|
5422
5438
|
async function loadGoal(filePath) {
|
|
5423
5439
|
let raw;
|
|
@@ -6032,7 +6048,7 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
6032
6048
|
}
|
|
6033
6049
|
};
|
|
6034
6050
|
function sleep(ms) {
|
|
6035
|
-
return new Promise((
|
|
6051
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
6036
6052
|
}
|
|
6037
6053
|
|
|
6038
6054
|
// src/coordination/subagent-budget.ts
|
|
@@ -6169,12 +6185,12 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
6169
6185
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
6170
6186
|
return Promise.resolve("stop");
|
|
6171
6187
|
}
|
|
6172
|
-
return new Promise((
|
|
6188
|
+
return new Promise((resolve3) => {
|
|
6173
6189
|
let resolved = false;
|
|
6174
6190
|
const respond = (d) => {
|
|
6175
6191
|
if (resolved) return;
|
|
6176
6192
|
resolved = true;
|
|
6177
|
-
|
|
6193
|
+
resolve3(d);
|
|
6178
6194
|
};
|
|
6179
6195
|
const fallback = setTimeout(
|
|
6180
6196
|
() => respond("stop"),
|
|
@@ -9172,7 +9188,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9172
9188
|
taskIds.map((id) => {
|
|
9173
9189
|
const cached = this.completedResults.find((r) => r.taskId === id);
|
|
9174
9190
|
if (cached) return cached;
|
|
9175
|
-
return new Promise((
|
|
9191
|
+
return new Promise((resolve3, reject) => {
|
|
9176
9192
|
const timeout = setTimeout(() => {
|
|
9177
9193
|
this.off("task.completed", handler);
|
|
9178
9194
|
reject(new Error(`awaitTasks timed out waiting for task "${id}"`));
|
|
@@ -9181,7 +9197,7 @@ var DefaultMultiAgentCoordinator = class extends EventEmitter {
|
|
|
9181
9197
|
if (result.taskId === id) {
|
|
9182
9198
|
clearTimeout(timeout);
|
|
9183
9199
|
this.off("task.completed", handler);
|
|
9184
|
-
|
|
9200
|
+
resolve3(result);
|
|
9185
9201
|
}
|
|
9186
9202
|
};
|
|
9187
9203
|
this.on("task.completed", handler);
|
|
@@ -9582,7 +9598,7 @@ function providerErrorToSubagentError(err, message, cause) {
|
|
|
9582
9598
|
|
|
9583
9599
|
// src/execution/parallel-eternal-engine.ts
|
|
9584
9600
|
function sleep2(ms) {
|
|
9585
|
-
return new Promise((
|
|
9601
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
9586
9602
|
}
|
|
9587
9603
|
var GOAL_COMPLETE_MARKER2 = /^\s*\[goal[_\s-]?complete\]\s*$/im;
|
|
9588
9604
|
var ParallelEternalEngine = class {
|
|
@@ -10171,7 +10187,7 @@ var InMemoryAgentBridge = class {
|
|
|
10171
10187
|
);
|
|
10172
10188
|
}
|
|
10173
10189
|
this.inflightGuards.add(correlationId);
|
|
10174
|
-
return new Promise((
|
|
10190
|
+
return new Promise((resolve3, reject) => {
|
|
10175
10191
|
const timer = setTimeout(() => {
|
|
10176
10192
|
this.inflightGuards.delete(correlationId);
|
|
10177
10193
|
this.pendingRequests.delete(correlationId);
|
|
@@ -10183,7 +10199,7 @@ var InMemoryAgentBridge = class {
|
|
|
10183
10199
|
return;
|
|
10184
10200
|
}
|
|
10185
10201
|
this.pendingRequests.set(correlationId, {
|
|
10186
|
-
resolve:
|
|
10202
|
+
resolve: resolve3,
|
|
10187
10203
|
reject,
|
|
10188
10204
|
timer
|
|
10189
10205
|
});
|
|
@@ -11311,11 +11327,11 @@ var Director = class {
|
|
|
11311
11327
|
if (cached) return cached;
|
|
11312
11328
|
const existing = this.taskWaiters.get(id);
|
|
11313
11329
|
if (existing) return existing.promise;
|
|
11314
|
-
let
|
|
11330
|
+
let resolve3;
|
|
11315
11331
|
const promise = new Promise((res) => {
|
|
11316
|
-
|
|
11332
|
+
resolve3 = res;
|
|
11317
11333
|
});
|
|
11318
|
-
this.taskWaiters.set(id, { promise, resolve:
|
|
11334
|
+
this.taskWaiters.set(id, { promise, resolve: resolve3 });
|
|
11319
11335
|
return promise;
|
|
11320
11336
|
})
|
|
11321
11337
|
);
|
|
@@ -11631,7 +11647,7 @@ function createDelegateTool(opts) {
|
|
|
11631
11647
|
subagentId
|
|
11632
11648
|
});
|
|
11633
11649
|
const dir = director;
|
|
11634
|
-
const result = await new Promise((
|
|
11650
|
+
const result = await new Promise((resolve3) => {
|
|
11635
11651
|
let settled = false;
|
|
11636
11652
|
let timer;
|
|
11637
11653
|
const finish = (value) => {
|
|
@@ -11640,7 +11656,7 @@ function createDelegateTool(opts) {
|
|
|
11640
11656
|
if (timer) clearTimeout(timer);
|
|
11641
11657
|
offTool();
|
|
11642
11658
|
offIter();
|
|
11643
|
-
|
|
11659
|
+
resolve3(value);
|
|
11644
11660
|
};
|
|
11645
11661
|
const arm = () => {
|
|
11646
11662
|
if (timer) clearTimeout(timer);
|
|
@@ -14830,6 +14846,276 @@ function createAutoExecutor(opts) {
|
|
|
14830
14846
|
});
|
|
14831
14847
|
}
|
|
14832
14848
|
|
|
14849
|
+
// src/sdd/sdd-task-decomposer.ts
|
|
14850
|
+
var SddTaskDecomposer = class {
|
|
14851
|
+
constructor(tracker, graph, opts = {}) {
|
|
14852
|
+
this.tracker = tracker;
|
|
14853
|
+
this.graph = graph;
|
|
14854
|
+
this.slots = Math.min(16, Math.max(1, opts.parallelSlots ?? 4));
|
|
14855
|
+
}
|
|
14856
|
+
tracker;
|
|
14857
|
+
graph;
|
|
14858
|
+
slots;
|
|
14859
|
+
wave = 0;
|
|
14860
|
+
// -------------------------------------------------------------------
|
|
14861
|
+
// Public API
|
|
14862
|
+
// -------------------------------------------------------------------
|
|
14863
|
+
/**
|
|
14864
|
+
* Return the next batch of runnable tasks.
|
|
14865
|
+
* Returns `allDone: true` when every node is completed.
|
|
14866
|
+
* Returns `deadlocked: true` when no batch can be produced because
|
|
14867
|
+
* all remaining tasks are blocked by failed nodes.
|
|
14868
|
+
*/
|
|
14869
|
+
nextBatch() {
|
|
14870
|
+
if (this.isDone()) {
|
|
14871
|
+
return { tasks: [], wave: this.wave, allDone: true, deadlocked: false };
|
|
14872
|
+
}
|
|
14873
|
+
const pending = this.pendingReadyNodes();
|
|
14874
|
+
if (pending.length === 0) {
|
|
14875
|
+
const hasBlockedTasks = this.hasAnyBlockedTasks();
|
|
14876
|
+
return { tasks: [], wave: this.wave, allDone: false, deadlocked: hasBlockedTasks };
|
|
14877
|
+
}
|
|
14878
|
+
const batch = pending.slice(0, this.slots);
|
|
14879
|
+
return { tasks: batch, wave: this.wave, allDone: false, deadlocked: false };
|
|
14880
|
+
}
|
|
14881
|
+
/**
|
|
14882
|
+
* Advance the wave counter after a batch completes.
|
|
14883
|
+
* Call this once per `nextBatch()` result that was fan-out.
|
|
14884
|
+
*/
|
|
14885
|
+
acknowledgeBatch(_completedTaskIds) {
|
|
14886
|
+
this.wave++;
|
|
14887
|
+
}
|
|
14888
|
+
/**
|
|
14889
|
+
* True when every node in the graph is completed.
|
|
14890
|
+
* Use this to exit the fan-out loop after `isDone() || deadlocked`.
|
|
14891
|
+
*/
|
|
14892
|
+
isDone() {
|
|
14893
|
+
const progress = this.tracker.getProgress();
|
|
14894
|
+
return progress.total > 0 && progress.completed === progress.total;
|
|
14895
|
+
}
|
|
14896
|
+
/**
|
|
14897
|
+
* Total waves produced so far.
|
|
14898
|
+
*/
|
|
14899
|
+
getWaveCount() {
|
|
14900
|
+
return this.wave;
|
|
14901
|
+
}
|
|
14902
|
+
// -------------------------------------------------------------------
|
|
14903
|
+
// Internal helpers
|
|
14904
|
+
// -------------------------------------------------------------------
|
|
14905
|
+
/**
|
|
14906
|
+
* Return pending nodes whose blockers are all completed.
|
|
14907
|
+
* Sorted by priority (critical first), then by creation time.
|
|
14908
|
+
*/
|
|
14909
|
+
pendingReadyNodes() {
|
|
14910
|
+
const allPending = this.tracker.getAllNodes({ status: ["pending"] });
|
|
14911
|
+
const ready = [];
|
|
14912
|
+
for (const node of allPending) {
|
|
14913
|
+
if (this.tracker.canStart(node.id)) {
|
|
14914
|
+
ready.push(node);
|
|
14915
|
+
}
|
|
14916
|
+
}
|
|
14917
|
+
const priorityRank = {
|
|
14918
|
+
critical: 0,
|
|
14919
|
+
high: 1,
|
|
14920
|
+
medium: 2,
|
|
14921
|
+
low: 3
|
|
14922
|
+
};
|
|
14923
|
+
ready.sort((a, b) => {
|
|
14924
|
+
const pr = priorityRank[a.priority] - priorityRank[b.priority];
|
|
14925
|
+
if (pr !== 0) return pr;
|
|
14926
|
+
return a.createdAt - b.createdAt;
|
|
14927
|
+
});
|
|
14928
|
+
return ready;
|
|
14929
|
+
}
|
|
14930
|
+
/** True when at least one non-completed, non-failed task is blocked. */
|
|
14931
|
+
hasAnyBlockedTasks() {
|
|
14932
|
+
const nodes = this.tracker.getAllNodes({
|
|
14933
|
+
status: ["pending", "in_progress", "blocked"]
|
|
14934
|
+
});
|
|
14935
|
+
return nodes.some((n) => n.status === "blocked");
|
|
14936
|
+
}
|
|
14937
|
+
};
|
|
14938
|
+
var SddParallelRun = class {
|
|
14939
|
+
constructor(opts) {
|
|
14940
|
+
this.opts = opts;
|
|
14941
|
+
this.slots = Math.min(16, Math.max(1, opts.parallelSlots ?? 4));
|
|
14942
|
+
this.timeoutMs = opts.taskTimeoutMs ?? 3e5;
|
|
14943
|
+
this.decomposer = new SddTaskDecomposer(opts.tracker, opts.graph, { parallelSlots: this.slots });
|
|
14944
|
+
}
|
|
14945
|
+
opts;
|
|
14946
|
+
slots;
|
|
14947
|
+
timeoutMs;
|
|
14948
|
+
decomposer;
|
|
14949
|
+
coordinator = null;
|
|
14950
|
+
stopRequested = false;
|
|
14951
|
+
// -------------------------------------------------------------------
|
|
14952
|
+
// Public API
|
|
14953
|
+
// -------------------------------------------------------------------
|
|
14954
|
+
/** Trigger stop — causes run() to abort after the current wave. */
|
|
14955
|
+
stop() {
|
|
14956
|
+
this.stopRequested = true;
|
|
14957
|
+
this.coordinator?.stopAll();
|
|
14958
|
+
}
|
|
14959
|
+
/** Execute all waves until completion or deadlock. Returns final summary. */
|
|
14960
|
+
async run() {
|
|
14961
|
+
this.stopRequested = false;
|
|
14962
|
+
const startTime = Date.now();
|
|
14963
|
+
let totalCompleted = 0;
|
|
14964
|
+
let totalFailed = 0;
|
|
14965
|
+
let totalWaves = 0;
|
|
14966
|
+
this.buildCoordinator();
|
|
14967
|
+
while (!this.stopRequested && !this.decomposer.isDone()) {
|
|
14968
|
+
const batch = this.decomposer.nextBatch();
|
|
14969
|
+
if (batch.deadlocked) {
|
|
14970
|
+
break;
|
|
14971
|
+
}
|
|
14972
|
+
if (batch.tasks.length === 0 && batch.allDone) {
|
|
14973
|
+
break;
|
|
14974
|
+
}
|
|
14975
|
+
const waveResult = await this.executeWave(batch);
|
|
14976
|
+
totalWaves++;
|
|
14977
|
+
totalCompleted += waveResult.successCount;
|
|
14978
|
+
totalFailed += waveResult.failCount;
|
|
14979
|
+
this.decomposer.acknowledgeBatch(batch.tasks.map((t) => t.id));
|
|
14980
|
+
this.opts.onWave?.(waveResult);
|
|
14981
|
+
const progress = this.buildProgress();
|
|
14982
|
+
this.opts.onProgress?.(progress);
|
|
14983
|
+
if (this.stopRequested) break;
|
|
14984
|
+
}
|
|
14985
|
+
const finalProgress = this.opts.tracker.getProgress();
|
|
14986
|
+
return {
|
|
14987
|
+
totalWaves,
|
|
14988
|
+
totalCompleted,
|
|
14989
|
+
totalFailed,
|
|
14990
|
+
totalDurationMs: Date.now() - startTime,
|
|
14991
|
+
deadlocked: !this.decomposer.isDone() && this.stopRequested === false,
|
|
14992
|
+
stopRequested: this.stopRequested,
|
|
14993
|
+
finalProgress
|
|
14994
|
+
};
|
|
14995
|
+
}
|
|
14996
|
+
// -------------------------------------------------------------------
|
|
14997
|
+
// Internal
|
|
14998
|
+
// -------------------------------------------------------------------
|
|
14999
|
+
buildCoordinator() {
|
|
15000
|
+
const config = {
|
|
15001
|
+
coordinatorId: `sdd-parallel-${randomUUID().slice(0, 8)}`,
|
|
15002
|
+
maxConcurrent: this.slots,
|
|
15003
|
+
doneCondition: { type: "all_tasks_done" }
|
|
15004
|
+
};
|
|
15005
|
+
this.coordinator = new DefaultMultiAgentCoordinator(config);
|
|
15006
|
+
const runner = makeAgentSubagentRunner({ factory: this.opts.subagentFactory ?? this.defaultFactory() });
|
|
15007
|
+
this.coordinator.setRunner?.(runner);
|
|
15008
|
+
}
|
|
15009
|
+
defaultFactory() {
|
|
15010
|
+
return async (config) => ({
|
|
15011
|
+
agent: this.opts.agent,
|
|
15012
|
+
events: this.opts.agent.events
|
|
15013
|
+
});
|
|
15014
|
+
}
|
|
15015
|
+
async executeWave(batch) {
|
|
15016
|
+
const wave = batch.wave;
|
|
15017
|
+
const tasks = batch.tasks;
|
|
15018
|
+
const waveStart = Date.now();
|
|
15019
|
+
for (const task of tasks) {
|
|
15020
|
+
this.opts.tracker.updateNodeStatus(task.id, "in_progress");
|
|
15021
|
+
}
|
|
15022
|
+
const progress = computeTaskProgress(this.opts.graph);
|
|
15023
|
+
const taskIds = tasks.map(() => randomUUID());
|
|
15024
|
+
const subagentIds = tasks.map((_, i) => `sdd-wave${wave}-${i}`);
|
|
15025
|
+
const directivePreamble = [
|
|
15026
|
+
"\u2550\u2550\u2550 SDD PARALLEL EXECUTION \u2550\u2550\u2550",
|
|
15027
|
+
"",
|
|
15028
|
+
`Wave ${wave + 1} of ~${Math.ceil(progress.total / this.slots)}`,
|
|
15029
|
+
`Graph: ${this.opts.graph.title}`,
|
|
15030
|
+
`Parallel slots: ${tasks.length}`,
|
|
15031
|
+
"",
|
|
15032
|
+
"\u2500\u2500 EXECUTION PROTOCOL \u2500\u2500",
|
|
15033
|
+
"\u2022 Execute the assigned SDD task end-to-end using multiple tool calls.",
|
|
15034
|
+
"\u2022 Mark the task [done] in the tracker when complete.",
|
|
15035
|
+
"\u2022 Do not ask for confirmation.",
|
|
15036
|
+
"\u2022 Keep output concise \u2014 summarize changes, do not transcribe files."
|
|
15037
|
+
].join("\n");
|
|
15038
|
+
const spawns = subagentIds.map(
|
|
15039
|
+
(subagentId) => this.coordinator.spawn({
|
|
15040
|
+
id: subagentId,
|
|
15041
|
+
name: subagentId,
|
|
15042
|
+
role: "executor",
|
|
15043
|
+
timeoutMs: this.timeoutMs
|
|
15044
|
+
})
|
|
15045
|
+
);
|
|
15046
|
+
const spawnResults = await Promise.all(spawns);
|
|
15047
|
+
if (!spawnResults.every((r) => r.subagentId)) {
|
|
15048
|
+
throw new Error("One or more subagent spawns failed");
|
|
15049
|
+
}
|
|
15050
|
+
const assignPromises = tasks.map((task, i) => {
|
|
15051
|
+
const spec = {
|
|
15052
|
+
id: taskIds[i],
|
|
15053
|
+
description: [
|
|
15054
|
+
directivePreamble,
|
|
15055
|
+
"",
|
|
15056
|
+
`\u2500\u2500 TASK ${i + 1}/${tasks.length} \u2500\u2500`,
|
|
15057
|
+
`[${task.priority.toUpperCase()}] ${task.title}`,
|
|
15058
|
+
"",
|
|
15059
|
+
task.description
|
|
15060
|
+
].join("\n"),
|
|
15061
|
+
subagentId: subagentIds[i],
|
|
15062
|
+
timeoutMs: this.timeoutMs
|
|
15063
|
+
};
|
|
15064
|
+
return this.coordinator.assign(spec);
|
|
15065
|
+
});
|
|
15066
|
+
await Promise.all(assignPromises);
|
|
15067
|
+
let results;
|
|
15068
|
+
try {
|
|
15069
|
+
results = await this.coordinator.awaitTasks(taskIds);
|
|
15070
|
+
} catch (err) {
|
|
15071
|
+
results = taskIds.map((id) => ({
|
|
15072
|
+
subagentId: "",
|
|
15073
|
+
taskId: id,
|
|
15074
|
+
status: "failed",
|
|
15075
|
+
error: { kind: "unknown", message: String(err), retryable: false },
|
|
15076
|
+
iterations: 0,
|
|
15077
|
+
toolCalls: 0,
|
|
15078
|
+
durationMs: 0
|
|
15079
|
+
}));
|
|
15080
|
+
}
|
|
15081
|
+
const successCount = results.filter((r) => r.status === "success").length;
|
|
15082
|
+
const failCount = results.length - successCount;
|
|
15083
|
+
for (let i = 0; i < results.length; i++) {
|
|
15084
|
+
const result = results[i];
|
|
15085
|
+
const taskId = taskIds[i];
|
|
15086
|
+
if (result.status === "success") {
|
|
15087
|
+
this.opts.tracker.updateNodeStatus(taskId, "completed");
|
|
15088
|
+
} else {
|
|
15089
|
+
const errMsg = result.error?.kind ? `${result.error.kind}: ${result.error.message}` : result.error?.message ?? "unknown error";
|
|
15090
|
+
this.opts.tracker.updateNodeStatus(taskId, "failed", errMsg);
|
|
15091
|
+
}
|
|
15092
|
+
}
|
|
15093
|
+
return {
|
|
15094
|
+
wave,
|
|
15095
|
+
batch,
|
|
15096
|
+
results,
|
|
15097
|
+
successCount,
|
|
15098
|
+
failCount,
|
|
15099
|
+
durationMs: Date.now() - waveStart,
|
|
15100
|
+
stopRequested: this.stopRequested
|
|
15101
|
+
};
|
|
15102
|
+
}
|
|
15103
|
+
buildProgress() {
|
|
15104
|
+
const gp = this.opts.tracker.getProgress();
|
|
15105
|
+
return {
|
|
15106
|
+
wave: this.decomposer.getWaveCount(),
|
|
15107
|
+
total: gp.total,
|
|
15108
|
+
completed: gp.completed,
|
|
15109
|
+
inProgress: gp.inProgress,
|
|
15110
|
+
failed: gp.failed,
|
|
15111
|
+
blocked: gp.blocked,
|
|
15112
|
+
pending: gp.pending,
|
|
15113
|
+
percent: gp.percentComplete,
|
|
15114
|
+
deadlocked: false
|
|
15115
|
+
};
|
|
15116
|
+
}
|
|
15117
|
+
};
|
|
15118
|
+
|
|
14833
15119
|
// src/observability/metrics.ts
|
|
14834
15120
|
var RESERVOIR_SIZE = 1024;
|
|
14835
15121
|
function labelKey(labels) {
|
|
@@ -14989,9 +15275,9 @@ var DefaultHealthRegistry = class {
|
|
|
14989
15275
|
}
|
|
14990
15276
|
async runOne(check) {
|
|
14991
15277
|
let timer = null;
|
|
14992
|
-
const timeout = new Promise((
|
|
15278
|
+
const timeout = new Promise((resolve3) => {
|
|
14993
15279
|
timer = setTimeout(
|
|
14994
|
-
() =>
|
|
15280
|
+
() => resolve3({ status: "unhealthy", detail: `timeout after ${this.timeoutMs}ms` }),
|
|
14995
15281
|
this.timeoutMs
|
|
14996
15282
|
);
|
|
14997
15283
|
});
|
|
@@ -15230,14 +15516,14 @@ async function startMetricsServer(opts) {
|
|
|
15230
15516
|
const { createServer } = await import('http');
|
|
15231
15517
|
server = createServer(listener);
|
|
15232
15518
|
}
|
|
15233
|
-
await new Promise((
|
|
15519
|
+
await new Promise((resolve3, reject) => {
|
|
15234
15520
|
const onError = (err) => {
|
|
15235
15521
|
server.off("listening", onListening);
|
|
15236
15522
|
reject(err);
|
|
15237
15523
|
};
|
|
15238
15524
|
const onListening = () => {
|
|
15239
15525
|
server.off("error", onError);
|
|
15240
|
-
|
|
15526
|
+
resolve3();
|
|
15241
15527
|
};
|
|
15242
15528
|
server.once("error", onError);
|
|
15243
15529
|
server.once("listening", onListening);
|
|
@@ -15249,8 +15535,8 @@ async function startMetricsServer(opts) {
|
|
|
15249
15535
|
return {
|
|
15250
15536
|
port: boundPort,
|
|
15251
15537
|
url: `${protocol}://${host}:${boundPort}${path18}`,
|
|
15252
|
-
close: () => new Promise((
|
|
15253
|
-
server.close((err) => err ? reject(err) :
|
|
15538
|
+
close: () => new Promise((resolve3, reject) => {
|
|
15539
|
+
server.close((err) => err ? reject(err) : resolve3());
|
|
15254
15540
|
})
|
|
15255
15541
|
};
|
|
15256
15542
|
}
|
|
@@ -15868,6 +16154,6 @@ var allServers = () => ({
|
|
|
15868
16154
|
"minimax-vision": { ...miniMaxVisionServer(), enabled: false }
|
|
15869
16155
|
});
|
|
15870
16156
|
|
|
15871
|
-
export { AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutonomousRunner, BUG_HUNTER_AGENT, BudgetExceededError, ConfigMigrationError, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPermissionPolicy, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionStore, DefaultSkillLoader, DefaultTaskStore, Director, DirectorStateCheckpoint, DoneConditionChecker, EternalAutonomyEngine, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FleetBus, FleetSpawnBudgetError, FleetUsageAggregator, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, IntelligentCompactor, LLMSelector, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, SelectiveCompactor, SessionAnalyzer, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, SubagentBudget, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, ToolExecutor, addPlanItem, allServers, analyzeCriticalPath, applyRosterBudget, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, braveSearchServer, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, classifyFamily, clearPlan, composeDirectorPrompt, composeSubagentPrompt, context7Server, contextManagerTool, createAutoExecutor, createContextManagerTool, createDelegateTool, createMessage, decryptConfigSecrets2 as decryptConfigSecrets, deriveTodosFromPlanItem, dispatchAgent, emptyPlan, encryptConfigSecrets, everArtServer, filesystemServer, formatPlan, formatPlanTemplates, getAgentDefinition, getPlanTemplate, getTemplate, githubServer, googleMapsServer, listPlanTemplates, listTemplates, loadDirectorState, loadPlan, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeAutonomyPromptContributor, makeDirectorSessionFactory, makeLLMClassifier, migratePlaintextSecrets, miniMaxVisionServer, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, savePlan, saveTodosCheckpoint, scoreAgents, sentinelServer, setPlanItemStatus, slackServer, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, templateToMarkdown, wireMetricsToEvents, zaiVisionServer };
|
|
16157
|
+
export { AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutonomousRunner, BUG_HUNTER_AGENT, BudgetExceededError, ConfigMigrationError, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPermissionPolicy, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionStore, DefaultSkillLoader, DefaultTaskStore, Director, DirectorStateCheckpoint, DoneConditionChecker, EternalAutonomyEngine, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FleetBus, FleetSpawnBudgetError, FleetUsageAggregator, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, IntelligentCompactor, LLMSelector, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, SddParallelRun, SddTaskDecomposer, SelectiveCompactor, SessionAnalyzer, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, SubagentBudget, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, ToolExecutor, addPlanItem, allServers, analyzeCriticalPath, applyRosterBudget, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, braveSearchServer, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, classifyFamily, clearPlan, composeDirectorPrompt, composeSubagentPrompt, context7Server, contextManagerTool, createAutoExecutor, createContextManagerTool, createDelegateTool, createMessage, decryptConfigSecrets2 as decryptConfigSecrets, deriveTodosFromPlanItem, dispatchAgent, emptyPlan, encryptConfigSecrets, everArtServer, filesystemServer, formatPlan, formatPlanTemplates, getAgentDefinition, getPlanTemplate, getTemplate, githubServer, googleMapsServer, listPlanTemplates, listTemplates, loadDirectorState, loadPlan, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeAutonomyPromptContributor, makeDirectorSessionFactory, makeLLMClassifier, migratePlaintextSecrets, miniMaxVisionServer, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, savePlan, saveTodosCheckpoint, scoreAgents, sentinelServer, setPlanItemStatus, slackServer, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, templateToMarkdown, wireMetricsToEvents, zaiVisionServer };
|
|
15872
16158
|
//# sourceMappingURL=index.js.map
|
|
15873
16159
|
//# sourceMappingURL=index.js.map
|