opencode-swarm 7.27.3 → 7.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +5 -5
- package/dist/index.js +200 -81
- 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.
|
|
37
|
+
version: "7.28.0",
|
|
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",
|
|
@@ -20932,7 +20932,7 @@ var init_scope_persistence = __esm(() => {
|
|
|
20932
20932
|
|
|
20933
20933
|
// src/hooks/shell-write-detect.ts
|
|
20934
20934
|
import parse5 from "bash-parser";
|
|
20935
|
-
var REDIRECT_WRITE_TOKENS, REDIRECT_HERE_TOKENS, REDIRECT_ALL_WRITE_TOKENS, BUILTIN_WRITE_COMMANDS, INPLACE_EDIT_COMMANDS, INTERPRETER_EVAL_COMMANDS, NETWORK_DOWNLOAD_COMMANDS, ARCHIVE_EXTRACT_COMMANDS,
|
|
20935
|
+
var REDIRECT_WRITE_TOKENS, REDIRECT_HERE_TOKENS, REDIRECT_ALL_WRITE_TOKENS, BUILTIN_WRITE_COMMANDS, INPLACE_EDIT_COMMANDS, INTERPRETER_EVAL_COMMANDS, NETWORK_DOWNLOAD_COMMANDS, ARCHIVE_EXTRACT_COMMANDS, _PS_WRITE_CMDLETS, _PS_WRITE_ALIASES, _CMD_WRITE_BUILTINS;
|
|
20936
20936
|
var init_shell_write_detect = __esm(() => {
|
|
20937
20937
|
REDIRECT_WRITE_TOKENS = new Set([
|
|
20938
20938
|
"GREAT",
|
|
@@ -20974,7 +20974,7 @@ var init_shell_write_detect = __esm(() => {
|
|
|
20974
20974
|
"7z",
|
|
20975
20975
|
"rar"
|
|
20976
20976
|
]);
|
|
20977
|
-
|
|
20977
|
+
_PS_WRITE_CMDLETS = new Set([
|
|
20978
20978
|
"Out-File",
|
|
20979
20979
|
"Set-Content",
|
|
20980
20980
|
"Add-Content",
|
|
@@ -20985,8 +20985,8 @@ var init_shell_write_detect = __esm(() => {
|
|
|
20985
20985
|
"Invoke-WebRequest",
|
|
20986
20986
|
"Start-Process"
|
|
20987
20987
|
]);
|
|
20988
|
-
|
|
20989
|
-
|
|
20988
|
+
_PS_WRITE_ALIASES = new Set(["echo", "write"]);
|
|
20989
|
+
_CMD_WRITE_BUILTINS = new Set([
|
|
20990
20990
|
"copy",
|
|
20991
20991
|
"move",
|
|
20992
20992
|
"type",
|
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.
|
|
51
|
+
version: "7.28.0",
|
|
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",
|
|
@@ -34311,8 +34311,8 @@ function wordText(node) {
|
|
|
34311
34311
|
if (!node || typeof node !== "object")
|
|
34312
34312
|
return null;
|
|
34313
34313
|
const n = node;
|
|
34314
|
-
if (n
|
|
34315
|
-
return n
|
|
34314
|
+
if (n.type === "Word" && typeof n.text === "string") {
|
|
34315
|
+
return n.text;
|
|
34316
34316
|
}
|
|
34317
34317
|
return null;
|
|
34318
34318
|
}
|
|
@@ -34320,64 +34320,62 @@ function collectLeafCommands(node, out2) {
|
|
|
34320
34320
|
if (!node || typeof node !== "object")
|
|
34321
34321
|
return;
|
|
34322
34322
|
const n = node;
|
|
34323
|
-
const type = n
|
|
34323
|
+
const type = n.type;
|
|
34324
34324
|
switch (type) {
|
|
34325
34325
|
case "Script":
|
|
34326
|
-
if (Array.isArray(n
|
|
34327
|
-
for (const cmd of n
|
|
34326
|
+
if (Array.isArray(n.commands)) {
|
|
34327
|
+
for (const cmd of n.commands) {
|
|
34328
34328
|
collectLeafCommands(cmd, out2);
|
|
34329
34329
|
}
|
|
34330
34330
|
}
|
|
34331
34331
|
break;
|
|
34332
34332
|
case "Pipeline":
|
|
34333
34333
|
case "Sequence":
|
|
34334
|
-
if (Array.isArray(n
|
|
34335
|
-
for (const cmd of n
|
|
34334
|
+
if (Array.isArray(n.commands)) {
|
|
34335
|
+
for (const cmd of n.commands) {
|
|
34336
34336
|
collectLeafCommands(cmd, out2);
|
|
34337
34337
|
}
|
|
34338
34338
|
}
|
|
34339
34339
|
break;
|
|
34340
34340
|
case "CompoundList":
|
|
34341
34341
|
out2.push(node);
|
|
34342
|
-
if (Array.isArray(n
|
|
34343
|
-
for (const cmd of n
|
|
34342
|
+
if (Array.isArray(n.commands)) {
|
|
34343
|
+
for (const cmd of n.commands) {
|
|
34344
34344
|
collectLeafCommands(cmd, out2);
|
|
34345
34345
|
}
|
|
34346
34346
|
}
|
|
34347
34347
|
break;
|
|
34348
34348
|
case "LogicalExpression":
|
|
34349
|
-
if (n
|
|
34350
|
-
collectLeafCommands(n
|
|
34351
|
-
if (n
|
|
34352
|
-
collectLeafCommands(n
|
|
34349
|
+
if (n.left)
|
|
34350
|
+
collectLeafCommands(n.left, out2);
|
|
34351
|
+
if (n.right)
|
|
34352
|
+
collectLeafCommands(n.right, out2);
|
|
34353
34353
|
break;
|
|
34354
34354
|
case "And":
|
|
34355
34355
|
case "Or":
|
|
34356
|
-
if (n
|
|
34357
|
-
collectLeafCommands(n
|
|
34358
|
-
if (n
|
|
34359
|
-
collectLeafCommands(n
|
|
34356
|
+
if (n.left)
|
|
34357
|
+
collectLeafCommands(n.left, out2);
|
|
34358
|
+
if (n.right)
|
|
34359
|
+
collectLeafCommands(n.right, out2);
|
|
34360
34360
|
break;
|
|
34361
34361
|
case "Subshell":
|
|
34362
34362
|
out2.push(node);
|
|
34363
|
-
if (n
|
|
34364
|
-
collectLeafCommands(n
|
|
34363
|
+
if (n.list)
|
|
34364
|
+
collectLeafCommands(n.list, out2);
|
|
34365
34365
|
break;
|
|
34366
34366
|
case "ProcessSubstitution":
|
|
34367
34367
|
{
|
|
34368
|
-
const op = n
|
|
34368
|
+
const op = n.op;
|
|
34369
34369
|
if (op && typeof op === "object") {
|
|
34370
|
-
const opType = op
|
|
34370
|
+
const opType = op.type?.toUpperCase();
|
|
34371
34371
|
if (opType === "GREAT") {
|
|
34372
|
-
if (n
|
|
34373
|
-
collectLeafCommands(n
|
|
34372
|
+
if (n.command) {
|
|
34373
|
+
collectLeafCommands(n.command, out2);
|
|
34374
34374
|
}
|
|
34375
34375
|
}
|
|
34376
34376
|
}
|
|
34377
34377
|
}
|
|
34378
34378
|
break;
|
|
34379
|
-
case "Command":
|
|
34380
|
-
case "SimpleCommand":
|
|
34381
34379
|
default:
|
|
34382
34380
|
out2.push(node);
|
|
34383
34381
|
break;
|
|
@@ -34387,15 +34385,15 @@ function getCommandName(cmd) {
|
|
|
34387
34385
|
if (!cmd || typeof cmd !== "object")
|
|
34388
34386
|
return null;
|
|
34389
34387
|
const c = cmd;
|
|
34390
|
-
if (typeof c
|
|
34391
|
-
return c
|
|
34392
|
-
return wordText(c
|
|
34388
|
+
if (typeof c.name === "string")
|
|
34389
|
+
return c.name;
|
|
34390
|
+
return wordText(c.name);
|
|
34393
34391
|
}
|
|
34394
34392
|
function getSuffixWords(cmd) {
|
|
34395
34393
|
if (!cmd || typeof cmd !== "object")
|
|
34396
34394
|
return [];
|
|
34397
34395
|
const c = cmd;
|
|
34398
|
-
const suffix = c
|
|
34396
|
+
const suffix = c.suffix;
|
|
34399
34397
|
if (!Array.isArray(suffix))
|
|
34400
34398
|
return [];
|
|
34401
34399
|
return suffix.map((s) => wordText(s) ?? "");
|
|
@@ -34404,12 +34402,12 @@ function getRedirections(cmd) {
|
|
|
34404
34402
|
if (!cmd || typeof cmd !== "object")
|
|
34405
34403
|
return [];
|
|
34406
34404
|
const c = cmd;
|
|
34407
|
-
if (Array.isArray(c
|
|
34408
|
-
return c
|
|
34405
|
+
if (Array.isArray(c.redirections)) {
|
|
34406
|
+
return c.redirections;
|
|
34409
34407
|
}
|
|
34410
34408
|
const results = [];
|
|
34411
|
-
const suffix = c
|
|
34412
|
-
const prefix = c
|
|
34409
|
+
const suffix = c.suffix;
|
|
34410
|
+
const prefix = c.prefix;
|
|
34413
34411
|
if (Array.isArray(suffix)) {
|
|
34414
34412
|
for (const item of suffix) {
|
|
34415
34413
|
if (isRedirectNode(item))
|
|
@@ -34425,13 +34423,13 @@ function getRedirections(cmd) {
|
|
|
34425
34423
|
return results;
|
|
34426
34424
|
}
|
|
34427
34425
|
function isRedirectNode(node) {
|
|
34428
|
-
return !!(node && typeof node === "object" && node
|
|
34426
|
+
return !!(node && typeof node === "object" && node.type === "Redirect");
|
|
34429
34427
|
}
|
|
34430
34428
|
function operatorLabel(op) {
|
|
34431
34429
|
if (!op || typeof op !== "object")
|
|
34432
34430
|
return "unknown";
|
|
34433
34431
|
const o = op;
|
|
34434
|
-
const opType = o
|
|
34432
|
+
const opType = o.type?.toUpperCase();
|
|
34435
34433
|
switch (opType) {
|
|
34436
34434
|
case "GREAT":
|
|
34437
34435
|
return ">";
|
|
@@ -34475,13 +34473,13 @@ function detectRedirects(cmd) {
|
|
|
34475
34473
|
if (!redirect || typeof redirect !== "object")
|
|
34476
34474
|
continue;
|
|
34477
34475
|
const r = redirect;
|
|
34478
|
-
const opNode = r
|
|
34476
|
+
const opNode = r.op;
|
|
34479
34477
|
if (!opNode || typeof opNode !== "object")
|
|
34480
34478
|
continue;
|
|
34481
|
-
const opType = opNode
|
|
34479
|
+
const opType = opNode.type?.toUpperCase();
|
|
34482
34480
|
if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
|
|
34483
34481
|
continue;
|
|
34484
|
-
const fileNode = r
|
|
34482
|
+
const fileNode = r.file;
|
|
34485
34483
|
const path11 = extractRedirectPath(fileNode);
|
|
34486
34484
|
const opLabel = operatorLabel(opNode);
|
|
34487
34485
|
if (REDIRECT_WRITE_TOKENS.has(opType)) {
|
|
@@ -34497,16 +34495,16 @@ function detectHereDocMarkers(cmd) {
|
|
|
34497
34495
|
if (!cmd || typeof cmd !== "object")
|
|
34498
34496
|
return results;
|
|
34499
34497
|
const c = cmd;
|
|
34500
|
-
const suffix = c
|
|
34498
|
+
const suffix = c.suffix;
|
|
34501
34499
|
if (!Array.isArray(suffix))
|
|
34502
34500
|
return results;
|
|
34503
34501
|
for (const item of suffix) {
|
|
34504
34502
|
if (!item || typeof item !== "object")
|
|
34505
34503
|
continue;
|
|
34506
34504
|
const n = item;
|
|
34507
|
-
const type = n
|
|
34505
|
+
const type = n.type?.toLowerCase();
|
|
34508
34506
|
if (type === "dless" || type === "dlessdash") {
|
|
34509
|
-
const text = n
|
|
34507
|
+
const text = n.text;
|
|
34510
34508
|
results.push({
|
|
34511
34509
|
category: "here_doc",
|
|
34512
34510
|
operator: text === "<<-" ? "<<-" : "<<",
|
|
@@ -34893,7 +34891,7 @@ function detectPowerShellWrites(command) {
|
|
|
34893
34891
|
const op = redirectMatch[2];
|
|
34894
34892
|
const path11 = redirectMatch[3];
|
|
34895
34893
|
const fdRedirectPattern = /\d>\s*$|\s\d>&$/;
|
|
34896
|
-
if (!fdRedirectPattern.test(beforeRedirect
|
|
34894
|
+
if (!fdRedirectPattern.test(`${beforeRedirect} ${op}`)) {
|
|
34897
34895
|
results.push({ category: "redirect", operator: op, path: path11 });
|
|
34898
34896
|
}
|
|
34899
34897
|
}
|
|
@@ -35034,8 +35032,8 @@ function detectPowerShellWrites(command) {
|
|
|
35034
35032
|
}
|
|
35035
35033
|
const aliasRedirectMatch = trimmed.match(/^(echo|write)\s+(\S+.*?)\s*(?:>|\s{2,})/i);
|
|
35036
35034
|
if (aliasRedirectMatch) {
|
|
35037
|
-
const
|
|
35038
|
-
const
|
|
35035
|
+
const _aliasPart = aliasRedirectMatch[0];
|
|
35036
|
+
const _afterAlias = trimmed.slice(aliasRedirectMatch[0].length);
|
|
35039
35037
|
const fullRedirectMatch = trimmed.match(/((?:>){1,2})\s*(\S+)$/);
|
|
35040
35038
|
if (fullRedirectMatch) {
|
|
35041
35039
|
results.push({
|
|
@@ -35295,28 +35293,28 @@ function getCdTarget(cmd) {
|
|
|
35295
35293
|
if (!cmd || typeof cmd !== "object")
|
|
35296
35294
|
return null;
|
|
35297
35295
|
const c = cmd;
|
|
35298
|
-
const nodeType = c
|
|
35296
|
+
const nodeType = c.type;
|
|
35299
35297
|
if (nodeType !== "SimpleCommand" && nodeType !== "Command")
|
|
35300
35298
|
return null;
|
|
35301
|
-
const name2 = c
|
|
35299
|
+
const name2 = c.name;
|
|
35302
35300
|
if (!name2 || typeof name2 !== "object")
|
|
35303
35301
|
return null;
|
|
35304
35302
|
const n = name2;
|
|
35305
|
-
if (n
|
|
35303
|
+
if (n.type !== "Word")
|
|
35306
35304
|
return null;
|
|
35307
|
-
const text = n
|
|
35305
|
+
const text = n.text;
|
|
35308
35306
|
if (text !== "cd")
|
|
35309
35307
|
return null;
|
|
35310
|
-
const suffix = c
|
|
35308
|
+
const suffix = c.suffix;
|
|
35311
35309
|
if (!Array.isArray(suffix) || suffix.length === 0)
|
|
35312
35310
|
return null;
|
|
35313
35311
|
const first = suffix[0];
|
|
35314
35312
|
if (!first || typeof first !== "object")
|
|
35315
35313
|
return null;
|
|
35316
35314
|
const firstWord = first;
|
|
35317
|
-
if (firstWord
|
|
35315
|
+
if (firstWord.type !== "Word")
|
|
35318
35316
|
return null;
|
|
35319
|
-
const target = firstWord
|
|
35317
|
+
const target = firstWord.text;
|
|
35320
35318
|
if (target === "-" || target === "~" || target === "~" + "/")
|
|
35321
35319
|
return null;
|
|
35322
35320
|
return target;
|
|
@@ -35325,12 +35323,12 @@ function collectWritesWithNodes(node, out2, cwdStack) {
|
|
|
35325
35323
|
if (!node || typeof node !== "object")
|
|
35326
35324
|
return;
|
|
35327
35325
|
const n = node;
|
|
35328
|
-
const type = n
|
|
35326
|
+
const type = n.type;
|
|
35329
35327
|
switch (type) {
|
|
35330
35328
|
case "Script": {
|
|
35331
|
-
const
|
|
35332
|
-
if (Array.isArray(n
|
|
35333
|
-
for (const cmd of n
|
|
35329
|
+
const _globalCwd = cwdStack[0] ?? "/";
|
|
35330
|
+
if (Array.isArray(n.commands)) {
|
|
35331
|
+
for (const cmd of n.commands) {
|
|
35334
35332
|
collectWritesWithNodes(cmd, out2, cwdStack);
|
|
35335
35333
|
}
|
|
35336
35334
|
}
|
|
@@ -35338,7 +35336,7 @@ function collectWritesWithNodes(node, out2, cwdStack) {
|
|
|
35338
35336
|
}
|
|
35339
35337
|
case "Subshell": {
|
|
35340
35338
|
const effectiveCwd = cwdStack[0] ?? "/";
|
|
35341
|
-
const subshellRedirs = n
|
|
35339
|
+
const subshellRedirs = n.redirections;
|
|
35342
35340
|
if (Array.isArray(subshellRedirs)) {
|
|
35343
35341
|
for (const redirect of subshellRedirs) {
|
|
35344
35342
|
const writesFromRedirect = getWritesFromRedirectNode(redirect, effectiveCwd);
|
|
@@ -35347,16 +35345,16 @@ function collectWritesWithNodes(node, out2, cwdStack) {
|
|
|
35347
35345
|
}
|
|
35348
35346
|
}
|
|
35349
35347
|
}
|
|
35350
|
-
if (n
|
|
35348
|
+
if (n.list) {
|
|
35351
35349
|
const subStack = [...cwdStack];
|
|
35352
|
-
collectWritesWithNodes(n
|
|
35350
|
+
collectWritesWithNodes(n.list, out2, subStack);
|
|
35353
35351
|
}
|
|
35354
35352
|
break;
|
|
35355
35353
|
}
|
|
35356
35354
|
case "CompoundList": {
|
|
35357
|
-
if (Array.isArray(n
|
|
35355
|
+
if (Array.isArray(n.commands)) {
|
|
35358
35356
|
const currentStack = cwdStack;
|
|
35359
|
-
for (const cmd of n
|
|
35357
|
+
for (const cmd of n.commands) {
|
|
35360
35358
|
const cdTarget = getCdTarget(cmd);
|
|
35361
35359
|
if (cdTarget) {
|
|
35362
35360
|
currentStack[0] = path10.posix.resolve(currentStack[0] ?? "/", cdTarget);
|
|
@@ -35370,32 +35368,32 @@ function collectWritesWithNodes(node, out2, cwdStack) {
|
|
|
35370
35368
|
}
|
|
35371
35369
|
case "Pipeline":
|
|
35372
35370
|
case "Sequence": {
|
|
35373
|
-
if (Array.isArray(n
|
|
35374
|
-
for (const cmd of n
|
|
35371
|
+
if (Array.isArray(n.commands)) {
|
|
35372
|
+
for (const cmd of n.commands) {
|
|
35375
35373
|
collectWritesWithNodes(cmd, out2, cwdStack);
|
|
35376
35374
|
}
|
|
35377
35375
|
}
|
|
35378
35376
|
break;
|
|
35379
35377
|
}
|
|
35380
35378
|
case "LogicalExpression": {
|
|
35381
|
-
if (n
|
|
35382
|
-
collectWritesWithNodes(n
|
|
35379
|
+
if (n.left) {
|
|
35380
|
+
collectWritesWithNodes(n.left, out2, cwdStack);
|
|
35383
35381
|
const leftContext = cwdStack[0] ?? "/";
|
|
35384
|
-
if (n
|
|
35382
|
+
if (n.right) {
|
|
35385
35383
|
const rightStack = [leftContext];
|
|
35386
|
-
collectWritesWithNodes(n
|
|
35384
|
+
collectWritesWithNodes(n.right, out2, rightStack);
|
|
35387
35385
|
}
|
|
35388
35386
|
}
|
|
35389
35387
|
break;
|
|
35390
35388
|
}
|
|
35391
35389
|
case "And":
|
|
35392
35390
|
case "Or": {
|
|
35393
|
-
if (n
|
|
35394
|
-
collectWritesWithNodes(n
|
|
35391
|
+
if (n.left) {
|
|
35392
|
+
collectWritesWithNodes(n.left, out2, cwdStack);
|
|
35395
35393
|
const leftContext = cwdStack[0] ?? "/";
|
|
35396
|
-
if (n
|
|
35394
|
+
if (n.right) {
|
|
35397
35395
|
const rightStack = [leftContext];
|
|
35398
|
-
collectWritesWithNodes(n
|
|
35396
|
+
collectWritesWithNodes(n.right, out2, rightStack);
|
|
35399
35397
|
}
|
|
35400
35398
|
}
|
|
35401
35399
|
break;
|
|
@@ -35444,13 +35442,13 @@ function getWritesFromRedirectNode(redirect, _context) {
|
|
|
35444
35442
|
if (!redirect || typeof redirect !== "object")
|
|
35445
35443
|
return [];
|
|
35446
35444
|
const r = redirect;
|
|
35447
|
-
const opNode = r
|
|
35445
|
+
const opNode = r.op;
|
|
35448
35446
|
if (!opNode || typeof opNode !== "object")
|
|
35449
35447
|
return [];
|
|
35450
|
-
const opType = opNode
|
|
35448
|
+
const opType = opNode.type?.toUpperCase();
|
|
35451
35449
|
if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
|
|
35452
35450
|
return [];
|
|
35453
|
-
const fileNode = r
|
|
35451
|
+
const fileNode = r.file;
|
|
35454
35452
|
const path11 = extractRedirectPath(fileNode);
|
|
35455
35453
|
const opLabel = operatorLabel(opNode);
|
|
35456
35454
|
if (REDIRECT_WRITE_TOKENS.has(opType)) {
|
|
@@ -35466,8 +35464,8 @@ function getWritesFromCommandRedirs(cmd, context) {
|
|
|
35466
35464
|
const c = cmd;
|
|
35467
35465
|
const results = [];
|
|
35468
35466
|
results.push(...detectHereDocMarkers(cmd));
|
|
35469
|
-
const suffix = c
|
|
35470
|
-
const prefix = c
|
|
35467
|
+
const suffix = c.suffix;
|
|
35468
|
+
const prefix = c.prefix;
|
|
35471
35469
|
if (Array.isArray(suffix)) {
|
|
35472
35470
|
for (const item of suffix) {
|
|
35473
35471
|
if (isRedirectNode(item)) {
|
|
@@ -35544,7 +35542,7 @@ function resolveWriteTargets(command, writes, cwd) {
|
|
|
35544
35542
|
};
|
|
35545
35543
|
});
|
|
35546
35544
|
}
|
|
35547
|
-
var import_bash_parser, REDIRECT_WRITE_TOKENS, REDIRECT_HERE_TOKENS, REDIRECT_ALL_WRITE_TOKENS, BUILTIN_WRITE_COMMANDS, INPLACE_EDIT_COMMANDS, INTERPRETER_EVAL_COMMANDS, NETWORK_DOWNLOAD_COMMANDS, ARCHIVE_EXTRACT_COMMANDS, GIT_COMMAND = "git",
|
|
35545
|
+
var import_bash_parser, REDIRECT_WRITE_TOKENS, REDIRECT_HERE_TOKENS, REDIRECT_ALL_WRITE_TOKENS, BUILTIN_WRITE_COMMANDS, INPLACE_EDIT_COMMANDS, INTERPRETER_EVAL_COMMANDS, NETWORK_DOWNLOAD_COMMANDS, ARCHIVE_EXTRACT_COMMANDS, GIT_COMMAND = "git", _PS_WRITE_CMDLETS, _PS_WRITE_ALIASES, _CMD_WRITE_BUILTINS;
|
|
35548
35546
|
var init_shell_write_detect = __esm(() => {
|
|
35549
35547
|
import_bash_parser = __toESM(require_src(), 1);
|
|
35550
35548
|
REDIRECT_WRITE_TOKENS = new Set([
|
|
@@ -35587,7 +35585,7 @@ var init_shell_write_detect = __esm(() => {
|
|
|
35587
35585
|
"7z",
|
|
35588
35586
|
"rar"
|
|
35589
35587
|
]);
|
|
35590
|
-
|
|
35588
|
+
_PS_WRITE_CMDLETS = new Set([
|
|
35591
35589
|
"Out-File",
|
|
35592
35590
|
"Set-Content",
|
|
35593
35591
|
"Add-Content",
|
|
@@ -35598,8 +35596,8 @@ var init_shell_write_detect = __esm(() => {
|
|
|
35598
35596
|
"Invoke-WebRequest",
|
|
35599
35597
|
"Start-Process"
|
|
35600
35598
|
]);
|
|
35601
|
-
|
|
35602
|
-
|
|
35599
|
+
_PS_WRITE_ALIASES = new Set(["echo", "write"]);
|
|
35600
|
+
_CMD_WRITE_BUILTINS = new Set([
|
|
35603
35601
|
"copy",
|
|
35604
35602
|
"move",
|
|
35605
35603
|
"type",
|
|
@@ -38848,6 +38846,73 @@ function isTaskCompletedForParallelGuidance(task) {
|
|
|
38848
38846
|
const status = task.status ?? "pending";
|
|
38849
38847
|
return status === "completed" || status === "closed";
|
|
38850
38848
|
}
|
|
38849
|
+
function getPlanTaskStatus(plan, taskId) {
|
|
38850
|
+
for (const phase of plan.phases) {
|
|
38851
|
+
const task = phase.tasks.find((candidate) => candidate.id === taskId);
|
|
38852
|
+
if (task)
|
|
38853
|
+
return task.status ?? "pending";
|
|
38854
|
+
}
|
|
38855
|
+
return null;
|
|
38856
|
+
}
|
|
38857
|
+
function resolveDelegatedPlanTaskId(args2, knownPlanTaskIds) {
|
|
38858
|
+
const rawTaskId = args2.task_id ?? args2.taskId;
|
|
38859
|
+
if (typeof rawTaskId === "string") {
|
|
38860
|
+
const trimmed = rawTaskId.trim();
|
|
38861
|
+
if (trimmed.length <= 20 && isStrictTaskId(trimmed))
|
|
38862
|
+
return trimmed;
|
|
38863
|
+
return null;
|
|
38864
|
+
}
|
|
38865
|
+
const candidateTextFields = [
|
|
38866
|
+
args2.prompt,
|
|
38867
|
+
args2.description,
|
|
38868
|
+
args2.task,
|
|
38869
|
+
args2.input
|
|
38870
|
+
];
|
|
38871
|
+
const seen = new Set;
|
|
38872
|
+
for (const field of candidateTextFields) {
|
|
38873
|
+
if (typeof field !== "string")
|
|
38874
|
+
continue;
|
|
38875
|
+
for (const m of field.matchAll(/\b(\d+\.\d+(?:\.\d+)*)\b/g)) {
|
|
38876
|
+
const candidate = m[1];
|
|
38877
|
+
if (isStrictTaskId(candidate)) {
|
|
38878
|
+
if (knownPlanTaskIds && !knownPlanTaskIds.has(candidate))
|
|
38879
|
+
continue;
|
|
38880
|
+
seen.add(candidate);
|
|
38881
|
+
}
|
|
38882
|
+
}
|
|
38883
|
+
}
|
|
38884
|
+
if (seen.size === 1)
|
|
38885
|
+
return seen.values().next().value;
|
|
38886
|
+
return null;
|
|
38887
|
+
}
|
|
38888
|
+
async function findTaskAwaitingCompletion(directory, session, requestedTaskId) {
|
|
38889
|
+
if (!directory)
|
|
38890
|
+
return null;
|
|
38891
|
+
let plan = null;
|
|
38892
|
+
try {
|
|
38893
|
+
plan = await loadPlanJsonOnly(directory);
|
|
38894
|
+
} catch {
|
|
38895
|
+
return null;
|
|
38896
|
+
}
|
|
38897
|
+
if (!plan)
|
|
38898
|
+
return null;
|
|
38899
|
+
for (const [taskId, state] of session.taskWorkflowStates) {
|
|
38900
|
+
if (state !== "tests_run")
|
|
38901
|
+
continue;
|
|
38902
|
+
if (requestedTaskId && requestedTaskId === taskId)
|
|
38903
|
+
continue;
|
|
38904
|
+
const planStatus = getPlanTaskStatus(plan, taskId);
|
|
38905
|
+
if (!planStatus)
|
|
38906
|
+
continue;
|
|
38907
|
+
if (planStatus === "completed" || planStatus === "closed")
|
|
38908
|
+
continue;
|
|
38909
|
+
return taskId;
|
|
38910
|
+
}
|
|
38911
|
+
return null;
|
|
38912
|
+
}
|
|
38913
|
+
function completionGateViolationMessage(taskAwaitingCompletion) {
|
|
38914
|
+
return `TASK_COMPLETION_GATE_VIOLATION: Task ${taskAwaitingCompletion} reached tests_run but is not marked completed in plan.json/plan.md. ` + `Call update_task_status with task_id="${taskAwaitingCompletion}" and status="completed" before starting another task.`;
|
|
38915
|
+
}
|
|
38851
38916
|
async function buildParallelExecutionGuidance(directory, sessionID, session) {
|
|
38852
38917
|
if (!directory)
|
|
38853
38918
|
return null;
|
|
@@ -38961,6 +39026,27 @@ function createDelegationGateHook(config2, directory) {
|
|
|
38961
39026
|
if (!input.sessionID)
|
|
38962
39027
|
return;
|
|
38963
39028
|
const normalized = normalizeToolName(input.tool);
|
|
39029
|
+
const completionArgs = output.args;
|
|
39030
|
+
if (completionArgs) {
|
|
39031
|
+
let completionPlanTaskIds;
|
|
39032
|
+
try {
|
|
39033
|
+
const plan = await loadPlanJsonOnly(directory);
|
|
39034
|
+
if (plan) {
|
|
39035
|
+
completionPlanTaskIds = new Set(plan.phases.flatMap((p) => p.tasks.map((t) => t.id)));
|
|
39036
|
+
}
|
|
39037
|
+
} catch {}
|
|
39038
|
+
const requestedTaskId = resolveDelegatedPlanTaskId(completionArgs, completionPlanTaskIds);
|
|
39039
|
+
const completionSession = ensureAgentSession(input.sessionID);
|
|
39040
|
+
const taskAwaitingCompletion = await findTaskAwaitingCompletion(directory, completionSession, requestedTaskId);
|
|
39041
|
+
if (taskAwaitingCompletion) {
|
|
39042
|
+
const allowingSameTaskRetry = requestedTaskId === taskAwaitingCompletion;
|
|
39043
|
+
const requestedTaskIsAwaitingCompletion = requestedTaskId && completionSession.taskWorkflowStates.get(requestedTaskId) === "tests_run";
|
|
39044
|
+
const allowCompletionUpdate = normalized === "update_task_status" && completionArgs.status === "completed" && requestedTaskIsAwaitingCompletion;
|
|
39045
|
+
if (!allowingSameTaskRetry && !allowCompletionUpdate) {
|
|
39046
|
+
throw new Error(completionGateViolationMessage(taskAwaitingCompletion));
|
|
39047
|
+
}
|
|
39048
|
+
}
|
|
39049
|
+
}
|
|
38964
39050
|
if (normalized !== "Task" && normalized !== "task")
|
|
38965
39051
|
return;
|
|
38966
39052
|
const args2 = output.args;
|
|
@@ -39018,6 +39104,23 @@ function createDelegationGateHook(config2, directory) {
|
|
|
39018
39104
|
return;
|
|
39019
39105
|
const normalized = normalizeToolName(input.tool);
|
|
39020
39106
|
const councilActive = await isCouncilGateActive(directory, config2.council);
|
|
39107
|
+
if (normalized === "update_task_status") {
|
|
39108
|
+
const directArgs = input.args;
|
|
39109
|
+
const storedArgs = getStoredInputArgs(input.callID);
|
|
39110
|
+
const completionArgs = directArgs ?? storedArgs;
|
|
39111
|
+
if (completionArgs && completionArgs.status === "completed") {
|
|
39112
|
+
const rawTaskId = completionArgs.task_id ?? completionArgs.taskId;
|
|
39113
|
+
const completionTaskId = typeof rawTaskId === "string" ? rawTaskId.trim() : null;
|
|
39114
|
+
if (completionTaskId && isStrictTaskId(completionTaskId)) {
|
|
39115
|
+
try {
|
|
39116
|
+
const completionSession = ensureAgentSession(input.sessionID);
|
|
39117
|
+
await advanceTaskStateAndPersist(completionSession, completionTaskId, "complete", directory, { telemetrySessionId: input.sessionID }, config2.council);
|
|
39118
|
+
} catch (err2) {
|
|
39119
|
+
warn(`[delegation-gate] toolAfter completion advancement: could not advance ${completionTaskId} → complete: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
39120
|
+
}
|
|
39121
|
+
}
|
|
39122
|
+
}
|
|
39123
|
+
}
|
|
39021
39124
|
if (normalized === "submit_council_verdicts") {
|
|
39022
39125
|
try {
|
|
39023
39126
|
const parsed = typeof _output === "string" ? JSON.parse(_output) : _output;
|
|
@@ -39290,6 +39393,18 @@ function createDelegationGateHook(config2, directory) {
|
|
|
39290
39393
|
console.warn(`[delegation-gate] fallback evidence recording failed: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
39291
39394
|
}
|
|
39292
39395
|
}
|
|
39396
|
+
if (session.taskWorkflowStates) {
|
|
39397
|
+
for (const [, state] of session.taskWorkflowStates) {
|
|
39398
|
+
if (state === "tests_run") {
|
|
39399
|
+
const taskAwaiting = await findTaskAwaitingCompletion(directory, session);
|
|
39400
|
+
if (taskAwaiting) {
|
|
39401
|
+
session.pendingAdvisoryMessages ??= [];
|
|
39402
|
+
session.pendingAdvisoryMessages.push(completionGateViolationMessage(taskAwaiting));
|
|
39403
|
+
}
|
|
39404
|
+
break;
|
|
39405
|
+
}
|
|
39406
|
+
}
|
|
39407
|
+
}
|
|
39293
39408
|
}
|
|
39294
39409
|
};
|
|
39295
39410
|
return {
|
|
@@ -39414,8 +39529,12 @@ ${trimComment}${after}`;
|
|
|
39414
39529
|
const deliberationSession = ensureAgentSession(deliberationSessionID);
|
|
39415
39530
|
const lastGate = deliberationSession.lastGateOutcome;
|
|
39416
39531
|
const parallelGuidance = await buildParallelExecutionGuidance(directory, deliberationSessionID, deliberationSession);
|
|
39532
|
+
const taskAwaitingCompletion = await findTaskAwaitingCompletion(directory, deliberationSession);
|
|
39417
39533
|
let guidance;
|
|
39418
|
-
if (
|
|
39534
|
+
if (taskAwaitingCompletion) {
|
|
39535
|
+
guidance = `[TASK COMPLETION REQUIRED] Task ${taskAwaitingCompletion} has completed reviewer/test_engineer gates and is awaiting durable plan update.
|
|
39536
|
+
[NEXT] Print the task completion checklist, then call update_task_status with task_id="${taskAwaitingCompletion}" and status="completed" before declare_scope or starting another task.`;
|
|
39537
|
+
} else if (lastGate?.taskId) {
|
|
39419
39538
|
const gateResult = lastGate.passed ? "PASSED" : "FAILED";
|
|
39420
39539
|
const sanitizedGate = lastGate.gate.replace(/</g, "<").replace(/>/g, ">").replace(/\[ \]/g, "()").replace(/\[/g, "(").replace(/\]/g, ")").replace(/[\r\n]/g, " ").slice(0, 64);
|
|
39421
39540
|
const sanitizedTaskId = lastGate.taskId.replace(/</g, "<").replace(/>/g, ">").replace(/\[/g, "(").replace(/\]/g, ")").replace(/[\r\n]/g, " ").slice(0, 32);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.28.0",
|
|
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",
|