@desplega.ai/agent-swarm 2.7.2 → 2.7.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/README.md +6 -0
- package/dist/{acp-adapter-624yge7a.js → acp-adapter-pdzw76ja.js} +1 -1
- package/dist/{actions-rd9xn281.js → actions-a90cfpca.js} +21 -21
- package/dist/{amp-adapter-k27hc00p.js → amp-adapter-4vtywcjk.js} +2 -2
- package/dist/{app-sjm3xc7g.js → app-8k68gygk.js} +3 -3
- package/dist/{assistant-6jbzs8wa.js → assistant-ck01q2yg.js} +32 -21
- package/dist/{boot-reembed-e2348eqc.js → boot-reembed-33spavpd.js} +1 -1
- package/dist/{boot-reembed-w53pd5xt.js → boot-reembed-xzge83a2.js} +1 -1
- package/dist/{boot-scrub-sweep-cpy4yg97.js → boot-scrub-sweep-mxvb8dr3.js} +3 -3
- package/dist/{boot-seeds-f6j4t6k6.js → boot-seeds-rpm8bb5r.js} +4 -4
- package/dist/{claude-adapter-v3ac8esd.js → claude-adapter-q12bcfj9.js} +3 -3
- package/dist/{claude-managed-setup-yyrkqvtm.js → claude-managed-setup-11vb6q89.js} +1 -1
- package/dist/{claude-sdk-session-85j69v6d.js → claude-sdk-session-gkv1107j.js} +10325 -10243
- package/dist/{cli-rs59z1qx.js → cli-07pcqwaj.js} +1 -1
- package/dist/{cli-6vq3ymqm.js → cli-0tkm519n.js} +1 -1
- package/dist/{cli-s7cm1927.js → cli-0xzbk52h.js} +4 -4
- package/dist/{cli-g0zc1b40.js → cli-0zae6bs6.js} +2 -2
- package/dist/{cli-p8yrsmfn.js → cli-10kjx0dm.js} +1 -1
- package/dist/{cli-7xsq63pe.js → cli-157ykn37.js} +10 -9
- package/dist/{cli-vjcj9k2p.js → cli-2h0rfmqk.js} +1 -1
- package/dist/{cli-9wasax9f.js → cli-35nzvqaf.js} +1 -1
- package/dist/{cli-e1p7dqe1.js → cli-4aydmmdy.js} +24 -3
- package/dist/{cli-942pp3bc.js → cli-54ax65rn.js} +3 -3
- package/dist/{cli-10cp92df.js → cli-5ke7gxwr.js} +6 -6
- package/dist/{cli-femw4q81.js → cli-6151a7dr.js} +2 -2
- package/dist/{cli-3cywb44q.js → cli-77eq8txs.js} +85 -3
- package/dist/{cli-atpfk4yd.js → cli-7cwrwb5x.js} +5 -5
- package/dist/{cli-bfbpvccx.js → cli-8a1k6mat.js} +61 -49
- package/dist/{cli-c18941tx.js → cli-8ch3b2r7.js} +3 -3
- package/dist/{cli-rs2s1t05.js → cli-9fk56y8c.js} +4 -4
- package/dist/{cli-0wx63vvw.js → cli-9km88w11.js} +1 -1
- package/dist/{cli-qy0z3mfj.js → cli-9vttw9nz.js} +56 -46
- package/dist/{cli-mzgppb7q.js → cli-a0w50zw9.js} +4 -4
- package/dist/{cli-z8a4mfz1.js → cli-aqp59jmv.js} +4 -4
- package/dist/{cli-5d8wd50e.js → cli-bs0fwb23.js} +1 -1
- package/dist/{cli-fa4kxxx3.js → cli-ct5920jb.js} +2 -2
- package/dist/{cli-0awbtmv2.js → cli-dek8hqjc.js} +10 -10
- package/dist/{cli-qp6adcmw.js → cli-e24w2mvk.js} +1 -1
- package/dist/{cli-t3npd8hm.js → cli-ghfhn1qc.js} +1 -1
- package/dist/{cli-jmcf8cnz.js → cli-ja369zab.js} +1 -1
- package/dist/{cli-wtjg6je3.js → cli-jhh7tbx6.js} +1 -1
- package/dist/{cli-e19bgatr.js → cli-jmk31131.js} +2 -2
- package/dist/{cli-2cj8fqv1.js → cli-kjcdzea8.js} +1 -1
- package/dist/{cli-1xpr5992.js → cli-kjha1q9k.js} +3 -3
- package/dist/{cli-9jfty8px.js → cli-ktcdczth.js} +538 -30
- package/dist/{cli-exd52qn4.js → cli-mcmpbpcc.js} +2 -2
- package/dist/{cli-2m2p3snc.js → cli-mmf43vcp.js} +6 -6
- package/dist/{cli-b2rhbaty.js → cli-pnm99spe.js} +10 -10
- package/dist/{cli-9jn9cj0q.js → cli-v9jk2k63.js} +1 -1
- package/dist/{cli-mt7bxjfd.js → cli-vhgcwppn.js} +1 -1
- package/dist/{cli-qa4hgda3.js → cli-vvz64zc5.js} +14 -13
- package/dist/{cli-txr0z97c.js → cli-wmhajw68.js} +171 -32
- package/dist/{cli-hzrmv8pg.js → cli-x38rmhap.js} +3 -3
- package/dist/{cli-hq9hd4hp.js → cli-xz6qjdqj.js} +1 -1
- package/dist/{cli-g9ypd5en.js → cli-z52gq55b.js} +4 -0
- package/dist/{cli-2qbmjfta.js → cli-z6219sd3.js} +4 -4
- package/dist/cli.js +19 -19
- package/dist/{codex-adapter-zm1bkdde.js → codex-adapter-46kbvvkx.js} +1 -1
- package/dist/{codex-hook-tkag7fxq.js → codex-hook-tm9ecrd5.js} +1 -1
- package/dist/{codex-session-runner-8k02mqw2.js → codex-session-runner-qy93hdrv.js} +1 -1
- package/dist/{commands-nw1dn4av.js → commands-hwdhacfx.js} +2 -2
- package/dist/{controller-3kkkmps0.js → controller-hjza5p1f.js} +3 -3
- package/dist/{controllers-connect-n2c4167r.js → controllers-connect-7m25cay2.js} +20 -20
- package/dist/{cursor-adapter-h5028emw.js → cursor-adapter-1qh7ps8w.js} +1 -1
- package/dist/{db-76y2msnf.js → db-w23k9301.js} +2 -2
- package/dist/{db-8rk0p8j1.js → db-wm8by383.js} +3 -3
- package/dist/{dispatcher-xp4wsx30.js → dispatcher-en25ebgc.js} +18 -18
- package/dist/{dsh-adapter-vyrr31bn.js → dsh-adapter-zkme32vd.js} +1 -1
- package/dist/{e2b-eesfj689.js → e2b-9z9mvt2p.js} +1 -1
- package/dist/{e2b-03nha1wz.js → e2b-yhvn70es.js} +1 -1
- package/dist/{embedding-space-ejefyep1.js → embedding-space-rgf4aypt.js} +6 -6
- package/dist/{embeddings-w297xaw0.js → embeddings-z9cmxhx1.js} +1 -1
- package/dist/{external-channel-mf9vp1fe.js → external-channel-g6vv85zv.js} +2 -2
- package/dist/{grok-adapter-mpzyyprz.js → grok-adapter-f6n1tpq3.js} +2 -2
- package/dist/handlers-ss5948rq.js +42 -0
- package/dist/{heartbeat-qnaycjzs.js → heartbeat-5xcdzz45.js} +21 -21
- package/dist/{hook-h6sqfzxr.js → hook-6423rme3.js} +2 -2
- package/dist/{hook-4zqdgea4.js → hook-8dk1csdd.js} +4 -4
- package/dist/{http-65ts210h.js → http-6mfh2ww9.js} +255 -60
- package/dist/{index-sqe7f6mj.js → index-0js6bgff.js} +1 -1
- package/dist/{index-farm1zsn.js → index-0ng1dd1t.js} +10937 -9527
- package/dist/{index-k3ewf1jg.js → index-5eyn1wc5.js} +18 -18
- package/dist/{index-vp4wa3qn.js → index-71gnebsn.js} +18 -18
- package/dist/{index-hdfad00b.js → index-q5gzpjdd.js} +12 -10
- package/dist/index-z3b1vfjx.js +44 -0
- package/dist/{keepalive-52k6skha.js → keepalive-cymckeg6.js} +3 -3
- package/dist/{lead-y9rj0gr1.js → lead-baknj2dh.js} +29 -29
- package/dist/{maintenance-f86wqfq6.js → maintenance-dfrnsx3n.js} +1 -1
- package/dist/{oauth-refresh-sweep-vddv9ky7.js → oauth-refresh-sweep-5dztk8x6.js} +2 -2
- package/dist/{onboard-8z2qk6gq.js → onboard-h36vja6y.js} +11 -6
- package/dist/{otel-impl-epet9j18.js → otel-impl-jerq8vz8.js} +1 -1
- package/dist/{pricing-refresh-6wm42a51.js → pricing-refresh-t3nx5krn.js} +3 -3
- package/dist/{rbac-roles-2kfcs1sc.js → rbac-roles-dw1awawd.js} +2 -2
- package/dist/{rbac-roles-13a0vj6d.js → rbac-roles-km0fc3e8.js} +1 -1
- package/dist/{registry-ajhexe44.js → registry-hzfh268v.js} +1 -1
- package/dist/{render-v2-cy8zsfsf.js → render-v2-65x4ayj8.js} +3 -3
- package/dist/{resume-c783qe6b.js → resume-61znk3hj.js} +6 -6
- package/dist/{session-access-s4tv0az8.js → session-access-4yc9htrg.js} +4 -4
- package/dist/{session-source-backfill-qzapz0ne.js → session-source-backfill-kr5bdjtp.js} +2 -2
- package/dist/{setup-st7htx1k.js → setup-9h61yr2p.js} +1 -1
- package/dist/{work-objects-ftj4zw70.js → work-objects-x7rb53qn.js} +27 -22
- package/dist/{worker-859fk25k.js → worker-7f3khgn0.js} +29 -29
- package/openapi.json +134 -3
- package/package.json +5 -5
- package/src/be/db/agents.ts +16 -1
- package/src/be/db/runtime.ts +25 -15
- package/src/be/db/session-summaries.ts +120 -0
- package/src/be/db/tasks/read.ts +7 -4
- package/src/be/db/tasks/search-index.ts +159 -0
- package/src/be/db/tasks/write.ts +3 -0
- package/src/be/db-queries/slack-inbound.ts +77 -0
- package/src/be/db.ts +27 -8
- package/src/be/mcp-overflow-sweep.ts +39 -0
- package/src/be/migrations/253_session_summaries.sql +300 -0
- package/src/be/migrations/254_query_audit_indexes.sql +25 -0
- package/src/be/migrations/256_agent_slack_icon.sql +2 -0
- package/src/be/migrations/257_agent_tasks_fts.sql +55 -0
- package/src/comb/config.ts +6 -2
- package/src/comb/requester.ts +69 -0
- package/src/comb/review-batch.ts +24 -2
- package/src/commands/onboard/agent-fs-version.ts +1 -1
- package/src/commands/onboard/compose-generator.ts +7 -2
- package/src/commands/onboard/env-generator.ts +8 -3
- package/src/commands/runner.ts +41 -24
- package/src/fs/agent-fs-provider.ts +9 -0
- package/src/heartbeat/heartbeat.ts +13 -6
- package/src/http/agents.ts +10 -2
- package/src/http/index.ts +15 -0
- package/src/http/integrations.ts +20 -0
- package/src/http/list-total-cache.ts +62 -0
- package/src/http/sessions.ts +9 -2
- package/src/http/slack-inbound.ts +1 -0
- package/src/http/status.ts +4 -1
- package/src/http/tasks.ts +12 -2
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/cursor-adapter.ts +1 -1
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/queue-stall-alarm.ts +4 -1
- package/src/slack/actions.ts +2 -2
- package/src/slack/app-icon.ts +50 -0
- package/src/slack/app.ts +13 -1
- package/src/slack/assistant.ts +22 -1
- package/src/slack/event-dedup.test.ts +11 -0
- package/src/slack/event-dedup.ts +8 -4
- package/src/slack/inbound-dispatch.ts +58 -0
- package/src/slack/render-v2.ts +7 -8
- package/src/slack/responses.ts +21 -8
- package/src/slack/socket-ack.ts +237 -0
- package/src/slack/thread-buffer.ts +3 -5
- package/src/slack/watcher.ts +2 -2
- package/src/slack/work-objects.ts +5 -1
- package/src/tests/agent-fs-release-notes.test.ts +40 -0
- package/src/tests/agent-slack-icon.test.ts +85 -0
- package/src/tests/approval-cancellation-migration.test.ts +2 -0
- package/src/tests/asset-key-migration.test.ts +26 -0
- package/src/tests/comb-default.test.ts +159 -0
- package/src/tests/comb-review-batch.test.ts +192 -4
- package/src/tests/comb-status.test.ts +65 -2
- package/src/tests/db-agents.test.ts +13 -0
- package/src/tests/db-tasks-read.test.ts +10 -15
- package/src/tests/deploy-one-box.test.ts +161 -0
- package/src/tests/deploy-stubs.ts +68 -0
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/e2e-codex-auth-chain.test.ts +18 -1
- package/src/tests/fixtures/deploy-stubs/bun +3 -0
- package/src/tests/fixtures/deploy-stubs/bunx +27 -0
- package/src/tests/fixtures/deploy-stubs/curl +26 -0
- package/src/tests/fixtures/deploy-stubs/docker +122 -0
- package/src/tests/fixtures/onboard/content.compose.yml.txt +5 -5
- package/src/tests/fixtures/onboard/dev.compose.yml.txt +4 -4
- package/src/tests/fixtures/onboard/full-all.compose.yml.txt +12 -12
- package/src/tests/fixtures/onboard/full.compose.yml.txt +12 -12
- package/src/tests/fixtures/onboard/research.compose.yml.txt +4 -4
- package/src/tests/fixtures/onboard/solo.compose.yml.txt +2 -2
- package/src/tests/heartbeat-expiry.test.ts +151 -25
- package/src/tests/http-api-integration.test.ts +31 -0
- package/src/tests/human-free-reclassify.test.ts +6 -0
- package/src/tests/install-sh-bind.test.ts +242 -0
- package/src/tests/install-sh-tunnel.test.ts +89 -0
- package/src/tests/kv-storage.test.ts +28 -0
- package/src/tests/list-endpoint-slimming.test.ts +3 -0
- package/src/tests/list-total-cache.test.ts +63 -0
- package/src/tests/mcp-overflow-sweep.test.ts +84 -0
- package/src/tests/onboard-compose.test.ts +17 -3
- package/src/tests/onboard-env.test.ts +13 -0
- package/src/tests/onboarding.test.ts +1 -1
- package/src/tests/preload.ts +1 -0
- package/src/tests/query-audit-plans.test.ts +314 -0
- package/src/tests/script-connections.test.ts +6 -0
- package/src/tests/session-summaries.test.ts +384 -0
- package/src/tests/sessions-tree.test.ts +5 -1
- package/src/tests/slack-app-icon.test.ts +90 -0
- package/src/tests/slack-external-channel-egress.test.ts +1 -1
- package/src/tests/slack-inbound-receipts.test.ts +34 -0
- package/src/tests/slack-inline-output.test.ts +29 -2
- package/src/tests/slack-render-v2-query-plans.test.ts +3 -2
- package/src/tests/slack-render-v2.test.ts +35 -0
- package/src/tests/slack-socket-ack.test.ts +553 -0
- package/src/tests/task-lineage.test.ts +3 -0
- package/src/tests/task-search-filter.test.ts +4 -4
- package/src/tests/task-search-fts.test.ts +320 -0
- package/src/tests/update-profile-auth.test.ts +28 -0
- package/src/tools/get-swarm.ts +1 -0
- package/src/tools/get-tasks.ts +6 -1
- package/src/tools/join-swarm.ts +1 -0
- package/src/tools/my-agent-info.ts +1 -0
- package/src/tools/slack-post.ts +2 -2
- package/src/tools/slack-reply.ts +2 -2
- package/src/tools/slack-start-thread.ts +2 -2
- package/src/tools/slack-update.ts +1 -1
- package/src/tools/update-profile.ts +20 -4
- package/src/tools/utils.ts +3 -4
- package/src/types.ts +47 -0
- package/src/utils/constants.ts +127 -5
- package/templates/official/lead/HEARTBEAT.md +4 -2
- package/templates/official/lead/config.json +2 -2
- package/templates/skills/swarm-docs/content.md +2 -0
- package/dist/handlers-7x8sywgr.js +0 -42
- package/dist/index-mc30r1hs.js +0 -44
|
@@ -36,7 +36,7 @@ services:
|
|
|
36
36
|
- GITHUB_DISABLE=false
|
|
37
37
|
|
|
38
38
|
ports:
|
|
39
|
-
- "3999:3013"
|
|
39
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3999:3013"
|
|
40
40
|
|
|
41
41
|
volumes:
|
|
42
42
|
- swarm_data:/app/data
|
|
@@ -89,7 +89,7 @@ services:
|
|
|
89
89
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
90
90
|
|
|
91
91
|
ports:
|
|
92
|
-
- "3201:3000"
|
|
92
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3201:3000"
|
|
93
93
|
|
|
94
94
|
volumes:
|
|
95
95
|
- swarm_logs:/logs
|
|
@@ -138,7 +138,7 @@ services:
|
|
|
138
138
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
139
139
|
|
|
140
140
|
ports:
|
|
141
|
-
- "3202:3000"
|
|
141
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3202:3000"
|
|
142
142
|
|
|
143
143
|
volumes:
|
|
144
144
|
- swarm_logs:/logs
|
|
@@ -187,7 +187,7 @@ services:
|
|
|
187
187
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
188
188
|
|
|
189
189
|
ports:
|
|
190
|
-
- "3203:3000"
|
|
190
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3203:3000"
|
|
191
191
|
|
|
192
192
|
volumes:
|
|
193
193
|
- swarm_logs:/logs
|
|
@@ -236,7 +236,7 @@ services:
|
|
|
236
236
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
237
237
|
|
|
238
238
|
ports:
|
|
239
|
-
- "3204:3000"
|
|
239
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3204:3000"
|
|
240
240
|
|
|
241
241
|
volumes:
|
|
242
242
|
- swarm_logs:/logs
|
|
@@ -285,7 +285,7 @@ services:
|
|
|
285
285
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
286
286
|
|
|
287
287
|
ports:
|
|
288
|
-
- "3205:3000"
|
|
288
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3205:3000"
|
|
289
289
|
|
|
290
290
|
volumes:
|
|
291
291
|
- swarm_logs:/logs
|
|
@@ -334,7 +334,7 @@ services:
|
|
|
334
334
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
335
335
|
|
|
336
336
|
ports:
|
|
337
|
-
- "3206:3000"
|
|
337
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3206:3000"
|
|
338
338
|
|
|
339
339
|
volumes:
|
|
340
340
|
- swarm_logs:/logs
|
|
@@ -383,7 +383,7 @@ services:
|
|
|
383
383
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
384
384
|
|
|
385
385
|
ports:
|
|
386
|
-
- "3207:3000"
|
|
386
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3207:3000"
|
|
387
387
|
|
|
388
388
|
volumes:
|
|
389
389
|
- swarm_logs:/logs
|
|
@@ -432,7 +432,7 @@ services:
|
|
|
432
432
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
433
433
|
|
|
434
434
|
ports:
|
|
435
|
-
- "3208:3000"
|
|
435
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3208:3000"
|
|
436
436
|
|
|
437
437
|
volumes:
|
|
438
438
|
- swarm_logs:/logs
|
|
@@ -481,7 +481,7 @@ services:
|
|
|
481
481
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
482
482
|
|
|
483
483
|
ports:
|
|
484
|
-
- "3209:3000"
|
|
484
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3209:3000"
|
|
485
485
|
|
|
486
486
|
volumes:
|
|
487
487
|
- swarm_logs:/logs
|
|
@@ -530,7 +530,7 @@ services:
|
|
|
530
530
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
531
531
|
|
|
532
532
|
ports:
|
|
533
|
-
- "3210:3000"
|
|
533
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3210:3000"
|
|
534
534
|
|
|
535
535
|
volumes:
|
|
536
536
|
- swarm_logs:/logs
|
|
@@ -579,7 +579,7 @@ services:
|
|
|
579
579
|
- SENTRY_ORG=${SENTRY_ORG}
|
|
580
580
|
|
|
581
581
|
ports:
|
|
582
|
-
- "3211:3000"
|
|
582
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3211:3000"
|
|
583
583
|
|
|
584
584
|
volumes:
|
|
585
585
|
- swarm_logs:/logs
|
|
@@ -32,7 +32,7 @@ services:
|
|
|
32
32
|
- APP_URL=https://app.agent-swarm.dev
|
|
33
33
|
|
|
34
34
|
ports:
|
|
35
|
-
- "3013:3013"
|
|
35
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3013:3013"
|
|
36
36
|
|
|
37
37
|
volumes:
|
|
38
38
|
- swarm_data:/app/data
|
|
@@ -73,7 +73,7 @@ services:
|
|
|
73
73
|
- MAX_CONCURRENT_TASKS=2
|
|
74
74
|
|
|
75
75
|
ports:
|
|
76
|
-
- "3201:3000"
|
|
76
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3201:3000"
|
|
77
77
|
|
|
78
78
|
volumes:
|
|
79
79
|
- swarm_logs:/logs
|
|
@@ -109,7 +109,7 @@ services:
|
|
|
109
109
|
- MAX_CONCURRENT_TASKS=1
|
|
110
110
|
|
|
111
111
|
ports:
|
|
112
|
-
- "3202:3000"
|
|
112
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3202:3000"
|
|
113
113
|
|
|
114
114
|
volumes:
|
|
115
115
|
- swarm_logs:/logs
|
|
@@ -145,7 +145,7 @@ services:
|
|
|
145
145
|
- MAX_CONCURRENT_TASKS=1
|
|
146
146
|
|
|
147
147
|
ports:
|
|
148
|
-
- "3203:3000"
|
|
148
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3203:3000"
|
|
149
149
|
|
|
150
150
|
volumes:
|
|
151
151
|
- swarm_logs:/logs
|
|
@@ -181,7 +181,7 @@ services:
|
|
|
181
181
|
- MAX_CONCURRENT_TASKS=1
|
|
182
182
|
|
|
183
183
|
ports:
|
|
184
|
-
- "3204:3000"
|
|
184
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3204:3000"
|
|
185
185
|
|
|
186
186
|
volumes:
|
|
187
187
|
- swarm_logs:/logs
|
|
@@ -217,7 +217,7 @@ services:
|
|
|
217
217
|
- MAX_CONCURRENT_TASKS=1
|
|
218
218
|
|
|
219
219
|
ports:
|
|
220
|
-
- "3205:3000"
|
|
220
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3205:3000"
|
|
221
221
|
|
|
222
222
|
volumes:
|
|
223
223
|
- swarm_logs:/logs
|
|
@@ -253,7 +253,7 @@ services:
|
|
|
253
253
|
- MAX_CONCURRENT_TASKS=1
|
|
254
254
|
|
|
255
255
|
ports:
|
|
256
|
-
- "3206:3000"
|
|
256
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3206:3000"
|
|
257
257
|
|
|
258
258
|
volumes:
|
|
259
259
|
- swarm_logs:/logs
|
|
@@ -289,7 +289,7 @@ services:
|
|
|
289
289
|
- MAX_CONCURRENT_TASKS=1
|
|
290
290
|
|
|
291
291
|
ports:
|
|
292
|
-
- "3207:3000"
|
|
292
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3207:3000"
|
|
293
293
|
|
|
294
294
|
volumes:
|
|
295
295
|
- swarm_logs:/logs
|
|
@@ -325,7 +325,7 @@ services:
|
|
|
325
325
|
- MAX_CONCURRENT_TASKS=1
|
|
326
326
|
|
|
327
327
|
ports:
|
|
328
|
-
- "3208:3000"
|
|
328
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3208:3000"
|
|
329
329
|
|
|
330
330
|
volumes:
|
|
331
331
|
- swarm_logs:/logs
|
|
@@ -361,7 +361,7 @@ services:
|
|
|
361
361
|
- MAX_CONCURRENT_TASKS=1
|
|
362
362
|
|
|
363
363
|
ports:
|
|
364
|
-
- "3209:3000"
|
|
364
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3209:3000"
|
|
365
365
|
|
|
366
366
|
volumes:
|
|
367
367
|
- swarm_logs:/logs
|
|
@@ -397,7 +397,7 @@ services:
|
|
|
397
397
|
- MAX_CONCURRENT_TASKS=1
|
|
398
398
|
|
|
399
399
|
ports:
|
|
400
|
-
- "3210:3000"
|
|
400
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3210:3000"
|
|
401
401
|
|
|
402
402
|
volumes:
|
|
403
403
|
- swarm_logs:/logs
|
|
@@ -433,7 +433,7 @@ services:
|
|
|
433
433
|
- MAX_CONCURRENT_TASKS=1
|
|
434
434
|
|
|
435
435
|
ports:
|
|
436
|
-
- "3211:3000"
|
|
436
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3211:3000"
|
|
437
437
|
|
|
438
438
|
volumes:
|
|
439
439
|
- swarm_logs:/logs
|
|
@@ -32,7 +32,7 @@ services:
|
|
|
32
32
|
- APP_URL=https://app.agent-swarm.dev
|
|
33
33
|
|
|
34
34
|
ports:
|
|
35
|
-
- "3013:3013"
|
|
35
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3013:3013"
|
|
36
36
|
|
|
37
37
|
volumes:
|
|
38
38
|
- swarm_data:/app/data
|
|
@@ -73,7 +73,7 @@ services:
|
|
|
73
73
|
- MAX_CONCURRENT_TASKS=2
|
|
74
74
|
|
|
75
75
|
ports:
|
|
76
|
-
- "3201:3000"
|
|
76
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3201:3000"
|
|
77
77
|
|
|
78
78
|
volumes:
|
|
79
79
|
- swarm_logs:/logs
|
|
@@ -109,7 +109,7 @@ services:
|
|
|
109
109
|
- MAX_CONCURRENT_TASKS=1
|
|
110
110
|
|
|
111
111
|
ports:
|
|
112
|
-
- "3202:3000"
|
|
112
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3202:3000"
|
|
113
113
|
|
|
114
114
|
volumes:
|
|
115
115
|
- swarm_logs:/logs
|
|
@@ -145,7 +145,7 @@ services:
|
|
|
145
145
|
- MAX_CONCURRENT_TASKS=1
|
|
146
146
|
|
|
147
147
|
ports:
|
|
148
|
-
- "3203:3000"
|
|
148
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3203:3000"
|
|
149
149
|
|
|
150
150
|
volumes:
|
|
151
151
|
- swarm_logs:/logs
|
|
@@ -32,7 +32,7 @@ services:
|
|
|
32
32
|
- APP_URL=https://app.agent-swarm.dev
|
|
33
33
|
|
|
34
34
|
ports:
|
|
35
|
-
- "3013:3013"
|
|
35
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3013:3013"
|
|
36
36
|
|
|
37
37
|
volumes:
|
|
38
38
|
- swarm_data:/app/data
|
|
@@ -73,7 +73,7 @@ services:
|
|
|
73
73
|
- MAX_CONCURRENT_TASKS=1
|
|
74
74
|
|
|
75
75
|
ports:
|
|
76
|
-
- "3201:3000"
|
|
76
|
+
- "${AGENT_SWARM_BIND_ADDRESS:+${AGENT_SWARM_BIND_ADDRESS:-}:}3201:3000"
|
|
77
77
|
|
|
78
78
|
volumes:
|
|
79
79
|
- swarm_logs:/logs
|
|
@@ -8,10 +8,11 @@ import {
|
|
|
8
8
|
initDb,
|
|
9
9
|
updateAgentProfile,
|
|
10
10
|
} from "../be/db";
|
|
11
|
-
import { handleAgentsRest } from "../http/agents";
|
|
11
|
+
import { handleAgentRegister, handleAgentsRest } from "../http/agents";
|
|
12
12
|
import { getPathSegments, parseQueryParams } from "../http/utils";
|
|
13
13
|
import { HeartbeatExpiryError, validateHeartbeatExpiry } from "../utils/heartbeat-expiry";
|
|
14
14
|
import { listenOnFreePort } from "./test-net";
|
|
15
|
+
import { CHILD_PROCESS_TEST_BUDGET_MS, expectChildOk, runChild } from "./test-proc";
|
|
15
16
|
|
|
16
17
|
const section = (...lines: string[]) => `## Tracked Items\n${lines.join("\n")}\n`;
|
|
17
18
|
|
|
@@ -143,33 +144,158 @@ describe("profile persistence heartbeat gate", () => {
|
|
|
143
144
|
await getDbClient().query("SELECT * FROM context_versions WHERE agentId = ?", [agentId]),
|
|
144
145
|
).toEqual(versionsBefore);
|
|
145
146
|
});
|
|
146
|
-
test("HTTP
|
|
147
|
-
|
|
147
|
+
test.each(["saved", "HTTP 400", "network failure"] as const)(
|
|
148
|
+
"first-boot runner handles profile %s and continues initializing",
|
|
149
|
+
async (outcome) => {
|
|
150
|
+
const leadId = crypto.randomUUID();
|
|
151
|
+
const secret = "profile-save-test-credential-value";
|
|
152
|
+
expect(await getAgentById(leadId)).toBeFalsy();
|
|
153
|
+
const templateFile = (name: string) =>
|
|
154
|
+
Bun.file(new URL(`../../templates/official/lead/${name}`, import.meta.url)).text();
|
|
155
|
+
const template = {
|
|
156
|
+
config: await Bun.file(
|
|
157
|
+
new URL("../../templates/official/lead/config.json", import.meta.url),
|
|
158
|
+
).json(),
|
|
159
|
+
files: {
|
|
160
|
+
soulMd: await templateFile("SOUL.md"),
|
|
161
|
+
identityMd: await templateFile("IDENTITY.md"),
|
|
162
|
+
claudeMd: await templateFile("CLAUDE.md"),
|
|
163
|
+
toolsMd: "",
|
|
164
|
+
setupScript: "",
|
|
165
|
+
heartbeatMd:
|
|
166
|
+
outcome === "HTTP 400"
|
|
167
|
+
? section("- New undated HTTP item")
|
|
168
|
+
: await templateFile("HEARTBEAT.md"),
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
let profileBefore: Awaited<ReturnType<typeof getAgentById>>;
|
|
172
|
+
const profileStatuses: number[] = [];
|
|
173
|
+
const server = createServer(async (req, res) => {
|
|
174
|
+
try {
|
|
175
|
+
const path = new URL(req.url ?? "/", "http://localhost").pathname;
|
|
176
|
+
const json = (data: unknown) => {
|
|
177
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
178
|
+
res.end(JSON.stringify(data));
|
|
179
|
+
};
|
|
180
|
+
if (path === "/api/templates/official/lead") return json(template);
|
|
181
|
+
if (path === "/api/config/resolved") return json({ configs: [] });
|
|
182
|
+
if (path === "/api/fs/agent-credentials") return json({ enabled: false });
|
|
183
|
+
if (path.startsWith("/api/active-sessions/")) return json({ recovered: 0 });
|
|
184
|
+
if (path === "/me") {
|
|
185
|
+
profileBefore = await getAgentById(leadId);
|
|
186
|
+
return json(profileBefore);
|
|
187
|
+
}
|
|
188
|
+
if (path === `/api/agents/${leadId}/profile` && req.method === "PUT") {
|
|
189
|
+
res.once("finish", () => profileStatuses.push(res.statusCode));
|
|
190
|
+
}
|
|
191
|
+
if (path === `/api/agents/${leadId}/mcp-servers`) return json({ servers: [] });
|
|
192
|
+
if (await handleAgentRegister(req, res, getPathSegments(req.url ?? "/"), leadId)) return;
|
|
193
|
+
if (
|
|
194
|
+
await handleAgentsRest(
|
|
195
|
+
req,
|
|
196
|
+
res,
|
|
197
|
+
getPathSegments(req.url ?? "/"),
|
|
198
|
+
parseQueryParams(req.url ?? "/"),
|
|
199
|
+
leadId,
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
return;
|
|
203
|
+
res.writeHead(404).end();
|
|
204
|
+
} catch {
|
|
205
|
+
res.writeHead(500).end();
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
const port = await listenOnFreePort(server);
|
|
209
|
+
const dir = `${process.env.TMPDIR ?? "/tmp"}/runner-profile-boot-${leadId}`;
|
|
210
|
+
await Bun.$`mkdir -p ${dir}`.quiet();
|
|
148
211
|
try {
|
|
149
|
-
await
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
212
|
+
await Bun.write(
|
|
213
|
+
`${dir}/boot.ts`,
|
|
214
|
+
`
|
|
215
|
+
import { mock } from "bun:test";
|
|
216
|
+
const fs = { ...await import("node:fs/promises") };
|
|
217
|
+
// A fresh template cache, without touching the host's /workspace.
|
|
218
|
+
const isolated = (fn) => (...args) => {
|
|
219
|
+
if (String(args[0]).startsWith("/workspace")) throw new Error("No fixture workspace");
|
|
220
|
+
return fn(...args);
|
|
221
|
+
};
|
|
222
|
+
mock.module("node:fs/promises", () => ({
|
|
223
|
+
...fs, stat: isolated(fs.stat), mkdir: isolated(fs.mkdir),
|
|
224
|
+
}));
|
|
225
|
+
const request = globalThis.fetch;
|
|
226
|
+
globalThis.fetch = Object.assign(async (...args) => {
|
|
227
|
+
const path = new URL(args[0] instanceof Request ? args[0].url : args[0]).pathname;
|
|
228
|
+
if (${JSON.stringify(outcome)} === "network failure" && path === "/api/agents/${leadId}/profile") {
|
|
229
|
+
throw new TypeError("fetch failed: " + process.env.AGENT_SWARM_API_KEY);
|
|
230
|
+
}
|
|
231
|
+
const response = await request(...args);
|
|
232
|
+
// This request follows profile initialization and precedes workspace writes.
|
|
233
|
+
if (new URL(response.url).pathname === "/api/agents/${leadId}/mcp-servers") {
|
|
234
|
+
console.log("Boot identity phase completed");
|
|
235
|
+
process.exit(0);
|
|
236
|
+
}
|
|
237
|
+
return response;
|
|
238
|
+
}, { preconnect: request.preconnect });
|
|
239
|
+
const { runAgent } = await import(${JSON.stringify(new URL("../commands/runner.ts", import.meta.url).pathname)});
|
|
240
|
+
await runAgent({ role: "lead", defaultPrompt: "/start-leader", metadataType: "lead_metadata" },
|
|
241
|
+
{ logsDir: ${JSON.stringify(`${dir}/logs`)} });
|
|
242
|
+
`,
|
|
243
|
+
);
|
|
244
|
+
const child = expectChildOk(
|
|
245
|
+
await runChild([process.execPath, `${dir}/boot.ts`], {
|
|
246
|
+
cwd: dir,
|
|
247
|
+
env: {
|
|
248
|
+
...process.env,
|
|
249
|
+
AGENT_ID: leadId,
|
|
250
|
+
AGENT_NAME: "Fresh lead",
|
|
251
|
+
AGENT_SWARM_API_KEY: secret,
|
|
252
|
+
MCP_BASE_URL: `http://localhost:${port}`,
|
|
253
|
+
TEMPLATE_ID: "official/lead",
|
|
254
|
+
TEMPLATE_REGISTRY_URL: `http://localhost:${port}`,
|
|
255
|
+
HARNESS_PROVIDER: "claude",
|
|
256
|
+
CRED_CHECK_DISABLE: "1",
|
|
257
|
+
ANONYMIZED_TELEMETRY: "false",
|
|
258
|
+
BUSINESS_USE_API_KEY: "",
|
|
259
|
+
OTEL_SDK_DISABLED: "true",
|
|
260
|
+
DESPLEGA_TELEMETRY_ENV: "test",
|
|
261
|
+
HOME: dir,
|
|
262
|
+
PATH: dir,
|
|
263
|
+
},
|
|
264
|
+
}),
|
|
265
|
+
"first-boot lead runner",
|
|
155
266
|
);
|
|
156
|
-
|
|
157
|
-
|
|
267
|
+
expect(child.stdout).toContain("Boot identity phase completed");
|
|
268
|
+
const saved = await getAgentById(leadId);
|
|
269
|
+
expect(saved).toBeTruthy();
|
|
270
|
+
expect(child.stdout + child.stderr).not.toContain(secret);
|
|
271
|
+
if (outcome === "saved") {
|
|
272
|
+
expect(profileStatuses).toEqual([200]);
|
|
273
|
+
expect(saved?.soulMd).toContain("# SOUL.md — Fresh lead");
|
|
274
|
+
expect(saved?.identityMd).toContain("# IDENTITY.md — Fresh lead");
|
|
275
|
+
expect(saved?.claudeMd).toBeTruthy();
|
|
276
|
+
expect(saved?.toolsMd).toBeTruthy();
|
|
277
|
+
expect(saved?.heartbeatMd).toBe(template.files.heartbeatMd);
|
|
278
|
+
expect(child.stdout).toContain("[lead] Generated and saved default identity templates");
|
|
279
|
+
} else {
|
|
280
|
+
expect(saved).toEqual(profileBefore);
|
|
281
|
+
expect(child.stdout).not.toContain("Generated and saved default identity templates");
|
|
282
|
+
expect(child.stderr).toContain("Could not save generated templates to server");
|
|
283
|
+
if (outcome === "HTTP 400") {
|
|
284
|
+
expect(profileStatuses).toEqual([400]);
|
|
285
|
+
expect(child.stderr).toContain("HTTP 400");
|
|
286
|
+
expect(child.stderr).toContain("New undated HTTP item");
|
|
287
|
+
} else {
|
|
288
|
+
expect(profileStatuses).toEqual([]);
|
|
289
|
+
expect(child.stderr).toContain("fetch failed");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
} finally {
|
|
293
|
+
await new Promise<void>((resolve) => server.close(() => resolve()));
|
|
294
|
+
await Bun.$`rm -rf ${dir}`.quiet();
|
|
158
295
|
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const response = await fetch(`http://localhost:${port}/api/agents/${agentId}/profile`, {
|
|
163
|
-
method: "PUT",
|
|
164
|
-
headers: { "Content-Type": "application/json" },
|
|
165
|
-
body: JSON.stringify({ heartbeatMd: section("- New undated HTTP item") }),
|
|
166
|
-
});
|
|
167
|
-
expect(response.status).toBe(400);
|
|
168
|
-
expect((await response.json()).error).toContain("New undated HTTP item");
|
|
169
|
-
} finally {
|
|
170
|
-
await new Promise<void>((resolve) => server.close(() => resolve()));
|
|
171
|
-
}
|
|
172
|
-
});
|
|
296
|
+
},
|
|
297
|
+
CHILD_PROCESS_TEST_BUDGET_MS,
|
|
298
|
+
);
|
|
173
299
|
test("persists edits, dated additions, pin durables, and deletions", async () => {
|
|
174
300
|
const next = section("- **Legacy:** Revised", "- Dated DELETE on 09-30", "📌 Durable");
|
|
175
301
|
expect((await updateAgentProfile(agentId, { heartbeatMd: next }))?.heartbeatMd).toBe(next);
|
|
@@ -308,6 +308,37 @@ describe("Agents", () => {
|
|
|
308
308
|
expect(rejected.status).toBe(400);
|
|
309
309
|
});
|
|
310
310
|
|
|
311
|
+
test("PUT /api/agents/:id/profile — sets, validates and resets slackIcon", async () => {
|
|
312
|
+
const path = `/api/agents/${ids.workerAgent}/profile`;
|
|
313
|
+
const owl = { type: "url", url: "https://example.com/owl.png" };
|
|
314
|
+
const set = await put(path, { body: { slackIcon: owl } });
|
|
315
|
+
expect(set.status).toBe(200);
|
|
316
|
+
expect(set.body.slackIcon).toEqual(owl);
|
|
317
|
+
|
|
318
|
+
for (const slackIcon of [
|
|
319
|
+
{ type: "emoji", emoji: "owl" },
|
|
320
|
+
{ type: "url", url: "http://example.com/owl.png" },
|
|
321
|
+
{ type: "url", url: "https://user:pass@example.com/owl.png" },
|
|
322
|
+
{ type: "url", url: "https://" },
|
|
323
|
+
]) {
|
|
324
|
+
expect((await put(path, { body: { slackIcon } })).status).toBe(400);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const app = await put(path, { body: { slackIcon: { type: "app" } } });
|
|
328
|
+
expect(app.status).toBe(200);
|
|
329
|
+
expect(app.body.slackIcon).toEqual({ type: "app" });
|
|
330
|
+
|
|
331
|
+
const reset = await put(path, { body: { slackIcon: null } });
|
|
332
|
+
expect(reset.status).toBe(200);
|
|
333
|
+
expect(reset.body.slackIcon).toBeNull();
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
test("GET /api/integrations/slack/app-icon — null with Slack off", async () => {
|
|
337
|
+
const { status, body } = await get("/api/integrations/slack/app-icon");
|
|
338
|
+
expect(status).toBe(200);
|
|
339
|
+
expect(body).toEqual({ imageUrl: null });
|
|
340
|
+
});
|
|
341
|
+
|
|
311
342
|
test("PUT /api/agents/:id/profile — persists structured filesystem sync rejections", async () => {
|
|
312
343
|
const current = "s".repeat(SOUL_MD_MAX_CHARS);
|
|
313
344
|
const accepted = await put(`/api/agents/${ids.workerAgent}/profile`, {
|
|
@@ -625,6 +625,9 @@ describe("human-free flag stays correct when a classifying input changes", () =>
|
|
|
625
625
|
const third = await task("cycle third", { parentTaskId: second });
|
|
626
626
|
// Nothing in the product writes a cycle, but the rule (a UNION over ids)
|
|
627
627
|
// is defined on one, so the reclassification must stay total on it.
|
|
628
|
+
// Product code never rewrites parentTaskId, and migration 253 guards it;
|
|
629
|
+
// this cycle fixture needs the guard off.
|
|
630
|
+
await getDbClient().run("DROP TRIGGER IF EXISTS session_task_parent_immutable");
|
|
628
631
|
await getDbClient().run("UPDATE agent_tasks SET parentTaskId = ? WHERE id = ?", [third, first]);
|
|
629
632
|
await getDbClient().run("UPDATE agent_tasks SET tags = ? WHERE id = ?", [
|
|
630
633
|
JSON.stringify(["heartbeat"]),
|
|
@@ -642,6 +645,9 @@ describe("human-free flag stays correct when a classifying input changes", () =>
|
|
|
642
645
|
test("a parent cycle longer than one batch stops re-queuing itself", async () => {
|
|
643
646
|
const ring: string[] = [await task("ring 0")];
|
|
644
647
|
for (let i = 1; i < 6; i++) ring.push(await task(`ring ${i}`, { parentTaskId: ring[i - 1] }));
|
|
648
|
+
// Product code never rewrites parentTaskId, and migration 253 guards it;
|
|
649
|
+
// this cycle fixture needs the guard off.
|
|
650
|
+
await getDbClient().run("DROP TRIGGER IF EXISTS session_task_parent_immutable");
|
|
645
651
|
await getDbClient().run("UPDATE agent_tasks SET parentTaskId = ? WHERE id = ?", [
|
|
646
652
|
ring[5],
|
|
647
653
|
ring[0],
|