@desplega.ai/agent-swarm 1.59.1 → 1.59.3
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/openapi.json +1 -1
- package/package.json +1 -1
- package/src/server.ts +2 -2
- package/src/slack/assistant.ts +22 -4
- package/src/slack/handlers.ts +24 -8
- package/src/tools/register-agentmail-inbox.ts +1 -1
package/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Agent Swarm API",
|
|
5
|
-
"version": "1.59.
|
|
5
|
+
"version": "1.59.3",
|
|
6
6
|
"description": "Multi-agent orchestration API for Claude Code, Codex, and Gemini CLI. Enables task distribution, agent communication, and service discovery.\n\nMCP tools are documented separately in [MCP.md](./MCP.md)."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
package/package.json
CHANGED
package/src/server.ts
CHANGED
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
registerSetPromptTemplateTool,
|
|
42
42
|
} from "./tools/prompt-templates";
|
|
43
43
|
import { registerReadMessagesTool } from "./tools/read-messages";
|
|
44
|
-
import {
|
|
44
|
+
import { registerRegisterAgentmailInboxTool } from "./tools/register-agentmail-inbox";
|
|
45
45
|
// Services capability
|
|
46
46
|
import { registerRegisterServiceTool } from "./tools/register-service";
|
|
47
47
|
// Repo management tools
|
|
@@ -193,7 +193,7 @@ export function createServer() {
|
|
|
193
193
|
registerSlackDownloadFileTool(server);
|
|
194
194
|
|
|
195
195
|
// AgentMail integration tool (always registered, self-service inbox mapping)
|
|
196
|
-
|
|
196
|
+
registerRegisterAgentmailInboxTool(server);
|
|
197
197
|
|
|
198
198
|
// Task pool capability - task pool operations (create unassigned, claim, release, accept, reject)
|
|
199
199
|
if (hasCapability("task-pool")) {
|
package/src/slack/assistant.ts
CHANGED
|
@@ -40,6 +40,24 @@ export function createAssistant(): Assistant {
|
|
|
40
40
|
},
|
|
41
41
|
|
|
42
42
|
userMessage: async ({ message, say, setStatus, setTitle, getThreadContext }) => {
|
|
43
|
+
// Wrap setStatus/setTitle to swallow all errors gracefully.
|
|
44
|
+
// These calls can fail for various reasons (no_permission when the thread
|
|
45
|
+
// wasn't started by the assistant, network errors, etc.), so we log and continue.
|
|
46
|
+
const safeSetStatus = async (status: string) => {
|
|
47
|
+
try {
|
|
48
|
+
await setStatus(status);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.warn("[Slack] setStatus failed (thread may not be an assistant thread):", error);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const safeSetTitle = async (title: string) => {
|
|
54
|
+
try {
|
|
55
|
+
await setTitle(title);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.warn("[Slack] setTitle failed (thread may not be an assistant thread):", error);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
43
61
|
try {
|
|
44
62
|
// Cast to access fields — Bolt's message union type is complex
|
|
45
63
|
const msg = message as unknown as Record<string, unknown>;
|
|
@@ -58,7 +76,7 @@ export function createAssistant(): Assistant {
|
|
|
58
76
|
// Follow-up message → route to the same agent
|
|
59
77
|
if (additiveSlack) {
|
|
60
78
|
bufferThreadMessage(channelId, threadTs, messageText, userId, message.ts);
|
|
61
|
-
await
|
|
79
|
+
await safeSetStatus("Queuing follow-up...");
|
|
62
80
|
return;
|
|
63
81
|
}
|
|
64
82
|
|
|
@@ -74,16 +92,16 @@ export function createAssistant(): Assistant {
|
|
|
74
92
|
requestedByUserId,
|
|
75
93
|
});
|
|
76
94
|
|
|
77
|
-
await
|
|
95
|
+
await safeSetStatus("Processing follow-up...");
|
|
78
96
|
return;
|
|
79
97
|
}
|
|
80
98
|
|
|
81
99
|
// 2. First message in thread — create new task for lead
|
|
82
|
-
await
|
|
100
|
+
await safeSetStatus("Processing your request...");
|
|
83
101
|
|
|
84
102
|
if (messageText) {
|
|
85
103
|
const title = messageText.length > 50 ? `${messageText.slice(0, 47)}...` : messageText;
|
|
86
|
-
await
|
|
104
|
+
await safeSetTitle(title);
|
|
87
105
|
}
|
|
88
106
|
|
|
89
107
|
// Optionally enrich with channel context
|
package/src/slack/handlers.ts
CHANGED
|
@@ -149,6 +149,7 @@ interface MessageEvent {
|
|
|
149
149
|
ts: string;
|
|
150
150
|
thread_ts?: string;
|
|
151
151
|
files?: SlackFile[];
|
|
152
|
+
assistant_thread?: Record<string, unknown>;
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
interface ThreadMessage {
|
|
@@ -358,6 +359,12 @@ export function registerMessageHandler(app: App): void {
|
|
|
358
359
|
// Check if bot was mentioned (in original text only)
|
|
359
360
|
const botMentioned = !!msg.text?.includes(`<@${botUserId}>`);
|
|
360
361
|
|
|
362
|
+
// Detect assistant thread context — file_share messages in DM assistant threads
|
|
363
|
+
// bypass the assistant handler and land here instead. Treat them as implicit mentions
|
|
364
|
+
// so they route to the lead agent rather than being silently dropped.
|
|
365
|
+
const isAssistantThread = !!msg.assistant_thread;
|
|
366
|
+
const isImplicitMention = isAssistantThread && !botMentioned;
|
|
367
|
+
|
|
361
368
|
// ADDITIVE_SLACK: Check for !now command in threads
|
|
362
369
|
const additiveSlack = process.env.ADDITIVE_SLACK === "true";
|
|
363
370
|
if (additiveSlack && msg.thread_ts) {
|
|
@@ -420,12 +427,17 @@ export function registerMessageHandler(app: App): void {
|
|
|
420
427
|
const routingThreadContext = msg.thread_ts
|
|
421
428
|
? { channelId: msg.channel, threadTs: msg.thread_ts }
|
|
422
429
|
: undefined;
|
|
423
|
-
const matches = routeMessage(
|
|
430
|
+
const matches = routeMessage(
|
|
431
|
+
routingText,
|
|
432
|
+
botUserId,
|
|
433
|
+
botMentioned || isImplicitMention,
|
|
434
|
+
routingThreadContext,
|
|
435
|
+
);
|
|
424
436
|
|
|
425
437
|
if (matches.length === 0) {
|
|
426
|
-
if (!botMentioned) return;
|
|
438
|
+
if (!botMentioned && !isImplicitMention) return;
|
|
427
439
|
|
|
428
|
-
// Bot was mentioned but no online agents matched — queue the request
|
|
440
|
+
// Bot was mentioned (or message is in assistant thread) but no online agents matched — queue the request
|
|
429
441
|
if (!checkRateLimit(msg.user)) {
|
|
430
442
|
await say({
|
|
431
443
|
text: ":satellite: _You're sending too many requests. Please slow down._",
|
|
@@ -434,12 +446,16 @@ export function registerMessageHandler(app: App): void {
|
|
|
434
446
|
return;
|
|
435
447
|
}
|
|
436
448
|
|
|
437
|
-
const taskDescription =
|
|
449
|
+
const taskDescription = isImplicitMention
|
|
450
|
+
? effectiveText
|
|
451
|
+
: extractTaskFromMessage(effectiveText, botUserId);
|
|
438
452
|
if (!taskDescription) {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
453
|
+
if (!isImplicitMention) {
|
|
454
|
+
await say({
|
|
455
|
+
text: ":satellite: _Please provide a task description after mentioning an agent._",
|
|
456
|
+
thread_ts: msg.thread_ts || msg.ts,
|
|
457
|
+
});
|
|
458
|
+
}
|
|
443
459
|
return;
|
|
444
460
|
}
|
|
445
461
|
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "@/be/db";
|
|
10
10
|
import { createToolRegistrar } from "@/tools/utils";
|
|
11
11
|
|
|
12
|
-
export const
|
|
12
|
+
export const registerRegisterAgentmailInboxTool = (server: McpServer) => {
|
|
13
13
|
createToolRegistrar(server)(
|
|
14
14
|
"register-agentmail-inbox",
|
|
15
15
|
{
|