@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.
- package/README.md +2 -1
- package/dist/{actions-e4c9f0xy.js → actions-z3d0fk7z.js} +6 -6
- package/dist/{app-vmvmj2v3.js → app-q2rc9tdr.js} +4 -4
- package/dist/{assistant-yn7a792a.js → assistant-3stjq7fz.js} +9 -9
- package/dist/{boot-reembed-xg1r86h2.js → boot-reembed-5867whnb.js} +3 -3
- package/dist/{boot-reembed-chxty50a.js → boot-reembed-v6r1df32.js} +4 -4
- package/dist/{boot-scrub-logs-exwddvp5.js → boot-scrub-logs-8b8jegk3.js} +2 -2
- package/dist/{cli-1592nfd6.js → cli-0925phzv.js} +1 -1
- package/dist/{cli-hbbxmhec.js → cli-2yr6edr7.js} +4 -4
- package/dist/{cli-8cq4z4x7.js → cli-3z4q09tn.js} +182 -19
- package/dist/{cli-vz9drmce.js → cli-5jn6wnd9.js} +17 -8
- package/dist/{cli-5arfywtm.js → cli-5ncdb7ff.js} +19 -9
- package/dist/{cli-3tv9z4wx.js → cli-92bqgbgy.js} +1 -1
- package/dist/{cli-fjf04hpa.js → cli-dq2ssyf0.js} +48 -56
- package/dist/{cli-mngsj9fx.js → cli-gkvf8d83.js} +1 -1
- package/dist/{cli-mepk1j0t.js → cli-gzjsamwc.js} +2 -2
- package/dist/{cli-c9m59f83.js → cli-h89g0qrd.js} +1 -1
- package/dist/{cli-n8mf7x4b.js → cli-jp4mdj9d.js} +2 -2
- package/dist/{cli-822d4bjk.js → cli-kk58tg33.js} +7 -7
- package/dist/{cli-9hj1adgp.js → cli-mcez7z4p.js} +1 -1
- package/dist/{cli-byv3720g.js → cli-mmk5vagg.js} +2 -2
- package/dist/{cli-zdp11t8m.js → cli-p0ec4vv6.js} +1 -1
- package/dist/{cli-h2say6xk.js → cli-p0zgv8pj.js} +3 -1
- package/dist/{cli-8ef5ky75.js → cli-perb20ma.js} +1 -1
- package/dist/{cli-zkj6f2sk.js → cli-qf7acvyr.js} +90 -4
- package/dist/{cli-kmm1rwmp.js → cli-qwsagsmg.js} +1 -1
- package/dist/{cli-we91ywvy.js → cli-sqv6c9b8.js} +6 -6
- package/dist/{cli-np0yhmmk.js → cli-vm20sh8d.js} +3 -3
- package/dist/{cli-p11rf59d.js → cli-wn3m6q54.js} +3 -3
- package/dist/{cli-mkpf4ndf.js → cli-x268say8.js} +2976 -5621
- package/dist/{cli-ngbsk4yx.js → cli-y43n987v.js} +1 -1
- package/dist/{cli-4509mwm5.js → cli-ykthjw29.js} +8 -8
- package/dist/{cli-9eka6jwv.js → cli-zxb72ctk.js} +2 -2
- package/dist/cli.js +12 -10
- package/dist/{commands-sjk3zfyr.js → commands-sda76yn8.js} +2 -2
- package/dist/{db-2je5agjb.js → db-vn9e4rqj.js} +6 -2
- package/dist/{e2b-2s4psnbf.js → e2b-q345y8s4.js} +0 -4
- package/dist/{handlers-yzv369hf.js → handlers-xfja18ac.js} +9 -9
- package/dist/{hook-rfsj2r8x.js → hook-2medrp47.js} +1 -40
- package/dist/{http-v9rr144m.js → http-937pyjfc.js} +99 -44
- package/dist/{index-nr2199m6.js → index-2bqd2q9v.js} +11 -11
- package/dist/{index-3xtk777g.js → index-gw4en7jg.js} +9 -9
- package/dist/{index-c3tan44f.js → index-knqczmnm.js} +10 -10
- package/dist/{index-smjdc3h9.js → index-vah60vxp.js} +8 -8
- package/dist/{keepalive-5ds53bjd.js → keepalive-20rd6hxh.js} +5 -5
- package/dist/{lead-5xhez25b.js → lead-7w2k3a49.js} +21 -21
- package/dist/{maintenance-b43d24q6.js → maintenance-p3x918yw.js} +4 -4
- package/dist/{oauth-refresh-sweep-qe286vn2.js → oauth-refresh-sweep-shm0nzm4.js} +4 -4
- package/dist/{onboard-c4r3ds3z.js → onboard-py9dnf54.js} +6 -2
- package/dist/{otel-impl-nv3rjw61.js → otel-impl-7yjkfg68.js} +1 -1
- package/dist/{pi-mono-adapter-2syx1x4d.js → pi-mono-adapter-z6h98fva.js} +4 -38
- package/dist/{pricing-refresh-5ct2wp4k.js → pricing-refresh-3snb6370.js} +4 -4
- package/dist/{rbac-roles-m502w0qv.js → rbac-roles-5e72bbpk.js} +3 -3
- package/dist/{rbac-roles-b82cxpxn.js → rbac-roles-gqxdp8st.js} +4 -4
- package/dist/{seed-pricing-jhjphbf0.js → seed-pricing-bg42d7h2.js} +3 -3
- package/dist/{setup-zbaspydq.js → setup-nzk3kbbq.js} +2 -2
- package/dist/{worker-snvhpax5.js → worker-0p1jdzkm.js} +21 -21
- package/openapi.json +146 -1
- package/package.json +3 -1
- package/src/be/db.ts +81 -4
- package/src/be/models-catalog.ts +156 -0
- package/src/be/modelsdev-cache.ts +14 -1
- package/src/be/pricing-refresh.ts +2 -0
- package/src/be/scripts/typecheck.ts +17 -4
- package/src/be/seed-scripts/catalog/task-context-gathering.ts +1 -1
- package/src/commands/onboard/env-generator.ts +12 -0
- package/src/e2b/env.ts +0 -4
- package/src/hooks/hook.ts +0 -67
- package/src/http/all-routes.ts +1 -0
- package/src/http/index.ts +2 -0
- package/src/http/models-catalog.ts +65 -0
- package/src/http/workflows.ts +16 -4
- package/src/prompts/base-prompt.ts +8 -7
- package/src/prompts/session-templates.ts +106 -12
- package/src/providers/pi-mono-adapter.ts +12 -2
- package/src/providers/pi-mono-extension.ts +0 -64
- package/src/providers/pricing-sources.md +16 -1
- package/src/scripts-runtime/eval-harness.ts +18 -1
- package/src/scripts-runtime/swarm-sdk.ts +10 -0
- package/src/scripts-runtime/types/stdlib.d.ts +13 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +13 -0
- package/src/server-user.ts +4 -7
- package/src/slack/blocks.ts +21 -8
- package/src/slack/responses.ts +27 -51
- package/src/slack/watcher.ts +22 -5
- package/src/telemetry.ts +169 -3
- package/src/tests/base-prompt.test.ts +79 -0
- package/src/tests/mcp-tools-user.test.ts +62 -16
- package/src/tests/mcp-tools.test.ts +6 -3
- package/src/tests/memory-edit.test.ts +21 -4
- package/src/tests/model-groups-live-catalog.test.ts +65 -0
- package/src/tests/models-catalog.test.ts +119 -0
- package/src/tests/oauth-access-token-tool.test.ts +71 -1
- package/src/tests/pricing-refresh.test.ts +25 -0
- package/src/tests/prompt-template-session.test.ts +142 -5
- package/src/tests/rbac-charact-skills.test.ts +81 -14
- package/src/tests/script-apis-mcp.test.ts +56 -8
- package/src/tests/scripts-mcp-e2e.test.ts +157 -8
- package/src/tests/scripts-typecheck.test.ts +17 -0
- package/src/tests/sdk-allowlist.test.ts +34 -1
- package/src/tests/seed-scripts.test.ts +43 -0
- package/src/tests/slack-blocks.test.ts +2 -1
- package/src/tests/slack-inline-output.test.ts +24 -30
- package/src/tests/slack-watcher.test.ts +42 -0
- package/src/tests/steer-task-tool.test.ts +37 -8
- package/src/tests/steering-transport.test.ts +18 -3
- package/src/tests/swarm-tool-result-gate.test.ts +399 -0
- package/src/tests/task-tools-ctx.test.ts +49 -17
- package/src/tests/task-tools-ownership.test.ts +41 -13
- package/src/tests/telemetry-init.test.ts +376 -2
- package/src/tests/tool-output-agent-id.test.ts +14 -2
- package/src/tests/workflow-http-v2.test.ts +116 -0
- package/src/tools/accept-steer.ts +45 -53
- package/src/tools/cancel-task.ts +31 -41
- package/src/tools/context-diff.ts +19 -63
- package/src/tools/context-history.ts +22 -51
- package/src/tools/create-channel.ts +24 -39
- package/src/tools/create-metric.ts +19 -82
- package/src/tools/create-page.ts +20 -81
- package/src/tools/credential-bindings/tool.ts +125 -246
- package/src/tools/db-query.ts +13 -24
- package/src/tools/delete-channel.ts +25 -71
- package/src/tools/delete-page.ts +27 -75
- package/src/tools/get-metrics.ts +29 -22
- package/src/tools/get-swarm.ts +44 -15
- package/src/tools/get-task-details.ts +150 -32
- package/src/tools/get-tasks.ts +63 -29
- package/src/tools/inject-learning.ts +8 -38
- package/src/tools/join-swarm.ts +45 -47
- package/src/tools/kv/kv-delete.ts +13 -37
- package/src/tools/kv/kv-get.ts +38 -29
- package/src/tools/kv/kv-incr.ts +28 -56
- package/src/tools/kv/kv-list.ts +40 -31
- package/src/tools/kv/kv-set.ts +34 -76
- package/src/tools/list-channels.ts +24 -17
- package/src/tools/list-services.ts +37 -45
- package/src/tools/manage-user.ts +53 -66
- package/src/tools/mcp-servers/mcp-server-create.ts +19 -55
- package/src/tools/mcp-servers/mcp-server-delete.ts +9 -39
- package/src/tools/mcp-servers/mcp-server-get.ts +9 -35
- package/src/tools/mcp-servers/mcp-server-install.ts +13 -60
- package/src/tools/mcp-servers/mcp-server-list.ts +28 -26
- package/src/tools/mcp-servers/mcp-server-uninstall.ts +10 -36
- package/src/tools/mcp-servers/mcp-server-update.ts +13 -57
- package/src/tools/memory-delete.ts +16 -46
- package/src/tools/memory-edit.ts +48 -49
- package/src/tools/memory-get.ts +40 -36
- package/src/tools/memory-rate.ts +14 -44
- package/src/tools/memory-search.ts +46 -52
- package/src/tools/my-agent-info.ts +39 -33
- package/src/tools/oauth-access-token.ts +9 -24
- package/src/tools/poll-task.ts +50 -77
- package/src/tools/post-message.ts +24 -38
- package/src/tools/prompt-templates/delete.ts +16 -48
- package/src/tools/prompt-templates/get.ts +45 -42
- package/src/tools/prompt-templates/list.ts +29 -44
- package/src/tools/prompt-templates/preview.ts +14 -40
- package/src/tools/prompt-templates/set.ts +30 -52
- package/src/tools/read-messages.ts +45 -54
- package/src/tools/register-agentmail-inbox.ts +28 -84
- package/src/tools/register-kapso-number.ts +20 -50
- package/src/tools/register-service.ts +36 -44
- package/src/tools/repos/get-repos.ts +29 -21
- package/src/tools/repos/update-repo.ts +30 -27
- package/src/tools/request-human-input.ts +10 -33
- package/src/tools/resolve-user.ts +59 -16
- package/src/tools/schedules/create-schedule.ts +58 -173
- package/src/tools/schedules/delete-schedule.ts +16 -56
- package/src/tools/schedules/list-schedules.ts +41 -67
- package/src/tools/schedules/patch-schedule.ts +57 -153
- package/src/tools/schedules/run-schedule-now.ts +18 -59
- package/src/tools/schedules/update-schedule.ts +57 -153
- package/src/tools/script-apis.ts +46 -28
- package/src/tools/script-common.ts +129 -34
- package/src/tools/script-connections/tool.ts +59 -154
- package/src/tools/script-query-types.ts +43 -3
- package/src/tools/script-run.ts +41 -2
- package/src/tools/script-runs.ts +69 -1
- package/src/tools/script-search.ts +24 -1
- package/src/tools/script-upsert.ts +18 -3
- package/src/tools/send-task.ts +32 -81
- package/src/tools/skills/skill-create.ts +14 -39
- package/src/tools/skills/skill-delete.ts +14 -42
- package/src/tools/skills/skill-get-file.ts +10 -43
- package/src/tools/skills/skill-get.ts +9 -32
- package/src/tools/skills/skill-install-remote.ts +16 -52
- package/src/tools/skills/skill-install.ts +14 -52
- package/src/tools/skills/skill-list.ts +24 -26
- package/src/tools/skills/skill-publish.ts +18 -54
- package/src/tools/skills/skill-search.ts +21 -18
- package/src/tools/skills/skill-sync-remote.ts +12 -24
- package/src/tools/skills/skill-uninstall.ts +10 -26
- package/src/tools/skills/skill-update.ts +24 -81
- package/src/tools/slack-delete.ts +8 -32
- package/src/tools/slack-download-file.ts +17 -57
- package/src/tools/slack-list-channels.ts +16 -43
- package/src/tools/slack-post.ts +11 -40
- package/src/tools/slack-read.ts +33 -103
- package/src/tools/slack-reply.ts +16 -53
- package/src/tools/slack-start-thread.ts +14 -55
- package/src/tools/slack-update.ts +8 -35
- package/src/tools/slack-upload-file.ts +22 -122
- package/src/tools/steer-task.ts +22 -35
- package/src/tools/store-progress.ts +11 -26
- package/src/tools/swarm-config/delete-config.ts +19 -57
- package/src/tools/swarm-config/get-config.ts +36 -44
- package/src/tools/swarm-config/list-config.ts +36 -44
- package/src/tools/swarm-config/set-config.ts +35 -73
- package/src/tools/swarm-x.ts +20 -26
- package/src/tools/task-action.ts +26 -46
- package/src/tools/task-tool-ctx.ts +5 -13
- package/src/tools/tracker/tracker-link-task.ts +8 -22
- package/src/tools/tracker/tracker-map-agent.ts +8 -22
- package/src/tools/tracker/tracker-status.ts +27 -19
- package/src/tools/tracker/tracker-sync-status.ts +8 -18
- package/src/tools/tracker/tracker-unlink.ts +4 -16
- package/src/tools/unregister-service.ts +19 -59
- package/src/tools/update-profile.ts +60 -100
- package/src/tools/update-service-status.ts +42 -67
- package/src/tools/utils.ts +189 -8
- package/src/tools/whatsapp-message.ts +19 -32
- package/src/tools/workflows/cancel-workflow-run.ts +4 -16
- package/src/tools/workflows/create-workflow.ts +9 -38
- package/src/tools/workflows/delete-workflow.ts +5 -17
- package/src/tools/workflows/get-workflow-run.ts +41 -31
- package/src/tools/workflows/get-workflow.ts +10 -21
- package/src/tools/workflows/list-workflow-runs.ts +107 -34
- package/src/tools/workflows/list-workflows.ts +5 -17
- package/src/tools/workflows/patch-workflow-node.ts +11 -39
- package/src/tools/workflows/patch-workflow.ts +11 -36
- package/src/tools/workflows/retry-workflow-run.ts +4 -16
- package/src/tools/workflows/trigger-workflow.ts +22 -58
- package/src/tools/workflows/update-workflow.ts +10 -42
- package/templates/skills/swarm-scripts/SKILL.md +1 -1
package/src/tools/slack-reply.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import { getSlackApp } from "@/slack/app";
|
|
11
11
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
12
12
|
import { markdownToSlack } from "@/slack/responses";
|
|
13
|
-
import { createToolRegistrar } from "@/tools/utils";
|
|
13
|
+
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
14
14
|
|
|
15
15
|
export const registerSlackReplyTool = (server: McpServer) => {
|
|
16
16
|
createToolRegistrar(server)(
|
|
@@ -32,26 +32,18 @@ export const registerSlackReplyTool = (server: McpServer) => {
|
|
|
32
32
|
.describe("The task ID with Slack context (for task-related threads)."),
|
|
33
33
|
message: z.string().min(1).max(4000).describe("The message to send to the Slack thread."),
|
|
34
34
|
}),
|
|
35
|
-
outputSchema:
|
|
36
|
-
success: z.boolean(),
|
|
37
|
-
message: z.string(),
|
|
35
|
+
outputSchema: swarmToolOutputSchema({
|
|
38
36
|
messageTs: z.string().optional(),
|
|
39
37
|
}),
|
|
40
38
|
},
|
|
41
39
|
async ({ inboxMessageId, taskId, message }, requestInfo, _meta) => {
|
|
42
40
|
if (!requestInfo.agentId) {
|
|
43
|
-
return
|
|
44
|
-
content: [{ type: "text", text: "Agent ID not found." }],
|
|
45
|
-
structuredContent: { success: false, message: "Agent ID not found." },
|
|
46
|
-
};
|
|
41
|
+
return toolErr("Agent ID not found.");
|
|
47
42
|
}
|
|
48
43
|
|
|
49
44
|
const agent = getAgentById(requestInfo.agentId);
|
|
50
45
|
if (!agent) {
|
|
51
|
-
return
|
|
52
|
-
content: [{ type: "text", text: "Agent not found." }],
|
|
53
|
-
structuredContent: { success: false, message: "Agent not found." },
|
|
54
|
-
};
|
|
46
|
+
return toolErr("Agent not found.");
|
|
55
47
|
}
|
|
56
48
|
|
|
57
49
|
let slackChannelId: string | undefined;
|
|
@@ -61,16 +53,10 @@ export const registerSlackReplyTool = (server: McpServer) => {
|
|
|
61
53
|
if (inboxMessageId) {
|
|
62
54
|
const inboxMsg = getInboxMessageById(inboxMessageId);
|
|
63
55
|
if (!inboxMsg) {
|
|
64
|
-
return
|
|
65
|
-
content: [{ type: "text", text: "Inbox message not found." }],
|
|
66
|
-
structuredContent: { success: false, message: "Inbox message not found." },
|
|
67
|
-
};
|
|
56
|
+
return toolErr("Inbox message not found.");
|
|
68
57
|
}
|
|
69
58
|
if (inboxMsg.agentId !== requestInfo.agentId) {
|
|
70
|
-
return
|
|
71
|
-
content: [{ type: "text", text: "This inbox message is not yours." }],
|
|
72
|
-
structuredContent: { success: false, message: "This inbox message is not yours." },
|
|
73
|
-
};
|
|
59
|
+
return toolErr("This inbox message is not yours.");
|
|
74
60
|
}
|
|
75
61
|
slackChannelId = inboxMsg.slackChannelId;
|
|
76
62
|
slackThreadTs = inboxMsg.slackThreadTs;
|
|
@@ -80,41 +66,26 @@ export const registerSlackReplyTool = (server: McpServer) => {
|
|
|
80
66
|
} else if (taskId) {
|
|
81
67
|
const task = getTaskById(taskId);
|
|
82
68
|
if (!task) {
|
|
83
|
-
return
|
|
84
|
-
content: [{ type: "text", text: "Task not found." }],
|
|
85
|
-
structuredContent: { success: false, message: "Task not found." },
|
|
86
|
-
};
|
|
69
|
+
return toolErr("Task not found.");
|
|
87
70
|
}
|
|
88
71
|
// Verify agent has context for this task
|
|
89
72
|
if (task.agentId !== requestInfo.agentId && task.creatorAgentId !== requestInfo.agentId) {
|
|
90
|
-
return
|
|
91
|
-
content: [{ type: "text", text: "You don't have context for this task." }],
|
|
92
|
-
structuredContent: { success: false, message: "You don't have context for this task." },
|
|
93
|
-
};
|
|
73
|
+
return toolErr("You don't have context for this task.");
|
|
94
74
|
}
|
|
95
75
|
slackChannelId = task.slackChannelId;
|
|
96
76
|
slackThreadTs = task.slackThreadTs;
|
|
97
77
|
} else {
|
|
98
|
-
return
|
|
99
|
-
content: [{ type: "text", text: "Must provide inboxMessageId or taskId." }],
|
|
100
|
-
structuredContent: { success: false, message: "Must provide inboxMessageId or taskId." },
|
|
101
|
-
};
|
|
78
|
+
return toolErr("Must provide inboxMessageId or taskId.");
|
|
102
79
|
}
|
|
103
80
|
|
|
104
81
|
if (!slackChannelId || !slackThreadTs) {
|
|
105
|
-
return
|
|
106
|
-
content: [{ type: "text", text: "No Slack context available." }],
|
|
107
|
-
structuredContent: { success: false, message: "No Slack context available." },
|
|
108
|
-
};
|
|
82
|
+
return toolErr("No Slack context available.");
|
|
109
83
|
}
|
|
110
84
|
|
|
111
85
|
// Send the reply
|
|
112
86
|
const app = getSlackApp();
|
|
113
87
|
if (!app) {
|
|
114
|
-
return
|
|
115
|
-
content: [{ type: "text", text: "Slack not configured." }],
|
|
116
|
-
structuredContent: { success: false, message: "Slack not configured." },
|
|
117
|
-
};
|
|
88
|
+
return toolErr("Slack not configured.");
|
|
118
89
|
}
|
|
119
90
|
|
|
120
91
|
try {
|
|
@@ -147,20 +118,12 @@ export const registerSlackReplyTool = (server: McpServer) => {
|
|
|
147
118
|
console.log(`[Slack] Marked slackReplySent=1 for task ${taskId}`);
|
|
148
119
|
}
|
|
149
120
|
|
|
150
|
-
return {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
text: `Reply sent successfully.${messageTs ? ` Message timestamp: ${messageTs}` : ""}`,
|
|
155
|
-
},
|
|
156
|
-
],
|
|
157
|
-
structuredContent: { success: true, message: "Reply sent successfully.", messageTs },
|
|
158
|
-
};
|
|
121
|
+
return toolOk("Reply sent successfully.", {
|
|
122
|
+
details: messageTs ? `Message timestamp: ${messageTs}` : undefined,
|
|
123
|
+
data: { messageTs },
|
|
124
|
+
});
|
|
159
125
|
} catch (error) {
|
|
160
|
-
return {
|
|
161
|
-
content: [{ type: "text", text: `Failed to send reply: ${error}` }],
|
|
162
|
-
structuredContent: { success: false, message: `Failed to send reply: ${error}` },
|
|
163
|
-
};
|
|
126
|
+
return toolErr(`Failed to send reply: ${error}`);
|
|
164
127
|
}
|
|
165
128
|
},
|
|
166
129
|
);
|
|
@@ -5,7 +5,7 @@ import { can } from "@/rbac";
|
|
|
5
5
|
import { getSlackApp } from "@/slack/app";
|
|
6
6
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
7
7
|
import { markdownToSlack } from "@/slack/responses";
|
|
8
|
-
import { createToolRegistrar } from "@/tools/utils";
|
|
8
|
+
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
9
9
|
|
|
10
10
|
export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
11
11
|
createToolRegistrar(server)(
|
|
@@ -20,9 +20,7 @@ export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
|
20
20
|
channelId: z.string().min(1).describe("The Slack channel ID to post to."),
|
|
21
21
|
message: z.string().min(1).max(4000).describe("The message content to post."),
|
|
22
22
|
}),
|
|
23
|
-
outputSchema:
|
|
24
|
-
success: z.boolean(),
|
|
25
|
-
message: z.string(),
|
|
23
|
+
outputSchema: swarmToolOutputSchema({
|
|
26
24
|
channelId: z.string().optional(),
|
|
27
25
|
ts: z.string().optional(),
|
|
28
26
|
messageTs: z.string().optional(),
|
|
@@ -30,18 +28,12 @@ export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
|
30
28
|
},
|
|
31
29
|
async ({ channelId, message }, requestInfo, _meta) => {
|
|
32
30
|
if (!requestInfo.agentId) {
|
|
33
|
-
return
|
|
34
|
-
content: [{ type: "text", text: "Agent ID not found." }],
|
|
35
|
-
structuredContent: { success: false, message: "Agent ID not found." },
|
|
36
|
-
};
|
|
31
|
+
return toolErr("Agent ID not found.");
|
|
37
32
|
}
|
|
38
33
|
|
|
39
34
|
const agent = getAgentById(requestInfo.agentId);
|
|
40
35
|
if (!agent) {
|
|
41
|
-
return
|
|
42
|
-
content: [{ type: "text", text: "Agent not found." }],
|
|
43
|
-
structuredContent: { success: false, message: "Agent not found." },
|
|
44
|
-
};
|
|
36
|
+
return toolErr("Agent not found.");
|
|
45
37
|
}
|
|
46
38
|
|
|
47
39
|
const decision = can({
|
|
@@ -51,21 +43,12 @@ export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
|
51
43
|
source: "mcp",
|
|
52
44
|
});
|
|
53
45
|
if (!decision.allow) {
|
|
54
|
-
return
|
|
55
|
-
content: [{ type: "text", text: "Posting to Slack channels requires lead privileges." }],
|
|
56
|
-
structuredContent: {
|
|
57
|
-
success: false,
|
|
58
|
-
message: "Posting to Slack channels requires lead privileges.",
|
|
59
|
-
},
|
|
60
|
-
};
|
|
46
|
+
return toolErr("Posting to Slack channels requires lead privileges.");
|
|
61
47
|
}
|
|
62
48
|
|
|
63
49
|
const app = getSlackApp();
|
|
64
50
|
if (!app) {
|
|
65
|
-
return
|
|
66
|
-
content: [{ type: "text", text: "Slack not configured." }],
|
|
67
|
-
structuredContent: { success: false, message: "Slack not configured." },
|
|
68
|
-
};
|
|
51
|
+
return toolErr("Slack not configured.");
|
|
69
52
|
}
|
|
70
53
|
|
|
71
54
|
try {
|
|
@@ -93,42 +76,18 @@ export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
|
93
76
|
const resolvedChannelId = result.channel ?? channelId;
|
|
94
77
|
|
|
95
78
|
if (!ts) {
|
|
96
|
-
return {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
type: "text",
|
|
100
|
-
text: "Message posted but Slack did not return a ts — cannot thread replies.",
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
|
-
structuredContent: {
|
|
104
|
-
success: false,
|
|
105
|
-
message: "Message posted but Slack did not return a ts — cannot thread replies.",
|
|
106
|
-
channelId: resolvedChannelId,
|
|
107
|
-
},
|
|
108
|
-
};
|
|
79
|
+
return toolErr("Message posted but Slack did not return a ts — cannot thread replies.", {
|
|
80
|
+
data: { channelId: resolvedChannelId },
|
|
81
|
+
});
|
|
109
82
|
}
|
|
110
83
|
|
|
111
|
-
return {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
text: `Thread started. channelId=${resolvedChannelId}, ts=${ts}. Pass ts as threadTs on slack-post to reply in-thread.`,
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
structuredContent: {
|
|
119
|
-
success: true,
|
|
120
|
-
message: "Thread started successfully.",
|
|
121
|
-
channelId: resolvedChannelId,
|
|
122
|
-
ts,
|
|
123
|
-
messageTs: ts,
|
|
124
|
-
},
|
|
125
|
-
};
|
|
84
|
+
return toolOk("Thread started successfully.", {
|
|
85
|
+
details: `Thread started. channelId=${resolvedChannelId}, ts=${ts}. Pass ts as threadTs on slack-post to reply in-thread.`,
|
|
86
|
+
data: { channelId: resolvedChannelId, ts, messageTs: ts },
|
|
87
|
+
});
|
|
126
88
|
} catch (error) {
|
|
127
89
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
128
|
-
return {
|
|
129
|
-
content: [{ type: "text", text: `Failed to start thread: ${errorMsg}` }],
|
|
130
|
-
structuredContent: { success: false, message: `Failed to start thread: ${errorMsg}` },
|
|
131
|
-
};
|
|
90
|
+
return toolErr(`Failed to start thread: ${errorMsg}`);
|
|
132
91
|
}
|
|
133
92
|
},
|
|
134
93
|
);
|
|
@@ -5,7 +5,7 @@ import { can } from "@/rbac";
|
|
|
5
5
|
import { getSlackApp } from "@/slack/app";
|
|
6
6
|
import { parseSlackTs } from "@/slack/message-text";
|
|
7
7
|
import { markdownToSlack } from "@/slack/responses";
|
|
8
|
-
import { createToolRegistrar } from "@/tools/utils";
|
|
8
|
+
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
9
9
|
|
|
10
10
|
export const registerSlackUpdateTool = (server: McpServer) => {
|
|
11
11
|
createToolRegistrar(server)(
|
|
@@ -26,26 +26,18 @@ export const registerSlackUpdateTool = (server: McpServer) => {
|
|
|
26
26
|
),
|
|
27
27
|
message: z.string().min(1).max(4000).describe("The new message content."),
|
|
28
28
|
}),
|
|
29
|
-
outputSchema:
|
|
30
|
-
success: z.boolean(),
|
|
31
|
-
message: z.string(),
|
|
29
|
+
outputSchema: swarmToolOutputSchema({
|
|
32
30
|
messageTs: z.string().optional(),
|
|
33
31
|
}),
|
|
34
32
|
},
|
|
35
33
|
async ({ channelId, messageTs, message }, requestInfo, _meta) => {
|
|
36
34
|
if (!requestInfo.agentId) {
|
|
37
|
-
return
|
|
38
|
-
content: [{ type: "text", text: "Agent ID not found." }],
|
|
39
|
-
structuredContent: { success: false, message: "Agent ID not found." },
|
|
40
|
-
};
|
|
35
|
+
return toolErr("Agent ID not found.");
|
|
41
36
|
}
|
|
42
37
|
|
|
43
38
|
const agent = getAgentById(requestInfo.agentId);
|
|
44
39
|
if (!agent) {
|
|
45
|
-
return
|
|
46
|
-
content: [{ type: "text", text: "Agent not found." }],
|
|
47
|
-
structuredContent: { success: false, message: "Agent not found." },
|
|
48
|
-
};
|
|
40
|
+
return toolErr("Agent not found.");
|
|
49
41
|
}
|
|
50
42
|
|
|
51
43
|
const decision = can({
|
|
@@ -55,21 +47,12 @@ export const registerSlackUpdateTool = (server: McpServer) => {
|
|
|
55
47
|
source: "mcp",
|
|
56
48
|
});
|
|
57
49
|
if (!decision.allow) {
|
|
58
|
-
return
|
|
59
|
-
content: [{ type: "text", text: "Editing Slack messages requires lead privileges." }],
|
|
60
|
-
structuredContent: {
|
|
61
|
-
success: false,
|
|
62
|
-
message: "Editing Slack messages requires lead privileges.",
|
|
63
|
-
},
|
|
64
|
-
};
|
|
50
|
+
return toolErr("Editing Slack messages requires lead privileges.");
|
|
65
51
|
}
|
|
66
52
|
|
|
67
53
|
const app = getSlackApp();
|
|
68
54
|
if (!app) {
|
|
69
|
-
return
|
|
70
|
-
content: [{ type: "text", text: "Slack not configured." }],
|
|
71
|
-
structuredContent: { success: false, message: "Slack not configured." },
|
|
72
|
-
};
|
|
55
|
+
return toolErr("Slack not configured.");
|
|
73
56
|
}
|
|
74
57
|
|
|
75
58
|
try {
|
|
@@ -91,14 +74,7 @@ export const registerSlackUpdateTool = (server: McpServer) => {
|
|
|
91
74
|
],
|
|
92
75
|
});
|
|
93
76
|
|
|
94
|
-
return {
|
|
95
|
-
content: [{ type: "text", text: "Message updated successfully." }],
|
|
96
|
-
structuredContent: {
|
|
97
|
-
success: true,
|
|
98
|
-
message: "Message updated successfully.",
|
|
99
|
-
messageTs: result.ts,
|
|
100
|
-
},
|
|
101
|
-
};
|
|
77
|
+
return toolOk("Message updated successfully.", { data: { messageTs: result.ts } });
|
|
102
78
|
} catch (error) {
|
|
103
79
|
const errorCode = (error as { data?: { error?: string } } | undefined)?.data?.error;
|
|
104
80
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
@@ -124,10 +100,7 @@ export const registerSlackUpdateTool = (server: McpServer) => {
|
|
|
124
100
|
message = `Failed to update message: ${errorMsg}`;
|
|
125
101
|
}
|
|
126
102
|
|
|
127
|
-
return
|
|
128
|
-
content: [{ type: "text", text: message }],
|
|
129
|
-
structuredContent: { success: false, message },
|
|
130
|
-
};
|
|
103
|
+
return toolErr(message);
|
|
131
104
|
}
|
|
132
105
|
},
|
|
133
106
|
);
|
|
@@ -4,7 +4,7 @@ import { getAgentById, getInboxMessageById, getTaskById } from "@/be/db";
|
|
|
4
4
|
import { can } from "@/rbac";
|
|
5
5
|
import { getSlackApp } from "@/slack/app";
|
|
6
6
|
import { MAX_FILE_SIZE, uploadFile } from "@/slack/files";
|
|
7
|
-
import { createToolRegistrar } from "@/tools/utils";
|
|
7
|
+
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Base directory for agent file operations.
|
|
@@ -152,9 +152,7 @@ export const registerSlackUploadFileTool = (server: McpServer) => {
|
|
|
152
152
|
.optional()
|
|
153
153
|
.describe("Optional message to post with the file."),
|
|
154
154
|
}),
|
|
155
|
-
outputSchema:
|
|
156
|
-
success: z.boolean(),
|
|
157
|
-
message: z.string(),
|
|
155
|
+
outputSchema: swarmToolOutputSchema({
|
|
158
156
|
fileId: z.string().optional(),
|
|
159
157
|
}),
|
|
160
158
|
},
|
|
@@ -164,18 +162,12 @@ export const registerSlackUploadFileTool = (server: McpServer) => {
|
|
|
164
162
|
_meta,
|
|
165
163
|
) => {
|
|
166
164
|
if (!requestInfo.agentId) {
|
|
167
|
-
return
|
|
168
|
-
content: [{ type: "text", text: "Agent ID not found." }],
|
|
169
|
-
structuredContent: { success: false, message: "Agent ID not found." },
|
|
170
|
-
};
|
|
165
|
+
return toolErr("Agent ID not found.");
|
|
171
166
|
}
|
|
172
167
|
|
|
173
168
|
const agent = getAgentById(requestInfo.agentId);
|
|
174
169
|
if (!agent) {
|
|
175
|
-
return
|
|
176
|
-
content: [{ type: "text", text: "Agent not found." }],
|
|
177
|
-
structuredContent: { success: false, message: "Agent not found." },
|
|
178
|
-
};
|
|
170
|
+
return toolErr("Agent not found.");
|
|
179
171
|
}
|
|
180
172
|
|
|
181
173
|
let slackChannelId: string | undefined;
|
|
@@ -185,33 +177,21 @@ export const registerSlackUploadFileTool = (server: McpServer) => {
|
|
|
185
177
|
if (inboxMessageId) {
|
|
186
178
|
const inboxMsg = getInboxMessageById(inboxMessageId);
|
|
187
179
|
if (!inboxMsg) {
|
|
188
|
-
return
|
|
189
|
-
content: [{ type: "text", text: "Inbox message not found." }],
|
|
190
|
-
structuredContent: { success: false, message: "Inbox message not found." },
|
|
191
|
-
};
|
|
180
|
+
return toolErr("Inbox message not found.");
|
|
192
181
|
}
|
|
193
182
|
if (inboxMsg.agentId !== requestInfo.agentId) {
|
|
194
|
-
return
|
|
195
|
-
content: [{ type: "text", text: "This inbox message is not yours." }],
|
|
196
|
-
structuredContent: { success: false, message: "This inbox message is not yours." },
|
|
197
|
-
};
|
|
183
|
+
return toolErr("This inbox message is not yours.");
|
|
198
184
|
}
|
|
199
185
|
slackChannelId = inboxMsg.slackChannelId;
|
|
200
186
|
slackThreadTs = inboxMsg.slackThreadTs;
|
|
201
187
|
} else if (taskId) {
|
|
202
188
|
const task = getTaskById(taskId);
|
|
203
189
|
if (!task) {
|
|
204
|
-
return
|
|
205
|
-
content: [{ type: "text", text: "Task not found." }],
|
|
206
|
-
structuredContent: { success: false, message: "Task not found." },
|
|
207
|
-
};
|
|
190
|
+
return toolErr("Task not found.");
|
|
208
191
|
}
|
|
209
192
|
// Verify agent has context for this task
|
|
210
193
|
if (task.agentId !== requestInfo.agentId && task.creatorAgentId !== requestInfo.agentId) {
|
|
211
|
-
return
|
|
212
|
-
content: [{ type: "text", text: "You don't have context for this task." }],
|
|
213
|
-
structuredContent: { success: false, message: "You don't have context for this task." },
|
|
214
|
-
};
|
|
194
|
+
return toolErr("You don't have context for this task.");
|
|
215
195
|
}
|
|
216
196
|
slackChannelId = task.slackChannelId;
|
|
217
197
|
slackThreadTs = resolveTaskUploadThreadTs(task);
|
|
@@ -224,81 +204,35 @@ export const registerSlackUploadFileTool = (server: McpServer) => {
|
|
|
224
204
|
source: "mcp",
|
|
225
205
|
});
|
|
226
206
|
if (!decision.allow) {
|
|
227
|
-
return
|
|
228
|
-
content: [{ type: "text", text: "Direct channel access requires lead privileges." }],
|
|
229
|
-
structuredContent: {
|
|
230
|
-
success: false,
|
|
231
|
-
message: "Direct channel access requires lead privileges.",
|
|
232
|
-
},
|
|
233
|
-
};
|
|
207
|
+
return toolErr("Direct channel access requires lead privileges.");
|
|
234
208
|
}
|
|
235
209
|
slackChannelId = channelId;
|
|
236
210
|
slackThreadTs = threadTs;
|
|
237
211
|
} else {
|
|
238
|
-
return
|
|
239
|
-
content: [{ type: "text", text: "Must provide inboxMessageId, taskId, or channelId." }],
|
|
240
|
-
structuredContent: {
|
|
241
|
-
success: false,
|
|
242
|
-
message: "Must provide inboxMessageId, taskId, or channelId.",
|
|
243
|
-
},
|
|
244
|
-
};
|
|
212
|
+
return toolErr("Must provide inboxMessageId, taskId, or channelId.");
|
|
245
213
|
}
|
|
246
214
|
|
|
247
215
|
if (!slackChannelId) {
|
|
248
|
-
return
|
|
249
|
-
content: [{ type: "text", text: "No Slack channel context available." }],
|
|
250
|
-
structuredContent: {
|
|
251
|
-
success: false,
|
|
252
|
-
message: "No Slack channel context available.",
|
|
253
|
-
},
|
|
254
|
-
};
|
|
216
|
+
return toolErr("No Slack channel context available.");
|
|
255
217
|
}
|
|
256
218
|
|
|
257
219
|
const app = getSlackApp();
|
|
258
220
|
if (!app) {
|
|
259
|
-
return
|
|
260
|
-
content: [{ type: "text", text: "Slack not configured." }],
|
|
261
|
-
structuredContent: { success: false, message: "Slack not configured." },
|
|
262
|
-
};
|
|
221
|
+
return toolErr("Slack not configured.");
|
|
263
222
|
}
|
|
264
223
|
|
|
265
224
|
// Validate: must provide either filePath OR content (not both, not neither)
|
|
266
225
|
if (!filePath && !content) {
|
|
267
|
-
return
|
|
268
|
-
content: [{ type: "text", text: "Must provide either filePath or content (base64)." }],
|
|
269
|
-
structuredContent: {
|
|
270
|
-
success: false,
|
|
271
|
-
message: "Must provide either filePath or content (base64).",
|
|
272
|
-
},
|
|
273
|
-
};
|
|
226
|
+
return toolErr("Must provide either filePath or content (base64).");
|
|
274
227
|
}
|
|
275
228
|
|
|
276
229
|
if (filePath && content) {
|
|
277
|
-
return
|
|
278
|
-
content: [
|
|
279
|
-
{
|
|
280
|
-
type: "text",
|
|
281
|
-
text: "Cannot provide both filePath and content. Use one or the other.",
|
|
282
|
-
},
|
|
283
|
-
],
|
|
284
|
-
structuredContent: {
|
|
285
|
-
success: false,
|
|
286
|
-
message: "Cannot provide both filePath and content. Use one or the other.",
|
|
287
|
-
},
|
|
288
|
-
};
|
|
230
|
+
return toolErr("Cannot provide both filePath and content. Use one or the other.");
|
|
289
231
|
}
|
|
290
232
|
|
|
291
233
|
// If using content (base64), filename is required
|
|
292
234
|
if (content && !filename) {
|
|
293
|
-
return
|
|
294
|
-
content: [
|
|
295
|
-
{ type: "text", text: "filename is required when using base64 content upload." },
|
|
296
|
-
],
|
|
297
|
-
structuredContent: {
|
|
298
|
-
success: false,
|
|
299
|
-
message: "filename is required when using base64 content upload.",
|
|
300
|
-
},
|
|
301
|
-
};
|
|
235
|
+
return toolErr("filename is required when using base64 content upload.");
|
|
302
236
|
}
|
|
303
237
|
|
|
304
238
|
let fileToUpload: string | Buffer;
|
|
@@ -319,10 +253,7 @@ export const registerSlackUploadFileTool = (server: McpServer) => {
|
|
|
319
253
|
`Tips:\n` +
|
|
320
254
|
`- Put the file in /workspace/shared/<agent-id>/ (e.g., '/workspace/shared/<agent-id>/my-file.png') and pass that path.\n` +
|
|
321
255
|
`- Or pass the file inline via the \`content\` arg as base64 (with \`filename\`) so no shared-mount round-trip is needed.`;
|
|
322
|
-
return
|
|
323
|
-
content: [{ type: "text", text: errorMsg }],
|
|
324
|
-
structuredContent: { success: false, message: errorMsg },
|
|
325
|
-
};
|
|
256
|
+
return toolErr(errorMsg);
|
|
326
257
|
}
|
|
327
258
|
|
|
328
259
|
const resolvedPath = pathResult.resolvedPath;
|
|
@@ -331,13 +262,7 @@ export const registerSlackUploadFileTool = (server: McpServer) => {
|
|
|
331
262
|
|
|
332
263
|
if (fileSize > MAX_FILE_SIZE) {
|
|
333
264
|
const sizeMB = Math.round(fileSize / 1024 / 1024);
|
|
334
|
-
return {
|
|
335
|
-
content: [{ type: "text", text: `File too large: ${sizeMB} MB. Maximum is 1 GB.` }],
|
|
336
|
-
structuredContent: {
|
|
337
|
-
success: false,
|
|
338
|
-
message: `File too large: ${sizeMB} MB. Maximum is 1 GB.`,
|
|
339
|
-
},
|
|
340
|
-
};
|
|
265
|
+
return toolErr(`File too large: ${sizeMB} MB. Maximum is 1 GB.`);
|
|
341
266
|
}
|
|
342
267
|
|
|
343
268
|
fileToUpload = resolvedPath;
|
|
@@ -347,21 +272,12 @@ export const registerSlackUploadFileTool = (server: McpServer) => {
|
|
|
347
272
|
try {
|
|
348
273
|
fileToUpload = Buffer.from(content!, "base64");
|
|
349
274
|
} catch {
|
|
350
|
-
return
|
|
351
|
-
content: [{ type: "text", text: "Invalid base64 content." }],
|
|
352
|
-
structuredContent: { success: false, message: "Invalid base64 content." },
|
|
353
|
-
};
|
|
275
|
+
return toolErr("Invalid base64 content.");
|
|
354
276
|
}
|
|
355
277
|
|
|
356
278
|
if (fileToUpload.length > MAX_FILE_SIZE) {
|
|
357
279
|
const sizeMB = Math.round(fileToUpload.length / 1024 / 1024);
|
|
358
|
-
return {
|
|
359
|
-
content: [{ type: "text", text: `File too large: ${sizeMB} MB. Maximum is 1 GB.` }],
|
|
360
|
-
structuredContent: {
|
|
361
|
-
success: false,
|
|
362
|
-
message: `File too large: ${sizeMB} MB. Maximum is 1 GB.`,
|
|
363
|
-
},
|
|
364
|
-
};
|
|
280
|
+
return toolErr(`File too large: ${sizeMB} MB. Maximum is 1 GB.`);
|
|
365
281
|
}
|
|
366
282
|
|
|
367
283
|
actualFilename = filename!;
|
|
@@ -377,30 +293,14 @@ export const registerSlackUploadFileTool = (server: McpServer) => {
|
|
|
377
293
|
});
|
|
378
294
|
|
|
379
295
|
if (!result.success) {
|
|
380
|
-
return {
|
|
381
|
-
content: [{ type: "text", text: `Failed to upload file: ${result.error}` }],
|
|
382
|
-
structuredContent: {
|
|
383
|
-
success: false,
|
|
384
|
-
message: `Failed to upload file: ${result.error}`,
|
|
385
|
-
},
|
|
386
|
-
};
|
|
296
|
+
return toolErr(`Failed to upload file: ${result.error}`);
|
|
387
297
|
}
|
|
388
298
|
|
|
389
299
|
const successMsg = `File uploaded successfully${result.fileId ? ` (ID: ${result.fileId})` : ""}.`;
|
|
390
|
-
return {
|
|
391
|
-
content: [{ type: "text", text: successMsg }],
|
|
392
|
-
structuredContent: {
|
|
393
|
-
success: true,
|
|
394
|
-
message: successMsg,
|
|
395
|
-
fileId: result.fileId,
|
|
396
|
-
},
|
|
397
|
-
};
|
|
300
|
+
return toolOk(successMsg, { data: { fileId: result.fileId } });
|
|
398
301
|
} catch (error) {
|
|
399
302
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
400
|
-
return {
|
|
401
|
-
content: [{ type: "text", text: `Failed to upload file: ${errorMsg}` }],
|
|
402
|
-
structuredContent: { success: false, message: `Failed to upload file: ${errorMsg}` },
|
|
403
|
-
};
|
|
303
|
+
return toolErr(`Failed to upload file: ${errorMsg}`);
|
|
404
304
|
}
|
|
405
305
|
},
|
|
406
306
|
);
|