@desplega.ai/agent-swarm 1.20.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 +271 -169
- package/openapi.json +5015 -0
- package/package.json +40 -7
- package/plugin/commands/close-issue.md +7 -3
- package/plugin/commands/create-pr.md +18 -12
- package/plugin/commands/implement-issue.md +7 -3
- package/plugin/commands/respond-github.md +8 -4
- package/plugin/commands/review-pr.md +44 -10
- package/plugin/commands/start-leader.md +1 -3
- package/plugin/commands/start-worker.md +1 -3
- package/plugin/commands/work-on-task.md +22 -3
- package/plugin/pi-skills/close-issue/SKILL.md +90 -0
- package/plugin/pi-skills/create-pr/SKILL.md +99 -0
- package/plugin/pi-skills/implement-issue/SKILL.md +135 -0
- package/plugin/pi-skills/investigate-sentry-issue/SKILL.md +138 -0
- package/plugin/pi-skills/respond-github/SKILL.md +98 -0
- package/plugin/pi-skills/review-offered-task/SKILL.md +45 -0
- package/plugin/pi-skills/review-pr/SKILL.md +261 -0
- package/plugin/pi-skills/start-leader/SKILL.md +121 -0
- package/plugin/pi-skills/start-worker/SKILL.md +60 -0
- package/plugin/pi-skills/swarm-chat/SKILL.md +82 -0
- package/plugin/pi-skills/todos/SKILL.md +66 -0
- package/plugin/pi-skills/work-on-task/SKILL.md +65 -0
- package/plugin/skills/artifacts/examples/approval-flow.ts +34 -0
- package/plugin/skills/artifacts/examples/hono-dashboard.ts +31 -0
- package/plugin/skills/artifacts/examples/multi-artifact.ts +20 -0
- package/plugin/skills/artifacts/examples/static-report.sh +17 -0
- package/plugin/skills/artifacts/skill.md +71 -0
- package/src/agentmail/app.ts +65 -0
- package/src/agentmail/handlers.ts +262 -0
- package/src/agentmail/index.ts +9 -0
- package/src/agentmail/templates.ts +111 -0
- package/src/agentmail/types.ts +51 -0
- package/src/artifact-sdk/browser-sdk.ts +30 -0
- package/src/artifact-sdk/index.ts +2 -0
- package/src/artifact-sdk/localtunnel.d.ts +20 -0
- package/src/artifact-sdk/port.ts +12 -0
- package/src/artifact-sdk/server.ts +156 -0
- package/src/artifact-sdk/tunnel.ts +19 -0
- package/src/be/chunking.ts +193 -0
- package/src/be/db-queries/oauth.ts +90 -0
- package/src/be/db-queries/tracker.ts +182 -0
- package/src/be/db.ts +3327 -784
- package/src/be/embedding.ts +80 -0
- package/src/be/migrations/001_initial.sql +409 -0
- package/src/be/migrations/002_one_time_schedules.sql +59 -0
- package/src/be/migrations/003_workflows.sql +51 -0
- package/src/be/migrations/004_workflow_source.sql +81 -0
- package/src/be/migrations/005_epic_next_steps.sql +2 -0
- package/src/be/migrations/006_vcs_provider.sql +94 -0
- package/src/be/migrations/007_task_dir.sql +2 -0
- package/src/be/migrations/008_workflow_redesign.sql +85 -0
- package/src/be/migrations/009_tracker_integration.sql +144 -0
- package/src/be/migrations/010_step_diagnostics.sql +1 -0
- package/src/be/migrations/011_step_next_port.sql +1 -0
- package/src/be/migrations/012_trigger_schema.sql +1 -0
- package/src/be/migrations/013_task_output_schema.sql +2 -0
- 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/migrations/runner.ts +188 -0
- package/src/be/seed.ts +62 -0
- package/src/cli.tsx +231 -299
- package/src/commands/artifact.ts +241 -0
- package/src/commands/onboard/compose-generator.ts +169 -0
- package/src/commands/onboard/env-generator.ts +79 -0
- package/src/commands/onboard/manifest.ts +37 -0
- package/src/commands/onboard/presets.ts +85 -0
- package/src/commands/onboard/service-names.ts +47 -0
- package/src/commands/onboard/steps/core-credentials.tsx +111 -0
- package/src/commands/onboard/steps/custom-templates.tsx +168 -0
- package/src/commands/onboard/steps/generate.tsx +154 -0
- package/src/commands/onboard/steps/harness-credentials.tsx +195 -0
- package/src/commands/onboard/steps/harness.tsx +21 -0
- package/src/commands/onboard/steps/health-check.tsx +171 -0
- package/src/commands/onboard/steps/integration-github.tsx +105 -0
- package/src/commands/onboard/steps/integration-gitlab.tsx +79 -0
- package/src/commands/onboard/steps/integration-menu.tsx +58 -0
- package/src/commands/onboard/steps/integration-sentry.tsx +79 -0
- package/src/commands/onboard/steps/integration-slack.tsx +165 -0
- package/src/commands/onboard/steps/post-connect.tsx +145 -0
- package/src/commands/onboard/steps/post-dashboard.tsx +34 -0
- package/src/commands/onboard/steps/post-task.tsx +103 -0
- package/src/commands/onboard/steps/prereq-check.tsx +178 -0
- package/src/commands/onboard/steps/review.tsx +82 -0
- package/src/commands/onboard/steps/start.tsx +97 -0
- package/src/commands/onboard/templates.ts +34 -0
- package/src/commands/onboard/types.ts +259 -0
- package/src/commands/onboard.tsx +425 -0
- package/src/commands/runner.ts +1540 -630
- package/src/commands/setup.tsx +23 -38
- package/src/commands/shared/client-config.ts +41 -0
- package/src/commands/templates.ts +172 -0
- package/src/github/app.ts +8 -0
- package/src/github/handlers.ts +384 -151
- package/src/github/index.ts +1 -0
- 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/github/types.ts +1 -0
- package/src/gitlab/auth.ts +63 -0
- package/src/gitlab/handlers.ts +368 -0
- package/src/gitlab/index.ts +19 -0
- package/src/gitlab/reactions.ts +104 -0
- package/src/gitlab/templates.ts +140 -0
- package/src/gitlab/types.ts +130 -0
- package/src/heartbeat/heartbeat.ts +434 -0
- package/src/heartbeat/index.ts +1 -0
- package/src/heartbeat/templates.ts +30 -0
- package/src/hooks/hook.ts +555 -4
- package/src/hooks/tool-loop-detection.test.ts +158 -0
- package/src/hooks/tool-loop-detection.ts +167 -0
- package/src/http/active-sessions.ts +199 -0
- package/src/http/agents.ts +328 -0
- package/src/http/config.ts +191 -0
- package/src/http/core.ts +309 -0
- package/src/http/db-query.ts +91 -0
- package/src/http/ecosystem.ts +63 -0
- package/src/http/epics.ts +460 -0
- package/src/http/index.ts +216 -0
- package/src/http/mcp.ts +77 -0
- package/src/http/memory.ts +168 -0
- package/src/http/openapi.ts +109 -0
- package/src/http/poll.ts +299 -0
- package/src/http/prompt-templates.ts +412 -0
- package/src/http/repos.ts +195 -0
- package/src/http/route-def.ts +123 -0
- package/src/http/schedules.ts +426 -0
- package/src/http/session-data.ts +241 -0
- package/src/http/stats.ts +174 -0
- package/src/http/tasks.ts +468 -0
- package/src/http/trackers/index.ts +10 -0
- package/src/http/trackers/linear.ts +187 -0
- package/src/http/types.ts +12 -0
- package/src/http/utils.ts +87 -0
- package/src/http/webhooks.ts +432 -0
- package/src/http/workflows.ts +530 -0
- package/src/http.ts +1 -1890
- package/src/linear/README.md +65 -0
- package/src/linear/app.ts +48 -0
- package/src/linear/client.ts +18 -0
- package/src/linear/index.ts +1 -0
- package/src/linear/oauth.ts +35 -0
- package/src/linear/outbound.ts +212 -0
- package/src/linear/sync.ts +567 -0
- package/src/linear/templates.ts +47 -0
- package/src/linear/types.ts +7 -0
- package/src/linear/webhook.ts +104 -0
- package/src/oauth/README.md +66 -0
- package/src/oauth/index.ts +6 -0
- package/src/oauth/wrapper.ts +204 -0
- package/src/prompts/base-prompt.ts +150 -265
- package/src/prompts/defaults.ts +196 -0
- 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 +442 -0
- package/src/providers/index.ts +24 -0
- package/src/providers/pi-mono-adapter.ts +442 -0
- package/src/providers/pi-mono-extension.ts +624 -0
- package/src/providers/pi-mono-mcp-client.ts +124 -0
- package/src/providers/types.ts +75 -0
- package/src/scheduler/scheduler.test.ts +2 -0
- package/src/scheduler/scheduler.ts +231 -40
- package/src/server.ts +97 -6
- package/src/slack/HEURISTICS.md +105 -0
- package/src/slack/actions.ts +133 -0
- package/src/slack/app.ts +7 -0
- package/src/slack/assistant.ts +118 -0
- package/src/slack/blocks.ts +233 -0
- package/src/slack/channel-activity.ts +177 -0
- package/src/slack/commands.ts +31 -17
- package/src/slack/files.ts +1 -1
- package/src/slack/handlers.test.ts +114 -1
- package/src/slack/handlers.ts +230 -55
- package/src/slack/responses.ts +120 -67
- package/src/slack/router.ts +17 -99
- package/src/slack/templates.ts +55 -0
- package/src/slack/thread-buffer.ts +213 -0
- package/src/slack/watcher.ts +119 -4
- package/src/tests/agent-activity.test.ts +247 -0
- package/src/tests/agentmail-filters.test.ts +97 -0
- package/src/tests/artifact-sdk.test.ts +800 -0
- package/src/tests/base-prompt.test.ts +264 -0
- package/src/tests/build-pi-skills.test.ts +127 -0
- package/src/tests/channel-activity.test.ts +363 -0
- package/src/tests/claude-adapter.test.ts +126 -0
- package/src/tests/context-versioning.test.ts +425 -0
- package/src/tests/db-queries-oauth.test.ts +197 -0
- package/src/tests/db-queries-tracker.test.ts +230 -0
- package/src/tests/epics.test.ts +3 -3
- package/src/tests/error-tracker.test.ts +368 -0
- package/src/tests/fetch-resolved-env.test.ts +167 -0
- package/src/tests/generate-default-claude-md.test.ts +9 -1
- package/src/tests/generate-identity-templates.test.ts +124 -0
- package/src/tests/gitlab-auth.test.ts +109 -0
- package/src/tests/gitlab-handlers.test.ts +691 -0
- package/src/tests/gitlab-vcs-db.test.ts +177 -0
- package/src/tests/heartbeat.test.ts +364 -0
- package/src/tests/http-api-integration.test.ts +1698 -0
- package/src/tests/linear-outbound-sync.test.ts +200 -0
- package/src/tests/linear-webhook.test.ts +406 -0
- package/src/tests/match-route.test.ts +187 -0
- package/src/tests/memory.test.ts +737 -0
- package/src/tests/migration-runner-regressions.test.ts +86 -0
- package/src/tests/model-control.test.ts +338 -0
- package/src/tests/oauth-wrapper.test.ts +147 -0
- package/src/tests/onboard-compose.test.ts +138 -0
- package/src/tests/onboard-env.test.ts +174 -0
- package/src/tests/onboard-manifest.test.ts +137 -0
- package/src/tests/pi-mono-adapter.test.ts +234 -0
- package/src/tests/pool-session-logs.test.ts +199 -0
- package/src/tests/progress-dedup.test.ts +98 -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/provider-adapter.test.ts +122 -0
- package/src/tests/provider-command-format.test.ts +98 -0
- package/src/tests/reload-config.test.ts +170 -0
- package/src/tests/runner-polling-api.test.ts +25 -20
- package/src/tests/scheduled-tasks.test.ts +104 -0
- package/src/tests/scheduler-backoff.test.ts +166 -0
- package/src/tests/self-improvement.test.ts +541 -0
- package/src/tests/session-attach.test.ts +536 -0
- package/src/tests/session-costs.test.ts +267 -1
- package/src/tests/slack-actions.test.ts +133 -0
- package/src/tests/slack-assistant.test.ts +136 -0
- package/src/tests/slack-blocks.test.ts +246 -0
- package/src/tests/slack-metadata-inheritance.test.ts +243 -0
- package/src/tests/slack-queue-offline.test.ts +174 -0
- package/src/tests/slack-router.test.ts +181 -0
- package/src/tests/slack-thread-buffer.test.ts +305 -0
- package/src/tests/slack-thread-followups.test.ts +298 -0
- package/src/tests/slack-watcher.test.ts +101 -0
- package/src/tests/structured-output.test.ts +307 -0
- package/src/tests/swarm-repos.test.ts +198 -0
- package/src/tests/task-cancellation.test.ts +6 -4
- package/src/tests/task-working-dir.test.ts +176 -0
- package/src/tests/template-fetch.test.ts +490 -0
- package/src/tests/tool-annotations.test.ts +371 -0
- package/src/tests/tracker-tools.test.ts +184 -0
- package/src/tests/update-profile-agentid.test.ts +248 -0
- package/src/tests/update-profile-api.test.ts +143 -3
- package/src/tests/update-profile-auth.test.ts +195 -0
- package/src/tests/validation-adapters.test.ts +86 -0
- package/src/tests/vcs-provider.test.ts +27 -0
- package/src/tests/workflow-agent-task.test.ts +196 -0
- package/src/tests/workflow-async-v2.test.ts +508 -0
- package/src/tests/workflow-convergence.test.ts +541 -0
- package/src/tests/workflow-definition-validation.test.ts +366 -0
- package/src/tests/workflow-engine-v2.test.ts +691 -0
- package/src/tests/workflow-executors.test.ts +736 -0
- package/src/tests/workflow-http-v2.test.ts +599 -0
- package/src/tests/workflow-integration-io.test.ts +902 -0
- package/src/tests/workflow-io-schemas.test.ts +624 -0
- package/src/tests/workflow-registry.test.ts +592 -0
- package/src/tests/workflow-retry-v2.test.ts +401 -0
- package/src/tests/workflow-retry-validation.test.ts +282 -0
- package/src/tests/workflow-schedule-trigger.test.ts +104 -0
- package/src/tests/workflow-template.test.ts +288 -0
- package/src/tests/workflow-trigger-schema.test.ts +359 -0
- package/src/tests/workflow-triggers-v2.test.ts +264 -0
- package/src/tests/workflow-versions.test.ts +208 -0
- package/src/tests/workflow-workspace.test.ts +272 -0
- package/src/tests/x402-client.test.ts +117 -0
- package/src/tests/x402-config.test.ts +182 -0
- package/src/tests/x402-spending-tracker.test.ts +185 -0
- package/src/tools/cancel-task.ts +2 -0
- package/src/tools/context-diff.ts +171 -0
- package/src/tools/context-history.ts +138 -0
- package/src/tools/create-channel.ts +1 -0
- package/src/tools/db-query.ts +78 -0
- package/src/tools/delete-channel.ts +132 -0
- package/src/tools/epics/assign-task-to-epic.ts +1 -0
- package/src/tools/epics/create-epic.ts +3 -2
- package/src/tools/epics/delete-epic.ts +2 -0
- package/src/tools/epics/get-epic-details.ts +2 -0
- package/src/tools/epics/list-epics.ts +2 -0
- package/src/tools/epics/unassign-task-from-epic.ts +1 -0
- package/src/tools/epics/update-epic.ts +7 -4
- package/src/tools/get-swarm.ts +2 -0
- package/src/tools/get-task-details.ts +2 -0
- package/src/tools/get-tasks.ts +27 -1
- package/src/tools/inject-learning.ts +106 -0
- package/src/tools/join-swarm.ts +17 -7
- package/src/tools/list-channels.ts +2 -0
- package/src/tools/list-services.ts +2 -0
- package/src/tools/memory-get.ts +56 -0
- package/src/tools/memory-search.ts +131 -0
- package/src/tools/my-agent-info.ts +2 -0
- package/src/tools/poll-task.ts +2 -20
- package/src/tools/post-message.ts +1 -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/read-messages.ts +2 -0
- package/src/tools/register-agentmail-inbox.ts +166 -0
- package/src/tools/register-service.ts +2 -0
- package/src/tools/schedules/create-schedule.ts +134 -24
- package/src/tools/schedules/delete-schedule.ts +2 -0
- package/src/tools/schedules/list-schedules.ts +20 -4
- package/src/tools/schedules/run-schedule-now.ts +1 -0
- package/src/tools/schedules/update-schedule.ts +49 -17
- package/src/tools/send-task.ts +132 -10
- package/src/tools/slack-download-file.ts +4 -2
- package/src/tools/slack-list-channels.ts +2 -0
- package/src/tools/slack-post.ts +2 -0
- package/src/tools/slack-read.ts +2 -0
- package/src/tools/slack-reply.ts +2 -0
- package/src/tools/slack-upload-file.ts +2 -0
- package/src/tools/store-progress.ts +205 -4
- package/src/tools/swarm-config/delete-config.ts +87 -0
- package/src/tools/swarm-config/get-config.ts +108 -0
- package/src/tools/swarm-config/index.ts +4 -0
- package/src/tools/swarm-config/list-config.ts +99 -0
- package/src/tools/swarm-config/set-config.ts +118 -0
- package/src/tools/task-action.ts +50 -5
- package/src/tools/task-dedup.ts +97 -0
- package/src/tools/templates.ts +53 -0
- package/src/tools/tool-config.ts +124 -0
- package/src/tools/tracker/index.ts +6 -0
- package/src/tools/tracker/tracker-link-epic.ts +64 -0
- package/src/tools/tracker/tracker-link-task.ts +64 -0
- package/src/tools/tracker/tracker-map-agent.ts +57 -0
- package/src/tools/tracker/tracker-status.ts +56 -0
- package/src/tools/tracker/tracker-sync-status.ts +42 -0
- package/src/tools/tracker/tracker-unlink.ts +41 -0
- package/src/tools/unregister-service.ts +2 -0
- package/src/tools/update-profile.ts +172 -17
- package/src/tools/update-service-status.ts +2 -0
- package/src/tools/utils.ts +10 -1
- package/src/tools/workflows/create-workflow.ts +129 -0
- package/src/tools/workflows/delete-workflow.ts +42 -0
- package/src/tools/workflows/get-workflow-run.ts +59 -0
- package/src/tools/workflows/get-workflow.ts +53 -0
- package/src/tools/workflows/index.ts +9 -0
- package/src/tools/workflows/list-workflow-runs.ts +48 -0
- package/src/tools/workflows/list-workflows.ts +42 -0
- package/src/tools/workflows/retry-workflow-run.ts +40 -0
- package/src/tools/workflows/trigger-workflow.ts +96 -0
- package/src/tools/workflows/update-workflow.ts +133 -0
- package/src/tracker/types.ts +51 -0
- package/src/types.ts +530 -14
- package/src/utils/credentials.test.ts +156 -0
- package/src/utils/credentials.ts +50 -0
- package/src/utils/error-tracker.ts +190 -0
- package/src/vcs/index.ts +15 -0
- package/src/vcs/types.ts +5 -0
- package/src/workflows/checkpoint.ts +121 -0
- package/src/workflows/cooldown.ts +28 -0
- package/src/workflows/definition.ts +235 -0
- package/src/workflows/engine.ts +580 -0
- package/src/workflows/event-bus.ts +29 -0
- package/src/workflows/executors/agent-task.ts +103 -0
- package/src/workflows/executors/base.ts +86 -0
- package/src/workflows/executors/code-match.ts +88 -0
- package/src/workflows/executors/index.ts +16 -0
- package/src/workflows/executors/notify.ts +93 -0
- package/src/workflows/executors/property-match.ts +104 -0
- package/src/workflows/executors/raw-llm.ts +83 -0
- package/src/workflows/executors/registry.ts +76 -0
- package/src/workflows/executors/script.ts +103 -0
- package/src/workflows/executors/validate.ts +215 -0
- package/src/workflows/executors/vcs.ts +58 -0
- package/src/workflows/index.ts +61 -0
- package/src/workflows/input.ts +46 -0
- package/src/workflows/json-schema-validator.ts +118 -0
- package/src/workflows/recovery.ts +139 -0
- package/src/workflows/resume.ts +229 -0
- package/src/workflows/retry-poller.ts +216 -0
- package/src/workflows/template.ts +74 -0
- package/src/workflows/templates.ts +86 -0
- package/src/workflows/triggers.ts +124 -0
- package/src/workflows/validation.ts +104 -0
- package/src/workflows/version.ts +44 -0
- package/src/x402/cli.ts +140 -0
- package/src/x402/client.ts +192 -0
- package/src/x402/config.ts +131 -0
- package/src/x402/index.ts +37 -0
- package/src/x402/openfort-signer.ts +83 -0
- package/src/x402/spending-tracker.ts +109 -0
- package/templates/official/coder/CLAUDE.md +49 -0
- package/templates/official/coder/IDENTITY.md +28 -0
- package/templates/official/coder/SOUL.md +43 -0
- package/templates/official/coder/TOOLS.md +40 -0
- package/templates/official/coder/config.json +23 -0
- package/templates/official/coder/start-up.sh +23 -0
- package/templates/official/content-reviewer/CLAUDE.md +68 -0
- package/templates/official/content-reviewer/IDENTITY.md +28 -0
- package/templates/official/content-reviewer/SOUL.md +44 -0
- package/templates/official/content-reviewer/TOOLS.md +37 -0
- package/templates/official/content-reviewer/config.json +23 -0
- package/templates/official/content-reviewer/start-up.sh +23 -0
- package/templates/official/content-strategist/CLAUDE.md +63 -0
- package/templates/official/content-strategist/IDENTITY.md +33 -0
- package/templates/official/content-strategist/SOUL.md +48 -0
- package/templates/official/content-strategist/TOOLS.md +47 -0
- package/templates/official/content-strategist/config.json +23 -0
- package/templates/official/content-strategist/start-up.sh +23 -0
- package/templates/official/content-writer/CLAUDE.md +72 -0
- package/templates/official/content-writer/IDENTITY.md +30 -0
- package/templates/official/content-writer/SOUL.md +46 -0
- package/templates/official/content-writer/TOOLS.md +44 -0
- package/templates/official/content-writer/config.json +23 -0
- package/templates/official/content-writer/start-up.sh +23 -0
- package/templates/official/forward-deployed-engineer/CLAUDE.md +54 -0
- package/templates/official/forward-deployed-engineer/IDENTITY.md +37 -0
- package/templates/official/forward-deployed-engineer/SOUL.md +55 -0
- package/templates/official/forward-deployed-engineer/config.json +21 -0
- package/templates/official/lead/CLAUDE.md +33 -0
- package/templates/official/lead/IDENTITY.md +36 -0
- package/templates/official/lead/SOUL.md +51 -0
- package/templates/official/lead/config.json +22 -0
- package/templates/official/researcher/CLAUDE.md +46 -0
- package/templates/official/researcher/IDENTITY.md +28 -0
- package/templates/official/researcher/SOUL.md +43 -0
- package/templates/official/researcher/config.json +21 -0
- package/templates/official/reviewer/CLAUDE.md +63 -0
- package/templates/official/reviewer/IDENTITY.md +28 -0
- package/templates/official/reviewer/SOUL.md +45 -0
- package/templates/official/reviewer/config.json +21 -0
- package/templates/official/tester/CLAUDE.md +53 -0
- package/templates/official/tester/IDENTITY.md +28 -0
- package/templates/official/tester/SOUL.md +55 -0
- package/templates/official/tester/config.json +21 -0
- package/templates/schema.ts +35 -0
- package/.claude/settings.local.json +0 -115
- package/.dockerignore +0 -61
- package/.editorconfig +0 -15
- package/.env.docker.example +0 -39
- package/.env.example +0 -40
- package/.github/workflows/ci.yml +0 -76
- package/.github/workflows/docker-and-deploy.yml +0 -117
- package/.wts-config.json +0 -4
- package/.wts-setup.ts +0 -102
- package/CLAUDE.md +0 -104
- package/CONTRIBUTING.md +0 -270
- package/DEPLOYMENT.md +0 -605
- package/Dockerfile +0 -57
- package/Dockerfile.worker +0 -157
- package/FAQ.md +0 -19
- package/MCP.md +0 -406
- package/UI.md +0 -40
- 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/docker-compose.example.yml +0 -159
- package/docker-entrypoint.sh +0 -352
- package/ecosystem.config.cjs +0 -66
- package/plugin/README.md +0 -1
- package/plugin/hooks/hooks.json +0 -71
- package/pyproject.toml +0 -9
- package/scripts/generate-mcp-docs.ts +0 -415
- package/slack-manifest.json +0 -71
- package/src/tests/get-inbox-message.test.ts +0 -145
- package/src/tools/get-inbox-message.ts +0 -89
- package/src/tools/inbox-delegate.ts +0 -113
- 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/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/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/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/tsconfig.json +0 -37
- package/ui/CLAUDE.md +0 -49
- package/ui/bun.lock +0 -771
- package/ui/index.html +0 -22
- package/ui/package-lock.json +0 -5290
- package/ui/package.json +0 -33
- package/ui/pnpm-lock.yaml +0 -3341
- package/ui/postcss.config.js +0 -6
- package/ui/public/logo.png +0 -0
- package/ui/src/App.tsx +0 -63
- package/ui/src/components/ActivityFeed.tsx +0 -440
- package/ui/src/components/AgentDetailPanel.tsx +0 -733
- package/ui/src/components/AgentsPanel.tsx +0 -815
- package/ui/src/components/ChatPanel.tsx +0 -1920
- package/ui/src/components/ConfigModal.tsx +0 -253
- package/ui/src/components/Dashboard.tsx +0 -832
- package/ui/src/components/EditAgentProfileModal.tsx +0 -433
- package/ui/src/components/EpicDetailPage.tsx +0 -741
- package/ui/src/components/EpicsPanel.tsx +0 -566
- package/ui/src/components/Header.tsx +0 -160
- package/ui/src/components/JsonViewer.tsx +0 -171
- package/ui/src/components/ScheduledTaskDetailPanel.tsx +0 -517
- package/ui/src/components/ScheduledTasksPanel.tsx +0 -639
- package/ui/src/components/ServicesPanel.tsx +0 -622
- package/ui/src/components/SessionLogPanel.tsx +0 -1219
- package/ui/src/components/StatsBar.tsx +0 -321
- package/ui/src/components/StatusBadge.tsx +0 -168
- package/ui/src/components/TaskDetailPanel.tsx +0 -903
- package/ui/src/components/TasksPanel.tsx +0 -614
- package/ui/src/components/UsageCharts.tsx +0 -216
- package/ui/src/components/UsageTab.tsx +0 -394
- package/ui/src/hooks/queries.ts +0 -353
- package/ui/src/hooks/useAutoScroll.ts +0 -83
- package/ui/src/index.css +0 -257
- package/ui/src/lib/api.ts +0 -268
- package/ui/src/lib/config.ts +0 -35
- package/ui/src/lib/contentPreview.ts +0 -208
- package/ui/src/lib/theme.ts +0 -214
- package/ui/src/lib/utils.ts +0 -88
- package/ui/src/main.tsx +0 -28
- package/ui/src/types/api.ts +0 -323
- package/ui/src/vite-env.d.ts +0 -1
- package/ui/tailwind.config.js +0 -37
- package/ui/tsconfig.json +0 -31
- package/ui/vite.config.ts +0 -35
- /package/{thoughts/shared/plans → templates/community}/.gitkeep +0 -0
package/src/server.ts
CHANGED
|
@@ -2,7 +2,11 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2
2
|
import pkg from "../package.json";
|
|
3
3
|
import { initDb } from "./be/db";
|
|
4
4
|
import { registerCancelTaskTool } from "./tools/cancel-task";
|
|
5
|
+
import { registerContextDiffTool } from "./tools/context-diff";
|
|
6
|
+
import { registerContextHistoryTool } from "./tools/context-history";
|
|
5
7
|
import { registerCreateChannelTool } from "./tools/create-channel";
|
|
8
|
+
import { registerDbQueryTool } from "./tools/db-query";
|
|
9
|
+
import { registerDeleteChannelTool } from "./tools/delete-channel";
|
|
6
10
|
// Epics capability
|
|
7
11
|
import {
|
|
8
12
|
registerAssignTaskToEpicTool,
|
|
@@ -13,20 +17,30 @@ import {
|
|
|
13
17
|
registerUnassignTaskFromEpicTool,
|
|
14
18
|
registerUpdateEpicTool,
|
|
15
19
|
} from "./tools/epics";
|
|
16
|
-
// Lead inbox tools
|
|
17
|
-
import { registerGetInboxMessageTool } from "./tools/get-inbox-message";
|
|
18
20
|
import { registerGetSwarmTool } from "./tools/get-swarm";
|
|
19
21
|
import { registerGetTaskDetailsTool } from "./tools/get-task-details";
|
|
20
22
|
import { registerGetTasksTool } from "./tools/get-tasks";
|
|
21
|
-
import {
|
|
23
|
+
import { registerInjectLearningTool } from "./tools/inject-learning";
|
|
22
24
|
import { registerJoinSwarmTool } from "./tools/join-swarm";
|
|
23
25
|
// Messaging capability
|
|
24
26
|
import { registerListChannelsTool } from "./tools/list-channels";
|
|
25
27
|
import { registerListServicesTool } from "./tools/list-services";
|
|
28
|
+
// Memory capability
|
|
29
|
+
import { registerMemoryGetTool } from "./tools/memory-get";
|
|
30
|
+
import { registerMemorySearchTool } from "./tools/memory-search";
|
|
26
31
|
import { registerMyAgentInfoTool } from "./tools/my-agent-info";
|
|
27
32
|
import { registerPollTaskTool } from "./tools/poll-task";
|
|
28
33
|
import { registerPostMessageTool } from "./tools/post-message";
|
|
34
|
+
// Prompt template tools
|
|
35
|
+
import {
|
|
36
|
+
registerDeletePromptTemplateTool,
|
|
37
|
+
registerGetPromptTemplateTool,
|
|
38
|
+
registerListPromptTemplatesTool,
|
|
39
|
+
registerPreviewPromptTemplateTool,
|
|
40
|
+
registerSetPromptTemplateTool,
|
|
41
|
+
} from "./tools/prompt-templates";
|
|
29
42
|
import { registerReadMessagesTool } from "./tools/read-messages";
|
|
43
|
+
import { registerRegisterAgentMailInboxTool } from "./tools/register-agentmail-inbox";
|
|
30
44
|
// Services capability
|
|
31
45
|
import { registerRegisterServiceTool } from "./tools/register-service";
|
|
32
46
|
// Scheduling capability
|
|
@@ -45,16 +59,45 @@ import { registerSlackReadTool } from "./tools/slack-read";
|
|
|
45
59
|
import { registerSlackReplyTool } from "./tools/slack-reply";
|
|
46
60
|
import { registerSlackUploadFileTool } from "./tools/slack-upload-file";
|
|
47
61
|
import { registerStoreProgressTool } from "./tools/store-progress";
|
|
62
|
+
// Swarm config tools
|
|
63
|
+
import {
|
|
64
|
+
registerDeleteConfigTool,
|
|
65
|
+
registerGetConfigTool,
|
|
66
|
+
registerListConfigTool,
|
|
67
|
+
registerSetConfigTool,
|
|
68
|
+
} from "./tools/swarm-config";
|
|
48
69
|
// Task pool capability
|
|
49
70
|
import { registerTaskActionTool } from "./tools/task-action";
|
|
71
|
+
// Tracker capability
|
|
72
|
+
import {
|
|
73
|
+
registerTrackerLinkEpicTool,
|
|
74
|
+
registerTrackerLinkTaskTool,
|
|
75
|
+
registerTrackerMapAgentTool,
|
|
76
|
+
registerTrackerStatusTool,
|
|
77
|
+
registerTrackerSyncStatusTool,
|
|
78
|
+
registerTrackerUnlinkTool,
|
|
79
|
+
} from "./tools/tracker";
|
|
50
80
|
import { registerUnregisterServiceTool } from "./tools/unregister-service";
|
|
51
81
|
// Profiles capability
|
|
52
82
|
import { registerUpdateProfileTool } from "./tools/update-profile";
|
|
53
83
|
import { registerUpdateServiceStatusTool } from "./tools/update-service-status";
|
|
84
|
+
// Workflows capability
|
|
85
|
+
import {
|
|
86
|
+
registerCreateWorkflowTool,
|
|
87
|
+
registerDeleteWorkflowTool,
|
|
88
|
+
registerGetWorkflowRunTool,
|
|
89
|
+
registerGetWorkflowTool,
|
|
90
|
+
registerListWorkflowRunsTool,
|
|
91
|
+
registerListWorkflowsTool,
|
|
92
|
+
registerRetryWorkflowRunTool,
|
|
93
|
+
registerTriggerWorkflowTool,
|
|
94
|
+
registerUpdateWorkflowTool,
|
|
95
|
+
} from "./tools/workflows";
|
|
54
96
|
|
|
55
97
|
// Capability-based feature flags
|
|
56
98
|
// Default: all capabilities enabled
|
|
57
|
-
const DEFAULT_CAPABILITIES =
|
|
99
|
+
const DEFAULT_CAPABILITIES =
|
|
100
|
+
"core,task-pool,messaging,profiles,services,scheduling,epics,memory,workflows";
|
|
58
101
|
const CAPABILITIES = new Set(
|
|
59
102
|
(process.env.CAPABILITIES || DEFAULT_CAPABILITIES).split(",").map((s) => s.trim()),
|
|
60
103
|
);
|
|
@@ -96,6 +139,22 @@ export function createServer() {
|
|
|
96
139
|
registerMyAgentInfoTool(server);
|
|
97
140
|
registerCancelTaskTool(server);
|
|
98
141
|
|
|
142
|
+
// Debug tools - always registered (self-guards with lead check)
|
|
143
|
+
registerDbQueryTool(server);
|
|
144
|
+
|
|
145
|
+
// Swarm config tools - always registered (config management is fundamental)
|
|
146
|
+
registerSetConfigTool(server);
|
|
147
|
+
registerGetConfigTool(server);
|
|
148
|
+
registerListConfigTool(server);
|
|
149
|
+
registerDeleteConfigTool(server);
|
|
150
|
+
|
|
151
|
+
// Prompt template tools - always registered (prompt management is fundamental)
|
|
152
|
+
registerListPromptTemplatesTool(server);
|
|
153
|
+
registerGetPromptTemplateTool(server);
|
|
154
|
+
registerSetPromptTemplateTool(server);
|
|
155
|
+
registerDeletePromptTemplateTool(server);
|
|
156
|
+
registerPreviewPromptTemplateTool(server);
|
|
157
|
+
|
|
99
158
|
// Slack integration tools (always registered, will no-op if Slack not configured)
|
|
100
159
|
registerSlackReplyTool(server);
|
|
101
160
|
registerSlackReadTool(server);
|
|
@@ -103,8 +162,9 @@ export function createServer() {
|
|
|
103
162
|
registerSlackListChannelsTool(server);
|
|
104
163
|
registerSlackUploadFileTool(server);
|
|
105
164
|
registerSlackDownloadFileTool(server);
|
|
106
|
-
|
|
107
|
-
|
|
165
|
+
|
|
166
|
+
// AgentMail integration tool (always registered, self-service inbox mapping)
|
|
167
|
+
registerRegisterAgentMailInboxTool(server);
|
|
108
168
|
|
|
109
169
|
// Task pool capability - task pool operations (create unassigned, claim, release, accept, reject)
|
|
110
170
|
if (hasCapability("task-pool")) {
|
|
@@ -115,6 +175,7 @@ export function createServer() {
|
|
|
115
175
|
if (hasCapability("messaging")) {
|
|
116
176
|
registerListChannelsTool(server);
|
|
117
177
|
registerCreateChannelTool(server);
|
|
178
|
+
registerDeleteChannelTool(server);
|
|
118
179
|
registerPostMessageTool(server);
|
|
119
180
|
registerReadMessagesTool(server);
|
|
120
181
|
}
|
|
@@ -122,6 +183,8 @@ export function createServer() {
|
|
|
122
183
|
// Profiles capability - agent profile management
|
|
123
184
|
if (hasCapability("profiles")) {
|
|
124
185
|
registerUpdateProfileTool(server);
|
|
186
|
+
registerContextHistoryTool(server);
|
|
187
|
+
registerContextDiffTool(server);
|
|
125
188
|
}
|
|
126
189
|
|
|
127
190
|
// Services capability - PM2/background service registry
|
|
@@ -152,5 +215,33 @@ export function createServer() {
|
|
|
152
215
|
registerUnassignTaskFromEpicTool(server);
|
|
153
216
|
}
|
|
154
217
|
|
|
218
|
+
// Memory capability - persistent memory with vector search
|
|
219
|
+
if (hasCapability("memory")) {
|
|
220
|
+
registerMemorySearchTool(server);
|
|
221
|
+
registerMemoryGetTool(server);
|
|
222
|
+
registerInjectLearningTool(server);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Tracker capability - external issue tracker integration
|
|
226
|
+
registerTrackerStatusTool(server);
|
|
227
|
+
registerTrackerLinkTaskTool(server);
|
|
228
|
+
registerTrackerLinkEpicTool(server);
|
|
229
|
+
registerTrackerUnlinkTool(server);
|
|
230
|
+
registerTrackerSyncStatusTool(server);
|
|
231
|
+
registerTrackerMapAgentTool(server);
|
|
232
|
+
|
|
233
|
+
// Workflows capability - DAG-based automation workflows
|
|
234
|
+
if (hasCapability("workflows")) {
|
|
235
|
+
registerCreateWorkflowTool(server);
|
|
236
|
+
registerListWorkflowsTool(server);
|
|
237
|
+
registerGetWorkflowTool(server);
|
|
238
|
+
registerUpdateWorkflowTool(server);
|
|
239
|
+
registerDeleteWorkflowTool(server);
|
|
240
|
+
registerTriggerWorkflowTool(server);
|
|
241
|
+
registerListWorkflowRunsTool(server);
|
|
242
|
+
registerGetWorkflowRunTool(server);
|
|
243
|
+
registerRetryWorkflowRunTool(server);
|
|
244
|
+
}
|
|
245
|
+
|
|
155
246
|
return server;
|
|
156
247
|
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Slack Routing & Buffering Heuristics
|
|
2
|
+
|
|
3
|
+
This document covers all heuristics used by the Slack integration for message routing, buffering, and task creation.
|
|
4
|
+
|
|
5
|
+
## Thread Follow-up Routing
|
|
6
|
+
|
|
7
|
+
When someone @mentions the bot in a thread, the router checks whether a worker agent is already active in that thread before falling back to the lead agent.
|
|
8
|
+
|
|
9
|
+
**Routing priority (in order):**
|
|
10
|
+
|
|
11
|
+
1. `swarm#<uuid>` — explicit agent targeting (always wins)
|
|
12
|
+
2. `swarm#all` — broadcast to all workers
|
|
13
|
+
3. **Thread follow-up** — if in a thread and a worker is actively working there, route to that worker
|
|
14
|
+
4. **Lead fallback** — if the bot was @mentioned and no other match, route to lead agent
|
|
15
|
+
|
|
16
|
+
**Thread follow-up conditions:**
|
|
17
|
+
- Message must be in a thread (`thread_ts` present)
|
|
18
|
+
- An agent must have an active task (`in_progress` or `pending`) linked to that thread via `slackChannelId` + `slackThreadTs`
|
|
19
|
+
- The matched agent must not be `offline`
|
|
20
|
+
|
|
21
|
+
**Why this matters:** Without thread follow-up routing, every @mention in a thread goes to the lead, who then has to re-delegate. This shortcut sends the message directly to the worker already handling that conversation.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Additive Slack Buffer
|
|
26
|
+
|
|
27
|
+
**Feature flag:** `ADDITIVE_SLACK=true` (disabled by default)
|
|
28
|
+
|
|
29
|
+
When enabled, thread replies that do NOT @mention the bot are captured, buffered, and batched into a single follow-up task. This allows humans to give multi-message feedback in a thread without needing to @mention the bot each time.
|
|
30
|
+
|
|
31
|
+
### How it works
|
|
32
|
+
|
|
33
|
+
1. A human sends a non-@mention message in a thread where the swarm is already active (has existing tasks)
|
|
34
|
+
2. The message enters an in-memory buffer keyed by `channelId:threadTs`
|
|
35
|
+
3. A debounce timer starts (default 10 seconds)
|
|
36
|
+
4. Additional messages within the window are appended to the buffer, resetting the timer each time
|
|
37
|
+
5. When the timer expires, all buffered messages are flushed into a single task
|
|
38
|
+
|
|
39
|
+
### Buffer flush behavior
|
|
40
|
+
|
|
41
|
+
- All buffered messages are concatenated with `---` separators
|
|
42
|
+
- The task is created as `pending` status
|
|
43
|
+
- If there is an active task in the thread, the new task gets `dependsOn` set to it (dependency chaining)
|
|
44
|
+
- If there is no active task, the new task has no dependency and is immediately pickable
|
|
45
|
+
|
|
46
|
+
### Important: Initial @mentions are never buffered
|
|
47
|
+
|
|
48
|
+
The first @mention in a thread always creates a task instantly. Only subsequent non-mention replies enter the buffer. This ensures responsiveness for explicit requests.
|
|
49
|
+
|
|
50
|
+
### In-memory tradeoffs
|
|
51
|
+
|
|
52
|
+
- Buffer is lost on server restart (acceptable since the 10s window is tiny)
|
|
53
|
+
- No persistence across process restarts
|
|
54
|
+
- Single-process only (no clustering support)
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## `!now` Command
|
|
59
|
+
|
|
60
|
+
**Syntax:** `/now [optional message]`
|
|
61
|
+
|
|
62
|
+
Used inside a thread with an active buffer to flush immediately, bypassing the debounce timer and dependency chain.
|
|
63
|
+
|
|
64
|
+
**Behavior:**
|
|
65
|
+
- If text follows `!now`, it is appended to the buffer before flushing
|
|
66
|
+
- The buffer is flushed with `immediate=true`, meaning **no `dependsOn`** is set
|
|
67
|
+
- The resulting task is immediately pickable by any available agent
|
|
68
|
+
- Works only when `ADDITIVE_SLACK=true` and in a thread with swarm activity
|
|
69
|
+
|
|
70
|
+
**Use case:** When you have been adding context to a thread and want the swarm to pick it up right now, rather than waiting for the debounce or for the current task to finish.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Dependency Chaining
|
|
75
|
+
|
|
76
|
+
When the additive buffer flushes normally (not via `!now`), the created task uses `dependsOn` to chain to the latest active task in the thread.
|
|
77
|
+
|
|
78
|
+
**Query:** Finds the most recent `in_progress` or `pending` task matching the thread's `slackChannelId` + `slackThreadTs`, ordered by `createdAt DESC`.
|
|
79
|
+
|
|
80
|
+
**Effect:** The follow-up task stays in `pending` until the depended-on task completes. This prevents workers from picking up follow-up context before the original task is done.
|
|
81
|
+
|
|
82
|
+
**`!now` override:** Using `!now` creates the task without any `dependsOn`, making it immediately available regardless of other active tasks.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Feature Flags
|
|
87
|
+
|
|
88
|
+
| Flag | Default | Description |
|
|
89
|
+
|------|---------|-------------|
|
|
90
|
+
| `ADDITIVE_SLACK` | `false` | Enables non-mention thread message buffering and batching |
|
|
91
|
+
| `ADDITIVE_SLACK_BUFFER_MS` | `10000` (10s) | Debounce window in milliseconds for the thread buffer |
|
|
92
|
+
|
|
93
|
+
Both are read from environment variables. `ADDITIVE_SLACK` must be exactly `"true"` to enable. `ADDITIVE_SLACK_BUFFER_MS` is parsed as a number with fallback to 10000.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Feedback Reactions Reference
|
|
98
|
+
|
|
99
|
+
| Event | Slack Feedback | Description |
|
|
100
|
+
|-------|---------------|-------------|
|
|
101
|
+
| First non-mention message buffered | :eyes: reaction | Acknowledges the message was captured |
|
|
102
|
+
| Additional message appended to buffer | :heavy_plus_sign: reaction | Indicates the message was added to existing buffer |
|
|
103
|
+
| `!now` command used | :zap: reaction | Confirms instant flush was triggered |
|
|
104
|
+
| Buffer flushed (with dependency) | :satellite: thread message | "N follow-up message(s) queued pending completion of current task" |
|
|
105
|
+
| Buffer flushed (no dependency / `!now`) | :satellite: thread message | "N follow-up message(s) batched into task" |
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { App } from "@slack/bolt";
|
|
2
|
+
import { cancelTask, createTaskExtended, getAgentById, getLeadAgent, getTaskById } from "../be/db";
|
|
3
|
+
import { buildCancelledBlocks, getTaskLink } from "./blocks";
|
|
4
|
+
|
|
5
|
+
export function registerActionHandlers(app: App): void {
|
|
6
|
+
// "View Full Logs" — URL button, just ack (Slack opens the link automatically)
|
|
7
|
+
app.action("view_task_logs", async ({ ack }) => {
|
|
8
|
+
await ack();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// "Follow-up" — open a modal to send a follow-up message to the same agent
|
|
12
|
+
app.action("follow_up_task", async ({ ack, action, body, client }) => {
|
|
13
|
+
await ack();
|
|
14
|
+
|
|
15
|
+
if (action.type !== "button") return;
|
|
16
|
+
const taskId = action.value;
|
|
17
|
+
if (!taskId) return;
|
|
18
|
+
|
|
19
|
+
const triggerId = "trigger_id" in body ? body.trigger_id : undefined;
|
|
20
|
+
if (!triggerId) return;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
await client.views.open({
|
|
24
|
+
trigger_id: triggerId,
|
|
25
|
+
view: {
|
|
26
|
+
type: "modal",
|
|
27
|
+
callback_id: "follow_up_submit",
|
|
28
|
+
private_metadata: taskId,
|
|
29
|
+
title: { type: "plain_text", text: "Follow-up" },
|
|
30
|
+
submit: { type: "plain_text", text: "Send" },
|
|
31
|
+
close: { type: "plain_text", text: "Cancel" },
|
|
32
|
+
blocks: [
|
|
33
|
+
{
|
|
34
|
+
type: "input",
|
|
35
|
+
block_id: "follow_up_input",
|
|
36
|
+
label: { type: "plain_text", text: "Follow-up message" },
|
|
37
|
+
element: {
|
|
38
|
+
type: "plain_text_input",
|
|
39
|
+
action_id: "follow_up_text",
|
|
40
|
+
multiline: true,
|
|
41
|
+
placeholder: {
|
|
42
|
+
type: "plain_text",
|
|
43
|
+
text: "What would you like the agent to do next?",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error("[Slack] Failed to open follow-up modal:", error);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Handle follow-up modal submission
|
|
56
|
+
app.view("follow_up_submit", async ({ ack, view, body, client }) => {
|
|
57
|
+
await ack();
|
|
58
|
+
|
|
59
|
+
const taskId = view.private_metadata;
|
|
60
|
+
const followUpText = view.state.values.follow_up_input?.follow_up_text?.value || "";
|
|
61
|
+
|
|
62
|
+
if (!taskId || !followUpText) return;
|
|
63
|
+
|
|
64
|
+
const originalTask = getTaskById(taskId);
|
|
65
|
+
if (!originalTask || !originalTask.slackChannelId) return;
|
|
66
|
+
|
|
67
|
+
const lead = getLeadAgent();
|
|
68
|
+
const followUpTask = createTaskExtended(followUpText, {
|
|
69
|
+
agentId: lead?.id,
|
|
70
|
+
source: "slack",
|
|
71
|
+
parentTaskId: taskId,
|
|
72
|
+
slackChannelId: originalTask.slackChannelId,
|
|
73
|
+
slackThreadTs: originalTask.slackThreadTs,
|
|
74
|
+
slackUserId: body.user.id,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const taskLink = getTaskLink(followUpTask.id);
|
|
78
|
+
const agentName = lead ? lead.name : "queue";
|
|
79
|
+
const threadTs = originalTask.slackThreadTs;
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
await client.chat.postMessage({
|
|
83
|
+
channel: originalTask.slackChannelId,
|
|
84
|
+
thread_ts: threadTs,
|
|
85
|
+
text: `💬 Follow-up sent to *${agentName}* (${taskLink})`,
|
|
86
|
+
});
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error("[Slack] Failed to post follow-up confirmation:", error);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// "Cancel" — cancel the task and update the message
|
|
93
|
+
app.action("cancel_task", async ({ ack, action, client, body }) => {
|
|
94
|
+
await ack();
|
|
95
|
+
|
|
96
|
+
if (action.type !== "button") return;
|
|
97
|
+
const taskId = action.value;
|
|
98
|
+
if (!taskId) return;
|
|
99
|
+
|
|
100
|
+
const task = getTaskById(taskId);
|
|
101
|
+
if (!task) return;
|
|
102
|
+
|
|
103
|
+
// Cancel the task in DB
|
|
104
|
+
const cancelled = cancelTask(taskId, "Cancelled via Slack");
|
|
105
|
+
if (!cancelled) {
|
|
106
|
+
// Task was already in a terminal state
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Update the message to show cancelled state
|
|
111
|
+
if (task.slackChannelId && task.agentId) {
|
|
112
|
+
const agent = getAgentById(task.agentId);
|
|
113
|
+
const agentName = agent?.name || "Unknown";
|
|
114
|
+
const blocks = buildCancelledBlocks({ agentName, taskId: task.id });
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
// body.message?.ts is the message where the button was clicked
|
|
118
|
+
const messageTs = "message" in body && body.message?.ts;
|
|
119
|
+
if (messageTs && typeof messageTs === "string") {
|
|
120
|
+
await client.chat.update({
|
|
121
|
+
channel: task.slackChannelId,
|
|
122
|
+
ts: messageTs,
|
|
123
|
+
text: "Task cancelled",
|
|
124
|
+
// biome-ignore lint/suspicious/noExplicitAny: Block Kit objects
|
|
125
|
+
blocks: blocks as any,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error("[Slack] Failed to update cancelled message:", error);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
package/src/slack/app.ts
CHANGED
|
@@ -41,9 +41,15 @@ export async function initSlackApp(): Promise<App | null> {
|
|
|
41
41
|
// Register handlers
|
|
42
42
|
const { registerMessageHandler } = await import("./handlers");
|
|
43
43
|
const { registerCommandHandler } = await import("./commands");
|
|
44
|
+
const { registerActionHandlers } = await import("./actions");
|
|
44
45
|
|
|
45
46
|
registerMessageHandler(app);
|
|
46
47
|
registerCommandHandler(app);
|
|
48
|
+
registerActionHandlers(app);
|
|
49
|
+
|
|
50
|
+
// Register assistant thread handler (safe even if "Agents & AI Apps" isn't enabled)
|
|
51
|
+
const { createAssistant } = await import("./assistant");
|
|
52
|
+
app.assistant(createAssistant());
|
|
47
53
|
|
|
48
54
|
return app;
|
|
49
55
|
}
|
|
@@ -70,4 +76,5 @@ export async function stopSlackApp(): Promise<void> {
|
|
|
70
76
|
app = null;
|
|
71
77
|
console.log("[Slack] Bot disconnected");
|
|
72
78
|
}
|
|
79
|
+
initialized = false;
|
|
73
80
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Assistant } from "@slack/bolt";
|
|
2
|
+
import {
|
|
3
|
+
createTaskExtended,
|
|
4
|
+
getAgentWorkingOnThread,
|
|
5
|
+
getLeadAgent,
|
|
6
|
+
getMostRecentTaskInThread,
|
|
7
|
+
} from "../be/db";
|
|
8
|
+
import { resolveTemplate } from "../prompts/resolver";
|
|
9
|
+
import { bufferThreadMessage } from "./thread-buffer";
|
|
10
|
+
// Side-effect import: registers all Slack event templates in the in-memory registry
|
|
11
|
+
import "./templates";
|
|
12
|
+
|
|
13
|
+
const additiveSlack = process.env.ADDITIVE_SLACK === "true";
|
|
14
|
+
|
|
15
|
+
export function createAssistant(): Assistant {
|
|
16
|
+
return new Assistant({
|
|
17
|
+
threadStarted: async ({ say, setSuggestedPrompts, saveThreadContext }) => {
|
|
18
|
+
try {
|
|
19
|
+
await saveThreadContext();
|
|
20
|
+
|
|
21
|
+
const greetingResult = resolveTemplate("slack.assistant.greeting", {});
|
|
22
|
+
await say(greetingResult.text);
|
|
23
|
+
|
|
24
|
+
await setSuggestedPrompts({
|
|
25
|
+
title: "Try these:",
|
|
26
|
+
prompts: [
|
|
27
|
+
{ title: "Check status", message: "What's the current status of all agents?" },
|
|
28
|
+
{ title: "Assign a task", message: "Can you help me with..." },
|
|
29
|
+
{ title: "List recent tasks", message: "Show me the most recent tasks" },
|
|
30
|
+
],
|
|
31
|
+
});
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.error("[Slack] Assistant threadStarted error:", error);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
threadContextChanged: async ({ saveThreadContext }) => {
|
|
38
|
+
await saveThreadContext();
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
userMessage: async ({ message, say, setStatus, setTitle, getThreadContext }) => {
|
|
42
|
+
try {
|
|
43
|
+
// Cast to access fields — Bolt's message union type is complex
|
|
44
|
+
const msg = message as unknown as Record<string, unknown>;
|
|
45
|
+
const threadTs = (msg.thread_ts as string) || message.ts;
|
|
46
|
+
const channelId = message.channel;
|
|
47
|
+
const messageText = (msg.text as string) || "";
|
|
48
|
+
const userId = (msg.user as string) || "";
|
|
49
|
+
|
|
50
|
+
// 1. Check if an agent is already working in this thread
|
|
51
|
+
const workingAgent = getAgentWorkingOnThread(channelId, threadTs);
|
|
52
|
+
|
|
53
|
+
if (workingAgent && workingAgent.status !== "offline") {
|
|
54
|
+
// Follow-up message → route to the same agent
|
|
55
|
+
if (additiveSlack) {
|
|
56
|
+
bufferThreadMessage(channelId, threadTs, messageText, userId, message.ts);
|
|
57
|
+
await setStatus("Queuing follow-up...");
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Otherwise, create a follow-up task for the working agent
|
|
62
|
+
const latestTask = getMostRecentTaskInThread(channelId, threadTs);
|
|
63
|
+
createTaskExtended(messageText, {
|
|
64
|
+
agentId: workingAgent.id,
|
|
65
|
+
source: "slack",
|
|
66
|
+
slackChannelId: channelId,
|
|
67
|
+
slackThreadTs: threadTs,
|
|
68
|
+
slackUserId: userId,
|
|
69
|
+
parentTaskId: latestTask?.id,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
await setStatus("Processing follow-up...");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 2. First message in thread — create new task for lead
|
|
77
|
+
await setStatus("Processing your request...");
|
|
78
|
+
|
|
79
|
+
if (messageText) {
|
|
80
|
+
const title = messageText.length > 50 ? `${messageText.slice(0, 47)}...` : messageText;
|
|
81
|
+
await setTitle(title);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Optionally enrich with channel context
|
|
85
|
+
const ctx = await getThreadContext();
|
|
86
|
+
const channelContext =
|
|
87
|
+
ctx && typeof ctx === "object" && "channel_id" in ctx && ctx.channel_id
|
|
88
|
+
? `\n\n[User is viewing channel <#${ctx.channel_id}>]`
|
|
89
|
+
: "";
|
|
90
|
+
|
|
91
|
+
const lead = getLeadAgent();
|
|
92
|
+
if (!lead) {
|
|
93
|
+
// No lead — still queue the task
|
|
94
|
+
createTaskExtended(messageText + channelContext, {
|
|
95
|
+
source: "slack",
|
|
96
|
+
slackChannelId: channelId,
|
|
97
|
+
slackThreadTs: threadTs,
|
|
98
|
+
slackUserId: userId,
|
|
99
|
+
});
|
|
100
|
+
const offlineResult = resolveTemplate("slack.assistant.offline", {});
|
|
101
|
+
await say(offlineResult.text);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
createTaskExtended(messageText + channelContext, {
|
|
106
|
+
agentId: lead.id,
|
|
107
|
+
source: "slack",
|
|
108
|
+
slackChannelId: channelId,
|
|
109
|
+
slackThreadTs: threadTs,
|
|
110
|
+
slackUserId: userId,
|
|
111
|
+
});
|
|
112
|
+
// setStatus shows typing indicator — watcher will post final result when done
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error("[Slack] Assistant userMessage error:", error);
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
}
|