@desplega.ai/agent-swarm 1.49.0 → 1.51.2
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 +1 -1
- package/openapi.json +582 -3
- package/package.json +10 -1
- package/src/agentmail/handlers.ts +65 -10
- package/src/agentmail/templates.ts +111 -0
- package/src/be/db.ts +591 -7
- package/src/be/migrations/014_prompt_templates.sql +33 -0
- package/src/be/migrations/015_workflow_workspace.sql +3 -0
- package/src/be/migrations/016_active_session_runner_session.sql +4 -0
- package/src/be/migrations/017_channel_activity_cursors.sql +6 -0
- package/src/be/migrations/018_fix_seed_double_version.sql +30 -0
- package/src/be/seed.ts +62 -0
- package/src/commands/runner.ts +186 -93
- package/src/commands/templates.ts +172 -0
- package/src/github/handlers.ts +292 -77
- package/src/github/mentions-aliases.test.ts +73 -0
- package/src/github/mentions.test.ts +3 -3
- package/src/github/mentions.ts +32 -6
- package/src/github/templates.ts +398 -0
- package/src/gitlab/handlers.ts +63 -22
- package/src/gitlab/templates.ts +140 -0
- package/src/heartbeat/heartbeat.ts +19 -10
- package/src/heartbeat/templates.ts +30 -0
- package/src/http/active-sessions.ts +27 -0
- package/src/http/index.ts +5 -2
- package/src/http/poll.ts +135 -14
- package/src/http/prompt-templates.ts +412 -0
- package/src/http/schedules.ts +35 -0
- package/src/http/workflows.ts +8 -0
- package/src/linear/sync.ts +28 -4
- package/src/linear/templates.ts +47 -0
- package/src/prompts/base-prompt.ts +33 -490
- package/src/prompts/registry.ts +57 -0
- package/src/prompts/resolver.ts +296 -0
- package/src/prompts/session-templates.ts +604 -0
- package/src/providers/claude-adapter.ts +15 -2
- package/src/providers/pi-mono-extension.ts +5 -1
- package/src/scheduler/scheduler.ts +125 -91
- package/src/server.ts +15 -0
- package/src/slack/assistant.ts +7 -4
- package/src/slack/channel-activity.ts +177 -0
- package/src/slack/handlers.ts +21 -6
- package/src/slack/templates.ts +55 -0
- package/src/tests/artifact-sdk.test.ts +12 -12
- package/src/tests/base-prompt.test.ts +49 -49
- package/src/tests/channel-activity.test.ts +363 -0
- package/src/tests/heartbeat.test.ts +1 -0
- package/src/tests/linear-webhook.test.ts +7 -3
- package/src/tests/pool-session-logs.test.ts +199 -0
- package/src/tests/prompt-template-github.test.ts +682 -0
- package/src/tests/prompt-template-remaining.test.ts +504 -0
- package/src/tests/prompt-template-resolver.test.ts +621 -0
- package/src/tests/prompt-template-session.test.ts +363 -0
- package/src/tests/prompt-templates-db.test.ts +616 -0
- package/src/tests/self-improvement.test.ts +8 -7
- package/src/tests/slack-metadata-inheritance.test.ts +1 -1
- package/src/tests/slack-thread-followups.test.ts +1 -1
- package/src/tests/structured-output.test.ts +0 -4
- package/src/tests/tool-annotations.test.ts +1 -1
- package/src/tests/update-profile-agentid.test.ts +248 -0
- package/src/tests/update-profile-auth.test.ts +195 -0
- package/src/tests/workflow-async-v2.test.ts +126 -4
- package/src/tests/workflow-definition-validation.test.ts +76 -0
- package/src/tests/workflow-retry-v2.test.ts +1 -1
- package/src/tests/workflow-schedule-trigger.test.ts +104 -0
- package/src/tests/workflow-workspace.test.ts +272 -0
- package/src/tools/prompt-templates/delete.ts +86 -0
- package/src/tools/prompt-templates/get.ts +89 -0
- package/src/tools/prompt-templates/index.ts +5 -0
- package/src/tools/prompt-templates/list.ts +95 -0
- package/src/tools/prompt-templates/preview.ts +84 -0
- package/src/tools/prompt-templates/set.ts +117 -0
- package/src/tools/store-progress.ts +22 -4
- package/src/tools/task-action.ts +20 -0
- package/src/tools/templates.ts +53 -0
- package/src/tools/tool-config.ts +7 -0
- package/src/tools/update-profile.ts +106 -34
- package/src/tools/workflows/create-workflow.ts +19 -1
- package/src/tools/workflows/update-workflow.ts +16 -1
- package/src/types.ts +55 -2
- package/src/workflows/definition.ts +30 -12
- package/src/workflows/engine.ts +40 -14
- package/src/workflows/executors/agent-task.ts +14 -3
- package/src/workflows/index.ts +1 -1
- package/src/workflows/resume.ts +98 -12
- package/src/workflows/triggers.ts +31 -2
- package/src/workflows/version.ts +2 -0
- package/.claude/settings.json +0 -84
- package/.claude/settings.local.json +0 -117
- package/.dockerignore +0 -61
- package/.editorconfig +0 -15
- package/.entire/settings.json +0 -4
- package/.env.docker.example +0 -56
- package/.env.example +0 -78
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -78
- package/.github/ISSUE_TEMPLATE/community-template.yml +0 -77
- package/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -60
- package/.github/PULL_REQUEST_TEMPLATE/community-template.md +0 -29
- package/.github/workflows/ci.yml +0 -52
- package/.github/workflows/docker-and-deploy.yml +0 -132
- package/.github/workflows/merge-gate.yml +0 -233
- package/.opencode/plugins/entire.ts +0 -133
- package/.superset/config.json +0 -6
- package/.wts-config.json +0 -4
- package/.wts-setup.ts +0 -171
- package/CHANGELOG.md +0 -447
- package/CLAUDE.md +0 -521
- package/CONTRIBUTING.md +0 -315
- package/DEPLOYMENT.md +0 -622
- package/Dockerfile +0 -65
- package/Dockerfile.worker +0 -189
- package/MCP.md +0 -841
- package/UI.md +0 -40
- package/api-entrypoint.sh +0 -56
- package/assets/agent-swarm-logo-orange.png +0 -0
- package/assets/agent-swarm-logo.png +0 -0
- package/assets/agent-swarm.mp4 +0 -0
- package/assets/agent-swarm.png +0 -0
- package/biome.json +0 -39
- package/deploy/DEPLOY.md +0 -60
- package/deploy/agent-swarm.service +0 -17
- package/deploy/docker-push.ts +0 -30
- package/deploy/install.ts +0 -85
- package/deploy/prod-db.ts +0 -42
- package/deploy/uninstall.ts +0 -12
- package/deploy/update.ts +0 -21
- package/depot.json +0 -1
- package/docker-compose.example.yml +0 -350
- package/docker-compose.local.yml +0 -119
- package/docker-entrypoint.sh +0 -632
- package/docs-site/app/api/search/route.ts +0 -4
- package/docs-site/app/docs/[[...slug]]/page.tsx +0 -87
- package/docs-site/app/docs/layout.tsx +0 -12
- package/docs-site/app/globals.css +0 -24
- package/docs-site/app/layout.config.tsx +0 -34
- package/docs-site/app/layout.tsx +0 -119
- package/docs-site/app/llms-full.txt/route.ts +0 -11
- package/docs-site/app/llms.mdx/docs/[[...slug]]/route.ts +0 -24
- package/docs-site/app/llms.txt/route.ts +0 -8
- package/docs-site/app/page.tsx +0 -5
- package/docs-site/app/robots.ts +0 -13
- package/docs-site/app/sitemap.ts +0 -37
- package/docs-site/components/api-page.client.tsx +0 -4
- package/docs-site/components/api-page.tsx +0 -7
- package/docs-site/components/mdx/mermaid.tsx +0 -55
- package/docs-site/content/docs/(documentation)/architecture/agents.mdx +0 -117
- package/docs-site/content/docs/(documentation)/architecture/hooks.mdx +0 -77
- package/docs-site/content/docs/(documentation)/architecture/memory.mdx +0 -96
- package/docs-site/content/docs/(documentation)/architecture/meta.json +0 -4
- package/docs-site/content/docs/(documentation)/architecture/overview.mdx +0 -172
- package/docs-site/content/docs/(documentation)/concepts/epics.mdx +0 -98
- package/docs-site/content/docs/(documentation)/concepts/meta.json +0 -4
- package/docs-site/content/docs/(documentation)/concepts/scheduling.mdx +0 -136
- package/docs-site/content/docs/(documentation)/concepts/services.mdx +0 -104
- package/docs-site/content/docs/(documentation)/concepts/task-lifecycle.mdx +0 -148
- package/docs-site/content/docs/(documentation)/concepts/workflows.mdx +0 -209
- package/docs-site/content/docs/(documentation)/contributing.mdx +0 -158
- package/docs-site/content/docs/(documentation)/getting-started.mdx +0 -157
- package/docs-site/content/docs/(documentation)/guides/agentmail-integration.mdx +0 -79
- package/docs-site/content/docs/(documentation)/guides/deployment.mdx +0 -171
- package/docs-site/content/docs/(documentation)/guides/github-integration.mdx +0 -81
- package/docs-site/content/docs/(documentation)/guides/gitlab-integration.mdx +0 -93
- package/docs-site/content/docs/(documentation)/guides/linear-integration.mdx +0 -98
- package/docs-site/content/docs/(documentation)/guides/meta.json +0 -13
- package/docs-site/content/docs/(documentation)/guides/sentry-integration.mdx +0 -52
- package/docs-site/content/docs/(documentation)/guides/slack-integration.mdx +0 -179
- package/docs-site/content/docs/(documentation)/guides/x402-payments.mdx +0 -154
- package/docs-site/content/docs/(documentation)/index.mdx +0 -65
- package/docs-site/content/docs/(documentation)/meta.json +0 -19
- package/docs-site/content/docs/(documentation)/reference/cli.mdx +0 -241
- package/docs-site/content/docs/(documentation)/reference/environment-variables.mdx +0 -205
- package/docs-site/content/docs/(documentation)/reference/mcp-tools.mdx +0 -449
- package/docs-site/content/docs/(documentation)/reference/meta.json +0 -4
- package/docs-site/content/docs/api-reference/active-sessions.mdx +0 -9
- package/docs-site/content/docs/api-reference/agents.mdx +0 -9
- package/docs-site/content/docs/api-reference/channels.mdx +0 -9
- package/docs-site/content/docs/api-reference/config.mdx +0 -9
- package/docs-site/content/docs/api-reference/debug.mdx +0 -9
- package/docs-site/content/docs/api-reference/ecosystem.mdx +0 -9
- package/docs-site/content/docs/api-reference/epics.mdx +0 -9
- package/docs-site/content/docs/api-reference/index.mdx +0 -32
- package/docs-site/content/docs/api-reference/memory.mdx +0 -9
- package/docs-site/content/docs/api-reference/meta.json +0 -25
- package/docs-site/content/docs/api-reference/poll.mdx +0 -9
- package/docs-site/content/docs/api-reference/repos.mdx +0 -9
- package/docs-site/content/docs/api-reference/schedules.mdx +0 -9
- package/docs-site/content/docs/api-reference/session-data.mdx +0 -9
- package/docs-site/content/docs/api-reference/stats.mdx +0 -9
- package/docs-site/content/docs/api-reference/tasks.mdx +0 -9
- package/docs-site/content/docs/api-reference/trackers.mdx +0 -9
- package/docs-site/content/docs/api-reference/webhooks.mdx +0 -9
- package/docs-site/content/docs/api-reference/workflows.mdx +0 -9
- package/docs-site/content/docs/meta.json +0 -3
- package/docs-site/lib/get-llm-text.ts +0 -10
- package/docs-site/lib/openapi.ts +0 -23
- package/docs-site/lib/source.ts +0 -8
- package/docs-site/mdx-components.tsx +0 -13
- package/docs-site/next.config.mjs +0 -29
- package/docs-site/package.json +0 -35
- package/docs-site/pnpm-lock.yaml +0 -5407
- package/docs-site/postcss.config.mjs +0 -8
- package/docs-site/public/logo.png +0 -0
- package/docs-site/scripts/generate-docs.ts +0 -171
- package/docs-site/source.config.ts +0 -17
- package/docs-site/tsconfig.json +0 -46
- package/ecosystem.config.cjs +0 -66
- package/landing/next.config.ts +0 -14
- package/landing/package.json +0 -31
- package/landing/pnpm-lock.yaml +0 -1091
- package/landing/postcss.config.mjs +0 -8
- package/landing/public/apple-touch-icon.png +0 -0
- package/landing/public/favicon.ico +0 -0
- package/landing/public/logo.png +0 -0
- package/landing/public/og-image.png +0 -0
- package/landing/public/omghost-desplega.svg +0 -30
- package/landing/public/omghost-openfort.svg +0 -9
- package/landing/src/app/actions/waitlist.ts +0 -25
- package/landing/src/app/blog/openfort-hackathon/page.tsx +0 -863
- package/landing/src/app/blog/page.tsx +0 -162
- package/landing/src/app/blog/swarm-metrics/page.tsx +0 -685
- package/landing/src/app/examples/page.tsx +0 -174
- package/landing/src/app/examples/x402/page.tsx +0 -456
- package/landing/src/app/globals.css +0 -122
- package/landing/src/app/layout.tsx +0 -134
- package/landing/src/app/page.tsx +0 -27
- package/landing/src/app/robots.ts +0 -13
- package/landing/src/app/sitemap.ts +0 -44
- package/landing/src/components/architecture.tsx +0 -163
- package/landing/src/components/cta.tsx +0 -52
- package/landing/src/components/features.tsx +0 -160
- package/landing/src/components/footer.tsx +0 -100
- package/landing/src/components/hero.tsx +0 -217
- package/landing/src/components/how-it-works.tsx +0 -165
- package/landing/src/components/navbar.tsx +0 -147
- package/landing/src/components/waitlist.tsx +0 -110
- package/landing/src/components/why-choose.tsx +0 -149
- package/landing/src/components/workshops.tsx +0 -328
- package/landing/src/lib/utils.ts +0 -6
- package/landing/tsconfig.json +0 -41
- package/misc/transcripts/2026-03-09-pi-mono-e2e-verification.md +0 -154
- package/new-ui/CLAUDE.md +0 -92
- package/new-ui/README.md +0 -73
- package/new-ui/biome.json +0 -42
- package/new-ui/components.json +0 -21
- package/new-ui/index.html +0 -25
- package/new-ui/package.json +0 -49
- package/new-ui/pnpm-lock.yaml +0 -4845
- package/new-ui/public/logo.png +0 -0
- package/new-ui/src/api/client.ts +0 -814
- package/new-ui/src/api/hooks/index.ts +0 -64
- package/new-ui/src/api/hooks/use-agents.ts +0 -58
- package/new-ui/src/api/hooks/use-channels.ts +0 -115
- package/new-ui/src/api/hooks/use-config-api.ts +0 -46
- package/new-ui/src/api/hooks/use-costs.ts +0 -122
- package/new-ui/src/api/hooks/use-db-query.ts +0 -29
- package/new-ui/src/api/hooks/use-epics.ts +0 -75
- package/new-ui/src/api/hooks/use-repos.ts +0 -61
- package/new-ui/src/api/hooks/use-schedules.ts +0 -81
- package/new-ui/src/api/hooks/use-services.ts +0 -16
- package/new-ui/src/api/hooks/use-stats.ts +0 -27
- package/new-ui/src/api/hooks/use-tasks.ts +0 -89
- package/new-ui/src/api/hooks/use-workflows.ts +0 -109
- package/new-ui/src/api/types.ts +0 -549
- package/new-ui/src/app/App.tsx +0 -13
- package/new-ui/src/app/providers.tsx +0 -32
- package/new-ui/src/app/router.tsx +0 -52
- package/new-ui/src/components/layout/app-header.tsx +0 -47
- package/new-ui/src/components/layout/app-sidebar.tsx +0 -128
- package/new-ui/src/components/layout/breadcrumbs.tsx +0 -57
- package/new-ui/src/components/layout/config-guard.tsx +0 -22
- package/new-ui/src/components/layout/root-layout.tsx +0 -40
- package/new-ui/src/components/layout/swarm-switcher.tsx +0 -85
- package/new-ui/src/components/shared/command-menu.tsx +0 -131
- package/new-ui/src/components/shared/data-grid.tsx +0 -141
- package/new-ui/src/components/shared/empty-state.tsx +0 -24
- package/new-ui/src/components/shared/error-boundary.tsx +0 -72
- package/new-ui/src/components/shared/json-viewer.tsx +0 -47
- package/new-ui/src/components/shared/name-connection-modal.tsx +0 -99
- package/new-ui/src/components/shared/page-skeleton.tsx +0 -16
- package/new-ui/src/components/shared/session-log-viewer.tsx +0 -364
- package/new-ui/src/components/shared/stats-bar.tsx +0 -132
- package/new-ui/src/components/shared/status-badge.tsx +0 -131
- package/new-ui/src/components/shared/usage-summary.tsx +0 -179
- package/new-ui/src/components/ui/alert-dialog.tsx +0 -176
- package/new-ui/src/components/ui/alert.tsx +0 -60
- package/new-ui/src/components/ui/avatar.tsx +0 -96
- package/new-ui/src/components/ui/badge.tsx +0 -46
- package/new-ui/src/components/ui/button.tsx +0 -62
- package/new-ui/src/components/ui/card.tsx +0 -75
- package/new-ui/src/components/ui/command.tsx +0 -160
- package/new-ui/src/components/ui/dialog.tsx +0 -143
- package/new-ui/src/components/ui/dropdown-menu.tsx +0 -226
- package/new-ui/src/components/ui/input.tsx +0 -21
- package/new-ui/src/components/ui/label.tsx +0 -19
- package/new-ui/src/components/ui/progress.tsx +0 -26
- package/new-ui/src/components/ui/scroll-area.tsx +0 -54
- package/new-ui/src/components/ui/select.tsx +0 -175
- package/new-ui/src/components/ui/separator.tsx +0 -28
- package/new-ui/src/components/ui/sheet.tsx +0 -132
- package/new-ui/src/components/ui/sidebar.tsx +0 -691
- package/new-ui/src/components/ui/skeleton.tsx +0 -13
- package/new-ui/src/components/ui/sonner.tsx +0 -35
- package/new-ui/src/components/ui/switch.tsx +0 -33
- package/new-ui/src/components/ui/table.tsx +0 -92
- package/new-ui/src/components/ui/tabs.tsx +0 -79
- package/new-ui/src/components/ui/textarea.tsx +0 -18
- package/new-ui/src/components/ui/tooltip.tsx +0 -51
- package/new-ui/src/components/workflows/action-node.tsx +0 -53
- package/new-ui/src/components/workflows/condition-node.tsx +0 -50
- package/new-ui/src/components/workflows/graph-utils.ts +0 -124
- package/new-ui/src/components/workflows/json-tree.tsx +0 -189
- package/new-ui/src/components/workflows/node-styles.ts +0 -10
- package/new-ui/src/components/workflows/step-detail-sheet.tsx +0 -87
- package/new-ui/src/components/workflows/trigger-node.tsx +0 -41
- package/new-ui/src/components/workflows/workflow-graph.tsx +0 -65
- package/new-ui/src/hooks/use-auto-scroll.ts +0 -82
- package/new-ui/src/hooks/use-config.ts +0 -203
- package/new-ui/src/hooks/use-keyboard-shortcuts.ts +0 -41
- package/new-ui/src/hooks/use-mobile.ts +0 -19
- package/new-ui/src/hooks/use-theme.ts +0 -60
- package/new-ui/src/lib/config.ts +0 -188
- package/new-ui/src/lib/slugs.ts +0 -71
- package/new-ui/src/lib/utils.ts +0 -120
- package/new-ui/src/main.tsx +0 -11
- package/new-ui/src/pages/agents/[id]/page.tsx +0 -492
- package/new-ui/src/pages/agents/page.tsx +0 -134
- package/new-ui/src/pages/chat/page.tsx +0 -674
- package/new-ui/src/pages/config/page.tsx +0 -1109
- package/new-ui/src/pages/dashboard/page.tsx +0 -454
- package/new-ui/src/pages/debug/page.tsx +0 -275
- package/new-ui/src/pages/epics/[id]/page.tsx +0 -809
- package/new-ui/src/pages/epics/page.tsx +0 -321
- package/new-ui/src/pages/not-found/page.tsx +0 -18
- package/new-ui/src/pages/repos/page.tsx +0 -369
- package/new-ui/src/pages/schedules/[id]/page.tsx +0 -664
- package/new-ui/src/pages/schedules/page.tsx +0 -477
- package/new-ui/src/pages/services/page.tsx +0 -128
- package/new-ui/src/pages/tasks/[id]/page.tsx +0 -670
- package/new-ui/src/pages/tasks/page.tsx +0 -592
- package/new-ui/src/pages/usage/page.tsx +0 -195
- package/new-ui/src/pages/workflow-runs/[id]/page.tsx +0 -363
- package/new-ui/src/pages/workflows/[id]/page.tsx +0 -417
- package/new-ui/src/pages/workflows/page.tsx +0 -266
- package/new-ui/src/styles/ag-grid.css +0 -36
- package/new-ui/src/styles/globals.css +0 -213
- package/new-ui/test-results/.last-run.json +0 -4
- package/new-ui/tsconfig.app.json +0 -34
- package/new-ui/tsconfig.json +0 -4
- package/new-ui/tsconfig.node.json +0 -26
- package/new-ui/vercel.json +0 -4
- package/new-ui/vite.config.ts +0 -28
- package/plugin/README.md +0 -1
- package/plugin/build-pi-skills.ts +0 -233
- package/plugin/hooks/hooks.json +0 -71
- package/prek.toml +0 -75
- package/pyproject.toml +0 -9
- package/scripts/check-db-boundary.sh +0 -60
- package/scripts/e2e-docker-provider.ts +0 -820
- package/scripts/e2e-io-schemas-test.ts +0 -807
- package/scripts/e2e-provider-test.ts +0 -220
- package/scripts/e2e-workflow-redesign.sh +0 -229
- package/scripts/e2e-workflow-test.sh +0 -285
- package/scripts/e2e-workflow-test.ts +0 -857
- package/scripts/generate-mcp-docs.ts +0 -415
- package/scripts/generate-openapi.ts +0 -26
- package/scripts/measure-tool-tokens.ts +0 -118
- package/scripts/x402-e2e-test.ts +0 -195
- package/scripts/x402-test-server.ts +0 -236
- package/scripts/x402-testnet-e2e.ts +0 -668
- package/slack-manifest.json +0 -88
- package/templates-ui/README.md +0 -46
- package/templates-ui/components.json +0 -17
- package/templates-ui/eslint.config.mjs +0 -18
- package/templates-ui/next.config.ts +0 -7
- package/templates-ui/package.json +0 -35
- package/templates-ui/pnpm-lock.yaml +0 -4571
- package/templates-ui/postcss.config.mjs +0 -7
- package/templates-ui/public/file.svg +0 -1
- package/templates-ui/public/globe.svg +0 -1
- package/templates-ui/public/logo.png +0 -0
- package/templates-ui/public/next.svg +0 -1
- package/templates-ui/public/vercel.svg +0 -1
- package/templates-ui/public/window.svg +0 -1
- package/templates-ui/src/app/[category]/[name]/page.tsx +0 -89
- package/templates-ui/src/app/api/templates/[...slug]/route.ts +0 -52
- package/templates-ui/src/app/api/templates/route.ts +0 -18
- package/templates-ui/src/app/builder/page.tsx +0 -37
- package/templates-ui/src/app/globals.css +0 -94
- package/templates-ui/src/app/layout.tsx +0 -79
- package/templates-ui/src/app/page.tsx +0 -38
- package/templates-ui/src/app/robots.ts +0 -11
- package/templates-ui/src/app/sitemap.ts +0 -31
- package/templates-ui/src/components/compose-builder.tsx +0 -442
- package/templates-ui/src/components/compose-preview.tsx +0 -117
- package/templates-ui/src/components/file-preview.tsx +0 -77
- package/templates-ui/src/components/footer.tsx +0 -40
- package/templates-ui/src/components/header.tsx +0 -41
- package/templates-ui/src/components/template-card.tsx +0 -87
- package/templates-ui/src/components/template-detail.tsx +0 -125
- package/templates-ui/src/components/template-gallery.tsx +0 -263
- package/templates-ui/src/components/ui/badge.tsx +0 -36
- package/templates-ui/src/components/ui/button.tsx +0 -57
- package/templates-ui/src/components/ui/card.tsx +0 -76
- package/templates-ui/src/components/ui/separator.tsx +0 -31
- package/templates-ui/src/components/ui/tooltip.tsx +0 -32
- package/templates-ui/src/lib/compose-generator.ts +0 -241
- package/templates-ui/src/lib/templates.ts +0 -137
- package/templates-ui/src/lib/utils.ts +0 -6
- package/templates-ui/tsconfig.json +0 -34
- package/thoughts/research/2026-02-28-openfort-viem-x402-research.md +0 -679
- package/thoughts/research/2026-02-28-x402-payments-research.md +0 -686
- package/thoughts/researcher/plans/2026-02-20-agent-self-improvement-plan.md +0 -282
- package/thoughts/researcher/research/2026-02-20-agent-self-improvement.md +0 -492
- package/thoughts/shared/plans/.gitkeep +0 -0
- package/thoughts/shared/plans/2025-12-18-slack-integration.md +0 -1195
- package/thoughts/shared/plans/2025-12-19-agent-log-streaming.md +0 -732
- package/thoughts/shared/plans/2025-12-19-role-based-swarm-plugin.md +0 -361
- package/thoughts/shared/plans/2025-12-20-mobile-responsive-ui.md +0 -501
- package/thoughts/shared/plans/2025-12-20-startup-team-swarm.md +0 -560
- package/thoughts/shared/plans/2025-12-23-runner-level-polling.md +0 -934
- package/thoughts/shared/plans/2025-12-23-runner-session-logs.md +0 -1000
- package/thoughts/shared/plans/2025-12-23-worker-lead-spawn-triggers.md +0 -568
- package/thoughts/shared/plans/2026-01-09-inverse-teleport.md +0 -1516
- package/thoughts/shared/plans/2026-01-12-agent-rename-pm2-control.md +0 -1133
- package/thoughts/shared/plans/2026-01-12-github-app-integration.md +0 -380
- package/thoughts/shared/plans/2026-01-12-lead-inbox-model.md +0 -876
- package/thoughts/shared/plans/2026-01-12-ralph-wiggum-integration.md +0 -463
- package/thoughts/shared/plans/2026-01-13-agent-concurrency.md +0 -691
- package/thoughts/shared/plans/2026-01-13-github-assignment-handling.md +0 -690
- package/thoughts/shared/plans/2026-01-13-prevent-duplicate-trigger-processing.md +0 -1071
- package/thoughts/shared/plans/2026-01-14-fix-slack-thread-context.md +0 -507
- package/thoughts/shared/plans/2026-01-15-scheduled-tasks-implementation.md +0 -565
- package/thoughts/shared/plans/2026-01-15-usage-cost-tracking-ui.md +0 -1479
- package/thoughts/shared/plans/2026-01-16-epics-feature-implementation.md +0 -1230
- package/thoughts/shared/plans/2026-02-26-mcp-tool-context-reduction.md +0 -282
- package/thoughts/shared/plans/2026-03-02-claude-context-mode-integration.md +0 -328
- package/thoughts/shared/plans/2026-03-02-code-level-heartbeat.md +0 -224
- package/thoughts/shared/research/.gitkeep +0 -0
- package/thoughts/shared/research/2025-01-09-inverse-teleport-plan-review.md +0 -420
- package/thoughts/shared/research/2025-12-18-slack-integration.md +0 -442
- package/thoughts/shared/research/2025-12-19-agent-log-streaming.md +0 -339
- package/thoughts/shared/research/2025-12-19-agent-secrets-cli-research.md +0 -390
- package/thoughts/shared/research/2025-12-21-gemini-cli-integration.md +0 -376
- package/thoughts/shared/research/2025-12-22-runner-loop-architecture.md +0 -582
- package/thoughts/shared/research/2025-12-22-setup-experience-improvements.md +0 -264
- package/thoughts/shared/research/2026-01-13-lead-duplicate-trigger-processing.md +0 -223
- package/thoughts/shared/research/2026-01-14-lead-slack-thread-context.md +0 -277
- package/thoughts/shared/research/2026-01-15-ai-tracker-agent-swarm-integration.md +0 -376
- package/thoughts/shared/research/2026-01-15-auto-starting-processes-in-worker-containers.md +0 -787
- package/thoughts/shared/research/2026-01-15-scheduled-tasks.md +0 -390
- package/thoughts/shared/research/2026-01-16-epics-feature-research.md +0 -437
- package/thoughts/shared/research/2026-02-26-cliffy-mcp-tools.md +0 -159
- package/thoughts/shared/research/2026-03-03-database-migration-system-refactor.md +0 -337
- package/thoughts/swarm-researcher/plans/2026-02-23-openclaw-improvements-plan.md +0 -778
- package/thoughts/swarm-researcher/plans/2026-02-26-artifacts-localtunnel-plan.md +0 -1269
- package/thoughts/swarm-researcher/research/2026-02-23-openclaw-vs-agent-swarm-comparison.md +0 -411
- package/thoughts/swarm-researcher/research/2026-02-26-artifacts-localtunnel.md +0 -724
- package/thoughts/taras/brainstorms/2026-03-20-prompt-template-registry.md +0 -443
- package/thoughts/taras/brainstorms/2026-03-20-setup-cli-onboarding.md +0 -307
- package/thoughts/taras/plans/2026-01-22-agent-swarm-schemas.md +0 -98
- package/thoughts/taras/plans/2026-01-28-per-worker-claude-md.md +0 -617
- package/thoughts/taras/plans/2026-01-28-sentry-cli-integration.md +0 -214
- package/thoughts/taras/plans/2026-02-20-auto-improvement.md +0 -803
- package/thoughts/taras/plans/2026-02-20-env-management.md +0 -538
- package/thoughts/taras/plans/2026-02-20-memory-system.md +0 -882
- package/thoughts/taras/plans/2026-02-20-repos-knowledge.md +0 -806
- package/thoughts/taras/plans/2026-02-20-session-attach.md +0 -647
- package/thoughts/taras/plans/2026-02-20-worker-identity.md +0 -820
- package/thoughts/taras/plans/2026-02-25-feat-new-ui-visual-redesign-plan.md +0 -768
- package/thoughts/taras/plans/2026-03-04-fix-buildSystemPrompt-missing-fields.md +0 -77
- package/thoughts/taras/plans/2026-03-04-new-ui-missing-actions.md +0 -543
- package/thoughts/taras/plans/2026-03-06-one-time-scheduled-tasks.md +0 -373
- package/thoughts/taras/plans/2026-03-08-memory-self-improvement-enhancements.md +0 -512
- package/thoughts/taras/plans/2026-03-08-pi-mono-provider-implementation.md +0 -919
- package/thoughts/taras/plans/2026-03-09-templates-registry.md +0 -723
- package/thoughts/taras/plans/2026-03-10-task-working-directory.md +0 -371
- package/thoughts/taras/plans/2026-03-11-archil-per-agent-write-strategy.md +0 -621
- package/thoughts/taras/plans/2026-03-12-eliminate-inbox-route-to-tasks.md +0 -61
- package/thoughts/taras/plans/2026-03-12-slack-thread-followup-additive.md +0 -488
- package/thoughts/taras/plans/2026-03-13-slack-ai-improvements.md +0 -644
- package/thoughts/taras/plans/2026-03-16-route-wrapper-openapi.md +0 -636
- package/thoughts/taras/plans/2026-03-17-multi-api-config.md +0 -444
- package/thoughts/taras/plans/2026-03-18-agent-fs-integration.md +0 -591
- package/thoughts/taras/plans/2026-03-18-debug-db-explorer.md +0 -446
- package/thoughts/taras/plans/2026-03-18-workflow-redesign.md +0 -987
- package/thoughts/taras/plans/2026-03-19-compound-learnings.md +0 -403
- package/thoughts/taras/plans/2026-03-19-ticket-tracker-linear-integration.md +0 -860
- package/thoughts/taras/plans/2026-03-19-workflow-io-schemas-and-bugs.md +0 -899
- package/thoughts/taras/plans/2026-03-20-setup-cli-onboarding.md +0 -874
- package/thoughts/taras/plans/2026-03-20-workflow-structured-output-validation-workspace.md +0 -723
- package/thoughts/taras/research/2026-01-22-vercel-cli-integration.md +0 -287
- package/thoughts/taras/research/2026-01-27-excessive-polling-issue.md +0 -311
- package/thoughts/taras/research/2026-01-28-per-worker-claude-md.md +0 -383
- package/thoughts/taras/research/2026-01-28-sentry-cli-integration.md +0 -240
- package/thoughts/taras/research/2026-02-19-agent-native-swarm-architecture.md +0 -390
- package/thoughts/taras/research/2026-02-19-swarm-gaps-implementation.md +0 -594
- package/thoughts/taras/research/2026-02-25-dashboard-ui-design-best-practices.md +0 -825
- package/thoughts/taras/research/2026-02-26-task-detail-page-redesign.md +0 -393
- package/thoughts/taras/research/2026-03-03-new-ui-missing-actions.md +0 -168
- package/thoughts/taras/research/2026-03-05-pi-mono-provider-research.md +0 -230
- package/thoughts/taras/research/2026-03-06-workflow-engine-design.md +0 -445
- package/thoughts/taras/research/2026-03-08-drive-loop-concept.md +0 -375
- package/thoughts/taras/research/2026-03-08-pi-mono-deep-dive.md +0 -869
- package/thoughts/taras/research/2026-03-09-templates-registry.md +0 -373
- package/thoughts/taras/research/2026-03-10-agent-working-directory.md +0 -223
- package/thoughts/taras/research/2026-03-10-configurable-event-prompts.md +0 -339
- package/thoughts/taras/research/2026-03-11-archil-production-setup.md +0 -181
- package/thoughts/taras/research/2026-03-11-archil-shared-disk-write-strategies.md +0 -437
- package/thoughts/taras/research/2026-03-13-slack-ai-features.md +0 -258
- package/thoughts/taras/research/2026-03-16-openapi-docs-generation.md +0 -335
- package/thoughts/taras/research/2026-03-16-route-wrapper-openapi.md +0 -670
- package/thoughts/taras/research/2026-03-16-slack-thread-followups-e2e.md +0 -54
- package/thoughts/taras/research/2026-03-18-agent-fs-integration.md +0 -558
- package/thoughts/taras/research/2026-03-18-linear-integration-finalization.md +0 -526
- package/thoughts/taras/research/2026-03-18-workflow-redesign.md +0 -797
- package/thoughts/taras/research/2026-03-19-workflow-node-io-schemas-and-bugs.md +0 -563
- package/thoughts/taras/research/2026-03-19-workflow-structured-output-validation-workspace.md +0 -486
- package/thoughts/taras/research/2026-03-20-prompt-template-registry.md +0 -469
- package/tsconfig.json +0 -37
|
@@ -1,876 +0,0 @@
|
|
|
1
|
-
# Lead Agent Inbox Model Implementation Plan
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Modify the agent swarm so that the lead agent focuses exclusively on **delegation and answering questions**, rather than performing tasks. When Slack messages are routed to the lead, they become **inbox messages** (not tasks), which the lead can respond to directly or delegate to workers.
|
|
6
|
-
|
|
7
|
-
## Current State Analysis
|
|
8
|
-
|
|
9
|
-
### Current Behavior (Problems)
|
|
10
|
-
1. **Slack messages to lead create tasks** - In `src/slack/handlers.ts:231`, `createTask()` is called for ALL matched agents including leads
|
|
11
|
-
2. **Lead prompt mentions `poll-task`** - In `src/prompts/base-prompt.ts:29`, the lead is told it can use poll-task to claim work
|
|
12
|
-
3. **Lead receives `task_assigned` triggers** - In `src/http.ts:314-322`, leads can get task assignment triggers like workers
|
|
13
|
-
4. **No inbox concept exists** - There's no separate mechanism for lead to receive messages without them becoming tasks
|
|
14
|
-
|
|
15
|
-
### Key Discoveries
|
|
16
|
-
- `send-task` already blocks direct task assignment to leads (`src/tools/send-task.ts:112-117`)
|
|
17
|
-
- Slack responses already work with agent personas (`src/slack/responses.ts`)
|
|
18
|
-
- The tool pattern uses `createToolRegistrar()` from `src/tools/utils.ts`
|
|
19
|
-
- Leads get triggers via polling in `src/http.ts:325-349`
|
|
20
|
-
|
|
21
|
-
## Desired End State
|
|
22
|
-
|
|
23
|
-
After this plan is complete:
|
|
24
|
-
1. Slack messages routed to the lead create **inbox messages** (not tasks)
|
|
25
|
-
2. Lead polling returns `slack_inbox_message` trigger for unread inbox items
|
|
26
|
-
3. Lead can use `slack-reply` tool to respond directly to Slack threads
|
|
27
|
-
4. Lead can use `inbox-delegate` tool to create tasks for workers from inbox items
|
|
28
|
-
5. Lead prompt no longer mentions `poll-task` and emphasizes delegation/answering
|
|
29
|
-
6. Workers continue to receive Slack-originated tasks normally (no change)
|
|
30
|
-
|
|
31
|
-
### Verification
|
|
32
|
-
- Send `@agent-swarm help me with X` in Slack
|
|
33
|
-
- Verify no task is created in `agent_tasks` table
|
|
34
|
-
- Verify inbox message is created in new `inbox_messages` table
|
|
35
|
-
- Poll as lead, verify `slack_inbox_message` trigger
|
|
36
|
-
- Use `slack-reply` tool, verify message appears in Slack thread
|
|
37
|
-
- Use `inbox-delegate` tool, verify task created for worker with Slack context
|
|
38
|
-
|
|
39
|
-
## What We're NOT Doing
|
|
40
|
-
|
|
41
|
-
- Changing worker behavior (workers still get tasks from Slack)
|
|
42
|
-
- Adding interactive Slack components (buttons, modals)
|
|
43
|
-
- OAuth flow for multi-workspace support
|
|
44
|
-
- Changing the internal swarm chat/channel messaging system
|
|
45
|
-
|
|
46
|
-
## Implementation Approach
|
|
47
|
-
|
|
48
|
-
We'll add a new `inbox_messages` table and two new tools (`slack-reply`, `inbox-delegate`), modify the Slack handler to route lead messages to inbox, and update lead polling/prompts.
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## Phase 1: Database Schema and Types
|
|
53
|
-
|
|
54
|
-
### Overview
|
|
55
|
-
Add the `inbox_messages` table and TypeScript types for the lead's inbox.
|
|
56
|
-
|
|
57
|
-
### Changes Required
|
|
58
|
-
|
|
59
|
-
#### 1. Add InboxMessage Type
|
|
60
|
-
**File**: `src/types.ts`
|
|
61
|
-
**Changes**: Add new schema and type for inbox messages
|
|
62
|
-
|
|
63
|
-
```typescript
|
|
64
|
-
// After line 54 (after AgentTaskSchema)
|
|
65
|
-
|
|
66
|
-
export const InboxMessageStatusSchema = z.enum([
|
|
67
|
-
"unread",
|
|
68
|
-
"read",
|
|
69
|
-
"responded",
|
|
70
|
-
"delegated",
|
|
71
|
-
]);
|
|
72
|
-
|
|
73
|
-
export const InboxMessageSchema = z.object({
|
|
74
|
-
id: z.uuid(),
|
|
75
|
-
agentId: z.uuid(), // Lead agent who received this
|
|
76
|
-
content: z.string().min(1), // The message content
|
|
77
|
-
source: z.enum(["slack"]).default("slack"),
|
|
78
|
-
status: InboxMessageStatusSchema.default("unread"),
|
|
79
|
-
|
|
80
|
-
// Slack context (for replying)
|
|
81
|
-
slackChannelId: z.string().optional(),
|
|
82
|
-
slackThreadTs: z.string().optional(),
|
|
83
|
-
slackUserId: z.string().optional(),
|
|
84
|
-
|
|
85
|
-
// Routing info
|
|
86
|
-
matchedText: z.string().optional(), // Why it was routed here
|
|
87
|
-
|
|
88
|
-
// Delegation tracking
|
|
89
|
-
delegatedToTaskId: z.uuid().optional(), // If delegated, which task
|
|
90
|
-
responseText: z.string().optional(), // If responded directly
|
|
91
|
-
|
|
92
|
-
// Timestamps
|
|
93
|
-
createdAt: z.iso.datetime(),
|
|
94
|
-
lastUpdatedAt: z.iso.datetime(),
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
export type InboxMessageStatus = z.infer<typeof InboxMessageStatusSchema>;
|
|
98
|
-
export type InboxMessage = z.infer<typeof InboxMessageSchema>;
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
#### 2. Add Database Table and Functions
|
|
102
|
-
**File**: `src/be/db.ts`
|
|
103
|
-
**Changes**: Add table creation in `initDb()` and CRUD functions
|
|
104
|
-
|
|
105
|
-
Add table in schema initialization (inside the `initSchema` transaction, after `session_logs`):
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
database.run(`
|
|
109
|
-
CREATE TABLE IF NOT EXISTS inbox_messages (
|
|
110
|
-
id TEXT PRIMARY KEY,
|
|
111
|
-
agentId TEXT NOT NULL,
|
|
112
|
-
content TEXT NOT NULL,
|
|
113
|
-
source TEXT NOT NULL DEFAULT 'slack',
|
|
114
|
-
status TEXT NOT NULL DEFAULT 'unread' CHECK(status IN ('unread', 'read', 'responded', 'delegated')),
|
|
115
|
-
slackChannelId TEXT,
|
|
116
|
-
slackThreadTs TEXT,
|
|
117
|
-
slackUserId TEXT,
|
|
118
|
-
matchedText TEXT,
|
|
119
|
-
delegatedToTaskId TEXT,
|
|
120
|
-
responseText TEXT,
|
|
121
|
-
createdAt TEXT NOT NULL,
|
|
122
|
-
lastUpdatedAt TEXT NOT NULL,
|
|
123
|
-
FOREIGN KEY (agentId) REFERENCES agents(id) ON DELETE CASCADE,
|
|
124
|
-
FOREIGN KEY (delegatedToTaskId) REFERENCES agent_tasks(id) ON DELETE SET NULL
|
|
125
|
-
)
|
|
126
|
-
`);
|
|
127
|
-
|
|
128
|
-
// Add index
|
|
129
|
-
database.run(`CREATE INDEX IF NOT EXISTS idx_inbox_messages_agentId ON inbox_messages(agentId)`);
|
|
130
|
-
database.run(`CREATE INDEX IF NOT EXISTS idx_inbox_messages_status ON inbox_messages(status)`);
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
Add CRUD functions after the session log section:
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
// ============================================================================
|
|
137
|
-
// Inbox Message Operations
|
|
138
|
-
// ============================================================================
|
|
139
|
-
|
|
140
|
-
type InboxMessageRow = {
|
|
141
|
-
id: string;
|
|
142
|
-
agentId: string;
|
|
143
|
-
content: string;
|
|
144
|
-
source: string;
|
|
145
|
-
status: InboxMessageStatus;
|
|
146
|
-
slackChannelId: string | null;
|
|
147
|
-
slackThreadTs: string | null;
|
|
148
|
-
slackUserId: string | null;
|
|
149
|
-
matchedText: string | null;
|
|
150
|
-
delegatedToTaskId: string | null;
|
|
151
|
-
responseText: string | null;
|
|
152
|
-
createdAt: string;
|
|
153
|
-
lastUpdatedAt: string;
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
function rowToInboxMessage(row: InboxMessageRow): InboxMessage {
|
|
157
|
-
return {
|
|
158
|
-
id: row.id,
|
|
159
|
-
agentId: row.agentId,
|
|
160
|
-
content: row.content,
|
|
161
|
-
source: row.source as "slack",
|
|
162
|
-
status: row.status,
|
|
163
|
-
slackChannelId: row.slackChannelId ?? undefined,
|
|
164
|
-
slackThreadTs: row.slackThreadTs ?? undefined,
|
|
165
|
-
slackUserId: row.slackUserId ?? undefined,
|
|
166
|
-
matchedText: row.matchedText ?? undefined,
|
|
167
|
-
delegatedToTaskId: row.delegatedToTaskId ?? undefined,
|
|
168
|
-
responseText: row.responseText ?? undefined,
|
|
169
|
-
createdAt: row.createdAt,
|
|
170
|
-
lastUpdatedAt: row.lastUpdatedAt,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export interface CreateInboxMessageOptions {
|
|
175
|
-
source?: "slack";
|
|
176
|
-
slackChannelId?: string;
|
|
177
|
-
slackThreadTs?: string;
|
|
178
|
-
slackUserId?: string;
|
|
179
|
-
matchedText?: string;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export function createInboxMessage(
|
|
183
|
-
agentId: string,
|
|
184
|
-
content: string,
|
|
185
|
-
options?: CreateInboxMessageOptions,
|
|
186
|
-
): InboxMessage {
|
|
187
|
-
const id = crypto.randomUUID();
|
|
188
|
-
const now = new Date().toISOString();
|
|
189
|
-
|
|
190
|
-
const row = getDb()
|
|
191
|
-
.prepare<InboxMessageRow, (string | null)[]>(
|
|
192
|
-
`INSERT INTO inbox_messages (id, agentId, content, source, status, slackChannelId, slackThreadTs, slackUserId, matchedText, createdAt, lastUpdatedAt)
|
|
193
|
-
VALUES (?, ?, ?, ?, 'unread', ?, ?, ?, ?, ?, ?) RETURNING *`,
|
|
194
|
-
)
|
|
195
|
-
.get(
|
|
196
|
-
id,
|
|
197
|
-
agentId,
|
|
198
|
-
content,
|
|
199
|
-
options?.source ?? "slack",
|
|
200
|
-
options?.slackChannelId ?? null,
|
|
201
|
-
options?.slackThreadTs ?? null,
|
|
202
|
-
options?.slackUserId ?? null,
|
|
203
|
-
options?.matchedText ?? null,
|
|
204
|
-
now,
|
|
205
|
-
now,
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
if (!row) throw new Error("Failed to create inbox message");
|
|
209
|
-
return rowToInboxMessage(row);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export function getInboxMessageById(id: string): InboxMessage | null {
|
|
213
|
-
const row = getDb()
|
|
214
|
-
.prepare<InboxMessageRow, [string]>("SELECT * FROM inbox_messages WHERE id = ?")
|
|
215
|
-
.get(id);
|
|
216
|
-
return row ? rowToInboxMessage(row) : null;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export function getUnreadInboxMessages(agentId: string): InboxMessage[] {
|
|
220
|
-
return getDb()
|
|
221
|
-
.prepare<InboxMessageRow, [string]>(
|
|
222
|
-
"SELECT * FROM inbox_messages WHERE agentId = ? AND status = 'unread' ORDER BY createdAt ASC",
|
|
223
|
-
)
|
|
224
|
-
.all(agentId)
|
|
225
|
-
.map(rowToInboxMessage);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export function markInboxMessageRead(id: string): InboxMessage | null {
|
|
229
|
-
const now = new Date().toISOString();
|
|
230
|
-
const row = getDb()
|
|
231
|
-
.prepare<InboxMessageRow, [string, string]>(
|
|
232
|
-
"UPDATE inbox_messages SET status = 'read', lastUpdatedAt = ? WHERE id = ? RETURNING *",
|
|
233
|
-
)
|
|
234
|
-
.get(now, id);
|
|
235
|
-
return row ? rowToInboxMessage(row) : null;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
export function markInboxMessageResponded(id: string, responseText: string): InboxMessage | null {
|
|
239
|
-
const now = new Date().toISOString();
|
|
240
|
-
const row = getDb()
|
|
241
|
-
.prepare<InboxMessageRow, [string, string, string]>(
|
|
242
|
-
"UPDATE inbox_messages SET status = 'responded', responseText = ?, lastUpdatedAt = ? WHERE id = ? RETURNING *",
|
|
243
|
-
)
|
|
244
|
-
.get(responseText, now, id);
|
|
245
|
-
return row ? rowToInboxMessage(row) : null;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
export function markInboxMessageDelegated(id: string, taskId: string): InboxMessage | null {
|
|
249
|
-
const now = new Date().toISOString();
|
|
250
|
-
const row = getDb()
|
|
251
|
-
.prepare<InboxMessageRow, [string, string, string]>(
|
|
252
|
-
"UPDATE inbox_messages SET status = 'delegated', delegatedToTaskId = ?, lastUpdatedAt = ? WHERE id = ? RETURNING *",
|
|
253
|
-
)
|
|
254
|
-
.get(taskId, now, id);
|
|
255
|
-
return row ? rowToInboxMessage(row) : null;
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### Success Criteria
|
|
260
|
-
|
|
261
|
-
#### Automated Verification
|
|
262
|
-
- [x] `bun test` passes (no regressions)
|
|
263
|
-
- [x] Server starts without errors: `bun run src/http.ts`
|
|
264
|
-
- [x] Table is created in SQLite database
|
|
265
|
-
|
|
266
|
-
#### Manual Verification
|
|
267
|
-
- [x] Can manually insert/query inbox_messages via SQLite CLI
|
|
268
|
-
|
|
269
|
-
---
|
|
270
|
-
|
|
271
|
-
## Phase 2: Slack Handler for Lead Routing
|
|
272
|
-
|
|
273
|
-
### Overview
|
|
274
|
-
Modify the Slack message handler to create inbox messages instead of tasks when routing to the lead.
|
|
275
|
-
|
|
276
|
-
### Changes Required
|
|
277
|
-
|
|
278
|
-
#### 1. Update Slack Handler
|
|
279
|
-
**File**: `src/slack/handlers.ts`
|
|
280
|
-
**Changes**: Import inbox functions and modify the task creation loop
|
|
281
|
-
|
|
282
|
-
Add import at top:
|
|
283
|
-
```typescript
|
|
284
|
-
import { createTask, getAgentById, getTasksByAgentId, createInboxMessage } from "../be/db";
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
Modify the loop starting at line 222:
|
|
288
|
-
|
|
289
|
-
```typescript
|
|
290
|
-
for (const match of matches) {
|
|
291
|
-
const agent = getAgentById(match.agent.id);
|
|
292
|
-
|
|
293
|
-
if (!agent) {
|
|
294
|
-
results.failed.push(`\`${match.agent.name}\` (not found)`);
|
|
295
|
-
continue;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
try {
|
|
299
|
-
// NEW: Check if this is a lead agent
|
|
300
|
-
if (agent.isLead) {
|
|
301
|
-
// Create inbox message instead of task
|
|
302
|
-
const inboxMsg = createInboxMessage(agent.id, fullTaskDescription, {
|
|
303
|
-
source: "slack",
|
|
304
|
-
slackChannelId: msg.channel,
|
|
305
|
-
slackThreadTs: threadTs,
|
|
306
|
-
slackUserId: msg.user,
|
|
307
|
-
matchedText: match.matchedText,
|
|
308
|
-
});
|
|
309
|
-
results.assigned.push(`*${agent.name}* (inbox)`);
|
|
310
|
-
continue;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Existing task creation for workers (unchanged)
|
|
314
|
-
const task = createTask(agent.id, fullTaskDescription, {
|
|
315
|
-
source: "slack",
|
|
316
|
-
slackChannelId: msg.channel,
|
|
317
|
-
slackThreadTs: threadTs,
|
|
318
|
-
slackUserId: msg.user,
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
// ... rest of existing logic
|
|
322
|
-
} catch {
|
|
323
|
-
results.failed.push(`\`${agent.name}\` (error)`);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
### Success Criteria
|
|
329
|
-
|
|
330
|
-
#### Automated Verification
|
|
331
|
-
- [x] `bun test` passes
|
|
332
|
-
- [x] TypeScript compiles without errors
|
|
333
|
-
|
|
334
|
-
#### Manual Verification
|
|
335
|
-
- [ ] Send `@agent-swarm help` in Slack (routes to lead)
|
|
336
|
-
- [ ] Verify NO task appears in `agent_tasks` table
|
|
337
|
-
- [ ] Verify inbox message appears in `inbox_messages` table
|
|
338
|
-
|
|
339
|
-
---
|
|
340
|
-
|
|
341
|
-
## Phase 3: Lead Polling Trigger
|
|
342
|
-
|
|
343
|
-
### Overview
|
|
344
|
-
Add the `slack_inbox_message` trigger type to lead polling so the lead wakes up when inbox messages arrive.
|
|
345
|
-
|
|
346
|
-
### Changes Required
|
|
347
|
-
|
|
348
|
-
#### 1. Update HTTP Polling
|
|
349
|
-
**File**: `src/http.ts`
|
|
350
|
-
**Changes**: Add inbox check in lead-specific triggers section
|
|
351
|
-
|
|
352
|
-
Add import:
|
|
353
|
-
```typescript
|
|
354
|
-
import {
|
|
355
|
-
// ... existing imports ...
|
|
356
|
-
getUnreadInboxMessages,
|
|
357
|
-
} from "./be/db";
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
Modify the lead triggers section (around line 325):
|
|
361
|
-
|
|
362
|
-
```typescript
|
|
363
|
-
if (agent.isLead) {
|
|
364
|
-
// === LEAD-SPECIFIC TRIGGERS ===
|
|
365
|
-
|
|
366
|
-
// NEW: Check for unread inbox messages (highest priority for lead)
|
|
367
|
-
const unreadInbox = getUnreadInboxMessages(myAgentId);
|
|
368
|
-
if (unreadInbox.length > 0) {
|
|
369
|
-
return {
|
|
370
|
-
trigger: {
|
|
371
|
-
type: "slack_inbox_message",
|
|
372
|
-
count: unreadInbox.length,
|
|
373
|
-
messages: unreadInbox.slice(0, 5), // Return up to 5 most recent
|
|
374
|
-
},
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Existing: Check for unread mentions (internal chat)
|
|
379
|
-
const inbox = getInboxSummary(myAgentId);
|
|
380
|
-
// ... rest of existing code
|
|
381
|
-
}
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
#### 2. Update Runner Trigger Prompt
|
|
385
|
-
**File**: `src/commands/runner.ts`
|
|
386
|
-
**Changes**: Add case for `slack_inbox_message` in `buildPromptForTrigger()`
|
|
387
|
-
|
|
388
|
-
Add new case in the switch statement (around line 280):
|
|
389
|
-
|
|
390
|
-
```typescript
|
|
391
|
-
case "slack_inbox_message":
|
|
392
|
-
// Format inbox message summaries
|
|
393
|
-
const inboxSummaries = trigger.messages
|
|
394
|
-
.map((m: { id: string; content: string }) => {
|
|
395
|
-
const preview = m.content.length > 100 ? `${m.content.slice(0, 100)}...` : m.content;
|
|
396
|
-
return `- "${preview}" (ID: ${m.id.slice(0, 8)})`;
|
|
397
|
-
})
|
|
398
|
-
.join("\n");
|
|
399
|
-
|
|
400
|
-
return `You have ${trigger.count} inbox message(s) from Slack:\n${inboxSummaries}\n\nFor each message, you can either:
|
|
401
|
-
- Use \`slack-reply\` with the inboxMessageId to respond directly to the user
|
|
402
|
-
- Use \`inbox-delegate\` to assign the request to a worker agent
|
|
403
|
-
|
|
404
|
-
Review each message and decide the appropriate action.`;
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### Success Criteria
|
|
408
|
-
|
|
409
|
-
#### Automated Verification
|
|
410
|
-
- [x] `bun test` passes
|
|
411
|
-
- [x] TypeScript compiles without errors
|
|
412
|
-
|
|
413
|
-
#### Manual Verification
|
|
414
|
-
- [ ] Poll as lead agent via HTTP API
|
|
415
|
-
- [ ] Verify `slack_inbox_message` trigger is returned when inbox has unread items
|
|
416
|
-
|
|
417
|
-
---
|
|
418
|
-
|
|
419
|
-
## Phase 4: Slack Reply Tool
|
|
420
|
-
|
|
421
|
-
### Overview
|
|
422
|
-
Create a new tool that allows agents (primarily lead) to reply directly to Slack threads.
|
|
423
|
-
|
|
424
|
-
### Changes Required
|
|
425
|
-
|
|
426
|
-
#### 1. Create slack-reply Tool
|
|
427
|
-
**File**: `src/tools/slack-reply.ts` (NEW FILE)
|
|
428
|
-
|
|
429
|
-
```typescript
|
|
430
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
431
|
-
import * as z from "zod";
|
|
432
|
-
import {
|
|
433
|
-
getAgentById,
|
|
434
|
-
getInboxMessageById,
|
|
435
|
-
getTaskById,
|
|
436
|
-
markInboxMessageResponded,
|
|
437
|
-
} from "@/be/db";
|
|
438
|
-
import { createToolRegistrar } from "@/tools/utils";
|
|
439
|
-
import { getSlackApp } from "@/slack/app";
|
|
440
|
-
|
|
441
|
-
export const registerSlackReplyTool = (server: McpServer) => {
|
|
442
|
-
createToolRegistrar(server)(
|
|
443
|
-
"slack-reply",
|
|
444
|
-
{
|
|
445
|
-
title: "Reply to Slack thread",
|
|
446
|
-
description:
|
|
447
|
-
"Send a reply to a Slack thread. Use inboxMessageId for inbox messages, or taskId for task-related threads.",
|
|
448
|
-
inputSchema: z.object({
|
|
449
|
-
inboxMessageId: z
|
|
450
|
-
.uuid()
|
|
451
|
-
.optional()
|
|
452
|
-
.describe("The inbox message ID to reply to (for leads responding to inbox)."),
|
|
453
|
-
taskId: z
|
|
454
|
-
.uuid()
|
|
455
|
-
.optional()
|
|
456
|
-
.describe("The task ID with Slack context (for task-related threads)."),
|
|
457
|
-
message: z
|
|
458
|
-
.string()
|
|
459
|
-
.min(1)
|
|
460
|
-
.max(4000)
|
|
461
|
-
.describe("The message to send to the Slack thread."),
|
|
462
|
-
}),
|
|
463
|
-
outputSchema: z.object({
|
|
464
|
-
success: z.boolean(),
|
|
465
|
-
message: z.string(),
|
|
466
|
-
}),
|
|
467
|
-
},
|
|
468
|
-
async ({ inboxMessageId, taskId, message }, requestInfo, _meta) => {
|
|
469
|
-
if (!requestInfo.agentId) {
|
|
470
|
-
return {
|
|
471
|
-
content: [{ type: "text", text: "Agent ID not found." }],
|
|
472
|
-
structuredContent: { success: false, message: "Agent ID not found." },
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
const agent = getAgentById(requestInfo.agentId);
|
|
477
|
-
if (!agent) {
|
|
478
|
-
return {
|
|
479
|
-
content: [{ type: "text", text: "Agent not found." }],
|
|
480
|
-
structuredContent: { success: false, message: "Agent not found." },
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
let slackChannelId: string | undefined;
|
|
485
|
-
let slackThreadTs: string | undefined;
|
|
486
|
-
|
|
487
|
-
// Determine Slack context from inbox message or task
|
|
488
|
-
if (inboxMessageId) {
|
|
489
|
-
const inboxMsg = getInboxMessageById(inboxMessageId);
|
|
490
|
-
if (!inboxMsg) {
|
|
491
|
-
return {
|
|
492
|
-
content: [{ type: "text", text: "Inbox message not found." }],
|
|
493
|
-
structuredContent: { success: false, message: "Inbox message not found." },
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
if (inboxMsg.agentId !== requestInfo.agentId) {
|
|
497
|
-
return {
|
|
498
|
-
content: [{ type: "text", text: "This inbox message is not yours." }],
|
|
499
|
-
structuredContent: { success: false, message: "This inbox message is not yours." },
|
|
500
|
-
};
|
|
501
|
-
}
|
|
502
|
-
slackChannelId = inboxMsg.slackChannelId;
|
|
503
|
-
slackThreadTs = inboxMsg.slackThreadTs;
|
|
504
|
-
|
|
505
|
-
// Mark as responded
|
|
506
|
-
markInboxMessageResponded(inboxMessageId, message);
|
|
507
|
-
} else if (taskId) {
|
|
508
|
-
const task = getTaskById(taskId);
|
|
509
|
-
if (!task) {
|
|
510
|
-
return {
|
|
511
|
-
content: [{ type: "text", text: "Task not found." }],
|
|
512
|
-
structuredContent: { success: false, message: "Task not found." },
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
// Verify agent has context for this task
|
|
516
|
-
if (task.agentId !== requestInfo.agentId && task.creatorAgentId !== requestInfo.agentId) {
|
|
517
|
-
return {
|
|
518
|
-
content: [{ type: "text", text: "You don't have context for this task." }],
|
|
519
|
-
structuredContent: { success: false, message: "You don't have context for this task." },
|
|
520
|
-
};
|
|
521
|
-
}
|
|
522
|
-
slackChannelId = task.slackChannelId;
|
|
523
|
-
slackThreadTs = task.slackThreadTs;
|
|
524
|
-
} else {
|
|
525
|
-
return {
|
|
526
|
-
content: [{ type: "text", text: "Must provide inboxMessageId or taskId." }],
|
|
527
|
-
structuredContent: { success: false, message: "Must provide inboxMessageId or taskId." },
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
if (!slackChannelId || !slackThreadTs) {
|
|
532
|
-
return {
|
|
533
|
-
content: [{ type: "text", text: "No Slack context available." }],
|
|
534
|
-
structuredContent: { success: false, message: "No Slack context available." },
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// Send the reply
|
|
539
|
-
const app = getSlackApp();
|
|
540
|
-
if (!app) {
|
|
541
|
-
return {
|
|
542
|
-
content: [{ type: "text", text: "Slack not configured." }],
|
|
543
|
-
structuredContent: { success: false, message: "Slack not configured." },
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
try {
|
|
548
|
-
await app.client.chat.postMessage({
|
|
549
|
-
channel: slackChannelId,
|
|
550
|
-
thread_ts: slackThreadTs,
|
|
551
|
-
text: message,
|
|
552
|
-
username: agent.name,
|
|
553
|
-
icon_emoji: agent.isLead ? ":crown:" : ":robot_face:",
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
return {
|
|
557
|
-
content: [{ type: "text", text: "Reply sent successfully." }],
|
|
558
|
-
structuredContent: { success: true, message: "Reply sent successfully." },
|
|
559
|
-
};
|
|
560
|
-
} catch (error) {
|
|
561
|
-
return {
|
|
562
|
-
content: [{ type: "text", text: `Failed to send reply: ${error}` }],
|
|
563
|
-
structuredContent: { success: false, message: `Failed to send reply: ${error}` },
|
|
564
|
-
};
|
|
565
|
-
}
|
|
566
|
-
},
|
|
567
|
-
);
|
|
568
|
-
};
|
|
569
|
-
```
|
|
570
|
-
|
|
571
|
-
### Success Criteria
|
|
572
|
-
|
|
573
|
-
#### Automated Verification
|
|
574
|
-
- [x] TypeScript compiles without errors
|
|
575
|
-
- [x] `bun test` passes
|
|
576
|
-
|
|
577
|
-
#### Manual Verification
|
|
578
|
-
- [ ] Lead can use `slack-reply` with inboxMessageId
|
|
579
|
-
- [ ] Message appears in Slack thread with lead's persona
|
|
580
|
-
|
|
581
|
-
---
|
|
582
|
-
|
|
583
|
-
## Phase 5: Inbox Delegate Tool
|
|
584
|
-
|
|
585
|
-
### Overview
|
|
586
|
-
Create a tool for leads to delegate inbox messages to workers by creating tasks.
|
|
587
|
-
|
|
588
|
-
### Changes Required
|
|
589
|
-
|
|
590
|
-
#### 1. Create inbox-delegate Tool
|
|
591
|
-
**File**: `src/tools/inbox-delegate.ts` (NEW FILE)
|
|
592
|
-
|
|
593
|
-
```typescript
|
|
594
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
595
|
-
import * as z from "zod";
|
|
596
|
-
import {
|
|
597
|
-
getAgentById,
|
|
598
|
-
getInboxMessageById,
|
|
599
|
-
markInboxMessageDelegated,
|
|
600
|
-
createTaskExtended,
|
|
601
|
-
} from "@/be/db";
|
|
602
|
-
import { createToolRegistrar } from "@/tools/utils";
|
|
603
|
-
import { AgentTaskSchema } from "@/types";
|
|
604
|
-
|
|
605
|
-
export const registerInboxDelegateTool = (server: McpServer) => {
|
|
606
|
-
createToolRegistrar(server)(
|
|
607
|
-
"inbox-delegate",
|
|
608
|
-
{
|
|
609
|
-
title: "Delegate inbox message to worker",
|
|
610
|
-
description:
|
|
611
|
-
"Delegate an inbox message to a worker agent by creating a task. The task inherits Slack context for replies.",
|
|
612
|
-
inputSchema: z.object({
|
|
613
|
-
inboxMessageId: z.uuid().describe("The inbox message ID to delegate."),
|
|
614
|
-
agentId: z.uuid().describe("The worker agent to delegate to."),
|
|
615
|
-
taskDescription: z
|
|
616
|
-
.string()
|
|
617
|
-
.min(1)
|
|
618
|
-
.optional()
|
|
619
|
-
.describe("Custom task description. If omitted, uses the original message."),
|
|
620
|
-
offerMode: z
|
|
621
|
-
.boolean()
|
|
622
|
-
.default(false)
|
|
623
|
-
.describe("If true, offer the task instead of direct assign."),
|
|
624
|
-
}),
|
|
625
|
-
outputSchema: z.object({
|
|
626
|
-
success: z.boolean(),
|
|
627
|
-
message: z.string(),
|
|
628
|
-
task: AgentTaskSchema.optional(),
|
|
629
|
-
}),
|
|
630
|
-
},
|
|
631
|
-
async ({ inboxMessageId, agentId, taskDescription, offerMode }, requestInfo, _meta) => {
|
|
632
|
-
if (!requestInfo.agentId) {
|
|
633
|
-
return {
|
|
634
|
-
content: [{ type: "text", text: "Agent ID not found." }],
|
|
635
|
-
structuredContent: { success: false, message: "Agent ID not found." },
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
const leadAgent = getAgentById(requestInfo.agentId);
|
|
640
|
-
if (!leadAgent || !leadAgent.isLead) {
|
|
641
|
-
return {
|
|
642
|
-
content: [{ type: "text", text: "Only leads can delegate inbox messages." }],
|
|
643
|
-
structuredContent: { success: false, message: "Only leads can delegate inbox messages." },
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
const inboxMsg = getInboxMessageById(inboxMessageId);
|
|
648
|
-
if (!inboxMsg) {
|
|
649
|
-
return {
|
|
650
|
-
content: [{ type: "text", text: "Inbox message not found." }],
|
|
651
|
-
structuredContent: { success: false, message: "Inbox message not found." },
|
|
652
|
-
};
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
if (inboxMsg.agentId !== requestInfo.agentId) {
|
|
656
|
-
return {
|
|
657
|
-
content: [{ type: "text", text: "This inbox message is not yours." }],
|
|
658
|
-
structuredContent: { success: false, message: "This inbox message is not yours." },
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
const targetAgent = getAgentById(agentId);
|
|
663
|
-
if (!targetAgent) {
|
|
664
|
-
return {
|
|
665
|
-
content: [{ type: "text", text: "Target agent not found." }],
|
|
666
|
-
structuredContent: { success: false, message: "Target agent not found." },
|
|
667
|
-
};
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
if (targetAgent.isLead) {
|
|
671
|
-
return {
|
|
672
|
-
content: [{ type: "text", text: "Cannot delegate to another lead." }],
|
|
673
|
-
structuredContent: { success: false, message: "Cannot delegate to another lead." },
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
// Create task for the worker
|
|
678
|
-
const task = createTaskExtended(taskDescription || inboxMsg.content, {
|
|
679
|
-
agentId: offerMode ? undefined : agentId,
|
|
680
|
-
offeredTo: offerMode ? agentId : undefined,
|
|
681
|
-
creatorAgentId: requestInfo.agentId,
|
|
682
|
-
source: "slack",
|
|
683
|
-
slackChannelId: inboxMsg.slackChannelId,
|
|
684
|
-
slackThreadTs: inboxMsg.slackThreadTs,
|
|
685
|
-
slackUserId: inboxMsg.slackUserId,
|
|
686
|
-
});
|
|
687
|
-
|
|
688
|
-
// Mark inbox as delegated
|
|
689
|
-
markInboxMessageDelegated(inboxMessageId, task.id);
|
|
690
|
-
|
|
691
|
-
return {
|
|
692
|
-
content: [
|
|
693
|
-
{
|
|
694
|
-
type: "text",
|
|
695
|
-
text: `Delegated to ${targetAgent.name}. Task ID: ${task.id.slice(0, 8)}`,
|
|
696
|
-
},
|
|
697
|
-
],
|
|
698
|
-
structuredContent: {
|
|
699
|
-
success: true,
|
|
700
|
-
message: `Task created and ${offerMode ? "offered to" : "assigned to"} ${targetAgent.name}.`,
|
|
701
|
-
task,
|
|
702
|
-
},
|
|
703
|
-
};
|
|
704
|
-
},
|
|
705
|
-
);
|
|
706
|
-
};
|
|
707
|
-
```
|
|
708
|
-
|
|
709
|
-
### Success Criteria
|
|
710
|
-
|
|
711
|
-
#### Automated Verification
|
|
712
|
-
- [x] TypeScript compiles without errors
|
|
713
|
-
- [x] `bun test` passes
|
|
714
|
-
|
|
715
|
-
#### Manual Verification
|
|
716
|
-
- [ ] Lead can use `inbox-delegate` to create task for worker
|
|
717
|
-
- [ ] Task has Slack context preserved
|
|
718
|
-
- [ ] Worker completion sends response to original Slack thread
|
|
719
|
-
|
|
720
|
-
---
|
|
721
|
-
|
|
722
|
-
## Phase 6: Tool Registration and Prompts
|
|
723
|
-
|
|
724
|
-
### Overview
|
|
725
|
-
Register the new tools and update the lead prompt to emphasize delegation and answering.
|
|
726
|
-
|
|
727
|
-
### Changes Required
|
|
728
|
-
|
|
729
|
-
#### 1. Register New Tools
|
|
730
|
-
**File**: `src/server.ts`
|
|
731
|
-
**Changes**: Import and register slack-reply and inbox-delegate
|
|
732
|
-
|
|
733
|
-
Add imports:
|
|
734
|
-
```typescript
|
|
735
|
-
import { registerSlackReplyTool } from "./tools/slack-reply";
|
|
736
|
-
import { registerInboxDelegateTool } from "./tools/inbox-delegate";
|
|
737
|
-
```
|
|
738
|
-
|
|
739
|
-
Add registration after line 68 (after registerMyAgentInfoTool):
|
|
740
|
-
```typescript
|
|
741
|
-
// Slack integration tools (always registered, will no-op if Slack not configured)
|
|
742
|
-
registerSlackReplyTool(server);
|
|
743
|
-
registerInboxDelegateTool(server);
|
|
744
|
-
```
|
|
745
|
-
|
|
746
|
-
#### 2. Update Lead Prompt
|
|
747
|
-
**File**: `src/prompts/base-prompt.ts`
|
|
748
|
-
**Changes**: Replace `BASE_PROMPT_LEAD` constant
|
|
749
|
-
|
|
750
|
-
```typescript
|
|
751
|
-
const BASE_PROMPT_LEAD = `
|
|
752
|
-
As the lead agent, you are responsible for coordinating the activities of all worker agents in the swarm.
|
|
753
|
-
|
|
754
|
-
**IMPORTANT:** You do NOT perform worker tasks yourself. Your role is to:
|
|
755
|
-
1. Answer questions directly when you have the knowledge
|
|
756
|
-
2. Delegate tasks to appropriate workers
|
|
757
|
-
3. Monitor progress and ensure the swarm operates efficiently
|
|
758
|
-
4. Resolve conflicts and provide guidance
|
|
759
|
-
|
|
760
|
-
#### Slack Inbox
|
|
761
|
-
When Slack messages are routed to you, they appear as "inbox messages" - NOT tasks.
|
|
762
|
-
- Use \`slack-reply\` with the inboxMessageId to respond directly to the user
|
|
763
|
-
- Use \`inbox-delegate\` with the inboxMessageId and agentId to create a task for a worker
|
|
764
|
-
|
|
765
|
-
#### General monitor and control tools
|
|
766
|
-
|
|
767
|
-
- get-swarm: To get the list of all workers in the swarm along with their status.
|
|
768
|
-
- get-tasks: To get the list of all tasks assigned to workers.
|
|
769
|
-
- get-task-details: To get detailed information about a specific task.
|
|
770
|
-
|
|
771
|
-
#### Task delegation tools
|
|
772
|
-
|
|
773
|
-
- send-task: Assign a new task to a specific worker, or to the general pool.
|
|
774
|
-
- inbox-delegate: Delegate an inbox message to a worker (creates task with Slack context).
|
|
775
|
-
- slack-reply: Respond directly to a Slack thread.
|
|
776
|
-
- task-action: Manage tasks (accept, reject, etc.) - note: you should rarely need this.
|
|
777
|
-
- store-progress: Useful to track your own coordination notes or fix task issues.
|
|
778
|
-
`;
|
|
779
|
-
```
|
|
780
|
-
|
|
781
|
-
### Success Criteria
|
|
782
|
-
|
|
783
|
-
#### Automated Verification
|
|
784
|
-
- [x] `bun test` passes
|
|
785
|
-
- [x] TypeScript compiles without errors
|
|
786
|
-
- [x] Server starts: `bun run src/http.ts`
|
|
787
|
-
|
|
788
|
-
#### Manual Verification
|
|
789
|
-
- [ ] Lead agent receives updated prompt with inbox instructions
|
|
790
|
-
|
|
791
|
-
---
|
|
792
|
-
|
|
793
|
-
## Phase 7: Block Lead from poll-task (Optional Enhancement)
|
|
794
|
-
|
|
795
|
-
### Overview
|
|
796
|
-
Optionally restrict the `poll-task` tool to prevent leads from claiming tasks.
|
|
797
|
-
|
|
798
|
-
### Changes Required
|
|
799
|
-
|
|
800
|
-
#### 1. Add Lead Check to poll-task
|
|
801
|
-
**File**: `src/tools/poll-task.ts`
|
|
802
|
-
**Changes**: Add early return if agent is lead
|
|
803
|
-
|
|
804
|
-
Add at the start of the handler (after getting requestInfo):
|
|
805
|
-
|
|
806
|
-
```typescript
|
|
807
|
-
// Check if lead is trying to poll
|
|
808
|
-
const agent = getAgentById(requestInfo.agentId);
|
|
809
|
-
if (agent?.isLead) {
|
|
810
|
-
return {
|
|
811
|
-
content: [
|
|
812
|
-
{
|
|
813
|
-
type: "text",
|
|
814
|
-
text: "Lead agents should not poll for tasks. Use inbox tools to respond to Slack messages, or get-tasks to monitor workers.",
|
|
815
|
-
},
|
|
816
|
-
],
|
|
817
|
-
structuredContent: {
|
|
818
|
-
success: false,
|
|
819
|
-
message: "Lead agents use inbox and delegation tools instead of polling for tasks.",
|
|
820
|
-
offeredTasks: [],
|
|
821
|
-
availableCount: 0,
|
|
822
|
-
waitedForSeconds: 0,
|
|
823
|
-
},
|
|
824
|
-
};
|
|
825
|
-
}
|
|
826
|
-
```
|
|
827
|
-
|
|
828
|
-
### Success Criteria
|
|
829
|
-
|
|
830
|
-
#### Automated Verification
|
|
831
|
-
- [x] `bun test` passes
|
|
832
|
-
|
|
833
|
-
#### Manual Verification
|
|
834
|
-
- [ ] Lead calling `poll-task` gets helpful error message
|
|
835
|
-
|
|
836
|
-
---
|
|
837
|
-
|
|
838
|
-
## Testing Strategy
|
|
839
|
-
|
|
840
|
-
### Unit Tests
|
|
841
|
-
- Test `createInboxMessage`, `getUnreadInboxMessages`, etc.
|
|
842
|
-
- Test `slack-reply` tool validation
|
|
843
|
-
- Test `inbox-delegate` tool validation
|
|
844
|
-
|
|
845
|
-
### Integration Tests
|
|
846
|
-
- End-to-end: Slack message → inbox → slack-reply → Slack response
|
|
847
|
-
- End-to-end: Slack message → inbox → inbox-delegate → worker task → completion → Slack response
|
|
848
|
-
|
|
849
|
-
### Manual Testing Steps
|
|
850
|
-
1. Start MCP server: `bun run src/http.ts`
|
|
851
|
-
2. Connect Slack (ensure bot tokens configured)
|
|
852
|
-
3. Send `@agent-swarm help me with X` in Slack
|
|
853
|
-
4. Verify inbox message created (not task)
|
|
854
|
-
5. Poll as lead, verify `slack_inbox_message` trigger
|
|
855
|
-
6. Use `slack-reply` tool, verify Slack response
|
|
856
|
-
7. Use `inbox-delegate` tool, verify task created
|
|
857
|
-
8. Worker completes task, verify Slack thread gets response
|
|
858
|
-
|
|
859
|
-
## Performance Considerations
|
|
860
|
-
|
|
861
|
-
- Inbox messages are queried frequently (on every lead poll)
|
|
862
|
-
- Added indexes on `agentId` and `status` for efficient lookups
|
|
863
|
-
- Limited to 5 messages per poll to avoid large payloads
|
|
864
|
-
|
|
865
|
-
## Migration Notes
|
|
866
|
-
|
|
867
|
-
- No data migration needed - new table starts empty
|
|
868
|
-
- Existing tasks and Slack flows continue working for workers
|
|
869
|
-
- Lead behavior changes immediately on deployment
|
|
870
|
-
|
|
871
|
-
## References
|
|
872
|
-
|
|
873
|
-
- Existing Slack integration: `src/slack/handlers.ts`, `src/slack/responses.ts`
|
|
874
|
-
- Tool pattern: `src/tools/utils.ts`, `src/tools/send-task.ts`
|
|
875
|
-
- Polling logic: `src/http.ts:282-379`
|
|
876
|
-
- Lead prompt: `src/prompts/base-prompt.ts:11-30`
|