@desplega.ai/agent-swarm 1.119.6 → 1.121.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 -2
- package/dist/{actions-qe5zjcbr.js → actions-mwshtkf7.js} +6 -6
- package/dist/{anthropic-messages-qjxzsabf.js → anthropic-messages-4gn944cn.js} +29 -13
- package/dist/{app-31x7k3vj.js → app-skbty91x.js} +4 -4
- package/dist/{assistant-4crt9dve.js → assistant-tg7dhfj8.js} +13 -13
- package/dist/{azure-openai-responses-ntfd05zd.js → azure-openai-responses-79zc0wyy.js} +28 -13
- package/dist/{boot-reembed-8g69ttz4.js → boot-reembed-ntjmeyh2.js} +4 -4
- package/dist/{boot-reembed-q648j733.js → boot-reembed-q5x0xpcp.js} +5 -5
- package/dist/{boot-scrub-logs-sfmzd2hj.js → boot-scrub-logs-5gznsfbe.js} +4 -4
- package/dist/{claude-adapter-9n3nzt65.js → claude-adapter-vxvcym3r.js} +3 -3
- package/dist/{claude-managed-adapter-pv2nbqy4.js → claude-managed-adapter-g807894s.js} +2 -2
- package/dist/{cli-bpvgs2y6.js → cli-072t49hf.js} +2123 -1533
- package/dist/{cli-g6qz2kts.js → cli-0df2g86x.js} +336 -18
- package/dist/cli-1728qh70.js +791 -0
- package/dist/{cli-vg1jxfqz.js → cli-3b1ayz83.js} +5 -5
- package/dist/{cli-r93nz80j.js → cli-3fxqwfh3.js} +1 -1
- package/dist/{cli-w6rhc30s.js → cli-3jrdwnn9.js} +20 -5
- package/dist/{cli-pasyk3vc.js → cli-46etyprn.js} +10 -5
- package/dist/{cli-433c0f4b.js → cli-4pfweq4x.js} +8 -8
- package/dist/{cli-2r7s8jhp.js → cli-5c4327dx.js} +7 -1
- package/dist/{cli-4s84mw72.js → cli-5hpvd15x.js} +2 -2
- package/dist/{cli-branks1w.js → cli-6s3ytc5x.js} +1 -1
- package/dist/{cli-da3x3btq.js → cli-7pt9sc83.js} +2 -2
- package/dist/{cli-2gv8ygwr.js → cli-7pzae66m.js} +2 -2
- package/dist/{cli-qs7nb3zn.js → cli-8wrympd7.js} +27 -1
- package/dist/{cli-qw1ccvxm.js → cli-95rbe11h.js} +70 -51
- package/dist/{cli-6rvm3jkk.js → cli-agdrxyex.js} +1 -1
- package/dist/{cli-wr706gez.js → cli-av2s7my4.js} +167 -66
- package/dist/{cli-59jy217p.js → cli-avw9ev3x.js} +55 -21
- package/dist/{cli-fkxxh5d4.js → cli-b2mqkg1h.js} +2 -2
- package/dist/{cli-1arw00dp.js → cli-ccjwgarc.js} +12 -3
- package/dist/{cli-pscrc6tw.js → cli-ch7t5v7n.js} +5 -0
- package/dist/{cli-tghre7g6.js → cli-cw70hymf.js} +1 -0
- package/dist/{cli-n61x2aph.js → cli-dmzv0986.js} +816 -1335
- package/dist/{cli-d1reabed.js → cli-g9vva2qh.js} +2 -2
- package/dist/{cli-ner6af7m.js → cli-gdpx70nc.js} +24048 -23715
- package/dist/{cli-96feg24n.js → cli-ghq3v4c9.js} +2 -2
- package/dist/{cli-wxbnjgce.js → cli-ky8esb8t.js} +3 -3
- package/dist/{cli-gdqdkr3j.js → cli-nf7sadev.js} +2 -2
- package/dist/{cli-h6cf69x5.js → cli-p9w7kb3h.js} +1 -1
- package/dist/{cli-xeatwfbe.js → cli-ry656xem.js} +24 -17
- package/dist/{cli-q8dway4w.js → cli-s8bdcke2.js} +1 -1
- package/dist/cli-s8s499xy.js +81 -0
- package/dist/{cli-sbkwvn5e.js → cli-srjqn7fd.js} +1 -1
- package/dist/cli-tv7vekye.js +367 -0
- package/dist/{cli-gg5bd32n.js → cli-vg3zrw6h.js} +4 -4
- package/dist/{cli-vx0y68jv.js → cli-vp9r4ap4.js} +5 -4
- package/dist/{cli-mg280wsv.js → cli-we156bmz.js} +1 -1
- package/dist/{cli-86fdnerz.js → cli-wwsaj97q.js} +9 -4
- package/dist/{cli-e0y603nn.js → cli-x0e0yvnq.js} +101 -1
- package/dist/{cli-mw3xpgwb.js → cli-x4apc9t3.js} +4 -4
- package/dist/cli.js +26 -21
- package/dist/{codex-adapter-6j2b38tg.js → codex-adapter-mmy741zd.js} +8 -9
- package/dist/{codex-session-runner-vz215wgw.js → codex-session-runner-sazmx9zt.js} +8 -9
- package/dist/{commands-6xr20jbe.js → commands-cxxye5e4.js} +3 -3
- package/dist/{db-1mmvk1z4.js → db-ab1954b7.js} +5 -3
- package/dist/{google-generative-ai-n1d3xt4n.js → google-generative-ai-wwa2ked5.js} +14 -18
- package/dist/{google-vertex-mxst23gy.js → google-vertex-71xmdd7n.js} +14 -18
- package/dist/{handlers-xvrknk8w.js → handlers-fmfe2343.js} +13 -13
- package/dist/{hook-qm7he8wn.js → hook-ygnw3cvt.js} +7 -8
- package/dist/{http-hj08zq67.js → http-kactcc0z.js} +1128 -536
- package/dist/{index-688jph6a.js → index-6erq0wvk.js} +11 -11
- package/dist/{index-gze4fg2w.js → index-g86j2yt5.js} +9 -9
- package/dist/{index-etz7d8md.js → index-gmzs6a2q.js} +10 -10
- package/dist/{index-wj8dfpwh.js → index-hmp82wn0.js} +12 -12
- package/dist/{keepalive-94wn9yxw.js → keepalive-3cvt26dw.js} +18 -14
- package/dist/{lead-rvcqkp11.js → lead-ysf26cjr.js} +31 -32
- package/dist/{maintenance-qhfc4dnp.js → maintenance-9npwptbb.js} +5 -5
- package/dist/{mistral-conversations-ykcg66za.js → mistral-conversations-26ya4yah.js} +17 -13
- package/dist/{oauth-refresh-sweep-rj8wgvsw.js → oauth-refresh-sweep-0r2v76vw.js} +23 -17
- package/dist/{onboard-8bv8q1wc.js → onboard-ddb1674a.js} +2 -2
- package/dist/{openai-codex-responses-zy0907j9.js → openai-codex-responses-6rr2ye0s.js} +78 -38
- package/dist/{openai-completions-xk4p56n9.js → openai-completions-zfa9nkvt.js} +130 -33
- package/dist/{openai-responses-4gv3ca5d.js → openai-responses-9wmdks0g.js} +38 -14
- package/dist/{opencode-adapter-5bwzvbwj.js → opencode-adapter-h6rkxwrk.js} +2 -2
- package/dist/{openrouter-images-4fsrrzes.js → openrouter-images-dgq98729.js} +10 -3
- package/dist/{otel-impl-1kf6fr2m.js → otel-impl-b43bkq8e.js} +4 -4
- package/dist/{pi-messages-zb8v76wx.js → pi-messages-nzjbbz47.js} +4 -6
- package/dist/{pi-mono-adapter-9sg69kg3.js → pi-mono-adapter-ke789738.js} +2328 -1281
- package/dist/{pricing-refresh-e84tar2s.js → pricing-refresh-2rqf114z.js} +5 -5
- package/dist/{rbac-roles-atytq5ch.js → rbac-roles-5wkhc8xv.js} +5 -5
- package/dist/{rbac-roles-pg0zvnwn.js → rbac-roles-6vtafvzb.js} +4 -4
- package/dist/{seed-pricing-xd6nxq7k.js → seed-pricing-23wrb873.js} +4 -4
- package/dist/{setup-4z389yk0.js → setup-6rny4fk6.js} +2 -2
- package/dist/{worker-m61r0t7m.js → worker-yapewe14.js} +31 -32
- package/openapi.json +2671 -1811
- package/package.json +10 -5
- package/plugin/commands/swarm-chat.md +2 -0
- package/plugin/pi-skills/swarm-chat/SKILL.md +2 -0
- package/src/be/connection-bindings-blob-migration.ts +123 -0
- package/src/be/db-queries/mcp-oauth.ts +409 -247
- package/src/be/db-queries/oauth.ts +813 -131
- package/src/be/db.ts +97 -6
- package/src/be/migrations/117_unified_oauth.sql +624 -0
- package/src/be/migrations/119_agent_avatar.sql +7 -0
- package/src/be/migrations/120_task_title.sql +3 -0
- package/src/be/oauth-credential-bindings.ts +48 -14
- package/src/be/oauth-encryption-backfill.ts +84 -0
- package/src/be/oauth-refresh-sweep.ts +38 -23
- package/src/be/script-connections.ts +1130 -163
- package/src/be/script-credential-broker.ts +37 -27
- package/src/be/scripts/typecheck.ts +3 -2
- package/src/be/seed-capabilities.ts +62 -0
- package/src/be/seed-pricing.ts +1 -1
- package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
- package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
- package/src/be/vendored-openapi.ts +98 -0
- package/src/commands/runner.ts +69 -6
- package/src/http/agents.ts +23 -5
- package/src/http/all-routes.ts +1 -0
- package/src/http/core.ts +8 -5
- package/src/http/index.ts +18 -5
- package/src/http/mcp-bridge.ts +5 -2
- package/src/http/mcp-oauth.ts +103 -101
- package/src/http/oauth-callback.ts +332 -0
- package/src/http/oauth-generic.ts +14 -54
- package/src/http/poll.ts +5 -1
- package/src/http/script-connections.ts +651 -170
- package/src/http/scripts.ts +4 -2
- package/src/http/sessions.ts +1 -1
- package/src/http/tasks.ts +35 -0
- package/src/http/trackers/jira.ts +22 -34
- package/src/http/trackers/linear.ts +21 -36
- package/src/http/x.ts +6 -2
- package/src/jira/app.ts +12 -6
- package/src/jira/oauth.ts +48 -48
- package/src/linear/app.ts +44 -2
- package/src/linear/oauth.ts +12 -37
- package/src/oauth/app-validation.ts +27 -9
- package/src/oauth/ensure-mcp-token.ts +1 -0
- package/src/oauth/ensure-token.ts +331 -108
- package/src/oauth/identity-capture.ts +103 -0
- package/src/oauth/keepalive.ts +14 -9
- package/src/oauth/presets.ts +242 -0
- package/src/oauth/wrapper.ts +197 -76
- package/src/prompts/base-prompt.ts +48 -4
- package/src/prompts/session-templates.ts +13 -1
- package/src/providers/claude-managed-models.ts +8 -0
- package/src/rbac/legacy-policy.ts +2 -1
- package/src/rbac/permissions.ts +7 -3
- package/src/scripts-runtime/credential-broker/broker.ts +51 -8
- package/src/scripts-runtime/credential-broker/fetch-patch.ts +30 -3
- package/src/scripts-runtime/credential-broker/index.ts +1 -1
- package/src/scripts-runtime/credential-broker/types.ts +55 -8
- package/src/scripts-runtime/egress-secrets.ts +6 -2
- package/src/scripts-runtime/eval-harness.ts +2 -2
- package/src/scripts-runtime/executors/types.ts +2 -1
- package/src/scripts-runtime/loader.ts +3 -0
- package/src/scripts-runtime/types/stdlib.d.ts +11 -0
- package/src/server.ts +230 -126
- package/src/tests/agent-avatar-resolution.test.ts +123 -0
- package/src/tests/agents-list-model-display.test.ts +10 -0
- package/src/tests/base-prompt.test.ts +72 -0
- package/src/tests/claude-managed-adapter.test.ts +6 -0
- package/src/tests/connection-embedded-auth.test.ts +709 -0
- package/src/tests/context-window.test.ts +1 -0
- package/src/tests/credential-broker.test.ts +123 -125
- package/src/tests/db-queries-oauth.test.ts +126 -1
- package/src/tests/ensure-token.test.ts +44 -2
- package/src/tests/list-endpoint-slimming.test.ts +45 -0
- package/src/tests/mcp-oauth-manual-client.test.ts +20 -1
- package/src/tests/mcp-oauth-queries.test.ts +154 -8
- package/src/tests/oauth-access-token-tool.test.ts +37 -1
- package/src/tests/oauth-callback-flow.test.ts +534 -0
- package/src/tests/oauth-credential-bindings.test.ts +50 -22
- package/src/tests/oauth-presets.test.ts +275 -0
- package/src/tests/oauth-refresh-failure.test.ts +263 -0
- package/src/tests/oauth-refresh-sweep.test.ts +83 -3
- package/src/tests/oauth-wrapper.test.ts +77 -55
- package/src/tests/prompt-template-session.test.ts +6 -5
- package/src/tests/rbac-charact-misc-tools.test.ts +60 -0
- package/src/tests/rbac-engine.test.ts +2 -1
- package/src/tests/script-connections-http.test.ts +356 -11
- package/src/tests/script-connections.test.ts +102 -0
- package/src/tests/sdk-allowlist.test.ts +4 -1
- package/src/tests/seed-capabilities.test.ts +92 -0
- package/src/tests/session-costs-model-key-normalize.test.ts +1 -0
- package/src/tests/sessions.test.ts +46 -0
- package/src/tests/spec-base-url.test.ts +266 -0
- package/src/tests/status.test.ts +3 -4
- package/src/tests/swarm-config-reserved-keys.test.ts +4 -2
- package/src/tests/task-title-route.test.ts +106 -0
- package/src/tests/tool-annotations.test.ts +6 -3
- package/src/tests/tracker-fold.test.ts +412 -0
- package/src/tests/unified-oauth-migration.test.ts +455 -0
- package/src/tests/vendored-openapi.test.ts +263 -0
- package/src/tools/credential-bindings/tool.ts +232 -77
- package/src/tools/oauth-access-token.ts +55 -6
- package/src/tools/script-connections/tool.ts +73 -53
- package/src/tools/swarm-config/set-config.ts +24 -50
- package/src/tools/update-profile.ts +15 -5
- package/src/tracker/types.ts +12 -0
- package/src/types.ts +29 -0
- package/src/utils/context-window.ts +1 -0
- package/src/workflows/executors/swarm-script.ts +6 -2
- package/vendored-openapi/README.md +22 -0
- package/vendored-openapi/github.json +7759 -0
- package/vendored-openapi/gmail.json +393 -0
- package/vendored-openapi/jira.json +3396 -0
- package/vendored-openapi/linear.json +252 -0
- package/vendored-openapi/manifest.json +128 -0
- package/vendored-openapi/slack.json +2895 -0
- package/dist/cli-0pygq9r1.js +0 -429
- package/dist/cli-8hhms4hp.js +0 -393
- package/dist/cli-z9gzq07x.js +0 -27
- package/src/scripts-runtime/credential-broker/store.ts +0 -72
- package/dist/{otel-g299k41b.js → otel-63jr5v38.js} +1 -1
package/src/server.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { startPricingRefreshLoop } from "./be/pricing-refresh";
|
|
|
5
5
|
import { ensureRbacSeedsSynced } from "./be/rbac-roles";
|
|
6
6
|
import { seedPricingFromModelsDev } from "./be/seed-pricing";
|
|
7
7
|
import { registerGithubTaskReactions } from "./github/task-reactions";
|
|
8
|
+
import { loadGlobalConfigsIntoEnv } from "./http/core";
|
|
8
9
|
import { isRbacEnabled } from "./rbac";
|
|
9
10
|
import { registerCancelTaskTool } from "./tools/cancel-task";
|
|
10
11
|
import { registerContextDiffTool } from "./tools/context-diff";
|
|
@@ -160,20 +161,83 @@ import {
|
|
|
160
161
|
} from "./tools/workflows";
|
|
161
162
|
import { resolveScriptsOnlyMode } from "./utils/scripts-only-mode";
|
|
162
163
|
|
|
164
|
+
// Every known capability, including the ones disabled by default. Exported for
|
|
165
|
+
// surfaces that must see the full tool registry regardless of deployment
|
|
166
|
+
// defaults (tests, drift checks).
|
|
167
|
+
export const ALL_CAPABILITIES = [
|
|
168
|
+
"core",
|
|
169
|
+
"task-pool",
|
|
170
|
+
"scripts",
|
|
171
|
+
"config",
|
|
172
|
+
"prompt-templates",
|
|
173
|
+
"mcp",
|
|
174
|
+
"profiles",
|
|
175
|
+
"services",
|
|
176
|
+
"scheduling",
|
|
177
|
+
"memory",
|
|
178
|
+
"workflows",
|
|
179
|
+
"pages",
|
|
180
|
+
"metrics",
|
|
181
|
+
"kv",
|
|
182
|
+
"slack",
|
|
183
|
+
"tracker",
|
|
184
|
+
"skills",
|
|
185
|
+
"messaging",
|
|
186
|
+
"repo",
|
|
187
|
+
"agentmail",
|
|
188
|
+
"kapso",
|
|
189
|
+
"swarm-x",
|
|
190
|
+
] as const;
|
|
191
|
+
|
|
192
|
+
type CAPABILITIES_T = (typeof ALL_CAPABILITIES)[number];
|
|
193
|
+
|
|
163
194
|
// Capability-based feature flags
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
"
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
195
|
+
const DEFAULT_CAPABILITIES: string = [
|
|
196
|
+
"core",
|
|
197
|
+
"task-pool",
|
|
198
|
+
"scripts",
|
|
199
|
+
"config",
|
|
200
|
+
"mcp",
|
|
201
|
+
"profiles",
|
|
202
|
+
"scheduling",
|
|
203
|
+
"memory",
|
|
204
|
+
"workflows",
|
|
205
|
+
"pages",
|
|
206
|
+
"metrics",
|
|
207
|
+
"kv",
|
|
208
|
+
"slack",
|
|
209
|
+
"tracker",
|
|
210
|
+
"skills",
|
|
211
|
+
"repo",
|
|
212
|
+
//
|
|
213
|
+
// Disabled by default
|
|
214
|
+
//
|
|
215
|
+
// "services",
|
|
216
|
+
// "prompt-templates",
|
|
217
|
+
// "messaging",
|
|
218
|
+
// "swarm-x",
|
|
219
|
+
// "agentmail",
|
|
220
|
+
// "kapso",
|
|
221
|
+
].join(",");
|
|
222
|
+
|
|
223
|
+
// Note: unknown names are kept (they never match hasCapability); workers
|
|
224
|
+
// reuse this env var for free-form skill tags, so dropping them here would
|
|
225
|
+
// break agent capability declarations. Empty entries (trailing commas) are
|
|
226
|
+
// filtered so they can't leak into enabledCapabilities payloads.
|
|
227
|
+
const getCapabilities = (): Set<CAPABILITIES_T> =>
|
|
228
|
+
new Set(
|
|
229
|
+
(process.env.CAPABILITIES || DEFAULT_CAPABILITIES)
|
|
230
|
+
.split(",")
|
|
231
|
+
.map((s) => s.trim() as CAPABILITIES_T)
|
|
232
|
+
.filter((s) => s.length > 0),
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
export function hasCapability(cap: CAPABILITIES_T): boolean {
|
|
236
|
+
return getCapabilities().has(cap);
|
|
173
237
|
}
|
|
174
238
|
|
|
175
|
-
export function getEnabledCapabilities():
|
|
176
|
-
return Array.from(
|
|
239
|
+
export function getEnabledCapabilities(): CAPABILITIES_T[] {
|
|
240
|
+
return Array.from(getCapabilities());
|
|
177
241
|
}
|
|
178
242
|
|
|
179
243
|
/**
|
|
@@ -187,16 +251,28 @@ export function isScriptsOnlyMcp(): boolean {
|
|
|
187
251
|
return resolveScriptsOnlyMode({ env: process.env.SCRIPTS_ONLY_MCP });
|
|
188
252
|
}
|
|
189
253
|
|
|
190
|
-
export function createServer(opts: { scriptsOnly?: boolean } = {}) {
|
|
254
|
+
export function createServer(opts: { scriptsOnly?: boolean; fullSurface?: boolean } = {}) {
|
|
255
|
+
// Reload env
|
|
256
|
+
loadGlobalConfigsIntoEnv(true);
|
|
257
|
+
|
|
258
|
+
// Capability flags shape the externally exposed MCP tool list only. Internal
|
|
259
|
+
// full-surface consumers (the scripts SDK bridge, drift-check tests) pass
|
|
260
|
+
// fullSurface to register every tool group regardless of CAPABILITIES.
|
|
261
|
+
// This shadows the module-level hasCapability for the registrations below.
|
|
262
|
+
const hasCapability = (cap: CAPABILITIES_T): boolean =>
|
|
263
|
+
opts.fullSurface === true || getCapabilities().has(cap);
|
|
264
|
+
|
|
191
265
|
// Initialize database with WAL mode
|
|
192
266
|
// Uses DATABASE_PATH env var for Docker volume compatibility (WAL needs .sqlite, .sqlite-wal, .sqlite-shm on same filesystem)
|
|
193
267
|
initDb(process.env.DATABASE_PATH);
|
|
268
|
+
|
|
194
269
|
// Phase 2: project the vendored models.dev snapshot into the pricing table.
|
|
195
270
|
// Idempotent (INSERT OR IGNORE keyed on PK with effective_from=0); safe to
|
|
196
271
|
// call on every boot. See src/be/seed-pricing.ts for the projection logic
|
|
197
272
|
// and the manual-override constants for runtime-fee / ACU pricing.
|
|
198
273
|
seedPricingFromModelsDev();
|
|
199
274
|
startPricingRefreshLoop();
|
|
275
|
+
|
|
200
276
|
try {
|
|
201
277
|
ensureRbacSeedsSynced();
|
|
202
278
|
} catch (err) {
|
|
@@ -233,94 +309,69 @@ export function createServer(opts: { scriptsOnly?: boolean } = {}) {
|
|
|
233
309
|
registerScriptDeleteTool(server);
|
|
234
310
|
registerScriptQueryTypesTool(server);
|
|
235
311
|
registerScriptRunsTools(server);
|
|
312
|
+
|
|
236
313
|
return server;
|
|
237
314
|
}
|
|
238
315
|
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
registerListConfigTool(server);
|
|
263
|
-
registerDeleteConfigTool(server);
|
|
264
|
-
registerCredentialBindingsTool(server);
|
|
265
|
-
|
|
266
|
-
// Repo management tools - always registered (repo config is fundamental)
|
|
267
|
-
registerGetReposTool(server);
|
|
268
|
-
registerUpdateRepoTool(server);
|
|
269
|
-
|
|
270
|
-
// Prompt template tools - always registered (prompt management is fundamental)
|
|
271
|
-
registerListPromptTemplatesTool(server);
|
|
272
|
-
registerGetPromptTemplateTool(server);
|
|
273
|
-
registerSetPromptTemplateTool(server);
|
|
274
|
-
registerDeletePromptTemplateTool(server);
|
|
275
|
-
registerPreviewPromptTemplateTool(server);
|
|
276
|
-
|
|
277
|
-
// Reusable script catalog tools - always registered (HTTP MCP only in v1).
|
|
278
|
-
registerScriptSearchTool(server);
|
|
279
|
-
registerScriptConnectionsTool(server);
|
|
280
|
-
registerScriptApisTool(server);
|
|
281
|
-
registerScriptRunTool(server);
|
|
282
|
-
registerScriptUpsertTool(server);
|
|
283
|
-
registerScriptDeleteTool(server);
|
|
284
|
-
registerScriptQueryTypesTool(server);
|
|
285
|
-
registerScriptRunsTools(server);
|
|
286
|
-
|
|
287
|
-
// External command routes - mirrors the `agent-swarm x ...` CLI surface.
|
|
288
|
-
registerSwarmXTool(server);
|
|
289
|
-
|
|
290
|
-
// Slack integration tools (always registered, will no-op if Slack not configured)
|
|
291
|
-
registerSlackReplyTool(server);
|
|
292
|
-
registerSlackReadTool(server);
|
|
293
|
-
registerSlackPostTool(server);
|
|
294
|
-
registerSlackStartThreadTool(server);
|
|
295
|
-
registerSlackListChannelsTool(server);
|
|
296
|
-
registerSlackUploadFileTool(server);
|
|
297
|
-
registerSlackDownloadFileTool(server);
|
|
298
|
-
registerSlackDeleteTool(server);
|
|
299
|
-
registerSlackUpdateTool(server);
|
|
300
|
-
|
|
301
|
-
// AgentMail integration tool (always registered, self-service inbox mapping)
|
|
302
|
-
registerRegisterAgentmailInboxTool(server);
|
|
303
|
-
|
|
304
|
-
// Kapso/WhatsApp integration tools (native inbound provisioning + outbound)
|
|
305
|
-
registerRegisterKapsoNumberTool(server);
|
|
306
|
-
registerUnregisterKapsoNumberTool(server);
|
|
307
|
-
registerSendWhatsappMessageTool(server);
|
|
308
|
-
registerReplyWhatsappMessageTool(server);
|
|
316
|
+
// Start of default-enabled capabilities
|
|
317
|
+
|
|
318
|
+
// Core capability - swarm membership, task flow, progress, user identity, and lead debug tools
|
|
319
|
+
if (hasCapability("core")) {
|
|
320
|
+
registerJoinSwarmTool(server);
|
|
321
|
+
registerPollTaskTool(server);
|
|
322
|
+
registerGetSwarmTool(server);
|
|
323
|
+
registerGetTasksTool(server);
|
|
324
|
+
registerGetMetricsTool(server);
|
|
325
|
+
registerSendTaskTool(server);
|
|
326
|
+
registerGetTaskDetailsTool(server);
|
|
327
|
+
registerStoreProgressTool(server);
|
|
328
|
+
registerMyAgentInfoTool(server);
|
|
329
|
+
registerCancelTaskTool(server);
|
|
330
|
+
|
|
331
|
+
// User identity tools
|
|
332
|
+
registerResolveUserTool(server);
|
|
333
|
+
registerManageUserTool(server); // self-guards with lead check
|
|
334
|
+
|
|
335
|
+
// Debug tools (self-guard with lead check)
|
|
336
|
+
registerDbQueryTool(server);
|
|
337
|
+
registerGetOauthAccessTokenTool(server);
|
|
338
|
+
}
|
|
309
339
|
|
|
310
340
|
// Task pool capability - task pool operations (create unassigned, claim, release, accept, reject)
|
|
311
341
|
if (hasCapability("task-pool")) {
|
|
312
342
|
registerTaskActionTool(server);
|
|
313
343
|
}
|
|
314
344
|
|
|
315
|
-
//
|
|
316
|
-
|
|
317
|
-
|
|
345
|
+
// Config capability - swarm config management and credential bindings
|
|
346
|
+
if (hasCapability("config")) {
|
|
347
|
+
registerSetConfigTool(server);
|
|
348
|
+
registerGetConfigTool(server);
|
|
349
|
+
registerListConfigTool(server);
|
|
350
|
+
registerDeleteConfigTool(server);
|
|
351
|
+
registerCredentialBindingsTool(server);
|
|
352
|
+
}
|
|
318
353
|
|
|
319
|
-
//
|
|
320
|
-
if (hasCapability("
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
354
|
+
// Scripts capability - reusable script catalog (HTTP MCP only in v1)
|
|
355
|
+
if (hasCapability("scripts")) {
|
|
356
|
+
registerScriptSearchTool(server);
|
|
357
|
+
registerScriptConnectionsTool(server);
|
|
358
|
+
registerScriptApisTool(server);
|
|
359
|
+
registerScriptRunTool(server);
|
|
360
|
+
registerScriptUpsertTool(server);
|
|
361
|
+
registerScriptDeleteTool(server);
|
|
362
|
+
registerScriptQueryTypesTool(server);
|
|
363
|
+
registerScriptRunsTools(server);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// MCP capability - managed MCP server registry (CRUD + install/uninstall)
|
|
367
|
+
if (hasCapability("mcp")) {
|
|
368
|
+
registerMcpServerCreateTool(server);
|
|
369
|
+
registerMcpServerUpdateTool(server);
|
|
370
|
+
registerMcpServerDeleteTool(server);
|
|
371
|
+
registerMcpServerGetTool(server);
|
|
372
|
+
registerMcpServerListTool(server);
|
|
373
|
+
registerMcpServerInstallTool(server);
|
|
374
|
+
registerMcpServerUninstallTool(server);
|
|
324
375
|
}
|
|
325
376
|
|
|
326
377
|
// Profiles capability - agent profile management
|
|
@@ -330,12 +381,10 @@ export function createServer(opts: { scriptsOnly?: boolean } = {}) {
|
|
|
330
381
|
registerContextDiffTool(server);
|
|
331
382
|
}
|
|
332
383
|
|
|
333
|
-
//
|
|
334
|
-
if (hasCapability("
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
registerListServicesTool(server);
|
|
338
|
-
registerUpdateServiceStatusTool(server);
|
|
384
|
+
// Repo capability - repository configuration management
|
|
385
|
+
if (hasCapability("repo")) {
|
|
386
|
+
registerGetReposTool(server);
|
|
387
|
+
registerUpdateRepoTool(server);
|
|
339
388
|
}
|
|
340
389
|
|
|
341
390
|
// Scheduling capability - scheduled task management
|
|
@@ -359,11 +408,13 @@ export function createServer(opts: { scriptsOnly?: boolean } = {}) {
|
|
|
359
408
|
}
|
|
360
409
|
|
|
361
410
|
// Tracker capability - external issue tracker integration
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
411
|
+
if (hasCapability("tracker")) {
|
|
412
|
+
registerTrackerStatusTool(server);
|
|
413
|
+
registerTrackerLinkTaskTool(server);
|
|
414
|
+
registerTrackerUnlinkTool(server);
|
|
415
|
+
registerTrackerSyncStatusTool(server);
|
|
416
|
+
registerTrackerMapAgentTool(server);
|
|
417
|
+
}
|
|
367
418
|
|
|
368
419
|
// Workflows capability - DAG-based automation workflows
|
|
369
420
|
if (hasCapability("workflows")) {
|
|
@@ -382,35 +433,34 @@ export function createServer(opts: { scriptsOnly?: boolean } = {}) {
|
|
|
382
433
|
registerRequestHumanInputTool(server);
|
|
383
434
|
}
|
|
384
435
|
|
|
385
|
-
// Skills -
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
436
|
+
// Skills capability - installable skill packages (create, search, install, publish)
|
|
437
|
+
if (hasCapability("skills")) {
|
|
438
|
+
registerSkillCreateTool(server);
|
|
439
|
+
registerSkillUpdateTool(server);
|
|
440
|
+
registerSkillDeleteTool(server);
|
|
441
|
+
registerSkillGetTool(server);
|
|
442
|
+
registerSkillGetFileTool(server);
|
|
443
|
+
registerSkillListTool(server);
|
|
444
|
+
registerSkillSearchTool(server);
|
|
445
|
+
registerSkillInstallTool(server);
|
|
446
|
+
registerSkillUninstallTool(server);
|
|
447
|
+
registerSkillInstallRemoteTool(server);
|
|
448
|
+
registerSkillSyncRemoteTool(server);
|
|
449
|
+
registerSkillPublishTool(server);
|
|
450
|
+
}
|
|
398
451
|
|
|
399
452
|
// Pages capability - DB-backed lightweight artifacts (HTML / JSON specs).
|
|
400
|
-
// Enabled by default (added to DEFAULT_CAPABILITIES in step-9 of the
|
|
401
|
-
// db-backed-pages plan). Operators can disable via explicit
|
|
402
|
-
// `CAPABILITIES=...` env without `pages`.
|
|
403
453
|
if (hasCapability("pages")) {
|
|
404
454
|
registerCreatePageTool(server);
|
|
405
455
|
registerDeletePageTool(server);
|
|
406
456
|
}
|
|
407
457
|
|
|
458
|
+
// Metrics capability - time-series metrics (DB-backed, for dashboards).
|
|
408
459
|
if (hasCapability("metrics")) {
|
|
409
460
|
registerCreateMetricTool(server);
|
|
410
461
|
}
|
|
411
462
|
|
|
412
463
|
// KV capability — namespaced Redis-like key/value (see src/be/migrations/061_kv_store.sql).
|
|
413
|
-
// Enabled by default; opt out via `CAPABILITIES=...` without `kv`.
|
|
414
464
|
if (hasCapability("kv")) {
|
|
415
465
|
registerKvGetTool(server);
|
|
416
466
|
registerKvSetTool(server);
|
|
@@ -419,14 +469,68 @@ export function createServer(opts: { scriptsOnly?: boolean } = {}) {
|
|
|
419
469
|
registerKvListTool(server);
|
|
420
470
|
}
|
|
421
471
|
|
|
422
|
-
//
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
472
|
+
// Slack capability - Slack integration tools (no-op if Slack is not configured)
|
|
473
|
+
if (hasCapability("slack")) {
|
|
474
|
+
registerSlackReplyTool(server);
|
|
475
|
+
registerSlackReadTool(server);
|
|
476
|
+
registerSlackPostTool(server);
|
|
477
|
+
registerSlackStartThreadTool(server);
|
|
478
|
+
registerSlackListChannelsTool(server);
|
|
479
|
+
registerSlackUploadFileTool(server);
|
|
480
|
+
registerSlackDownloadFileTool(server);
|
|
481
|
+
registerSlackDeleteTool(server);
|
|
482
|
+
registerSlackUpdateTool(server);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// End of default-enabled capabilities
|
|
486
|
+
// ----------------------------
|
|
487
|
+
// Start of default-disabled capabilities
|
|
488
|
+
|
|
489
|
+
// Prompt-templates capability - prompt template management (list/get/set/delete/preview)
|
|
490
|
+
if (hasCapability("prompt-templates")) {
|
|
491
|
+
registerListPromptTemplatesTool(server);
|
|
492
|
+
registerGetPromptTemplateTool(server);
|
|
493
|
+
registerSetPromptTemplateTool(server);
|
|
494
|
+
registerDeletePromptTemplateTool(server);
|
|
495
|
+
registerPreviewPromptTemplateTool(server);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Agentmail capability - AgentMail integration (self-service inbox mapping)
|
|
499
|
+
if (hasCapability("agentmail")) {
|
|
500
|
+
registerRegisterAgentmailInboxTool(server);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Kapso capability - Kapso/WhatsApp integration (native inbound provisioning + outbound)
|
|
504
|
+
if (hasCapability("kapso")) {
|
|
505
|
+
registerRegisterKapsoNumberTool(server);
|
|
506
|
+
registerUnregisterKapsoNumberTool(server);
|
|
507
|
+
registerSendWhatsappMessageTool(server);
|
|
508
|
+
registerReplyWhatsappMessageTool(server);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Swarm-x capability - external command routes mirroring the `agent-swarm x ...` CLI surface
|
|
512
|
+
if (hasCapability("swarm-x")) {
|
|
513
|
+
registerSwarmXTool(server);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Messaging capability - internal swarm chat (post/read messages, channel CRUD)
|
|
517
|
+
if (hasCapability("messaging")) {
|
|
518
|
+
registerPostMessageTool(server);
|
|
519
|
+
registerReadMessagesTool(server);
|
|
520
|
+
|
|
521
|
+
// Channel management (CRUD on channels)
|
|
522
|
+
registerListChannelsTool(server);
|
|
523
|
+
registerCreateChannelTool(server);
|
|
524
|
+
registerDeleteChannelTool(server);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Services capability - PM2/background service registry
|
|
528
|
+
if (hasCapability("services")) {
|
|
529
|
+
registerRegisterServiceTool(server);
|
|
530
|
+
registerUnregisterServiceTool(server);
|
|
531
|
+
registerListServicesTool(server);
|
|
532
|
+
registerUpdateServiceStatusTool(server);
|
|
533
|
+
}
|
|
430
534
|
|
|
431
535
|
return server;
|
|
432
536
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { getAgentColorToken, resolveAgentColor } from "../../apps/ui/src/lib/agent-color";
|
|
3
|
+
import {
|
|
4
|
+
AVATAR_ICON_CATALOG,
|
|
5
|
+
getAgentIcon,
|
|
6
|
+
resolveAgentIcon,
|
|
7
|
+
} from "../../apps/ui/src/lib/agent-icon";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Covers the pure avatar-resolution logic behind the customizable agent
|
|
11
|
+
* avatar feature (icon + color). These are the deterministic building
|
|
12
|
+
* blocks consumed by `agent-avatar.tsx` and the appearance picker — no React
|
|
13
|
+
* rendering involved, so they're testable with the existing `bun test`
|
|
14
|
+
* harness (apps/ui has no component-test infra; see PR discussion).
|
|
15
|
+
*/
|
|
16
|
+
describe("agent avatar resolution", () => {
|
|
17
|
+
describe("getAgentIcon (deterministic fallback)", () => {
|
|
18
|
+
test("lead always resolves to Crown, regardless of id", () => {
|
|
19
|
+
expect(getAgentIcon({ agentId: "any-id", isLead: true })).toBe(AVATAR_ICON_CATALOG.crown);
|
|
20
|
+
expect(getAgentIcon({ role: "lead", agentId: "any-id" })).toBe(AVATAR_ICON_CATALOG.crown);
|
|
21
|
+
expect(getAgentIcon({ agentName: "Lead", agentId: "any-id" })).toBe(
|
|
22
|
+
AVATAR_ICON_CATALOG.crown,
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test("same agentId always resolves to the same icon (deterministic)", () => {
|
|
27
|
+
const first = getAgentIcon({ agentId: "agent-123" });
|
|
28
|
+
const second = getAgentIcon({ agentId: "agent-123" });
|
|
29
|
+
expect(first).toBe(second);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("different agentIds can resolve to different icons", () => {
|
|
33
|
+
// Not a strict guarantee for every pair (hash collisions are possible),
|
|
34
|
+
// but across a spread of ids we should see more than one icon.
|
|
35
|
+
const icons = new Set(
|
|
36
|
+
Array.from({ length: 20 }, (_, i) => getAgentIcon({ agentId: `worker-${i}` })),
|
|
37
|
+
);
|
|
38
|
+
expect(icons.size).toBeGreaterThan(1);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("empty/missing seed falls back to Bot", () => {
|
|
42
|
+
expect(getAgentIcon({})).toBe(AVATAR_ICON_CATALOG.bot);
|
|
43
|
+
expect(getAgentIcon({ agentId: "", agentName: "" })).toBe(AVATAR_ICON_CATALOG.bot);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("resolveAgentIcon (custom avatar overrides deterministic fallback)", () => {
|
|
48
|
+
test("a known catalog icon wins over the deterministic fallback", () => {
|
|
49
|
+
const avatar = { type: "lucide" as const, icon: "trophy" };
|
|
50
|
+
const fallback = { agentId: "some-agent" };
|
|
51
|
+
expect(resolveAgentIcon(avatar, fallback)).toBe(AVATAR_ICON_CATALOG.trophy);
|
|
52
|
+
// Sanity check it's actually overriding, not coincidentally equal.
|
|
53
|
+
expect(resolveAgentIcon(avatar, fallback)).not.toBe(getAgentIcon(fallback));
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("an unknown icon name falls back to the deterministic default", () => {
|
|
57
|
+
const avatar = { type: "lucide" as const, icon: "not-a-real-icon" };
|
|
58
|
+
const fallback = { agentId: "some-agent" };
|
|
59
|
+
expect(resolveAgentIcon(avatar, fallback)).toBe(getAgentIcon(fallback));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("null/undefined avatar (reset to default) falls back to the deterministic default", () => {
|
|
63
|
+
const fallback = { agentId: "some-agent", isLead: false };
|
|
64
|
+
expect(resolveAgentIcon(null, fallback)).toBe(getAgentIcon(fallback));
|
|
65
|
+
expect(resolveAgentIcon(undefined, fallback)).toBe(getAgentIcon(fallback));
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("getAgentColorToken (deterministic fallback)", () => {
|
|
70
|
+
test("lead always resolves to primary", () => {
|
|
71
|
+
expect(getAgentColorToken({ role: "lead", agentId: "x" })).toBe("primary");
|
|
72
|
+
expect(getAgentColorToken({ agentName: "Lead", agentId: "x" })).toBe("primary");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("same agentId always resolves to the same token (deterministic)", () => {
|
|
76
|
+
expect(getAgentColorToken({ agentId: "agent-abc" })).toBe(
|
|
77
|
+
getAgentColorToken({ agentId: "agent-abc" }),
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("empty/missing seed falls back to action-default", () => {
|
|
82
|
+
expect(getAgentColorToken({})).toBe("action-default");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("resolveAgentColor (custom hex overrides deterministic fallback)", () => {
|
|
87
|
+
test("a custom hex wins over the deterministic token", () => {
|
|
88
|
+
const avatar = { type: "lucide" as const, icon: "star", color: "#ff00aa" };
|
|
89
|
+
const fallback = { agentId: "some-agent" };
|
|
90
|
+
expect(resolveAgentColor(avatar, fallback)).toEqual({ kind: "custom", hex: "#ff00aa" });
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("a lucide avatar with no color falls back to the deterministic token", () => {
|
|
94
|
+
const avatar = { type: "lucide" as const, icon: "star" };
|
|
95
|
+
const fallback = { agentId: "some-agent" };
|
|
96
|
+
expect(resolveAgentColor(avatar, fallback)).toEqual({
|
|
97
|
+
kind: "token",
|
|
98
|
+
token: getAgentColorToken(fallback),
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("an empty-string color is treated as unset (falls back)", () => {
|
|
103
|
+
const avatar = { type: "lucide" as const, icon: "star", color: "" };
|
|
104
|
+
const fallback = { agentId: "some-agent" };
|
|
105
|
+
expect(resolveAgentColor(avatar, fallback)).toEqual({
|
|
106
|
+
kind: "token",
|
|
107
|
+
token: getAgentColorToken(fallback),
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("null/undefined avatar (reset to default) falls back to the deterministic token", () => {
|
|
112
|
+
const fallback = { agentId: "some-agent" };
|
|
113
|
+
expect(resolveAgentColor(null, fallback)).toEqual({
|
|
114
|
+
kind: "token",
|
|
115
|
+
token: getAgentColorToken(fallback),
|
|
116
|
+
});
|
|
117
|
+
expect(resolveAgentColor(undefined, fallback)).toEqual({
|
|
118
|
+
kind: "token",
|
|
119
|
+
token: getAgentColorToken(fallback),
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
@@ -44,6 +44,11 @@ describe("agents list model display", () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
test("presents latest Anthropic direct model ids as readable labels", () => {
|
|
47
|
+
expect(getAgentModelPresentation("claude-opus-5")).toMatchObject({
|
|
48
|
+
label: "Claude Opus 5",
|
|
49
|
+
provider: "Anthropic",
|
|
50
|
+
providerId: "anthropic",
|
|
51
|
+
});
|
|
47
52
|
expect(getAgentModelPresentation("claude-fable-5")).toMatchObject({
|
|
48
53
|
label: "Claude Fable 5",
|
|
49
54
|
provider: "Anthropic",
|
|
@@ -59,6 +64,11 @@ describe("agents list model display", () => {
|
|
|
59
64
|
provider: "Anthropic",
|
|
60
65
|
providerId: "anthropic",
|
|
61
66
|
});
|
|
67
|
+
expect(getAgentModelPresentation("opus")).toMatchObject({
|
|
68
|
+
label: "Claude Opus 5",
|
|
69
|
+
provider: "Anthropic",
|
|
70
|
+
providerId: "anthropic",
|
|
71
|
+
});
|
|
62
72
|
});
|
|
63
73
|
|
|
64
74
|
// ── Phase 6 (reasoning-effort plan) ─────────────────────────────────────────
|
|
@@ -739,3 +739,75 @@ describe("getBasePrompt — conditional Slack templates", () => {
|
|
|
739
739
|
expect(result).toContain("C123");
|
|
740
740
|
});
|
|
741
741
|
});
|
|
742
|
+
|
|
743
|
+
// ---------------------------------------------------------------------------
|
|
744
|
+
// Server capability gating (serverCapabilities = the API server's enabled
|
|
745
|
+
// tool groups, reported on registration; distinct from agent skill tags)
|
|
746
|
+
// ---------------------------------------------------------------------------
|
|
747
|
+
|
|
748
|
+
describe("getBasePrompt — serverCapabilities gating", () => {
|
|
749
|
+
test("messaging section kept when serverCapabilities is unknown (legacy servers registered the tools unconditionally)", async () => {
|
|
750
|
+
const result = await getBasePrompt(minimalArgs);
|
|
751
|
+
expect(result).toContain("post-message");
|
|
752
|
+
expect(result).toContain("read-messages");
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
test("messaging section omitted when server capabilities omit messaging", async () => {
|
|
756
|
+
const result = await getBasePrompt({
|
|
757
|
+
...minimalArgs,
|
|
758
|
+
serverCapabilities: ["core"],
|
|
759
|
+
});
|
|
760
|
+
expect(result).not.toContain("post-message");
|
|
761
|
+
expect(result).not.toContain("read-messages");
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
test("messaging section included when the server enables messaging", async () => {
|
|
765
|
+
const result = await getBasePrompt({
|
|
766
|
+
...minimalArgs,
|
|
767
|
+
serverCapabilities: ["core", "messaging"],
|
|
768
|
+
});
|
|
769
|
+
expect(result).toContain("#### Swarm Messaging");
|
|
770
|
+
expect(result).toContain("post-message");
|
|
771
|
+
expect(result).toContain("read-messages");
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
test("services section dropped when server capabilities omit services", async () => {
|
|
775
|
+
const result = await getBasePrompt({
|
|
776
|
+
...minimalArgs,
|
|
777
|
+
serverCapabilities: ["core"],
|
|
778
|
+
});
|
|
779
|
+
expect(result).not.toContain("register-service");
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
test("services section kept for legacy servers that report no capabilities", async () => {
|
|
783
|
+
const result = await getBasePrompt(minimalArgs);
|
|
784
|
+
expect(result).toContain("register-service");
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
test("server-enabled services shows section even without the agent skill tag", async () => {
|
|
788
|
+
const result = await getBasePrompt({
|
|
789
|
+
...minimalArgs,
|
|
790
|
+
capabilities: ["typescript"],
|
|
791
|
+
serverCapabilities: ["core", "services"],
|
|
792
|
+
});
|
|
793
|
+
expect(result).toContain("register-service");
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
test("slack section dropped when server capabilities omit slack", async () => {
|
|
797
|
+
enableSlackPromptTools();
|
|
798
|
+
const result = await getBasePrompt({
|
|
799
|
+
...minimalArgs,
|
|
800
|
+
serverCapabilities: ["core"],
|
|
801
|
+
});
|
|
802
|
+
expect(result).not.toContain("slack-list-channels");
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
test("slack section kept when the server enables slack", async () => {
|
|
806
|
+
enableSlackPromptTools();
|
|
807
|
+
const result = await getBasePrompt({
|
|
808
|
+
...minimalArgs,
|
|
809
|
+
serverCapabilities: ["core", "slack"],
|
|
810
|
+
});
|
|
811
|
+
expect(result).toContain("slack-list-channels");
|
|
812
|
+
});
|
|
813
|
+
});
|
|
@@ -802,6 +802,12 @@ describe("ClaudeManagedAdapter (Phase 4) — repo provisioning + cost data", ()
|
|
|
802
802
|
});
|
|
803
803
|
|
|
804
804
|
test("CLAUDE_MANAGED_MODEL_PRICING covers sonnet, opus, haiku at minimum", () => {
|
|
805
|
+
expect(CLAUDE_MANAGED_MODEL_PRICING["claude-opus-5"]).toEqual({
|
|
806
|
+
inputPerMillion: 5.0,
|
|
807
|
+
outputPerMillion: 25.0,
|
|
808
|
+
cacheReadPerMillion: 0.5,
|
|
809
|
+
cacheWritePerMillion: 6.25,
|
|
810
|
+
});
|
|
805
811
|
expect(CLAUDE_MANAGED_MODEL_PRICING["claude-fable-5"]).toEqual({
|
|
806
812
|
inputPerMillion: 10.0,
|
|
807
813
|
outputPerMillion: 50.0,
|