opencode-swarm-plugin 0.12.6 → 0.12.8

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.
@@ -466,6 +466,13 @@
466
466
  {"id":"opencode-swarm-plugin-97yt8","title":"Query test bead","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-10T09:06:06.460876-08:00","updated_at":"2025-12-10T09:06:10.054925-08:00","closed_at":"2025-12-10T09:06:10.054925-08:00"}
467
467
  {"id":"opencode-swarm-plugin-98oh","title":"Thread link test bead","description":"[thread:test-thread-456]","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T09:09:32.231853-08:00","updated_at":"2025-12-08T09:09:33.887506-08:00","closed_at":"2025-12-08T09:09:33.887506-08:00"}
468
468
  {"id":"opencode-swarm-plugin-99kl","title":"Test bug with priority","description":"This is a critical bug","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-12-08T08:25:09.19481-08:00","updated_at":"2025-12-08T08:25:11.989888-08:00","closed_at":"2025-12-08T08:25:11.989888-08:00"}
469
+ {"id":"opencode-swarm-plugin-9bwp7","title":"Swarm Plugin Improvements from AI Agent Pattern Research","description":"Improvements derived from PDF library research (Patterns for Building AI Agents, Principles of Building AI Agents). Focus on context engineering, error handling, and coordination patterns.","status":"open","priority":1,"issue_type":"epic","created_at":"2025-12-10T10:02:46.552187-08:00","updated_at":"2025-12-10T10:02:46.552187-08:00"}
470
+ {"id":"opencode-swarm-plugin-9bwp7.1","title":"Add swarm_compress_context tool for inter-subtask context pruning","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-10T10:02:46.602046-08:00","updated_at":"2025-12-10T10:09:07.1119-08:00","closed_at":"2025-12-10T10:09:07.1119-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-9bwp7.1","depends_on_id":"opencode-swarm-plugin-9bwp7","type":"parent-child","created_at":"2025-12-10T10:02:46.603062-08:00","created_by":"daemon"}]}
471
+ {"id":"opencode-swarm-plugin-9bwp7.2","title":"Add error accumulator that feeds errors into retry prompts","description":"","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-10T10:02:46.646473-08:00","updated_at":"2025-12-10T10:14:05.802245-08:00","closed_at":"2025-12-10T10:14:05.802245-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-9bwp7.2","depends_on_id":"opencode-swarm-plugin-9bwp7","type":"parent-child","created_at":"2025-12-10T10:02:46.647689-08:00","created_by":"daemon"}]}
472
+ {"id":"opencode-swarm-plugin-9bwp7.3","title":"Add failure mode taxonomy to swarm_record_outcome","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-10T10:02:46.693562-08:00","updated_at":"2025-12-10T10:02:46.693562-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-9bwp7.3","depends_on_id":"opencode-swarm-plugin-9bwp7","type":"parent-child","created_at":"2025-12-10T10:02:46.695053-08:00","created_by":"daemon"}]}
473
+ {"id":"opencode-swarm-plugin-9bwp7.4","title":"Add swarm_broadcast for mid-task context sharing between agents","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-10T10:02:46.743428-08:00","updated_at":"2025-12-10T10:02:46.743428-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-9bwp7.4","depends_on_id":"opencode-swarm-plugin-9bwp7","type":"parent-child","created_at":"2025-12-10T10:02:46.744327-08:00","created_by":"daemon"}]}
474
+ {"id":"opencode-swarm-plugin-9bwp7.5","title":"Restructure SUBTASK_PROMPT with explicit context sections","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-10T10:02:46.790385-08:00","updated_at":"2025-12-10T10:02:46.790385-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-9bwp7.5","depends_on_id":"opencode-swarm-plugin-9bwp7","type":"parent-child","created_at":"2025-12-10T10:02:46.791322-08:00","created_by":"daemon"}]}
475
+ {"id":"opencode-swarm-plugin-9bwp7.6","title":"Audit tool descriptions for semantic clarity","description":"","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-10T10:02:46.835414-08:00","updated_at":"2025-12-10T10:02:46.835414-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-9bwp7.6","depends_on_id":"opencode-swarm-plugin-9bwp7","type":"parent-child","created_at":"2025-12-10T10:02:46.836428-08:00","created_by":"daemon"}]}
469
476
  {"id":"opencode-swarm-plugin-9c51","title":"Thread link test bead","description":"[thread:test-thread-456]","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T08:25:11.111119-08:00","updated_at":"2025-12-08T08:25:12.950452-08:00","closed_at":"2025-12-08T08:25:12.950452-08:00"}
470
477
  {"id":"opencode-swarm-plugin-9c6","title":"Cleanup task","description":"","status":"closed","priority":3,"issue_type":"chore","created_at":"2025-12-07T19:34:52.310497-08:00","updated_at":"2025-12-07T19:34:54.508737-08:00","closed_at":"2025-12-07T19:34:54.508737-08:00"}
471
478
  {"id":"opencode-swarm-plugin-9csf","title":"Limit test bead 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T08:11:39.347968-08:00","updated_at":"2025-12-08T08:11:41.877049-08:00","closed_at":"2025-12-08T08:11:41.877049-08:00"}
@@ -533,6 +540,7 @@
533
540
  {"id":"opencode-swarm-plugin-ai2p","title":"Update test bead","description":"Original description","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T08:22:17.302997-08:00","updated_at":"2025-12-08T08:22:19.488446-08:00","closed_at":"2025-12-08T08:22:19.488446-08:00"}
534
541
  {"id":"opencode-swarm-plugin-ajqu","title":"Query test bead","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-07T19:41:10.735824-08:00","updated_at":"2025-12-07T19:41:13.322607-08:00","closed_at":"2025-12-07T19:41:13.322607-08:00"}
535
542
  {"id":"opencode-swarm-plugin-am6b","title":"Single subtask epic","description":"","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-08T08:11:40.362506-08:00","updated_at":"2025-12-08T08:11:42.362957-08:00","closed_at":"2025-12-08T08:11:42.362957-08:00"}
543
+ {"id":"opencode-swarm-plugin-anlp2","title":"AI Agent Pattern Research: Plugin Improvement Analysis","description":"Research synthesis from PDF library (Patterns for Building AI Agents, Principles of Building AI Agents, Training Complex Cognitive Skills) applied to opencode-swarm-plugin improvements.\n\n## Key Patterns Identified\n\n### 1. Context Engineering (from Patterns for Building AI Agents)\n- **Current gap**: Our SUBTASK_PROMPT is verbose but lacks structured context sections\n- **Pattern**: \"Context engineering is both art and science\" - Karpathy\n- **Improvement**: Add explicit context sections: [IDENTITY] [TASK] [CONSTRAINTS] [TOOLS] [OUTPUT]\n\n### 2. Context Compression (p.37-39)\n- **Current gap**: No automatic context pruning between agent tasks\n- **Pattern**: \"Periodic context compression can prune irrelevant context\"\n- **Improvement**: Add `swarm_compress_context` tool that summarizes completed work\n\n### 3. Feed Errors Into Context (p.40)\n- **Current gap**: Errors are logged but not fed back into agent context\n- **Pattern**: \"Good agents examine and correct errors when something goes wrong\"\n- **Improvement**: Add error accumulator that feeds into retry prompts\n\n### 4. Parallelize Carefully (p.31)\n- **Current gap**: We spawn parallel agents but don't ensure context sharing\n- **Pattern**: \"Ensure subagents can share context along the way\"\n- **Improvement**: Add `swarm_broadcast` for mid-task context updates\n\n### 5. List Failure Modes (p.46)\n- **Current gap**: No classification of why agent failures occur\n- **Pattern**: \"Create classification process for agent failures\"\n- **Improvement**: Add failure taxonomy to swarm_record_outcome\n\n### 6. Tool Calling Best Practices (Principles p.36)\n- **Current gap**: Tool descriptions are functional but not semantic\n- **Pattern**: \"Use semantic naming that matches tool's purpose\"\n- **Improvement**: Audit all tool descriptions for semantic clarity\n\n### 7. Workflows as Tools (Principles p.109)\n- **Current gap**: Swarm is a command, not composable\n- **Pattern**: \"Multi-agent architecture = primitives + arrangement\"\n- **Improvement**: Make swarm_decompose callable from other workflows\n\n### 8. Implicit Feedback Scoring (already implemented)\n- **Current strength**: swarm_record_outcome tracks duration/errors/retries\n- **Enhancement**: Add strategy-specific scoring (file-based vs feature-based)\n\n## Recommended Improvements (Priority Order)\n\n1. **HIGH**: Context compression between subtasks\n2. **HIGH**: Error accumulator for retry prompts \n3. **MEDIUM**: Failure mode taxonomy\n4. **MEDIUM**: Mid-task context broadcast\n5. **LOW**: Semantic tool description audit\n6. **LOW**: Composable workflow primitives","status":"open","priority":1,"issue_type":"task","created_at":"2025-12-10T10:02:37.4266-08:00","updated_at":"2025-12-10T10:02:37.4266-08:00"}
536
544
  {"id":"opencode-swarm-plugin-anuj","title":"New feature request","description":"","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-07T19:57:05.6861-08:00","updated_at":"2025-12-07T19:57:08.122037-08:00","closed_at":"2025-12-07T19:57:08.122037-08:00"}
537
545
  {"id":"opencode-swarm-plugin-aoed","title":"Workflow test epic","description":"","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-07T19:39:30.83873-08:00","updated_at":"2025-12-07T19:39:31.011277-08:00","closed_at":"2025-12-07T19:39:31.011277-08:00"}
538
546
  {"id":"opencode-swarm-plugin-aoed.1","title":"Step 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-07T19:39:30.870528-08:00","updated_at":"2025-12-07T19:39:30.943621-08:00","closed_at":"2025-12-07T19:39:30.943621-08:00","dependencies":[{"issue_id":"opencode-swarm-plugin-aoed.1","depends_on_id":"opencode-swarm-plugin-aoed","type":"parent-child","created_at":"2025-12-07T19:39:30.870831-08:00","created_by":"daemon"}]}
@@ -600,6 +608,7 @@
600
608
  {"id":"opencode-swarm-plugin-c3ut","title":"Single subtask epic","description":"","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-08T08:25:10.733148-08:00","updated_at":"2025-12-08T08:25:12.718944-08:00","closed_at":"2025-12-08T08:25:12.718944-08:00"}
601
609
  {"id":"opencode-swarm-plugin-c3x","title":"Limit test bead 3","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-07T19:37:34.169277-08:00","updated_at":"2025-12-07T19:37:36.225991-08:00","closed_at":"2025-12-07T19:37:36.225991-08:00"}
602
610
  {"id":"opencode-swarm-plugin-c40t","title":"Update test bead","description":"Blocked on dependency","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-08T11:11:23.290111-08:00","updated_at":"2025-12-08T11:11:25.615728-08:00","closed_at":"2025-12-08T11:11:25.615728-08:00"}
611
+ {"id":"opencode-swarm-plugin-c4zjn","title":"Make Agent Mail auto-restart more aggressive","description":"Agent Mail server frequently gets into bad state with \"Server encountered an unexpected error\" but auto-restart is too conservative.\n\nCurrent config:\n- failureThreshold: 2 (needs 2 failures before restart)\n- restartCooldownMs: 30000 (30 second cooldown)\n\nProblems:\n1. First failure doesn't trigger restart, just retries\n2. 30s cooldown is too long when server is truly broken\n3. After restart, availability cache isn't cleared aggressively enough\n\nProposed fix:\n1. Reduce failureThreshold to 1 (restart on first \"unexpected error\")\n2. Reduce restartCooldownMs to 10000 (10 seconds)\n3. Add proactive health check on agentmail_init that triggers restart if server is unhealthy\n4. Clear availability cache after any restart attempt\n5. Add `agentmail_restart` tool for manual restart\n\nFiles: src/agent-mail.ts","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-10T10:14:48.242736-08:00","updated_at":"2025-12-10T10:16:17.53306-08:00","closed_at":"2025-12-10T10:16:17.53306-08:00"}
603
612
  {"id":"opencode-swarm-plugin-c540","title":"Limit test bead 2","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-08T08:22:16.856145-08:00","updated_at":"2025-12-08T08:22:19.29045-08:00","closed_at":"2025-12-08T08:22:19.29045-08:00"}
604
613
  {"id":"opencode-swarm-plugin-c591c","title":"swarm.ts:1774-1777 - File reservation release without verification","description":"swarm.ts:1774-1777 - swarm_complete calls release_file_reservations but doesn't check if it succeeds. If release fails, reservations leak and block other agents. Suggested fix: Check mcpCall result and log/retry on failure.","status":"open","priority":2,"issue_type":"bug","created_at":"2025-12-10T09:06:38.089086-08:00","updated_at":"2025-12-10T09:06:38.089086-08:00"}
605
614
  {"id":"opencode-swarm-plugin-c5l","title":"Bead to close","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-07T19:37:34.574305-08:00","updated_at":"2025-12-07T19:37:34.598352-08:00","closed_at":"2025-12-07T19:37:34.598352-08:00"}
package/dist/index.js CHANGED
@@ -22632,8 +22632,8 @@ var RETRY_CONFIG = {
22632
22632
  jitterPercent: 20
22633
22633
  };
22634
22634
  var RECOVERY_CONFIG = {
22635
- failureThreshold: 2,
22636
- restartCooldownMs: 30000,
22635
+ failureThreshold: 1,
22636
+ restartCooldownMs: 1e4,
22637
22637
  enabled: process.env.OPENCODE_AGENT_MAIL_AUTO_RESTART !== "false"
22638
22638
  };
22639
22639
  var SESSION_STATE_DIR = process.env.SWARM_STATE_DIR || join2(tmpdir(), "swarm-sessions");
@@ -22931,6 +22931,7 @@ async function mcpCallOnce(toolName, args) {
22931
22931
  }
22932
22932
  async function mcpCall(toolName, args) {
22933
22933
  let lastError = null;
22934
+ let restartAttempted = false;
22934
22935
  for (let attempt = 0;attempt <= RETRY_CONFIG.maxRetries; attempt++) {
22935
22936
  if (attempt > 0) {
22936
22937
  const delay = calculateBackoffDelay(attempt);
@@ -22943,13 +22944,28 @@ async function mcpCall(toolName, args) {
22943
22944
  return result;
22944
22945
  } catch (error45) {
22945
22946
  lastError = error45 instanceof Error ? error45 : new Error(String(error45));
22947
+ const errorMessage = lastError.message.toLowerCase();
22946
22948
  consecutiveFailures++;
22947
22949
  const retryable = isRetryableError(error45);
22948
- if (consecutiveFailures >= RECOVERY_CONFIG.failureThreshold && RECOVERY_CONFIG.enabled) {
22950
+ const isUnexpectedError = errorMessage.includes("unexpected error");
22951
+ if (isUnexpectedError && !restartAttempted && RECOVERY_CONFIG.enabled) {
22952
+ console.warn(`[agent-mail] "${toolName}" got unexpected error, restarting server immediately...`);
22953
+ restartAttempted = true;
22954
+ const restarted = await restartServer();
22955
+ if (restarted) {
22956
+ agentMailAvailable = null;
22957
+ consecutiveFailures = 0;
22958
+ await new Promise((resolve) => setTimeout(resolve, 1000));
22959
+ attempt--;
22960
+ continue;
22961
+ }
22962
+ }
22963
+ if (!isUnexpectedError && consecutiveFailures >= RECOVERY_CONFIG.failureThreshold && RECOVERY_CONFIG.enabled && !restartAttempted) {
22949
22964
  console.warn(`[agent-mail] ${consecutiveFailures} consecutive failures, checking server health...`);
22950
22965
  const healthy = await isServerFunctional();
22951
22966
  if (!healthy) {
22952
22967
  console.warn("[agent-mail] Server unhealthy, attempting restart...");
22968
+ restartAttempted = true;
22953
22969
  const restarted = await restartServer();
22954
22970
  if (restarted) {
22955
22971
  agentMailAvailable = null;
@@ -23007,24 +23023,57 @@ var agentmail_init = tool({
23007
23023
  fallback: "Swarm will continue without multi-agent coordination. File conflicts possible if multiple agents active."
23008
23024
  }, null, 2);
23009
23025
  }
23010
- const project = await mcpCall("ensure_project", {
23011
- human_key: args.project_path
23012
- });
23013
- const agent = await mcpCall("register_agent", {
23014
- project_key: args.project_path,
23015
- program: "opencode",
23016
- model: "claude-opus-4",
23017
- name: args.agent_name,
23018
- task_description: args.task_description || ""
23019
- });
23020
- const state = {
23021
- projectKey: args.project_path,
23022
- agentName: agent.name,
23023
- reservations: [],
23024
- startedAt: new Date().toISOString()
23025
- };
23026
- setState(ctx.sessionID, state);
23027
- return JSON.stringify({ project, agent, available: true }, null, 2);
23026
+ const MAX_INIT_RETRIES = 3;
23027
+ let lastError = null;
23028
+ for (let attempt = 1;attempt <= MAX_INIT_RETRIES; attempt++) {
23029
+ try {
23030
+ const project = await mcpCall("ensure_project", {
23031
+ human_key: args.project_path
23032
+ });
23033
+ const agent = await mcpCall("register_agent", {
23034
+ project_key: args.project_path,
23035
+ program: "opencode",
23036
+ model: "claude-opus-4",
23037
+ name: args.agent_name,
23038
+ task_description: args.task_description || ""
23039
+ });
23040
+ const state = {
23041
+ projectKey: args.project_path,
23042
+ agentName: agent.name,
23043
+ reservations: [],
23044
+ startedAt: new Date().toISOString()
23045
+ };
23046
+ setState(ctx.sessionID, state);
23047
+ if (attempt > 1) {
23048
+ console.warn(`[agent-mail] Init succeeded on attempt ${attempt} after restart`);
23049
+ }
23050
+ return JSON.stringify({ project, agent, available: true }, null, 2);
23051
+ } catch (error45) {
23052
+ lastError = error45 instanceof Error ? error45 : new Error(String(error45));
23053
+ const isUnexpectedError = lastError.message.toLowerCase().includes("unexpected error");
23054
+ console.warn(`[agent-mail] Init attempt ${attempt}/${MAX_INIT_RETRIES} failed: ${lastError.message}`);
23055
+ if (isUnexpectedError && attempt < MAX_INIT_RETRIES) {
23056
+ console.warn("[agent-mail] Detected 'unexpected error', restarting server...");
23057
+ const restarted = await restartServer();
23058
+ if (restarted) {
23059
+ agentMailAvailable = null;
23060
+ consecutiveFailures = 0;
23061
+ await new Promise((resolve) => setTimeout(resolve, 1000));
23062
+ continue;
23063
+ }
23064
+ }
23065
+ if (!isUnexpectedError) {
23066
+ break;
23067
+ }
23068
+ }
23069
+ }
23070
+ return JSON.stringify({
23071
+ error: `Agent Mail init failed after ${MAX_INIT_RETRIES} attempts`,
23072
+ available: false,
23073
+ lastError: lastError?.message,
23074
+ hint: "Manually restart Agent Mail: pkill -f agent-mail && agent-mail serve",
23075
+ fallback: "Swarm will continue without multi-agent coordination."
23076
+ }, null, 2);
23028
23077
  }
23029
23078
  });
23030
23079
  var agentmail_send = tool({
@@ -23230,7 +23279,11 @@ var agentmail_health = tool({
23230
23279
  try {
23231
23280
  const response = await fetch(`${AGENT_MAIL_URL}/health/liveness`);
23232
23281
  if (response.ok) {
23233
- return "Agent Mail is running";
23282
+ const functional = await isServerFunctional();
23283
+ if (functional) {
23284
+ return "Agent Mail is running and functional";
23285
+ }
23286
+ return "Agent Mail health OK but MCP not responding - consider restart";
23234
23287
  }
23235
23288
  return `Agent Mail returned status ${response.status}`;
23236
23289
  } catch (error45) {
@@ -23238,6 +23291,41 @@ var agentmail_health = tool({
23238
23291
  }
23239
23292
  }
23240
23293
  });
23294
+ var agentmail_restart = tool({
23295
+ description: "Manually restart Agent Mail server (use when getting 'unexpected error')",
23296
+ args: {
23297
+ force: tool.schema.boolean().optional().describe("Force restart even if server appears healthy (default: false)")
23298
+ },
23299
+ async execute(args) {
23300
+ if (!args.force) {
23301
+ const functional = await isServerFunctional();
23302
+ if (functional) {
23303
+ return JSON.stringify({
23304
+ restarted: false,
23305
+ reason: "Server is functional, no restart needed",
23306
+ hint: "Use force=true to restart anyway"
23307
+ }, null, 2);
23308
+ }
23309
+ }
23310
+ console.warn("[agent-mail] Manual restart requested...");
23311
+ const success2 = await restartServer();
23312
+ agentMailAvailable = null;
23313
+ consecutiveFailures = 0;
23314
+ if (success2) {
23315
+ return JSON.stringify({
23316
+ restarted: true,
23317
+ success: true,
23318
+ message: "Agent Mail server restarted successfully"
23319
+ }, null, 2);
23320
+ }
23321
+ return JSON.stringify({
23322
+ restarted: true,
23323
+ success: false,
23324
+ error: "Restart attempted but server did not come back up",
23325
+ hint: "Check server logs or manually start: agent-mail serve"
23326
+ }, null, 2);
23327
+ }
23328
+ });
23241
23329
  var agentMailTools = {
23242
23330
  agentmail_init,
23243
23331
  agentmail_send,
@@ -23248,7 +23336,8 @@ var agentMailTools = {
23248
23336
  agentmail_release,
23249
23337
  agentmail_ack,
23250
23338
  agentmail_search,
23251
- agentmail_health
23339
+ agentmail_health,
23340
+ agentmail_restart
23252
23341
  };
23253
23342
 
23254
23343
  // src/structured.ts
@@ -23664,6 +23753,24 @@ var CriterionWeightSchema = exports_external.object({
23664
23753
  last_validated: exports_external.string().optional(),
23665
23754
  half_life_days: exports_external.number().positive().default(90)
23666
23755
  });
23756
+ var ErrorTypeSchema = exports_external.enum([
23757
+ "validation",
23758
+ "timeout",
23759
+ "conflict",
23760
+ "tool_failure",
23761
+ "unknown"
23762
+ ]);
23763
+ var ErrorEntrySchema = exports_external.object({
23764
+ id: exports_external.string(),
23765
+ bead_id: exports_external.string(),
23766
+ error_type: ErrorTypeSchema,
23767
+ message: exports_external.string(),
23768
+ stack_trace: exports_external.string().optional(),
23769
+ tool_name: exports_external.string().optional(),
23770
+ timestamp: exports_external.string(),
23771
+ resolved: exports_external.boolean().default(false),
23772
+ context: exports_external.string().optional()
23773
+ });
23667
23774
  var DecompositionStrategySchema = exports_external.enum([
23668
23775
  "file-based",
23669
23776
  "feature-based",
@@ -23753,6 +23860,118 @@ class InMemoryFeedbackStorage {
23753
23860
  }
23754
23861
  }
23755
23862
 
23863
+ class InMemoryErrorStorage {
23864
+ errors = [];
23865
+ async store(entry) {
23866
+ this.errors.push(entry);
23867
+ }
23868
+ async getByBead(beadId) {
23869
+ return this.errors.filter((e) => e.bead_id === beadId);
23870
+ }
23871
+ async getUnresolvedByBead(beadId) {
23872
+ return this.errors.filter((e) => e.bead_id === beadId && !e.resolved);
23873
+ }
23874
+ async markResolved(id) {
23875
+ const error45 = this.errors.find((e) => e.id === id);
23876
+ if (error45) {
23877
+ error45.resolved = true;
23878
+ }
23879
+ }
23880
+ async getAll() {
23881
+ return [...this.errors];
23882
+ }
23883
+ }
23884
+
23885
+ class ErrorAccumulator {
23886
+ storage;
23887
+ constructor(storage) {
23888
+ this.storage = storage ?? new InMemoryErrorStorage;
23889
+ }
23890
+ async recordError(beadId, errorType, message, options) {
23891
+ const entry = {
23892
+ id: `${beadId}-${errorType}-${Date.now()}`,
23893
+ bead_id: beadId,
23894
+ error_type: errorType,
23895
+ message,
23896
+ stack_trace: options?.stack_trace,
23897
+ tool_name: options?.tool_name,
23898
+ timestamp: new Date().toISOString(),
23899
+ resolved: false,
23900
+ context: options?.context
23901
+ };
23902
+ const validated = ErrorEntrySchema.parse(entry);
23903
+ await this.storage.store(validated);
23904
+ return validated;
23905
+ }
23906
+ async getErrors(beadId) {
23907
+ return this.storage.getByBead(beadId);
23908
+ }
23909
+ async getUnresolvedErrors(beadId) {
23910
+ return this.storage.getUnresolvedByBead(beadId);
23911
+ }
23912
+ async resolveError(errorId) {
23913
+ await this.storage.markResolved(errorId);
23914
+ }
23915
+ async getErrorContext(beadId, includeResolved = false) {
23916
+ const errors3 = includeResolved ? await this.getErrors(beadId) : await this.getUnresolvedErrors(beadId);
23917
+ if (errors3.length === 0) {
23918
+ return "";
23919
+ }
23920
+ const byType = errors3.reduce((acc, err) => {
23921
+ const type = err.error_type;
23922
+ if (!acc[type]) {
23923
+ acc[type] = [];
23924
+ }
23925
+ acc[type].push(err);
23926
+ return acc;
23927
+ }, {});
23928
+ const lines = [
23929
+ "## Previous Errors",
23930
+ "",
23931
+ "The following errors were encountered during execution:",
23932
+ ""
23933
+ ];
23934
+ for (const [type, typeErrors] of Object.entries(byType)) {
23935
+ lines.push(`### ${type} (${typeErrors.length} error${typeErrors.length > 1 ? "s" : ""})`);
23936
+ lines.push("");
23937
+ for (const err of typeErrors) {
23938
+ lines.push(`- **${err.message}**`);
23939
+ if (err.context) {
23940
+ lines.push(` - Context: ${err.context}`);
23941
+ }
23942
+ if (err.tool_name) {
23943
+ lines.push(` - Tool: ${err.tool_name}`);
23944
+ }
23945
+ if (err.stack_trace) {
23946
+ lines.push(` - Stack: \`${err.stack_trace.slice(0, 100)}...\``);
23947
+ }
23948
+ lines.push(` - Time: ${new Date(err.timestamp).toLocaleString()}${err.resolved ? " (resolved)" : ""}`);
23949
+ lines.push("");
23950
+ }
23951
+ }
23952
+ lines.push("**Action Required**: Address these errors before proceeding. Consider:");
23953
+ lines.push("- What caused each error?");
23954
+ lines.push("- How can you prevent similar errors?");
23955
+ lines.push("- Are there patterns across error types?");
23956
+ lines.push("");
23957
+ return lines.join(`
23958
+ `);
23959
+ }
23960
+ async getErrorStats(beadId) {
23961
+ const allErrors = await this.getErrors(beadId);
23962
+ const unresolved = await this.getUnresolvedErrors(beadId);
23963
+ const byType = allErrors.reduce((acc, err) => {
23964
+ acc[err.error_type] = (acc[err.error_type] || 0) + 1;
23965
+ return acc;
23966
+ }, {});
23967
+ return {
23968
+ total: allErrors.length,
23969
+ unresolved: unresolved.length,
23970
+ by_type: byType
23971
+ };
23972
+ }
23973
+ }
23974
+
23756
23975
  // src/swarm.ts
23757
23976
  var POSITIVE_MARKERS = [
23758
23977
  "always",
@@ -24163,6 +24382,10 @@ Only modify these files. Need others? Message the coordinator.
24163
24382
  ## Context
24164
24383
  {shared_context}
24165
24384
 
24385
+ {compressed_context}
24386
+
24387
+ {error_context}
24388
+
24166
24389
  ## MANDATORY: Use These Tools
24167
24390
 
24168
24391
  ### Agent Mail - communicate with the swarm
@@ -24196,7 +24419,9 @@ Begin now.`;
24196
24419
  function formatSubtaskPromptV2(params) {
24197
24420
  const fileList = params.files.length > 0 ? params.files.map((f) => `- \`${f}\``).join(`
24198
24421
  `) : "(no specific files - use judgment)";
24199
- return SUBTASK_PROMPT_V2.replace(/{bead_id}/g, params.bead_id).replace(/{epic_id}/g, params.epic_id).replace("{subtask_title}", params.subtask_title).replace("{subtask_description}", params.subtask_description || "(see title)").replace("{file_list}", fileList).replace("{shared_context}", params.shared_context || "(none)");
24422
+ const compressedSection = params.compressed_context ? params.compressed_context : "";
24423
+ const errorSection = params.error_context ? params.error_context : "";
24424
+ return SUBTASK_PROMPT_V2.replace(/{bead_id}/g, params.bead_id).replace(/{epic_id}/g, params.epic_id).replace("{subtask_title}", params.subtask_title).replace("{subtask_description}", params.subtask_description || "(see title)").replace("{file_list}", fileList).replace("{shared_context}", params.shared_context || "(none)").replace("{compressed_context}", compressedSection).replace("{error_context}", errorSection);
24200
24425
  }
24201
24426
  var EVALUATION_PROMPT = `Evaluate the work completed for this subtask.
24202
24427
 
@@ -24902,6 +25127,7 @@ var swarm_record_outcome = tool({
24902
25127
  };
24903
25128
  const validated = OutcomeSignalsSchema.parse(signals);
24904
25129
  const scored = scoreImplicitFeedback(validated, DEFAULT_LEARNING_CONFIG);
25130
+ const errorStats = await globalErrorAccumulator.getErrorStats(args.bead_id);
24905
25131
  const criteriaToScore = args.criteria ?? [
24906
25132
  "type_safe",
24907
25133
  "no_bugs",
@@ -24913,6 +25139,10 @@ var swarm_record_outcome = tool({
24913
25139
  if (args.strategy) {
24914
25140
  event.context = `${event.context || ""} [strategy: ${args.strategy}]`.trim();
24915
25141
  }
25142
+ if (errorStats.total > 0) {
25143
+ const errorSummary = Object.entries(errorStats.by_type).map(([type, count]) => `${type}:${count}`).join(", ");
25144
+ event.context = `${event.context || ""} [errors: ${errorSummary}]`.trim();
25145
+ }
24916
25146
  return event;
24917
25147
  });
24918
25148
  return JSON.stringify({
@@ -24926,13 +25156,16 @@ var swarm_record_outcome = tool({
24926
25156
  }
24927
25157
  },
24928
25158
  feedback_events: feedbackEvents,
25159
+ error_patterns: errorStats,
24929
25160
  summary: {
24930
25161
  feedback_type: scored.type,
24931
25162
  duration_seconds: Math.round(args.duration_ms / 1000),
24932
25163
  error_count: args.error_count ?? 0,
24933
25164
  retry_count: args.retry_count ?? 0,
24934
25165
  success: args.success,
24935
- strategy: args.strategy
25166
+ strategy: args.strategy,
25167
+ accumulated_errors: errorStats.total,
25168
+ unresolved_errors: errorStats.unresolved
24936
25169
  },
24937
25170
  note: "Feedback events should be stored for criterion weight calculation. Use learning.ts functions to apply weights."
24938
25171
  }, null, 2);
@@ -25102,6 +25335,70 @@ var swarm_evaluation_prompt = tool({
25102
25335
  }, null, 2);
25103
25336
  }
25104
25337
  });
25338
+ var globalErrorAccumulator = new ErrorAccumulator;
25339
+ var swarm_accumulate_error = tool({
25340
+ description: "Record an error during subtask execution. Errors feed into retry prompts.",
25341
+ args: {
25342
+ bead_id: tool.schema.string().describe("Bead ID where error occurred"),
25343
+ error_type: tool.schema.enum(["validation", "timeout", "conflict", "tool_failure", "unknown"]).describe("Category of error"),
25344
+ message: tool.schema.string().describe("Human-readable error message"),
25345
+ stack_trace: tool.schema.string().optional().describe("Stack trace for debugging"),
25346
+ tool_name: tool.schema.string().optional().describe("Tool that failed"),
25347
+ context: tool.schema.string().optional().describe("What was happening when error occurred")
25348
+ },
25349
+ async execute(args) {
25350
+ const entry = await globalErrorAccumulator.recordError(args.bead_id, args.error_type, args.message, {
25351
+ stack_trace: args.stack_trace,
25352
+ tool_name: args.tool_name,
25353
+ context: args.context
25354
+ });
25355
+ return JSON.stringify({
25356
+ success: true,
25357
+ error_id: entry.id,
25358
+ bead_id: entry.bead_id,
25359
+ error_type: entry.error_type,
25360
+ message: entry.message,
25361
+ timestamp: entry.timestamp,
25362
+ note: "Error recorded for retry context. Use swarm_get_error_context to retrieve accumulated errors."
25363
+ }, null, 2);
25364
+ }
25365
+ });
25366
+ var swarm_get_error_context = tool({
25367
+ description: "Get accumulated errors for a bead. Returns formatted context for retry prompts.",
25368
+ args: {
25369
+ bead_id: tool.schema.string().describe("Bead ID to get errors for"),
25370
+ include_resolved: tool.schema.boolean().optional().describe("Include resolved errors (default: false)")
25371
+ },
25372
+ async execute(args) {
25373
+ const errorContext = await globalErrorAccumulator.getErrorContext(args.bead_id, args.include_resolved ?? false);
25374
+ const stats = await globalErrorAccumulator.getErrorStats(args.bead_id);
25375
+ return JSON.stringify({
25376
+ bead_id: args.bead_id,
25377
+ error_context: errorContext,
25378
+ stats: {
25379
+ total_errors: stats.total,
25380
+ unresolved: stats.unresolved,
25381
+ by_type: stats.by_type
25382
+ },
25383
+ has_errors: errorContext.length > 0,
25384
+ usage: "Inject error_context into retry prompt using {error_context} placeholder"
25385
+ }, null, 2);
25386
+ }
25387
+ });
25388
+ var swarm_resolve_error = tool({
25389
+ description: "Mark an error as resolved after fixing it. Updates error accumulator state.",
25390
+ args: {
25391
+ error_id: tool.schema.string().describe("Error ID to mark as resolved")
25392
+ },
25393
+ async execute(args) {
25394
+ await globalErrorAccumulator.resolveError(args.error_id);
25395
+ return JSON.stringify({
25396
+ success: true,
25397
+ error_id: args.error_id,
25398
+ resolved: true
25399
+ }, null, 2);
25400
+ }
25401
+ });
25105
25402
  var swarm_init = tool({
25106
25403
  description: "Initialize swarm session and check tool availability. Call at swarm start to see what features are available.",
25107
25404
  args: {
@@ -25163,7 +25460,10 @@ var swarmTools = {
25163
25460
  swarm_subtask_prompt,
25164
25461
  swarm_spawn_subtask,
25165
25462
  swarm_complete_subtask,
25166
- swarm_evaluation_prompt
25463
+ swarm_evaluation_prompt,
25464
+ swarm_accumulate_error,
25465
+ swarm_get_error_context,
25466
+ swarm_resolve_error
25167
25467
  };
25168
25468
  // src/anti-patterns.ts
25169
25469
  var PatternKindSchema = exports_external.enum(["pattern", "anti_pattern"]);