opencode-swarm-plugin 0.25.2 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -121,9 +121,6 @@ export const SwarmPlugin: Plugin = async (
121
121
  });
122
122
 
123
123
  if (response.ok) {
124
- console.log(
125
- `[swarm-plugin] Auto-released ${activeAgentMailState.reservations.length} file reservation(s)`,
126
- );
127
124
  activeAgentMailState.reservations = [];
128
125
  }
129
126
  } catch (error) {
@@ -202,9 +199,6 @@ export const SwarmPlugin: Plugin = async (
202
199
  const guardrailResult = guardrailOutput(toolName, output.output);
203
200
  if (guardrailResult.truncated) {
204
201
  output.output = guardrailResult.output;
205
- console.log(
206
- `[swarm-plugin] Guardrail truncated ${toolName}: ${guardrailResult.originalLength} → ${guardrailResult.truncatedLength} chars`,
207
- );
208
202
  }
209
203
  }
210
204
 
@@ -242,20 +236,12 @@ export const SwarmPlugin: Plugin = async (
242
236
  // Auto-release after swarm:complete
243
237
  if (toolName === "swarm_complete" && activeAgentMailState) {
244
238
  await releaseReservations();
245
- console.log(
246
- "[swarm-plugin] Auto-released reservations after swarm:complete",
247
- );
248
239
  }
249
240
 
250
241
  // Auto-sync beads after closing
251
242
  if (toolName === "beads_close") {
252
243
  // Trigger async sync without blocking - fire and forget
253
- void $`bd sync`
254
- .quiet()
255
- .nothrow()
256
- .then(() => {
257
- console.log("[swarm-plugin] Auto-synced beads after close");
258
- });
244
+ void $`bd sync`.quiet().nothrow();
259
245
  }
260
246
  },
261
247
  };
@@ -490,11 +490,6 @@ export class SqliteRateLimiter implements RateLimiter {
490
490
  if (result.changes < BATCH_SIZE) break;
491
491
  }
492
492
 
493
- if (totalDeleted > 0) {
494
- console.log("[RateLimiter] Cleanup completed:", {
495
- deletedRows: totalDeleted,
496
- });
497
- }
498
493
  }
499
494
 
500
495
  async recordRequest(agentName: string, endpoint: string): Promise<void> {
package/src/storage.ts CHANGED
@@ -329,10 +329,6 @@ export class SemanticMemoryStorage implements LearningStorage {
329
329
  constructor(config: Partial<StorageConfig> = {}) {
330
330
  // Use getDefaultStorageConfig() to ensure env vars are read at runtime
331
331
  this.config = { ...getDefaultStorageConfig(), ...config };
332
- console.log(
333
- `[storage] SemanticMemoryStorage initialized with collections:`,
334
- this.config.collections,
335
- );
336
332
  }
337
333
 
338
334
  // -------------------------------------------------------------------------
@@ -381,7 +377,6 @@ export class SemanticMemoryStorage implements LearningStorage {
381
377
  args.push("--metadata", JSON.stringify(metadata));
382
378
  }
383
379
 
384
- console.log(`[storage] store() -> collection="${collection}"`);
385
380
  sessionStats.storesCount++;
386
381
 
387
382
  const result = await execSemanticMemory(args);
@@ -416,9 +411,6 @@ export class SemanticMemoryStorage implements LearningStorage {
416
411
  args.push("--fts");
417
412
  }
418
413
 
419
- console.log(
420
- `[storage] find() -> collection="${collection}", query="${query.slice(0, 50)}${query.length > 50 ? "..." : ""}", limit=${limit}, fts=${useFts}`,
421
- );
422
414
  sessionStats.queriesCount++;
423
415
 
424
416
  const result = await execSemanticMemory(args);
@@ -456,7 +448,6 @@ export class SemanticMemoryStorage implements LearningStorage {
456
448
  }
457
449
 
458
450
  private async list<T>(collection: string): Promise<T[]> {
459
- console.log(`[storage] list() -> collection="${collection}"`);
460
451
  sessionStats.queriesCount++;
461
452
 
462
453
  const result = await execSemanticMemory([
@@ -9,7 +9,11 @@
9
9
 
10
10
  import { randomUUID } from "node:crypto";
11
11
  import { describe, it, expect, beforeEach, afterEach } from "vitest";
12
- import { resetDatabase, closeDatabase, getDatabase } from "./streams/index";
12
+ import {
13
+ resetDatabase,
14
+ getDatabase,
15
+ closeDatabase,
16
+ } from "swarm-mail";
13
17
  import {
14
18
  swarmmail_init,
15
19
  swarmmail_send,
@@ -1031,7 +1031,7 @@ export const swarm_complete = tool({
1031
1031
  .optional()
1032
1032
  .describe("Number of retry attempts during task"),
1033
1033
  },
1034
- async execute(args) {
1034
+ async execute(args, _ctx) {
1035
1035
  // Extract epic ID early for error notifications
1036
1036
  const epicId = args.bead_id.includes(".")
1037
1037
  ? args.bead_id.split(".")[0]
@@ -1295,9 +1295,6 @@ Continuing with completion, but this should be fixed for future subtasks.`;
1295
1295
 
1296
1296
  if (storeResult.exitCode === 0) {
1297
1297
  memoryStored = true;
1298
- console.log(
1299
- `[swarm_complete] Stored learning for ${args.bead_id} in semantic-memory`,
1300
- );
1301
1298
  } else {
1302
1299
  memoryError = `semantic-memory store failed: ${storeResult.stderr.toString().slice(0, 200)}`;
1303
1300
  console.warn(`[swarm_complete] ${memoryError}`);
@@ -1351,15 +1348,27 @@ Continuing with completion, but this should be fixed for future subtasks.`;
1351
1348
  .filter(Boolean)
1352
1349
  .join("\n");
1353
1350
 
1354
- await sendSwarmMessage({
1355
- projectPath: args.project_key,
1356
- fromAgent: args.agent_name,
1357
- toAgents: [], // Thread broadcast
1358
- subject: `Complete: ${args.bead_id}`,
1359
- body: completionBody,
1360
- threadId: epicId,
1361
- importance: "normal",
1362
- });
1351
+ // Send completion message (non-fatal if it fails)
1352
+ let messageSent = false;
1353
+ let messageError: string | undefined;
1354
+ try {
1355
+ await sendSwarmMessage({
1356
+ projectPath: args.project_key,
1357
+ fromAgent: args.agent_name,
1358
+ toAgents: [], // Thread broadcast
1359
+ subject: `Complete: ${args.bead_id}`,
1360
+ body: completionBody,
1361
+ threadId: epicId,
1362
+ importance: "normal",
1363
+ });
1364
+ messageSent = true;
1365
+ } catch (error) {
1366
+ // Non-fatal - log and continue
1367
+ messageError = error instanceof Error ? error.message : String(error);
1368
+ console.warn(
1369
+ `[swarm_complete] Failed to send completion message: ${messageError}`,
1370
+ );
1371
+ }
1363
1372
 
1364
1373
  // Build success response with semantic-memory integration
1365
1374
  const response = {
@@ -1367,7 +1376,8 @@ Continuing with completion, but this should be fixed for future subtasks.`;
1367
1376
  bead_id: args.bead_id,
1368
1377
  closed: true,
1369
1378
  reservations_released: true,
1370
- message_sent: true,
1379
+ message_sent: messageSent,
1380
+ message_error: messageError,
1371
1381
  agent_registration: {
1372
1382
  verified: agentRegistered,
1373
1383
  warning: registrationWarning || undefined,
@@ -1548,6 +1548,89 @@ describe("Swarm Prompt V2 (with Swarm Mail/Beads)", () => {
1548
1548
  },
1549
1549
  );
1550
1550
  });
1551
+
1552
+ describe("swarm_complete error handling", () => {
1553
+ let beadsAvailable = false;
1554
+
1555
+ beforeAll(async () => {
1556
+ beadsAvailable = await isBeadsAvailable();
1557
+ });
1558
+
1559
+ it.skipIf(!beadsAvailable)(
1560
+ "returns structured error when bead close fails",
1561
+ async () => {
1562
+ // Try to complete a non-existent bead
1563
+ const result = await swarm_complete.execute(
1564
+ {
1565
+ project_key: "/tmp/test-error-handling",
1566
+ agent_name: "test-agent",
1567
+ bead_id: "bd-nonexistent-12345",
1568
+ summary: "This should fail",
1569
+ skip_verification: true,
1570
+ },
1571
+ mockContext,
1572
+ );
1573
+
1574
+ const parsed = JSON.parse(result);
1575
+
1576
+ // Should return structured error, not throw
1577
+ expect(parsed.success).toBe(false);
1578
+ expect(parsed.error).toContain("Failed to close bead");
1579
+ expect(parsed.failed_step).toBe("bd close");
1580
+ expect(parsed.bead_id).toBe("bd-nonexistent-12345");
1581
+ expect(parsed.recovery).toBeDefined();
1582
+ expect(parsed.recovery.steps).toBeInstanceOf(Array);
1583
+ },
1584
+ );
1585
+
1586
+ it.skipIf(!beadsAvailable)(
1587
+ "includes message_sent status in response",
1588
+ async () => {
1589
+ const createResult =
1590
+ await Bun.$`bd create "Test message status" -t task --json`
1591
+ .quiet()
1592
+ .nothrow();
1593
+
1594
+ if (createResult.exitCode !== 0) {
1595
+ console.warn(
1596
+ "Could not create bead:",
1597
+ createResult.stderr.toString(),
1598
+ );
1599
+ return;
1600
+ }
1601
+
1602
+ const bead = JSON.parse(createResult.stdout.toString());
1603
+
1604
+ try {
1605
+ const result = await swarm_complete.execute(
1606
+ {
1607
+ project_key: "/tmp/test-message-status",
1608
+ agent_name: "test-agent",
1609
+ bead_id: bead.id,
1610
+ summary: "Test message status tracking",
1611
+ skip_verification: true,
1612
+ },
1613
+ mockContext,
1614
+ );
1615
+
1616
+ const parsed = JSON.parse(result);
1617
+
1618
+ // Should have message_sent field (true or false)
1619
+ expect(parsed).toHaveProperty("message_sent");
1620
+ // If message failed, should have message_error
1621
+ if (!parsed.message_sent) {
1622
+ expect(parsed).toHaveProperty("message_error");
1623
+ }
1624
+ } catch (error) {
1625
+ // Clean up bead if test fails
1626
+ await Bun.$`bd close ${bead.id} --reason "Test cleanup"`
1627
+ .quiet()
1628
+ .nothrow();
1629
+ throw error;
1630
+ }
1631
+ },
1632
+ );
1633
+ });
1551
1634
  });
1552
1635
 
1553
1636
  // ============================================================================