@desplega.ai/agent-swarm 1.89.0 → 1.91.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.
Files changed (63) hide show
  1. package/README.md +4 -0
  2. package/openapi.json +74 -1
  3. package/package.json +6 -6
  4. package/plugin/skills/composio/SKILL.md +138 -63
  5. package/plugin/skills/composio-gmail/SKILL.md +83 -0
  6. package/plugin/skills/composio-google-calendar/SKILL.md +81 -0
  7. package/plugin/skills/composio-google-docs/SKILL.md +71 -0
  8. package/src/artifact-sdk/server.ts +2 -1
  9. package/src/be/db.ts +28 -0
  10. package/src/be/memory/providers/sqlite-store.ts +6 -1
  11. package/src/be/memory/types.ts +1 -0
  12. package/src/be/modelsdev-cache.json +752 -81
  13. package/src/be/scripts/typecheck.ts +132 -1
  14. package/src/be/seed-scripts/catalog/compound-insights.ts +188 -0
  15. package/src/be/seed-scripts/catalog/schedule-health.ts +73 -0
  16. package/src/be/seed-scripts/catalog/smart-recall.ts +65 -0
  17. package/src/be/seed-scripts/catalog/tool-usage.ts +56 -0
  18. package/src/be/seed-scripts/index.ts +36 -0
  19. package/src/commands/artifact.ts +3 -2
  20. package/src/commands/profile-sync.ts +310 -0
  21. package/src/commands/runner.ts +91 -1
  22. package/src/heartbeat/heartbeat.ts +54 -7
  23. package/src/hooks/hook.ts +32 -9
  24. package/src/http/index.ts +47 -0
  25. package/src/http/integrations.ts +6 -1
  26. package/src/http/mcp-bridge.ts +117 -0
  27. package/src/http/mcp-oauth.ts +97 -39
  28. package/src/http/memory.ts +5 -2
  29. package/src/http/openapi.ts +2 -2
  30. package/src/http/pages-public.ts +10 -11
  31. package/src/http/pages.ts +7 -11
  32. package/src/http/scripts.ts +24 -1
  33. package/src/http/tasks.ts +2 -0
  34. package/src/http/utils.ts +11 -4
  35. package/src/jira/app.ts +2 -3
  36. package/src/jira/webhook-lifecycle.ts +2 -1
  37. package/src/linear/app.ts +2 -3
  38. package/src/providers/claude-adapter.ts +26 -0
  39. package/src/scripts-runtime/executors/native.ts +1 -0
  40. package/src/scripts-runtime/sdk-allowlist.ts +121 -0
  41. package/src/scripts-runtime/swarm-sdk.ts +198 -3
  42. package/src/scripts-runtime/types/stdlib.d.ts +227 -0
  43. package/src/scripts-runtime/types/swarm-sdk.d.ts +227 -0
  44. package/src/tasks/worker-follow-up.ts +19 -1
  45. package/src/tests/claude-adapter-otel.test.ts +85 -1
  46. package/src/tests/heartbeat-supersede-resume.test.ts +91 -1
  47. package/src/tests/hook-registration-nudge.test.ts +69 -0
  48. package/src/tests/mcp-oauth-manual-client.test.ts +213 -0
  49. package/src/tests/pages-public-html.test.ts +41 -0
  50. package/src/tests/pages-public-json-redirect.test.ts +37 -2
  51. package/src/tests/profile-sync.test.ts +282 -0
  52. package/src/tests/scripts-runtime.test.ts +33 -0
  53. package/src/tests/seed-scripts.test.ts +2 -2
  54. package/src/tools/create-metric.ts +2 -3
  55. package/src/tools/create-page.ts +3 -6
  56. package/src/tools/memory-rate.ts +2 -1
  57. package/src/tools/memory-search.ts +1 -0
  58. package/src/tools/register-kapso-number.ts +2 -4
  59. package/src/tools/request-human-input.ts +2 -1
  60. package/src/tools/script-common.ts +2 -4
  61. package/src/tools/script-run.ts +7 -0
  62. package/src/utils/constants.ts +58 -8
  63. package/templates/skills/swarm-scripts/content.md +46 -7
@@ -47,6 +47,7 @@ declare module "swarm-sdk" {
47
47
  }
48
48
 
49
49
  export interface SwarmSdk {
50
+ // --- memory ---
50
51
  memory_search(args: {
51
52
  query: string;
52
53
  scope?: "all" | "agent" | "swarm";
@@ -55,9 +56,12 @@ declare module "swarm-sdk" {
55
56
  }): Promise<unknown>;
56
57
  memory_get(args: { memoryId: string }): Promise<unknown>;
57
58
  memory_rate(args: { id: string; useful: boolean; note?: string }): Promise<unknown>;
59
+ // --- tasks ---
58
60
  task_list(args?: Record<string, unknown>): Promise<unknown>;
59
61
  task_get(args: { taskId: string }): Promise<unknown>;
60
62
  task_storeProgress(args: Record<string, unknown>): Promise<unknown>;
63
+ task_poll(args?: Record<string, unknown>): Promise<unknown>;
64
+ // --- kv ---
61
65
  kv_get(args: { key: string; namespace?: string }): Promise<unknown>;
62
66
  kv_set(args: {
63
67
  key: string;
@@ -69,8 +73,11 @@ declare module "swarm-sdk" {
69
73
  kv_del(args: { key: string; namespace?: string }): Promise<unknown>;
70
74
  kv_incr(args: { key: string; by?: number; namespace?: string }): Promise<unknown>;
71
75
  kv_list(args?: { prefix?: string; namespace?: string; limit?: number }): Promise<unknown>;
76
+ // --- repos ---
72
77
  repo_list(args?: Record<string, unknown>): Promise<unknown>;
78
+ // --- schedules ---
73
79
  schedule_list(args?: Record<string, unknown>): Promise<unknown>;
80
+ // --- scripts ---
74
81
  script_search(args: { query?: string; scope?: ScriptScope; limit?: number }): Promise<unknown>;
75
82
  script_run(args: {
76
83
  name?: string;
@@ -79,7 +86,227 @@ declare module "swarm-sdk" {
79
86
  intent?: string;
80
87
  scope?: ScriptScope;
81
88
  fsMode?: ScriptFsMode;
89
+ idempotencyKey?: string;
82
90
  }): Promise<unknown>;
91
+ // --- swarm / agent ---
92
+ swarm_get(args?: { includeFull?: boolean }): Promise<unknown>;
93
+ agent_info(args?: Record<string, unknown>): Promise<unknown>;
94
+ metrics_get(args?: Record<string, unknown>): Promise<unknown>;
95
+ user_resolve(args?: {
96
+ kind?: string;
97
+ externalId?: string;
98
+ email?: string;
99
+ userId?: string;
100
+ }): Promise<unknown>;
101
+ db_query(args: { sql: string; params?: unknown[] }): Promise<unknown>;
102
+ // --- config ---
103
+ config_get(args?: {
104
+ agentId?: string;
105
+ repoId?: string;
106
+ key?: string;
107
+ includeSecrets?: boolean;
108
+ }): Promise<unknown>;
109
+ config_list(args?: {
110
+ scope?: "global" | "agent" | "repo";
111
+ scopeId?: string;
112
+ key?: string;
113
+ includeSecrets?: boolean;
114
+ }): Promise<unknown>;
115
+ // --- slack ---
116
+ slack_read(args?: {
117
+ inboxMessageId?: string;
118
+ taskId?: string;
119
+ channelId?: string;
120
+ threadTs?: string;
121
+ limit?: number;
122
+ includeFiles?: boolean;
123
+ }): Promise<unknown>;
124
+ slack_listChannels(args?: {
125
+ types?: Array<"public" | "private" | "dm" | "mpim">;
126
+ limit?: number;
127
+ }): Promise<unknown>;
128
+ // --- messaging ---
129
+ message_read(args?: {
130
+ channel?: string;
131
+ limit?: number;
132
+ since?: string;
133
+ unreadOnly?: boolean;
134
+ mentionsOnly?: boolean;
135
+ markAsRead?: boolean;
136
+ }): Promise<unknown>;
137
+ // --- services ---
138
+ service_list(args?: {
139
+ agentId?: string;
140
+ name?: string;
141
+ status?: "starting" | "healthy" | "unhealthy" | "stopped";
142
+ includeOwn?: boolean;
143
+ }): Promise<unknown>;
144
+ // --- context / profiles ---
145
+ context_history(args?: {
146
+ agentId?: string;
147
+ field?: "soulMd" | "identityMd" | "toolsMd" | "claudeMd" | "setupScript";
148
+ limit?: number;
149
+ }): Promise<unknown>;
150
+ context_diff(args: { versionId: string; compareToVersionId?: string }): Promise<unknown>;
151
+ // --- workflows ---
152
+ workflow_list(args?: { enabled?: boolean; includeFull?: boolean }): Promise<unknown>;
153
+ workflow_get(args: { id: string }): Promise<unknown>;
154
+ workflow_listRuns(args: {
155
+ workflowId: string;
156
+ status?: "running" | "waiting" | "completed" | "failed" | "skipped" | "cancelled";
157
+ }): Promise<unknown>;
158
+ workflow_getRun(args: { id: string }): Promise<unknown>;
159
+ // --- prompt templates ---
160
+ prompt_list(args?: {
161
+ eventType?: string;
162
+ scope?: "global" | "agent" | "repo";
163
+ scopeId?: string;
164
+ isDefault?: boolean;
165
+ }): Promise<unknown>;
166
+ prompt_get(args: { id: string }): Promise<unknown>;
167
+ // --- tracker ---
168
+ tracker_status(args?: Record<string, unknown>): Promise<unknown>;
169
+ tracker_syncStatus(args?: Record<string, unknown>): Promise<unknown>;
170
+ tracker_linkTask(args: {
171
+ taskId: string;
172
+ externalId: string;
173
+ provider?: string;
174
+ }): Promise<unknown>;
175
+ tracker_unlink(args: { taskId: string }): Promise<unknown>;
176
+ tracker_mapAgent(args: {
177
+ agentId: string;
178
+ externalId: string;
179
+ provider?: string;
180
+ }): Promise<unknown>;
181
+
182
+ // --- write: memory ---
183
+ memory_delete(args: { id: string }): Promise<unknown>;
184
+ inject_learning(args: {
185
+ content: string;
186
+ name?: string;
187
+ scope?: "agent" | "swarm";
188
+ source?: string;
189
+ tags?: string[];
190
+ }): Promise<unknown>;
191
+
192
+ // --- write: tasks ---
193
+ task_send(args: Record<string, unknown>): Promise<unknown>;
194
+ task_cancel(args: { taskId: string }): Promise<unknown>;
195
+ task_action(args: Record<string, unknown>): Promise<unknown>;
196
+
197
+ // --- write: config ---
198
+ config_set(args: {
199
+ key: string;
200
+ value: unknown;
201
+ scope?: "global" | "agent" | "repo";
202
+ scopeId?: string;
203
+ isSecret?: boolean;
204
+ }): Promise<unknown>;
205
+ config_delete(args: { id: string }): Promise<unknown>;
206
+
207
+ // --- write: slack ---
208
+ slack_post(args: { channelId: string; message: string; blocks?: unknown }): Promise<unknown>;
209
+ slack_reply(args: {
210
+ channelId?: string;
211
+ threadTs?: string;
212
+ message: string;
213
+ taskId?: string;
214
+ }): Promise<unknown>;
215
+ slack_startThread(args: { channelId: string; message: string }): Promise<unknown>;
216
+ slack_uploadFile(args: Record<string, unknown>): Promise<unknown>;
217
+ slack_downloadFile(args: { url: string }): Promise<unknown>;
218
+
219
+ // --- write: messaging (internal) ---
220
+ message_post(args: { channel?: string; content: string; to?: string }): Promise<unknown>;
221
+
222
+ // --- write: profiles ---
223
+ profile_update(args: Record<string, unknown>): Promise<unknown>;
224
+
225
+ // --- write: services ---
226
+ service_register(args: Record<string, unknown>): Promise<unknown>;
227
+ service_unregister(args: { name: string }): Promise<unknown>;
228
+ service_updateStatus(args: {
229
+ name: string;
230
+ status: "starting" | "healthy" | "unhealthy" | "stopped";
231
+ }): Promise<unknown>;
232
+
233
+ // --- write: schedules ---
234
+ schedule_create(args: Record<string, unknown>): Promise<unknown>;
235
+ schedule_update(args: Record<string, unknown>): Promise<unknown>;
236
+ schedule_delete(args: { id: string }): Promise<unknown>;
237
+ schedule_runNow(args: { id: string }): Promise<unknown>;
238
+
239
+ // --- write: workflows ---
240
+ workflow_create(args: Record<string, unknown>): Promise<unknown>;
241
+ workflow_update(args: Record<string, unknown>): Promise<unknown>;
242
+ workflow_patch(args: Record<string, unknown>): Promise<unknown>;
243
+ workflow_patchNode(args: Record<string, unknown>): Promise<unknown>;
244
+ workflow_delete(args: { id: string }): Promise<unknown>;
245
+ workflow_trigger(args: { id: string; input?: Record<string, unknown> }): Promise<unknown>;
246
+ workflow_retryRun(args: { id: string }): Promise<unknown>;
247
+ workflow_cancelRun(args: { id: string }): Promise<unknown>;
248
+
249
+ // --- write: prompt templates ---
250
+ prompt_set(args: Record<string, unknown>): Promise<unknown>;
251
+ prompt_delete(args: { id: string }): Promise<unknown>;
252
+ prompt_preview(args: Record<string, unknown>): Promise<unknown>;
253
+
254
+ // --- write: scripts ---
255
+ script_upsert(args: {
256
+ name: string;
257
+ source: string;
258
+ description?: string;
259
+ intent?: string;
260
+ scope?: ScriptScope;
261
+ fsMode?: ScriptFsMode;
262
+ }): Promise<unknown>;
263
+ script_delete(args: { name: string; scope?: ScriptScope }): Promise<unknown>;
264
+ script_queryTypes(args: { name: string; scope?: ScriptScope }): Promise<unknown>;
265
+
266
+ // --- write: repos ---
267
+ repo_update(args: Record<string, unknown>): Promise<unknown>;
268
+
269
+ // --- write: agent ---
270
+ agent_join(args: {
271
+ name: string;
272
+ role?: string;
273
+ description?: string;
274
+ capabilities?: string[];
275
+ requestedId?: string;
276
+ lead?: boolean;
277
+ }): Promise<unknown>;
278
+ user_manage(args: Record<string, unknown>): Promise<unknown>;
279
+
280
+ // --- skills ---
281
+ skill_list(args?: {
282
+ scope?: string;
283
+ scopeId?: string;
284
+ includeBuiltin?: boolean;
285
+ }): Promise<unknown>;
286
+ skill_get(args: { id: string }): Promise<unknown>;
287
+ skill_search(args: { query: string; limit?: number }): Promise<unknown>;
288
+ skill_create(args: Record<string, unknown>): Promise<unknown>;
289
+ skill_update(args: Record<string, unknown>): Promise<unknown>;
290
+ skill_delete(args: { id: string }): Promise<unknown>;
291
+ skill_install(args: Record<string, unknown>): Promise<unknown>;
292
+ skill_uninstall(args: Record<string, unknown>): Promise<unknown>;
293
+ skill_publish(args: Record<string, unknown>): Promise<unknown>;
294
+
295
+ // --- mcp servers ---
296
+ mcpServer_list(args?: Record<string, unknown>): Promise<unknown>;
297
+ mcpServer_get(args: { id: string }): Promise<unknown>;
298
+ mcpServer_create(args: Record<string, unknown>): Promise<unknown>;
299
+ mcpServer_update(args: Record<string, unknown>): Promise<unknown>;
300
+ mcpServer_delete(args: { id: string }): Promise<unknown>;
301
+ mcpServer_install(args: Record<string, unknown>): Promise<unknown>;
302
+ mcpServer_uninstall(args: Record<string, unknown>): Promise<unknown>;
303
+
304
+ // --- pages & metrics ---
305
+ page_create(args: Record<string, unknown>): Promise<unknown>;
306
+ metric_create(args: Record<string, unknown>): Promise<unknown>;
307
+
308
+ // --- human input ---
309
+ request_humanInput(args: Record<string, unknown>): Promise<unknown>;
83
310
  }
84
311
 
85
312
  export interface ScriptStdlib {
@@ -29,6 +29,7 @@ declare module "swarm-sdk" {
29
29
  }
30
30
 
31
31
  export interface SwarmSdk {
32
+ // --- memory ---
32
33
  memory_search(args: {
33
34
  query: string;
34
35
  scope?: "all" | "agent" | "swarm";
@@ -37,9 +38,12 @@ declare module "swarm-sdk" {
37
38
  }): Promise<unknown>;
38
39
  memory_get(args: { memoryId: string }): Promise<unknown>;
39
40
  memory_rate(args: { id: string; useful: boolean; note?: string }): Promise<unknown>;
41
+ // --- tasks ---
40
42
  task_list(args?: Record<string, unknown>): Promise<unknown>;
41
43
  task_get(args: { taskId: string }): Promise<unknown>;
42
44
  task_storeProgress(args: Record<string, unknown>): Promise<unknown>;
45
+ task_poll(args?: Record<string, unknown>): Promise<unknown>;
46
+ // --- kv ---
43
47
  kv_get(args: { key: string; namespace?: string }): Promise<unknown>;
44
48
  kv_set(args: {
45
49
  key: string;
@@ -51,8 +55,11 @@ declare module "swarm-sdk" {
51
55
  kv_del(args: { key: string; namespace?: string }): Promise<unknown>;
52
56
  kv_incr(args: { key: string; by?: number; namespace?: string }): Promise<unknown>;
53
57
  kv_list(args?: { prefix?: string; namespace?: string; limit?: number }): Promise<unknown>;
58
+ // --- repos ---
54
59
  repo_list(args?: Record<string, unknown>): Promise<unknown>;
60
+ // --- schedules ---
55
61
  schedule_list(args?: Record<string, unknown>): Promise<unknown>;
62
+ // --- scripts ---
56
63
  script_search(args: { query?: string; scope?: ScriptScope; limit?: number }): Promise<unknown>;
57
64
  script_run(args: {
58
65
  name?: string;
@@ -61,7 +68,227 @@ declare module "swarm-sdk" {
61
68
  intent?: string;
62
69
  scope?: ScriptScope;
63
70
  fsMode?: ScriptFsMode;
71
+ idempotencyKey?: string;
64
72
  }): Promise<unknown>;
73
+ // --- swarm / agent ---
74
+ swarm_get(args?: { includeFull?: boolean }): Promise<unknown>;
75
+ agent_info(args?: Record<string, unknown>): Promise<unknown>;
76
+ metrics_get(args?: Record<string, unknown>): Promise<unknown>;
77
+ user_resolve(args?: {
78
+ kind?: string;
79
+ externalId?: string;
80
+ email?: string;
81
+ userId?: string;
82
+ }): Promise<unknown>;
83
+ db_query(args: { sql: string; params?: unknown[] }): Promise<unknown>;
84
+ // --- config ---
85
+ config_get(args?: {
86
+ agentId?: string;
87
+ repoId?: string;
88
+ key?: string;
89
+ includeSecrets?: boolean;
90
+ }): Promise<unknown>;
91
+ config_list(args?: {
92
+ scope?: "global" | "agent" | "repo";
93
+ scopeId?: string;
94
+ key?: string;
95
+ includeSecrets?: boolean;
96
+ }): Promise<unknown>;
97
+ // --- slack ---
98
+ slack_read(args?: {
99
+ inboxMessageId?: string;
100
+ taskId?: string;
101
+ channelId?: string;
102
+ threadTs?: string;
103
+ limit?: number;
104
+ includeFiles?: boolean;
105
+ }): Promise<unknown>;
106
+ slack_listChannels(args?: {
107
+ types?: Array<"public" | "private" | "dm" | "mpim">;
108
+ limit?: number;
109
+ }): Promise<unknown>;
110
+ // --- messaging ---
111
+ message_read(args?: {
112
+ channel?: string;
113
+ limit?: number;
114
+ since?: string;
115
+ unreadOnly?: boolean;
116
+ mentionsOnly?: boolean;
117
+ markAsRead?: boolean;
118
+ }): Promise<unknown>;
119
+ // --- services ---
120
+ service_list(args?: {
121
+ agentId?: string;
122
+ name?: string;
123
+ status?: "starting" | "healthy" | "unhealthy" | "stopped";
124
+ includeOwn?: boolean;
125
+ }): Promise<unknown>;
126
+ // --- context / profiles ---
127
+ context_history(args?: {
128
+ agentId?: string;
129
+ field?: "soulMd" | "identityMd" | "toolsMd" | "claudeMd" | "setupScript";
130
+ limit?: number;
131
+ }): Promise<unknown>;
132
+ context_diff(args: { versionId: string; compareToVersionId?: string }): Promise<unknown>;
133
+ // --- workflows ---
134
+ workflow_list(args?: { enabled?: boolean; includeFull?: boolean }): Promise<unknown>;
135
+ workflow_get(args: { id: string }): Promise<unknown>;
136
+ workflow_listRuns(args: {
137
+ workflowId: string;
138
+ status?: "running" | "waiting" | "completed" | "failed" | "skipped" | "cancelled";
139
+ }): Promise<unknown>;
140
+ workflow_getRun(args: { id: string }): Promise<unknown>;
141
+ // --- prompt templates ---
142
+ prompt_list(args?: {
143
+ eventType?: string;
144
+ scope?: "global" | "agent" | "repo";
145
+ scopeId?: string;
146
+ isDefault?: boolean;
147
+ }): Promise<unknown>;
148
+ prompt_get(args: { id: string }): Promise<unknown>;
149
+ // --- tracker ---
150
+ tracker_status(args?: Record<string, unknown>): Promise<unknown>;
151
+ tracker_syncStatus(args?: Record<string, unknown>): Promise<unknown>;
152
+ tracker_linkTask(args: {
153
+ taskId: string;
154
+ externalId: string;
155
+ provider?: string;
156
+ }): Promise<unknown>;
157
+ tracker_unlink(args: { taskId: string }): Promise<unknown>;
158
+ tracker_mapAgent(args: {
159
+ agentId: string;
160
+ externalId: string;
161
+ provider?: string;
162
+ }): Promise<unknown>;
163
+
164
+ // --- write: memory ---
165
+ memory_delete(args: { id: string }): Promise<unknown>;
166
+ inject_learning(args: {
167
+ content: string;
168
+ name?: string;
169
+ scope?: "agent" | "swarm";
170
+ source?: string;
171
+ tags?: string[];
172
+ }): Promise<unknown>;
173
+
174
+ // --- write: tasks ---
175
+ task_send(args: Record<string, unknown>): Promise<unknown>;
176
+ task_cancel(args: { taskId: string }): Promise<unknown>;
177
+ task_action(args: Record<string, unknown>): Promise<unknown>;
178
+
179
+ // --- write: config ---
180
+ config_set(args: {
181
+ key: string;
182
+ value: unknown;
183
+ scope?: "global" | "agent" | "repo";
184
+ scopeId?: string;
185
+ isSecret?: boolean;
186
+ }): Promise<unknown>;
187
+ config_delete(args: { id: string }): Promise<unknown>;
188
+
189
+ // --- write: slack ---
190
+ slack_post(args: { channelId: string; message: string; blocks?: unknown }): Promise<unknown>;
191
+ slack_reply(args: {
192
+ channelId?: string;
193
+ threadTs?: string;
194
+ message: string;
195
+ taskId?: string;
196
+ }): Promise<unknown>;
197
+ slack_startThread(args: { channelId: string; message: string }): Promise<unknown>;
198
+ slack_uploadFile(args: Record<string, unknown>): Promise<unknown>;
199
+ slack_downloadFile(args: { url: string }): Promise<unknown>;
200
+
201
+ // --- write: messaging (internal) ---
202
+ message_post(args: { channel?: string; content: string; to?: string }): Promise<unknown>;
203
+
204
+ // --- write: profiles ---
205
+ profile_update(args: Record<string, unknown>): Promise<unknown>;
206
+
207
+ // --- write: services ---
208
+ service_register(args: Record<string, unknown>): Promise<unknown>;
209
+ service_unregister(args: { name: string }): Promise<unknown>;
210
+ service_updateStatus(args: {
211
+ name: string;
212
+ status: "starting" | "healthy" | "unhealthy" | "stopped";
213
+ }): Promise<unknown>;
214
+
215
+ // --- write: schedules ---
216
+ schedule_create(args: Record<string, unknown>): Promise<unknown>;
217
+ schedule_update(args: Record<string, unknown>): Promise<unknown>;
218
+ schedule_delete(args: { id: string }): Promise<unknown>;
219
+ schedule_runNow(args: { id: string }): Promise<unknown>;
220
+
221
+ // --- write: workflows ---
222
+ workflow_create(args: Record<string, unknown>): Promise<unknown>;
223
+ workflow_update(args: Record<string, unknown>): Promise<unknown>;
224
+ workflow_patch(args: Record<string, unknown>): Promise<unknown>;
225
+ workflow_patchNode(args: Record<string, unknown>): Promise<unknown>;
226
+ workflow_delete(args: { id: string }): Promise<unknown>;
227
+ workflow_trigger(args: { id: string; input?: Record<string, unknown> }): Promise<unknown>;
228
+ workflow_retryRun(args: { id: string }): Promise<unknown>;
229
+ workflow_cancelRun(args: { id: string }): Promise<unknown>;
230
+
231
+ // --- write: prompt templates ---
232
+ prompt_set(args: Record<string, unknown>): Promise<unknown>;
233
+ prompt_delete(args: { id: string }): Promise<unknown>;
234
+ prompt_preview(args: Record<string, unknown>): Promise<unknown>;
235
+
236
+ // --- write: scripts ---
237
+ script_upsert(args: {
238
+ name: string;
239
+ source: string;
240
+ description?: string;
241
+ intent?: string;
242
+ scope?: ScriptScope;
243
+ fsMode?: ScriptFsMode;
244
+ }): Promise<unknown>;
245
+ script_delete(args: { name: string; scope?: ScriptScope }): Promise<unknown>;
246
+ script_queryTypes(args: { name: string; scope?: ScriptScope }): Promise<unknown>;
247
+
248
+ // --- write: repos ---
249
+ repo_update(args: Record<string, unknown>): Promise<unknown>;
250
+
251
+ // --- write: agent ---
252
+ agent_join(args: {
253
+ name: string;
254
+ role?: string;
255
+ description?: string;
256
+ capabilities?: string[];
257
+ requestedId?: string;
258
+ lead?: boolean;
259
+ }): Promise<unknown>;
260
+ user_manage(args: Record<string, unknown>): Promise<unknown>;
261
+
262
+ // --- skills ---
263
+ skill_list(args?: {
264
+ scope?: string;
265
+ scopeId?: string;
266
+ includeBuiltin?: boolean;
267
+ }): Promise<unknown>;
268
+ skill_get(args: { id: string }): Promise<unknown>;
269
+ skill_search(args: { query: string; limit?: number }): Promise<unknown>;
270
+ skill_create(args: Record<string, unknown>): Promise<unknown>;
271
+ skill_update(args: Record<string, unknown>): Promise<unknown>;
272
+ skill_delete(args: { id: string }): Promise<unknown>;
273
+ skill_install(args: Record<string, unknown>): Promise<unknown>;
274
+ skill_uninstall(args: Record<string, unknown>): Promise<unknown>;
275
+ skill_publish(args: Record<string, unknown>): Promise<unknown>;
276
+
277
+ // --- mcp servers ---
278
+ mcpServer_list(args?: Record<string, unknown>): Promise<unknown>;
279
+ mcpServer_get(args: { id: string }): Promise<unknown>;
280
+ mcpServer_create(args: Record<string, unknown>): Promise<unknown>;
281
+ mcpServer_update(args: Record<string, unknown>): Promise<unknown>;
282
+ mcpServer_delete(args: { id: string }): Promise<unknown>;
283
+ mcpServer_install(args: Record<string, unknown>): Promise<unknown>;
284
+ mcpServer_uninstall(args: Record<string, unknown>): Promise<unknown>;
285
+
286
+ // --- pages & metrics ---
287
+ page_create(args: Record<string, unknown>): Promise<unknown>;
288
+ metric_create(args: Record<string, unknown>): Promise<unknown>;
289
+
290
+ // --- human input ---
291
+ request_humanInput(args: Record<string, unknown>): Promise<unknown>;
65
292
  }
66
293
 
67
294
  export interface ScriptStdlib {
@@ -22,6 +22,20 @@ export const WORKER_LIVENESS_WINDOW_SECONDS = Number(
22
22
  process.env.WORKER_LIVENESS_WINDOW_SECONDS || "30",
23
23
  );
24
24
 
25
+ export const RESUME_GENERATION_TAG_PREFIX = "resume-generation:";
26
+
27
+ export function getResumeGeneration(task: Pick<AgentTask, "tags">): number {
28
+ const tag = task.tags.find((value) => value.startsWith(RESUME_GENERATION_TAG_PREFIX));
29
+ if (!tag) return 0;
30
+
31
+ const parsed = Number(tag.slice(RESUME_GENERATION_TAG_PREFIX.length));
32
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : 0;
33
+ }
34
+
35
+ export function getNextResumeGeneration(parent: Pick<AgentTask, "tags">): number {
36
+ return getResumeGeneration(parent) + 1;
37
+ }
38
+
25
39
  function attachmentPointer(a: TaskAttachment): string {
26
40
  switch (a.kind) {
27
41
  case "url":
@@ -205,7 +219,11 @@ export function createResumeFollowUp(args: {
205
219
  ].join("\n");
206
220
 
207
221
  const priority = Math.min(100, (parent.priority ?? 50) + 10);
208
- const tags = ["auto-resume", `reason:${args.reason}`];
222
+ const tags = [
223
+ "auto-resume",
224
+ `reason:${args.reason}`,
225
+ `${RESUME_GENERATION_TAG_PREFIX}${getNextResumeGeneration(parent)}`,
226
+ ];
209
227
 
210
228
  // Identity-shaped fields (dir, VCS provider/repo/number/url/etc.,
211
229
  // outputSchema, slack channel/thread/user, agentmail, mention, contextKey,
@@ -15,7 +15,11 @@
15
15
 
16
16
  import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
17
17
  import { type Span, trace } from "@opentelemetry/api";
18
- import { buildClaudeCodeOtelEnv, ClaudeAdapter } from "../providers/claude-adapter";
18
+ import {
19
+ buildClaudeCodeOtelEnv,
20
+ buildClaudeCodeRuntimeEnv,
21
+ ClaudeAdapter,
22
+ } from "../providers/claude-adapter";
19
23
  import type { ProviderSessionConfig } from "../providers/types";
20
24
 
21
25
  // Example IDs from the task — trace af2c8371…, span adff4f24… (the orphaned
@@ -136,6 +140,51 @@ describe("buildClaudeCodeOtelEnv — gate on", () => {
136
140
  });
137
141
  });
138
142
 
143
+ describe("buildClaudeCodeRuntimeEnv", () => {
144
+ test("sets memory/privacy defaults for ephemeral Claude Code sessions", () => {
145
+ const env = buildClaudeCodeRuntimeEnv({});
146
+
147
+ expect(env.ENABLE_TOOL_SEARCH).toBe("true");
148
+ expect(env.CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING).toBe("1");
149
+ expect(env.CLAUDE_CODE_SKIP_PROMPT_HISTORY).toBe("1");
150
+ expect(env.CLAUDE_CODE_DISABLE_ATTACHMENTS).toBe("1");
151
+ expect(env.DISABLE_FEEDBACK_COMMAND).toBe("1");
152
+ expect(env.DISABLE_BUG_COMMAND).toBe("1");
153
+ });
154
+
155
+ test("always disables Claude Code Statsig/DNT telemetry", () => {
156
+ const env = buildClaudeCodeRuntimeEnv({});
157
+
158
+ expect(env.DISABLE_TELEMETRY).toBe("1");
159
+ expect(env.DO_NOT_TRACK).toBe("1");
160
+ });
161
+
162
+ test("keeps Claude Code Statsig/DNT opt-out separate from OTel config", () => {
163
+ for (const sourceEnv of [
164
+ { CLAUDE_CODE_ENABLE_TELEMETRY: "1" },
165
+ { CLAUDE_CODE_ENABLE_TELEMETRY: "true" },
166
+ { OTEL_EXPORTER_OTLP_ENDPOINT: "https://otel.example.test" },
167
+ { OTEL_TRACES_EXPORTER: "otlp" },
168
+ { OTEL_METRICS_EXPORTER: "otlp" },
169
+ { OTEL_LOGS_EXPORTER: "otlp" },
170
+ ]) {
171
+ const env = buildClaudeCodeRuntimeEnv(sourceEnv);
172
+ expect(env.DISABLE_TELEMETRY).toBe("1");
173
+ expect(env.DO_NOT_TRACK).toBe("1");
174
+ }
175
+ });
176
+
177
+ test("ignores empty OTel env values for runtime defaults", () => {
178
+ const env = buildClaudeCodeRuntimeEnv({
179
+ OTEL_EXPORTER_OTLP_ENDPOINT: "",
180
+ CLAUDE_CODE_ENABLE_TELEMETRY: "0",
181
+ });
182
+
183
+ expect(env.DISABLE_TELEMETRY).toBe("1");
184
+ expect(env.DO_NOT_TRACK).toBe("1");
185
+ });
186
+ });
187
+
139
188
  // ─── Spawn integration through ClaudeAdapter.createSession ────────────────────
140
189
 
141
190
  /** Fake Bun.Subprocess — exits cleanly with no output. */
@@ -222,4 +271,39 @@ describe("ClaudeSession spawn env — SWARM_ENABLE_CLAUDE_CODE_OTEL", () => {
222
271
  expect(env?.ENABLE_PROMPT_CACHING_1H).toBe("1");
223
272
  expect(env?.CLAUDE_CODE_OAUTH_TOKEN).toBe("test-token");
224
273
  });
274
+
275
+ test("spawn env carries Claude Code runtime guardrails", async () => {
276
+ const adapter = new ClaudeAdapter();
277
+ await adapter.createSession(makeConfig({ env: { CLAUDE_CODE_OAUTH_TOKEN: "test-token" } }));
278
+
279
+ expect(spawnedEnvs).toHaveLength(1);
280
+ const env = spawnedEnvs[0];
281
+ expect(env?.ENABLE_TOOL_SEARCH).toBe("true");
282
+ expect(env?.CLAUDE_CODE_DISABLE_FILE_CHECKPOINTING).toBe("1");
283
+ expect(env?.CLAUDE_CODE_SKIP_PROMPT_HISTORY).toBe("1");
284
+ expect(env?.CLAUDE_CODE_DISABLE_ATTACHMENTS).toBe("1");
285
+ expect(env?.DISABLE_FEEDBACK_COMMAND).toBe("1");
286
+ expect(env?.DISABLE_BUG_COMMAND).toBe("1");
287
+ expect(env?.DISABLE_TELEMETRY).toBe("1");
288
+ expect(env?.DO_NOT_TRACK).toBe("1");
289
+ expect(env?.CLAUDE_CODE_DISABLE_THINKING).toBeUndefined();
290
+ });
291
+
292
+ test("spawn env keeps Statsig/DNT opt-out even when OTel is configured", async () => {
293
+ const adapter = new ClaudeAdapter();
294
+ await adapter.createSession(
295
+ makeConfig({
296
+ env: {
297
+ CLAUDE_CODE_OAUTH_TOKEN: "test-token",
298
+ CLAUDE_CODE_ENABLE_TELEMETRY: "1",
299
+ OTEL_EXPORTER_OTLP_ENDPOINT: "https://otel.example.test",
300
+ },
301
+ }),
302
+ );
303
+
304
+ expect(spawnedEnvs).toHaveLength(1);
305
+ const env = spawnedEnvs[0];
306
+ expect(env?.DISABLE_TELEMETRY).toBe("1");
307
+ expect(env?.DO_NOT_TRACK).toBe("1");
308
+ });
225
309
  });