opencode-swarm 7.0.0 → 7.0.2
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/README.md +4 -3
- package/dist/__tests__/convene-general-council.test.d.ts +4 -2
- package/dist/agents/council-prompts.d.ts +26 -0
- package/dist/agents/council-prompts.test.d.ts +9 -0
- package/dist/agents/council-registration.test.d.ts +23 -0
- package/dist/agents/index.d.ts +1 -2
- package/dist/cli/index.d.ts +30 -0
- package/dist/cli/index.js +300 -73
- package/dist/commands/registry.d.ts +3 -3
- package/dist/commands/reset.d.ts +1 -1
- package/dist/config/cache-paths.d.ts +6 -0
- package/dist/config/constants.d.ts +2 -2
- package/dist/council/general-council-advisory.d.ts +1 -1
- package/dist/council/general-council-types.d.ts +44 -17
- package/dist/index.js +683 -686
- package/dist/plan/checkpoint.d.ts +2 -2
- package/dist/tools/checkpoint.d.ts +10 -0
- package/dist/tools/convene-general-council.d.ts +5 -4
- package/dist/tools/web-search.d.ts +1 -1
- package/package.json +1 -1
- package/dist/agents/council-member.d.ts +0 -30
- package/dist/agents/council-member.test.d.ts +0 -8
- package/dist/agents/council-moderator.d.ts +0 -20
package/dist/cli/index.js
CHANGED
|
@@ -14736,7 +14736,7 @@ async function loadPlan(directory) {
|
|
|
14736
14736
|
const rebuilt = await replayFromLedger(directory);
|
|
14737
14737
|
if (rebuilt) {
|
|
14738
14738
|
await rebuildPlan(directory, rebuilt);
|
|
14739
|
-
warn("[loadPlan] Rebuilt plan from ledger. Checkpoint available at SWARM_PLAN.md if it exists.");
|
|
14739
|
+
warn("[loadPlan] Rebuilt plan from ledger. Checkpoint available at .swarm/SWARM_PLAN.md if it exists.");
|
|
14740
14740
|
return rebuilt;
|
|
14741
14741
|
}
|
|
14742
14742
|
} catch (replayError) {
|
|
@@ -14757,7 +14757,7 @@ async function loadPlan(directory) {
|
|
|
14757
14757
|
return approved.plan;
|
|
14758
14758
|
}
|
|
14759
14759
|
} catch {}
|
|
14760
|
-
warn(`[loadPlan] Ledger replay failed during hash-mismatch rebuild: ${replayError instanceof Error ? replayError.message : String(replayError)}. Returning stale plan.json. To recover: check SWARM_PLAN.md for a checkpoint, or run /swarm reset-session.`);
|
|
14760
|
+
warn(`[loadPlan] Ledger replay failed during hash-mismatch rebuild: ${replayError instanceof Error ? replayError.message : String(replayError)}. Returning stale plan.json. To recover: check .swarm/SWARM_PLAN.md for a checkpoint, or run /swarm reset-session.`);
|
|
14761
14761
|
}
|
|
14762
14762
|
}
|
|
14763
14763
|
}
|
|
@@ -14803,7 +14803,7 @@ async function loadPlan(directory) {
|
|
|
14803
14803
|
}
|
|
14804
14804
|
return validated;
|
|
14805
14805
|
} catch (error49) {
|
|
14806
|
-
warn(`[loadPlan] plan.json validation failed: ${error49 instanceof Error ? error49.message : String(error49)}. Attempting rebuild from ledger. If rebuild fails, check SWARM_PLAN.md for a checkpoint.`);
|
|
14806
|
+
warn(`[loadPlan] plan.json validation failed: ${error49 instanceof Error ? error49.message : String(error49)}. Attempting rebuild from ledger. If rebuild fails, check .swarm/SWARM_PLAN.md for a checkpoint.`);
|
|
14807
14807
|
let rawPlanId = null;
|
|
14808
14808
|
try {
|
|
14809
14809
|
const rawParsed = JSON.parse(planJsonContent);
|
|
@@ -18577,11 +18577,11 @@ var init_evidence_summary_service = __esm(() => {
|
|
|
18577
18577
|
// src/cli/index.ts
|
|
18578
18578
|
import * as fs21 from "fs";
|
|
18579
18579
|
import * as os7 from "os";
|
|
18580
|
-
import * as
|
|
18580
|
+
import * as path34 from "path";
|
|
18581
18581
|
// package.json
|
|
18582
18582
|
var package_default = {
|
|
18583
18583
|
name: "opencode-swarm",
|
|
18584
|
-
version: "7.0.
|
|
18584
|
+
version: "7.0.2",
|
|
18585
18585
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
18586
18586
|
main: "dist/index.js",
|
|
18587
18587
|
types: "dist/index.d.ts",
|
|
@@ -18799,8 +18799,9 @@ var ALL_SUBAGENT_NAMES = [
|
|
|
18799
18799
|
"critic_hallucination_verifier",
|
|
18800
18800
|
"curator_init",
|
|
18801
18801
|
"curator_phase",
|
|
18802
|
-
"
|
|
18803
|
-
"
|
|
18802
|
+
"council_generalist",
|
|
18803
|
+
"council_skeptic",
|
|
18804
|
+
"council_domain_expert",
|
|
18804
18805
|
...QA_AGENTS,
|
|
18805
18806
|
...PIPELINE_AGENTS
|
|
18806
18807
|
];
|
|
@@ -18873,7 +18874,8 @@ var AGENT_TOOL_MAP = {
|
|
|
18873
18874
|
"repo_map",
|
|
18874
18875
|
"get_qa_gate_profile",
|
|
18875
18876
|
"set_qa_gates",
|
|
18876
|
-
"convene_general_council"
|
|
18877
|
+
"convene_general_council",
|
|
18878
|
+
"web_search"
|
|
18877
18879
|
],
|
|
18878
18880
|
explorer: [
|
|
18879
18881
|
"complexity_hotspots",
|
|
@@ -19024,8 +19026,9 @@ var AGENT_TOOL_MAP = {
|
|
|
19024
19026
|
],
|
|
19025
19027
|
curator_init: ["knowledge_recall"],
|
|
19026
19028
|
curator_phase: ["knowledge_recall"],
|
|
19027
|
-
|
|
19028
|
-
|
|
19029
|
+
council_generalist: [],
|
|
19030
|
+
council_skeptic: [],
|
|
19031
|
+
council_domain_expert: []
|
|
19029
19032
|
};
|
|
19030
19033
|
for (const [agentName, tools] of Object.entries(AGENT_TOOL_MAP)) {
|
|
19031
19034
|
const invalidTools = tools.filter((tool) => !TOOL_NAME_SET.has(tool));
|
|
@@ -20484,6 +20487,115 @@ var DeltaSpecSchema = exports_external.union([
|
|
|
20484
20487
|
// src/services/warning-buffer.ts
|
|
20485
20488
|
var deferredWarnings = [];
|
|
20486
20489
|
|
|
20490
|
+
// src/agents/council-prompts.ts
|
|
20491
|
+
var ROUND_PROTOCOL = `================================================================
|
|
20492
|
+
ROUND PROTOCOL
|
|
20493
|
+
================================================================
|
|
20494
|
+
|
|
20495
|
+
ROUND 1 \u2014 Independent Analysis and Answer
|
|
20496
|
+
- Use the RESEARCH CONTEXT block provided by the architect in your dispatch message as your external evidence source. The architect has already gathered the relevant web search results.
|
|
20497
|
+
- Cite EVERY factual claim that depends on external evidence with a source from the RESEARCH CONTEXT (use the title and URL exactly as given).
|
|
20498
|
+
- State your confidence (0.0\u20131.0) explicitly. Be honest \u2014 overconfident answers hurt the council.
|
|
20499
|
+
- Enumerate areas of uncertainty so the architect knows where you're guessing vs. where you're sure.
|
|
20500
|
+
- Do NOT coordinate with other members. You will not see their responses until Round 2.
|
|
20501
|
+
- Do NOT pad. Be concise. Substance over volume.
|
|
20502
|
+
|
|
20503
|
+
ROUND 2 \u2014 Targeted Deliberation (ONLY when this round is invoked for you)
|
|
20504
|
+
- The architect will pass you the disagreement topic and the opposing position(s) in the dispatch message.
|
|
20505
|
+
- Re-read the RESEARCH CONTEXT for any evidence relevant to the disagreement.
|
|
20506
|
+
- Declare your stance explicitly using one of these keywords as the FIRST word of a paragraph:
|
|
20507
|
+
MAINTAIN \u2014 your Round 1 position holds; cite the evidence supporting it
|
|
20508
|
+
CONCEDE \u2014 the opposing position is correct; state specifically what you got wrong
|
|
20509
|
+
NUANCE \u2014 both positions are partially right; state the boundary condition that distinguishes them
|
|
20510
|
+
- Never CONCEDE without evidence. Sycophantic capitulation degrades the council below an individual member's baseline (NSED arXiv:2601.16863).
|
|
20511
|
+
- Never MAINTAIN without engaging the opposing argument on its merits.`;
|
|
20512
|
+
var RESPONSE_FORMAT = `================================================================
|
|
20513
|
+
RESPONSE FORMAT (always \u2014 both rounds)
|
|
20514
|
+
================================================================
|
|
20515
|
+
|
|
20516
|
+
Reply with a single fenced JSON block. No prose outside the block.
|
|
20517
|
+
|
|
20518
|
+
\`\`\`json
|
|
20519
|
+
{
|
|
20520
|
+
"memberId": "<your hardcoded memberId>",
|
|
20521
|
+
"role": "<your hardcoded role>",
|
|
20522
|
+
"round": 1,
|
|
20523
|
+
"response": "Your full answer (Round 1) or stance + reasoning (Round 2). Markdown OK inside the string.",
|
|
20524
|
+
"searchQueries": [],
|
|
20525
|
+
"sources": [
|
|
20526
|
+
{ "title": "...", "url": "...", "snippet": "...", "query": "..." }
|
|
20527
|
+
],
|
|
20528
|
+
"confidence": 0.85,
|
|
20529
|
+
"areasOfUncertainty": [
|
|
20530
|
+
"What I'm not sure about, in plain language."
|
|
20531
|
+
],
|
|
20532
|
+
"disagreementTopics": []
|
|
20533
|
+
}
|
|
20534
|
+
\`\`\`
|
|
20535
|
+
|
|
20536
|
+
Notes:
|
|
20537
|
+
- \`searchQueries\` is optional \u2014 list queries you would have run if you had web access (the architect uses these for audit), or omit / leave empty if none.
|
|
20538
|
+
- \`sources\` MUST come from the RESEARCH CONTEXT only. Copy title/url/snippet/query verbatim. Never invent sources.
|
|
20539
|
+
- For Round 1: leave \`disagreementTopics\` as []. For Round 2: list the specific disagreement topics this response addresses.`;
|
|
20540
|
+
var HARD_RULES = `================================================================
|
|
20541
|
+
HARD RULES
|
|
20542
|
+
================================================================
|
|
20543
|
+
- You have no tools. Reason from the provided RESEARCH CONTEXT and your training knowledge.
|
|
20544
|
+
- Never invent sources. If the RESEARCH CONTEXT does not cover a needed claim, say so in \`areasOfUncertainty\`.
|
|
20545
|
+
- Never echo other members' responses verbatim. Paraphrase or quote with attribution.
|
|
20546
|
+
- Stay within your role and persona. The architect chose you for a specific perspective.`;
|
|
20547
|
+
var GENERALIST_COUNCIL_PROMPT = `You are the GENERALIST voice on a multi-model General Council.
|
|
20548
|
+
|
|
20549
|
+
You are the GENERALIST voice on this council. Your perspective is broad and synthesizing:
|
|
20550
|
+
- You reason from first principles and across disciplines.
|
|
20551
|
+
- You weigh competing considerations without domain bias.
|
|
20552
|
+
- You surface tensions between different valid approaches.
|
|
20553
|
+
- You are the integrating voice \u2014 you see what the specialists might miss by being too deep in their domain.
|
|
20554
|
+
Member ID: "council_generalist" | Role: "generalist"
|
|
20555
|
+
|
|
20556
|
+
You are participating in a structured deliberation. Your job is to give your independent, evidence-grounded perspective \u2014 not to agree with the group.
|
|
20557
|
+
|
|
20558
|
+
${ROUND_PROTOCOL}
|
|
20559
|
+
|
|
20560
|
+
${RESPONSE_FORMAT}
|
|
20561
|
+
|
|
20562
|
+
${HARD_RULES}
|
|
20563
|
+
`;
|
|
20564
|
+
var SKEPTIC_COUNCIL_PROMPT = `You are the SKEPTIC voice on a multi-model General Council.
|
|
20565
|
+
|
|
20566
|
+
You are the SKEPTIC voice on this council. Your job is rigorous stress-testing:
|
|
20567
|
+
- You challenge assumptions the other members take for granted.
|
|
20568
|
+
- You look for weak points, edge cases, and unstated dependencies.
|
|
20569
|
+
- You are NOT contrarian for its own sake \u2014 your pushback must be evidence-grounded.
|
|
20570
|
+
- You make the council's final answer more robust by finding what could go wrong before the user does.
|
|
20571
|
+
Member ID: "council_skeptic" | Role: "skeptic"
|
|
20572
|
+
|
|
20573
|
+
You are participating in a structured deliberation. Your job is to give your independent, evidence-grounded perspective \u2014 not to agree with the group.
|
|
20574
|
+
|
|
20575
|
+
${ROUND_PROTOCOL}
|
|
20576
|
+
|
|
20577
|
+
${RESPONSE_FORMAT}
|
|
20578
|
+
|
|
20579
|
+
${HARD_RULES}
|
|
20580
|
+
`;
|
|
20581
|
+
var DOMAIN_EXPERT_COUNCIL_PROMPT = `You are the DOMAIN EXPERT voice on a multi-model General Council.
|
|
20582
|
+
|
|
20583
|
+
You are the DOMAIN EXPERT voice on this council. Your perspective is technically precise:
|
|
20584
|
+
- You go deep where others stay broad.
|
|
20585
|
+
- You cite specific mechanisms, constraints, and implementation-level detail.
|
|
20586
|
+
- You surface edge cases and gotchas that only emerge at depth.
|
|
20587
|
+
- Your answers are concrete \u2014 no hand-waving, no vague recommendations.
|
|
20588
|
+
Member ID: "council_domain_expert" | Role: "domain_expert"
|
|
20589
|
+
|
|
20590
|
+
You are participating in a structured deliberation. Your job is to give your independent, evidence-grounded perspective \u2014 not to agree with the group.
|
|
20591
|
+
|
|
20592
|
+
${ROUND_PROTOCOL}
|
|
20593
|
+
|
|
20594
|
+
${RESPONSE_FORMAT}
|
|
20595
|
+
|
|
20596
|
+
${HARD_RULES}
|
|
20597
|
+
`;
|
|
20598
|
+
|
|
20487
20599
|
// src/agents/index.ts
|
|
20488
20600
|
var warnedAgents = new Set;
|
|
20489
20601
|
|
|
@@ -35341,7 +35453,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35341
35453
|
try {
|
|
35342
35454
|
const evidenceDir = path12.join(swarmDir, "evidence");
|
|
35343
35455
|
const evidenceEntries = await fs7.readdir(evidenceDir);
|
|
35344
|
-
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-"));
|
|
35456
|
+
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
35345
35457
|
for (const retroDir of retroDirs) {
|
|
35346
35458
|
const evidencePath = path12.join(evidenceDir, retroDir, "evidence.json");
|
|
35347
35459
|
try {
|
|
@@ -35492,22 +35604,20 @@ async function handleCloseCommand(directory, args) {
|
|
|
35492
35604
|
}
|
|
35493
35605
|
} catch {}
|
|
35494
35606
|
let swarmPlanFilesRemoved = 0;
|
|
35495
|
-
const
|
|
35496
|
-
|
|
35497
|
-
|
|
35498
|
-
|
|
35499
|
-
|
|
35500
|
-
|
|
35501
|
-
|
|
35502
|
-
|
|
35503
|
-
|
|
35504
|
-
|
|
35505
|
-
|
|
35506
|
-
|
|
35507
|
-
|
|
35508
|
-
|
|
35509
|
-
if (err?.code !== "ENOENT") {
|
|
35510
|
-
warnings.push(`Failed to remove SWARM_PLAN.md: ${err instanceof Error ? err.message : String(err)}`);
|
|
35607
|
+
const candidates = [
|
|
35608
|
+
path12.join(directory, ".swarm", "SWARM_PLAN.json"),
|
|
35609
|
+
path12.join(directory, ".swarm", "SWARM_PLAN.md"),
|
|
35610
|
+
path12.join(directory, "SWARM_PLAN.json"),
|
|
35611
|
+
path12.join(directory, "SWARM_PLAN.md")
|
|
35612
|
+
];
|
|
35613
|
+
for (const candidate of candidates) {
|
|
35614
|
+
try {
|
|
35615
|
+
await fs7.unlink(candidate);
|
|
35616
|
+
swarmPlanFilesRemoved++;
|
|
35617
|
+
} catch (err) {
|
|
35618
|
+
if (err?.code !== "ENOENT") {
|
|
35619
|
+
warnings.push(`Failed to remove ${path12.basename(candidate)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
35620
|
+
}
|
|
35511
35621
|
}
|
|
35512
35622
|
}
|
|
35513
35623
|
clearAllScopes(directory);
|
|
@@ -35582,9 +35692,7 @@ async function handleCloseCommand(directory, args) {
|
|
|
35582
35692
|
"- Reset context.md for next session",
|
|
35583
35693
|
"- Cleared agent sessions and delegation chains",
|
|
35584
35694
|
...configBackupsRemoved > 0 ? [`- Removed ${configBackupsRemoved} stale config backup file(s)`] : [],
|
|
35585
|
-
...swarmPlanFilesRemoved > 0 ? [
|
|
35586
|
-
`- Removed ${swarmPlanFilesRemoved} root-level SWARM_PLAN checkpoint artifact(s)`
|
|
35587
|
-
] : [],
|
|
35695
|
+
...swarmPlanFilesRemoved > 0 ? [`- Removed ${swarmPlanFilesRemoved} SWARM_PLAN checkpoint artifact(s)`] : [],
|
|
35588
35696
|
...planExists && !planAlreadyDone ? ["- Set non-completed phases/tasks to closed status"] : [],
|
|
35589
35697
|
...curationSucceeded && allLessons.length > 0 ? [`- Committed ${allLessons.length} lesson(s) to knowledge store`] : [],
|
|
35590
35698
|
"",
|
|
@@ -36471,11 +36579,39 @@ function getPluginConfigDir() {
|
|
|
36471
36579
|
function getPluginCachePaths() {
|
|
36472
36580
|
const cacheBase = process.env.XDG_CACHE_HOME || path17.join(os5.homedir(), ".cache");
|
|
36473
36581
|
const configDir = getPluginConfigDir();
|
|
36474
|
-
|
|
36582
|
+
const paths = [
|
|
36583
|
+
path17.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
36475
36584
|
path17.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
36476
|
-
path17.join(configDir, "node_modules", "opencode-swarm")
|
|
36477
|
-
path17.join(cacheBase, "opencode", "node_modules", "opencode-swarm")
|
|
36585
|
+
path17.join(configDir, "node_modules", "opencode-swarm")
|
|
36478
36586
|
];
|
|
36587
|
+
if (process.platform === "darwin") {
|
|
36588
|
+
const libCaches = path17.join(os5.homedir(), "Library", "Caches");
|
|
36589
|
+
paths.push(path17.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path17.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
36590
|
+
}
|
|
36591
|
+
if (process.platform === "win32") {
|
|
36592
|
+
const localAppData = process.env.LOCALAPPDATA || path17.join(os5.homedir(), "AppData", "Local");
|
|
36593
|
+
const appData = process.env.APPDATA || path17.join(os5.homedir(), "AppData", "Roaming");
|
|
36594
|
+
paths.push(path17.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path17.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path17.join(appData, "opencode", "node_modules", "opencode-swarm"));
|
|
36595
|
+
}
|
|
36596
|
+
return paths;
|
|
36597
|
+
}
|
|
36598
|
+
function getPluginLockFilePaths() {
|
|
36599
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path17.join(os5.homedir(), ".cache");
|
|
36600
|
+
const configDir = getPluginConfigDir();
|
|
36601
|
+
const paths = [
|
|
36602
|
+
path17.join(cacheBase, "opencode", "bun.lock"),
|
|
36603
|
+
path17.join(cacheBase, "opencode", "bun.lockb"),
|
|
36604
|
+
path17.join(configDir, "package-lock.json")
|
|
36605
|
+
];
|
|
36606
|
+
if (process.platform === "darwin") {
|
|
36607
|
+
const libCaches = path17.join(os5.homedir(), "Library", "Caches");
|
|
36608
|
+
paths.push(path17.join(libCaches, "opencode", "bun.lock"), path17.join(libCaches, "opencode", "bun.lockb"));
|
|
36609
|
+
}
|
|
36610
|
+
if (process.platform === "win32") {
|
|
36611
|
+
const localAppData = process.env.LOCALAPPDATA || path17.join(os5.homedir(), "AppData", "Local");
|
|
36612
|
+
paths.push(path17.join(localAppData, "opencode", "bun.lock"), path17.join(localAppData, "opencode", "bun.lockb"));
|
|
36613
|
+
}
|
|
36614
|
+
return paths;
|
|
36479
36615
|
}
|
|
36480
36616
|
|
|
36481
36617
|
// src/services/diagnose-service.ts
|
|
@@ -40532,6 +40668,13 @@ function parseGitRemoteUrl2(remoteUrl) {
|
|
|
40532
40668
|
repo: sshMatch[2].replace(/\.git$/, "")
|
|
40533
40669
|
};
|
|
40534
40670
|
}
|
|
40671
|
+
const pathMatch = remoteUrl.match(/\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
|
|
40672
|
+
if (pathMatch) {
|
|
40673
|
+
return {
|
|
40674
|
+
owner: pathMatch[1],
|
|
40675
|
+
repo: pathMatch[2].replace(/\.git$/, "")
|
|
40676
|
+
};
|
|
40677
|
+
}
|
|
40535
40678
|
return null;
|
|
40536
40679
|
}
|
|
40537
40680
|
function handlePrReviewCommand(_directory, args) {
|
|
@@ -44454,6 +44597,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
44454
44597
|
|
|
44455
44598
|
// src/commands/reset.ts
|
|
44456
44599
|
import * as fs18 from "fs";
|
|
44600
|
+
import * as path30 from "path";
|
|
44457
44601
|
|
|
44458
44602
|
// src/background/manager.ts
|
|
44459
44603
|
init_utils();
|
|
@@ -45141,7 +45285,7 @@ async function handleResetCommand(directory, args) {
|
|
|
45141
45285
|
return [
|
|
45142
45286
|
"## Swarm Reset",
|
|
45143
45287
|
"",
|
|
45144
|
-
"\u26A0\uFE0F This will delete
|
|
45288
|
+
"\u26A0\uFE0F This will delete all swarm state from .swarm/ (plan, context, checkpoints, SWARM_PLAN artifacts)",
|
|
45145
45289
|
"",
|
|
45146
45290
|
"**Tip**: Run `/swarm export` first to backup your state.",
|
|
45147
45291
|
"",
|
|
@@ -45149,7 +45293,15 @@ async function handleResetCommand(directory, args) {
|
|
|
45149
45293
|
].join(`
|
|
45150
45294
|
`);
|
|
45151
45295
|
}
|
|
45152
|
-
const filesToReset = [
|
|
45296
|
+
const filesToReset = [
|
|
45297
|
+
"plan.md",
|
|
45298
|
+
"plan.json",
|
|
45299
|
+
"context.md",
|
|
45300
|
+
"SWARM_PLAN.md",
|
|
45301
|
+
"SWARM_PLAN.json",
|
|
45302
|
+
"checkpoints.json",
|
|
45303
|
+
"events.jsonl"
|
|
45304
|
+
];
|
|
45153
45305
|
const results = [];
|
|
45154
45306
|
for (const filename of filesToReset) {
|
|
45155
45307
|
try {
|
|
@@ -45164,6 +45316,15 @@ async function handleResetCommand(directory, args) {
|
|
|
45164
45316
|
results.push(`- \u274C Failed to delete ${filename}`);
|
|
45165
45317
|
}
|
|
45166
45318
|
}
|
|
45319
|
+
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
45320
|
+
try {
|
|
45321
|
+
const rootPath = path30.join(directory, filename);
|
|
45322
|
+
if (fs18.existsSync(rootPath)) {
|
|
45323
|
+
fs18.unlinkSync(rootPath);
|
|
45324
|
+
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
45325
|
+
}
|
|
45326
|
+
} catch {}
|
|
45327
|
+
}
|
|
45167
45328
|
try {
|
|
45168
45329
|
resetAutomationManager();
|
|
45169
45330
|
results.push("- \u2705 Stopped background automation (in-memory queues cleared)");
|
|
@@ -45194,7 +45355,7 @@ async function handleResetCommand(directory, args) {
|
|
|
45194
45355
|
// src/commands/reset-session.ts
|
|
45195
45356
|
init_utils2();
|
|
45196
45357
|
import * as fs19 from "fs";
|
|
45197
|
-
import * as
|
|
45358
|
+
import * as path31 from "path";
|
|
45198
45359
|
async function handleResetSessionCommand(directory, _args) {
|
|
45199
45360
|
const results = [];
|
|
45200
45361
|
try {
|
|
@@ -45209,13 +45370,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
45209
45370
|
results.push("\u274C Failed to delete state.json");
|
|
45210
45371
|
}
|
|
45211
45372
|
try {
|
|
45212
|
-
const sessionDir =
|
|
45373
|
+
const sessionDir = path31.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
45213
45374
|
if (fs19.existsSync(sessionDir)) {
|
|
45214
45375
|
const files = fs19.readdirSync(sessionDir);
|
|
45215
45376
|
const otherFiles = files.filter((f) => f !== "state.json");
|
|
45216
45377
|
let deletedCount = 0;
|
|
45217
45378
|
for (const file3 of otherFiles) {
|
|
45218
|
-
const filePath =
|
|
45379
|
+
const filePath = path31.join(sessionDir, file3);
|
|
45219
45380
|
if (fs19.lstatSync(filePath).isFile()) {
|
|
45220
45381
|
fs19.unlinkSync(filePath);
|
|
45221
45382
|
deletedCount++;
|
|
@@ -45245,7 +45406,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
45245
45406
|
// src/summaries/manager.ts
|
|
45246
45407
|
init_utils2();
|
|
45247
45408
|
init_utils();
|
|
45248
|
-
import * as
|
|
45409
|
+
import * as path32 from "path";
|
|
45249
45410
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
45250
45411
|
function sanitizeSummaryId(id) {
|
|
45251
45412
|
if (!id || id.length === 0) {
|
|
@@ -45269,7 +45430,7 @@ function sanitizeSummaryId(id) {
|
|
|
45269
45430
|
}
|
|
45270
45431
|
async function loadFullOutput(directory, id) {
|
|
45271
45432
|
const sanitizedId = sanitizeSummaryId(id);
|
|
45272
|
-
const relativePath =
|
|
45433
|
+
const relativePath = path32.join("summaries", `${sanitizedId}.json`);
|
|
45273
45434
|
validateSwarmPath(directory, relativePath);
|
|
45274
45435
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
45275
45436
|
if (content === null) {
|
|
@@ -45325,7 +45486,7 @@ init_plan_schema();
|
|
|
45325
45486
|
init_utils2();
|
|
45326
45487
|
init_ledger();
|
|
45327
45488
|
import * as fs20 from "fs";
|
|
45328
|
-
import * as
|
|
45489
|
+
import * as path33 from "path";
|
|
45329
45490
|
async function handleRollbackCommand(directory, args) {
|
|
45330
45491
|
const phaseArg = args[0];
|
|
45331
45492
|
if (!phaseArg) {
|
|
@@ -45390,8 +45551,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
45390
45551
|
if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
|
|
45391
45552
|
continue;
|
|
45392
45553
|
}
|
|
45393
|
-
const src =
|
|
45394
|
-
const dest =
|
|
45554
|
+
const src = path33.join(checkpointDir, file3);
|
|
45555
|
+
const dest = path33.join(swarmDir, file3);
|
|
45395
45556
|
try {
|
|
45396
45557
|
fs20.cpSync(src, dest, { recursive: true, force: true });
|
|
45397
45558
|
successes.push(file3);
|
|
@@ -45410,12 +45571,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
45410
45571
|
].join(`
|
|
45411
45572
|
`);
|
|
45412
45573
|
}
|
|
45413
|
-
const existingLedgerPath =
|
|
45574
|
+
const existingLedgerPath = path33.join(swarmDir, "plan-ledger.jsonl");
|
|
45414
45575
|
if (fs20.existsSync(existingLedgerPath)) {
|
|
45415
45576
|
fs20.unlinkSync(existingLedgerPath);
|
|
45416
45577
|
}
|
|
45417
45578
|
try {
|
|
45418
|
-
const planJsonPath =
|
|
45579
|
+
const planJsonPath = path33.join(swarmDir, "plan.json");
|
|
45419
45580
|
if (fs20.existsSync(planJsonPath)) {
|
|
45420
45581
|
const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
|
|
45421
45582
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -45488,9 +45649,9 @@ async function handleSimulateCommand(directory, args) {
|
|
|
45488
45649
|
const report = reportLines.filter(Boolean).join(`
|
|
45489
45650
|
`);
|
|
45490
45651
|
const fs21 = await import("fs/promises");
|
|
45491
|
-
const
|
|
45492
|
-
const reportPath =
|
|
45493
|
-
await fs21.mkdir(
|
|
45652
|
+
const path34 = await import("path");
|
|
45653
|
+
const reportPath = path34.join(directory, ".swarm", "simulate-report.md");
|
|
45654
|
+
await fs21.mkdir(path34.dirname(reportPath), { recursive: true });
|
|
45494
45655
|
await fs21.writeFile(reportPath, report, "utf-8");
|
|
45495
45656
|
return `${darkMatterPairs.length} hidden coupling pairs detected`;
|
|
45496
45657
|
}
|
|
@@ -45904,9 +46065,9 @@ var COMMAND_REGISTRY = {
|
|
|
45904
46065
|
},
|
|
45905
46066
|
council: {
|
|
45906
46067
|
handler: (ctx) => handleCouncilCommand(ctx.directory, ctx.args),
|
|
45907
|
-
description: "Enter architect MODE: COUNCIL \u2014 multi-model deliberation [question] [--
|
|
45908
|
-
args: "<question> [--
|
|
45909
|
-
details: "Triggers the architect to convene a
|
|
46068
|
+
description: "Enter architect MODE: COUNCIL \u2014 multi-model deliberation [question] [--spec-review]",
|
|
46069
|
+
args: "<question> [--spec-review]",
|
|
46070
|
+
details: "Triggers the architect to convene a three-agent General Council: " + "Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). " + "The architect first runs 1\u20133 targeted web searches and passes a compiled RESEARCH CONTEXT " + "to all three agents before dispatching them in parallel. " + "Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, " + "Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). " + "The architect synthesizes the final answer directly from convene_general_council output. " + "--spec-review switches to single-pass advisory mode for spec review. " + "Requires council.general.enabled: true and a search API key in opencode-swarm.json."
|
|
45910
46071
|
},
|
|
45911
46072
|
"pr-review": {
|
|
45912
46073
|
handler: async (ctx) => handlePrReviewCommand(ctx.directory, ctx.args),
|
|
@@ -46038,34 +46199,55 @@ function resolveCommand(tokens) {
|
|
|
46038
46199
|
// src/cli/index.ts
|
|
46039
46200
|
var { version: version4 } = package_default;
|
|
46040
46201
|
var CONFIG_DIR = getPluginConfigDir();
|
|
46041
|
-
var OPENCODE_CONFIG_PATH =
|
|
46042
|
-
var PLUGIN_CONFIG_PATH =
|
|
46043
|
-
var PROMPTS_DIR =
|
|
46202
|
+
var OPENCODE_CONFIG_PATH = path34.join(CONFIG_DIR, "opencode.json");
|
|
46203
|
+
var PLUGIN_CONFIG_PATH = path34.join(CONFIG_DIR, "opencode-swarm.json");
|
|
46204
|
+
var PROMPTS_DIR = path34.join(CONFIG_DIR, "opencode-swarm");
|
|
46044
46205
|
var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
|
|
46206
|
+
var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
|
|
46045
46207
|
function isSafeCachePath(p) {
|
|
46046
|
-
const resolved =
|
|
46047
|
-
const home =
|
|
46208
|
+
const resolved = path34.resolve(p);
|
|
46209
|
+
const home = path34.resolve(os7.homedir());
|
|
46048
46210
|
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
46049
46211
|
return false;
|
|
46050
46212
|
}
|
|
46051
|
-
const segments = resolved.split(
|
|
46213
|
+
const segments = resolved.split(path34.sep).filter((s) => s.length > 0);
|
|
46052
46214
|
if (segments.length < 4) {
|
|
46053
46215
|
return false;
|
|
46054
46216
|
}
|
|
46055
|
-
const leaf =
|
|
46217
|
+
const leaf = path34.basename(resolved);
|
|
46056
46218
|
if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
|
|
46057
46219
|
return false;
|
|
46058
46220
|
}
|
|
46059
|
-
const parent =
|
|
46221
|
+
const parent = path34.basename(path34.dirname(resolved));
|
|
46060
46222
|
if (parent !== "packages" && parent !== "node_modules") {
|
|
46061
46223
|
return false;
|
|
46062
46224
|
}
|
|
46063
|
-
const grandparent =
|
|
46225
|
+
const grandparent = path34.basename(path34.dirname(path34.dirname(resolved)));
|
|
46064
46226
|
if (grandparent !== "opencode") {
|
|
46065
46227
|
return false;
|
|
46066
46228
|
}
|
|
46067
46229
|
return true;
|
|
46068
46230
|
}
|
|
46231
|
+
function isSafeLockFilePath(p) {
|
|
46232
|
+
const resolved = path34.resolve(p);
|
|
46233
|
+
const home = path34.resolve(os7.homedir());
|
|
46234
|
+
if (resolved === "/" || resolved === home || resolved.length <= home.length) {
|
|
46235
|
+
return false;
|
|
46236
|
+
}
|
|
46237
|
+
const segments = resolved.split(path34.sep).filter((s) => s.length > 0);
|
|
46238
|
+
if (segments.length < 4) {
|
|
46239
|
+
return false;
|
|
46240
|
+
}
|
|
46241
|
+
const leaf = path34.basename(resolved);
|
|
46242
|
+
if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
|
|
46243
|
+
return false;
|
|
46244
|
+
}
|
|
46245
|
+
const parent = path34.basename(path34.dirname(resolved));
|
|
46246
|
+
if (parent !== "opencode") {
|
|
46247
|
+
return false;
|
|
46248
|
+
}
|
|
46249
|
+
return true;
|
|
46250
|
+
}
|
|
46069
46251
|
function ensureDir(dir) {
|
|
46070
46252
|
if (!fs21.existsSync(dir)) {
|
|
46071
46253
|
fs21.mkdirSync(dir, { recursive: true });
|
|
@@ -46086,8 +46268,8 @@ function saveJson(filepath, data) {
|
|
|
46086
46268
|
}
|
|
46087
46269
|
function writeProjectConfigIfMissing(cwd) {
|
|
46088
46270
|
try {
|
|
46089
|
-
const opencodeDir =
|
|
46090
|
-
const projectConfigPath =
|
|
46271
|
+
const opencodeDir = path34.join(cwd, ".opencode");
|
|
46272
|
+
const projectConfigPath = path34.join(opencodeDir, "opencode-swarm.json");
|
|
46091
46273
|
if (fs21.existsSync(projectConfigPath)) {
|
|
46092
46274
|
return;
|
|
46093
46275
|
}
|
|
@@ -46105,7 +46287,7 @@ async function install() {
|
|
|
46105
46287
|
`);
|
|
46106
46288
|
ensureDir(CONFIG_DIR);
|
|
46107
46289
|
ensureDir(PROMPTS_DIR);
|
|
46108
|
-
const LEGACY_CONFIG_PATH =
|
|
46290
|
+
const LEGACY_CONFIG_PATH = path34.join(CONFIG_DIR, "config.json");
|
|
46109
46291
|
let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
|
|
46110
46292
|
if (!opencodeConfig) {
|
|
46111
46293
|
const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
|
|
@@ -46144,6 +46326,14 @@ async function install() {
|
|
|
46144
46326
|
console.warn(`\u26A0 Could not clear opencode plugin cache \u2014 you may need to delete it manually:
|
|
46145
46327
|
${failed}`);
|
|
46146
46328
|
}
|
|
46329
|
+
const lockEvicted = evictLockFiles();
|
|
46330
|
+
if (lockEvicted.cleared.length > 0) {
|
|
46331
|
+
console.log(`\u2713 Cleared opencode lock file(s) (next start will fetch latest): ${lockEvicted.cleared.join(", ")}`);
|
|
46332
|
+
}
|
|
46333
|
+
for (const failed of lockEvicted.failed) {
|
|
46334
|
+
console.warn(`\u26A0 Could not clear opencode lock file \u2014 you may need to delete it manually:
|
|
46335
|
+
${failed}`);
|
|
46336
|
+
}
|
|
46147
46337
|
if (!fs21.existsSync(PLUGIN_CONFIG_PATH)) {
|
|
46148
46338
|
const defaultConfig = {
|
|
46149
46339
|
agents: {
|
|
@@ -46202,14 +46392,6 @@ async function install() {
|
|
|
46202
46392
|
curator_phase: {
|
|
46203
46393
|
model: "opencode/gpt-5-nano",
|
|
46204
46394
|
fallback_models: ["opencode/big-pickle"]
|
|
46205
|
-
},
|
|
46206
|
-
council_member: {
|
|
46207
|
-
model: "opencode/gpt-5-nano",
|
|
46208
|
-
fallback_models: ["opencode/big-pickle"]
|
|
46209
|
-
},
|
|
46210
|
-
council_moderator: {
|
|
46211
|
-
model: "opencode/gpt-5-nano",
|
|
46212
|
-
fallback_models: ["opencode/big-pickle"]
|
|
46213
46395
|
}
|
|
46214
46396
|
},
|
|
46215
46397
|
max_iterations: 5
|
|
@@ -46246,6 +46428,7 @@ async function update() {
|
|
|
46246
46428
|
console.log(`\uD83D\uDC1D Refreshing OpenCode Swarm plugin cache...
|
|
46247
46429
|
`);
|
|
46248
46430
|
const result = evictPluginCaches();
|
|
46431
|
+
const lockResult = evictLockFiles();
|
|
46249
46432
|
if (result.cleared.length > 0) {
|
|
46250
46433
|
for (const cleared of result.cleared) {
|
|
46251
46434
|
console.log(`\u2713 Cleared: ${cleared}`);
|
|
@@ -46253,17 +46436,33 @@ async function update() {
|
|
|
46253
46436
|
console.log(`
|
|
46254
46437
|
Restart OpenCode to fetch the latest version from npm.`);
|
|
46255
46438
|
}
|
|
46256
|
-
if (
|
|
46439
|
+
if (lockResult.cleared.length > 0) {
|
|
46440
|
+
for (const cleared of lockResult.cleared) {
|
|
46441
|
+
console.log(`\u2713 Cleared lock file: ${cleared}`);
|
|
46442
|
+
}
|
|
46443
|
+
}
|
|
46444
|
+
if (lockResult.failed.length > 0) {
|
|
46445
|
+
for (const failed of lockResult.failed) {
|
|
46446
|
+
console.error(`\u2717 Could not clear lock file: ${failed}`);
|
|
46447
|
+
}
|
|
46448
|
+
}
|
|
46449
|
+
if (result.cleared.length === 0 && result.failed.length === 0 && lockResult.cleared.length === 0 && lockResult.failed.length === 0) {
|
|
46257
46450
|
console.log("No cached plugin found. Restart OpenCode to fetch the latest version from npm.");
|
|
46258
46451
|
console.log("Checked locations:");
|
|
46259
46452
|
for (const p of OPENCODE_PLUGIN_CACHE_PATHS) {
|
|
46260
46453
|
console.log(` - ${p}`);
|
|
46261
46454
|
}
|
|
46455
|
+
console.log("Lock files checked:");
|
|
46456
|
+
for (const p of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
|
|
46457
|
+
console.log(` - ${p}`);
|
|
46458
|
+
}
|
|
46262
46459
|
}
|
|
46263
46460
|
if (result.failed.length > 0) {
|
|
46264
46461
|
for (const failed of result.failed) {
|
|
46265
46462
|
console.error(`\u2717 Could not clear: ${failed}`);
|
|
46266
46463
|
}
|
|
46464
|
+
}
|
|
46465
|
+
if (result.failed.length > 0 || lockResult.failed.length > 0) {
|
|
46267
46466
|
return 1;
|
|
46268
46467
|
}
|
|
46269
46468
|
return 0;
|
|
@@ -46287,6 +46486,30 @@ function evictPluginCaches() {
|
|
|
46287
46486
|
}
|
|
46288
46487
|
return { cleared, failed };
|
|
46289
46488
|
}
|
|
46489
|
+
function evictLockFiles() {
|
|
46490
|
+
const cleared = [];
|
|
46491
|
+
const failed = [];
|
|
46492
|
+
for (const lockPath of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
|
|
46493
|
+
if (!fs21.existsSync(lockPath))
|
|
46494
|
+
continue;
|
|
46495
|
+
if (!isSafeLockFilePath(lockPath)) {
|
|
46496
|
+
failed.push(`${lockPath} (refused: failed safety check)`);
|
|
46497
|
+
continue;
|
|
46498
|
+
}
|
|
46499
|
+
try {
|
|
46500
|
+
fs21.unlinkSync(lockPath);
|
|
46501
|
+
cleared.push(lockPath);
|
|
46502
|
+
} catch (err) {
|
|
46503
|
+
const code = err?.code;
|
|
46504
|
+
if (code === "EISDIR") {
|
|
46505
|
+
failed.push(`${lockPath} (path is a directory, not a file)`);
|
|
46506
|
+
} else {
|
|
46507
|
+
failed.push(`${lockPath} (${err instanceof Error ? err.message : String(err)})`);
|
|
46508
|
+
}
|
|
46509
|
+
}
|
|
46510
|
+
}
|
|
46511
|
+
return { cleared, failed };
|
|
46512
|
+
}
|
|
46290
46513
|
async function uninstall() {
|
|
46291
46514
|
try {
|
|
46292
46515
|
console.log(`\uD83D\uDC1D Uninstalling OpenCode Swarm...
|
|
@@ -46452,5 +46675,9 @@ Valid commands: ${VALID_COMMANDS.join(", ")}`);
|
|
|
46452
46675
|
return 0;
|
|
46453
46676
|
}
|
|
46454
46677
|
export {
|
|
46455
|
-
run
|
|
46678
|
+
run,
|
|
46679
|
+
isSafeLockFilePath,
|
|
46680
|
+
isSafeCachePath,
|
|
46681
|
+
evictPluginCaches,
|
|
46682
|
+
evictLockFiles
|
|
46456
46683
|
};
|
|
@@ -162,9 +162,9 @@ export declare const COMMAND_REGISTRY: {
|
|
|
162
162
|
};
|
|
163
163
|
readonly council: {
|
|
164
164
|
readonly handler: (ctx: CommandContext) => Promise<string>;
|
|
165
|
-
readonly description: "Enter architect MODE: COUNCIL — multi-model deliberation [question] [--
|
|
166
|
-
readonly args: "<question> [--
|
|
167
|
-
readonly details:
|
|
165
|
+
readonly description: "Enter architect MODE: COUNCIL — multi-model deliberation [question] [--spec-review]";
|
|
166
|
+
readonly args: "<question> [--spec-review]";
|
|
167
|
+
readonly details: string;
|
|
168
168
|
};
|
|
169
169
|
readonly 'pr-review': {
|
|
170
170
|
readonly handler: (ctx: CommandContext) => Promise<string>;
|
package/dist/commands/reset.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Handles the /swarm reset command.
|
|
3
|
-
* Clears
|
|
3
|
+
* Clears all swarm state files from .swarm/ and project root.
|
|
4
4
|
* Stops background automation and resets in-memory queues.
|
|
5
5
|
* Requires --confirm flag as a safety gate.
|
|
6
6
|
*/
|