@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
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { getResolvedConfig, maskSecrets } from "@/be/db";
|
|
4
|
+
import { createToolRegistrar } from "@/tools/utils";
|
|
5
|
+
import { SwarmConfigSchema } from "@/types";
|
|
6
|
+
|
|
7
|
+
export const registerGetConfigTool = (server: McpServer) => {
|
|
8
|
+
createToolRegistrar(server)(
|
|
9
|
+
"get-config",
|
|
10
|
+
{
|
|
11
|
+
title: "Get Config",
|
|
12
|
+
description:
|
|
13
|
+
"Get resolved configuration values with scope resolution (repo > agent > global). Returns one entry per unique key with the most-specific scope winning. Use includeSecrets=true to see secret values.",
|
|
14
|
+
annotations: { readOnlyHint: true },
|
|
15
|
+
|
|
16
|
+
inputSchema: z.object({
|
|
17
|
+
agentId: z
|
|
18
|
+
.string()
|
|
19
|
+
.uuid()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Agent ID for scope resolution. Omit for global-only configs."),
|
|
22
|
+
repoId: z
|
|
23
|
+
.string()
|
|
24
|
+
.uuid()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Repo ID for scope resolution. Omit for agent/global-only configs."),
|
|
27
|
+
key: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Filter by specific key. If omitted, returns all resolved configs."),
|
|
31
|
+
includeSecrets: z
|
|
32
|
+
.boolean()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("If true, include actual secret values (default: false, secrets are masked)."),
|
|
35
|
+
}),
|
|
36
|
+
outputSchema: z.object({
|
|
37
|
+
yourAgentId: z.string().uuid().optional(),
|
|
38
|
+
success: z.boolean(),
|
|
39
|
+
message: z.string(),
|
|
40
|
+
configs: z.array(SwarmConfigSchema),
|
|
41
|
+
count: z.number(),
|
|
42
|
+
}),
|
|
43
|
+
},
|
|
44
|
+
async ({ agentId, repoId, key, includeSecrets }, requestInfo) => {
|
|
45
|
+
if (!requestInfo.agentId) {
|
|
46
|
+
return {
|
|
47
|
+
content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
|
|
48
|
+
structuredContent: {
|
|
49
|
+
success: false,
|
|
50
|
+
message: 'Agent ID not found. Set the "X-Agent-ID" header.',
|
|
51
|
+
configs: [],
|
|
52
|
+
count: 0,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
let configs = getResolvedConfig(agentId, repoId);
|
|
59
|
+
|
|
60
|
+
if (key) {
|
|
61
|
+
configs = configs.filter((c) => c.key === key);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const result = includeSecrets ? configs : maskSecrets(configs);
|
|
65
|
+
const count = result.length;
|
|
66
|
+
|
|
67
|
+
const configList =
|
|
68
|
+
count === 0
|
|
69
|
+
? "No configs found."
|
|
70
|
+
: result
|
|
71
|
+
.map(
|
|
72
|
+
(c) =>
|
|
73
|
+
`- ${c.key}=${c.isSecret && !includeSecrets ? "********" : c.value} (scope: ${c.scope}${c.scopeId ? `, scopeId: ${c.scopeId}` : ""})`,
|
|
74
|
+
)
|
|
75
|
+
.join("\n");
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: "text",
|
|
81
|
+
text:
|
|
82
|
+
count === 0 ? "No configs found." : `Found ${count} config(s):\n\n${configList}`,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
structuredContent: {
|
|
86
|
+
yourAgentId: requestInfo.agentId,
|
|
87
|
+
success: true,
|
|
88
|
+
message: count === 0 ? "No configs found." : `Found ${count} config(s).`,
|
|
89
|
+
configs: result,
|
|
90
|
+
count,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
} catch (error) {
|
|
94
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
95
|
+
return {
|
|
96
|
+
content: [{ type: "text", text: `Failed to get config: ${message}` }],
|
|
97
|
+
structuredContent: {
|
|
98
|
+
yourAgentId: requestInfo.agentId,
|
|
99
|
+
success: false,
|
|
100
|
+
message: `Failed to get config: ${message}`,
|
|
101
|
+
configs: [],
|
|
102
|
+
count: 0,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { getSwarmConfigs, maskSecrets } from "@/be/db";
|
|
4
|
+
import { createToolRegistrar } from "@/tools/utils";
|
|
5
|
+
import { SwarmConfigSchema, SwarmConfigScopeSchema } from "@/types";
|
|
6
|
+
|
|
7
|
+
export const registerListConfigTool = (server: McpServer) => {
|
|
8
|
+
createToolRegistrar(server)(
|
|
9
|
+
"list-config",
|
|
10
|
+
{
|
|
11
|
+
title: "List Config",
|
|
12
|
+
description:
|
|
13
|
+
"List raw config entries with optional filters. Unlike get-config, this returns raw entries without scope resolution — useful for seeing exactly what's configured at each scope level.",
|
|
14
|
+
annotations: { readOnlyHint: true },
|
|
15
|
+
|
|
16
|
+
inputSchema: z.object({
|
|
17
|
+
scope: SwarmConfigScopeSchema.optional().describe(
|
|
18
|
+
"Filter by scope: 'global', 'agent', or 'repo'.",
|
|
19
|
+
),
|
|
20
|
+
scopeId: z.string().uuid().optional().describe("Filter by agent ID or repo ID."),
|
|
21
|
+
key: z.string().optional().describe("Filter by specific key."),
|
|
22
|
+
includeSecrets: z
|
|
23
|
+
.boolean()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("If true, include actual secret values (default: false)."),
|
|
26
|
+
}),
|
|
27
|
+
outputSchema: z.object({
|
|
28
|
+
yourAgentId: z.string().uuid().optional(),
|
|
29
|
+
success: z.boolean(),
|
|
30
|
+
message: z.string(),
|
|
31
|
+
configs: z.array(SwarmConfigSchema),
|
|
32
|
+
count: z.number(),
|
|
33
|
+
}),
|
|
34
|
+
},
|
|
35
|
+
async ({ scope, scopeId, key, includeSecrets }, requestInfo) => {
|
|
36
|
+
if (!requestInfo.agentId) {
|
|
37
|
+
return {
|
|
38
|
+
content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
|
|
39
|
+
structuredContent: {
|
|
40
|
+
success: false,
|
|
41
|
+
message: 'Agent ID not found. Set the "X-Agent-ID" header.',
|
|
42
|
+
configs: [],
|
|
43
|
+
count: 0,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const configs = getSwarmConfigs({
|
|
50
|
+
scope,
|
|
51
|
+
scopeId,
|
|
52
|
+
key,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const result = includeSecrets ? configs : maskSecrets(configs);
|
|
56
|
+
const count = result.length;
|
|
57
|
+
|
|
58
|
+
const configList =
|
|
59
|
+
count === 0
|
|
60
|
+
? "No configs found."
|
|
61
|
+
: result
|
|
62
|
+
.map(
|
|
63
|
+
(c) =>
|
|
64
|
+
`- [${c.scope}${c.scopeId ? `:${c.scopeId}` : ""}] ${c.key}=${c.isSecret && !includeSecrets ? "********" : c.value}${c.description ? ` — ${c.description}` : ""}`,
|
|
65
|
+
)
|
|
66
|
+
.join("\n");
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
content: [
|
|
70
|
+
{
|
|
71
|
+
type: "text",
|
|
72
|
+
text:
|
|
73
|
+
count === 0 ? "No configs found." : `Found ${count} config(s):\n\n${configList}`,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
structuredContent: {
|
|
77
|
+
yourAgentId: requestInfo.agentId,
|
|
78
|
+
success: true,
|
|
79
|
+
message: count === 0 ? "No configs found." : `Found ${count} config(s).`,
|
|
80
|
+
configs: result,
|
|
81
|
+
count,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
} catch (error) {
|
|
85
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
86
|
+
return {
|
|
87
|
+
content: [{ type: "text", text: `Failed to list configs: ${message}` }],
|
|
88
|
+
structuredContent: {
|
|
89
|
+
yourAgentId: requestInfo.agentId,
|
|
90
|
+
success: false,
|
|
91
|
+
message: `Failed to list configs: ${message}`,
|
|
92
|
+
configs: [],
|
|
93
|
+
count: 0,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
);
|
|
99
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { maskSecrets, upsertSwarmConfig } from "@/be/db";
|
|
4
|
+
import { createToolRegistrar } from "@/tools/utils";
|
|
5
|
+
import { SwarmConfigSchema, SwarmConfigScopeSchema } from "@/types";
|
|
6
|
+
|
|
7
|
+
export const registerSetConfigTool = (server: McpServer) => {
|
|
8
|
+
createToolRegistrar(server)(
|
|
9
|
+
"set-config",
|
|
10
|
+
{
|
|
11
|
+
title: "Set Config",
|
|
12
|
+
description:
|
|
13
|
+
"Set or update a swarm configuration value. Upserts by (scope, scopeId, key). Use scope='global' for server-wide settings, 'agent' for agent-specific, or 'repo' for repo-specific. Set isSecret=true to mask the value in API responses.",
|
|
14
|
+
annotations: { idempotentHint: true },
|
|
15
|
+
|
|
16
|
+
inputSchema: z.object({
|
|
17
|
+
scope: SwarmConfigScopeSchema.describe("Config scope: 'global', 'agent', or 'repo'."),
|
|
18
|
+
scopeId: z
|
|
19
|
+
.string()
|
|
20
|
+
.uuid()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe(
|
|
23
|
+
"Agent ID or repo ID. Required for 'agent' and 'repo' scopes, omit for 'global'.",
|
|
24
|
+
),
|
|
25
|
+
key: z
|
|
26
|
+
.string()
|
|
27
|
+
.min(1)
|
|
28
|
+
.max(255)
|
|
29
|
+
.describe("Configuration key (e.g., 'AGENTMAIL_WEBHOOK_SECRET')."),
|
|
30
|
+
value: z.string().describe("Configuration value."),
|
|
31
|
+
isSecret: z
|
|
32
|
+
.boolean()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("If true, value is masked in API responses (default: false)."),
|
|
35
|
+
envPath: z
|
|
36
|
+
.string()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("Optional: file path to write the value as KEY=VALUE in a .env file."),
|
|
39
|
+
description: z
|
|
40
|
+
.string()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe("Optional human-readable description of this config entry."),
|
|
43
|
+
}),
|
|
44
|
+
outputSchema: z.object({
|
|
45
|
+
yourAgentId: z.string().uuid().optional(),
|
|
46
|
+
success: z.boolean(),
|
|
47
|
+
message: z.string(),
|
|
48
|
+
config: SwarmConfigSchema.optional(),
|
|
49
|
+
}),
|
|
50
|
+
},
|
|
51
|
+
async ({ scope, scopeId, key, value, isSecret, envPath, description }, requestInfo) => {
|
|
52
|
+
if (!requestInfo.agentId) {
|
|
53
|
+
return {
|
|
54
|
+
content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
|
|
55
|
+
structuredContent: {
|
|
56
|
+
success: false,
|
|
57
|
+
message: 'Agent ID not found. Set the "X-Agent-ID" header.',
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
if (scope !== "global" && !scopeId) {
|
|
64
|
+
return {
|
|
65
|
+
content: [
|
|
66
|
+
{
|
|
67
|
+
type: "text",
|
|
68
|
+
text: `scopeId is required for scope '${scope}'. Provide an agent ID or repo ID.`,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
structuredContent: {
|
|
72
|
+
yourAgentId: requestInfo.agentId,
|
|
73
|
+
success: false,
|
|
74
|
+
message: `scopeId is required for scope '${scope}'.`,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const config = upsertSwarmConfig({
|
|
80
|
+
scope,
|
|
81
|
+
scopeId: scope === "global" ? null : scopeId,
|
|
82
|
+
key,
|
|
83
|
+
value,
|
|
84
|
+
isSecret,
|
|
85
|
+
envPath,
|
|
86
|
+
description,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const [masked] = maskSecrets([config]);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
content: [
|
|
93
|
+
{
|
|
94
|
+
type: "text",
|
|
95
|
+
text: `Config "${key}" set successfully (scope: ${scope}${scopeId ? `, scopeId: ${scopeId}` : ""}).`,
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
structuredContent: {
|
|
99
|
+
yourAgentId: requestInfo.agentId,
|
|
100
|
+
success: true,
|
|
101
|
+
message: `Config "${key}" set successfully.`,
|
|
102
|
+
config: masked,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
} catch (error) {
|
|
106
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
107
|
+
return {
|
|
108
|
+
content: [{ type: "text", text: `Failed to set config: ${message}` }],
|
|
109
|
+
structuredContent: {
|
|
110
|
+
yourAgentId: requestInfo.agentId,
|
|
111
|
+
success: false,
|
|
112
|
+
message: `Failed to set config: ${message}`,
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
);
|
|
118
|
+
};
|
package/src/tools/task-action.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
checkDependencies,
|
|
6
6
|
claimTask,
|
|
7
7
|
createTaskExtended,
|
|
8
|
+
getActiveSessions,
|
|
8
9
|
getActiveTaskCount,
|
|
9
10
|
getAgentById,
|
|
10
11
|
getDb,
|
|
@@ -12,8 +13,10 @@ import {
|
|
|
12
13
|
hasCapacity,
|
|
13
14
|
moveTaskFromBacklog,
|
|
14
15
|
moveTaskToBacklog,
|
|
16
|
+
reassociateSessionLogs,
|
|
15
17
|
rejectTask,
|
|
16
18
|
releaseTask,
|
|
19
|
+
updateTaskClaudeSessionId,
|
|
17
20
|
} from "@/be/db";
|
|
18
21
|
import { createToolRegistrar } from "@/tools/utils";
|
|
19
22
|
import { AgentTaskSchema } from "@/types";
|
|
@@ -33,6 +36,7 @@ export const registerTaskActionTool = (server: McpServer) => {
|
|
|
33
36
|
"task-action",
|
|
34
37
|
{
|
|
35
38
|
title: "Task Pool Actions",
|
|
39
|
+
annotations: { destructiveHint: false },
|
|
36
40
|
description:
|
|
37
41
|
"Perform task pool operations: create unassigned tasks, claim/release tasks from pool, accept/reject offered tasks.",
|
|
38
42
|
inputSchema: z.object({
|
|
@@ -58,6 +62,21 @@ export const registerTaskActionTool = (server: McpServer) => {
|
|
|
58
62
|
taskId: z.uuid().optional().describe("Task ID (required for claim/release/accept/reject)."),
|
|
59
63
|
// For 'reject' action:
|
|
60
64
|
reason: z.string().optional().describe("Reason for rejection (optional for 'reject')."),
|
|
65
|
+
// For 'create' action:
|
|
66
|
+
dir: z
|
|
67
|
+
.string()
|
|
68
|
+
.min(1)
|
|
69
|
+
.startsWith("/")
|
|
70
|
+
.optional()
|
|
71
|
+
.describe(
|
|
72
|
+
"Working directory (absolute path) for the agent to start in. Only used with 'create' action.",
|
|
73
|
+
),
|
|
74
|
+
model: z
|
|
75
|
+
.enum(["haiku", "sonnet", "opus"])
|
|
76
|
+
.optional()
|
|
77
|
+
.describe(
|
|
78
|
+
"Model to use for the created task ('haiku', 'sonnet', or 'opus'). Only used with 'create' action.",
|
|
79
|
+
),
|
|
61
80
|
}),
|
|
62
81
|
outputSchema: z.object({
|
|
63
82
|
yourAgentId: z.string().uuid().optional(),
|
|
@@ -67,7 +86,8 @@ export const registerTaskActionTool = (server: McpServer) => {
|
|
|
67
86
|
}),
|
|
68
87
|
},
|
|
69
88
|
async (input, requestInfo, _meta) => {
|
|
70
|
-
const { action, task, taskType, tags, priority, dependsOn, taskId, reason } =
|
|
89
|
+
const { action, task, taskType, tags, priority, dependsOn, taskId, reason, dir, model } =
|
|
90
|
+
input;
|
|
71
91
|
|
|
72
92
|
if (!requestInfo.agentId) {
|
|
73
93
|
return {
|
|
@@ -96,6 +116,8 @@ export const registerTaskActionTool = (server: McpServer) => {
|
|
|
96
116
|
tags,
|
|
97
117
|
priority,
|
|
98
118
|
dependsOn,
|
|
119
|
+
dir,
|
|
120
|
+
model,
|
|
99
121
|
});
|
|
100
122
|
return {
|
|
101
123
|
success: true,
|
|
@@ -117,6 +139,8 @@ export const registerTaskActionTool = (server: McpServer) => {
|
|
|
117
139
|
message: `You have no capacity (${activeCount}/${agent?.maxTasks ?? 1} tasks). Complete a task first.`,
|
|
118
140
|
};
|
|
119
141
|
}
|
|
142
|
+
// Pre-checks for informative error messages (the atomic UPDATE in
|
|
143
|
+
// claimTask is the real guard against race conditions)
|
|
120
144
|
const existingTask = getTaskById(taskId);
|
|
121
145
|
if (!existingTask) {
|
|
122
146
|
return { success: false, message: `Task "${taskId}" not found.` };
|
|
@@ -124,7 +148,7 @@ export const registerTaskActionTool = (server: McpServer) => {
|
|
|
124
148
|
if (existingTask.status !== "unassigned") {
|
|
125
149
|
return {
|
|
126
150
|
success: false,
|
|
127
|
-
message: `Task "${taskId}" is not unassigned (status: ${existingTask.status}).`,
|
|
151
|
+
message: `Task "${taskId}" is not unassigned (status: ${existingTask.status}). It may have been claimed by another agent.`,
|
|
128
152
|
};
|
|
129
153
|
}
|
|
130
154
|
// Check if task dependencies are met
|
|
@@ -135,10 +159,31 @@ export const registerTaskActionTool = (server: McpServer) => {
|
|
|
135
159
|
message: `Task "${taskId}" has unmet dependencies: ${blockedBy.join(", ")}. Cannot claim until dependencies are completed.`,
|
|
136
160
|
};
|
|
137
161
|
}
|
|
162
|
+
// Atomic claim — only one agent can win this race
|
|
138
163
|
const claimedTask = claimTask(taskId, agentId);
|
|
139
164
|
if (!claimedTask) {
|
|
140
|
-
return {
|
|
165
|
+
return {
|
|
166
|
+
success: false,
|
|
167
|
+
message: `Task "${taskId}" was already claimed by another agent. Try a different task.`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Reassociate session logs from pool trigger's random UUID to real task ID
|
|
172
|
+
const sessions = getActiveSessions(agentId);
|
|
173
|
+
const activeSession = sessions.find((s) => s.runnerSessionId);
|
|
174
|
+
if (activeSession?.runnerSessionId) {
|
|
175
|
+
const count = reassociateSessionLogs(activeSession.runnerSessionId, taskId);
|
|
176
|
+
if (count > 0) {
|
|
177
|
+
console.log(
|
|
178
|
+
`[task-action] Reassociated ${count} session logs for claimed task ${taskId.slice(0, 8)}`,
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
// Propagate provider session ID (e.g. claudeSessionId) to the task
|
|
182
|
+
if (activeSession.providerSessionId) {
|
|
183
|
+
updateTaskClaudeSessionId(taskId, activeSession.providerSessionId);
|
|
184
|
+
}
|
|
141
185
|
}
|
|
186
|
+
|
|
142
187
|
return {
|
|
143
188
|
success: true,
|
|
144
189
|
message: `Claimed task "${taskId}".`,
|
|
@@ -157,10 +202,10 @@ export const registerTaskActionTool = (server: McpServer) => {
|
|
|
157
202
|
if (existingTask.agentId !== agentId) {
|
|
158
203
|
return { success: false, message: `Task "${taskId}" is not assigned to you.` };
|
|
159
204
|
}
|
|
160
|
-
if (existingTask.status !== "pending") {
|
|
205
|
+
if (existingTask.status !== "pending" && existingTask.status !== "in_progress") {
|
|
161
206
|
return {
|
|
162
207
|
success: false,
|
|
163
|
-
message: `Cannot release task in status "${existingTask.status}". Only 'pending' tasks can be released.`,
|
|
208
|
+
message: `Cannot release task in status "${existingTask.status}". Only 'pending' or 'in_progress' tasks can be released.`,
|
|
164
209
|
};
|
|
165
210
|
}
|
|
166
211
|
const releasedTask = releaseTask(taskId);
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { findRecentSimilarTasks } from "@/be/db";
|
|
2
|
+
import type { AgentTask } from "@/types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Jaccard similarity on word sets.
|
|
6
|
+
* Tokenizes both strings into lowercase word sets and computes |intersection| / |union|.
|
|
7
|
+
*/
|
|
8
|
+
export function jaccardSimilarity(a: string, b: string): number {
|
|
9
|
+
const tokenize = (s: string) =>
|
|
10
|
+
new Set(
|
|
11
|
+
s
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.replace(/[^\w\s]/g, " ")
|
|
14
|
+
.split(/\s+/)
|
|
15
|
+
.filter((w) => w.length > 0),
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const wordsA = tokenize(a);
|
|
19
|
+
const wordsB = tokenize(b);
|
|
20
|
+
|
|
21
|
+
if (wordsA.size === 0 && wordsB.size === 0) return 1;
|
|
22
|
+
if (wordsA.size === 0 || wordsB.size === 0) return 0;
|
|
23
|
+
|
|
24
|
+
let intersection = 0;
|
|
25
|
+
for (const w of wordsA) {
|
|
26
|
+
if (wordsB.has(w)) intersection++;
|
|
27
|
+
}
|
|
28
|
+
const union = new Set([...wordsA, ...wordsB]).size;
|
|
29
|
+
return intersection / union;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Similarity above which any two task descriptions are considered duplicates */
|
|
33
|
+
const HIGH_SIMILARITY_THRESHOLD = 0.8;
|
|
34
|
+
/** Lower threshold used when the tasks also target the same agent */
|
|
35
|
+
const SAME_AGENT_SIMILARITY_THRESHOLD = 0.6;
|
|
36
|
+
|
|
37
|
+
export interface DedupMatch {
|
|
38
|
+
task: AgentTask;
|
|
39
|
+
reason: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check for duplicate tasks created recently.
|
|
44
|
+
* Returns the first matching duplicate, or null if none found.
|
|
45
|
+
*/
|
|
46
|
+
export function findDuplicateTask(opts: {
|
|
47
|
+
taskDescription: string;
|
|
48
|
+
creatorAgentId: string;
|
|
49
|
+
targetAgentId?: string;
|
|
50
|
+
slackChannelId?: string;
|
|
51
|
+
slackThreadTs?: string;
|
|
52
|
+
windowMinutes?: number;
|
|
53
|
+
}): DedupMatch | null {
|
|
54
|
+
const recentTasks = findRecentSimilarTasks({
|
|
55
|
+
creatorAgentId: opts.creatorAgentId,
|
|
56
|
+
windowMinutes: opts.windowMinutes ?? 10,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
for (const existing of recentTasks) {
|
|
60
|
+
// 1. Exact Slack thread match — definitely a duplicate
|
|
61
|
+
if (
|
|
62
|
+
opts.slackChannelId &&
|
|
63
|
+
opts.slackThreadTs &&
|
|
64
|
+
existing.slackChannelId === opts.slackChannelId &&
|
|
65
|
+
existing.slackThreadTs === opts.slackThreadTs
|
|
66
|
+
) {
|
|
67
|
+
return {
|
|
68
|
+
task: existing,
|
|
69
|
+
reason: `same Slack thread (${opts.slackChannelId}/${opts.slackThreadTs})`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const similarity = jaccardSimilarity(existing.task, opts.taskDescription);
|
|
74
|
+
|
|
75
|
+
// 2. Very similar task description — likely duplicate regardless of target
|
|
76
|
+
if (similarity > HIGH_SIMILARITY_THRESHOLD) {
|
|
77
|
+
return {
|
|
78
|
+
task: existing,
|
|
79
|
+
reason: `similar task description (${(similarity * 100).toFixed(0)}% match)`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 3. Same target agent + moderately similar task — lower threshold
|
|
84
|
+
if (
|
|
85
|
+
opts.targetAgentId &&
|
|
86
|
+
existing.agentId === opts.targetAgentId &&
|
|
87
|
+
similarity > SAME_AGENT_SIMILARITY_THRESHOLD
|
|
88
|
+
) {
|
|
89
|
+
return {
|
|
90
|
+
task: existing,
|
|
91
|
+
reason: `similar task to same agent (${(similarity * 100).toFixed(0)}% match)`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task lifecycle prompt template definitions (store-progress follow-ups).
|
|
3
|
+
*
|
|
4
|
+
* Each template is registered at module load time via registerTemplate().
|
|
5
|
+
* Handlers import this module for the side-effect of registration.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { registerTemplate } from "../prompts/registry";
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Worker task follow-ups (created by store-progress for the lead)
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
registerTemplate({
|
|
15
|
+
eventType: "task.worker.completed",
|
|
16
|
+
header: "",
|
|
17
|
+
defaultBody: `Worker task completed \u2014 review needed.
|
|
18
|
+
|
|
19
|
+
Agent: {{agent_name}}
|
|
20
|
+
Task: "{{task_desc}}"
|
|
21
|
+
|
|
22
|
+
Output:
|
|
23
|
+
{{output_summary}}
|
|
24
|
+
|
|
25
|
+
Use \`get-task-details\` with taskId "{{task_id}}" for full details.`,
|
|
26
|
+
variables: [
|
|
27
|
+
{ name: "agent_name", description: "Worker agent name or ID prefix" },
|
|
28
|
+
{ name: "task_desc", description: "Task description (truncated to 200 chars)" },
|
|
29
|
+
{ name: "output_summary", description: "Task output (truncated to 500 chars)" },
|
|
30
|
+
{ name: "task_id", description: "Original task ID" },
|
|
31
|
+
],
|
|
32
|
+
category: "task_lifecycle",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
registerTemplate({
|
|
36
|
+
eventType: "task.worker.failed",
|
|
37
|
+
header: "",
|
|
38
|
+
defaultBody: `Worker task failed \u2014 action needed.
|
|
39
|
+
|
|
40
|
+
Agent: {{agent_name}}
|
|
41
|
+
Task: "{{task_desc}}"
|
|
42
|
+
|
|
43
|
+
Failure reason: {{failure_reason}}
|
|
44
|
+
|
|
45
|
+
Decide whether to reassign, retry, or handle the failure. Use \`get-task-details\` with taskId "{{task_id}}" for full details.`,
|
|
46
|
+
variables: [
|
|
47
|
+
{ name: "agent_name", description: "Worker agent name or ID prefix" },
|
|
48
|
+
{ name: "task_desc", description: "Task description (truncated to 200 chars)" },
|
|
49
|
+
{ name: "failure_reason", description: "Failure reason text" },
|
|
50
|
+
{ name: "task_id", description: "Original task ID" },
|
|
51
|
+
],
|
|
52
|
+
category: "task_lifecycle",
|
|
53
|
+
});
|