opencode-swarm 7.28.2 → 7.28.3
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/cli/index.js +55 -13
- package/dist/index.js +55 -13
- package/dist/tools/test-runner.d.ts +0 -1
- package/dist/utils/bun-compat.d.ts +10 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.28.
|
|
37
|
+
version: "7.28.3",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -308,6 +308,27 @@ function bunHash(input) {
|
|
|
308
308
|
}
|
|
309
309
|
return hash;
|
|
310
310
|
}
|
|
311
|
+
function killProcessTreeImpl(pid, signal, directKill, wasDetached) {
|
|
312
|
+
if (typeof pid !== "number" || pid <= 0) {
|
|
313
|
+
directKill();
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
if (process.platform === "win32") {
|
|
317
|
+
try {
|
|
318
|
+
nodeSpawnSync("taskkill", ["/PID", String(pid), "/T", "/F"]);
|
|
319
|
+
} catch {
|
|
320
|
+
directKill();
|
|
321
|
+
}
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (wasDetached) {
|
|
325
|
+
try {
|
|
326
|
+
process.kill(-pid, signal ?? "SIGKILL");
|
|
327
|
+
return;
|
|
328
|
+
} catch {}
|
|
329
|
+
}
|
|
330
|
+
directKill();
|
|
331
|
+
}
|
|
311
332
|
function streamFromNode(pipe) {
|
|
312
333
|
const collected = new Promise((resolve) => {
|
|
313
334
|
if (!pipe) {
|
|
@@ -430,20 +451,34 @@ function bunSpawn(cmd, options) {
|
|
|
430
451
|
return proc2.exitCode;
|
|
431
452
|
},
|
|
432
453
|
kill(sig) {
|
|
433
|
-
|
|
454
|
+
if (options?.killProcessTree) {
|
|
455
|
+
killProcessTreeImpl(proc2.pid, sig, () => proc2.kill(sig), false);
|
|
456
|
+
} else {
|
|
457
|
+
proc2.kill(sig);
|
|
458
|
+
}
|
|
434
459
|
}
|
|
435
460
|
};
|
|
436
461
|
}
|
|
437
462
|
const [file, ...args] = cmd;
|
|
463
|
+
const detached = options?.killProcessTree === true;
|
|
438
464
|
const proc = nodeSpawn(file, args, {
|
|
439
465
|
cwd: options?.cwd,
|
|
440
466
|
env: options?.env,
|
|
467
|
+
detached,
|
|
468
|
+
windowsHide: true,
|
|
441
469
|
stdio: [
|
|
442
470
|
mapStdio(options?.stdin),
|
|
443
471
|
mapStdio(options?.stdout),
|
|
444
472
|
mapStdio(options?.stderr)
|
|
445
473
|
]
|
|
446
474
|
});
|
|
475
|
+
const killChild = (signal) => {
|
|
476
|
+
if (detached) {
|
|
477
|
+
killProcessTreeImpl(proc.pid, signal, () => proc.kill(signal), true);
|
|
478
|
+
} else {
|
|
479
|
+
proc.kill(signal);
|
|
480
|
+
}
|
|
481
|
+
};
|
|
447
482
|
let timeoutHandle;
|
|
448
483
|
const exited = new Promise((resolve) => {
|
|
449
484
|
proc.on("exit", (code) => resolve(code ?? 0));
|
|
@@ -451,7 +486,7 @@ function bunSpawn(cmd, options) {
|
|
|
451
486
|
if (options?.timeout && options.timeout > 0) {
|
|
452
487
|
timeoutHandle = setTimeout(() => {
|
|
453
488
|
try {
|
|
454
|
-
|
|
489
|
+
killChild("SIGKILL");
|
|
455
490
|
} catch {}
|
|
456
491
|
}, options.timeout);
|
|
457
492
|
if (typeof timeoutHandle.unref === "function") {
|
|
@@ -471,7 +506,7 @@ function bunSpawn(cmd, options) {
|
|
|
471
506
|
},
|
|
472
507
|
kill(signal) {
|
|
473
508
|
try {
|
|
474
|
-
|
|
509
|
+
killChild(signal);
|
|
475
510
|
} catch {}
|
|
476
511
|
}
|
|
477
512
|
};
|
|
@@ -46255,7 +46290,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
46255
46290
|
const coverage = opts.coverage ?? false;
|
|
46256
46291
|
switch (framework) {
|
|
46257
46292
|
case "bun": {
|
|
46258
|
-
const args = ["bun", "test"];
|
|
46293
|
+
const args = ["bun", "--smol", "test"];
|
|
46259
46294
|
if (coverage)
|
|
46260
46295
|
args.push("--coverage");
|
|
46261
46296
|
if (scope !== "all" && files.length > 0)
|
|
@@ -48688,7 +48723,7 @@ function getTargetedExecutionUnsupportedReason(framework) {
|
|
|
48688
48723
|
function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
48689
48724
|
switch (framework) {
|
|
48690
48725
|
case "bun": {
|
|
48691
|
-
const args = ["bun", "test"];
|
|
48726
|
+
const args = ["bun", "--smol", "test"];
|
|
48692
48727
|
if (coverage)
|
|
48693
48728
|
args.push("--coverage");
|
|
48694
48729
|
if (scope !== "all" && files.length > 0) {
|
|
@@ -49225,17 +49260,24 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
49225
49260
|
const proc = bunSpawn(command, {
|
|
49226
49261
|
stdout: "pipe",
|
|
49227
49262
|
stderr: "pipe",
|
|
49228
|
-
|
|
49263
|
+
stdin: "ignore",
|
|
49264
|
+
cwd,
|
|
49265
|
+
killProcessTree: true
|
|
49266
|
+
});
|
|
49267
|
+
let timeoutHandle;
|
|
49268
|
+
const timeoutPromise = new Promise((resolve14) => {
|
|
49269
|
+
timeoutHandle = setTimeout(() => {
|
|
49270
|
+
proc.kill();
|
|
49271
|
+
resolve14(-1);
|
|
49272
|
+
}, timeout_ms);
|
|
49229
49273
|
});
|
|
49230
|
-
const timeoutPromise = new Promise((resolve14) => setTimeout(() => {
|
|
49231
|
-
proc.kill();
|
|
49232
|
-
resolve14(-1);
|
|
49233
|
-
}, timeout_ms));
|
|
49234
49274
|
const [exitCode, stdoutResult, stderrResult] = await Promise.all([
|
|
49235
49275
|
Promise.race([proc.exited, timeoutPromise]),
|
|
49236
49276
|
readBoundedStream(proc.stdout, MAX_OUTPUT_BYTES3),
|
|
49237
49277
|
readBoundedStream(proc.stderr, MAX_OUTPUT_BYTES3)
|
|
49238
49278
|
]);
|
|
49279
|
+
if (timeoutHandle !== undefined)
|
|
49280
|
+
clearTimeout(timeoutHandle);
|
|
49239
49281
|
const duration_ms = Date.now() - startTime;
|
|
49240
49282
|
let output = stdoutResult.text;
|
|
49241
49283
|
if (stderrResult.text) {
|
|
@@ -49538,7 +49580,6 @@ var init_test_runner = __esm(() => {
|
|
|
49538
49580
|
files: exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),
|
|
49539
49581
|
coverage: exports_external.boolean().optional().describe("Enable coverage reporting if supported"),
|
|
49540
49582
|
timeout_ms: exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
|
|
49541
|
-
allow_full_suite: exports_external.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),
|
|
49542
49583
|
working_directory: exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
|
|
49543
49584
|
},
|
|
49544
49585
|
async execute(args, directory) {
|
|
@@ -49612,7 +49653,8 @@ var init_test_runner = __esm(() => {
|
|
|
49612
49653
|
}
|
|
49613
49654
|
const scope = args.scope || "all";
|
|
49614
49655
|
if (scope === "all") {
|
|
49615
|
-
|
|
49656
|
+
const fullSuiteAllowed = process.env.SWARM_ALLOW_FULL_SUITE === "1" || process.env.SWARM_ALLOW_FULL_SUITE === "true";
|
|
49657
|
+
if (!fullSuiteAllowed) {
|
|
49616
49658
|
const errorResult = {
|
|
49617
49659
|
success: false,
|
|
49618
49660
|
framework: "none",
|
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ var package_default;
|
|
|
48
48
|
var init_package = __esm(() => {
|
|
49
49
|
package_default = {
|
|
50
50
|
name: "opencode-swarm",
|
|
51
|
-
version: "7.28.
|
|
51
|
+
version: "7.28.3",
|
|
52
52
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
53
53
|
main: "dist/index.js",
|
|
54
54
|
types: "dist/index.d.ts",
|
|
@@ -16518,6 +16518,27 @@ function bunHash(input) {
|
|
|
16518
16518
|
}
|
|
16519
16519
|
return hash2;
|
|
16520
16520
|
}
|
|
16521
|
+
function killProcessTreeImpl(pid, signal, directKill, wasDetached) {
|
|
16522
|
+
if (typeof pid !== "number" || pid <= 0) {
|
|
16523
|
+
directKill();
|
|
16524
|
+
return;
|
|
16525
|
+
}
|
|
16526
|
+
if (process.platform === "win32") {
|
|
16527
|
+
try {
|
|
16528
|
+
nodeSpawnSync("taskkill", ["/PID", String(pid), "/T", "/F"]);
|
|
16529
|
+
} catch {
|
|
16530
|
+
directKill();
|
|
16531
|
+
}
|
|
16532
|
+
return;
|
|
16533
|
+
}
|
|
16534
|
+
if (wasDetached) {
|
|
16535
|
+
try {
|
|
16536
|
+
process.kill(-pid, signal ?? "SIGKILL");
|
|
16537
|
+
return;
|
|
16538
|
+
} catch {}
|
|
16539
|
+
}
|
|
16540
|
+
directKill();
|
|
16541
|
+
}
|
|
16521
16542
|
function streamFromNode(pipe2) {
|
|
16522
16543
|
const collected = new Promise((resolve) => {
|
|
16523
16544
|
if (!pipe2) {
|
|
@@ -16640,20 +16661,34 @@ function bunSpawn(cmd, options) {
|
|
|
16640
16661
|
return proc2.exitCode;
|
|
16641
16662
|
},
|
|
16642
16663
|
kill(sig) {
|
|
16643
|
-
|
|
16664
|
+
if (options?.killProcessTree) {
|
|
16665
|
+
killProcessTreeImpl(proc2.pid, sig, () => proc2.kill(sig), false);
|
|
16666
|
+
} else {
|
|
16667
|
+
proc2.kill(sig);
|
|
16668
|
+
}
|
|
16644
16669
|
}
|
|
16645
16670
|
};
|
|
16646
16671
|
}
|
|
16647
16672
|
const [file2, ...args2] = cmd;
|
|
16673
|
+
const detached = options?.killProcessTree === true;
|
|
16648
16674
|
const proc = nodeSpawn(file2, args2, {
|
|
16649
16675
|
cwd: options?.cwd,
|
|
16650
16676
|
env: options?.env,
|
|
16677
|
+
detached,
|
|
16678
|
+
windowsHide: true,
|
|
16651
16679
|
stdio: [
|
|
16652
16680
|
mapStdio(options?.stdin),
|
|
16653
16681
|
mapStdio(options?.stdout),
|
|
16654
16682
|
mapStdio(options?.stderr)
|
|
16655
16683
|
]
|
|
16656
16684
|
});
|
|
16685
|
+
const killChild = (signal) => {
|
|
16686
|
+
if (detached) {
|
|
16687
|
+
killProcessTreeImpl(proc.pid, signal, () => proc.kill(signal), true);
|
|
16688
|
+
} else {
|
|
16689
|
+
proc.kill(signal);
|
|
16690
|
+
}
|
|
16691
|
+
};
|
|
16657
16692
|
let timeoutHandle;
|
|
16658
16693
|
const exited = new Promise((resolve) => {
|
|
16659
16694
|
proc.on("exit", (code) => resolve(code ?? 0));
|
|
@@ -16661,7 +16696,7 @@ function bunSpawn(cmd, options) {
|
|
|
16661
16696
|
if (options?.timeout && options.timeout > 0) {
|
|
16662
16697
|
timeoutHandle = setTimeout(() => {
|
|
16663
16698
|
try {
|
|
16664
|
-
|
|
16699
|
+
killChild("SIGKILL");
|
|
16665
16700
|
} catch {}
|
|
16666
16701
|
}, options.timeout);
|
|
16667
16702
|
if (typeof timeoutHandle.unref === "function") {
|
|
@@ -16681,7 +16716,7 @@ function bunSpawn(cmd, options) {
|
|
|
16681
16716
|
},
|
|
16682
16717
|
kill(signal) {
|
|
16683
16718
|
try {
|
|
16684
|
-
|
|
16719
|
+
killChild(signal);
|
|
16685
16720
|
} catch {}
|
|
16686
16721
|
}
|
|
16687
16722
|
};
|
|
@@ -67348,7 +67383,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
|
|
|
67348
67383
|
const coverage = opts.coverage ?? false;
|
|
67349
67384
|
switch (framework) {
|
|
67350
67385
|
case "bun": {
|
|
67351
|
-
const args2 = ["bun", "test"];
|
|
67386
|
+
const args2 = ["bun", "--smol", "test"];
|
|
67352
67387
|
if (coverage)
|
|
67353
67388
|
args2.push("--coverage");
|
|
67354
67389
|
if (scope !== "all" && files.length > 0)
|
|
@@ -69781,7 +69816,7 @@ function getTargetedExecutionUnsupportedReason(framework) {
|
|
|
69781
69816
|
function buildTestCommand2(framework, scope, files, coverage, baseDir) {
|
|
69782
69817
|
switch (framework) {
|
|
69783
69818
|
case "bun": {
|
|
69784
|
-
const args2 = ["bun", "test"];
|
|
69819
|
+
const args2 = ["bun", "--smol", "test"];
|
|
69785
69820
|
if (coverage)
|
|
69786
69821
|
args2.push("--coverage");
|
|
69787
69822
|
if (scope !== "all" && files.length > 0) {
|
|
@@ -70318,17 +70353,24 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
|
|
|
70318
70353
|
const proc = bunSpawn(command, {
|
|
70319
70354
|
stdout: "pipe",
|
|
70320
70355
|
stderr: "pipe",
|
|
70321
|
-
|
|
70356
|
+
stdin: "ignore",
|
|
70357
|
+
cwd,
|
|
70358
|
+
killProcessTree: true
|
|
70359
|
+
});
|
|
70360
|
+
let timeoutHandle;
|
|
70361
|
+
const timeoutPromise = new Promise((resolve16) => {
|
|
70362
|
+
timeoutHandle = setTimeout(() => {
|
|
70363
|
+
proc.kill();
|
|
70364
|
+
resolve16(-1);
|
|
70365
|
+
}, timeout_ms);
|
|
70322
70366
|
});
|
|
70323
|
-
const timeoutPromise = new Promise((resolve16) => setTimeout(() => {
|
|
70324
|
-
proc.kill();
|
|
70325
|
-
resolve16(-1);
|
|
70326
|
-
}, timeout_ms));
|
|
70327
70367
|
const [exitCode, stdoutResult, stderrResult] = await Promise.all([
|
|
70328
70368
|
Promise.race([proc.exited, timeoutPromise]),
|
|
70329
70369
|
readBoundedStream(proc.stdout, MAX_OUTPUT_BYTES3),
|
|
70330
70370
|
readBoundedStream(proc.stderr, MAX_OUTPUT_BYTES3)
|
|
70331
70371
|
]);
|
|
70372
|
+
if (timeoutHandle !== undefined)
|
|
70373
|
+
clearTimeout(timeoutHandle);
|
|
70332
70374
|
const duration_ms = Date.now() - startTime;
|
|
70333
70375
|
let output = stdoutResult.text;
|
|
70334
70376
|
if (stderrResult.text) {
|
|
@@ -70631,7 +70673,6 @@ var init_test_runner = __esm(() => {
|
|
|
70631
70673
|
files: exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),
|
|
70632
70674
|
coverage: exports_external.boolean().optional().describe("Enable coverage reporting if supported"),
|
|
70633
70675
|
timeout_ms: exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
|
|
70634
|
-
allow_full_suite: exports_external.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),
|
|
70635
70676
|
working_directory: exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
|
|
70636
70677
|
},
|
|
70637
70678
|
async execute(args2, directory) {
|
|
@@ -70705,7 +70746,8 @@ var init_test_runner = __esm(() => {
|
|
|
70705
70746
|
}
|
|
70706
70747
|
const scope = args2.scope || "all";
|
|
70707
70748
|
if (scope === "all") {
|
|
70708
|
-
|
|
70749
|
+
const fullSuiteAllowed = process.env.SWARM_ALLOW_FULL_SUITE === "1" || process.env.SWARM_ALLOW_FULL_SUITE === "true";
|
|
70750
|
+
if (!fullSuiteAllowed) {
|
|
70709
70751
|
const errorResult = {
|
|
70710
70752
|
success: false,
|
|
70711
70753
|
framework: "none",
|
|
@@ -23,7 +23,6 @@ export interface TestRunnerArgs {
|
|
|
23
23
|
files?: string[];
|
|
24
24
|
coverage?: boolean;
|
|
25
25
|
timeout_ms?: number;
|
|
26
|
-
allow_full_suite?: boolean;
|
|
27
26
|
}
|
|
28
27
|
export type RegressionOutcome = 'pass' | 'skip' | 'regression' | 'scope_exceeded' | 'error';
|
|
29
28
|
export interface TestTotals {
|
|
@@ -71,6 +71,16 @@ export interface BunCompatSpawnOptions {
|
|
|
71
71
|
stdout?: 'inherit' | 'ignore' | 'pipe';
|
|
72
72
|
stderr?: 'inherit' | 'ignore' | 'pipe';
|
|
73
73
|
timeout?: number;
|
|
74
|
+
/**
|
|
75
|
+
* When true, spawn the child as its own process-group leader (Node path:
|
|
76
|
+
* `detached`) and kill the entire descendant tree on `kill()`/timeout
|
|
77
|
+
* rather than only the direct child. A test runner that forks worker
|
|
78
|
+
* processes (jest/vitest, or a runaway suite) can otherwise outlive a
|
|
79
|
+
* `proc.kill()` of the parent and keep consuming memory after the timeout.
|
|
80
|
+
* Opt-in because the default single-child kill is correct for the many
|
|
81
|
+
* short-lived `bunSpawn` callers (git, lint, version checks).
|
|
82
|
+
*/
|
|
83
|
+
killProcessTree?: boolean;
|
|
74
84
|
}
|
|
75
85
|
export interface BunCompatStream {
|
|
76
86
|
text(): Promise<string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.28.
|
|
3
|
+
"version": "7.28.3",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|