opencode-swarm 6.30.0 → 6.30.1

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 CHANGED
@@ -17453,7 +17453,8 @@ var swarmState = {
17453
17453
  delegationChains: new Map,
17454
17454
  pendingEvents: 0,
17455
17455
  lastBudgetPct: 0,
17456
- agentSessions: new Map
17456
+ agentSessions: new Map,
17457
+ pendingRehydrations: new Set
17457
17458
  };
17458
17459
  function getAgentSession(sessionId) {
17459
17460
  return swarmState.agentSessions.get(sessionId);
package/dist/index.js CHANGED
@@ -39377,9 +39377,10 @@ var swarmState = {
39377
39377
  delegationChains: new Map,
39378
39378
  pendingEvents: 0,
39379
39379
  lastBudgetPct: 0,
39380
- agentSessions: new Map
39380
+ agentSessions: new Map,
39381
+ pendingRehydrations: new Set
39381
39382
  };
39382
- function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, _directory) {
39383
+ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, directory) {
39383
39384
  const now = Date.now();
39384
39385
  const staleIds = [];
39385
39386
  for (const [id, session] of swarmState.agentSessions) {
@@ -39428,11 +39429,18 @@ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, _dir
39428
39429
  swarmState.agentSessions.set(sessionId, sessionState);
39429
39430
  swarmState.activeAgent.set(sessionId, agentName);
39430
39431
  applyRehydrationCache(sessionState);
39432
+ if (directory) {
39433
+ let rehydrationPromise;
39434
+ rehydrationPromise = rehydrateSessionFromDisk(directory, sessionState).catch(() => {}).finally(() => {
39435
+ swarmState.pendingRehydrations.delete(rehydrationPromise);
39436
+ });
39437
+ swarmState.pendingRehydrations.add(rehydrationPromise);
39438
+ }
39431
39439
  }
39432
39440
  function getAgentSession(sessionId) {
39433
39441
  return swarmState.agentSessions.get(sessionId);
39434
39442
  }
39435
- function ensureAgentSession(sessionId, agentName, _directory) {
39443
+ function ensureAgentSession(sessionId, agentName, directory) {
39436
39444
  const now = Date.now();
39437
39445
  let session = swarmState.agentSessions.get(sessionId);
39438
39446
  if (session) {
@@ -39532,7 +39540,7 @@ function ensureAgentSession(sessionId, agentName, _directory) {
39532
39540
  session.lastToolCallTime = now;
39533
39541
  return session;
39534
39542
  }
39535
- startAgentSession(sessionId, agentName ?? "unknown", 7200000);
39543
+ startAgentSession(sessionId, agentName ?? "unknown", 7200000, directory);
39536
39544
  session = swarmState.agentSessions.get(sessionId);
39537
39545
  if (!session) {
39538
39546
  throw new Error(`Failed to create guardrail session for ${sessionId}`);
@@ -39761,6 +39769,10 @@ function applyRehydrationCache(session) {
39761
39769
  }
39762
39770
  }
39763
39771
  }
39772
+ async function rehydrateSessionFromDisk(directory, session) {
39773
+ await buildRehydrationCache(directory);
39774
+ applyRehydrationCache(session);
39775
+ }
39764
39776
  function hasActiveTurboMode() {
39765
39777
  for (const [_sessionId, session] of swarmState.agentSessions) {
39766
39778
  if (session.turboMode === true) {
@@ -49897,6 +49909,8 @@ ${joined}
49897
49909
  ` + textPart2.text;
49898
49910
  }
49899
49911
  session.pendingAdvisoryMessages = [];
49912
+ } else if (!isArchitectSession && session && (session.pendingAdvisoryMessages?.length ?? 0) > 0) {
49913
+ session.pendingAdvisoryMessages = [];
49900
49914
  }
49901
49915
  if (isArchitectSession && session && session.architectWriteCount > session.selfCodingWarnedAtCount) {
49902
49916
  let targetSystemMessage = systemMessages[0];
@@ -52565,19 +52579,38 @@ import * as path33 from "path";
52565
52579
 
52566
52580
  // src/hooks/spawn-helper.ts
52567
52581
  import { spawn } from "child_process";
52582
+ var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
52568
52583
  function spawnAsync(command, cwd, timeoutMs) {
52569
52584
  return new Promise((resolve11) => {
52570
52585
  try {
52571
- const [cmd, ...args2] = command;
52586
+ const [rawCmd, ...args2] = command;
52587
+ const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
52572
52588
  const proc = spawn(cmd, args2, { cwd, stdio: ["ignore", "pipe", "pipe"] });
52573
52589
  let stdout = "";
52574
52590
  let stderr = "";
52575
52591
  let done = false;
52592
+ const MAX_OUTPUT = 512 * 1024;
52576
52593
  proc.stdout.on("data", (d) => {
52577
- stdout += d;
52594
+ if (stdout.length < MAX_OUTPUT) {
52595
+ stdout += d;
52596
+ if (stdout.length >= MAX_OUTPUT) {
52597
+ stdout = stdout.slice(0, MAX_OUTPUT);
52598
+ try {
52599
+ proc.stdout.destroy();
52600
+ } catch {}
52601
+ }
52602
+ }
52578
52603
  });
52579
52604
  proc.stderr.on("data", (d) => {
52580
- stderr += d;
52605
+ if (stderr.length < MAX_OUTPUT) {
52606
+ stderr += d;
52607
+ if (stderr.length >= MAX_OUTPUT) {
52608
+ stderr = stderr.slice(0, MAX_OUTPUT);
52609
+ try {
52610
+ proc.stderr.destroy();
52611
+ } catch {}
52612
+ }
52613
+ }
52581
52614
  });
52582
52615
  const timer = setTimeout(() => {
52583
52616
  if (done)
@@ -52616,19 +52649,31 @@ function spawnAsync(command, cwd, timeoutMs) {
52616
52649
 
52617
52650
  // src/hooks/incremental-verify.ts
52618
52651
  var emittedSkipAdvisories = new Set;
52652
+ function detectPackageManager(projectDir) {
52653
+ if (fs20.existsSync(path33.join(projectDir, "bun.lockb")))
52654
+ return "bun";
52655
+ if (fs20.existsSync(path33.join(projectDir, "pnpm-lock.yaml")))
52656
+ return "pnpm";
52657
+ if (fs20.existsSync(path33.join(projectDir, "yarn.lock")))
52658
+ return "yarn";
52659
+ if (fs20.existsSync(path33.join(projectDir, "package-lock.json")))
52660
+ return "npm";
52661
+ return "bun";
52662
+ }
52619
52663
  function detectTypecheckCommand(projectDir) {
52620
52664
  const pkgPath = path33.join(projectDir, "package.json");
52621
52665
  if (fs20.existsSync(pkgPath)) {
52622
52666
  try {
52623
52667
  const pkg = JSON.parse(fs20.readFileSync(pkgPath, "utf8"));
52624
52668
  const scripts = pkg.scripts;
52625
- if (scripts?.typecheck)
52626
- return { command: ["bun", "run", "typecheck"], language: "typescript" };
52627
- if (scripts?.["type-check"])
52628
- return {
52629
- command: ["bun", "run", "type-check"],
52630
- language: "typescript"
52631
- };
52669
+ if (scripts?.typecheck) {
52670
+ const pm = detectPackageManager(projectDir);
52671
+ return { command: [pm, "run", "typecheck"], language: "typescript" };
52672
+ }
52673
+ if (scripts?.["type-check"]) {
52674
+ const pm = detectPackageManager(projectDir);
52675
+ return { command: [pm, "run", "type-check"], language: "typescript" };
52676
+ }
52632
52677
  const deps = {
52633
52678
  ...pkg.dependencies,
52634
52679
  ...pkg.devDependencies
@@ -52683,7 +52728,11 @@ function createIncrementalVerifyHook(config3, projectDir, injectMessage) {
52683
52728
  }
52684
52729
  let commandToRun = null;
52685
52730
  if (config3.command != null) {
52686
- commandToRun = Array.isArray(config3.command) ? config3.command : config3.command.split(" ");
52731
+ if (Array.isArray(config3.command)) {
52732
+ commandToRun = config3.command;
52733
+ } else {
52734
+ commandToRun = config3.command.split(" ");
52735
+ }
52687
52736
  } else {
52688
52737
  const detected = detectTypecheckCommand(projectDir);
52689
52738
  if (detected === null) {
@@ -53954,7 +54003,10 @@ async function readSnapshot(directory) {
53954
54003
  return null;
53955
54004
  }
53956
54005
  }
53957
- function rehydrateState(snapshot) {
54006
+ async function rehydrateState(snapshot) {
54007
+ if (swarmState.pendingRehydrations.size > 0) {
54008
+ await Promise.allSettled([...swarmState.pendingRehydrations]);
54009
+ }
53958
54010
  swarmState.toolAggregates.clear();
53959
54011
  swarmState.activeAgent.clear();
53960
54012
  swarmState.delegationChains.clear();
@@ -53985,7 +54037,7 @@ async function loadSnapshot(directory) {
53985
54037
  await buildRehydrationCache(directory);
53986
54038
  const snapshot = await readSnapshot(directory);
53987
54039
  if (snapshot !== null) {
53988
- rehydrateState(snapshot);
54040
+ await rehydrateState(snapshot);
53989
54041
  for (const session of swarmState.agentSessions.values()) {
53990
54042
  applyRehydrationCache(session);
53991
54043
  }
@@ -56643,32 +56695,32 @@ async function executePhaseComplete(args2, workingDirectory) {
56643
56695
  ]
56644
56696
  }, null, 2);
56645
56697
  }
56698
+ const knowledgeConfig = {
56699
+ enabled: true,
56700
+ swarm_max_entries: 100,
56701
+ hive_max_entries: 200,
56702
+ auto_promote_days: 90,
56703
+ max_inject_count: 5,
56704
+ dedup_threshold: 0.6,
56705
+ scope_filter: ["global"],
56706
+ hive_enabled: true,
56707
+ rejected_max_entries: 20,
56708
+ validation_enabled: true,
56709
+ evergreen_confidence: 0.9,
56710
+ evergreen_utility: 0.8,
56711
+ low_utility_threshold: 0.3,
56712
+ min_retrievals_for_utility: 3,
56713
+ schema_version: 1,
56714
+ same_project_weight: 1,
56715
+ cross_project_weight: 0.5,
56716
+ min_encounter_score: 0.1,
56717
+ initial_encounter_score: 1,
56718
+ encounter_increment: 0.1,
56719
+ max_encounter_score: 10
56720
+ };
56646
56721
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
56647
56722
  try {
56648
56723
  const projectName = path44.basename(dir);
56649
- const knowledgeConfig = {
56650
- enabled: true,
56651
- swarm_max_entries: 100,
56652
- hive_max_entries: 200,
56653
- auto_promote_days: 90,
56654
- max_inject_count: 5,
56655
- dedup_threshold: 0.6,
56656
- scope_filter: ["global"],
56657
- hive_enabled: true,
56658
- rejected_max_entries: 20,
56659
- validation_enabled: true,
56660
- evergreen_confidence: 0.9,
56661
- evergreen_utility: 0.8,
56662
- low_utility_threshold: 0.3,
56663
- min_retrievals_for_utility: 3,
56664
- schema_version: 1,
56665
- same_project_weight: 1,
56666
- cross_project_weight: 0.5,
56667
- min_encounter_score: 0.1,
56668
- initial_encounter_score: 1,
56669
- encounter_increment: 0.1,
56670
- max_encounter_score: 10
56671
- };
56672
56724
  await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
56673
56725
  } catch (error93) {
56674
56726
  safeWarn("[phase_complete] Failed to curate lessons from retrospective:", error93);
@@ -56679,7 +56731,7 @@ async function executePhaseComplete(args2, workingDirectory) {
56679
56731
  const curatorConfig = CuratorConfigSchema.parse(config3.curator ?? {});
56680
56732
  if (curatorConfig.enabled && curatorConfig.phase_enabled) {
56681
56733
  const curatorResult = await runCuratorPhase(dir, phase, agentsDispatched, curatorConfig, {});
56682
- await applyCuratorKnowledgeUpdates(dir, curatorResult.knowledge_recommendations, {});
56734
+ await applyCuratorKnowledgeUpdates(dir, curatorResult.knowledge_recommendations, knowledgeConfig);
56683
56735
  await runCriticDriftCheck(dir, phase, curatorResult, curatorConfig);
56684
56736
  if (curatorResult.compliance.length > 0 && !curatorConfig.suppress_warnings) {
56685
56737
  const complianceLines = curatorResult.compliance.map((obs) => `[${obs.severity.toUpperCase()}] ${obs.description}`).slice(0, 5);
@@ -20,7 +20,7 @@ export declare function readSnapshot(directory: string): Promise<SnapshotData |
20
20
  * Clears existing maps first, then populates from snapshot.
21
21
  * Does NOT touch activeToolCalls or pendingEvents (remain at defaults).
22
22
  */
23
- export declare function rehydrateState(snapshot: SnapshotData): void;
23
+ export declare function rehydrateState(snapshot: SnapshotData): Promise<void>;
24
24
  /**
25
25
  * Load snapshot from disk and rehydrate swarmState.
26
26
  * Called on plugin init to restore state from previous session.
package/dist/state.d.ts CHANGED
@@ -181,6 +181,8 @@ export declare const swarmState: {
181
181
  lastBudgetPct: number;
182
182
  /** Per-session guardrail state — keyed by sessionID */
183
183
  agentSessions: Map<string, AgentSessionState>;
184
+ /** In-flight rehydration promises — awaited by rehydrateState before clearing agentSessions */
185
+ pendingRehydrations: Set<Promise<void>>;
184
186
  };
185
187
  /**
186
188
  * Reset all state to initial values - useful for testing
@@ -194,7 +196,7 @@ export declare function resetSwarmState(): void;
194
196
  * @param staleDurationMs - Age threshold for stale session eviction (default: 120 min)
195
197
  * @param directory - Optional project directory for rehydrating workflow state from disk
196
198
  */
197
- export declare function startAgentSession(sessionId: string, agentName: string, staleDurationMs?: number, _directory?: string): void;
199
+ export declare function startAgentSession(sessionId: string, agentName: string, staleDurationMs?: number, directory?: string): void;
198
200
  /**
199
201
  * End an agent session by removing it from the state.
200
202
  * NOTE: Currently unused in production — no session lifecycle teardown is wired up.
@@ -218,7 +220,7 @@ export declare function getAgentSession(sessionId: string): AgentSessionState |
218
220
  * @param agentName - Optional agent name (if known)
219
221
  * @returns The AgentSessionState
220
222
  */
221
- export declare function ensureAgentSession(sessionId: string, agentName?: string, _directory?: string): AgentSessionState;
223
+ export declare function ensureAgentSession(sessionId: string, agentName?: string, directory?: string): AgentSessionState;
222
224
  /**
223
225
  * Update only the agent event timestamp (for stale detection).
224
226
  * Does NOT change agent name or reset guardrail state.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.30.0",
3
+ "version": "6.30.1",
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",