opencode-swarm-plugin 0.12.4 → 0.12.7

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.
@@ -2,282 +2,117 @@
2
2
  description: Decompose task into parallel subtasks and coordinate agents
3
3
  ---
4
4
 
5
- You are a swarm coordinator. Take a complex task, break it into beads, and unleash parallel agents.
5
+ You are a swarm coordinator. Decompose the task into beads and spawn parallel agents.
6
6
 
7
- ## Usage
7
+ ## Task
8
8
 
9
- ```
10
- /swarm <task description or bead-id>
11
- /swarm --to-main <task> # Skip PR, push directly to main (use sparingly)
12
- /swarm --no-sync <task> # Skip mid-task context sync (for simple independent tasks)
13
- ```
14
-
15
- **Default behavior: Feature branch + PR with context sync.** All swarm work goes to a feature branch, agents share context mid-task, and creates a PR for review.
16
-
17
- ## Step 1: Initialize Session
18
-
19
- Use the plugin's agent-mail tools to register:
20
-
21
- ```
22
- agentmail_init with project_path=$PWD, task_description="Swarm coordinator: <task>"
23
- ```
24
-
25
- This returns your agent name and session state. Remember it.
26
-
27
- ## Step 2: Create Feature Branch
28
-
29
- **CRITICAL: Never push directly to main.**
30
-
31
- ```bash
32
- # Create branch from bead ID or task name
33
- git checkout -b swarm/<bead-id> # e.g., swarm/trt-buddy-d7d
34
- # Or for ad-hoc tasks:
35
- git checkout -b swarm/<short-description> # e.g., swarm/contextual-checkins
36
-
37
- git push -u origin HEAD
38
- ```
39
-
40
- ## Step 3: Understand the Task
41
-
42
- If given a bead-id:
9
+ $ARGUMENTS
43
10
 
44
- ```
45
- beads_query with id=<bead-id>
46
- ```
11
+ ## Flags (parse from task above)
47
12
 
48
- If given a description, analyze it to understand scope.
13
+ - `--to-main` - Push directly to main, skip PR
14
+ - `--no-sync` - Skip mid-task context sharing
49
15
 
50
- ## Step 4: Select Strategy & Decompose
16
+ **Default: Feature branch + PR with context sync.**
51
17
 
52
- ### Option A: Use the Planner Agent (Recommended)
18
+ ## Workflow
53
19
 
54
- Spawn the `@swarm-planner` agent to handle decomposition:
20
+ ### 1. Initialize
55
21
 
56
22
  ```
57
- Task(
58
- subagent_type="general",
59
- description="Plan swarm decomposition",
60
- prompt="You are @swarm-planner. Decompose this task: <task description>. Use swarm_select_strategy and swarm_plan_prompt to guide your decomposition. Return ONLY valid BeadTree JSON."
61
- )
23
+ agentmail_init(project_path="$PWD", task_description="Swarm: <task summary>")
62
24
  ```
63
25
 
64
- ### Option B: Manual Decomposition
65
-
66
- 1. **Select strategy**:
26
+ ### 2. Create Feature Branch (unless --to-main)
67
27
 
68
- ```
69
- swarm_select_strategy with task="<task description>"
70
- ```
71
-
72
- 2. **Get planning prompt**:
73
-
74
- ```
75
- swarm_plan_prompt with task="<task description>", strategy="<selected or auto>"
28
+ ```bash
29
+ git checkout -b swarm/<short-task-name>
30
+ git push -u origin HEAD
76
31
  ```
77
32
 
78
- 3. **Create decomposition** following the prompt guidelines
33
+ ### 3. Decompose Task
79
34
 
80
- 4. **Validate**:
35
+ Use strategy selection and planning:
81
36
 
82
37
  ```
83
- swarm_validate_decomposition with response="<your BeadTree JSON>"
38
+ swarm_select_strategy(task="<the task>")
39
+ swarm_plan_prompt(task="<the task>", strategy="<auto or selected>")
84
40
  ```
85
41
 
86
- ### Create Beads
87
-
88
- Once you have a valid BeadTree:
42
+ Follow the prompt to create a BeadTree, then validate:
89
43
 
90
44
  ```
91
- beads_create_epic with epic_title="<parent task>", subtasks=[{title, description, files, priority}...]
45
+ swarm_validate_decomposition(response="<your BeadTree JSON>")
92
46
  ```
93
47
 
94
- **Decomposition rules:**
95
-
96
- - Each bead should be completable by one agent
97
- - Beads should be independent (parallelizable) where possible
98
- - If there are dependencies, order them in the subtasks array
99
- - Aim for 3-7 beads per swarm (too few = not parallel, too many = coordination overhead)
100
-
101
- ## Step 5: Reserve Files
102
-
103
- For each subtask, reserve the files it will touch:
48
+ ### 4. Create Beads
104
49
 
105
50
  ```
106
- agentmail_reserve with paths=[<files>], reason="<bead-id>: <brief description>"
51
+ beads_create_epic(epic_title="<task>", subtasks=[{title, files, priority}...])
107
52
  ```
108
53
 
109
- **Conflict prevention:**
110
-
111
- - No two agents should edit the same file
112
- - If overlap exists, merge beads or sequence them
113
-
114
- ## Step 6: Spawn the Swarm
115
-
116
- **CRITICAL: Spawn ALL agents in a SINGLE message with multiple Task calls.**
117
-
118
- Use the prompt generator for each subtask:
54
+ Rules:
119
55
 
120
- ```
121
- swarm_spawn_subtask with bead_id="<bead-id>", epic_id="<epic-id>", subtask_title="<title>", subtask_description="<description>", files=[<files>], shared_context="Branch: swarm/<id>, sync_enabled: true"
122
- ```
56
+ - Each bead completable by one agent
57
+ - Independent where possible (parallelizable)
58
+ - 3-7 beads per swarm
123
59
 
124
- Then spawn agents with the generated prompts:
60
+ ### 5. Reserve Files
125
61
 
126
62
  ```
127
- Task(
128
- subagent_type="general",
129
- description="Swarm worker: <bead-title>",
130
- prompt="<output from swarm_spawn_subtask>"
131
- )
63
+ agentmail_reserve(paths=[<files>], reason="<bead-id>: <description>")
132
64
  ```
133
65
 
134
- Spawn ALL agents in parallel in a single response.
135
-
136
- ## Step 7: Monitor Progress (unless --no-sync)
66
+ No two agents should edit the same file.
137
67
 
138
- Check swarm status:
68
+ ### 6. Spawn Agents
139
69
 
140
- ```
141
- swarm_status with epic_id="<parent-bead-id>"
142
- ```
70
+ **CRITICAL: Spawn ALL in a SINGLE message with multiple Task calls.**
143
71
 
144
- Monitor inbox for progress updates:
72
+ For each subtask:
145
73
 
146
74
  ```
147
- agentmail_inbox
75
+ swarm_spawn_subtask(bead_id="<id>", epic_id="<epic>", subtask_title="<title>", files=[...])
148
76
  ```
149
77
 
150
- **When you receive progress updates:**
151
-
152
- 1. **Review decisions made** - Are agents making compatible choices?
153
- 2. **Check for pattern conflicts** - Different approaches to the same problem?
154
- 3. **Identify shared concerns** - Common blockers or discoveries?
155
-
156
- **If you spot incompatibilities, broadcast shared context:**
78
+ Then spawn:
157
79
 
158
80
  ```
159
- agentmail_send with to=["*"], subject="Coordinator Update", body="<guidance>", thread_id="<epic-id>", importance="high"
81
+ Task(subagent_type="swarm-worker", description="<bead-title>", prompt="<from swarm_spawn_subtask>")
160
82
  ```
161
83
 
162
- ## Step 8: Collect Results
163
-
164
- When agents complete, they send completion messages. Summarize the thread:
84
+ ### 7. Monitor (unless --no-sync)
165
85
 
166
86
  ```
167
- agentmail_summarize_thread with thread_id="<epic-id>"
87
+ swarm_status(epic_id="<epic-id>")
88
+ agentmail_inbox()
168
89
  ```
169
90
 
170
- ## Step 9: Complete Swarm
171
-
172
- Use the swarm completion tool:
91
+ If incompatibilities spotted, broadcast:
173
92
 
174
93
  ```
175
- swarm_complete with project_key=$PWD, agent_name=<YOUR_NAME>, bead_id="<epic-id>", summary="<what was accomplished>", files_touched=[<all files>]
94
+ agentmail_send(to=["*"], subject="Coordinator Update", body="<guidance>", importance="high")
176
95
  ```
177
96
 
178
- This:
179
-
180
- - Runs [UBS (Ultimate Bug Scanner)](https://github.com/Dicklesworthstone/ultimate_bug_scanner) on touched files to detect bugs before completion
181
- - Releases file reservations
182
- - Closes the bead
183
- - Records outcome for learning
184
-
185
- > **Note:** UBS is optional but recommended. If not installed, swarm completion proceeds with a warning that manual review is advised. Install via:
186
- > ```bash
187
- > curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/ultimate_bug_scanner/master/install.sh" | bash
188
- > ```
189
- > See the [UBS repo](https://github.com/Dicklesworthstone/ultimate_bug_scanner) for more options (Docker, Nix, etc.).
190
-
191
- Then sync beads:
97
+ ### 8. Complete
192
98
 
193
99
  ```
194
- beads_sync
100
+ swarm_complete(project_key="$PWD", agent_name="<your-name>", bead_id="<epic-id>", summary="<done>", files_touched=[...])
101
+ beads_sync()
195
102
  ```
196
103
 
197
- ## Step 10: Create PR
104
+ ### 9. Create PR (unless --to-main)
198
105
 
199
106
  ```bash
200
- gh pr create --title "feat: <epic title>" --body "$(cat <<'EOF'
201
- ## Summary
202
- <1-3 bullet points from swarm results>
203
-
204
- ## Beads Completed
205
- - <bead-id>: <summary>
206
- - <bead-id>: <summary>
207
-
208
- ## Files Changed
209
- <aggregate list>
210
-
211
- ## Testing
212
- - [ ] Type check passes
213
- - [ ] Tests pass (if applicable)
214
- EOF
215
- )"
216
- ```
217
-
218
- Report summary:
219
-
220
- ```markdown
221
- ## Swarm Complete: <task>
222
-
223
- ### PR: #<number>
224
-
225
- ### Agents Spawned: N
226
-
227
- ### Beads Closed: N
228
-
229
- ### Work Completed
230
-
231
- - [bead-id]: [summary]
232
-
233
- ### Files Changed
234
-
235
- - [aggregate list]
107
+ gh pr create --title "feat: <epic title>" --body "## Summary\n<bullets>\n\n## Beads\n<list>"
236
108
  ```
237
109
 
238
- ## Failure Handling
239
-
240
- If an agent fails:
241
-
242
- - Check its messages: `agentmail_inbox`
243
- - The bead remains in-progress
244
- - Manually investigate or re-spawn
245
-
246
- If file conflicts occur:
247
-
248
- - Agent Mail reservations should prevent this
249
- - If it happens, one agent needs to wait
250
-
251
- ## Direct-to-Main Mode (--to-main)
252
-
253
- Only use when explicitly requested. Skips branch/PR:
254
-
255
- - Trivial fixes across many files
256
- - Automated migrations with high confidence
257
- - User explicitly says "push to main"
258
-
259
- ## No-Sync Mode (--no-sync)
260
-
261
- Skip mid-task context sharing when tasks are truly independent:
262
-
263
- - Simple mechanical changes (find/replace, formatting, lint fixes)
264
- - Tasks with zero integration points
265
- - Completely separate feature areas with no shared types
266
-
267
- In this mode:
268
-
269
- - Agents skip the mid-task progress message
270
- - Coordinator skips Step 7 (monitoring)
271
- - Faster execution, less coordination overhead
272
-
273
- **Default is sync ON** - prefer sharing context. Use `--no-sync` deliberately.
274
-
275
110
  ## Strategy Reference
276
111
 
277
- | Strategy | Best For | Auto-Detected Keywords |
278
- | ----------------- | --------------------------- | ---------------------------------------------- |
279
- | **file-based** | Refactoring, migrations | refactor, migrate, rename, update all, convert |
280
- | **feature-based** | New features, functionality | add, implement, build, create, feature, new |
281
- | **risk-based** | Bug fixes, security | fix, bug, security, critical, urgent, hotfix |
112
+ | Strategy | Best For | Keywords |
113
+ | ------------- | ----------------------- | ------------------------------------- |
114
+ | file-based | Refactoring, migrations | refactor, migrate, rename, update all |
115
+ | feature-based | New features | add, implement, build, create, new |
116
+ | risk-based | Bug fixes, security | fix, bug, security, critical, urgent |
282
117
 
283
- Use `swarm_select_strategy` to see which strategy is recommended and why.
118
+ Begin decomposition now.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm-plugin",
3
- "version": "0.12.4",
3
+ "version": "0.12.7",
4
4
  "description": "Multi-agent swarm coordination for OpenCode with learning capabilities, beads integration, and Agent Mail",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/agent-mail.ts CHANGED
@@ -38,10 +38,10 @@ const RETRY_CONFIG = {
38
38
 
39
39
  // Server recovery configuration
40
40
  const RECOVERY_CONFIG = {
41
- /** Max consecutive failures before attempting restart */
42
- failureThreshold: 2,
43
- /** Cooldown between restart attempts (ms) */
44
- restartCooldownMs: 30000,
41
+ /** Max consecutive failures before attempting restart (1 = restart on first "unexpected error") */
42
+ failureThreshold: 1,
43
+ /** Cooldown between restart attempts (ms) - 10 seconds */
44
+ restartCooldownMs: 10000,
45
45
  /** Whether auto-restart is enabled */
46
46
  enabled: process.env.OPENCODE_AGENT_MAIL_AUTO_RESTART !== "false",
47
47
  };
@@ -107,8 +107,10 @@ function loadSessionState(sessionID: string): AgentMailState | null {
107
107
 
108
108
  /**
109
109
  * Save session state to disk
110
+ *
111
+ * @returns true if save succeeded, false if failed
110
112
  */
111
- function saveSessionState(sessionID: string, state: AgentMailState): void {
113
+ function saveSessionState(sessionID: string, state: AgentMailState): boolean {
112
114
  try {
113
115
  // Ensure directory exists
114
116
  if (!existsSync(SESSION_STATE_DIR)) {
@@ -116,9 +118,16 @@ function saveSessionState(sessionID: string, state: AgentMailState): void {
116
118
  }
117
119
  const path = getSessionStatePath(sessionID);
118
120
  writeFileSync(path, JSON.stringify(state, null, 2));
121
+ return true;
119
122
  } catch (error) {
120
123
  // Non-fatal - state just won't persist
121
- console.warn(`[agent-mail] Could not save session state: ${error}`);
124
+ console.error(
125
+ `[agent-mail] CRITICAL: Could not save session state: ${error}`,
126
+ );
127
+ console.error(
128
+ `[agent-mail] Session state will not persist across CLI invocations!`,
129
+ );
130
+ return false;
122
131
  }
123
132
  }
124
133
 
@@ -718,6 +727,9 @@ export async function mcpCall<T>(
718
727
  // Track consecutive failures
719
728
  consecutiveFailures++;
720
729
 
730
+ // Check if error is retryable FIRST
731
+ const retryable = isRetryableError(error);
732
+
721
733
  // Check if we should attempt server restart
722
734
  if (
723
735
  consecutiveFailures >= RECOVERY_CONFIG.failureThreshold &&
@@ -734,15 +746,18 @@ export async function mcpCall<T>(
734
746
  if (restarted) {
735
747
  // Reset availability cache since server restarted
736
748
  agentMailAvailable = null;
737
- // Don't count this attempt against retries - try again
738
- attempt--;
739
- continue;
749
+ // Only retry if the error was retryable in the first place
750
+ if (retryable) {
751
+ // Don't count this attempt against retries - try again
752
+ attempt--;
753
+ continue;
754
+ }
740
755
  }
741
756
  }
742
757
  }
743
758
 
744
- // Check if error is retryable
745
- if (!isRetryableError(error)) {
759
+ // If error is not retryable, throw immediately
760
+ if (!retryable) {
746
761
  console.warn(
747
762
  `[agent-mail] Non-retryable error for ${toolName}: ${lastError.message}`,
748
763
  );
@@ -865,30 +880,88 @@ export const agentmail_init = tool({
865
880
  );
866
881
  }
867
882
 
868
- // 1. Ensure project exists
869
- const project = await mcpCall<ProjectInfo>("ensure_project", {
870
- human_key: args.project_path,
871
- });
883
+ // Retry loop with restart on failure
884
+ const MAX_INIT_RETRIES = 3;
885
+ let lastError: Error | null = null;
872
886
 
873
- // 2. Register agent
874
- const agent = await mcpCall<AgentInfo>("register_agent", {
875
- project_key: args.project_path,
876
- program: "opencode",
877
- model: "claude-opus-4",
878
- name: args.agent_name, // undefined = auto-generate
879
- task_description: args.task_description || "",
880
- });
887
+ for (let attempt = 1; attempt <= MAX_INIT_RETRIES; attempt++) {
888
+ try {
889
+ // 1. Ensure project exists
890
+ const project = await mcpCall<ProjectInfo>("ensure_project", {
891
+ human_key: args.project_path,
892
+ });
893
+
894
+ // 2. Register agent
895
+ const agent = await mcpCall<AgentInfo>("register_agent", {
896
+ project_key: args.project_path,
897
+ program: "opencode",
898
+ model: "claude-opus-4",
899
+ name: args.agent_name, // undefined = auto-generate
900
+ task_description: args.task_description || "",
901
+ });
902
+
903
+ // 3. Store state using sessionID
904
+ const state: AgentMailState = {
905
+ projectKey: args.project_path,
906
+ agentName: agent.name,
907
+ reservations: [],
908
+ startedAt: new Date().toISOString(),
909
+ };
910
+ setState(ctx.sessionID, state);
911
+
912
+ // Success - if we retried, log it
913
+ if (attempt > 1) {
914
+ console.warn(
915
+ `[agent-mail] Init succeeded on attempt ${attempt} after restart`,
916
+ );
917
+ }
881
918
 
882
- // 3. Store state using sessionID
883
- const state: AgentMailState = {
884
- projectKey: args.project_path,
885
- agentName: agent.name,
886
- reservations: [],
887
- startedAt: new Date().toISOString(),
888
- };
889
- setState(ctx.sessionID, state);
919
+ return JSON.stringify({ project, agent, available: true }, null, 2);
920
+ } catch (error) {
921
+ lastError = error instanceof Error ? error : new Error(String(error));
922
+ const isUnexpectedError = lastError.message
923
+ .toLowerCase()
924
+ .includes("unexpected error");
925
+
926
+ console.warn(
927
+ `[agent-mail] Init attempt ${attempt}/${MAX_INIT_RETRIES} failed: ${lastError.message}`,
928
+ );
890
929
 
891
- return JSON.stringify({ project, agent, available: true }, null, 2);
930
+ // If it's an "unexpected error" and we have retries left, restart and retry
931
+ if (isUnexpectedError && attempt < MAX_INIT_RETRIES) {
932
+ console.warn(
933
+ "[agent-mail] Detected 'unexpected error', restarting server...",
934
+ );
935
+ const restarted = await restartServer();
936
+ if (restarted) {
937
+ // Clear cache and retry
938
+ agentMailAvailable = null;
939
+ consecutiveFailures = 0;
940
+ // Small delay to let server stabilize
941
+ await new Promise((resolve) => setTimeout(resolve, 1000));
942
+ continue;
943
+ }
944
+ }
945
+
946
+ // For non-unexpected errors or if restart failed, don't retry
947
+ if (!isUnexpectedError) {
948
+ break;
949
+ }
950
+ }
951
+ }
952
+
953
+ // All retries exhausted
954
+ return JSON.stringify(
955
+ {
956
+ error: `Agent Mail init failed after ${MAX_INIT_RETRIES} attempts`,
957
+ available: false,
958
+ lastError: lastError?.message,
959
+ hint: "Manually restart Agent Mail: pkill -f agent-mail && agent-mail serve",
960
+ fallback: "Swarm will continue without multi-agent coordination.",
961
+ },
962
+ null,
963
+ 2,
964
+ );
892
965
  },
893
966
  });
894
967
 
@@ -1006,18 +1079,18 @@ export const agentmail_read_message = tool({
1006
1079
  message_id: args.message_id,
1007
1080
  });
1008
1081
 
1009
- // Fetch with body - we need to use fetch_inbox with specific message
1010
- // Since there's no get_message, we'll use search
1082
+ // Fetch with body - fetch more messages to find the requested one
1083
+ // Since there's no get_message endpoint, we need to fetch a reasonable batch
1011
1084
  const messages = await mcpCall<MessageHeader[]>("fetch_inbox", {
1012
1085
  project_key: state.projectKey,
1013
1086
  agent_name: state.agentName,
1014
- limit: 1,
1087
+ limit: 50, // Fetch more messages to increase chance of finding the target
1015
1088
  include_bodies: true, // Only for single message fetch
1016
1089
  });
1017
1090
 
1018
1091
  const message = messages.find((m) => m.id === args.message_id);
1019
1092
  if (!message) {
1020
- return `Message ${args.message_id} not found`;
1093
+ return `Message ${args.message_id} not found in recent 50 messages. Try using agentmail_search to locate it.`;
1021
1094
  }
1022
1095
 
1023
1096
  // Record successful request
@@ -1255,7 +1328,12 @@ export const agentmail_health = tool({
1255
1328
  try {
1256
1329
  const response = await fetch(`${AGENT_MAIL_URL}/health/liveness`);
1257
1330
  if (response.ok) {
1258
- return "Agent Mail is running";
1331
+ // Also check if MCP is functional
1332
+ const functional = await isServerFunctional();
1333
+ if (functional) {
1334
+ return "Agent Mail is running and functional";
1335
+ }
1336
+ return "Agent Mail health OK but MCP not responding - consider restart";
1259
1337
  }
1260
1338
  return `Agent Mail returned status ${response.status}`;
1261
1339
  } catch (error) {
@@ -1264,6 +1342,73 @@ export const agentmail_health = tool({
1264
1342
  },
1265
1343
  });
1266
1344
 
1345
+ /**
1346
+ * Manually restart Agent Mail server
1347
+ *
1348
+ * Use when server is in bad state (health OK but MCP failing).
1349
+ * This kills the existing process and starts a fresh one.
1350
+ */
1351
+ export const agentmail_restart = tool({
1352
+ description:
1353
+ "Manually restart Agent Mail server (use when getting 'unexpected error')",
1354
+ args: {
1355
+ force: tool.schema
1356
+ .boolean()
1357
+ .optional()
1358
+ .describe(
1359
+ "Force restart even if server appears healthy (default: false)",
1360
+ ),
1361
+ },
1362
+ async execute(args) {
1363
+ // Check if restart is needed
1364
+ if (!args.force) {
1365
+ const functional = await isServerFunctional();
1366
+ if (functional) {
1367
+ return JSON.stringify(
1368
+ {
1369
+ restarted: false,
1370
+ reason: "Server is functional, no restart needed",
1371
+ hint: "Use force=true to restart anyway",
1372
+ },
1373
+ null,
1374
+ 2,
1375
+ );
1376
+ }
1377
+ }
1378
+
1379
+ // Attempt restart
1380
+ console.warn("[agent-mail] Manual restart requested...");
1381
+ const success = await restartServer();
1382
+
1383
+ // Clear caches
1384
+ agentMailAvailable = null;
1385
+ consecutiveFailures = 0;
1386
+
1387
+ if (success) {
1388
+ return JSON.stringify(
1389
+ {
1390
+ restarted: true,
1391
+ success: true,
1392
+ message: "Agent Mail server restarted successfully",
1393
+ },
1394
+ null,
1395
+ 2,
1396
+ );
1397
+ }
1398
+
1399
+ return JSON.stringify(
1400
+ {
1401
+ restarted: true,
1402
+ success: false,
1403
+ error: "Restart attempted but server did not come back up",
1404
+ hint: "Check server logs or manually start: agent-mail serve",
1405
+ },
1406
+ null,
1407
+ 2,
1408
+ );
1409
+ },
1410
+ });
1411
+
1267
1412
  // ============================================================================
1268
1413
  // Export all tools
1269
1414
  // ============================================================================
@@ -1279,6 +1424,7 @@ export const agentMailTools = {
1279
1424
  agentmail_ack: agentmail_ack,
1280
1425
  agentmail_search: agentmail_search,
1281
1426
  agentmail_health: agentmail_health,
1427
+ agentmail_restart: agentmail_restart,
1282
1428
  };
1283
1429
 
1284
1430
  // ============================================================================