opencode-swarm 6.43.1 → 6.43.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/dist/cli/index.js CHANGED
@@ -16127,7 +16127,7 @@ var require_proper_lockfile = __commonJS((exports, module) => {
16127
16127
 
16128
16128
  // src/plan/manager.ts
16129
16129
  import { renameSync as renameSync3, unlinkSync } from "fs";
16130
- import * as path12 from "path";
16130
+ import * as path9 from "path";
16131
16131
  async function loadPlanJsonOnly(directory) {
16132
16132
  const planJsonContent = await readSwarmFileAsync(directory, "plan.json");
16133
16133
  if (planJsonContent !== null) {
@@ -16209,13 +16209,13 @@ async function isPlanMdInSync(directory, plan) {
16209
16209
  return normalizedActual.includes(normalizedExpected) || normalizedExpected.includes(normalizedActual.replace(/^#.*$/gm, "").trim());
16210
16210
  }
16211
16211
  async function regeneratePlanMarkdown(directory, plan) {
16212
- const swarmDir = path12.resolve(directory, ".swarm");
16212
+ const swarmDir = path9.resolve(directory, ".swarm");
16213
16213
  const contentHash = computePlanContentHash(plan);
16214
16214
  const markdown = derivePlanMarkdown(plan);
16215
16215
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
16216
16216
  ${markdown}`;
16217
- const mdPath = path12.join(swarmDir, "plan.md");
16218
- const mdTempPath = path12.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16217
+ const mdPath = path9.join(swarmDir, "plan.md");
16218
+ const mdTempPath = path9.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16219
16219
  try {
16220
16220
  await Bun.write(mdTempPath, markdownWithHash);
16221
16221
  renameSync3(mdTempPath, mdPath);
@@ -16302,9 +16302,9 @@ async function savePlan(directory, plan, options) {
16302
16302
  phase.status = "pending";
16303
16303
  }
16304
16304
  }
16305
- const swarmDir = path12.resolve(directory, ".swarm");
16306
- const planPath = path12.join(swarmDir, "plan.json");
16307
- const tempPath = path12.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16305
+ const swarmDir = path9.resolve(directory, ".swarm");
16306
+ const planPath = path9.join(swarmDir, "plan.json");
16307
+ const tempPath = path9.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16308
16308
  try {
16309
16309
  await Bun.write(tempPath, JSON.stringify(validated, null, 2));
16310
16310
  renameSync3(tempPath, planPath);
@@ -16317,8 +16317,8 @@ async function savePlan(directory, plan, options) {
16317
16317
  const markdown = derivePlanMarkdown(validated);
16318
16318
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
16319
16319
  ${markdown}`;
16320
- const mdPath = path12.join(swarmDir, "plan.md");
16321
- const mdTempPath = path12.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16320
+ const mdPath = path9.join(swarmDir, "plan.md");
16321
+ const mdTempPath = path9.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16322
16322
  try {
16323
16323
  await Bun.write(mdTempPath, markdownWithHash);
16324
16324
  renameSync3(mdTempPath, mdPath);
@@ -16328,7 +16328,7 @@ ${markdown}`;
16328
16328
  } catch {}
16329
16329
  }
16330
16330
  try {
16331
- const markerPath = path12.join(swarmDir, ".plan-write-marker");
16331
+ const markerPath = path9.join(swarmDir, ".plan-write-marker");
16332
16332
  const tasksCount = validated.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
16333
16333
  const marker = JSON.stringify({
16334
16334
  source: "plan_manager",
@@ -18253,7 +18253,8 @@ var CuratorConfigSchema = exports_external.object({
18253
18253
  min_knowledge_confidence: exports_external.number().min(0).max(1).default(0.7),
18254
18254
  compliance_report: exports_external.boolean().default(true),
18255
18255
  suppress_warnings: exports_external.boolean().default(true),
18256
- drift_inject_max_chars: exports_external.number().min(100).max(2000).default(500)
18256
+ drift_inject_max_chars: exports_external.number().min(100).max(2000).default(500),
18257
+ llm_timeout_ms: exports_external.number().int().min(5000).max(600000).default(300000)
18257
18258
  });
18258
18259
  var SlopDetectorConfigSchema = exports_external.object({
18259
18260
  enabled: exports_external.boolean().default(true),
@@ -32849,7 +32850,7 @@ async function handleConfigCommand(directory, _args) {
32849
32850
  }
32850
32851
 
32851
32852
  // src/hooks/hive-promoter.ts
32852
- import path9 from "path";
32853
+ import path10 from "path";
32853
32854
 
32854
32855
  // src/background/event-bus.ts
32855
32856
  init_utils();
@@ -32921,6 +32922,7 @@ function getGlobalEventBus() {
32921
32922
  }
32922
32923
 
32923
32924
  // src/hooks/curator.ts
32925
+ init_manager2();
32924
32926
  init_utils2();
32925
32927
 
32926
32928
  // src/hooks/hive-promoter.ts
@@ -33103,7 +33105,7 @@ async function promoteToHive(directory, lesson, category) {
33103
33105
  schema_version: 1,
33104
33106
  created_at: new Date().toISOString(),
33105
33107
  updated_at: new Date().toISOString(),
33106
- source_project: path9.basename(directory) || "unknown",
33108
+ source_project: path10.basename(directory) || "unknown",
33107
33109
  encounter_score: 1
33108
33110
  };
33109
33111
  await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
@@ -33181,13 +33183,13 @@ function formatCurationSummary(summary) {
33181
33183
  }
33182
33184
 
33183
33185
  // src/commands/dark-matter.ts
33184
- import path11 from "path";
33186
+ import path12 from "path";
33185
33187
 
33186
33188
  // src/tools/co-change-analyzer.ts
33187
33189
  import * as child_process from "child_process";
33188
33190
  import { randomUUID } from "crypto";
33189
33191
  import { readdir, readFile as readFile2, stat } from "fs/promises";
33190
- import * as path10 from "path";
33192
+ import * as path11 from "path";
33191
33193
  import { promisify } from "util";
33192
33194
  function getExecFileAsync() {
33193
33195
  return promisify(child_process.execFile);
@@ -33289,7 +33291,7 @@ async function scanSourceFiles(dir) {
33289
33291
  try {
33290
33292
  const entries = await readdir(dir, { withFileTypes: true });
33291
33293
  for (const entry of entries) {
33292
- const fullPath = path10.join(dir, entry.name);
33294
+ const fullPath = path11.join(dir, entry.name);
33293
33295
  if (entry.isDirectory()) {
33294
33296
  if (skipDirs.has(entry.name)) {
33295
33297
  continue;
@@ -33297,7 +33299,7 @@ async function scanSourceFiles(dir) {
33297
33299
  const subFiles = await scanSourceFiles(fullPath);
33298
33300
  results.push(...subFiles);
33299
33301
  } else if (entry.isFile()) {
33300
- const ext = path10.extname(entry.name);
33302
+ const ext = path11.extname(entry.name);
33301
33303
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
33302
33304
  results.push(fullPath);
33303
33305
  }
@@ -33319,8 +33321,8 @@ async function getStaticEdges(directory) {
33319
33321
  continue;
33320
33322
  }
33321
33323
  try {
33322
- const sourceDir = path10.dirname(sourceFile);
33323
- const resolvedPath = path10.resolve(sourceDir, importPath);
33324
+ const sourceDir = path11.dirname(sourceFile);
33325
+ const resolvedPath = path11.resolve(sourceDir, importPath);
33324
33326
  const extensions = [
33325
33327
  "",
33326
33328
  ".ts",
@@ -33345,8 +33347,8 @@ async function getStaticEdges(directory) {
33345
33347
  if (!targetFile) {
33346
33348
  continue;
33347
33349
  }
33348
- const relSource = path10.relative(directory, sourceFile).replace(/\\/g, "/");
33349
- const relTarget = path10.relative(directory, targetFile).replace(/\\/g, "/");
33350
+ const relSource = path11.relative(directory, sourceFile).replace(/\\/g, "/");
33351
+ const relTarget = path11.relative(directory, targetFile).replace(/\\/g, "/");
33350
33352
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
33351
33353
  edges.add(key);
33352
33354
  } catch {}
@@ -33358,7 +33360,7 @@ async function getStaticEdges(directory) {
33358
33360
  function isTestImplementationPair(fileA, fileB) {
33359
33361
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
33360
33362
  const getBaseName = (filePath) => {
33361
- const base = path10.basename(filePath);
33363
+ const base = path11.basename(filePath);
33362
33364
  for (const pattern of testPatterns) {
33363
33365
  if (base.endsWith(pattern)) {
33364
33366
  return base.slice(0, -pattern.length);
@@ -33368,16 +33370,16 @@ function isTestImplementationPair(fileA, fileB) {
33368
33370
  };
33369
33371
  const baseA = getBaseName(fileA);
33370
33372
  const baseB = getBaseName(fileB);
33371
- return baseA === baseB && baseA !== path10.basename(fileA) && baseA !== path10.basename(fileB);
33373
+ return baseA === baseB && baseA !== path11.basename(fileA) && baseA !== path11.basename(fileB);
33372
33374
  }
33373
33375
  function hasSharedPrefix(fileA, fileB) {
33374
- const dirA = path10.dirname(fileA);
33375
- const dirB = path10.dirname(fileB);
33376
+ const dirA = path11.dirname(fileA);
33377
+ const dirB = path11.dirname(fileB);
33376
33378
  if (dirA !== dirB) {
33377
33379
  return false;
33378
33380
  }
33379
- const baseA = path10.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33380
- const baseB = path10.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33381
+ const baseA = path11.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33382
+ const baseB = path11.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33381
33383
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
33382
33384
  return true;
33383
33385
  }
@@ -33431,8 +33433,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
33431
33433
  const entries = [];
33432
33434
  const now = new Date().toISOString();
33433
33435
  for (const pair of pairs.slice(0, 10)) {
33434
- const baseA = path10.basename(pair.fileA);
33435
- const baseB = path10.basename(pair.fileB);
33436
+ const baseA = path11.basename(pair.fileA);
33437
+ const baseB = path11.basename(pair.fileB);
33436
33438
  let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
33437
33439
  if (lesson.length > 280) {
33438
33440
  lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
@@ -33542,7 +33544,7 @@ async function handleDarkMatterCommand(directory, args) {
33542
33544
  const output = formatDarkMatterOutput(pairs);
33543
33545
  if (pairs.length > 0) {
33544
33546
  try {
33545
- const projectName = path11.basename(path11.resolve(directory));
33547
+ const projectName = path12.basename(path12.resolve(directory));
33546
33548
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
33547
33549
  if (entries.length > 0) {
33548
33550
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -442,6 +442,7 @@ export declare const CuratorConfigSchema: z.ZodObject<{
442
442
  compliance_report: z.ZodDefault<z.ZodBoolean>;
443
443
  suppress_warnings: z.ZodDefault<z.ZodBoolean>;
444
444
  drift_inject_max_chars: z.ZodDefault<z.ZodNumber>;
445
+ llm_timeout_ms: z.ZodDefault<z.ZodNumber>;
445
446
  }, z.core.$strip>;
446
447
  export type CuratorConfig = z.infer<typeof CuratorConfigSchema>;
447
448
  export declare const SlopDetectorConfigSchema: z.ZodObject<{
@@ -753,6 +754,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
753
754
  compliance_report: z.ZodDefault<z.ZodBoolean>;
754
755
  suppress_warnings: z.ZodDefault<z.ZodBoolean>;
755
756
  drift_inject_max_chars: z.ZodDefault<z.ZodNumber>;
757
+ llm_timeout_ms: z.ZodDefault<z.ZodNumber>;
756
758
  }, z.core.$strip>>;
757
759
  tool_output: z.ZodOptional<z.ZodObject<{
758
760
  truncation_enabled: z.ZodDefault<z.ZodBoolean>;
@@ -77,6 +77,7 @@ export interface CuratorConfig {
77
77
  compliance_report: boolean;
78
78
  suppress_warnings: boolean;
79
79
  drift_inject_max_chars: number;
80
+ llm_timeout_ms?: number;
80
81
  }
81
82
  export interface CuratorInitResult {
82
83
  briefing: string;
@@ -15,7 +15,7 @@ import type { KnowledgeConfig } from './knowledge-types.js';
15
15
  * Takes a system prompt and user input, returns the LLM output text.
16
16
  * Used to delegate analysis to the explorer agent in CURATOR mode.
17
17
  */
18
- export type CuratorLLMDelegate = (systemPrompt: string, userInput: string) => Promise<string>;
18
+ export type CuratorLLMDelegate = (systemPrompt: string, userInput: string, signal?: AbortSignal) => Promise<string>;
19
19
  /**
20
20
  * Parse KNOWLEDGE_UPDATES section from curator LLM output.
21
21
  * Expected format per line: "- [action] [entry_id or "new"]: [reason]"
@@ -72,7 +72,7 @@ export declare function runCuratorInit(directory: string, config: CuratorConfig,
72
72
  * @param llmDelegate - Optional LLM delegate for enhanced analysis
73
73
  * @returns CuratorPhaseResult with digest, compliance, and recommendations
74
74
  */
75
- export declare function runCuratorPhase(directory: string, phase: number, agentsDispatched: string[], _config: CuratorConfig, _knowledgeConfig: {
75
+ export declare function runCuratorPhase(directory: string, phase: number, agentsDispatched: string[], config: CuratorConfig, _knowledgeConfig: {
76
76
  directory?: string;
77
77
  }, llmDelegate?: CuratorLLMDelegate): Promise<CuratorPhaseResult>;
78
78
  /**
package/dist/index.js CHANGED
@@ -14974,7 +14974,8 @@ var init_schema = __esm(() => {
14974
14974
  min_knowledge_confidence: exports_external.number().min(0).max(1).default(0.7),
14975
14975
  compliance_report: exports_external.boolean().default(true),
14976
14976
  suppress_warnings: exports_external.boolean().default(true),
14977
- drift_inject_max_chars: exports_external.number().min(100).max(2000).default(500)
14977
+ drift_inject_max_chars: exports_external.number().min(100).max(2000).default(500),
14978
+ llm_timeout_ms: exports_external.number().int().min(5000).max(600000).default(300000)
14978
14979
  });
14979
14980
  SlopDetectorConfigSchema = exports_external.object({
14980
14981
  enabled: exports_external.boolean().default(true),
@@ -47592,9 +47593,10 @@ import path17 from "path";
47592
47593
  import * as fs10 from "fs";
47593
47594
  import * as path16 from "path";
47594
47595
  init_event_bus();
47596
+ init_manager2();
47595
47597
  init_knowledge_store();
47596
47598
  init_utils2();
47597
- var CURATOR_LLM_TIMEOUT_MS = 30000;
47599
+ var DEFAULT_CURATOR_LLM_TIMEOUT_MS = 300000;
47598
47600
  function parseKnowledgeRecommendations(llmOutput) {
47599
47601
  const recommendations = [];
47600
47602
  const section = llmOutput.match(/KNOWLEDGE_UPDATES:\s*\n([\s\S]*?)(?:\n\n|\n[A-Z_]+:|$)/);
@@ -47835,10 +47837,20 @@ async function runCuratorInit(directory, config3, llmDelegate) {
47835
47837
  ].join(`
47836
47838
  `);
47837
47839
  const systemPrompt = CURATOR_INIT_PROMPT;
47838
- const llmOutput = await Promise.race([
47839
- llmDelegate(systemPrompt, userInput),
47840
- new Promise((_, reject) => setTimeout(() => reject(new Error("CURATOR_LLM_TIMEOUT")), CURATOR_LLM_TIMEOUT_MS))
47841
- ]);
47840
+ const timeoutMs = config3.llm_timeout_ms ?? DEFAULT_CURATOR_LLM_TIMEOUT_MS;
47841
+ const ac = new AbortController;
47842
+ const timer = setTimeout(() => ac.abort(), timeoutMs);
47843
+ let llmOutput;
47844
+ try {
47845
+ llmOutput = await Promise.race([
47846
+ llmDelegate(systemPrompt, userInput, ac.signal),
47847
+ new Promise((_, reject) => {
47848
+ ac.signal.addEventListener("abort", () => reject(new Error("CURATOR_LLM_TIMEOUT")));
47849
+ })
47850
+ ]);
47851
+ } finally {
47852
+ clearTimeout(timer);
47853
+ }
47842
47854
  if (llmOutput?.trim()) {
47843
47855
  briefingText = `${briefingText}
47844
47856
 
@@ -47881,15 +47893,28 @@ Could not load prior session context.`,
47881
47893
  };
47882
47894
  }
47883
47895
  }
47884
- async function runCuratorPhase(directory, phase, agentsDispatched, _config, _knowledgeConfig, llmDelegate) {
47896
+ async function runCuratorPhase(directory, phase, agentsDispatched, config3, _knowledgeConfig, llmDelegate) {
47885
47897
  try {
47886
47898
  const priorSummary = await readCuratorSummary(directory);
47899
+ if (priorSummary?.phase_digests.some((d) => d.phase === phase)) {
47900
+ const existingDigest = priorSummary.phase_digests.find((d) => d.phase === phase);
47901
+ return {
47902
+ phase,
47903
+ digest: existingDigest,
47904
+ compliance: priorSummary.compliance_observations.filter((c) => c.phase === phase),
47905
+ knowledge_recommendations: [],
47906
+ summary_updated: false
47907
+ };
47908
+ }
47887
47909
  const eventsJsonlContent = await readSwarmFileAsync(directory, "events.jsonl");
47888
47910
  const phaseEvents = eventsJsonlContent ? filterPhaseEvents(eventsJsonlContent, phase) : [];
47889
47911
  const contextMd = await readSwarmFileAsync(directory, "context.md");
47890
47912
  const requiredAgents = ["reviewer", "test_engineer"];
47891
47913
  const complianceObservations = checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, phase);
47892
- const tasksCompleted = phaseEvents.filter((e) => e.type === "task.completed").length;
47914
+ const plan = await loadPlanJsonOnly(directory);
47915
+ const phaseData = plan?.phases.find((p) => p.id === phase);
47916
+ const tasksCompleted = phaseData ? phaseData.tasks.filter((t) => t.status === "completed").length : 0;
47917
+ const tasksTotal = phaseData ? phaseData.tasks.length : 0;
47893
47918
  const keyDecisions = [];
47894
47919
  if (contextMd) {
47895
47920
  const decisionSection = contextMd.match(/## Decisions\r?\n([\s\S]*?)(?:\r?\n##|$)/);
@@ -47907,10 +47932,10 @@ async function runCuratorPhase(directory, phase, agentsDispatched, _config, _kno
47907
47932
  const phaseDigest = {
47908
47933
  phase,
47909
47934
  timestamp: new Date().toISOString(),
47910
- summary: `Phase ${phase} completed. ${tasksCompleted} tasks recorded. ${complianceObservations.length} compliance observations.`,
47935
+ summary: `Phase ${phase} completed. ${tasksCompleted}/${tasksTotal} tasks completed. ${complianceObservations.length} compliance observations.`,
47911
47936
  agents_used: [...new Set(agentsDispatched.map(normalizeAgentName))],
47912
47937
  tasks_completed: tasksCompleted,
47913
- tasks_total: tasksCompleted,
47938
+ tasks_total: tasksTotal,
47914
47939
  key_decisions: keyDecisions.slice(0, 5),
47915
47940
  blockers_resolved: []
47916
47941
  };
@@ -47928,10 +47953,20 @@ async function runCuratorPhase(directory, phase, agentsDispatched, _config, _kno
47928
47953
  `AGENTS_EXPECTED: ["reviewer", "test_engineer"]`
47929
47954
  ].join(`
47930
47955
  `);
47931
- const llmOutput = await Promise.race([
47932
- llmDelegate(systemPrompt, userInput),
47933
- new Promise((_, reject) => setTimeout(() => reject(new Error("CURATOR_LLM_TIMEOUT")), CURATOR_LLM_TIMEOUT_MS))
47934
- ]);
47956
+ const timeoutMs = config3.llm_timeout_ms ?? DEFAULT_CURATOR_LLM_TIMEOUT_MS;
47957
+ const ac = new AbortController;
47958
+ const timer = setTimeout(() => ac.abort(), timeoutMs);
47959
+ let llmOutput;
47960
+ try {
47961
+ llmOutput = await Promise.race([
47962
+ llmDelegate(systemPrompt, userInput, ac.signal),
47963
+ new Promise((_, reject) => {
47964
+ ac.signal.addEventListener("abort", () => reject(new Error("CURATOR_LLM_TIMEOUT")));
47965
+ })
47966
+ ]);
47967
+ } finally {
47968
+ clearTimeout(timer);
47969
+ }
47935
47970
  if (llmOutput?.trim()) {
47936
47971
  knowledgeRecommendations = parseKnowledgeRecommendations(llmOutput);
47937
47972
  }
@@ -52455,8 +52490,20 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
52455
52490
  const client = swarmState.opencodeClient;
52456
52491
  if (!client)
52457
52492
  return;
52458
- return async (_systemPrompt, userInput) => {
52493
+ return async (_systemPrompt, userInput, signal) => {
52459
52494
  let ephemeralSessionId;
52495
+ const cleanup = () => {
52496
+ if (ephemeralSessionId) {
52497
+ const id = ephemeralSessionId;
52498
+ ephemeralSessionId = undefined;
52499
+ client.session.delete({ path: { id } }).catch(() => {});
52500
+ }
52501
+ };
52502
+ if (signal?.aborted) {
52503
+ cleanup();
52504
+ throw new Error("CURATOR_LLM_TIMEOUT");
52505
+ }
52506
+ signal?.addEventListener("abort", cleanup, { once: true });
52460
52507
  try {
52461
52508
  const createResult = await client.session.create({
52462
52509
  query: { directory }
@@ -52465,6 +52512,9 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
52465
52512
  throw new Error(`Failed to create curator session: ${JSON.stringify(createResult.error)}`);
52466
52513
  }
52467
52514
  ephemeralSessionId = createResult.data.id;
52515
+ if (signal?.aborted) {
52516
+ throw new Error("CURATOR_LLM_TIMEOUT");
52517
+ }
52468
52518
  const agentName = resolveCuratorAgentName(mode, sessionId);
52469
52519
  const promptResult = await client.session.prompt({
52470
52520
  path: { id: ephemeralSessionId },
@@ -52481,9 +52531,8 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
52481
52531
  return textParts.map((p) => p.text).join(`
52482
52532
  `);
52483
52533
  } finally {
52484
- if (ephemeralSessionId) {
52485
- client.session.delete({ path: { id: ephemeralSessionId } }).catch(() => {});
52486
- }
52534
+ signal?.removeEventListener("abort", cleanup);
52535
+ cleanup();
52487
52536
  }
52488
52537
  };
52489
52538
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.43.1",
3
+ "version": "6.43.2",
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",