@desplega.ai/agent-swarm 1.91.0 → 1.92.1
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 +3 -2
- package/openapi.json +1005 -152
- package/package.json +6 -6
- package/plugin/skills/pages/SKILL.md +5 -2
- package/src/be/db.ts +662 -19
- package/src/be/memory/constants.ts +2 -1
- package/src/be/memory/providers/openai-embedding.ts +2 -5
- package/src/be/memory/providers/sqlite-store.ts +293 -76
- package/src/be/memory/types.ts +35 -0
- package/src/be/migrations/083_script_workflows.sql +51 -0
- package/src/be/migrations/084_script_run_journal_duration.sql +5 -0
- package/src/be/migrations/085_script_runs_kind.sql +9 -0
- package/src/be/migrations/086_pages_default_authed.sql +64 -0
- package/src/be/migrations/087_skill_files.sql +19 -0
- package/src/be/modelsdev-cache.json +42310 -38617
- package/src/be/scripts/typecheck.ts +49 -0
- package/src/be/seed-scripts/catalog/boot-triage.ts +221 -0
- package/src/be/seed-scripts/catalog/catalog-report.ts +457 -0
- package/src/be/seed-scripts/catalog/compound-insights.ts +310 -6
- package/src/be/seed-scripts/catalog/gh-pr-snapshot.ts +1 -1
- package/src/be/seed-scripts/catalog/memory-eval.ts +1059 -0
- package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +506 -0
- package/src/be/seed-scripts/catalog/schedule-health.ts +78 -2
- package/src/be/seed-scripts/catalog/task-context-gathering.ts +92 -0
- package/src/be/seed-scripts/catalog/task-failure-audit.ts +48 -1
- package/src/be/seed-scripts/catalog/tool-usage.ts +6 -3
- package/src/be/seed-scripts/index.ts +51 -5
- package/src/be/seed-skills/index.ts +3 -3
- package/src/be/skill-sync.ts +91 -7
- package/src/be/swarm-config-guard.ts +17 -0
- package/src/commands/runner.ts +49 -4
- package/src/heartbeat/templates.ts +20 -16
- package/src/http/db-query.ts +20 -5
- package/src/http/index.ts +51 -7
- package/src/http/mcp-user.ts +23 -0
- package/src/http/mcp.ts +58 -0
- package/src/http/memory.ts +58 -0
- package/src/http/pages.ts +1 -1
- package/src/http/script-runs.ts +557 -0
- package/src/http/scripts.ts +39 -2
- package/src/http/skills.ts +225 -0
- package/src/prompts/session-templates.ts +24 -4
- package/src/providers/claude-adapter.ts +107 -28
- package/src/script-workflows/executor.ts +110 -0
- package/src/script-workflows/harness.ts +73 -0
- package/src/script-workflows/label-lint.ts +51 -0
- package/src/script-workflows/limits.ts +22 -0
- package/src/script-workflows/supervisor.ts +139 -0
- package/src/script-workflows/workflow-ctx.ts +209 -0
- package/src/scripts-runtime/sdk-allowlist.ts +4 -0
- package/src/scripts-runtime/swarm-sdk.ts +13 -0
- package/src/scripts-runtime/types/stdlib.d.ts +61 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +61 -0
- package/src/server.ts +4 -0
- package/src/slack/handlers.ts +11 -4
- package/src/slack/message-text.ts +98 -0
- package/src/slack/thread-buffer.ts +5 -3
- package/src/tests/claude-adapter-binary.test.ts +271 -74
- package/src/tests/create-page-tool.test.ts +19 -2
- package/src/tests/db-query.test.ts +28 -0
- package/src/tests/error-tracker.test.ts +121 -0
- package/src/tests/harness-provider-resolution.test.ts +33 -0
- package/src/tests/heartbeat-checklist.test.ts +36 -0
- package/src/tests/mcp-tools.test.ts +6 -0
- package/src/tests/mcp-transport-gc.test.ts +58 -0
- package/src/tests/memory-health-endpoint.test.ts +78 -0
- package/src/tests/memory-store.test.ts +221 -1
- package/src/tests/pages-http.test.ts +20 -2
- package/src/tests/pages-storage.test.ts +26 -0
- package/src/tests/prompt-template-session.test.ts +34 -5
- package/src/tests/script-runs-http.test.ts +278 -0
- package/src/tests/script-workflows-label-lint.test.ts +43 -0
- package/src/tests/script-workflows-runtime-e2e.test.ts +170 -0
- package/src/tests/scripts-mcp-e2e.test.ts +102 -2
- package/src/tests/seed-scripts.test.ts +468 -3
- package/src/tests/skill-files-http.test.ts +171 -0
- package/src/tests/skill-files.test.ts +162 -0
- package/src/tests/skill-get-file-tool.test.ts +110 -0
- package/src/tests/skill-sync.test.ts +125 -6
- package/src/tests/slack-message-text.test.ts +250 -0
- package/src/tests/system-default-skills.test.ts +40 -0
- package/src/tools/create-page.ts +2 -2
- package/src/tools/db-query.ts +16 -6
- package/src/tools/script-runs.ts +123 -0
- package/src/tools/skills/index.ts +1 -0
- package/src/tools/skills/skill-get-file.ts +80 -0
- package/src/tools/slack-read.ts +12 -3
- package/src/tools/tool-config.ts +6 -2
- package/src/types.ts +72 -0
- package/src/utils/error-tracker.ts +40 -1
- package/src/utils/internal-ai/complete-structured.ts +10 -4
- package/src/workflows/executors/raw-llm.ts +76 -59
- package/templates/schedules/daily-blocker-digest/content.md +68 -54
- package/templates/schedules/daily-compounding-reflection/content.md +4 -4
- package/templates/schedules/daily-hn-briefing/content.md +5 -5
- package/templates/schedules/daily-workflow-health-audit/content.md +6 -6
- package/templates/schedules/gtm-weekly-review/content.md +9 -9
- package/templates/schedules/weekly-dependabot-triage/content.md +24 -20
- package/templates/skills/agentmail-sending/content.md +6 -7
- package/templates/skills/desloppify/content.md +8 -9
- package/templates/skills/jira-interaction/content.md +25 -33
- package/templates/skills/kapso-whatsapp/content.md +29 -30
- package/templates/skills/linear-interaction/content.md +8 -9
- package/templates/skills/pages/content.md +205 -55
- package/templates/skills/profile-corruption-escalation/content.md +44 -85
- package/templates/skills/script-workflows/config.json +14 -0
- package/templates/skills/script-workflows/content.md +68 -0
- package/templates/skills/sprite-cli/content.md +4 -5
- package/templates/skills/swarm-scripts/content.md +2 -3
- package/templates/skills/turso-interaction/content.md +14 -17
- package/templates/skills/workflow-iterate/content.md +38 -391
- package/templates/skills/x-api-interactions/content.md +4 -6
- package/templates/skills/scheduled-task-resilience/config.json +0 -14
- package/templates/skills/scheduled-task-resilience/content.md +0 -95
package/src/server.ts
CHANGED
|
@@ -78,6 +78,7 @@ import {
|
|
|
78
78
|
import { registerScriptDeleteTool } from "./tools/script-delete";
|
|
79
79
|
import { registerScriptQueryTypesTool } from "./tools/script-query-types";
|
|
80
80
|
import { registerScriptRunTool } from "./tools/script-run";
|
|
81
|
+
import { registerScriptRunsTools } from "./tools/script-runs";
|
|
81
82
|
import { registerScriptSearchTool } from "./tools/script-search";
|
|
82
83
|
import { registerScriptUpsertTool } from "./tools/script-upsert";
|
|
83
84
|
import { registerSendTaskTool } from "./tools/send-task";
|
|
@@ -85,6 +86,7 @@ import { registerSendTaskTool } from "./tools/send-task";
|
|
|
85
86
|
import {
|
|
86
87
|
registerSkillCreateTool,
|
|
87
88
|
registerSkillDeleteTool,
|
|
89
|
+
registerSkillGetFileTool,
|
|
88
90
|
registerSkillGetTool,
|
|
89
91
|
registerSkillInstallRemoteTool,
|
|
90
92
|
registerSkillInstallTool,
|
|
@@ -227,6 +229,7 @@ export function createServer() {
|
|
|
227
229
|
registerScriptUpsertTool(server);
|
|
228
230
|
registerScriptDeleteTool(server);
|
|
229
231
|
registerScriptQueryTypesTool(server);
|
|
232
|
+
registerScriptRunsTools(server);
|
|
230
233
|
|
|
231
234
|
// External command routes - mirrors the `agent-swarm x ...` CLI surface.
|
|
232
235
|
registerSwarmXTool(server);
|
|
@@ -327,6 +330,7 @@ export function createServer() {
|
|
|
327
330
|
registerSkillUpdateTool(server);
|
|
328
331
|
registerSkillDeleteTool(server);
|
|
329
332
|
registerSkillGetTool(server);
|
|
333
|
+
registerSkillGetFileTool(server);
|
|
330
334
|
registerSkillListTool(server);
|
|
331
335
|
registerSkillSearchTool(server);
|
|
332
336
|
registerSkillInstallTool(server);
|
package/src/slack/handlers.ts
CHANGED
|
@@ -18,6 +18,7 @@ import type { SlackFile } from "./files";
|
|
|
18
18
|
import { extractTaskFromMessage, hasOtherUserMention, routeMessage } from "./router";
|
|
19
19
|
// Side-effect import: registers all Slack event templates in the in-memory registry
|
|
20
20
|
import "./templates";
|
|
21
|
+
import { extractSlackMessageText } from "./message-text";
|
|
21
22
|
import { bufferThreadMessage, getBufferMessageCount, instantFlush } from "./thread-buffer";
|
|
22
23
|
import { registerTreeMessage } from "./watcher";
|
|
23
24
|
|
|
@@ -173,6 +174,8 @@ interface ThreadMessage {
|
|
|
173
174
|
subtype?: string;
|
|
174
175
|
text?: string;
|
|
175
176
|
ts: string;
|
|
177
|
+
attachments?: Array<{ fallback?: string; text?: string; title?: string; pretext?: string }>;
|
|
178
|
+
blocks?: unknown[];
|
|
176
179
|
}
|
|
177
180
|
|
|
178
181
|
// Cache for bot's own user ID (avoids redundant auth.test calls)
|
|
@@ -286,8 +289,11 @@ async function getThreadContext(
|
|
|
286
289
|
});
|
|
287
290
|
|
|
288
291
|
const messages = (result.messages || []) as ThreadMessage[];
|
|
289
|
-
// Filter out the current message
|
|
290
|
-
const previousMessages = messages.filter((m) =>
|
|
292
|
+
// Filter out the current message; include any message with extractable text
|
|
293
|
+
const previousMessages = messages.filter((m) => {
|
|
294
|
+
if (m.ts === currentTs) return false;
|
|
295
|
+
return extractSlackMessageText(m) !== "";
|
|
296
|
+
});
|
|
291
297
|
|
|
292
298
|
if (previousMessages.length === 0) return "";
|
|
293
299
|
|
|
@@ -298,13 +304,14 @@ async function getThreadContext(
|
|
|
298
304
|
const isBotMessage =
|
|
299
305
|
m.user === botUserId || m.bot_id !== undefined || m.subtype === "bot_message";
|
|
300
306
|
|
|
307
|
+
const text = extractSlackMessageText(m);
|
|
301
308
|
if (isBotMessage) {
|
|
302
309
|
// Bot/agent message - truncate if too long
|
|
303
|
-
const truncatedText =
|
|
310
|
+
const truncatedText = text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
304
311
|
formattedMessages.push(`[Agent]: ${truncatedText}`);
|
|
305
312
|
} else {
|
|
306
313
|
const userName = m.user ? await getUserDisplayName(client, m.user) : "Unknown";
|
|
307
|
-
formattedMessages.push(`${userName}: ${
|
|
314
|
+
formattedMessages.push(`${userName}: ${text}`);
|
|
308
315
|
}
|
|
309
316
|
}
|
|
310
317
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utility for extracting displayable text from a Slack message.
|
|
3
|
+
*
|
|
4
|
+
* Slack integration/alert apps (Datadog, PagerDuty, GitHub) often post with
|
|
5
|
+
* an empty top-level `text` field and put all content in legacy `attachments`
|
|
6
|
+
* or Block Kit `blocks`. This helper falls back through those layers so callers
|
|
7
|
+
* never silently drop those messages.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface SlackAttachment {
|
|
11
|
+
fallback?: string;
|
|
12
|
+
text?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
pretext?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Internal shape used only inside the helper; callers pass `blocks?: unknown[]`
|
|
18
|
+
interface SlackBlockInternal {
|
|
19
|
+
type?: string;
|
|
20
|
+
text?: { type?: string; text?: string };
|
|
21
|
+
/** section blocks may use fields[] instead of (or alongside) a top-level text object */
|
|
22
|
+
fields?: Array<{ type?: string; text?: string }>;
|
|
23
|
+
elements?: unknown[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SlackMessageLike {
|
|
27
|
+
text?: string;
|
|
28
|
+
attachments?: SlackAttachment[];
|
|
29
|
+
/** Typed as unknown[] so any Slack SDK block variant is accepted without casting. */
|
|
30
|
+
blocks?: unknown[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Recursively collect plain text from a Slack rich_text node tree.
|
|
35
|
+
*
|
|
36
|
+
* Handles text leaf nodes plus all container types that carry child elements:
|
|
37
|
+
* rich_text_section, rich_text_list, rich_text_quote, rich_text_preformatted.
|
|
38
|
+
*/
|
|
39
|
+
function collectRichTextParts(node: unknown, parts: string[]): void {
|
|
40
|
+
if (node == null || typeof node !== "object") return;
|
|
41
|
+
const n = node as { type?: string; text?: string; elements?: unknown[] };
|
|
42
|
+
if (n.type === "text" && n.text) {
|
|
43
|
+
parts.push(n.text);
|
|
44
|
+
}
|
|
45
|
+
if (Array.isArray(n.elements)) {
|
|
46
|
+
for (const child of n.elements) {
|
|
47
|
+
collectRichTextParts(child, parts);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Return the best displayable text for a Slack message.
|
|
54
|
+
*
|
|
55
|
+
* Priority:
|
|
56
|
+
* 1. `msg.text` (non-empty)
|
|
57
|
+
* 2. `msg.attachments[]` — joins `fallback || text || title || pretext` for each
|
|
58
|
+
* 3. `msg.blocks[]` — extracts text from section (text + fields) and rich_text blocks
|
|
59
|
+
* 4. `""` if nothing found
|
|
60
|
+
*/
|
|
61
|
+
export function extractSlackMessageText(msg: SlackMessageLike): string {
|
|
62
|
+
if (msg.text?.trim()) return msg.text;
|
|
63
|
+
|
|
64
|
+
// Legacy attachments (Datadog, PagerDuty, GitHub alert apps)
|
|
65
|
+
if (Array.isArray(msg.attachments) && msg.attachments.length > 0) {
|
|
66
|
+
const parts = msg.attachments
|
|
67
|
+
.filter((a): a is SlackAttachment => a != null && typeof a === "object")
|
|
68
|
+
.map((a) => a.fallback || a.text || a.title || a.pretext || "")
|
|
69
|
+
.filter(Boolean);
|
|
70
|
+
if (parts.length > 0) return parts.join("\n");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Block Kit blocks
|
|
74
|
+
if (Array.isArray(msg.blocks) && msg.blocks.length > 0) {
|
|
75
|
+
const parts: string[] = [];
|
|
76
|
+
for (const rawBlock of msg.blocks) {
|
|
77
|
+
if (rawBlock == null || typeof rawBlock !== "object") continue;
|
|
78
|
+
const block = rawBlock as SlackBlockInternal;
|
|
79
|
+
if (block.type === "section") {
|
|
80
|
+
if (block.text?.text) parts.push(block.text.text);
|
|
81
|
+
if (Array.isArray(block.fields)) {
|
|
82
|
+
for (const field of block.fields) {
|
|
83
|
+
if (field != null && typeof field === "object" && field.text) {
|
|
84
|
+
parts.push(field.text);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} else if (block.type === "rich_text" && Array.isArray(block.elements)) {
|
|
89
|
+
for (const el of block.elements) {
|
|
90
|
+
collectRichTextParts(el, parts);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (parts.length > 0) return parts.join("\n");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return "";
|
|
98
|
+
}
|
|
@@ -4,6 +4,7 @@ import { slackContextKey } from "../tasks/context-key";
|
|
|
4
4
|
import { createTaskWithSiblingAwareness } from "../tasks/sibling-awareness";
|
|
5
5
|
import { getSlackApp } from "./app";
|
|
6
6
|
import { buildBufferFlushBlocks } from "./blocks";
|
|
7
|
+
import { extractSlackMessageText } from "./message-text";
|
|
7
8
|
import { registerTreeMessage } from "./watcher";
|
|
8
9
|
|
|
9
10
|
interface BufferedMessage {
|
|
@@ -93,15 +94,16 @@ async function getThreadContextForBuffer(channelId: string, threadTs: string): P
|
|
|
93
94
|
if (messages.length === 0) return "";
|
|
94
95
|
|
|
95
96
|
const formatted = messages
|
|
96
|
-
.filter((m) => m
|
|
97
|
+
.filter((m) => extractSlackMessageText(m) !== "")
|
|
97
98
|
.map((m) => {
|
|
98
99
|
const msg = m as Record<string, unknown>;
|
|
99
100
|
const isBotMessage = msg.bot_id !== undefined || msg.subtype === "bot_message";
|
|
101
|
+
const text = extractSlackMessageText(m);
|
|
100
102
|
if (isBotMessage) {
|
|
101
|
-
const truncated =
|
|
103
|
+
const truncated = text.length > 500 ? `${text.slice(0, 500)}...` : text;
|
|
102
104
|
return `[Agent]: ${truncated}`;
|
|
103
105
|
}
|
|
104
|
-
return `<@${m.user}>: ${
|
|
106
|
+
return `<@${m.user}>: ${text}`;
|
|
105
107
|
})
|
|
106
108
|
.join("\n");
|
|
107
109
|
|