opencode-swarm 6.86.11 → 6.86.12
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 +49 -15
- package/dist/commands/knowledge.d.ts +2 -0
- package/dist/index.js +60 -26
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -18580,7 +18580,7 @@ import * as path33 from "path";
|
|
|
18580
18580
|
// package.json
|
|
18581
18581
|
var package_default = {
|
|
18582
18582
|
name: "opencode-swarm",
|
|
18583
|
-
version: "6.86.
|
|
18583
|
+
version: "6.86.12",
|
|
18584
18584
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
18585
18585
|
main: "dist/index.js",
|
|
18586
18586
|
types: "dist/index.d.ts",
|
|
@@ -39480,6 +39480,9 @@ async function handleHistoryCommand(directory, _args) {
|
|
|
39480
39480
|
const historyData = await getHistoryData(directory);
|
|
39481
39481
|
return formatHistoryMarkdown(historyData);
|
|
39482
39482
|
}
|
|
39483
|
+
// src/commands/knowledge.ts
|
|
39484
|
+
import { join as join21 } from "path";
|
|
39485
|
+
|
|
39483
39486
|
// src/hooks/knowledge-migrator.ts
|
|
39484
39487
|
init_logger();
|
|
39485
39488
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -39710,34 +39713,65 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
39710
39713
|
}
|
|
39711
39714
|
|
|
39712
39715
|
// src/commands/knowledge.ts
|
|
39716
|
+
function resolveEntryByPrefix(entries, inputId) {
|
|
39717
|
+
const exact = entries.find((e) => e.id === inputId);
|
|
39718
|
+
if (exact)
|
|
39719
|
+
return { entry: exact };
|
|
39720
|
+
const matches = entries.filter((e) => e.id.startsWith(inputId));
|
|
39721
|
+
if (matches.length === 0) {
|
|
39722
|
+
return { error: `No entry found matching '${inputId}'.` };
|
|
39723
|
+
}
|
|
39724
|
+
if (matches.length === 1) {
|
|
39725
|
+
return { entry: matches[0] };
|
|
39726
|
+
}
|
|
39727
|
+
const candidates = matches.map((e) => e.id).join(`
|
|
39728
|
+
`);
|
|
39729
|
+
return {
|
|
39730
|
+
error: `Ambiguous prefix '${inputId}' matches ${matches.length} entries:
|
|
39731
|
+
${candidates}`
|
|
39732
|
+
};
|
|
39733
|
+
}
|
|
39713
39734
|
async function handleKnowledgeQuarantineCommand(directory, args) {
|
|
39714
|
-
const
|
|
39715
|
-
if (!
|
|
39735
|
+
const inputId = args[0];
|
|
39736
|
+
if (!inputId) {
|
|
39716
39737
|
return "Usage: /swarm knowledge quarantine <id> [reason]";
|
|
39717
39738
|
}
|
|
39718
|
-
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(
|
|
39739
|
+
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
|
|
39719
39740
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
39720
39741
|
}
|
|
39721
39742
|
const reason = args.slice(1).join(" ") || "Quarantined via /swarm knowledge quarantine command";
|
|
39722
39743
|
try {
|
|
39723
|
-
await
|
|
39724
|
-
|
|
39744
|
+
const entries = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
39745
|
+
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
39746
|
+
if ("error" in resolved) {
|
|
39747
|
+
return `\u274C ${resolved.error}`;
|
|
39748
|
+
}
|
|
39749
|
+
const fullId = resolved.entry.id;
|
|
39750
|
+
await quarantineEntry(directory, fullId, reason, "user");
|
|
39751
|
+
return `\u2705 Entry ${fullId} quarantined successfully.`;
|
|
39725
39752
|
} catch (error93) {
|
|
39726
39753
|
console.warn("[knowledge-command] quarantineEntry error:", error93 instanceof Error ? error93.message : String(error93));
|
|
39727
39754
|
return `\u274C Failed to quarantine entry. Check the entry ID and try again.`;
|
|
39728
39755
|
}
|
|
39729
39756
|
}
|
|
39730
39757
|
async function handleKnowledgeRestoreCommand(directory, args) {
|
|
39731
|
-
const
|
|
39732
|
-
if (!
|
|
39758
|
+
const inputId = args[0];
|
|
39759
|
+
if (!inputId) {
|
|
39733
39760
|
return "Usage: /swarm knowledge restore <id>";
|
|
39734
39761
|
}
|
|
39735
|
-
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(
|
|
39762
|
+
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
|
|
39736
39763
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
39737
39764
|
}
|
|
39738
39765
|
try {
|
|
39739
|
-
|
|
39740
|
-
|
|
39766
|
+
const quarantinePath = join21(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
39767
|
+
const entries = await readKnowledge(quarantinePath);
|
|
39768
|
+
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
39769
|
+
if ("error" in resolved) {
|
|
39770
|
+
return `\u274C ${resolved.error}`;
|
|
39771
|
+
}
|
|
39772
|
+
const fullId = resolved.entry.id;
|
|
39773
|
+
await restoreEntry(directory, fullId);
|
|
39774
|
+
return `\u2705 Entry ${fullId} restored successfully.`;
|
|
39741
39775
|
} catch (error93) {
|
|
39742
39776
|
console.warn("[knowledge-command] restoreEntry error:", error93 instanceof Error ? error93.message : String(error93));
|
|
39743
39777
|
return `\u274C Failed to restore entry. Check the entry ID and try again.`;
|
|
@@ -39775,16 +39809,16 @@ async function handleKnowledgeListCommand(directory, _args) {
|
|
|
39775
39809
|
const lines = [
|
|
39776
39810
|
`## Knowledge Entries (${entries.length} total)`,
|
|
39777
39811
|
"",
|
|
39778
|
-
"| ID | Category | Confidence | Lesson (truncated) |",
|
|
39779
|
-
"
|
|
39812
|
+
"| ID (prefix) | Category | Confidence | Lesson (truncated) |",
|
|
39813
|
+
"|--------------|----------|------------|---------------------|"
|
|
39780
39814
|
];
|
|
39781
39815
|
for (const entry of entries) {
|
|
39782
39816
|
const truncatedLesson = entry.lesson.length > 60 ? `${entry.lesson.slice(0, 57)}...` : entry.lesson;
|
|
39783
39817
|
const confidencePct = Math.round(entry.confidence * 100);
|
|
39784
|
-
lines.push(`| ${entry.id.slice(0,
|
|
39818
|
+
lines.push(`| ${entry.id.slice(0, 12)}\u2026 | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
|
|
39785
39819
|
}
|
|
39786
39820
|
lines.push("");
|
|
39787
|
-
lines.push("Use `/swarm knowledge quarantine <id>` to hide an entry.");
|
|
39821
|
+
lines.push("Use `/swarm knowledge quarantine <id-prefix>` to hide an entry. Prefix matching is supported \u2014 the 12-character prefix shown is unique in most stores.");
|
|
39788
39822
|
return lines.join(`
|
|
39789
39823
|
`);
|
|
39790
39824
|
} catch (error93) {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Handles /swarm knowledge quarantine <id> [reason] command.
|
|
3
3
|
* Moves a knowledge entry to quarantine with optional reason.
|
|
4
|
+
* Accepts a full ID or a unique prefix.
|
|
4
5
|
*/
|
|
5
6
|
export declare function handleKnowledgeQuarantineCommand(directory: string, args: string[]): Promise<string>;
|
|
6
7
|
/**
|
|
7
8
|
* Handles /swarm knowledge restore <id> command.
|
|
8
9
|
* Restores a quarantined knowledge entry.
|
|
10
|
+
* Accepts a full ID or a unique prefix.
|
|
9
11
|
*/
|
|
10
12
|
export declare function handleKnowledgeRestoreCommand(directory: string, args: string[]): Promise<string>;
|
|
11
13
|
/**
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "6.86.
|
|
36
|
+
version: "6.86.12",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -48396,34 +48396,66 @@ var init_knowledge_migrator = __esm(() => {
|
|
|
48396
48396
|
});
|
|
48397
48397
|
|
|
48398
48398
|
// src/commands/knowledge.ts
|
|
48399
|
+
import { join as join28 } from "node:path";
|
|
48400
|
+
function resolveEntryByPrefix(entries, inputId) {
|
|
48401
|
+
const exact = entries.find((e) => e.id === inputId);
|
|
48402
|
+
if (exact)
|
|
48403
|
+
return { entry: exact };
|
|
48404
|
+
const matches = entries.filter((e) => e.id.startsWith(inputId));
|
|
48405
|
+
if (matches.length === 0) {
|
|
48406
|
+
return { error: `No entry found matching '${inputId}'.` };
|
|
48407
|
+
}
|
|
48408
|
+
if (matches.length === 1) {
|
|
48409
|
+
return { entry: matches[0] };
|
|
48410
|
+
}
|
|
48411
|
+
const candidates = matches.map((e) => e.id).join(`
|
|
48412
|
+
`);
|
|
48413
|
+
return {
|
|
48414
|
+
error: `Ambiguous prefix '${inputId}' matches ${matches.length} entries:
|
|
48415
|
+
${candidates}`
|
|
48416
|
+
};
|
|
48417
|
+
}
|
|
48399
48418
|
async function handleKnowledgeQuarantineCommand(directory, args2) {
|
|
48400
|
-
const
|
|
48401
|
-
if (!
|
|
48419
|
+
const inputId = args2[0];
|
|
48420
|
+
if (!inputId) {
|
|
48402
48421
|
return "Usage: /swarm knowledge quarantine <id> [reason]";
|
|
48403
48422
|
}
|
|
48404
|
-
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(
|
|
48423
|
+
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
|
|
48405
48424
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
48406
48425
|
}
|
|
48407
48426
|
const reason = args2.slice(1).join(" ") || "Quarantined via /swarm knowledge quarantine command";
|
|
48408
48427
|
try {
|
|
48409
|
-
await
|
|
48410
|
-
|
|
48428
|
+
const entries = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
48429
|
+
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
48430
|
+
if ("error" in resolved) {
|
|
48431
|
+
return `❌ ${resolved.error}`;
|
|
48432
|
+
}
|
|
48433
|
+
const fullId = resolved.entry.id;
|
|
48434
|
+
await quarantineEntry(directory, fullId, reason, "user");
|
|
48435
|
+
return `✅ Entry ${fullId} quarantined successfully.`;
|
|
48411
48436
|
} catch (error93) {
|
|
48412
48437
|
console.warn("[knowledge-command] quarantineEntry error:", error93 instanceof Error ? error93.message : String(error93));
|
|
48413
48438
|
return `❌ Failed to quarantine entry. Check the entry ID and try again.`;
|
|
48414
48439
|
}
|
|
48415
48440
|
}
|
|
48416
48441
|
async function handleKnowledgeRestoreCommand(directory, args2) {
|
|
48417
|
-
const
|
|
48418
|
-
if (!
|
|
48442
|
+
const inputId = args2[0];
|
|
48443
|
+
if (!inputId) {
|
|
48419
48444
|
return "Usage: /swarm knowledge restore <id>";
|
|
48420
48445
|
}
|
|
48421
|
-
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(
|
|
48446
|
+
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(inputId)) {
|
|
48422
48447
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
48423
48448
|
}
|
|
48424
48449
|
try {
|
|
48425
|
-
|
|
48426
|
-
|
|
48450
|
+
const quarantinePath = join28(directory, ".swarm", "knowledge-quarantined.jsonl");
|
|
48451
|
+
const entries = await readKnowledge(quarantinePath);
|
|
48452
|
+
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
48453
|
+
if ("error" in resolved) {
|
|
48454
|
+
return `❌ ${resolved.error}`;
|
|
48455
|
+
}
|
|
48456
|
+
const fullId = resolved.entry.id;
|
|
48457
|
+
await restoreEntry(directory, fullId);
|
|
48458
|
+
return `✅ Entry ${fullId} restored successfully.`;
|
|
48427
48459
|
} catch (error93) {
|
|
48428
48460
|
console.warn("[knowledge-command] restoreEntry error:", error93 instanceof Error ? error93.message : String(error93));
|
|
48429
48461
|
return `❌ Failed to restore entry. Check the entry ID and try again.`;
|
|
@@ -48461,16 +48493,16 @@ async function handleKnowledgeListCommand(directory, _args) {
|
|
|
48461
48493
|
const lines = [
|
|
48462
48494
|
`## Knowledge Entries (${entries.length} total)`,
|
|
48463
48495
|
"",
|
|
48464
|
-
"| ID | Category | Confidence | Lesson (truncated) |",
|
|
48465
|
-
"
|
|
48496
|
+
"| ID (prefix) | Category | Confidence | Lesson (truncated) |",
|
|
48497
|
+
"|--------------|----------|------------|---------------------|"
|
|
48466
48498
|
];
|
|
48467
48499
|
for (const entry of entries) {
|
|
48468
48500
|
const truncatedLesson = entry.lesson.length > 60 ? `${entry.lesson.slice(0, 57)}...` : entry.lesson;
|
|
48469
48501
|
const confidencePct = Math.round(entry.confidence * 100);
|
|
48470
|
-
lines.push(`| ${entry.id.slice(0,
|
|
48502
|
+
lines.push(`| ${entry.id.slice(0, 12)}… | ${entry.category} | ${confidencePct}% | ${truncatedLesson} |`);
|
|
48471
48503
|
}
|
|
48472
48504
|
lines.push("");
|
|
48473
|
-
lines.push("Use `/swarm knowledge quarantine <id>` to hide an entry.");
|
|
48505
|
+
lines.push("Use `/swarm knowledge quarantine <id-prefix>` to hide an entry. Prefix matching is supported — the 12-character prefix shown is unique in most stores.");
|
|
48474
48506
|
return lines.join(`
|
|
48475
48507
|
`);
|
|
48476
48508
|
} catch (error93) {
|
|
@@ -63841,7 +63873,7 @@ ${content.substring(endIndex + 1)}`;
|
|
|
63841
63873
|
init_manager();
|
|
63842
63874
|
init_utils2();
|
|
63843
63875
|
import * as fs31 from "node:fs";
|
|
63844
|
-
import { join as
|
|
63876
|
+
import { join as join42 } from "node:path";
|
|
63845
63877
|
function createCompactionCustomizerHook(config3, directory) {
|
|
63846
63878
|
const enabled = config3.hooks?.compaction !== false;
|
|
63847
63879
|
if (!enabled) {
|
|
@@ -63886,7 +63918,7 @@ function createCompactionCustomizerHook(config3, directory) {
|
|
|
63886
63918
|
}
|
|
63887
63919
|
}
|
|
63888
63920
|
try {
|
|
63889
|
-
const summariesDir =
|
|
63921
|
+
const summariesDir = join42(directory, ".swarm", "summaries");
|
|
63890
63922
|
const files = await fs31.promises.readdir(summariesDir);
|
|
63891
63923
|
if (files.length > 0) {
|
|
63892
63924
|
const count = files.length;
|
|
@@ -74619,7 +74651,7 @@ import {
|
|
|
74619
74651
|
readFileSync as readFileSync36,
|
|
74620
74652
|
writeFileSync as writeFileSync11
|
|
74621
74653
|
} from "node:fs";
|
|
74622
|
-
import { join as
|
|
74654
|
+
import { join as join66 } from "node:path";
|
|
74623
74655
|
var EVIDENCE_DIR2 = ".swarm/evidence";
|
|
74624
74656
|
var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
|
|
74625
74657
|
var COUNCIL_GATE_NAME = "council";
|
|
@@ -74653,9 +74685,9 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
74653
74685
|
if (!VALID_TASK_ID.test(synthesis.taskId)) {
|
|
74654
74686
|
throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
|
|
74655
74687
|
}
|
|
74656
|
-
const dir =
|
|
74688
|
+
const dir = join66(workingDir, EVIDENCE_DIR2);
|
|
74657
74689
|
mkdirSync18(dir, { recursive: true });
|
|
74658
|
-
const filePath =
|
|
74690
|
+
const filePath = join66(dir, `${synthesis.taskId}.json`);
|
|
74659
74691
|
const existingRoot = Object.create(null);
|
|
74660
74692
|
if (existsSync37(filePath)) {
|
|
74661
74693
|
try {
|
|
@@ -74689,7 +74721,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
74689
74721
|
updated.required_gates = [];
|
|
74690
74722
|
writeFileSync11(filePath, JSON.stringify(updated, null, 2));
|
|
74691
74723
|
try {
|
|
74692
|
-
const councilDir =
|
|
74724
|
+
const councilDir = join66(workingDir, ".swarm", "council");
|
|
74693
74725
|
mkdirSync18(councilDir, { recursive: true });
|
|
74694
74726
|
const auditLine = JSON.stringify({
|
|
74695
74727
|
round: synthesis.roundNumber,
|
|
@@ -74697,7 +74729,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
|
|
|
74697
74729
|
timestamp: synthesis.timestamp,
|
|
74698
74730
|
vetoedBy: synthesis.vetoedBy
|
|
74699
74731
|
});
|
|
74700
|
-
appendFileSync6(
|
|
74732
|
+
appendFileSync6(join66(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
|
|
74701
74733
|
`);
|
|
74702
74734
|
} catch (auditError) {
|
|
74703
74735
|
console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
|
|
@@ -74830,20 +74862,20 @@ function buildUnifiedFeedback(taskId, verdict, vetoedBy, requiredFixes, advisory
|
|
|
74830
74862
|
|
|
74831
74863
|
// src/council/criteria-store.ts
|
|
74832
74864
|
import { existsSync as existsSync38, mkdirSync as mkdirSync19, readFileSync as readFileSync37, writeFileSync as writeFileSync12 } from "node:fs";
|
|
74833
|
-
import { join as
|
|
74865
|
+
import { join as join67 } from "node:path";
|
|
74834
74866
|
var COUNCIL_DIR = ".swarm/council";
|
|
74835
74867
|
function writeCriteria(workingDir, taskId, criteria) {
|
|
74836
|
-
const dir =
|
|
74868
|
+
const dir = join67(workingDir, COUNCIL_DIR);
|
|
74837
74869
|
mkdirSync19(dir, { recursive: true });
|
|
74838
74870
|
const payload = {
|
|
74839
74871
|
taskId,
|
|
74840
74872
|
criteria,
|
|
74841
74873
|
declaredAt: new Date().toISOString()
|
|
74842
74874
|
};
|
|
74843
|
-
writeFileSync12(
|
|
74875
|
+
writeFileSync12(join67(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
|
|
74844
74876
|
}
|
|
74845
74877
|
function readCriteria(workingDir, taskId) {
|
|
74846
|
-
const filePath =
|
|
74878
|
+
const filePath = join67(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
|
|
74847
74879
|
if (!existsSync38(filePath))
|
|
74848
74880
|
return null;
|
|
74849
74881
|
try {
|
|
@@ -77388,6 +77420,7 @@ var VALID_CATEGORIES2 = [
|
|
|
77388
77420
|
"debugging",
|
|
77389
77421
|
"performance",
|
|
77390
77422
|
"integration",
|
|
77423
|
+
"todo",
|
|
77391
77424
|
"other"
|
|
77392
77425
|
];
|
|
77393
77426
|
var knowledge_add = createSwarmTool({
|
|
@@ -77532,6 +77565,7 @@ var VALID_CATEGORIES3 = [
|
|
|
77532
77565
|
"debugging",
|
|
77533
77566
|
"performance",
|
|
77534
77567
|
"integration",
|
|
77568
|
+
"todo",
|
|
77535
77569
|
"other"
|
|
77536
77570
|
];
|
|
77537
77571
|
var VALID_STATUSES = ["candidate", "established", "promoted"];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.86.
|
|
3
|
+
"version": "6.86.12",
|
|
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",
|