opencode-swarm-plugin 0.11.2 → 0.12.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.
@@ -678,6 +678,12 @@
678
678
  {"id":"opencode-swarm-plugin-fmkz8.1","title":"Step 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T11:12:43.192563-08:00","updated_at":"2025-12-08T11:12:43.285206-08:00","closed_at":"2025-12-08T11:12:43.285206-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-fmkz8.1","depends_on_id":"opencode-swarm-plugin-fmkz8","type":"parent-child","created_at":"2025-12-08T11:12:43.192901-08:00","created_by":"daemon"}]}
679
679
  {"id":"opencode-swarm-plugin-fmkz8.2","title":"Step 2","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T11:12:43.229469-08:00","updated_at":"2025-12-08T11:12:43.340511-08:00","closed_at":"2025-12-08T11:12:43.340511-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-fmkz8.2","depends_on_id":"opencode-swarm-plugin-fmkz8","type":"parent-child","created_at":"2025-12-08T11:12:43.229808-08:00","created_by":"daemon"}]}
680
680
  {"id":"opencode-swarm-plugin-fmte","title":"Thread link test bead","description":"[thread:test-thread-456]","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T08:14:30.118389-08:00","updated_at":"2025-12-08T08:14:31.757071-08:00","closed_at":"2025-12-08T08:14:31.757071-08:00"}
681
+ {"id":"opencode-swarm-plugin-fn2a3","title":"CLI-based plugin wrapper for OpenCode","description":"Replace broken npm import plugin with thin wrapper that shells out to `swarm tool` CLI. Fixes bun: protocol crash.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-09T12:44:59.286448-08:00","updated_at":"2025-12-09T12:53:22.927803-08:00","closed_at":"2025-12-09T12:53:22.927803-08:00"}
682
+ {"id":"opencode-swarm-plugin-fn2a3.1","title":"Add CLI tool subcommand with JSON interface","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-09T12:44:59.380582-08:00","updated_at":"2025-12-09T12:48:28.655484-08:00","closed_at":"2025-12-09T12:48:28.655484-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-fn2a3.1","depends_on_id":"opencode-swarm-plugin-fn2a3","type":"parent-child","created_at":"2025-12-09T12:44:59.381424-08:00","created_by":"daemon"}]}
683
+ {"id":"opencode-swarm-plugin-fn2a3.2","title":"Add file-based session state for Agent Mail","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-09T12:44:59.452126-08:00","updated_at":"2025-12-09T12:50:05.569927-08:00","closed_at":"2025-12-09T12:50:05.569927-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-fn2a3.2","depends_on_id":"opencode-swarm-plugin-fn2a3","type":"parent-child","created_at":"2025-12-09T12:44:59.452571-08:00","created_by":"daemon"}]}
684
+ {"id":"opencode-swarm-plugin-fn2a3.3","title":"Create plugin wrapper template generator","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-09T12:44:59.511026-08:00","updated_at":"2025-12-09T12:52:13.47915-08:00","closed_at":"2025-12-09T12:52:13.47915-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-fn2a3.3","depends_on_id":"opencode-swarm-plugin-fn2a3","type":"parent-child","created_at":"2025-12-09T12:44:59.511712-08:00","created_by":"daemon"}]}
685
+ {"id":"opencode-swarm-plugin-fn2a3.4","title":"Update setup command to generate new plugin wrapper","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-09T12:44:59.559682-08:00","updated_at":"2025-12-09T12:53:13.282356-08:00","closed_at":"2025-12-09T12:53:13.282356-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-fn2a3.4","depends_on_id":"opencode-swarm-plugin-fn2a3","type":"parent-child","created_at":"2025-12-09T12:44:59.560036-08:00","created_by":"daemon"}]}
686
+ {"id":"opencode-swarm-plugin-fn2a3.5","title":"Export tool registry from source modules","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-09T12:44:59.609125-08:00","updated_at":"2025-12-09T12:46:18.092813-08:00","closed_at":"2025-12-09T12:46:18.092813-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-fn2a3.5","depends_on_id":"opencode-swarm-plugin-fn2a3","type":"parent-child","created_at":"2025-12-09T12:44:59.609492-08:00","created_by":"daemon"}]}
681
687
  {"id":"opencode-swarm-plugin-fo9z","title":"Query test bead","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T07:53:43.635138-08:00","updated_at":"2025-12-08T07:53:46.190181-08:00","closed_at":"2025-12-08T07:53:46.190181-08:00"}
682
688
  {"id":"opencode-swarm-plugin-foht","title":"New feature request","description":"","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-08T11:11:07.341455-08:00","updated_at":"2025-12-08T11:11:10.086863-08:00","closed_at":"2025-12-08T11:11:10.086863-08:00"}
683
689
  {"id":"opencode-swarm-plugin-fomf","title":"Limit test bead 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T11:12:25.714274-08:00","updated_at":"2025-12-08T11:12:28.097683-08:00","closed_at":"2025-12-08T11:12:28.097683-08:00"}
package/README.md CHANGED
@@ -45,9 +45,9 @@ The setup wizard handles everything:
45
45
 
46
46
  ◇ Setting up OpenCode integration...
47
47
 
48
- ◆ Plugin: ~/.config/opencode/plugins/swarm.ts
49
- ◆ Command: ~/.config/opencode/commands/swarm.md
50
- ◆ Agent: ~/.config/opencode/agents/swarm-planner.md
48
+ ◆ Plugin: ~/.config/opencode/plugin/swarm.ts
49
+ ◆ Command: ~/.config/opencode/command/swarm.md
50
+ ◆ Agent: ~/.config/opencode/agent/swarm-planner.md
51
51
 
52
52
  └ Setup complete!
53
53
  ```
@@ -90,18 +90,18 @@ Run `swarm config` to see your config file paths:
90
90
 
91
91
  ```
92
92
  🔌 Plugin loader
93
- ~/.config/opencode/plugins/swarm.ts
93
+ ~/.config/opencode/plugin/swarm.ts
94
94
 
95
95
  📜 /swarm command prompt
96
- ~/.config/opencode/commands/swarm.md
96
+ ~/.config/opencode/command/swarm.md
97
97
 
98
98
  🤖 @swarm-planner agent
99
- ~/.config/opencode/agents/swarm-planner.md
99
+ ~/.config/opencode/agent/swarm-planner.md
100
100
  ```
101
101
 
102
102
  ### /swarm Command
103
103
 
104
- The `/swarm` command is defined in `~/.config/opencode/commands/swarm.md`:
104
+ The `/swarm` command is defined in `~/.config/opencode/command/swarm.md`:
105
105
 
106
106
  ```markdown
107
107
  ---
@@ -138,7 +138,7 @@ Begin decomposition now.
138
138
 
139
139
  ### @swarm-planner Agent
140
140
 
141
- The `@swarm-planner` agent is defined in `~/.config/opencode/agents/swarm-planner.md`:
141
+ The `@swarm-planner` agent is defined in `~/.config/opencode/agent/swarm-planner.md`:
142
142
 
143
143
  ````markdown
144
144
  ---
package/bin/swarm.ts CHANGED
@@ -457,9 +457,32 @@ async function checkAllDependencies(): Promise<CheckResult[]> {
457
457
  // File Templates
458
458
  // ============================================================================
459
459
 
460
- const PLUGIN_WRAPPER = `import { SwarmPlugin } from "opencode-swarm-plugin"
460
+ /**
461
+ * Get the plugin wrapper template
462
+ *
463
+ * Reads from examples/plugin-wrapper-template.ts which contains a self-contained
464
+ * plugin that shells out to the `swarm` CLI for all tool execution.
465
+ */
466
+ function getPluginWrapper(): string {
467
+ const templatePath = join(
468
+ __dirname,
469
+ "..",
470
+ "examples",
471
+ "plugin-wrapper-template.ts",
472
+ );
473
+ try {
474
+ return readFileSync(templatePath, "utf-8");
475
+ } catch (error) {
476
+ // Fallback to minimal wrapper if template not found (shouldn't happen in normal install)
477
+ console.warn(
478
+ `[swarm] Could not read plugin template from ${templatePath}, using minimal wrapper`,
479
+ );
480
+ return `// Minimal fallback - install opencode-swarm-plugin globally for full functionality
481
+ import { SwarmPlugin } from "opencode-swarm-plugin"
461
482
  export default SwarmPlugin
462
483
  `;
484
+ }
485
+ }
463
486
 
464
487
  const SWARM_COMMAND = `---
465
488
  description: Decompose task into parallel subtasks and coordinate agents
@@ -636,13 +659,13 @@ async function setup() {
636
659
  // Check if already configured FIRST
637
660
  const configDir = join(homedir(), ".config", "opencode");
638
661
  const pluginDir = join(configDir, "plugin");
639
- const commandsDir = join(configDir, "commands");
640
- const agentsDir = join(configDir, "agents");
662
+ const commandDir = join(configDir, "command");
663
+ const agentDir = join(configDir, "agent");
641
664
 
642
665
  const pluginPath = join(pluginDir, "swarm.ts");
643
- const commandPath = join(commandsDir, "swarm.md");
644
- const plannerAgentPath = join(agentsDir, "swarm-planner.md");
645
- const workerAgentPath = join(agentsDir, "swarm-worker.md");
666
+ const commandPath = join(commandDir, "swarm.md");
667
+ const plannerAgentPath = join(agentDir, "swarm-planner.md");
668
+ const workerAgentPath = join(agentDir, "swarm-worker.md");
646
669
 
647
670
  const existingFiles = [
648
671
  pluginPath,
@@ -955,13 +978,13 @@ async function setup() {
955
978
  p.log.step("Setting up OpenCode integration...");
956
979
 
957
980
  // Create directories if needed
958
- for (const dir of [pluginDir, commandsDir, agentsDir]) {
981
+ for (const dir of [pluginDir, commandDir, agentDir]) {
959
982
  if (!existsSync(dir)) {
960
983
  mkdirSync(dir, { recursive: true });
961
984
  }
962
985
  }
963
986
 
964
- writeFileSync(pluginPath, PLUGIN_WRAPPER);
987
+ writeFileSync(pluginPath, getPluginWrapper());
965
988
  p.log.success("Plugin: " + pluginPath);
966
989
 
967
990
  writeFileSync(commandPath, SWARM_COMMAND);
@@ -1081,9 +1104,9 @@ async function version() {
1081
1104
  function config() {
1082
1105
  const configDir = join(homedir(), ".config", "opencode");
1083
1106
  const pluginPath = join(configDir, "plugin", "swarm.ts");
1084
- const commandPath = join(configDir, "commands", "swarm.md");
1085
- const plannerAgentPath = join(configDir, "agents", "swarm-planner.md");
1086
- const workerAgentPath = join(configDir, "agents", "swarm-worker.md");
1107
+ const commandPath = join(configDir, "command", "swarm.md");
1108
+ const plannerAgentPath = join(configDir, "agent", "swarm-planner.md");
1109
+ const workerAgentPath = join(configDir, "agent", "swarm-worker.md");
1087
1110
 
1088
1111
  console.log(yellow(BANNER));
1089
1112
  console.log(dim(" " + TAGLINE + " v" + VERSION));
@@ -1180,8 +1203,14 @@ ${cyan("Commands:")}
1180
1203
  swarm config Show paths to generated config files
1181
1204
  swarm update Update to latest version
1182
1205
  swarm version Show version and banner
1206
+ swarm tool Execute a tool (for plugin wrapper)
1183
1207
  swarm help Show this help
1184
1208
 
1209
+ ${cyan("Tool Execution:")}
1210
+ swarm tool --list List all available tools
1211
+ swarm tool <name> Execute tool with no args
1212
+ swarm tool <name> --json '<args>' Execute tool with JSON args
1213
+
1185
1214
  ${cyan("Usage in OpenCode:")}
1186
1215
  /swarm "Add user authentication with OAuth"
1187
1216
  @swarm-planner "Decompose this into parallel tasks"
@@ -1189,9 +1218,9 @@ ${cyan("Usage in OpenCode:")}
1189
1218
 
1190
1219
  ${cyan("Customization:")}
1191
1220
  Edit the generated files to customize behavior:
1192
- ${dim("~/.config/opencode/commands/swarm.md")} - /swarm command prompt
1193
- ${dim("~/.config/opencode/agents/swarm-planner.md")} - @swarm-planner (coordinator)
1194
- ${dim("~/.config/opencode/agents/swarm-worker.md")} - @swarm-worker (fast executor)
1221
+ ${dim("~/.config/opencode/command/swarm.md")} - /swarm command prompt
1222
+ ${dim("~/.config/opencode/agent/swarm-planner.md")} - @swarm-planner (coordinator)
1223
+ ${dim("~/.config/opencode/agent/swarm-worker.md")} - @swarm-worker (fast executor)
1195
1224
  ${dim("~/.config/opencode/plugin/swarm.ts")} - Plugin loader
1196
1225
 
1197
1226
  ${dim("Docs: https://github.com/joelhooks/opencode-swarm-plugin")}
@@ -1202,6 +1231,150 @@ ${dim("Docs: https://github.com/joelhooks/opencode-swarm-plugin")}
1202
1231
  if (updateInfo) showUpdateNotification(updateInfo);
1203
1232
  }
1204
1233
 
1234
+ // ============================================================================
1235
+ // Tool Execution (for plugin wrapper)
1236
+ // ============================================================================
1237
+
1238
+ /**
1239
+ * Execute a tool by name with JSON args
1240
+ *
1241
+ * This is the bridge between the plugin wrapper and the actual tool implementations.
1242
+ * The plugin wrapper shells out to `swarm tool <name> --json '<args>'` and this
1243
+ * function executes the tool and returns JSON.
1244
+ *
1245
+ * Exit codes:
1246
+ * - 0: Success
1247
+ * - 1: Tool execution error (error details in JSON output)
1248
+ * - 2: Unknown tool name
1249
+ * - 3: Invalid JSON args
1250
+ */
1251
+ async function executeTool(toolName: string, argsJson?: string) {
1252
+ // Lazy import to avoid loading all tools on every CLI invocation
1253
+ const { allTools } = await import("../src/index");
1254
+
1255
+ // Validate tool name
1256
+ if (!(toolName in allTools)) {
1257
+ const availableTools = Object.keys(allTools).sort();
1258
+ console.log(
1259
+ JSON.stringify({
1260
+ success: false,
1261
+ error: {
1262
+ code: "UNKNOWN_TOOL",
1263
+ message: `Unknown tool: ${toolName}`,
1264
+ available_tools: availableTools,
1265
+ },
1266
+ }),
1267
+ );
1268
+ process.exit(2);
1269
+ }
1270
+
1271
+ // Parse args
1272
+ let args: Record<string, unknown> = {};
1273
+ if (argsJson) {
1274
+ try {
1275
+ args = JSON.parse(argsJson);
1276
+ } catch (e) {
1277
+ console.log(
1278
+ JSON.stringify({
1279
+ success: false,
1280
+ error: {
1281
+ code: "INVALID_JSON",
1282
+ message: `Invalid JSON args: ${e instanceof Error ? e.message : String(e)}`,
1283
+ raw_input: argsJson.slice(0, 200),
1284
+ },
1285
+ }),
1286
+ );
1287
+ process.exit(3);
1288
+ }
1289
+ }
1290
+
1291
+ // Create mock context for tools that need sessionID
1292
+ // This mimics what OpenCode provides to plugins
1293
+ const mockContext = {
1294
+ sessionID: process.env.OPENCODE_SESSION_ID || `cli-${Date.now()}`,
1295
+ messageID: process.env.OPENCODE_MESSAGE_ID || `msg-${Date.now()}`,
1296
+ agent: process.env.OPENCODE_AGENT || "cli",
1297
+ abort: new AbortController().signal,
1298
+ };
1299
+
1300
+ // Get the tool
1301
+ const toolDef = allTools[toolName as keyof typeof allTools];
1302
+
1303
+ // Execute tool
1304
+ // Note: We cast args to any because the CLI accepts arbitrary JSON
1305
+ // The tool's internal Zod validation will catch type errors
1306
+ try {
1307
+ const result = await toolDef.execute(args as any, mockContext);
1308
+
1309
+ // If result is already valid JSON, try to parse and re-wrap it
1310
+ // Otherwise wrap the string result
1311
+ try {
1312
+ const parsed = JSON.parse(result);
1313
+ // If it's already a success/error response, pass through
1314
+ if (typeof parsed === "object" && "success" in parsed) {
1315
+ console.log(JSON.stringify(parsed));
1316
+ } else {
1317
+ console.log(JSON.stringify({ success: true, data: parsed }));
1318
+ }
1319
+ } catch {
1320
+ // Result is a plain string, wrap it
1321
+ console.log(JSON.stringify({ success: true, data: result }));
1322
+ }
1323
+ process.exit(0);
1324
+ } catch (error) {
1325
+ console.log(
1326
+ JSON.stringify({
1327
+ success: false,
1328
+ error: {
1329
+ code: error instanceof Error ? error.name : "TOOL_ERROR",
1330
+ message: error instanceof Error ? error.message : String(error),
1331
+ details:
1332
+ error instanceof Error && "zodError" in error
1333
+ ? (error as { zodError?: unknown }).zodError
1334
+ : undefined,
1335
+ },
1336
+ }),
1337
+ );
1338
+ process.exit(1);
1339
+ }
1340
+ }
1341
+
1342
+ /**
1343
+ * List all available tools
1344
+ */
1345
+ async function listTools() {
1346
+ const { allTools } = await import("../src/index");
1347
+ const tools = Object.keys(allTools).sort();
1348
+
1349
+ console.log(yellow(BANNER));
1350
+ console.log(dim(" " + TAGLINE + " v" + VERSION));
1351
+ console.log();
1352
+ console.log(cyan("Available tools:") + ` (${tools.length} total)`);
1353
+ console.log();
1354
+
1355
+ // Group by prefix
1356
+ const groups: Record<string, string[]> = {};
1357
+ for (const tool of tools) {
1358
+ const prefix = tool.split("_")[0];
1359
+ if (!groups[prefix]) groups[prefix] = [];
1360
+ groups[prefix].push(tool);
1361
+ }
1362
+
1363
+ for (const [prefix, toolList] of Object.entries(groups)) {
1364
+ console.log(green(` ${prefix}:`));
1365
+ for (const t of toolList) {
1366
+ console.log(` ${t}`);
1367
+ }
1368
+ console.log();
1369
+ }
1370
+
1371
+ console.log(dim("Usage: swarm tool <name> [--json '<args>']"));
1372
+ console.log(dim("Example: swarm tool beads_ready"));
1373
+ console.log(
1374
+ dim('Example: swarm tool beads_create --json \'{"title": "Fix bug"}\''),
1375
+ );
1376
+ }
1377
+
1205
1378
  // ============================================================================
1206
1379
  // Main
1207
1380
  // ============================================================================
@@ -1224,6 +1397,19 @@ switch (command) {
1224
1397
  case "update":
1225
1398
  await update();
1226
1399
  break;
1400
+ case "tool": {
1401
+ const toolName = process.argv[3];
1402
+ if (!toolName || toolName === "--list" || toolName === "-l") {
1403
+ await listTools();
1404
+ } else {
1405
+ // Look for --json flag
1406
+ const jsonFlagIndex = process.argv.indexOf("--json");
1407
+ const argsJson =
1408
+ jsonFlagIndex !== -1 ? process.argv[jsonFlagIndex + 1] : undefined;
1409
+ await executeTool(toolName, argsJson);
1410
+ }
1411
+ break;
1412
+ }
1227
1413
  case "version":
1228
1414
  case "--version":
1229
1415
  case "-v":
package/dist/index.js CHANGED
@@ -22590,6 +22590,15 @@ async function getRateLimiter() {
22590
22590
  }
22591
22591
 
22592
22592
  // src/agent-mail.ts
22593
+ import {
22594
+ existsSync as existsSync2,
22595
+ mkdirSync as mkdirSync2,
22596
+ readFileSync,
22597
+ writeFileSync,
22598
+ unlinkSync
22599
+ } from "fs";
22600
+ import { join as join2 } from "path";
22601
+ import { tmpdir } from "os";
22593
22602
  var AGENT_MAIL_URL = "http://127.0.0.1:8765";
22594
22603
  var DEFAULT_TTL_SECONDS = 3600;
22595
22604
  var MAX_INBOX_LIMIT = 5;
@@ -22605,6 +22614,34 @@ var RECOVERY_CONFIG = {
22605
22614
  restartCooldownMs: 30000,
22606
22615
  enabled: process.env.OPENCODE_AGENT_MAIL_AUTO_RESTART !== "false"
22607
22616
  };
22617
+ var SESSION_STATE_DIR = process.env.SWARM_STATE_DIR || join2(tmpdir(), "swarm-sessions");
22618
+ function getSessionStatePath(sessionID) {
22619
+ const safeID = sessionID.replace(/[^a-zA-Z0-9_-]/g, "_");
22620
+ return join2(SESSION_STATE_DIR, `${safeID}.json`);
22621
+ }
22622
+ function loadSessionState(sessionID) {
22623
+ const path = getSessionStatePath(sessionID);
22624
+ try {
22625
+ if (existsSync2(path)) {
22626
+ const data = readFileSync(path, "utf-8");
22627
+ return JSON.parse(data);
22628
+ }
22629
+ } catch (error45) {
22630
+ console.warn(`[agent-mail] Could not load session state: ${error45}`);
22631
+ }
22632
+ return null;
22633
+ }
22634
+ function saveSessionState(sessionID, state) {
22635
+ try {
22636
+ if (!existsSync2(SESSION_STATE_DIR)) {
22637
+ mkdirSync2(SESSION_STATE_DIR, { recursive: true });
22638
+ }
22639
+ const path = getSessionStatePath(sessionID);
22640
+ writeFileSync(path, JSON.stringify(state, null, 2));
22641
+ } catch (error45) {
22642
+ console.warn(`[agent-mail] Could not save session state: ${error45}`);
22643
+ }
22644
+ }
22608
22645
  var sessionStates = new Map;
22609
22646
 
22610
22647
  class AgentMailError extends Error {
@@ -22908,7 +22945,13 @@ async function mcpCall(toolName, args) {
22908
22945
  throw lastError || new Error("Unknown error in mcpCall");
22909
22946
  }
22910
22947
  function requireState(sessionID) {
22911
- const state = sessionStates.get(sessionID);
22948
+ let state = sessionStates.get(sessionID);
22949
+ if (!state) {
22950
+ state = loadSessionState(sessionID) ?? undefined;
22951
+ if (state) {
22952
+ sessionStates.set(sessionID, state);
22953
+ }
22954
+ }
22912
22955
  if (!state) {
22913
22956
  throw new AgentMailNotInitializedError;
22914
22957
  }
@@ -22916,6 +22959,7 @@ function requireState(sessionID) {
22916
22959
  }
22917
22960
  function setState(sessionID, state) {
22918
22961
  sessionStates.set(sessionID, state);
22962
+ saveSessionState(sessionID, state);
22919
22963
  }
22920
22964
  var agentmail_init = tool({
22921
22965
  description: "Initialize Agent Mail session (ensure project + register agent)",
@@ -25554,6 +25598,12 @@ var SwarmPlugin = async (input) => {
25554
25598
  };
25555
25599
  };
25556
25600
  var src_default = SwarmPlugin;
25601
+ var allTools = {
25602
+ ...beadsTools,
25603
+ ...agentMailTools,
25604
+ ...structuredTools,
25605
+ ...swarmTools
25606
+ };
25557
25607
  export {
25558
25608
  withToolFallback,
25559
25609
  warnMissingTool,
@@ -25592,6 +25642,7 @@ export {
25592
25642
  beads_create,
25593
25643
  beads_close,
25594
25644
  beadsTools,
25645
+ allTools,
25595
25646
  agentMailTools,
25596
25647
  WeightedEvaluationSchema,
25597
25648
  WeightedCriterionEvaluationSchema,
package/dist/plugin.js CHANGED
@@ -22564,6 +22564,15 @@ async function getRateLimiter() {
22564
22564
  }
22565
22565
 
22566
22566
  // src/agent-mail.ts
22567
+ import {
22568
+ existsSync as existsSync2,
22569
+ mkdirSync as mkdirSync2,
22570
+ readFileSync,
22571
+ writeFileSync,
22572
+ unlinkSync
22573
+ } from "fs";
22574
+ import { join as join2 } from "path";
22575
+ import { tmpdir } from "os";
22567
22576
  var AGENT_MAIL_URL = "http://127.0.0.1:8765";
22568
22577
  var DEFAULT_TTL_SECONDS = 3600;
22569
22578
  var MAX_INBOX_LIMIT = 5;
@@ -22579,6 +22588,34 @@ var RECOVERY_CONFIG = {
22579
22588
  restartCooldownMs: 30000,
22580
22589
  enabled: process.env.OPENCODE_AGENT_MAIL_AUTO_RESTART !== "false"
22581
22590
  };
22591
+ var SESSION_STATE_DIR = process.env.SWARM_STATE_DIR || join2(tmpdir(), "swarm-sessions");
22592
+ function getSessionStatePath(sessionID) {
22593
+ const safeID = sessionID.replace(/[^a-zA-Z0-9_-]/g, "_");
22594
+ return join2(SESSION_STATE_DIR, `${safeID}.json`);
22595
+ }
22596
+ function loadSessionState(sessionID) {
22597
+ const path = getSessionStatePath(sessionID);
22598
+ try {
22599
+ if (existsSync2(path)) {
22600
+ const data = readFileSync(path, "utf-8");
22601
+ return JSON.parse(data);
22602
+ }
22603
+ } catch (error45) {
22604
+ console.warn(`[agent-mail] Could not load session state: ${error45}`);
22605
+ }
22606
+ return null;
22607
+ }
22608
+ function saveSessionState(sessionID, state) {
22609
+ try {
22610
+ if (!existsSync2(SESSION_STATE_DIR)) {
22611
+ mkdirSync2(SESSION_STATE_DIR, { recursive: true });
22612
+ }
22613
+ const path = getSessionStatePath(sessionID);
22614
+ writeFileSync(path, JSON.stringify(state, null, 2));
22615
+ } catch (error45) {
22616
+ console.warn(`[agent-mail] Could not save session state: ${error45}`);
22617
+ }
22618
+ }
22582
22619
  var sessionStates = new Map;
22583
22620
 
22584
22621
  class AgentMailError extends Error {
@@ -22882,7 +22919,13 @@ async function mcpCall(toolName, args) {
22882
22919
  throw lastError || new Error("Unknown error in mcpCall");
22883
22920
  }
22884
22921
  function requireState(sessionID) {
22885
- const state = sessionStates.get(sessionID);
22922
+ let state = sessionStates.get(sessionID);
22923
+ if (!state) {
22924
+ state = loadSessionState(sessionID) ?? undefined;
22925
+ if (state) {
22926
+ sessionStates.set(sessionID, state);
22927
+ }
22928
+ }
22886
22929
  if (!state) {
22887
22930
  throw new AgentMailNotInitializedError;
22888
22931
  }
@@ -22890,6 +22933,7 @@ function requireState(sessionID) {
22890
22933
  }
22891
22934
  function setState(sessionID, state) {
22892
22935
  sessionStates.set(sessionID, state);
22936
+ saveSessionState(sessionID, state);
22893
22937
  }
22894
22938
  var agentmail_init = tool({
22895
22939
  description: "Initialize Agent Mail session (ensure project + register agent)",
@@ -25203,6 +25247,12 @@ var SwarmPlugin = async (input) => {
25203
25247
  }
25204
25248
  };
25205
25249
  };
25250
+ var allTools = {
25251
+ ...beadsTools,
25252
+ ...agentMailTools,
25253
+ ...structuredTools,
25254
+ ...swarmTools
25255
+ };
25206
25256
  export {
25207
25257
  SwarmPlugin
25208
25258
  };