@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 CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Agent Swarm API",
5
- "version": "1.59.1",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@desplega.ai/agent-swarm",
3
- "version": "1.59.1",
3
+ "version": "1.59.3",
4
4
  "description": "Multi-agent orchestration for Claude Code, Codex, Gemini CLI, and other AI coding assistants",
5
5
  "license": "MIT",
6
6
  "author": "desplega.sh <contact@desplega.sh>",
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 { registerRegisterAgentMailInboxTool } from "./tools/register-agentmail-inbox";
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
- registerRegisterAgentMailInboxTool(server);
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")) {
@@ -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 setStatus("Queuing follow-up...");
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 setStatus("Processing follow-up...");
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 setStatus("Processing your request...");
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 setTitle(title);
104
+ await safeSetTitle(title);
87
105
  }
88
106
 
89
107
  // Optionally enrich with channel context
@@ -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(routingText, botUserId, botMentioned, routingThreadContext);
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 = extractTaskFromMessage(effectiveText, botUserId);
449
+ const taskDescription = isImplicitMention
450
+ ? effectiveText
451
+ : extractTaskFromMessage(effectiveText, botUserId);
438
452
  if (!taskDescription) {
439
- await say({
440
- text: ":satellite: _Please provide a task description after mentioning an agent._",
441
- thread_ts: msg.thread_ts || msg.ts,
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 registerRegisterAgentMailInboxTool = (server: McpServer) => {
12
+ export const registerRegisterAgentmailInboxTool = (server: McpServer) => {
13
13
  createToolRegistrar(server)(
14
14
  "register-agentmail-inbox",
15
15
  {