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.
- package/.beads/issues.jsonl +9 -0
- package/dist/index.js +326 -26
- package/dist/plugin.js +325 -26
- package/package.json +1 -1
- package/src/agent-mail.ts +184 -32
- package/src/learning.ts +277 -0
- package/src/swarm.ts +176 -1
package/.beads/issues.jsonl
CHANGED
|
@@ -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:
|
|
22636
|
-
restartCooldownMs:
|
|
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
|
-
|
|
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
|
|
23011
|
-
|
|
23012
|
-
|
|
23013
|
-
|
|
23014
|
-
|
|
23015
|
-
|
|
23016
|
-
|
|
23017
|
-
|
|
23018
|
-
|
|
23019
|
-
|
|
23020
|
-
|
|
23021
|
-
|
|
23022
|
-
|
|
23023
|
-
|
|
23024
|
-
|
|
23025
|
-
|
|
23026
|
-
|
|
23027
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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"]);
|