@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,94 @@
|
|
|
1
|
+
-- Add VCS provider abstraction: rename github* columns to vcs*, add vcsProvider,
|
|
2
|
+
-- and update source CHECK constraint to include 'gitlab'.
|
|
3
|
+
-- Uses the 12-step table recreation approach since SQLite doesn't support ALTER CHECK.
|
|
4
|
+
|
|
5
|
+
PRAGMA defer_foreign_keys = ON;
|
|
6
|
+
|
|
7
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
8
|
+
-- agent_tasks: recreate with vcs* columns + updated CHECK constraint
|
|
9
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
10
|
+
|
|
11
|
+
CREATE TABLE agent_tasks_new (
|
|
12
|
+
id TEXT PRIMARY KEY,
|
|
13
|
+
agentId TEXT,
|
|
14
|
+
creatorAgentId TEXT,
|
|
15
|
+
task TEXT NOT NULL,
|
|
16
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
17
|
+
source TEXT NOT NULL DEFAULT 'mcp' CHECK(source IN ('mcp', 'slack', 'api', 'github', 'gitlab', 'agentmail', 'system', 'schedule', 'workflow')),
|
|
18
|
+
taskType TEXT,
|
|
19
|
+
tags TEXT DEFAULT '[]',
|
|
20
|
+
priority INTEGER DEFAULT 50,
|
|
21
|
+
dependsOn TEXT DEFAULT '[]',
|
|
22
|
+
offeredTo TEXT,
|
|
23
|
+
offeredAt TEXT,
|
|
24
|
+
acceptedAt TEXT,
|
|
25
|
+
rejectionReason TEXT,
|
|
26
|
+
slackChannelId TEXT,
|
|
27
|
+
slackThreadTs TEXT,
|
|
28
|
+
slackUserId TEXT,
|
|
29
|
+
mentionMessageId TEXT,
|
|
30
|
+
mentionChannelId TEXT,
|
|
31
|
+
vcsProvider TEXT,
|
|
32
|
+
vcsRepo TEXT,
|
|
33
|
+
vcsEventType TEXT,
|
|
34
|
+
vcsNumber INTEGER,
|
|
35
|
+
vcsCommentId INTEGER,
|
|
36
|
+
vcsAuthor TEXT,
|
|
37
|
+
vcsUrl TEXT,
|
|
38
|
+
epicId TEXT REFERENCES epics(id) ON DELETE SET NULL,
|
|
39
|
+
parentTaskId TEXT,
|
|
40
|
+
claudeSessionId TEXT,
|
|
41
|
+
agentmailInboxId TEXT,
|
|
42
|
+
agentmailMessageId TEXT,
|
|
43
|
+
agentmailThreadId TEXT,
|
|
44
|
+
model TEXT,
|
|
45
|
+
scheduleId TEXT,
|
|
46
|
+
workflowRunId TEXT REFERENCES workflow_runs(id),
|
|
47
|
+
workflowRunStepId TEXT REFERENCES workflow_run_steps(id),
|
|
48
|
+
createdAt TEXT NOT NULL,
|
|
49
|
+
lastUpdatedAt TEXT NOT NULL,
|
|
50
|
+
finishedAt TEXT,
|
|
51
|
+
failureReason TEXT,
|
|
52
|
+
output TEXT,
|
|
53
|
+
progress TEXT,
|
|
54
|
+
notifiedAt TEXT
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
-- Copy data, renaming github* → vcs* and adding vcsProvider backfill
|
|
58
|
+
INSERT INTO agent_tasks_new SELECT
|
|
59
|
+
id, agentId, creatorAgentId, task, status, source,
|
|
60
|
+
taskType, tags, priority, dependsOn, offeredTo, offeredAt,
|
|
61
|
+
acceptedAt, rejectionReason, slackChannelId, slackThreadTs, slackUserId,
|
|
62
|
+
mentionMessageId, mentionChannelId,
|
|
63
|
+
CASE WHEN githubRepo IS NOT NULL THEN 'github' ELSE NULL END,
|
|
64
|
+
githubRepo, githubEventType, githubNumber, githubCommentId, githubAuthor, githubUrl,
|
|
65
|
+
epicId, parentTaskId, claudeSessionId,
|
|
66
|
+
agentmailInboxId, agentmailMessageId, agentmailThreadId,
|
|
67
|
+
model, scheduleId, workflowRunId, workflowRunStepId,
|
|
68
|
+
createdAt, lastUpdatedAt, finishedAt, failureReason, output, progress, notifiedAt
|
|
69
|
+
FROM agent_tasks;
|
|
70
|
+
|
|
71
|
+
DROP TABLE agent_tasks;
|
|
72
|
+
ALTER TABLE agent_tasks_new RENAME TO agent_tasks;
|
|
73
|
+
|
|
74
|
+
-- Recreate indexes
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_agentId ON agent_tasks(agentId);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_status ON agent_tasks(status);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_offeredTo ON agent_tasks(offeredTo);
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_taskType ON agent_tasks(taskType);
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_epicId ON agent_tasks(epicId);
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_agentmailThreadId ON agent_tasks(agentmailThreadId);
|
|
81
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_schedule_id ON agent_tasks(scheduleId);
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_workflow_run ON agent_tasks(workflowRunId);
|
|
83
|
+
|
|
84
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
85
|
+
-- epics: rename github* → vcs* and add vcsProvider
|
|
86
|
+
-- (No CHECK constraint to update, so ALTER TABLE is fine)
|
|
87
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
88
|
+
|
|
89
|
+
ALTER TABLE epics RENAME COLUMN githubRepo TO vcsRepo;
|
|
90
|
+
ALTER TABLE epics RENAME COLUMN githubMilestone TO vcsMilestone;
|
|
91
|
+
ALTER TABLE epics ADD COLUMN vcsProvider TEXT DEFAULT NULL;
|
|
92
|
+
|
|
93
|
+
-- Backfill vcsProvider for epics
|
|
94
|
+
UPDATE epics SET vcsProvider = 'github' WHERE vcsRepo IS NOT NULL;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
-- Workflow Engine Redesign: drop and recreate workflow tables with new schema.
|
|
2
|
+
-- This is a clean-slate migration — no existing workflow data is preserved.
|
|
3
|
+
|
|
4
|
+
-- Disable FK enforcement so we can drop referenced tables
|
|
5
|
+
PRAGMA foreign_keys = OFF;
|
|
6
|
+
|
|
7
|
+
-- NULL out FK columns on agent_tasks that reference workflow tables
|
|
8
|
+
UPDATE agent_tasks SET workflowRunId = NULL, workflowRunStepId = NULL
|
|
9
|
+
WHERE workflowRunId IS NOT NULL OR workflowRunStepId IS NOT NULL;
|
|
10
|
+
|
|
11
|
+
-- Drop old tables in FK-safe order
|
|
12
|
+
DROP TABLE IF EXISTS workflow_run_steps;
|
|
13
|
+
DROP TABLE IF EXISTS workflow_runs;
|
|
14
|
+
DROP TABLE IF EXISTS workflows;
|
|
15
|
+
|
|
16
|
+
-- Recreate workflows with new columns (triggers, cooldown, input; no webhookSecret)
|
|
17
|
+
CREATE TABLE IF NOT EXISTS workflows (
|
|
18
|
+
id TEXT PRIMARY KEY,
|
|
19
|
+
name TEXT NOT NULL UNIQUE,
|
|
20
|
+
description TEXT,
|
|
21
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
22
|
+
definition TEXT NOT NULL,
|
|
23
|
+
triggers TEXT NOT NULL DEFAULT '[]',
|
|
24
|
+
cooldown TEXT,
|
|
25
|
+
input TEXT,
|
|
26
|
+
createdByAgentId TEXT,
|
|
27
|
+
createdAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
28
|
+
lastUpdatedAt TEXT NOT NULL DEFAULT (datetime('now'))
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
-- Recreate workflow_runs with 'skipped' status
|
|
32
|
+
CREATE TABLE IF NOT EXISTS workflow_runs (
|
|
33
|
+
id TEXT PRIMARY KEY,
|
|
34
|
+
workflowId TEXT NOT NULL REFERENCES workflows(id),
|
|
35
|
+
status TEXT NOT NULL DEFAULT 'running'
|
|
36
|
+
CHECK(status IN ('running', 'waiting', 'completed', 'failed', 'skipped')),
|
|
37
|
+
triggerData TEXT,
|
|
38
|
+
context TEXT,
|
|
39
|
+
error TEXT,
|
|
40
|
+
startedAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
41
|
+
lastUpdatedAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
42
|
+
finishedAt TEXT
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
CREATE INDEX IF NOT EXISTS idx_workflow_runs_workflowId ON workflow_runs(workflowId);
|
|
46
|
+
CREATE INDEX IF NOT EXISTS idx_workflow_runs_status ON workflow_runs(status);
|
|
47
|
+
|
|
48
|
+
-- Recreate workflow_run_steps with retry columns
|
|
49
|
+
CREATE TABLE IF NOT EXISTS workflow_run_steps (
|
|
50
|
+
id TEXT PRIMARY KEY,
|
|
51
|
+
runId TEXT NOT NULL REFERENCES workflow_runs(id),
|
|
52
|
+
nodeId TEXT NOT NULL,
|
|
53
|
+
nodeType TEXT NOT NULL,
|
|
54
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
55
|
+
CHECK(status IN ('pending', 'running', 'waiting', 'completed', 'failed', 'skipped')),
|
|
56
|
+
input TEXT,
|
|
57
|
+
output TEXT,
|
|
58
|
+
error TEXT,
|
|
59
|
+
startedAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
60
|
+
finishedAt TEXT,
|
|
61
|
+
retryCount INTEGER NOT NULL DEFAULT 0,
|
|
62
|
+
maxRetries INTEGER NOT NULL DEFAULT 3,
|
|
63
|
+
nextRetryAt TEXT,
|
|
64
|
+
idempotencyKey TEXT
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_workflow_run_steps_runId ON workflow_run_steps(runId);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_wrs_retry
|
|
69
|
+
ON workflow_run_steps(status, nextRetryAt)
|
|
70
|
+
WHERE status = 'failed' AND nextRetryAt IS NOT NULL;
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_wrs_idempotency ON workflow_run_steps(idempotencyKey);
|
|
72
|
+
|
|
73
|
+
-- New: workflow version history
|
|
74
|
+
CREATE TABLE IF NOT EXISTS workflow_versions (
|
|
75
|
+
id TEXT PRIMARY KEY,
|
|
76
|
+
workflowId TEXT NOT NULL REFERENCES workflows(id) ON DELETE CASCADE,
|
|
77
|
+
version INTEGER NOT NULL,
|
|
78
|
+
snapshot TEXT NOT NULL,
|
|
79
|
+
changedByAgentId TEXT,
|
|
80
|
+
createdAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
81
|
+
UNIQUE(workflowId, version)
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
-- Re-enable FK enforcement
|
|
85
|
+
PRAGMA foreign_keys = ON;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
-- Tracker integration: generic OAuth, entity sync mapping, agent mapping tables.
|
|
2
|
+
-- Also adds 'linear' to the agent_tasks source CHECK constraint.
|
|
3
|
+
|
|
4
|
+
PRAGMA defer_foreign_keys = ON;
|
|
5
|
+
|
|
6
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
7
|
+
-- Generic OAuth tables (reusable across any OAuth provider in the swarm)
|
|
8
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
9
|
+
|
|
10
|
+
-- Generic OAuth application configuration (one row per provider)
|
|
11
|
+
CREATE TABLE IF NOT EXISTS oauth_apps (
|
|
12
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
13
|
+
provider TEXT NOT NULL UNIQUE,
|
|
14
|
+
clientId TEXT NOT NULL,
|
|
15
|
+
clientSecret TEXT NOT NULL,
|
|
16
|
+
authorizeUrl TEXT NOT NULL,
|
|
17
|
+
tokenUrl TEXT NOT NULL,
|
|
18
|
+
redirectUri TEXT NOT NULL,
|
|
19
|
+
scopes TEXT NOT NULL,
|
|
20
|
+
metadata TEXT DEFAULT '{}',
|
|
21
|
+
createdAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
22
|
+
updatedAt TEXT NOT NULL DEFAULT (datetime('now'))
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
-- Generic OAuth token storage (one active token set per provider)
|
|
26
|
+
CREATE TABLE IF NOT EXISTS oauth_tokens (
|
|
27
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
28
|
+
provider TEXT NOT NULL UNIQUE,
|
|
29
|
+
accessToken TEXT NOT NULL,
|
|
30
|
+
refreshToken TEXT,
|
|
31
|
+
expiresAt TEXT NOT NULL,
|
|
32
|
+
scope TEXT,
|
|
33
|
+
createdAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
34
|
+
updatedAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
35
|
+
FOREIGN KEY (provider) REFERENCES oauth_apps(provider)
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
39
|
+
-- Generic tracker tables (reusable across any ticket tracker)
|
|
40
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
41
|
+
|
|
42
|
+
-- Generic tracker entity mapping
|
|
43
|
+
CREATE TABLE IF NOT EXISTS tracker_sync (
|
|
44
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
45
|
+
provider TEXT NOT NULL,
|
|
46
|
+
entityType TEXT NOT NULL CHECK (entityType IN ('task', 'epic')),
|
|
47
|
+
providerEntityType TEXT,
|
|
48
|
+
swarmId TEXT NOT NULL,
|
|
49
|
+
externalId TEXT NOT NULL,
|
|
50
|
+
externalIdentifier TEXT,
|
|
51
|
+
externalUrl TEXT,
|
|
52
|
+
lastSyncedAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
53
|
+
lastSyncOrigin TEXT CHECK (lastSyncOrigin IN ('swarm', 'external')),
|
|
54
|
+
lastDeliveryId TEXT,
|
|
55
|
+
syncDirection TEXT NOT NULL DEFAULT 'inbound' CHECK (syncDirection IN ('inbound', 'outbound', 'bidirectional')),
|
|
56
|
+
createdAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
57
|
+
UNIQUE(provider, entityType, swarmId),
|
|
58
|
+
UNIQUE(provider, entityType, externalId)
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
-- Generic agent-to-external-user mapping
|
|
62
|
+
CREATE TABLE IF NOT EXISTS tracker_agent_mapping (
|
|
63
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
64
|
+
provider TEXT NOT NULL,
|
|
65
|
+
agentId TEXT NOT NULL,
|
|
66
|
+
externalUserId TEXT NOT NULL,
|
|
67
|
+
agentName TEXT NOT NULL,
|
|
68
|
+
createdAt TEXT NOT NULL DEFAULT (datetime('now')),
|
|
69
|
+
UNIQUE(provider, agentId),
|
|
70
|
+
UNIQUE(provider, externalUserId)
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
-- Indexes
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_oauth_tokens_provider ON oauth_tokens(provider);
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_tracker_sync_swarm ON tracker_sync(provider, entityType, swarmId);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_tracker_sync_external ON tracker_sync(provider, entityType, externalId);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_tracker_agent_agentId ON tracker_agent_mapping(provider, agentId);
|
|
78
|
+
|
|
79
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
80
|
+
-- agent_tasks: recreate with 'linear' added to source CHECK constraint
|
|
81
|
+
-- (copied from previous 008_linear_integration.sql lines 54-114)
|
|
82
|
+
-- ═══════════════════════════════════════════════════════════════════
|
|
83
|
+
|
|
84
|
+
CREATE TABLE agent_tasks_new (
|
|
85
|
+
id TEXT PRIMARY KEY,
|
|
86
|
+
agentId TEXT,
|
|
87
|
+
creatorAgentId TEXT,
|
|
88
|
+
task TEXT NOT NULL,
|
|
89
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
90
|
+
source TEXT NOT NULL DEFAULT 'mcp' CHECK(source IN ('mcp', 'slack', 'api', 'github', 'gitlab', 'agentmail', 'system', 'schedule', 'workflow', 'linear')),
|
|
91
|
+
taskType TEXT,
|
|
92
|
+
tags TEXT DEFAULT '[]',
|
|
93
|
+
priority INTEGER DEFAULT 50,
|
|
94
|
+
dependsOn TEXT DEFAULT '[]',
|
|
95
|
+
offeredTo TEXT,
|
|
96
|
+
offeredAt TEXT,
|
|
97
|
+
acceptedAt TEXT,
|
|
98
|
+
rejectionReason TEXT,
|
|
99
|
+
slackChannelId TEXT,
|
|
100
|
+
slackThreadTs TEXT,
|
|
101
|
+
slackUserId TEXT,
|
|
102
|
+
mentionMessageId TEXT,
|
|
103
|
+
mentionChannelId TEXT,
|
|
104
|
+
vcsProvider TEXT,
|
|
105
|
+
vcsRepo TEXT,
|
|
106
|
+
vcsEventType TEXT,
|
|
107
|
+
vcsNumber INTEGER,
|
|
108
|
+
vcsCommentId INTEGER,
|
|
109
|
+
vcsAuthor TEXT,
|
|
110
|
+
vcsUrl TEXT,
|
|
111
|
+
epicId TEXT REFERENCES epics(id) ON DELETE SET NULL,
|
|
112
|
+
parentTaskId TEXT,
|
|
113
|
+
claudeSessionId TEXT,
|
|
114
|
+
agentmailInboxId TEXT,
|
|
115
|
+
agentmailMessageId TEXT,
|
|
116
|
+
agentmailThreadId TEXT,
|
|
117
|
+
model TEXT,
|
|
118
|
+
scheduleId TEXT,
|
|
119
|
+
workflowRunId TEXT REFERENCES workflow_runs(id),
|
|
120
|
+
workflowRunStepId TEXT REFERENCES workflow_run_steps(id),
|
|
121
|
+
createdAt TEXT NOT NULL,
|
|
122
|
+
lastUpdatedAt TEXT NOT NULL,
|
|
123
|
+
finishedAt TEXT,
|
|
124
|
+
failureReason TEXT,
|
|
125
|
+
output TEXT,
|
|
126
|
+
progress TEXT,
|
|
127
|
+
notifiedAt TEXT,
|
|
128
|
+
dir TEXT
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
INSERT INTO agent_tasks_new SELECT * FROM agent_tasks;
|
|
132
|
+
|
|
133
|
+
DROP TABLE agent_tasks;
|
|
134
|
+
ALTER TABLE agent_tasks_new RENAME TO agent_tasks;
|
|
135
|
+
|
|
136
|
+
-- Recreate indexes
|
|
137
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_agentId ON agent_tasks(agentId);
|
|
138
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_status ON agent_tasks(status);
|
|
139
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_offeredTo ON agent_tasks(offeredTo);
|
|
140
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_taskType ON agent_tasks(taskType);
|
|
141
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_epicId ON agent_tasks(epicId);
|
|
142
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_agentmailThreadId ON agent_tasks(agentmailThreadId);
|
|
143
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_schedule_id ON agent_tasks(scheduleId);
|
|
144
|
+
CREATE INDEX IF NOT EXISTS idx_agent_tasks_workflow_run ON agent_tasks(workflowRunId);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE workflow_run_steps ADD COLUMN diagnostics TEXT;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE workflow_run_steps ADD COLUMN nextPort TEXT;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE workflows ADD COLUMN triggerSchema TEXT;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
-- 013_prompt_templates.sql
|
|
2
|
+
-- Prompt Template Registry: per-event customizable prompt templates with scope resolution,
|
|
3
|
+
-- three-state behavior, wildcard matching, and version history.
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS prompt_templates (
|
|
6
|
+
id TEXT PRIMARY KEY,
|
|
7
|
+
eventType TEXT NOT NULL,
|
|
8
|
+
scope TEXT NOT NULL CHECK(scope IN ('global', 'agent', 'repo')),
|
|
9
|
+
scopeId TEXT,
|
|
10
|
+
state TEXT NOT NULL DEFAULT 'enabled' CHECK(state IN ('enabled', 'default_prompt_fallback', 'skip_event')),
|
|
11
|
+
body TEXT NOT NULL,
|
|
12
|
+
isDefault INTEGER NOT NULL DEFAULT 0,
|
|
13
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
14
|
+
createdBy TEXT,
|
|
15
|
+
createdAt TEXT NOT NULL,
|
|
16
|
+
updatedAt TEXT NOT NULL,
|
|
17
|
+
UNIQUE(eventType, scope, scopeId)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS prompt_template_history (
|
|
21
|
+
id TEXT PRIMARY KEY,
|
|
22
|
+
templateId TEXT NOT NULL,
|
|
23
|
+
version INTEGER NOT NULL,
|
|
24
|
+
body TEXT NOT NULL,
|
|
25
|
+
state TEXT NOT NULL,
|
|
26
|
+
changedBy TEXT,
|
|
27
|
+
changedAt TEXT NOT NULL,
|
|
28
|
+
changeReason TEXT
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_prompt_templates_event_type ON prompt_templates(eventType);
|
|
32
|
+
CREATE INDEX IF NOT EXISTS idx_prompt_templates_scope ON prompt_templates(scope, scopeId);
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_prompt_template_history_template ON prompt_template_history(templateId);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-- Fix: template seeding created a spurious version 2 ("Reset to default") for every
|
|
2
|
+
-- seeded template because upsertPromptTemplate hardcoded isDefault=0, requiring
|
|
3
|
+
-- an immediate resetPromptTemplateToDefault call to flip it.
|
|
4
|
+
|
|
5
|
+
-- Delete spurious "Reset to default" history entries created by the two-step seed.
|
|
6
|
+
-- These are version=2 entries where version=1 for the same template has identical body.
|
|
7
|
+
DELETE FROM prompt_template_history
|
|
8
|
+
WHERE version = 2
|
|
9
|
+
AND changeReason = 'Reset to default'
|
|
10
|
+
AND templateId IN (
|
|
11
|
+
SELECT h2.templateId
|
|
12
|
+
FROM prompt_template_history h2
|
|
13
|
+
JOIN prompt_template_history h1
|
|
14
|
+
ON h1.templateId = h2.templateId
|
|
15
|
+
AND h1.version = 1
|
|
16
|
+
AND h1.changeReason = 'Seeded from code registry'
|
|
17
|
+
AND h1.body = h2.body
|
|
18
|
+
WHERE h2.version = 2
|
|
19
|
+
AND h2.changeReason = 'Reset to default'
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
-- Reset version back to 1 for templates that are currently at version=2
|
|
23
|
+
-- and only have version=1 history remaining (the spurious v2 was just deleted).
|
|
24
|
+
UPDATE prompt_templates
|
|
25
|
+
SET version = 1
|
|
26
|
+
WHERE version = 2
|
|
27
|
+
AND isDefault = 1
|
|
28
|
+
AND id NOT IN (
|
|
29
|
+
SELECT templateId FROM prompt_template_history WHERE version = 2
|
|
30
|
+
);
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
interface Migration {
|
|
7
|
+
version: number;
|
|
8
|
+
name: string;
|
|
9
|
+
sql: string;
|
|
10
|
+
checksum: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface AppliedMigration {
|
|
14
|
+
version: number;
|
|
15
|
+
name: string;
|
|
16
|
+
checksum: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const BASELINE_TABLES = [
|
|
20
|
+
"agents",
|
|
21
|
+
"channels",
|
|
22
|
+
"epics",
|
|
23
|
+
"agent_tasks",
|
|
24
|
+
"agent_log",
|
|
25
|
+
"channel_messages",
|
|
26
|
+
"channel_read_state",
|
|
27
|
+
"services",
|
|
28
|
+
"session_logs",
|
|
29
|
+
"session_costs",
|
|
30
|
+
"inbox_messages",
|
|
31
|
+
"scheduled_tasks",
|
|
32
|
+
"swarm_config",
|
|
33
|
+
"swarm_repos",
|
|
34
|
+
"agent_memory",
|
|
35
|
+
"active_sessions",
|
|
36
|
+
"agentmail_inbox_mappings",
|
|
37
|
+
"context_versions",
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
function shouldBootstrapInitialMigration(db: Database): boolean {
|
|
41
|
+
const rows = db
|
|
42
|
+
.prepare<{ name: string }, []>(
|
|
43
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE '\\_migrations' ESCAPE '\\'",
|
|
44
|
+
)
|
|
45
|
+
.all();
|
|
46
|
+
|
|
47
|
+
if (rows.length === 0) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const existingTables = new Set(rows.map((row) => row.name));
|
|
52
|
+
return BASELINE_TABLES.every((table) => existingTables.has(table));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Runs all pending database migrations.
|
|
57
|
+
*
|
|
58
|
+
* - Creates the `_migrations` tracking table if it doesn't exist
|
|
59
|
+
* - Reads `.sql` files from the migrations directory (sorted by numeric prefix)
|
|
60
|
+
* - For existing databases (pre-migration-system), bootstraps by marking 001_initial as applied
|
|
61
|
+
* - Applies pending migrations in order, each within its own transaction
|
|
62
|
+
* - Verifies checksums of previously-applied migrations (warns on mismatch)
|
|
63
|
+
*/
|
|
64
|
+
export function runMigrations(db: Database): void {
|
|
65
|
+
// 1. Ensure tracking table exists
|
|
66
|
+
db.run(`
|
|
67
|
+
CREATE TABLE IF NOT EXISTS _migrations (
|
|
68
|
+
version INTEGER PRIMARY KEY,
|
|
69
|
+
name TEXT NOT NULL,
|
|
70
|
+
applied_at TEXT NOT NULL,
|
|
71
|
+
checksum TEXT NOT NULL
|
|
72
|
+
)
|
|
73
|
+
`);
|
|
74
|
+
|
|
75
|
+
// 2. Load migration files
|
|
76
|
+
// import.meta.dir resolves to /$bunfs/root in compiled binaries, which isn't scannable.
|
|
77
|
+
// Fall back to MIGRATIONS_DIR env var (set in Dockerfile) for compiled binary support.
|
|
78
|
+
const migrationsDir = (() => {
|
|
79
|
+
const dir = import.meta.dir;
|
|
80
|
+
try {
|
|
81
|
+
readdirSync(dir);
|
|
82
|
+
return dir;
|
|
83
|
+
} catch {
|
|
84
|
+
const fallback = process.env.MIGRATIONS_DIR;
|
|
85
|
+
if (fallback) return fallback;
|
|
86
|
+
console.warn(
|
|
87
|
+
"[migrations] Cannot read migrations directory and MIGRATIONS_DIR not set — skipping",
|
|
88
|
+
);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
})();
|
|
92
|
+
|
|
93
|
+
if (!migrationsDir) return;
|
|
94
|
+
|
|
95
|
+
const files = readdirSync(migrationsDir)
|
|
96
|
+
.filter((f) => f.endsWith(".sql"))
|
|
97
|
+
.sort();
|
|
98
|
+
|
|
99
|
+
const migrations: Migration[] = files.map((file) => {
|
|
100
|
+
const version = parseInt(file.split("_")[0] ?? "0", 10);
|
|
101
|
+
const name = file.replace(".sql", "");
|
|
102
|
+
const sql = readFileSync(join(migrationsDir, file), "utf-8");
|
|
103
|
+
const checksum = createHash("sha256").update(sql).digest("hex");
|
|
104
|
+
return { version, name, sql, checksum };
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (migrations.length === 0) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 3. Get applied migrations
|
|
112
|
+
const applied = new Map<number, AppliedMigration>();
|
|
113
|
+
const rows = db
|
|
114
|
+
.prepare("SELECT version, name, checksum FROM _migrations")
|
|
115
|
+
.all() as AppliedMigration[];
|
|
116
|
+
for (const row of rows) {
|
|
117
|
+
applied.set(row.version, {
|
|
118
|
+
version: row.version,
|
|
119
|
+
name: row.name,
|
|
120
|
+
checksum: row.checksum,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 4. Bootstrap existing databases
|
|
125
|
+
// If no migrations have been applied yet and database tables already exist,
|
|
126
|
+
// this is a pre-migration-system database. Mark 001_initial as applied without
|
|
127
|
+
// executing it (the schema already exists).
|
|
128
|
+
if (applied.size === 0) {
|
|
129
|
+
const initialMigration = migrations.find((m) => m.version === 1);
|
|
130
|
+
if (initialMigration) {
|
|
131
|
+
if (shouldBootstrapInitialMigration(db)) {
|
|
132
|
+
console.log("[migrations] Existing database detected — bootstrapping migration tracking");
|
|
133
|
+
db.run(
|
|
134
|
+
"INSERT INTO _migrations (version, name, applied_at, checksum) VALUES (?, ?, ?, ?)",
|
|
135
|
+
[
|
|
136
|
+
initialMigration.version,
|
|
137
|
+
initialMigration.name,
|
|
138
|
+
new Date().toISOString(),
|
|
139
|
+
initialMigration.checksum,
|
|
140
|
+
],
|
|
141
|
+
);
|
|
142
|
+
applied.set(initialMigration.version, {
|
|
143
|
+
version: initialMigration.version,
|
|
144
|
+
name: initialMigration.name,
|
|
145
|
+
checksum: initialMigration.checksum,
|
|
146
|
+
});
|
|
147
|
+
} else {
|
|
148
|
+
console.log(
|
|
149
|
+
"[migrations] Existing database appears incomplete — applying 001_initial migration",
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 5. Run pending migrations
|
|
156
|
+
for (const migration of migrations) {
|
|
157
|
+
const existing = applied.get(migration.version);
|
|
158
|
+
|
|
159
|
+
if (existing) {
|
|
160
|
+
// Verify checksum hasn't changed
|
|
161
|
+
if (existing.checksum !== migration.checksum) {
|
|
162
|
+
console.warn(
|
|
163
|
+
`[migrations] WARNING: Migration ${migration.name} checksum mismatch. ` +
|
|
164
|
+
`Applied: ${existing.checksum.slice(0, 12)}..., Current: ${migration.checksum.slice(0, 12)}... ` +
|
|
165
|
+
`Do not modify applied migrations — create a new one instead.`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Apply migration in a transaction
|
|
172
|
+
console.log(`[migrations] Applying: ${migration.name}`);
|
|
173
|
+
const start = performance.now();
|
|
174
|
+
|
|
175
|
+
db.transaction(() => {
|
|
176
|
+
db.exec(migration.sql);
|
|
177
|
+
db.run("INSERT INTO _migrations (version, name, applied_at, checksum) VALUES (?, ?, ?, ?)", [
|
|
178
|
+
migration.version,
|
|
179
|
+
migration.name,
|
|
180
|
+
new Date().toISOString(),
|
|
181
|
+
migration.checksum,
|
|
182
|
+
]);
|
|
183
|
+
})();
|
|
184
|
+
|
|
185
|
+
const elapsed = (performance.now() - start).toFixed(1);
|
|
186
|
+
console.log(`[migrations] Applied: ${migration.name} (${elapsed}ms)`);
|
|
187
|
+
}
|
|
188
|
+
}
|
package/src/be/seed.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed default prompt templates into the DB from the in-memory code registry.
|
|
3
|
+
*
|
|
4
|
+
* Called from initDb() after migrations run. Ensures every registered
|
|
5
|
+
* EventTemplateDefinition has a corresponding global default in the
|
|
6
|
+
* prompt_templates table.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { getAllTemplateDefinitions } from "../prompts/registry";
|
|
10
|
+
import { getPromptTemplates, resetPromptTemplateToDefault, upsertPromptTemplate } from "./db";
|
|
11
|
+
|
|
12
|
+
// Side-effect imports: register ALL template definitions so they're seeded on API startup.
|
|
13
|
+
// Webhook handler templates (github, gitlab, etc.) are loaded transitively by the API server's
|
|
14
|
+
// handler imports, but runner/session templates are only loaded by the worker. Importing them
|
|
15
|
+
// here ensures all templates are available for the render endpoint and seeded to the DB.
|
|
16
|
+
import "../prompts/session-templates";
|
|
17
|
+
import "../commands/templates";
|
|
18
|
+
import "../tools/templates";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Seed default templates into the DB.
|
|
22
|
+
*
|
|
23
|
+
* For each registered EventTemplateDefinition:
|
|
24
|
+
* - If no global record exists at all, insert one as default (isDefault=true, state=enabled)
|
|
25
|
+
* - If a global default (isDefault=true) exists and its body differs from code, update it
|
|
26
|
+
* - Never touch records where isDefault=false (user customizations)
|
|
27
|
+
*/
|
|
28
|
+
export function seedDefaultTemplates(): void {
|
|
29
|
+
const definitions = getAllTemplateDefinitions();
|
|
30
|
+
|
|
31
|
+
if (definitions.length === 0) {
|
|
32
|
+
return; // No templates registered yet — expected during early phases
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const def of definitions) {
|
|
36
|
+
// Look for ALL existing global records for this eventType (both default and customized)
|
|
37
|
+
const allGlobal = getPromptTemplates({
|
|
38
|
+
eventType: def.eventType,
|
|
39
|
+
scope: "global",
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const globalRecord = allGlobal.find((t) => t.scopeId === null);
|
|
43
|
+
|
|
44
|
+
if (!globalRecord) {
|
|
45
|
+
// No global record at all — seed one with isDefault=true directly.
|
|
46
|
+
upsertPromptTemplate({
|
|
47
|
+
eventType: def.eventType,
|
|
48
|
+
scope: "global",
|
|
49
|
+
body: def.defaultBody,
|
|
50
|
+
createdBy: "system",
|
|
51
|
+
changeReason: "Seeded from code registry",
|
|
52
|
+
isDefault: true,
|
|
53
|
+
});
|
|
54
|
+
} else if (globalRecord.isDefault && globalRecord.body !== def.defaultBody) {
|
|
55
|
+
// Global default exists but body has drifted from code — update it.
|
|
56
|
+
// Only update if the record is still marked as default (not user-customized).
|
|
57
|
+
resetPromptTemplateToDefault(globalRecord.id, def.defaultBody);
|
|
58
|
+
}
|
|
59
|
+
// If record exists with isDefault=false (user customization): leave it alone
|
|
60
|
+
// If record exists with isDefault=true and body matches: leave it alone
|
|
61
|
+
}
|
|
62
|
+
}
|