@desplega.ai/agent-swarm 1.123.0 → 1.124.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 (234) hide show
  1. package/README.md +2 -1
  2. package/dist/{actions-e4c9f0xy.js → actions-z3d0fk7z.js} +6 -6
  3. package/dist/{app-vmvmj2v3.js → app-q2rc9tdr.js} +4 -4
  4. package/dist/{assistant-yn7a792a.js → assistant-3stjq7fz.js} +9 -9
  5. package/dist/{boot-reembed-xg1r86h2.js → boot-reembed-5867whnb.js} +3 -3
  6. package/dist/{boot-reembed-chxty50a.js → boot-reembed-v6r1df32.js} +4 -4
  7. package/dist/{boot-scrub-logs-exwddvp5.js → boot-scrub-logs-8b8jegk3.js} +2 -2
  8. package/dist/{cli-1592nfd6.js → cli-0925phzv.js} +1 -1
  9. package/dist/{cli-hbbxmhec.js → cli-2yr6edr7.js} +4 -4
  10. package/dist/{cli-8cq4z4x7.js → cli-3z4q09tn.js} +182 -19
  11. package/dist/{cli-vz9drmce.js → cli-5jn6wnd9.js} +17 -8
  12. package/dist/{cli-5arfywtm.js → cli-5ncdb7ff.js} +19 -9
  13. package/dist/{cli-3tv9z4wx.js → cli-92bqgbgy.js} +1 -1
  14. package/dist/{cli-fjf04hpa.js → cli-dq2ssyf0.js} +48 -56
  15. package/dist/{cli-mngsj9fx.js → cli-gkvf8d83.js} +1 -1
  16. package/dist/{cli-mepk1j0t.js → cli-gzjsamwc.js} +2 -2
  17. package/dist/{cli-c9m59f83.js → cli-h89g0qrd.js} +1 -1
  18. package/dist/{cli-n8mf7x4b.js → cli-jp4mdj9d.js} +2 -2
  19. package/dist/{cli-822d4bjk.js → cli-kk58tg33.js} +7 -7
  20. package/dist/{cli-9hj1adgp.js → cli-mcez7z4p.js} +1 -1
  21. package/dist/{cli-byv3720g.js → cli-mmk5vagg.js} +2 -2
  22. package/dist/{cli-zdp11t8m.js → cli-p0ec4vv6.js} +1 -1
  23. package/dist/{cli-h2say6xk.js → cli-p0zgv8pj.js} +3 -1
  24. package/dist/{cli-8ef5ky75.js → cli-perb20ma.js} +1 -1
  25. package/dist/{cli-zkj6f2sk.js → cli-qf7acvyr.js} +90 -4
  26. package/dist/{cli-kmm1rwmp.js → cli-qwsagsmg.js} +1 -1
  27. package/dist/{cli-we91ywvy.js → cli-sqv6c9b8.js} +6 -6
  28. package/dist/{cli-np0yhmmk.js → cli-vm20sh8d.js} +3 -3
  29. package/dist/{cli-p11rf59d.js → cli-wn3m6q54.js} +3 -3
  30. package/dist/{cli-mkpf4ndf.js → cli-x268say8.js} +2976 -5621
  31. package/dist/{cli-ngbsk4yx.js → cli-y43n987v.js} +1 -1
  32. package/dist/{cli-4509mwm5.js → cli-ykthjw29.js} +8 -8
  33. package/dist/{cli-9eka6jwv.js → cli-zxb72ctk.js} +2 -2
  34. package/dist/cli.js +12 -10
  35. package/dist/{commands-sjk3zfyr.js → commands-sda76yn8.js} +2 -2
  36. package/dist/{db-2je5agjb.js → db-vn9e4rqj.js} +6 -2
  37. package/dist/{e2b-2s4psnbf.js → e2b-q345y8s4.js} +0 -4
  38. package/dist/{handlers-yzv369hf.js → handlers-xfja18ac.js} +9 -9
  39. package/dist/{hook-rfsj2r8x.js → hook-2medrp47.js} +1 -40
  40. package/dist/{http-v9rr144m.js → http-937pyjfc.js} +99 -44
  41. package/dist/{index-nr2199m6.js → index-2bqd2q9v.js} +11 -11
  42. package/dist/{index-3xtk777g.js → index-gw4en7jg.js} +9 -9
  43. package/dist/{index-c3tan44f.js → index-knqczmnm.js} +10 -10
  44. package/dist/{index-smjdc3h9.js → index-vah60vxp.js} +8 -8
  45. package/dist/{keepalive-5ds53bjd.js → keepalive-20rd6hxh.js} +5 -5
  46. package/dist/{lead-5xhez25b.js → lead-7w2k3a49.js} +21 -21
  47. package/dist/{maintenance-b43d24q6.js → maintenance-p3x918yw.js} +4 -4
  48. package/dist/{oauth-refresh-sweep-qe286vn2.js → oauth-refresh-sweep-shm0nzm4.js} +4 -4
  49. package/dist/{onboard-c4r3ds3z.js → onboard-py9dnf54.js} +6 -2
  50. package/dist/{otel-impl-nv3rjw61.js → otel-impl-7yjkfg68.js} +1 -1
  51. package/dist/{pi-mono-adapter-2syx1x4d.js → pi-mono-adapter-z6h98fva.js} +4 -38
  52. package/dist/{pricing-refresh-5ct2wp4k.js → pricing-refresh-3snb6370.js} +4 -4
  53. package/dist/{rbac-roles-m502w0qv.js → rbac-roles-5e72bbpk.js} +3 -3
  54. package/dist/{rbac-roles-b82cxpxn.js → rbac-roles-gqxdp8st.js} +4 -4
  55. package/dist/{seed-pricing-jhjphbf0.js → seed-pricing-bg42d7h2.js} +3 -3
  56. package/dist/{setup-zbaspydq.js → setup-nzk3kbbq.js} +2 -2
  57. package/dist/{worker-snvhpax5.js → worker-0p1jdzkm.js} +21 -21
  58. package/openapi.json +146 -1
  59. package/package.json +3 -1
  60. package/src/be/db.ts +81 -4
  61. package/src/be/models-catalog.ts +156 -0
  62. package/src/be/modelsdev-cache.ts +14 -1
  63. package/src/be/pricing-refresh.ts +2 -0
  64. package/src/be/scripts/typecheck.ts +17 -4
  65. package/src/be/seed-scripts/catalog/task-context-gathering.ts +1 -1
  66. package/src/commands/onboard/env-generator.ts +12 -0
  67. package/src/e2b/env.ts +0 -4
  68. package/src/hooks/hook.ts +0 -67
  69. package/src/http/all-routes.ts +1 -0
  70. package/src/http/index.ts +2 -0
  71. package/src/http/models-catalog.ts +65 -0
  72. package/src/http/workflows.ts +16 -4
  73. package/src/prompts/base-prompt.ts +8 -7
  74. package/src/prompts/session-templates.ts +106 -12
  75. package/src/providers/pi-mono-adapter.ts +12 -2
  76. package/src/providers/pi-mono-extension.ts +0 -64
  77. package/src/providers/pricing-sources.md +16 -1
  78. package/src/scripts-runtime/eval-harness.ts +18 -1
  79. package/src/scripts-runtime/swarm-sdk.ts +10 -0
  80. package/src/scripts-runtime/types/stdlib.d.ts +13 -0
  81. package/src/scripts-runtime/types/swarm-sdk.d.ts +13 -0
  82. package/src/server-user.ts +4 -7
  83. package/src/slack/blocks.ts +21 -8
  84. package/src/slack/responses.ts +27 -51
  85. package/src/slack/watcher.ts +22 -5
  86. package/src/telemetry.ts +169 -3
  87. package/src/tests/base-prompt.test.ts +79 -0
  88. package/src/tests/mcp-tools-user.test.ts +62 -16
  89. package/src/tests/mcp-tools.test.ts +6 -3
  90. package/src/tests/memory-edit.test.ts +21 -4
  91. package/src/tests/model-groups-live-catalog.test.ts +65 -0
  92. package/src/tests/models-catalog.test.ts +119 -0
  93. package/src/tests/oauth-access-token-tool.test.ts +71 -1
  94. package/src/tests/pricing-refresh.test.ts +25 -0
  95. package/src/tests/prompt-template-session.test.ts +142 -5
  96. package/src/tests/rbac-charact-skills.test.ts +81 -14
  97. package/src/tests/script-apis-mcp.test.ts +56 -8
  98. package/src/tests/scripts-mcp-e2e.test.ts +157 -8
  99. package/src/tests/scripts-typecheck.test.ts +17 -0
  100. package/src/tests/sdk-allowlist.test.ts +34 -1
  101. package/src/tests/seed-scripts.test.ts +43 -0
  102. package/src/tests/slack-blocks.test.ts +2 -1
  103. package/src/tests/slack-inline-output.test.ts +24 -30
  104. package/src/tests/slack-watcher.test.ts +42 -0
  105. package/src/tests/steer-task-tool.test.ts +37 -8
  106. package/src/tests/steering-transport.test.ts +18 -3
  107. package/src/tests/swarm-tool-result-gate.test.ts +399 -0
  108. package/src/tests/task-tools-ctx.test.ts +49 -17
  109. package/src/tests/task-tools-ownership.test.ts +41 -13
  110. package/src/tests/telemetry-init.test.ts +376 -2
  111. package/src/tests/tool-output-agent-id.test.ts +14 -2
  112. package/src/tests/workflow-http-v2.test.ts +116 -0
  113. package/src/tools/accept-steer.ts +45 -53
  114. package/src/tools/cancel-task.ts +31 -41
  115. package/src/tools/context-diff.ts +19 -63
  116. package/src/tools/context-history.ts +22 -51
  117. package/src/tools/create-channel.ts +24 -39
  118. package/src/tools/create-metric.ts +19 -82
  119. package/src/tools/create-page.ts +20 -81
  120. package/src/tools/credential-bindings/tool.ts +125 -246
  121. package/src/tools/db-query.ts +13 -24
  122. package/src/tools/delete-channel.ts +25 -71
  123. package/src/tools/delete-page.ts +27 -75
  124. package/src/tools/get-metrics.ts +29 -22
  125. package/src/tools/get-swarm.ts +44 -15
  126. package/src/tools/get-task-details.ts +150 -32
  127. package/src/tools/get-tasks.ts +63 -29
  128. package/src/tools/inject-learning.ts +8 -38
  129. package/src/tools/join-swarm.ts +45 -47
  130. package/src/tools/kv/kv-delete.ts +13 -37
  131. package/src/tools/kv/kv-get.ts +38 -29
  132. package/src/tools/kv/kv-incr.ts +28 -56
  133. package/src/tools/kv/kv-list.ts +40 -31
  134. package/src/tools/kv/kv-set.ts +34 -76
  135. package/src/tools/list-channels.ts +24 -17
  136. package/src/tools/list-services.ts +37 -45
  137. package/src/tools/manage-user.ts +53 -66
  138. package/src/tools/mcp-servers/mcp-server-create.ts +19 -55
  139. package/src/tools/mcp-servers/mcp-server-delete.ts +9 -39
  140. package/src/tools/mcp-servers/mcp-server-get.ts +9 -35
  141. package/src/tools/mcp-servers/mcp-server-install.ts +13 -60
  142. package/src/tools/mcp-servers/mcp-server-list.ts +28 -26
  143. package/src/tools/mcp-servers/mcp-server-uninstall.ts +10 -36
  144. package/src/tools/mcp-servers/mcp-server-update.ts +13 -57
  145. package/src/tools/memory-delete.ts +16 -46
  146. package/src/tools/memory-edit.ts +48 -49
  147. package/src/tools/memory-get.ts +40 -36
  148. package/src/tools/memory-rate.ts +14 -44
  149. package/src/tools/memory-search.ts +46 -52
  150. package/src/tools/my-agent-info.ts +39 -33
  151. package/src/tools/oauth-access-token.ts +9 -24
  152. package/src/tools/poll-task.ts +50 -77
  153. package/src/tools/post-message.ts +24 -38
  154. package/src/tools/prompt-templates/delete.ts +16 -48
  155. package/src/tools/prompt-templates/get.ts +45 -42
  156. package/src/tools/prompt-templates/list.ts +29 -44
  157. package/src/tools/prompt-templates/preview.ts +14 -40
  158. package/src/tools/prompt-templates/set.ts +30 -52
  159. package/src/tools/read-messages.ts +45 -54
  160. package/src/tools/register-agentmail-inbox.ts +28 -84
  161. package/src/tools/register-kapso-number.ts +20 -50
  162. package/src/tools/register-service.ts +36 -44
  163. package/src/tools/repos/get-repos.ts +29 -21
  164. package/src/tools/repos/update-repo.ts +30 -27
  165. package/src/tools/request-human-input.ts +10 -33
  166. package/src/tools/resolve-user.ts +59 -16
  167. package/src/tools/schedules/create-schedule.ts +58 -173
  168. package/src/tools/schedules/delete-schedule.ts +16 -56
  169. package/src/tools/schedules/list-schedules.ts +41 -67
  170. package/src/tools/schedules/patch-schedule.ts +57 -153
  171. package/src/tools/schedules/run-schedule-now.ts +18 -59
  172. package/src/tools/schedules/update-schedule.ts +57 -153
  173. package/src/tools/script-apis.ts +46 -28
  174. package/src/tools/script-common.ts +129 -34
  175. package/src/tools/script-connections/tool.ts +59 -154
  176. package/src/tools/script-query-types.ts +43 -3
  177. package/src/tools/script-run.ts +41 -2
  178. package/src/tools/script-runs.ts +69 -1
  179. package/src/tools/script-search.ts +24 -1
  180. package/src/tools/script-upsert.ts +18 -3
  181. package/src/tools/send-task.ts +32 -81
  182. package/src/tools/skills/skill-create.ts +14 -39
  183. package/src/tools/skills/skill-delete.ts +14 -42
  184. package/src/tools/skills/skill-get-file.ts +10 -43
  185. package/src/tools/skills/skill-get.ts +9 -32
  186. package/src/tools/skills/skill-install-remote.ts +16 -52
  187. package/src/tools/skills/skill-install.ts +14 -52
  188. package/src/tools/skills/skill-list.ts +24 -26
  189. package/src/tools/skills/skill-publish.ts +18 -54
  190. package/src/tools/skills/skill-search.ts +21 -18
  191. package/src/tools/skills/skill-sync-remote.ts +12 -24
  192. package/src/tools/skills/skill-uninstall.ts +10 -26
  193. package/src/tools/skills/skill-update.ts +24 -81
  194. package/src/tools/slack-delete.ts +8 -32
  195. package/src/tools/slack-download-file.ts +17 -57
  196. package/src/tools/slack-list-channels.ts +16 -43
  197. package/src/tools/slack-post.ts +11 -40
  198. package/src/tools/slack-read.ts +33 -103
  199. package/src/tools/slack-reply.ts +16 -53
  200. package/src/tools/slack-start-thread.ts +14 -55
  201. package/src/tools/slack-update.ts +8 -35
  202. package/src/tools/slack-upload-file.ts +22 -122
  203. package/src/tools/steer-task.ts +22 -35
  204. package/src/tools/store-progress.ts +11 -26
  205. package/src/tools/swarm-config/delete-config.ts +19 -57
  206. package/src/tools/swarm-config/get-config.ts +36 -44
  207. package/src/tools/swarm-config/list-config.ts +36 -44
  208. package/src/tools/swarm-config/set-config.ts +35 -73
  209. package/src/tools/swarm-x.ts +20 -26
  210. package/src/tools/task-action.ts +26 -46
  211. package/src/tools/task-tool-ctx.ts +5 -13
  212. package/src/tools/tracker/tracker-link-task.ts +8 -22
  213. package/src/tools/tracker/tracker-map-agent.ts +8 -22
  214. package/src/tools/tracker/tracker-status.ts +27 -19
  215. package/src/tools/tracker/tracker-sync-status.ts +8 -18
  216. package/src/tools/tracker/tracker-unlink.ts +4 -16
  217. package/src/tools/unregister-service.ts +19 -59
  218. package/src/tools/update-profile.ts +60 -100
  219. package/src/tools/update-service-status.ts +42 -67
  220. package/src/tools/utils.ts +189 -8
  221. package/src/tools/whatsapp-message.ts +19 -32
  222. package/src/tools/workflows/cancel-workflow-run.ts +4 -16
  223. package/src/tools/workflows/create-workflow.ts +9 -38
  224. package/src/tools/workflows/delete-workflow.ts +5 -17
  225. package/src/tools/workflows/get-workflow-run.ts +41 -31
  226. package/src/tools/workflows/get-workflow.ts +10 -21
  227. package/src/tools/workflows/list-workflow-runs.ts +107 -34
  228. package/src/tools/workflows/list-workflows.ts +5 -17
  229. package/src/tools/workflows/patch-workflow-node.ts +11 -39
  230. package/src/tools/workflows/patch-workflow.ts +11 -36
  231. package/src/tools/workflows/retry-workflow-run.ts +4 -16
  232. package/src/tools/workflows/trigger-workflow.ts +22 -58
  233. package/src/tools/workflows/update-workflow.ts +10 -42
  234. package/templates/skills/swarm-scripts/SKILL.md +1 -1
@@ -11,7 +11,7 @@ import {
11
11
  upsertScriptConnection,
12
12
  } from "@/be/script-connections";
13
13
  import { can } from "@/rbac";
14
- import { createToolRegistrar } from "@/tools/utils";
14
+ import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
15
15
  import { resolveScopedResourceId, scopedResourceScopeIdSchema } from "@/utils/scoped-resource";
16
16
 
17
17
  const scriptConnectionsInputSchema = z.object({
@@ -92,11 +92,9 @@ const scriptConnectionsInputSchema = z.object({
92
92
  enabled: z.boolean().optional().describe("Whether the connection is enabled."),
93
93
  });
94
94
 
95
- const scriptConnectionsOutputSchema = z.object({
95
+ const scriptConnectionsOutputSchema = swarmToolOutputSchema({
96
96
  yourAgentId: z.string().optional(),
97
- success: z.boolean(),
98
- message: z.string(),
99
- connections: z.array(z.unknown()),
97
+ connections: z.array(z.unknown()).optional(),
100
98
  });
101
99
 
102
100
  type ScriptConnectionsArgs = z.infer<typeof scriptConnectionsInputSchema>;
@@ -148,14 +146,7 @@ export const registerScriptConnectionsTool = (server: McpServer) => {
148
146
  },
149
147
  async (args, requestInfo) => {
150
148
  if (!requestInfo.agentId) {
151
- return {
152
- content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
153
- structuredContent: {
154
- success: false,
155
- message: 'Agent ID not found. Set the "X-Agent-ID" header.',
156
- connections: [],
157
- },
158
- };
149
+ return toolErr('Agent ID not found. Set the "X-Agent-ID" header.');
159
150
  }
160
151
 
161
152
  const agent = getAgentById(requestInfo.agentId);
@@ -170,15 +161,9 @@ export const registerScriptConnectionsTool = (server: McpServer) => {
170
161
  source: "mcp",
171
162
  });
172
163
  if (!decision.allow) {
173
- return {
174
- content: [{ type: "text", text: "Only the lead can manage script connections." }],
175
- structuredContent: {
176
- yourAgentId: requestInfo.agentId,
177
- success: false,
178
- message: "Only the lead can manage script connections.",
179
- connections: [],
180
- },
181
- };
164
+ return toolErr("Only the lead can manage script connections.", {
165
+ data: { yourAgentId: requestInfo.agentId },
166
+ });
182
167
  }
183
168
 
184
169
  if (args.action === "list") {
@@ -186,101 +171,61 @@ export const registerScriptConnectionsTool = (server: McpServer) => {
186
171
  const provenanceLines = connections
187
172
  .filter((connection) => connection.kind === "openapi" || connection.baseUrl !== null)
188
173
  .map(baseUrlProvenanceText);
189
- return {
190
- content: [
191
- {
192
- type: "text",
193
- text: `Found ${connections.length} script connection(s).${provenanceLines.length ? `\n${provenanceLines.join("\n")}` : ""}`,
194
- },
195
- ],
196
- structuredContent: {
197
- yourAgentId: requestInfo.agentId,
198
- success: true,
199
- message: `Found ${connections.length} script connection(s).`,
200
- connections,
201
- },
202
- };
174
+ return toolOk(`Found ${connections.length} script connection(s).`, {
175
+ details: provenanceLines.length > 0 ? provenanceLines.join("\n") : undefined,
176
+ data: { yourAgentId: requestInfo.agentId, connections },
177
+ });
203
178
  }
204
179
 
205
180
  if (args.action === "disable") {
206
181
  if (!args.id) {
207
- return {
208
- content: [{ type: "text", text: "id is required for disable." }],
209
- structuredContent: {
182
+ return toolErr("id is required for disable.", {
183
+ data: {
210
184
  yourAgentId: requestInfo.agentId,
211
- success: false,
212
- message: "id is required for disable.",
213
185
  connections: listScriptConnections({ includeDisabled: true, allScopes: true }),
214
186
  },
215
- };
187
+ });
216
188
  }
217
189
  setScriptConnectionEnabled(args.id, false);
218
190
  const connections = listScriptConnections({ includeDisabled: true, allScopes: true });
219
- return {
220
- content: [{ type: "text", text: "Script connection disabled." }],
221
- structuredContent: {
222
- yourAgentId: requestInfo.agentId,
223
- success: true,
224
- message: "Script connection disabled.",
225
- connections,
226
- },
227
- };
191
+ return toolOk("Script connection disabled.", {
192
+ data: { yourAgentId: requestInfo.agentId, connections },
193
+ });
228
194
  }
229
195
 
230
196
  if (args.action === "refresh") {
231
197
  if (!args.id) {
232
- return {
233
- content: [{ type: "text", text: "id is required for refresh." }],
234
- structuredContent: {
198
+ return toolErr("id is required for refresh.", {
199
+ data: {
235
200
  yourAgentId: requestInfo.agentId,
236
- success: false,
237
- message: "id is required for refresh.",
238
201
  connections: listScriptConnections({ includeDisabled: true, allScopes: true }),
239
202
  },
240
- };
203
+ });
241
204
  }
242
205
  const refreshed = await refreshScriptConnection(args.id, null, requestInfo.agentId);
243
206
  const connections = listScriptConnections({ includeDisabled: true, allScopes: true });
244
207
  if (!refreshed) {
245
- return {
246
- content: [{ type: "text", text: "Script connection not found." }],
247
- structuredContent: {
248
- yourAgentId: requestInfo.agentId,
249
- success: false,
250
- message: "Script connection not found.",
251
- connections,
252
- },
253
- };
208
+ return toolErr("Script connection not found.", {
209
+ data: { yourAgentId: requestInfo.agentId, connections },
210
+ });
254
211
  }
255
- return {
256
- content: [
257
- {
258
- type: "text",
259
- text: `Script connection ${refreshed.slug} refreshed (${baseUrlProvenanceText(refreshed)}).`,
260
- },
261
- ],
262
- structuredContent: {
263
- yourAgentId: requestInfo.agentId,
264
- success: !refreshed.generationError,
265
- message: refreshed.generationError
266
- ? `Refreshed but generation failed: ${refreshed.generationError}`
267
- : `Script connection ${refreshed.slug} refreshed.`,
268
- connections,
269
- },
212
+ const extras = {
213
+ details: baseUrlProvenanceText(refreshed),
214
+ data: { yourAgentId: requestInfo.agentId, connections },
270
215
  };
216
+ return refreshed.generationError
217
+ ? toolErr(`Refreshed but generation failed: ${refreshed.generationError}`, extras)
218
+ : toolOk(`Script connection ${refreshed.slug} refreshed.`, extras);
271
219
  }
272
220
 
273
221
  if (args.action === "upsert-mcp") {
274
222
  if (!args.slug || !args.mcpServerId) {
275
- return {
276
- content: [{ type: "text", text: "slug and mcpServerId are required." }],
277
- structuredContent: {
223
+ return toolErr("slug and mcpServerId are required.", {
224
+ data: {
278
225
  yourAgentId: requestInfo.agentId,
279
- success: false,
280
- message: "slug and mcpServerId are required.",
281
226
  connections: listScriptConnections({ includeDisabled: true, allScopes: true }),
282
227
  },
283
- };
228
+ });
284
229
  }
285
230
 
286
231
  const existing = args.id ? getScriptConnectionById(args.id) : null;
@@ -298,30 +243,20 @@ export const registerScriptConnectionsTool = (server: McpServer) => {
298
243
  });
299
244
 
300
245
  const connections = listScriptConnections({ includeDisabled: true, allScopes: true });
301
- return {
302
- content: [{ type: "text", text: `Script MCP connection ${connection.slug} saved.` }],
303
- structuredContent: {
304
- yourAgentId: requestInfo.agentId,
305
- success: !connection.generationError,
306
- message: connection.generationError
307
- ? `Saved but generation failed: ${connection.generationError}`
308
- : `Script MCP connection ${connection.slug} saved.`,
309
- connections,
310
- },
311
- };
246
+ const extras = { data: { yourAgentId: requestInfo.agentId, connections } };
247
+ return connection.generationError
248
+ ? toolErr(`Saved but generation failed: ${connection.generationError}`, extras)
249
+ : toolOk(`Script MCP connection ${connection.slug} saved.`, extras);
312
250
  }
313
251
 
314
252
  if (args.action === "upsert-graphql") {
315
253
  if (!args.slug || !args.baseUrl || !args.allowedHosts?.length) {
316
- return {
317
- content: [{ type: "text", text: "slug, baseUrl, and allowedHosts are required." }],
318
- structuredContent: {
254
+ return toolErr("slug, baseUrl, and allowedHosts are required.", {
255
+ data: {
319
256
  yourAgentId: requestInfo.agentId,
320
- success: false,
321
- message: "slug, baseUrl, and allowedHosts are required.",
322
257
  connections: listScriptConnections({ includeDisabled: true, allScopes: true }),
323
258
  },
324
- };
259
+ });
325
260
  }
326
261
 
327
262
  const existing = args.id ? getScriptConnectionById(args.id) : null;
@@ -347,51 +282,30 @@ export const registerScriptConnectionsTool = (server: McpServer) => {
347
282
  });
348
283
 
349
284
  const connections = listScriptConnections({ includeDisabled: true, allScopes: true });
350
- return {
351
- content: [{ type: "text", text: `Script GraphQL connection ${connection.slug} saved.` }],
352
- structuredContent: {
353
- yourAgentId: requestInfo.agentId,
354
- success: !connection.generationError,
355
- message: connection.generationError
356
- ? `Saved but generation failed: ${connection.generationError}`
357
- : `Script GraphQL connection ${connection.slug} saved.`,
358
- connections,
359
- },
360
- };
285
+ const extras = { data: { yourAgentId: requestInfo.agentId, connections } };
286
+ return connection.generationError
287
+ ? toolErr(`Saved but generation failed: ${connection.generationError}`, extras)
288
+ : toolOk(`Script GraphQL connection ${connection.slug} saved.`, extras);
361
289
  }
362
290
 
363
291
  if (!args.slug || (!args.openapiSpecJson && !args.openapiSpecUrl && !args.specSource)) {
364
- return {
365
- content: [
366
- {
367
- type: "text",
368
- text: "slug and exactly one OpenAPI spec source (openapiSpecJson, openapiSpecUrl, or specSource) are required.",
292
+ return toolErr(
293
+ "slug and exactly one OpenAPI spec source (openapiSpecJson, openapiSpecUrl, or specSource) are required.",
294
+ {
295
+ data: {
296
+ yourAgentId: requestInfo.agentId,
297
+ connections: listScriptConnections({ includeDisabled: true, allScopes: true }),
369
298
  },
370
- ],
371
- structuredContent: {
372
- yourAgentId: requestInfo.agentId,
373
- success: false,
374
- message:
375
- "slug and exactly one OpenAPI spec source (openapiSpecJson, openapiSpecUrl, or specSource) are required.",
376
- connections: listScriptConnections({ includeDisabled: true, allScopes: true }),
377
299
  },
378
- };
300
+ );
379
301
  }
380
302
  if ([args.openapiSpecJson, args.openapiSpecUrl, args.specSource].filter(Boolean).length > 1) {
381
- return {
382
- content: [
383
- {
384
- type: "text",
385
- text: "Provide exactly one OpenAPI spec source.",
386
- },
387
- ],
388
- structuredContent: {
303
+ return toolErr("Provide exactly one OpenAPI spec source.", {
304
+ data: {
389
305
  yourAgentId: requestInfo.agentId,
390
- success: false,
391
- message: "Provide exactly one OpenAPI spec source.",
392
306
  connections: listScriptConnections({ includeDisabled: true, allScopes: true }),
393
307
  },
394
- };
308
+ });
395
309
  }
396
310
 
397
311
  const existing = args.id ? getScriptConnectionById(args.id) : null;
@@ -421,22 +335,13 @@ export const registerScriptConnectionsTool = (server: McpServer) => {
421
335
  });
422
336
 
423
337
  const connections = listScriptConnections({ includeDisabled: true, allScopes: true });
424
- return {
425
- content: [
426
- {
427
- type: "text",
428
- text: `Script connection ${connection.slug} saved (${baseUrlProvenanceText(connection)}).`,
429
- },
430
- ],
431
- structuredContent: {
432
- yourAgentId: requestInfo.agentId,
433
- success: !connection.generationError,
434
- message: connection.generationError
435
- ? `Saved but generation failed: ${connection.generationError}`
436
- : `Script connection ${connection.slug} saved.`,
437
- connections,
438
- },
338
+ const extras = {
339
+ details: baseUrlProvenanceText(connection),
340
+ data: { yourAgentId: requestInfo.agentId, connections },
439
341
  };
342
+ return connection.generationError
343
+ ? toolErr(`Saved but generation failed: ${connection.generationError}`, extras)
344
+ : toolOk(`Script connection ${connection.slug} saved.`, extras);
440
345
  },
441
346
  );
442
347
  };
@@ -9,7 +9,31 @@ import {
9
9
  } from "./script-common";
10
10
 
11
11
  export const SCRIPT_QUERY_TYPES_DESCRIPTION =
12
- "Fetch the signature + the auto-generated `swarm-sdk.d.ts` (derived from the live MCP tool registry) + the `stdlib.d.ts` blobs — for IDE-style introspection before authoring or running a script. The same types are used by `script-upsert`'s typecheck pass, so they are authoritative.";
12
+ "Fetch the auto-generated `swarm-sdk.d.ts` (derived from the live MCP tool registry) + the `stdlib.d.ts` blobs — for IDE-style introspection before authoring or running a script. Pass `name` to also get that script's signature; omit it for the swarm-wide type surface. The same types are used by `script-upsert`'s typecheck pass, so they are authoritative.";
13
+
14
+ function renderTypeBlobs(data: unknown): string | undefined {
15
+ if (typeof data !== "object" || data === null) return undefined;
16
+ const body = data as {
17
+ signature?: unknown;
18
+ argsJsonSchema?: unknown;
19
+ sdkTypes?: unknown;
20
+ stdlibTypes?: unknown;
21
+ };
22
+ const parts: string[] = [];
23
+ if (body.signature !== undefined && body.signature !== null) {
24
+ parts.push(`signature:\n${JSON.stringify(body.signature, null, 2)}`);
25
+ }
26
+ if (body.argsJsonSchema !== undefined && body.argsJsonSchema !== null) {
27
+ parts.push(`argsJsonSchema:\n${JSON.stringify(body.argsJsonSchema, null, 2)}`);
28
+ }
29
+ if (typeof body.sdkTypes === "string" && body.sdkTypes) {
30
+ parts.push(`swarm-sdk.d.ts:\n${body.sdkTypes}`);
31
+ }
32
+ if (typeof body.stdlibTypes === "string" && body.stdlibTypes) {
33
+ parts.push(`stdlib.d.ts:\n${body.stdlibTypes}`);
34
+ }
35
+ return parts.length > 0 ? parts.join("\n\n") : undefined;
36
+ }
13
37
 
14
38
  export const registerScriptQueryTypesTool = (server: McpServer) => {
15
39
  createToolRegistrar(server)(
@@ -19,18 +43,34 @@ export const registerScriptQueryTypesTool = (server: McpServer) => {
19
43
  description: SCRIPT_QUERY_TYPES_DESCRIPTION,
20
44
  annotations: { readOnlyHint: true, openWorldHint: false },
21
45
  inputSchema: z.object({
22
- name: scriptNameSchema.describe("Script name whose signature should be fetched."),
46
+ name: scriptNameSchema
47
+ .optional()
48
+ .describe(
49
+ "Optional script name whose signature should be fetched. Omit to get the swarm-wide sdk/stdlib type surface.",
50
+ ),
23
51
  scope: scriptScopeSchema.optional().describe("Optional scope for script resolution."),
24
52
  }),
25
53
  outputSchema: scriptToolOutputSchema,
26
54
  },
27
55
  async ({ name, scope }, requestInfo) => {
56
+ if (!name) {
57
+ return proxyScriptsApi({
58
+ method: "GET",
59
+ path: "/api/scripts/type-defs",
60
+ requestInfo,
61
+ successMessage: () => "Swarm script SDK + stdlib type definitions fetched.",
62
+ successDetails: renderTypeBlobs,
63
+ uncappedDetails: true,
64
+ });
65
+ }
28
66
  const query = scope ? `?scope=${encodeURIComponent(scope)}` : "";
29
67
  return proxyScriptsApi({
30
68
  method: "GET",
31
69
  path: `/api/scripts/${encodeURIComponent(name)}/types${query}`,
32
70
  requestInfo,
33
- successMessage: () => "Script type query completed.",
71
+ successMessage: () => `Type definitions for script \`${name}\` fetched.`,
72
+ successDetails: renderTypeBlobs,
73
+ uncappedDetails: true,
34
74
  });
35
75
  },
36
76
  );
@@ -10,7 +10,39 @@ import {
10
10
  } from "./script-common";
11
11
 
12
12
  export const SCRIPT_RUN_DESCRIPTION =
13
- "Run a named swarm-shared script (callable across agents and from workflow `swarm-script` nodes), OR inline source (auto-saved as scratch to the catalog). Use for swarm-visible, durable scripts. For local-only throwaway TS, use code-mode `run`.";
13
+ "Run a named swarm-shared script (callable across agents and from workflow `swarm-script` nodes), OR inline source (auto-saved as scratch to the catalog). Inline source executes without the `script-upsert` compile-time typecheck. Use for swarm-visible, durable scripts. For local-only throwaway TS, use code-mode `run`.";
14
+
15
+ function renderRunOutput(data: unknown): string | undefined {
16
+ if (typeof data !== "object" || data === null) return undefined;
17
+ const body = data as {
18
+ result?: unknown;
19
+ stdout?: string;
20
+ durationMs?: number;
21
+ truncated?: { stdout?: boolean; stderr?: boolean };
22
+ autoSaved?: { slug?: string };
23
+ kvSaved?: { namespace?: string; key?: string };
24
+ };
25
+ const parts: string[] = [];
26
+ if (body.result !== undefined) {
27
+ parts.push(
28
+ `result:\n${typeof body.result === "string" ? body.result : JSON.stringify(body.result, null, 2)}`,
29
+ );
30
+ }
31
+ if (typeof body.stdout === "string" && body.stdout.trim()) {
32
+ parts.push(`stdout:\n${body.stdout.trim()}`);
33
+ }
34
+ const notes: string[] = [];
35
+ if (typeof body.durationMs === "number") notes.push(`${body.durationMs}ms`);
36
+ if (body.truncated?.stdout || body.truncated?.stderr) {
37
+ notes.push("output truncated by the runtime");
38
+ }
39
+ if (body.autoSaved?.slug) notes.push(`auto-saved as scratch script \`${body.autoSaved.slug}\``);
40
+ if (body.kvSaved?.key) {
41
+ notes.push(`output persisted to kv ${body.kvSaved.namespace}/${body.kvSaved.key}`);
42
+ }
43
+ if (notes.length > 0) parts.push(`(${notes.join("; ")})`);
44
+ return parts.length > 0 ? parts.join("\n\n") : undefined;
45
+ }
14
46
 
15
47
  export const registerScriptRunTool = (server: McpServer) => {
16
48
  createToolRegistrar(server)(
@@ -21,7 +53,13 @@ export const registerScriptRunTool = (server: McpServer) => {
21
53
  annotations: { openWorldHint: true },
22
54
  inputSchema: z.object({
23
55
  name: scriptNameSchema.optional().describe("Name of a reusable script to run."),
24
- source: z.string().min(1).optional().describe("Inline TypeScript source to run."),
56
+ source: z
57
+ .string()
58
+ .min(1)
59
+ .optional()
60
+ .describe(
61
+ 'Inline TypeScript source to run without a compile-time typecheck. Must `export default async function (args, ctx)` — args FIRST, ctx second. Import `ScriptContext` from "swarm-sdk" for promotion-safe typing.',
62
+ ),
25
63
  args: z.unknown().optional().describe("JSON-serializable script arguments."),
26
64
  intent: z.string().default("").describe("Why this script is being run."),
27
65
  scope: scriptScopeSchema.optional().describe("Optional scope for named script resolution."),
@@ -45,6 +83,7 @@ export const registerScriptRunTool = (server: McpServer) => {
45
83
  body: args,
46
84
  requestInfo,
47
85
  successMessage: () => "Script run completed.",
86
+ successDetails: renderRunOutput,
48
87
  }),
49
88
  );
50
89
  };
@@ -13,6 +13,66 @@ export const GET_SCRIPT_RUN_DESCRIPTION =
13
13
  export const LIST_SCRIPT_RUNS_DESCRIPTION =
14
14
  "List durable script workflow runs, optionally filtered by status or agent ID.";
15
15
 
16
+ const JOURNAL_RENDER_LIMIT = 20;
17
+ const JOURNAL_VALUE_CAP = 400;
18
+
19
+ function journalValuePreview(value: unknown): string | undefined {
20
+ if (value === undefined || value === null) return undefined;
21
+ const serialized = typeof value === "string" ? value : JSON.stringify(value);
22
+ if (!serialized) return undefined;
23
+ return serialized.length > JOURNAL_VALUE_CAP
24
+ ? `${serialized.slice(0, JOURNAL_VALUE_CAP)}…`
25
+ : serialized;
26
+ }
27
+
28
+ function renderRunDetail(data: unknown): string | undefined {
29
+ if (typeof data !== "object" || data === null) return undefined;
30
+ const run = (data as { run?: Record<string, unknown> }).run;
31
+ if (!run) return undefined;
32
+ const lines: string[] = [];
33
+ if (typeof run.status === "string") lines.push(`status: ${run.status}`);
34
+ if (typeof run.error === "string" && run.error) lines.push(`error: ${run.error}`);
35
+ if (run.output !== undefined && run.output !== null) {
36
+ lines.push(`output: ${JSON.stringify(run.output)}`);
37
+ }
38
+ // Journal entries must reach the text channel — most harnesses never show
39
+ // the model structuredContent, and a bare count hides step outcomes.
40
+ const journal = (data as { journal?: unknown[] }).journal;
41
+ if (Array.isArray(journal) && journal.length > 0) {
42
+ lines.push(`journal (${journal.length} entr${journal.length === 1 ? "y" : "ies"}):`);
43
+ for (const raw of journal.slice(0, JOURNAL_RENDER_LIMIT)) {
44
+ const entry = (raw ?? {}) as Record<string, unknown>;
45
+ const key = String(entry.stepKey ?? entry.label ?? entry.id ?? "?");
46
+ const kind = typeof entry.stepType === "string" ? ` [${entry.stepType}]` : "";
47
+ const status = typeof entry.status === "string" ? ` ${entry.status}` : "";
48
+ const error =
49
+ typeof entry.error === "string" && entry.error ? ` — error: ${entry.error}` : "";
50
+ const output = error ? undefined : journalValuePreview(entry.output ?? entry.result);
51
+ lines.push(`- ${key}${kind}:${status}${error}${output ? ` — ${output}` : ""}`);
52
+ }
53
+ if (journal.length > JOURNAL_RENDER_LIMIT) {
54
+ lines.push(
55
+ `… +${journal.length - JOURNAL_RENDER_LIMIT} more entries (see structuredContent.data.journal)`,
56
+ );
57
+ }
58
+ }
59
+ return lines.length > 0 ? lines.join("\n") : undefined;
60
+ }
61
+
62
+ function renderRunsList(data: unknown): string | undefined {
63
+ if (typeof data !== "object" || data === null) return undefined;
64
+ const runs = (data as { runs?: unknown[] }).runs;
65
+ if (!Array.isArray(runs) || runs.length === 0) return undefined;
66
+ return runs
67
+ .map((entry) => {
68
+ const run = entry as Record<string, unknown>;
69
+ const name = typeof run.scriptName === "string" && run.scriptName ? ` ${run.scriptName}` : "";
70
+ const error = typeof run.error === "string" && run.error ? ` — ${run.error}` : "";
71
+ return `- ${String(run.id ?? "?")}${name}: ${String(run.status ?? "unknown")}${error}`;
72
+ })
73
+ .join("\n");
74
+ }
75
+
16
76
  export const registerScriptRunsTools = (server: McpServer) => {
17
77
  const register = createToolRegistrar(server);
18
78
 
@@ -23,7 +83,12 @@ export const registerScriptRunsTools = (server: McpServer) => {
23
83
  description: LAUNCH_SCRIPT_RUN_DESCRIPTION,
24
84
  annotations: { openWorldHint: true },
25
85
  inputSchema: z.object({
26
- source: z.string().min(1).describe("TypeScript script workflow source."),
86
+ source: z
87
+ .string()
88
+ .min(1)
89
+ .describe(
90
+ "TypeScript script workflow source. Must `export default async function (args, ctx)` — args FIRST, ctx second.",
91
+ ),
27
92
  args: z.unknown().optional().describe("JSON-serializable workflow arguments."),
28
93
  idempotencyKey: z
29
94
  .string()
@@ -83,6 +148,8 @@ export const registerScriptRunsTools = (server: McpServer) => {
83
148
  : "unknown";
84
149
  return `Script run ${id} status: ${status}.`;
85
150
  },
151
+ successDetails: renderRunDetail,
152
+ failureDetails: renderRunDetail,
86
153
  }),
87
154
  );
88
155
 
@@ -117,6 +184,7 @@ export const registerScriptRunsTools = (server: McpServer) => {
117
184
  : 0;
118
185
  return `Found ${Number.isFinite(total) ? total : 0} script run(s).`;
119
186
  },
187
+ successDetails: renderRunsList,
120
188
  });
121
189
  },
122
190
  );
@@ -6,6 +6,20 @@ import { proxyScriptsApi, scriptScopeSchema, scriptToolOutputSchema } from "./sc
6
6
  export const SCRIPT_SEARCH_DESCRIPTION =
7
7
  "Semantic search over swarm-shared TypeScript scripts (catalog persisted in the agent-swarm DB; callable from agents and workflows). For ephemeral throwaway TS on your local machine, use code-mode instead.";
8
8
 
9
+ function renderSearchResults(data: unknown): string | undefined {
10
+ if (typeof data !== "object" || data === null) return undefined;
11
+ const results = (data as { results?: unknown[] }).results;
12
+ if (!Array.isArray(results) || results.length === 0) return undefined;
13
+ return results
14
+ .map((entry) => {
15
+ const item = entry as { name?: unknown; description?: unknown; score?: unknown };
16
+ const description =
17
+ typeof item.description === "string" && item.description ? ` — ${item.description}` : "";
18
+ return `- ${String(item.name ?? "?")}${description}`;
19
+ })
20
+ .join("\n");
21
+ }
22
+
9
23
  export const registerScriptSearchTool = (server: McpServer) => {
10
24
  createToolRegistrar(server)(
11
25
  "script-search",
@@ -26,7 +40,16 @@ export const registerScriptSearchTool = (server: McpServer) => {
26
40
  path: "/api/scripts/search",
27
41
  body: args,
28
42
  requestInfo,
29
- successMessage: () => "Script search completed.",
43
+ successMessage: (data) => {
44
+ const results =
45
+ typeof data === "object" &&
46
+ data !== null &&
47
+ Array.isArray((data as { results?: unknown[] }).results)
48
+ ? (data as { results: unknown[] }).results
49
+ : [];
50
+ return `Found ${results.length} script(s).`;
51
+ },
52
+ successDetails: renderSearchResults,
30
53
  }),
31
54
  );
32
55
  };
@@ -10,7 +10,7 @@ import {
10
10
  } from "./script-common";
11
11
 
12
12
  export const SCRIPT_UPSERT_DESCRIPTION =
13
- "Persist a TypeScript script to the swarm catalog under your agent scope (or global if you're a lead). Other agents and workflow nodes will be able to find and run it. For local-only scripts, use code-mode `save`.";
13
+ 'Typecheck and persist a TypeScript script to the swarm catalog under your agent scope (or global if you\'re a lead). Import `ScriptContext` from "swarm-sdk" for a real context type. Other agents and workflow nodes will be able to find and run it. For local-only scripts, use code-mode `save`.';
14
14
 
15
15
  export const registerScriptUpsertTool = (server: McpServer) => {
16
16
  createToolRegistrar(server)(
@@ -21,7 +21,12 @@ export const registerScriptUpsertTool = (server: McpServer) => {
21
21
  annotations: { openWorldHint: false },
22
22
  inputSchema: z.object({
23
23
  name: scriptNameSchema.describe("Stable script name within the selected scope."),
24
- source: z.string().min(1).describe("TypeScript source with a default export function."),
24
+ source: z
25
+ .string()
26
+ .min(1)
27
+ .describe(
28
+ 'TypeScript source, typechecked before saving. Must `export default async function (args, ctx)` — args FIRST, ctx second. Import `ScriptContext` from "swarm-sdk" to type `ctx`.',
29
+ ),
25
30
  description: z.string().default("").describe("Human-readable script description."),
26
31
  intent: z.string().default("").describe("Why this script exists."),
27
32
  scope: scriptScopeSchema.default("agent").describe("Persist under agent or global scope."),
@@ -37,7 +42,17 @@ export const registerScriptUpsertTool = (server: McpServer) => {
37
42
  path: "/api/scripts/upsert",
38
43
  body: args,
39
44
  requestInfo,
40
- successMessage: () => "Script upsert completed.",
45
+ successMessage: (data) => {
46
+ const body = (data ?? {}) as {
47
+ name?: unknown;
48
+ version?: unknown;
49
+ contentDeduped?: unknown;
50
+ };
51
+ const name = typeof body.name === "string" ? body.name : args.name;
52
+ const version = typeof body.version === "number" ? ` v${body.version}` : "";
53
+ const deduped = body.contentDeduped ? " (content unchanged — deduped)" : "";
54
+ return `Script \`${name}\`${version} saved.${deduped}`;
55
+ },
41
56
  }),
42
57
  );
43
58
  };