profclaw 0.0.1-beta.1
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/.env.example +215 -0
- package/CHANGELOG.md +49 -0
- package/CONTRIBUTING.md +119 -0
- package/Dockerfile +107 -0
- package/LICENSE +661 -0
- package/README.md +196 -0
- package/config/agents.yml +55 -0
- package/config/budget.yml +15 -0
- package/config/pricing.yml +46 -0
- package/config/settings.yml +168 -0
- package/dist/adapters/claude-code.d.ts +46 -0
- package/dist/adapters/claude-code.js +215 -0
- package/dist/adapters/index.d.ts +4 -0
- package/dist/adapters/index.js +4 -0
- package/dist/adapters/ollama.d.ts +45 -0
- package/dist/adapters/ollama.js +277 -0
- package/dist/adapters/openclaw.d.ts +60 -0
- package/dist/adapters/openclaw.js +289 -0
- package/dist/adapters/registry.d.ts +56 -0
- package/dist/adapters/registry.js +163 -0
- package/dist/agents/executor.d.ts +78 -0
- package/dist/agents/executor.js +657 -0
- package/dist/agents/index.d.ts +10 -0
- package/dist/agents/index.js +27 -0
- package/dist/agents/stop-conditions.d.ts +108 -0
- package/dist/agents/stop-conditions.js +299 -0
- package/dist/agents/types.d.ts +185 -0
- package/dist/agents/types.js +14 -0
- package/dist/ai/embedding-service.d.ts +96 -0
- package/dist/ai/embedding-service.js +333 -0
- package/dist/auth/api-tokens.d.ts +71 -0
- package/dist/auth/api-tokens.js +235 -0
- package/dist/auth/auth-service.d.ts +75 -0
- package/dist/auth/auth-service.js +557 -0
- package/dist/auth/device-identity.d.ts +96 -0
- package/dist/auth/device-identity.js +250 -0
- package/dist/auth/github-oauth.d.ts +20 -0
- package/dist/auth/github-oauth.js +59 -0
- package/dist/auth/jira-oauth.d.ts +25 -0
- package/dist/auth/jira-oauth.js +75 -0
- package/dist/auth/linear-oauth.d.ts +21 -0
- package/dist/auth/linear-oauth.js +59 -0
- package/dist/auth/middleware.d.ts +44 -0
- package/dist/auth/middleware.js +190 -0
- package/dist/auth/pairing-codes.d.ts +109 -0
- package/dist/auth/pairing-codes.js +274 -0
- package/dist/auth/password.d.ts +53 -0
- package/dist/auth/password.js +126 -0
- package/dist/auth/qr-pairing.d.ts +36 -0
- package/dist/auth/qr-pairing.js +138 -0
- package/dist/auth/slack-oauth.d.ts +31 -0
- package/dist/auth/slack-oauth.js +80 -0
- package/dist/backup/index.d.ts +50 -0
- package/dist/backup/index.js +184 -0
- package/dist/browser/adapters.d.ts +25 -0
- package/dist/browser/adapters.js +32 -0
- package/dist/browser/cli.d.ts +19 -0
- package/dist/browser/cli.js +277 -0
- package/dist/browser/compression.d.ts +32 -0
- package/dist/browser/compression.js +269 -0
- package/dist/browser/extensions.d.ts +144 -0
- package/dist/browser/extensions.js +251 -0
- package/dist/browser/index.d.ts +37 -0
- package/dist/browser/index.js +43 -0
- package/dist/browser/refs.d.ts +46 -0
- package/dist/browser/refs.js +120 -0
- package/dist/browser/search.d.ts +36 -0
- package/dist/browser/search.js +193 -0
- package/dist/browser/service.d.ts +94 -0
- package/dist/browser/service.js +358 -0
- package/dist/browser/snapshot.d.ts +19 -0
- package/dist/browser/snapshot.js +250 -0
- package/dist/browser/tools.d.ts +259 -0
- package/dist/browser/tools.js +463 -0
- package/dist/browser/types.d.ts +134 -0
- package/dist/browser/types.js +17 -0
- package/dist/chat/agentic-executor.d.ts +108 -0
- package/dist/chat/agentic-executor.js +739 -0
- package/dist/chat/api-key-detector.d.ts +41 -0
- package/dist/chat/api-key-detector.js +290 -0
- package/dist/chat/auto-reply.d.ts +90 -0
- package/dist/chat/auto-reply.js +272 -0
- package/dist/chat/conversations.d.ts +91 -0
- package/dist/chat/conversations.js +297 -0
- package/dist/chat/execution/audit.d.ts +192 -0
- package/dist/chat/execution/audit.js +323 -0
- package/dist/chat/execution/executor.d.ts +56 -0
- package/dist/chat/execution/executor.js +654 -0
- package/dist/chat/execution/guardrails.d.ts +98 -0
- package/dist/chat/execution/guardrails.js +571 -0
- package/dist/chat/execution/index.d.ts +61 -0
- package/dist/chat/execution/index.js +129 -0
- package/dist/chat/execution/model-capability.d.ts +34 -0
- package/dist/chat/execution/model-capability.js +96 -0
- package/dist/chat/execution/process-pool.d.ts +110 -0
- package/dist/chat/execution/process-pool.js +290 -0
- package/dist/chat/execution/pty.d.ts +92 -0
- package/dist/chat/execution/pty.js +285 -0
- package/dist/chat/execution/rate-limiter.d.ts +87 -0
- package/dist/chat/execution/rate-limiter.js +305 -0
- package/dist/chat/execution/registry.d.ts +54 -0
- package/dist/chat/execution/registry.js +220 -0
- package/dist/chat/execution/sandbox.d.ts +109 -0
- package/dist/chat/execution/sandbox.js +684 -0
- package/dist/chat/execution/secrets.d.ts +45 -0
- package/dist/chat/execution/secrets.js +338 -0
- package/dist/chat/execution/security.d.ts +179 -0
- package/dist/chat/execution/security.js +739 -0
- package/dist/chat/execution/self-correction.d.ts +162 -0
- package/dist/chat/execution/self-correction.js +557 -0
- package/dist/chat/execution/session-manager.d.ts +79 -0
- package/dist/chat/execution/session-manager.js +356 -0
- package/dist/chat/execution/session-spawn/config.d.ts +37 -0
- package/dist/chat/execution/session-spawn/config.js +83 -0
- package/dist/chat/execution/session-spawn/index.d.ts +10 -0
- package/dist/chat/execution/session-spawn/index.js +10 -0
- package/dist/chat/execution/session-spawn/manager.d.ts +35 -0
- package/dist/chat/execution/session-spawn/manager.js +418 -0
- package/dist/chat/execution/session-spawn/types.d.ts +117 -0
- package/dist/chat/execution/session-spawn/types.js +16 -0
- package/dist/chat/execution/smart-prompts.d.ts +34 -0
- package/dist/chat/execution/smart-prompts.js +151 -0
- package/dist/chat/execution/stream-results.d.ts +65 -0
- package/dist/chat/execution/stream-results.js +156 -0
- package/dist/chat/execution/tool-router.d.ts +76 -0
- package/dist/chat/execution/tool-router.js +296 -0
- package/dist/chat/execution/tools/agents-list.d.ts +49 -0
- package/dist/chat/execution/tools/agents-list.js +165 -0
- package/dist/chat/execution/tools/browser.d.ts +12 -0
- package/dist/chat/execution/tools/browser.js +14 -0
- package/dist/chat/execution/tools/canvas.d.ts +61 -0
- package/dist/chat/execution/tools/canvas.js +150 -0
- package/dist/chat/execution/tools/complete-task.d.ts +72 -0
- package/dist/chat/execution/tools/complete-task.js +104 -0
- package/dist/chat/execution/tools/cron-tool.d.ts +204 -0
- package/dist/chat/execution/tools/cron-tool.js +680 -0
- package/dist/chat/execution/tools/discord-actions.d.ts +120 -0
- package/dist/chat/execution/tools/discord-actions.js +361 -0
- package/dist/chat/execution/tools/exec.d.ts +43 -0
- package/dist/chat/execution/tools/exec.js +223 -0
- package/dist/chat/execution/tools/file-ops.d.ts +175 -0
- package/dist/chat/execution/tools/file-ops.js +723 -0
- package/dist/chat/execution/tools/git.d.ts +143 -0
- package/dist/chat/execution/tools/git.js +395 -0
- package/dist/chat/execution/tools/github.d.ts +42 -0
- package/dist/chat/execution/tools/github.js +184 -0
- package/dist/chat/execution/tools/glinr-ops.d.ts +202 -0
- package/dist/chat/execution/tools/glinr-ops.js +694 -0
- package/dist/chat/execution/tools/image-analyze.d.ts +29 -0
- package/dist/chat/execution/tools/image-analyze.js +127 -0
- package/dist/chat/execution/tools/index.d.ts +64 -0
- package/dist/chat/execution/tools/index.js +245 -0
- package/dist/chat/execution/tools/integrations.d.ts +109 -0
- package/dist/chat/execution/tools/integrations.js +237 -0
- package/dist/chat/execution/tools/link-understand.d.ts +34 -0
- package/dist/chat/execution/tools/link-understand.js +307 -0
- package/dist/chat/execution/tools/maintenance.d.ts +29 -0
- package/dist/chat/execution/tools/maintenance.js +105 -0
- package/dist/chat/execution/tools/memory-tools.d.ts +76 -0
- package/dist/chat/execution/tools/memory-tools.js +278 -0
- package/dist/chat/execution/tools/openai-image-gen.d.ts +51 -0
- package/dist/chat/execution/tools/openai-image-gen.js +212 -0
- package/dist/chat/execution/tools/profclaw-ops.d.ts +204 -0
- package/dist/chat/execution/tools/profclaw-ops.js +665 -0
- package/dist/chat/execution/tools/session-spawn.d.ts +146 -0
- package/dist/chat/execution/tools/session-spawn.js +544 -0
- package/dist/chat/execution/tools/session-status.d.ts +38 -0
- package/dist/chat/execution/tools/session-status.js +185 -0
- package/dist/chat/execution/tools/sessions-list.d.ts +49 -0
- package/dist/chat/execution/tools/sessions-list.js +153 -0
- package/dist/chat/execution/tools/sessions-send.d.ts +48 -0
- package/dist/chat/execution/tools/sessions-send.js +207 -0
- package/dist/chat/execution/tools/sessions-spawn.d.ts +51 -0
- package/dist/chat/execution/tools/sessions-spawn.js +137 -0
- package/dist/chat/execution/tools/slack-actions.d.ts +90 -0
- package/dist/chat/execution/tools/slack-actions.js +272 -0
- package/dist/chat/execution/tools/subagent-orchestrate.d.ts +66 -0
- package/dist/chat/execution/tools/subagent-orchestrate.js +313 -0
- package/dist/chat/execution/tools/system.d.ts +121 -0
- package/dist/chat/execution/tools/system.js +415 -0
- package/dist/chat/execution/tools/telegram-actions.d.ts +126 -0
- package/dist/chat/execution/tools/telegram-actions.js +339 -0
- package/dist/chat/execution/tools/test-run.d.ts +43 -0
- package/dist/chat/execution/tools/test-run.js +391 -0
- package/dist/chat/execution/tools/tts-speak.d.ts +39 -0
- package/dist/chat/execution/tools/tts-speak.js +199 -0
- package/dist/chat/execution/tools/web-fetch.d.ts +42 -0
- package/dist/chat/execution/tools/web-fetch.js +247 -0
- package/dist/chat/execution/tools/web-search.d.ts +53 -0
- package/dist/chat/execution/tools/web-search.js +130 -0
- package/dist/chat/execution/types.d.ts +337 -0
- package/dist/chat/execution/types.js +8 -0
- package/dist/chat/execution/workflows/built-in.d.ts +10 -0
- package/dist/chat/execution/workflows/built-in.js +249 -0
- package/dist/chat/execution/workflows/executor.d.ts +13 -0
- package/dist/chat/execution/workflows/executor.js +259 -0
- package/dist/chat/execution/workflows/index.d.ts +5 -0
- package/dist/chat/execution/workflows/index.js +5 -0
- package/dist/chat/execution/workflows/trigger.d.ts +15 -0
- package/dist/chat/execution/workflows/trigger.js +111 -0
- package/dist/chat/execution/workflows/types.d.ts +80 -0
- package/dist/chat/execution/workflows/types.js +2 -0
- package/dist/chat/failover/error.d.ts +73 -0
- package/dist/chat/failover/error.js +412 -0
- package/dist/chat/failover/index.d.ts +10 -0
- package/dist/chat/failover/index.js +11 -0
- package/dist/chat/failover/model-fallback.d.ts +97 -0
- package/dist/chat/failover/model-fallback.js +328 -0
- package/dist/chat/failover/types.d.ts +47 -0
- package/dist/chat/failover/types.js +8 -0
- package/dist/chat/format/chunk.d.ts +59 -0
- package/dist/chat/format/chunk.js +253 -0
- package/dist/chat/format/index.d.ts +7 -0
- package/dist/chat/format/index.js +7 -0
- package/dist/chat/format/tool-result-formatter.d.ts +30 -0
- package/dist/chat/format/tool-result-formatter.js +177 -0
- package/dist/chat/group.d.ts +232 -0
- package/dist/chat/group.js +311 -0
- package/dist/chat/index.d.ts +21 -0
- package/dist/chat/index.js +30 -0
- package/dist/chat/memory.d.ts +108 -0
- package/dist/chat/memory.js +343 -0
- package/dist/chat/message-handler.d.ts +38 -0
- package/dist/chat/message-handler.js +274 -0
- package/dist/chat/proactive/index.d.ts +167 -0
- package/dist/chat/proactive/index.js +721 -0
- package/dist/chat/prompt-adapter.d.ts +52 -0
- package/dist/chat/prompt-adapter.js +245 -0
- package/dist/chat/providers/dingtalk/index.d.ts +69 -0
- package/dist/chat/providers/dingtalk/index.js +225 -0
- package/dist/chat/providers/discord/index.d.ts +264 -0
- package/dist/chat/providers/discord/index.js +657 -0
- package/dist/chat/providers/feishu/index.d.ts +97 -0
- package/dist/chat/providers/feishu/index.js +362 -0
- package/dist/chat/providers/googlechat/index.d.ts +269 -0
- package/dist/chat/providers/googlechat/index.js +634 -0
- package/dist/chat/providers/imessage/index.d.ts +61 -0
- package/dist/chat/providers/imessage/index.js +166 -0
- package/dist/chat/providers/index.d.ts +76 -0
- package/dist/chat/providers/index.js +430 -0
- package/dist/chat/providers/irc/index.d.ts +101 -0
- package/dist/chat/providers/irc/index.js +557 -0
- package/dist/chat/providers/line/index.d.ts +113 -0
- package/dist/chat/providers/line/index.js +434 -0
- package/dist/chat/providers/matrix/index.d.ts +161 -0
- package/dist/chat/providers/matrix/index.js +559 -0
- package/dist/chat/providers/mattermost/index.d.ts +106 -0
- package/dist/chat/providers/mattermost/index.js +425 -0
- package/dist/chat/providers/msteams/index.d.ts +198 -0
- package/dist/chat/providers/msteams/index.js +694 -0
- package/dist/chat/providers/nextcloud/index.d.ts +52 -0
- package/dist/chat/providers/nextcloud/index.js +156 -0
- package/dist/chat/providers/nostr/index.d.ts +60 -0
- package/dist/chat/providers/nostr/index.js +200 -0
- package/dist/chat/providers/qq/index.d.ts +57 -0
- package/dist/chat/providers/qq/index.js +260 -0
- package/dist/chat/providers/registry.d.ts +89 -0
- package/dist/chat/providers/registry.js +213 -0
- package/dist/chat/providers/signal/index.d.ts +88 -0
- package/dist/chat/providers/signal/index.js +357 -0
- package/dist/chat/providers/slack/index.d.ts +52 -0
- package/dist/chat/providers/slack/index.js +477 -0
- package/dist/chat/providers/synology/index.d.ts +50 -0
- package/dist/chat/providers/synology/index.js +138 -0
- package/dist/chat/providers/telegram/index.d.ts +148 -0
- package/dist/chat/providers/telegram/index.js +492 -0
- package/dist/chat/providers/tlon/index.d.ts +44 -0
- package/dist/chat/providers/tlon/index.js +243 -0
- package/dist/chat/providers/twitch/index.d.ts +79 -0
- package/dist/chat/providers/twitch/index.js +349 -0
- package/dist/chat/providers/types.d.ts +437 -0
- package/dist/chat/providers/types.js +14 -0
- package/dist/chat/providers/webchat/index.d.ts +38 -0
- package/dist/chat/providers/webchat/index.js +214 -0
- package/dist/chat/providers/wecom/index.d.ts +62 -0
- package/dist/chat/providers/wecom/index.js +228 -0
- package/dist/chat/providers/whatsapp/index.d.ts +147 -0
- package/dist/chat/providers/whatsapp/index.js +396 -0
- package/dist/chat/providers/zalo/index.d.ts +54 -0
- package/dist/chat/providers/zalo/index.js +158 -0
- package/dist/chat/providers/zalo-personal/index.d.ts +53 -0
- package/dist/chat/providers/zalo-personal/index.js +212 -0
- package/dist/chat/skills.d.ts +82 -0
- package/dist/chat/skills.js +410 -0
- package/dist/chat/system-prompts.d.ts +76 -0
- package/dist/chat/system-prompts.js +407 -0
- package/dist/chat/tool-handler.d.ts +57 -0
- package/dist/chat/tool-handler.js +336 -0
- package/dist/chat/tools.d.ts +373 -0
- package/dist/chat/tools.js +512 -0
- package/dist/cli/commands/agent.d.ts +3 -0
- package/dist/cli/commands/agent.js +108 -0
- package/dist/cli/commands/auth.d.ts +12 -0
- package/dist/cli/commands/auth.js +301 -0
- package/dist/cli/commands/browser.d.ts +3 -0
- package/dist/cli/commands/browser.js +138 -0
- package/dist/cli/commands/canvas.d.ts +3 -0
- package/dist/cli/commands/canvas.js +155 -0
- package/dist/cli/commands/channels.d.ts +3 -0
- package/dist/cli/commands/channels.js +167 -0
- package/dist/cli/commands/chat.d.ts +9 -0
- package/dist/cli/commands/chat.js +360 -0
- package/dist/cli/commands/completion.d.ts +3 -0
- package/dist/cli/commands/completion.js +170 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.js +193 -0
- package/dist/cli/commands/cost.d.ts +3 -0
- package/dist/cli/commands/cost.js +134 -0
- package/dist/cli/commands/daemon.d.ts +3 -0
- package/dist/cli/commands/daemon.js +381 -0
- package/dist/cli/commands/devices.d.ts +3 -0
- package/dist/cli/commands/devices.js +150 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.js +295 -0
- package/dist/cli/commands/logs.d.ts +3 -0
- package/dist/cli/commands/logs.js +139 -0
- package/dist/cli/commands/mcp.d.ts +15 -0
- package/dist/cli/commands/mcp.js +157 -0
- package/dist/cli/commands/memory.d.ts +3 -0
- package/dist/cli/commands/memory.js +170 -0
- package/dist/cli/commands/models.d.ts +3 -0
- package/dist/cli/commands/models.js +197 -0
- package/dist/cli/commands/nodes.d.ts +3 -0
- package/dist/cli/commands/nodes.js +193 -0
- package/dist/cli/commands/onboard.d.ts +13 -0
- package/dist/cli/commands/onboard.js +360 -0
- package/dist/cli/commands/plugin.d.ts +15 -0
- package/dist/cli/commands/plugin.js +226 -0
- package/dist/cli/commands/provider.d.ts +16 -0
- package/dist/cli/commands/provider.js +320 -0
- package/dist/cli/commands/security.d.ts +3 -0
- package/dist/cli/commands/security.js +180 -0
- package/dist/cli/commands/serve.d.ts +3 -0
- package/dist/cli/commands/serve.js +179 -0
- package/dist/cli/commands/session.d.ts +3 -0
- package/dist/cli/commands/session.js +172 -0
- package/dist/cli/commands/setup.d.ts +13 -0
- package/dist/cli/commands/setup.js +636 -0
- package/dist/cli/commands/skill.d.ts +15 -0
- package/dist/cli/commands/skill.js +191 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.js +71 -0
- package/dist/cli/commands/summary.d.ts +3 -0
- package/dist/cli/commands/summary.js +160 -0
- package/dist/cli/commands/task.d.ts +3 -0
- package/dist/cli/commands/task.js +170 -0
- package/dist/cli/commands/ticket.d.ts +3 -0
- package/dist/cli/commands/ticket.js +421 -0
- package/dist/cli/commands/tools.d.ts +9 -0
- package/dist/cli/commands/tools.js +508 -0
- package/dist/cli/commands/tui.d.ts +3 -0
- package/dist/cli/commands/tui.js +158 -0
- package/dist/cli/commands/tunnel.d.ts +3 -0
- package/dist/cli/commands/tunnel.js +135 -0
- package/dist/cli/commands/webhooks.d.ts +3 -0
- package/dist/cli/commands/webhooks.js +191 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +127 -0
- package/dist/cli/utils/api.d.ts +17 -0
- package/dist/cli/utils/api.js +63 -0
- package/dist/cli/utils/config.d.ts +31 -0
- package/dist/cli/utils/config.js +81 -0
- package/dist/cli/utils/output.d.ts +58 -0
- package/dist/cli/utils/output.js +148 -0
- package/dist/core/deployment.d.ts +30 -0
- package/dist/core/deployment.js +114 -0
- package/dist/core/sandbox-config.d.ts +63 -0
- package/dist/core/sandbox-config.js +148 -0
- package/dist/costs/budget.d.ts +28 -0
- package/dist/costs/budget.js +57 -0
- package/dist/costs/persistence.d.ts +77 -0
- package/dist/costs/persistence.js +210 -0
- package/dist/costs/pricing.d.ts +16 -0
- package/dist/costs/pricing.js +39 -0
- package/dist/costs/token-tracker.d.ts +34 -0
- package/dist/costs/token-tracker.js +141 -0
- package/dist/cron/heartbeat.d.ts +23 -0
- package/dist/cron/heartbeat.js +109 -0
- package/dist/cron/index.d.ts +22 -0
- package/dist/cron/index.js +37 -0
- package/dist/cron/issue-poller.d.ts +15 -0
- package/dist/cron/issue-poller.js +174 -0
- package/dist/cron/scheduler.d.ts +315 -0
- package/dist/cron/scheduler.js +1008 -0
- package/dist/cron/stale-checker.d.ts +16 -0
- package/dist/cron/stale-checker.js +61 -0
- package/dist/cron/templates.d.ts +107 -0
- package/dist/cron/templates.js +395 -0
- package/dist/diagnostics/exporters.d.ts +21 -0
- package/dist/diagnostics/exporters.js +138 -0
- package/dist/diagnostics/index.d.ts +10 -0
- package/dist/diagnostics/index.js +9 -0
- package/dist/diagnostics/middleware.d.ts +12 -0
- package/dist/diagnostics/middleware.js +58 -0
- package/dist/diagnostics/tracer.d.ts +133 -0
- package/dist/diagnostics/tracer.js +257 -0
- package/dist/discovery/index.d.ts +8 -0
- package/dist/discovery/index.js +7 -0
- package/dist/discovery/mdns.d.ts +40 -0
- package/dist/discovery/mdns.js +249 -0
- package/dist/gateway/index.d.ts +35 -0
- package/dist/gateway/index.js +36 -0
- package/dist/gateway/router.d.ts +110 -0
- package/dist/gateway/router.js +649 -0
- package/dist/gateway/types.d.ts +275 -0
- package/dist/gateway/types.js +2 -0
- package/dist/gateway/workflows.d.ts +37 -0
- package/dist/gateway/workflows.js +748 -0
- package/dist/hooks/agent-webhook.d.ts +277 -0
- package/dist/hooks/agent-webhook.js +197 -0
- package/dist/hooks/index.d.ts +13 -0
- package/dist/hooks/index.js +15 -0
- package/dist/hooks/prompt-submit.d.ts +45 -0
- package/dist/hooks/prompt-submit.js +111 -0
- package/dist/hooks/schemas.d.ts +563 -0
- package/dist/hooks/schemas.js +108 -0
- package/dist/hooks/session-end.d.ts +25 -0
- package/dist/hooks/session-end.js +153 -0
- package/dist/hooks/tool-use.d.ts +41 -0
- package/dist/hooks/tool-use.js +201 -0
- package/dist/hooks/types.d.ts +76 -0
- package/dist/hooks/types.js +7 -0
- package/dist/integrations/cloudflare-tunnel.d.ts +78 -0
- package/dist/integrations/cloudflare-tunnel.js +268 -0
- package/dist/integrations/github-client.d.ts +27 -0
- package/dist/integrations/github-client.js +79 -0
- package/dist/integrations/github-projects.d.ts +97 -0
- package/dist/integrations/github-projects.js +433 -0
- package/dist/integrations/github-ticket-sync.d.ts +82 -0
- package/dist/integrations/github-ticket-sync.js +352 -0
- package/dist/integrations/github.d.ts +11 -0
- package/dist/integrations/github.js +241 -0
- package/dist/integrations/jira-client.d.ts +30 -0
- package/dist/integrations/jira-client.js +67 -0
- package/dist/integrations/jira.d.ts +13 -0
- package/dist/integrations/jira.js +108 -0
- package/dist/integrations/linear-client.d.ts +23 -0
- package/dist/integrations/linear-client.js +52 -0
- package/dist/integrations/linear.d.ts +15 -0
- package/dist/integrations/linear.js +312 -0
- package/dist/integrations/tailscale.d.ts +68 -0
- package/dist/integrations/tailscale.js +173 -0
- package/dist/integrations/web-search.d.ts +112 -0
- package/dist/integrations/web-search.js +287 -0
- package/dist/intelligence/index.d.ts +8 -0
- package/dist/intelligence/index.js +8 -0
- package/dist/intelligence/ollama.d.ts +50 -0
- package/dist/intelligence/ollama.js +213 -0
- package/dist/intelligence/rules.d.ts +39 -0
- package/dist/intelligence/rules.js +308 -0
- package/dist/labels/index.d.ts +93 -0
- package/dist/labels/index.js +248 -0
- package/dist/mcp/browser-tools.d.ts +10 -0
- package/dist/mcp/browser-tools.js +16 -0
- package/dist/mcp/client.d.ts +54 -0
- package/dist/mcp/client.js +153 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.js +13 -0
- package/dist/mcp/server.d.ts +40 -0
- package/dist/mcp/server.js +826 -0
- package/dist/mcp/tool-adapter.d.ts +49 -0
- package/dist/mcp/tool-adapter.js +193 -0
- package/dist/memory/experience-store.d.ts +121 -0
- package/dist/memory/experience-store.js +439 -0
- package/dist/memory/index.d.ts +8 -0
- package/dist/memory/index.js +25 -0
- package/dist/memory/memory-service.d.ts +312 -0
- package/dist/memory/memory-service.js +1172 -0
- package/dist/memory/memory-watcher.d.ts +116 -0
- package/dist/memory/memory-watcher.js +239 -0
- package/dist/middleware/logging.d.ts +34 -0
- package/dist/middleware/logging.js +184 -0
- package/dist/middleware/rate-limit.d.ts +29 -0
- package/dist/middleware/rate-limit.js +91 -0
- package/dist/notifications/in-app.d.ts +28 -0
- package/dist/notifications/in-app.js +53 -0
- package/dist/notifications/index.d.ts +3 -0
- package/dist/notifications/index.js +3 -0
- package/dist/notifications/push.d.ts +74 -0
- package/dist/notifications/push.js +175 -0
- package/dist/notifications/slack.d.ts +32 -0
- package/dist/notifications/slack.js +157 -0
- package/dist/plugins/clawhub.d.ts +70 -0
- package/dist/plugins/clawhub.js +260 -0
- package/dist/plugins/loader.d.ts +23 -0
- package/dist/plugins/loader.js +140 -0
- package/dist/plugins/marketplace.d.ts +77 -0
- package/dist/plugins/marketplace.js +275 -0
- package/dist/plugins/registry.d.ts +122 -0
- package/dist/plugins/registry.js +352 -0
- package/dist/plugins/sandbox.d.ts +77 -0
- package/dist/plugins/sandbox.js +287 -0
- package/dist/plugins/scaffolder.d.ts +28 -0
- package/dist/plugins/scaffolder.js +409 -0
- package/dist/plugins/sdk.d.ts +35 -0
- package/dist/plugins/sdk.js +8 -0
- package/dist/plugins/search/brave.d.ts +9 -0
- package/dist/plugins/search/brave.js +157 -0
- package/dist/plugins/search/duckduckgo.d.ts +9 -0
- package/dist/plugins/search/duckduckgo.js +171 -0
- package/dist/plugins/search/index.d.ts +13 -0
- package/dist/plugins/search/index.js +23 -0
- package/dist/plugins/search/searxng.d.ts +9 -0
- package/dist/plugins/search/searxng.js +170 -0
- package/dist/plugins/search/serper.d.ts +9 -0
- package/dist/plugins/search/serper.js +135 -0
- package/dist/plugins/search/tavily.d.ts +9 -0
- package/dist/plugins/search/tavily.js +146 -0
- package/dist/plugins/types.d.ts +174 -0
- package/dist/plugins/types.js +8 -0
- package/dist/projects/index.d.ts +133 -0
- package/dist/projects/index.js +897 -0
- package/dist/projects/types.d.ts +444 -0
- package/dist/projects/types.js +207 -0
- package/dist/providers/adapters/anthropic.d.ts +26 -0
- package/dist/providers/adapters/anthropic.js +306 -0
- package/dist/providers/adapters/base.d.ts +53 -0
- package/dist/providers/adapters/base.js +99 -0
- package/dist/providers/adapters/ollama.d.ts +30 -0
- package/dist/providers/adapters/ollama.js +292 -0
- package/dist/providers/ai-sdk.d.ts +178 -0
- package/dist/providers/ai-sdk.js +1552 -0
- package/dist/providers/core/index.d.ts +8 -0
- package/dist/providers/core/index.js +10 -0
- package/dist/providers/core/models.d.ts +31 -0
- package/dist/providers/core/models.js +949 -0
- package/dist/providers/core/types.d.ts +117 -0
- package/dist/providers/core/types.js +83 -0
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.js +7 -0
- package/dist/providers/registry.d.ts +93 -0
- package/dist/providers/registry.js +228 -0
- package/dist/providers/schema-utils.d.ts +23 -0
- package/dist/providers/schema-utils.js +545 -0
- package/dist/providers/types.d.ts +609 -0
- package/dist/providers/types.js +279 -0
- package/dist/queue/failure-handler.d.ts +93 -0
- package/dist/queue/failure-handler.js +379 -0
- package/dist/queue/index.d.ts +23 -0
- package/dist/queue/index.js +86 -0
- package/dist/queue/memory-queue.d.ts +30 -0
- package/dist/queue/memory-queue.js +429 -0
- package/dist/queue/notifications.d.ts +6 -0
- package/dist/queue/notifications.js +128 -0
- package/dist/queue/task-queue.d.ts +55 -0
- package/dist/queue/task-queue.js +518 -0
- package/dist/queue/webhook-queue.d.ts +47 -0
- package/dist/queue/webhook-queue.js +158 -0
- package/dist/routes/agents.d.ts +4 -0
- package/dist/routes/agents.js +45 -0
- package/dist/routes/auth.d.ts +19 -0
- package/dist/routes/auth.js +492 -0
- package/dist/routes/backup.d.ts +6 -0
- package/dist/routes/backup.js +71 -0
- package/dist/routes/chat.d.ts +10 -0
- package/dist/routes/chat.js +1678 -0
- package/dist/routes/clawhub.d.ts +8 -0
- package/dist/routes/clawhub.js +89 -0
- package/dist/routes/costs.d.ts +4 -0
- package/dist/routes/costs.js +78 -0
- package/dist/routes/cron.d.ts +11 -0
- package/dist/routes/cron.js +708 -0
- package/dist/routes/devices.d.ts +9 -0
- package/dist/routes/devices.js +490 -0
- package/dist/routes/discord.d.ts +15 -0
- package/dist/routes/discord.js +524 -0
- package/dist/routes/dlq.d.ts +4 -0
- package/dist/routes/dlq.js +64 -0
- package/dist/routes/gateway.d.ts +4 -0
- package/dist/routes/gateway.js +253 -0
- package/dist/routes/health.d.ts +29 -0
- package/dist/routes/health.js +296 -0
- package/dist/routes/hooks.d.ts +4 -0
- package/dist/routes/hooks.js +170 -0
- package/dist/routes/import.d.ts +9 -0
- package/dist/routes/import.js +540 -0
- package/dist/routes/index.d.ts +38 -0
- package/dist/routes/index.js +39 -0
- package/dist/routes/integrations.d.ts +10 -0
- package/dist/routes/integrations.js +200 -0
- package/dist/routes/labels.d.ts +8 -0
- package/dist/routes/labels.js +240 -0
- package/dist/routes/mcp.d.ts +14 -0
- package/dist/routes/mcp.js +125 -0
- package/dist/routes/memory.d.ts +10 -0
- package/dist/routes/memory.js +622 -0
- package/dist/routes/notifications.d.ts +9 -0
- package/dist/routes/notifications.js +154 -0
- package/dist/routes/oobe.d.ts +10 -0
- package/dist/routes/oobe.js +405 -0
- package/dist/routes/openapi.d.ts +9 -0
- package/dist/routes/openapi.js +537 -0
- package/dist/routes/plugins.d.ts +8 -0
- package/dist/routes/plugins.js +108 -0
- package/dist/routes/projects.d.ts +8 -0
- package/dist/routes/projects.js +592 -0
- package/dist/routes/push.d.ts +8 -0
- package/dist/routes/push.js +75 -0
- package/dist/routes/search.d.ts +4 -0
- package/dist/routes/search.js +189 -0
- package/dist/routes/security.d.ts +10 -0
- package/dist/routes/security.js +189 -0
- package/dist/routes/settings.d.ts +4 -0
- package/dist/routes/settings.js +119 -0
- package/dist/routes/setup.d.ts +11 -0
- package/dist/routes/setup.js +525 -0
- package/dist/routes/skills.d.ts +13 -0
- package/dist/routes/skills.js +152 -0
- package/dist/routes/slack.d.ts +12 -0
- package/dist/routes/slack.js +999 -0
- package/dist/routes/states.d.ts +8 -0
- package/dist/routes/states.js +123 -0
- package/dist/routes/stats.d.ts +6 -0
- package/dist/routes/stats.js +369 -0
- package/dist/routes/summaries.d.ts +4 -0
- package/dist/routes/summaries.js +344 -0
- package/dist/routes/sync.d.ts +13 -0
- package/dist/routes/sync.js +268 -0
- package/dist/routes/tasks.d.ts +4 -0
- package/dist/routes/tasks.js +473 -0
- package/dist/routes/telegram.d.ts +14 -0
- package/dist/routes/telegram.js +420 -0
- package/dist/routes/tickets.d.ts +4 -0
- package/dist/routes/tickets.js +1090 -0
- package/dist/routes/tokens.d.ts +4 -0
- package/dist/routes/tokens.js +83 -0
- package/dist/routes/tools.d.ts +14 -0
- package/dist/routes/tools.js +790 -0
- package/dist/routes/tunnels.d.ts +8 -0
- package/dist/routes/tunnels.js +145 -0
- package/dist/routes/users.d.ts +15 -0
- package/dist/routes/users.js +998 -0
- package/dist/routes/voice.d.ts +8 -0
- package/dist/routes/voice.js +127 -0
- package/dist/routes/webchat.d.ts +11 -0
- package/dist/routes/webchat.js +173 -0
- package/dist/routes/webhook-dedup.d.ts +11 -0
- package/dist/routes/webhook-dedup.js +49 -0
- package/dist/routes/webhooks.d.ts +4 -0
- package/dist/routes/webhooks.js +71 -0
- package/dist/routes/whatsapp.d.ts +14 -0
- package/dist/routes/whatsapp.js +391 -0
- package/dist/security/audit-scanner.d.ts +32 -0
- package/dist/security/audit-scanner.js +217 -0
- package/dist/security/fs-guard.d.ts +41 -0
- package/dist/security/fs-guard.js +206 -0
- package/dist/security/prompt-guard.d.ts +47 -0
- package/dist/security/prompt-guard.js +198 -0
- package/dist/security/ssrf-guard.d.ts +38 -0
- package/dist/security/ssrf-guard.js +266 -0
- package/dist/security/types.d.ts +92 -0
- package/dist/security/types.js +8 -0
- package/dist/server/route-loader.d.ts +15 -0
- package/dist/server/route-loader.js +135 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +835 -0
- package/dist/settings/index.d.ts +841 -0
- package/dist/settings/index.js +451 -0
- package/dist/skills/compiler.d.ts +83 -0
- package/dist/skills/compiler.js +358 -0
- package/dist/skills/frontmatter.d.ts +33 -0
- package/dist/skills/frontmatter.js +175 -0
- package/dist/skills/index.d.ts +19 -0
- package/dist/skills/index.js +24 -0
- package/dist/skills/installer.d.ts +22 -0
- package/dist/skills/installer.js +220 -0
- package/dist/skills/loader.d.ts +72 -0
- package/dist/skills/loader.js +484 -0
- package/dist/skills/prompt-builder.d.ts +48 -0
- package/dist/skills/prompt-builder.js +135 -0
- package/dist/skills/registry.d.ts +115 -0
- package/dist/skills/registry.js +225 -0
- package/dist/skills/types.d.ts +202 -0
- package/dist/skills/types.js +24 -0
- package/dist/states/index.d.ts +64 -0
- package/dist/states/index.js +142 -0
- package/dist/storage/adapter.d.ts +146 -0
- package/dist/storage/adapter.js +2 -0
- package/dist/storage/index.d.ts +48 -0
- package/dist/storage/index.js +135 -0
- package/dist/storage/libsql.d.ts +99 -0
- package/dist/storage/libsql.js +1873 -0
- package/dist/storage/migrations.d.ts +65 -0
- package/dist/storage/migrations.js +289 -0
- package/dist/storage/schema.d.ts +10185 -0
- package/dist/storage/schema.js +1113 -0
- package/dist/summaries/extractor.d.ts +56 -0
- package/dist/summaries/extractor.js +377 -0
- package/dist/summaries/index.d.ts +13 -0
- package/dist/summaries/index.js +14 -0
- package/dist/summaries/storage.d.ts +51 -0
- package/dist/summaries/storage.js +101 -0
- package/dist/summaries/templates.d.ts +68 -0
- package/dist/summaries/templates.js +245 -0
- package/dist/sync/adapters/base.d.ts +42 -0
- package/dist/sync/adapters/base.js +142 -0
- package/dist/sync/adapters/github.d.ts +45 -0
- package/dist/sync/adapters/github.js +445 -0
- package/dist/sync/adapters/linear.d.ts +40 -0
- package/dist/sync/adapters/linear.js +434 -0
- package/dist/sync/config.d.ts +388 -0
- package/dist/sync/config.js +281 -0
- package/dist/sync/engine.d.ts +112 -0
- package/dist/sync/engine.js +623 -0
- package/dist/sync/index.d.ts +31 -0
- package/dist/sync/index.js +34 -0
- package/dist/sync/integration.d.ts +53 -0
- package/dist/sync/integration.js +231 -0
- package/dist/sync/types.d.ts +249 -0
- package/dist/sync/types.js +30 -0
- package/dist/tickets/index.d.ts +139 -0
- package/dist/tickets/index.js +1406 -0
- package/dist/tickets/types.d.ts +817 -0
- package/dist/tickets/types.js +310 -0
- package/dist/tools/adapters.d.ts +56 -0
- package/dist/tools/adapters.js +183 -0
- package/dist/tools/index.d.ts +66 -0
- package/dist/tools/index.js +105 -0
- package/dist/tools/types.d.ts +117 -0
- package/dist/tools/types.js +20 -0
- package/dist/types/agent.d.ts +101 -0
- package/dist/types/agent.js +2 -0
- package/dist/types/errors.d.ts +150 -0
- package/dist/types/errors.js +338 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +3 -0
- package/dist/types/summary.d.ts +638 -0
- package/dist/types/summary.js +137 -0
- package/dist/types/task.d.ts +123 -0
- package/dist/types/task.js +46 -0
- package/dist/utils/ai-cache.d.ts +72 -0
- package/dist/utils/ai-cache.js +204 -0
- package/dist/utils/ai-inference.d.ts +57 -0
- package/dist/utils/ai-inference.js +190 -0
- package/dist/utils/ai-responder.d.ts +44 -0
- package/dist/utils/ai-responder.js +272 -0
- package/dist/utils/circuit-breaker.d.ts +139 -0
- package/dist/utils/circuit-breaker.js +281 -0
- package/dist/utils/config-loader.d.ts +12 -0
- package/dist/utils/config-loader.js +44 -0
- package/dist/utils/crypto.d.ts +10 -0
- package/dist/utils/crypto.js +59 -0
- package/dist/utils/env-validator.d.ts +44 -0
- package/dist/utils/env-validator.js +236 -0
- package/dist/utils/file-lock.d.ts +85 -0
- package/dist/utils/file-lock.js +204 -0
- package/dist/utils/logger.d.ts +153 -0
- package/dist/utils/logger.js +282 -0
- package/dist/utils/metrics.d.ts +183 -0
- package/dist/utils/metrics.js +345 -0
- package/dist/utils/security.d.ts +90 -0
- package/dist/utils/security.js +347 -0
- package/dist/voice/index.d.ts +79 -0
- package/dist/voice/index.js +144 -0
- package/dist/voice/stt/whisper.d.ts +13 -0
- package/dist/voice/stt/whisper.js +116 -0
- package/dist/voice/tts/elevenlabs.d.ts +18 -0
- package/dist/voice/tts/elevenlabs.js +178 -0
- package/dist/voice/tts/openai-tts.d.ts +19 -0
- package/dist/voice/tts/openai-tts.js +127 -0
- package/dist/voice/tts/system.d.ts +26 -0
- package/dist/voice/tts/system.js +146 -0
- package/dist/voice/wake-word.d.ts +44 -0
- package/dist/voice/wake-word.js +145 -0
- package/docker-compose.yml +222 -0
- package/package.json +154 -0
- package/profclaw.mjs +24 -0
- package/skills/1password/SKILL.md +155 -0
- package/skills/api-tester/SKILL.md +177 -0
- package/skills/apple-notes/SKILL.md +167 -0
- package/skills/apple-reminders/SKILL.md +178 -0
- package/skills/bear-notes/SKILL.md +166 -0
- package/skills/blogwatcher/SKILL.md +177 -0
- package/skills/camsnap/SKILL.md +130 -0
- package/skills/code-generation/SKILL.md +139 -0
- package/skills/code-review/SKILL.md +116 -0
- package/skills/coding-agent/SKILL.md +184 -0
- package/skills/cron-manager/SKILL.md +141 -0
- package/skills/debug-helper/SKILL.md +134 -0
- package/skills/docker-ops/SKILL.md +246 -0
- package/skills/file-manager/SKILL.md +160 -0
- package/skills/git-workflow/SKILL.md +171 -0
- package/skills/github-issues/SKILL.md +244 -0
- package/skills/gog/SKILL.md +191 -0
- package/skills/goplaces/SKILL.md +156 -0
- package/skills/healthcheck/SKILL.md +270 -0
- package/skills/himalaya/SKILL.md +165 -0
- package/skills/mcp-discovery/SKILL.md +109 -0
- package/skills/memory-manager/SKILL.md +151 -0
- package/skills/model-usage/SKILL.md +177 -0
- package/skills/nano-banana-pro/SKILL.md +214 -0
- package/skills/nano-pdf/SKILL.md +165 -0
- package/skills/notion/SKILL.md +147 -0
- package/skills/obsidian/SKILL.md +163 -0
- package/skills/openai-image-gen/SKILL.md +194 -0
- package/skills/openai-whisper/SKILL.md +98 -0
- package/skills/openai-whisper-api/SKILL.md +130 -0
- package/skills/openhue/SKILL.md +203 -0
- package/skills/oracle/SKILL.md +236 -0
- package/skills/phone-control/SKILL.md +201 -0
- package/skills/profclaw-assistant/SKILL.md +81 -0
- package/skills/profclaw-projects/SKILL.md +68 -0
- package/skills/profclaw-tickets/SKILL.md +91 -0
- package/skills/session-logs/SKILL.md +216 -0
- package/skills/sherpa-onnx-tts/SKILL.md +134 -0
- package/skills/skill-creator/SKILL.md +183 -0
- package/skills/songsee/SKILL.md +170 -0
- package/skills/spotify-player/SKILL.md +254 -0
- package/skills/summarize/SKILL.md +155 -0
- package/skills/system-admin/SKILL.md +179 -0
- package/skills/things-mac/SKILL.md +179 -0
- package/skills/tmux/SKILL.md +170 -0
- package/skills/trello/SKILL.md +154 -0
- package/skills/video-frames/SKILL.md +127 -0
- package/skills/weather/SKILL.md +186 -0
- package/skills/web-research/SKILL.md +128 -0
- package/skills/xurl/SKILL.md +198 -0
- package/ui/README.md +73 -0
- package/ui/dist/assets/ActivityView-CkPgKhwm.js +1 -0
- package/ui/dist/assets/AgentList-C3SVdeEz.js +1 -0
- package/ui/dist/assets/AnalyticsDashboard-DVU--vlP.js +1 -0
- package/ui/dist/assets/AreaChart-B5qMEGWj.js +1 -0
- package/ui/dist/assets/CartesianChart-B50bcUJi.js +36 -0
- package/ui/dist/assets/ChatView-BZFJs7w_.js +10 -0
- package/ui/dist/assets/CostsDashboard-ChfH8BlG.js +1 -0
- package/ui/dist/assets/EstimateSelect-CLpB4NQO.js +1 -0
- package/ui/dist/assets/FloatingChatbot-CBzBY9a0.js +2 -0
- package/ui/dist/assets/InviteCodeManagement-DsbdPa6W.js +2 -0
- package/ui/dist/assets/ProjectDetail-BEM3tFXg.js +2 -0
- package/ui/dist/assets/ProjectDetail-D1-0B2xV.css +1 -0
- package/ui/dist/assets/ProjectIcon-CN1FmFAk.js +1 -0
- package/ui/dist/assets/ProjectList-DSDaNhxQ.js +4 -0
- package/ui/dist/assets/Settings-dPVcqC_d.js +6 -0
- package/ui/dist/assets/StatusIndicator-DA3NAo_b.js +1 -0
- package/ui/dist/assets/SummaryDetail-Bjnf9lT8.js +27 -0
- package/ui/dist/assets/SummaryList-ENwKDBKW.js +1 -0
- package/ui/dist/assets/TaskDetail-DnwG6MzB.js +1 -0
- package/ui/dist/assets/TaskList-D9Ug_HiV.js +1 -0
- package/ui/dist/assets/TicketBoard-CviH1571.js +1 -0
- package/ui/dist/assets/TicketDetail-8Jk8O-33.js +1 -0
- package/ui/dist/assets/TicketList-B-iV4rRA.js +1 -0
- package/ui/dist/assets/UserManagement-CPZ8s7s2.js +2 -0
- package/ui/dist/assets/ViewSwitcher-BUyOOWDI.js +1 -0
- package/ui/dist/assets/alert-dialog-BOmnTkN-.js +7 -0
- package/ui/dist/assets/archive-D5my9zOG.js +1 -0
- package/ui/dist/assets/badge-B4ov81_m.js +1 -0
- package/ui/dist/assets/brain-C53ElFLD.js +1 -0
- package/ui/dist/assets/bug-D0TJoCYn.js +1 -0
- package/ui/dist/assets/calendar-BkWIhKa1.js +1 -0
- package/ui/dist/assets/chevron-up-BRTtndUZ.js +1 -0
- package/ui/dist/assets/circle-x-BN89YhbS.js +1 -0
- package/ui/dist/assets/constants-fc7TFI7u.js +1 -0
- package/ui/dist/assets/cpu-B41x1-vV.js +1 -0
- package/ui/dist/assets/database-D9Cnfmzj.js +1 -0
- package/ui/dist/assets/defineProperty-CoXUr7_6.js +2 -0
- package/ui/dist/assets/dialog-DrWB4EYD.js +1 -0
- package/ui/dist/assets/element-adapter-DL0DQilL.js +4 -0
- package/ui/dist/assets/ellipsis-NuUWekvu.js +1 -0
- package/ui/dist/assets/ellipsis-vertical-BueMfuCw.js +1 -0
- package/ui/dist/assets/file-code-HR9829Jc.js +1 -0
- package/ui/dist/assets/folder-open-C_7oYEqe.js +1 -0
- package/ui/dist/assets/funnel-B5gmNXGf.js +1 -0
- package/ui/dist/assets/git-branch-BRMiJmV3.js +1 -0
- package/ui/dist/assets/git-commit-horizontal-CXOUQeJI.js +1 -0
- package/ui/dist/assets/globe-CCspjvus.js +1 -0
- package/ui/dist/assets/hash-g3102kPC.js +1 -0
- package/ui/dist/assets/history-CNqcBBrV.js +1 -0
- package/ui/dist/assets/index-27mTPKuh.js +1 -0
- package/ui/dist/assets/index-BMx3fH-e.js +1 -0
- package/ui/dist/assets/index-C9jNQXzL.js +1 -0
- package/ui/dist/assets/index-CEZ6R2Uw.js +7 -0
- package/ui/dist/assets/index-DURTouJI.js +1 -0
- package/ui/dist/assets/index-WclMPci1.css +1 -0
- package/ui/dist/assets/index-kb4AJXUB.js +67 -0
- package/ui/dist/assets/layers-CLXiHN6o.js +1 -0
- package/ui/dist/assets/layout-dashboard-B07MFhBs.js +1 -0
- package/ui/dist/assets/lightbulb-B2dgG5ks.js +1 -0
- package/ui/dist/assets/link-2-BxNmr9hL.js +1 -0
- package/ui/dist/assets/markdown-renderer-CjU6hBcW.js +36 -0
- package/ui/dist/assets/message-square-Bf2-CVbt.js +1 -0
- package/ui/dist/assets/pencil-D096Ey62.js +1 -0
- package/ui/dist/assets/play-DfdcSI3x.js +1 -0
- package/ui/dist/assets/popover-BV0QJDQq.js +1 -0
- package/ui/dist/assets/progress-DjPEDJfI.js +1 -0
- package/ui/dist/assets/rocket-CPsTc-5G.js +1 -0
- package/ui/dist/assets/select-LsO16slr.js +1 -0
- package/ui/dist/assets/send-BDYBZDUZ.js +1 -0
- package/ui/dist/assets/server-B3k6noce.js +1 -0
- package/ui/dist/assets/settings-2-Cu4xTjhG.js +1 -0
- package/ui/dist/assets/sheet-BScLnPKX.js +1 -0
- package/ui/dist/assets/shield-check-CQqkwufI.js +1 -0
- package/ui/dist/assets/shield-off-ZFruH9KO.js +1 -0
- package/ui/dist/assets/skeleton-CtkIA_MU.js +1 -0
- package/ui/dist/assets/smartphone-DnoksVkc.js +1 -0
- package/ui/dist/assets/square-uD9ZHMfW.js +1 -0
- package/ui/dist/assets/switch-MQPnwGJK.js +1 -0
- package/ui/dist/assets/table-B8cqlywA.js +1 -0
- package/ui/dist/assets/tag-wEJQRWlV.js +1 -0
- package/ui/dist/assets/textarea-D5LJCOGl.js +1 -0
- package/ui/dist/assets/timer-mbGHegmr.js +1 -0
- package/ui/dist/assets/tooltip-Df1CunSp.js +1 -0
- package/ui/dist/assets/trash-2-B4oAXsX-.js +1 -0
- package/ui/dist/assets/trending-up-BGWxvlmZ.js +1 -0
- package/ui/dist/assets/wand-sparkles-CZy4xvL3.js +1 -0
- package/ui/dist/assets/wrench-ByZkjO6m.js +1 -0
- package/ui/dist/audio-worklets/vad-processor.js +132 -0
- package/ui/dist/brand/profclaw-appicon-192.png +0 -0
- package/ui/dist/brand/profclaw-appicon-512.png +0 -0
- package/ui/dist/brand/profclaw-appicon-shadow.svg +51 -0
- package/ui/dist/brand/profclaw-appicon.svg +50 -0
- package/ui/dist/brand/profclaw-favicon-coral-bg-128.png +0 -0
- package/ui/dist/brand/profclaw-favicon-coral-bg-64.png +0 -0
- package/ui/dist/brand/profclaw-favicon-coral-bg.svg +52 -0
- package/ui/dist/brand/profclaw-favicon-coral-body-128.png +0 -0
- package/ui/dist/brand/profclaw-favicon-coral-body.svg +41 -0
- package/ui/dist/brand/profclaw-favicon-shadow-128.png +0 -0
- package/ui/dist/brand/profclaw-favicon-shadow-64.png +0 -0
- package/ui/dist/brand/profclaw-favicon-shadow.svg +51 -0
- package/ui/dist/brand/profclaw-mark-coral-256.png +0 -0
- package/ui/dist/brand/profclaw-mark-coral-64.png +0 -0
- package/ui/dist/brand/profclaw-mark-coral.svg +31 -0
- package/ui/dist/brand/profclaw-mono-white.svg +18 -0
- package/ui/dist/brand/profclaw-text-dark.svg +18 -0
- package/ui/dist/brand/profclaw-text-light.svg +18 -0
- package/ui/dist/brand/profclaw-wordmark-dark.svg +48 -0
- package/ui/dist/brand/profclaw-wordmark-light.svg +48 -0
- package/ui/dist/brand/safari-pinned-tab.svg +15 -0
- package/ui/dist/favicon/android-chrome-192x192.png +0 -0
- package/ui/dist/favicon/android-chrome-384x384.png +0 -0
- package/ui/dist/favicon/android-chrome-512x512.png +0 -0
- package/ui/dist/favicon/apple-touch-icon.png +0 -0
- package/ui/dist/favicon/browserconfig.xml +9 -0
- package/ui/dist/favicon/favicon-16x16.png +0 -0
- package/ui/dist/favicon/favicon-32x32.png +0 -0
- package/ui/dist/favicon/favicon.ico +0 -0
- package/ui/dist/favicon/mstile-150x150.png +0 -0
- package/ui/dist/favicon/safari-pinned-tab.svg +46 -0
- package/ui/dist/favicon/site.webmanifest +22 -0
- package/ui/dist/index.html +32 -0
- package/ui/dist/manifest.json +49 -0
- package/ui/dist/sw.js +124 -0
- package/ui/dist/vite.svg +1 -0
|
@@ -0,0 +1,897 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* profClaw Projects & Sprints Service
|
|
3
|
+
*
|
|
4
|
+
* Multi-project support with custom ticket prefixes and sprint management.
|
|
5
|
+
* Designed for bi-directional sync with Linear, Jira, GitHub.
|
|
6
|
+
*/
|
|
7
|
+
import { randomUUID } from 'crypto';
|
|
8
|
+
import { eq, and, desc, asc, sql, inArray, count } from 'drizzle-orm';
|
|
9
|
+
import { getDb } from '../storage/index.js';
|
|
10
|
+
import { projects, projectSequence, projectExternalLinks, sprints, sprintSequence, sprintTickets, tickets, } from '../storage/schema.js';
|
|
11
|
+
import { CreateProjectSchema, UpdateProjectSchema, ProjectQuerySchema, CreateSprintSchema, UpdateSprintSchema, SprintQuerySchema, AddTicketsToSprintSchema, } from './types.js';
|
|
12
|
+
// Re-export types
|
|
13
|
+
export * from './types.js';
|
|
14
|
+
// === Helpers ===
|
|
15
|
+
function generateId() {
|
|
16
|
+
return randomUUID();
|
|
17
|
+
}
|
|
18
|
+
function toISOString(value) {
|
|
19
|
+
if (!value)
|
|
20
|
+
return new Date().toISOString();
|
|
21
|
+
if (value instanceof Date) {
|
|
22
|
+
const time = value.getTime();
|
|
23
|
+
if (isNaN(time) || time < 0 || time > 8640000000000000) {
|
|
24
|
+
return new Date().toISOString();
|
|
25
|
+
}
|
|
26
|
+
return value.toISOString();
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === 'number') {
|
|
29
|
+
const timestamp = value > 1e12 ? value : value * 1000;
|
|
30
|
+
if (isNaN(timestamp) || timestamp < 0 || timestamp > 8640000000000000) {
|
|
31
|
+
return new Date().toISOString();
|
|
32
|
+
}
|
|
33
|
+
return new Date(timestamp).toISOString();
|
|
34
|
+
}
|
|
35
|
+
if (typeof value === 'string') {
|
|
36
|
+
const date = new Date(value);
|
|
37
|
+
const time = date.getTime();
|
|
38
|
+
if (isNaN(time) || time < 0 || time > 8640000000000000) {
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
return date.toISOString();
|
|
42
|
+
}
|
|
43
|
+
return new Date().toISOString();
|
|
44
|
+
}
|
|
45
|
+
function toOptionalISOString(value) {
|
|
46
|
+
if (!value)
|
|
47
|
+
return undefined;
|
|
48
|
+
if (value instanceof Date) {
|
|
49
|
+
const time = value.getTime();
|
|
50
|
+
if (isNaN(time) || time < 0 || time > 8640000000000000) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
return value.toISOString();
|
|
54
|
+
}
|
|
55
|
+
if (typeof value === 'number') {
|
|
56
|
+
const timestamp = value > 1e12 ? value : value * 1000;
|
|
57
|
+
if (isNaN(timestamp) || timestamp < 0 || timestamp > 8640000000000000) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return new Date(timestamp).toISOString();
|
|
61
|
+
}
|
|
62
|
+
if (typeof value === 'string') {
|
|
63
|
+
const date = new Date(value);
|
|
64
|
+
const time = date.getTime();
|
|
65
|
+
if (isNaN(time) || time < 0 || time > 8640000000000000) {
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
return date.toISOString();
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
// === Project Sequence ===
|
|
73
|
+
async function getNextProjectSequence(workspaceId = 'default') {
|
|
74
|
+
const db = getDb();
|
|
75
|
+
if (!db)
|
|
76
|
+
throw new Error('Database not initialized');
|
|
77
|
+
const result = await db
|
|
78
|
+
.insert(projectSequence)
|
|
79
|
+
.values({ workspaceId, lastSequence: 1 })
|
|
80
|
+
.onConflictDoUpdate({
|
|
81
|
+
target: projectSequence.workspaceId,
|
|
82
|
+
set: { lastSequence: sql `${projectSequence.lastSequence} + 1` },
|
|
83
|
+
})
|
|
84
|
+
.returning();
|
|
85
|
+
return result[0]?.lastSequence ?? 1;
|
|
86
|
+
}
|
|
87
|
+
// === Sprint Sequence ===
|
|
88
|
+
async function getNextSprintSequence(projectId) {
|
|
89
|
+
const db = getDb();
|
|
90
|
+
if (!db)
|
|
91
|
+
throw new Error('Database not initialized');
|
|
92
|
+
const result = await db
|
|
93
|
+
.insert(sprintSequence)
|
|
94
|
+
.values({ projectId, lastSequence: 1 })
|
|
95
|
+
.onConflictDoUpdate({
|
|
96
|
+
target: sprintSequence.projectId,
|
|
97
|
+
set: { lastSequence: sql `${sprintSequence.lastSequence} + 1` },
|
|
98
|
+
})
|
|
99
|
+
.returning();
|
|
100
|
+
return result[0]?.lastSequence ?? 1;
|
|
101
|
+
}
|
|
102
|
+
// === Enum Guards ===
|
|
103
|
+
const PROJECT_STATUSES = ['active', 'archived'];
|
|
104
|
+
function toProjectStatus(value) {
|
|
105
|
+
const v = value ?? 'active';
|
|
106
|
+
return PROJECT_STATUSES.includes(v)
|
|
107
|
+
? v
|
|
108
|
+
: 'active';
|
|
109
|
+
}
|
|
110
|
+
const SPRINT_STATUSES = ['planning', 'active', 'completed', 'cancelled'];
|
|
111
|
+
function toSprintStatus(value) {
|
|
112
|
+
const v = value ?? 'planning';
|
|
113
|
+
return SPRINT_STATUSES.includes(v)
|
|
114
|
+
? v
|
|
115
|
+
: 'planning';
|
|
116
|
+
}
|
|
117
|
+
const SYNC_DIRECTIONS = ['push', 'pull', 'bidirectional'];
|
|
118
|
+
function toSyncDirection(value) {
|
|
119
|
+
const v = value ?? 'bidirectional';
|
|
120
|
+
return SYNC_DIRECTIONS.includes(v)
|
|
121
|
+
? v
|
|
122
|
+
: 'bidirectional';
|
|
123
|
+
}
|
|
124
|
+
// === Row Converters ===
|
|
125
|
+
function rowToProject(row) {
|
|
126
|
+
return {
|
|
127
|
+
id: row.id,
|
|
128
|
+
sequence: row.sequence,
|
|
129
|
+
workspaceId: row.workspaceId || 'default',
|
|
130
|
+
key: row.key,
|
|
131
|
+
name: row.name,
|
|
132
|
+
description: row.description || undefined,
|
|
133
|
+
icon: row.icon || '📋',
|
|
134
|
+
color: row.color || '#6366f1',
|
|
135
|
+
defaultAssignee: row.defaultAssignee || undefined,
|
|
136
|
+
defaultAgent: row.defaultAgent || undefined,
|
|
137
|
+
defaultLabels: row.defaultLabels || [],
|
|
138
|
+
cycleView: row.cycleView ?? true,
|
|
139
|
+
boardView: row.boardView ?? true,
|
|
140
|
+
lead: row.lead || undefined,
|
|
141
|
+
status: toProjectStatus(row.status),
|
|
142
|
+
createdAt: toISOString(row.createdAt),
|
|
143
|
+
updatedAt: toISOString(row.updatedAt),
|
|
144
|
+
archivedAt: toOptionalISOString(row.archivedAt),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function rowToSprint(row) {
|
|
148
|
+
return {
|
|
149
|
+
id: row.id,
|
|
150
|
+
sequence: row.sequence,
|
|
151
|
+
projectId: row.projectId,
|
|
152
|
+
name: row.name,
|
|
153
|
+
goal: row.goal || undefined,
|
|
154
|
+
description: row.description || undefined,
|
|
155
|
+
status: toSprintStatus(row.status),
|
|
156
|
+
startDate: toOptionalISOString(row.startDate),
|
|
157
|
+
endDate: toOptionalISOString(row.endDate),
|
|
158
|
+
capacity: row.capacity || undefined,
|
|
159
|
+
createdAt: toISOString(row.createdAt),
|
|
160
|
+
updatedAt: toISOString(row.updatedAt),
|
|
161
|
+
completedAt: toOptionalISOString(row.completedAt),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function rowToExternalLink(row) {
|
|
165
|
+
return {
|
|
166
|
+
id: row.id,
|
|
167
|
+
projectId: row.projectId,
|
|
168
|
+
platform: row.platform,
|
|
169
|
+
externalId: row.externalId,
|
|
170
|
+
externalUrl: row.externalUrl || undefined,
|
|
171
|
+
syncEnabled: row.syncEnabled ?? true,
|
|
172
|
+
syncDirection: toSyncDirection(row.syncDirection),
|
|
173
|
+
lastSyncedAt: toOptionalISOString(row.lastSyncedAt),
|
|
174
|
+
syncError: row.syncError || undefined,
|
|
175
|
+
createdAt: toISOString(row.createdAt),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
// PROJECTS CRUD
|
|
179
|
+
/**
|
|
180
|
+
* Create a new project
|
|
181
|
+
*/
|
|
182
|
+
export async function createProject(input) {
|
|
183
|
+
const parsed = CreateProjectSchema.parse(input);
|
|
184
|
+
const db = getDb();
|
|
185
|
+
if (!db)
|
|
186
|
+
throw new Error('Database not initialized');
|
|
187
|
+
const id = generateId();
|
|
188
|
+
const sequence = await getNextProjectSequence();
|
|
189
|
+
const now = new Date();
|
|
190
|
+
const project = {
|
|
191
|
+
id,
|
|
192
|
+
sequence,
|
|
193
|
+
workspaceId: 'default',
|
|
194
|
+
key: parsed.key,
|
|
195
|
+
name: parsed.name,
|
|
196
|
+
description: parsed.description,
|
|
197
|
+
icon: parsed.icon || '📋',
|
|
198
|
+
color: parsed.color || '#6366f1',
|
|
199
|
+
defaultAssignee: parsed.defaultAssignee,
|
|
200
|
+
defaultAgent: parsed.defaultAgent,
|
|
201
|
+
defaultLabels: parsed.defaultLabels || [],
|
|
202
|
+
cycleView: parsed.cycleView ?? true,
|
|
203
|
+
boardView: parsed.boardView ?? true,
|
|
204
|
+
lead: parsed.lead,
|
|
205
|
+
status: 'active',
|
|
206
|
+
createdAt: now.toISOString(),
|
|
207
|
+
updatedAt: now.toISOString(),
|
|
208
|
+
};
|
|
209
|
+
await db.insert(projects).values({
|
|
210
|
+
id: project.id,
|
|
211
|
+
sequence: project.sequence,
|
|
212
|
+
workspaceId: project.workspaceId,
|
|
213
|
+
key: project.key,
|
|
214
|
+
name: project.name,
|
|
215
|
+
description: project.description,
|
|
216
|
+
icon: project.icon,
|
|
217
|
+
color: project.color,
|
|
218
|
+
defaultAssignee: project.defaultAssignee,
|
|
219
|
+
defaultAgent: project.defaultAgent,
|
|
220
|
+
defaultLabels: project.defaultLabels,
|
|
221
|
+
cycleView: project.cycleView,
|
|
222
|
+
boardView: project.boardView,
|
|
223
|
+
lead: project.lead,
|
|
224
|
+
status: project.status,
|
|
225
|
+
createdAt: now,
|
|
226
|
+
updatedAt: now,
|
|
227
|
+
});
|
|
228
|
+
// Create external link if provided
|
|
229
|
+
if (parsed.externalLink) {
|
|
230
|
+
await createProjectExternalLink(id, {
|
|
231
|
+
platform: parsed.externalLink.platform,
|
|
232
|
+
externalId: parsed.externalLink.externalId,
|
|
233
|
+
externalUrl: parsed.externalLink.externalUrl,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return project;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get a project by ID
|
|
240
|
+
*/
|
|
241
|
+
export async function getProject(id) {
|
|
242
|
+
const db = getDb();
|
|
243
|
+
if (!db)
|
|
244
|
+
throw new Error('Database not initialized');
|
|
245
|
+
const result = await db.select().from(projects).where(eq(projects.id, id)).limit(1);
|
|
246
|
+
if (result.length === 0)
|
|
247
|
+
return null;
|
|
248
|
+
return rowToProject(result[0]);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get a project by key (e.g., "PC")
|
|
252
|
+
*/
|
|
253
|
+
export async function getProjectByKey(key) {
|
|
254
|
+
const db = getDb();
|
|
255
|
+
if (!db)
|
|
256
|
+
throw new Error('Database not initialized');
|
|
257
|
+
const result = await db.select().from(projects).where(eq(projects.key, key.toUpperCase())).limit(1);
|
|
258
|
+
if (result.length === 0)
|
|
259
|
+
return null;
|
|
260
|
+
return rowToProject(result[0]);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get a project with all relations (external links, stats)
|
|
264
|
+
*/
|
|
265
|
+
export async function getProjectWithRelations(id) {
|
|
266
|
+
const project = await getProject(id);
|
|
267
|
+
if (!project)
|
|
268
|
+
return null;
|
|
269
|
+
const db = getDb();
|
|
270
|
+
if (!db)
|
|
271
|
+
throw new Error('Database not initialized');
|
|
272
|
+
// Get external links
|
|
273
|
+
const externalLinks = await db
|
|
274
|
+
.select()
|
|
275
|
+
.from(projectExternalLinks)
|
|
276
|
+
.where(eq(projectExternalLinks.projectId, id));
|
|
277
|
+
// Get ticket stats
|
|
278
|
+
const ticketStatsResult = await db
|
|
279
|
+
.select({
|
|
280
|
+
status: tickets.status,
|
|
281
|
+
count: count(),
|
|
282
|
+
})
|
|
283
|
+
.from(tickets)
|
|
284
|
+
.where(eq(tickets.projectId, id))
|
|
285
|
+
.groupBy(tickets.status);
|
|
286
|
+
const stats = {
|
|
287
|
+
totalTickets: 0,
|
|
288
|
+
openTickets: 0,
|
|
289
|
+
inProgressTickets: 0,
|
|
290
|
+
doneTickets: 0,
|
|
291
|
+
};
|
|
292
|
+
for (const row of ticketStatsResult) {
|
|
293
|
+
stats.totalTickets += Number(row.count);
|
|
294
|
+
if (row.status === 'backlog' || row.status === 'todo') {
|
|
295
|
+
stats.openTickets += Number(row.count);
|
|
296
|
+
}
|
|
297
|
+
else if (row.status === 'in_progress' || row.status === 'in_review') {
|
|
298
|
+
stats.inProgressTickets += Number(row.count);
|
|
299
|
+
}
|
|
300
|
+
else if (row.status === 'done') {
|
|
301
|
+
stats.doneTickets += Number(row.count);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// Get active sprint count
|
|
305
|
+
const activeSprintsResult = await db
|
|
306
|
+
.select({ count: count() })
|
|
307
|
+
.from(sprints)
|
|
308
|
+
.where(and(eq(sprints.projectId, id), eq(sprints.status, 'active')));
|
|
309
|
+
return {
|
|
310
|
+
...project,
|
|
311
|
+
externalLinks: externalLinks.map(rowToExternalLink),
|
|
312
|
+
ticketCount: stats.totalTickets,
|
|
313
|
+
activeSprintCount: Number(activeSprintsResult[0]?.count || 0),
|
|
314
|
+
stats,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Update a project
|
|
319
|
+
*/
|
|
320
|
+
export async function updateProject(id, input) {
|
|
321
|
+
const parsed = UpdateProjectSchema.parse(input);
|
|
322
|
+
const db = getDb();
|
|
323
|
+
if (!db)
|
|
324
|
+
throw new Error('Database not initialized');
|
|
325
|
+
const now = new Date();
|
|
326
|
+
await db
|
|
327
|
+
.update(projects)
|
|
328
|
+
.set({
|
|
329
|
+
...parsed,
|
|
330
|
+
updatedAt: now,
|
|
331
|
+
})
|
|
332
|
+
.where(eq(projects.id, id));
|
|
333
|
+
const updated = await getProject(id);
|
|
334
|
+
if (!updated)
|
|
335
|
+
throw new Error(`Project ${id} not found after update`);
|
|
336
|
+
return updated;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Archive a project
|
|
340
|
+
*/
|
|
341
|
+
export async function archiveProject(id) {
|
|
342
|
+
const db = getDb();
|
|
343
|
+
if (!db)
|
|
344
|
+
throw new Error('Database not initialized');
|
|
345
|
+
const now = new Date();
|
|
346
|
+
await db
|
|
347
|
+
.update(projects)
|
|
348
|
+
.set({
|
|
349
|
+
status: 'archived',
|
|
350
|
+
archivedAt: now,
|
|
351
|
+
updatedAt: now,
|
|
352
|
+
})
|
|
353
|
+
.where(eq(projects.id, id));
|
|
354
|
+
const updated = await getProject(id);
|
|
355
|
+
if (!updated)
|
|
356
|
+
throw new Error(`Project ${id} not found after archive`);
|
|
357
|
+
return updated;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Delete a project (hard delete - use archiveProject instead in most cases)
|
|
361
|
+
*/
|
|
362
|
+
export async function deleteProject(id) {
|
|
363
|
+
const db = getDb();
|
|
364
|
+
if (!db)
|
|
365
|
+
throw new Error('Database not initialized');
|
|
366
|
+
// Delete external links first
|
|
367
|
+
await db.delete(projectExternalLinks).where(eq(projectExternalLinks.projectId, id));
|
|
368
|
+
// Delete project
|
|
369
|
+
await db.delete(projects).where(eq(projects.id, id));
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Query projects with filters
|
|
374
|
+
*/
|
|
375
|
+
export async function queryProjects(query = {}) {
|
|
376
|
+
const parsed = ProjectQuerySchema.parse(query);
|
|
377
|
+
const db = getDb();
|
|
378
|
+
if (!db)
|
|
379
|
+
throw new Error('Database not initialized');
|
|
380
|
+
const conditions = [];
|
|
381
|
+
// Status filter
|
|
382
|
+
if (parsed.status) {
|
|
383
|
+
if (Array.isArray(parsed.status)) {
|
|
384
|
+
conditions.push(inArray(projects.status, parsed.status));
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
conditions.push(eq(projects.status, parsed.status));
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else if (!parsed.includeArchived) {
|
|
391
|
+
conditions.push(eq(projects.status, 'active'));
|
|
392
|
+
}
|
|
393
|
+
// Workspace filter
|
|
394
|
+
if (parsed.workspaceId) {
|
|
395
|
+
conditions.push(eq(projects.workspaceId, parsed.workspaceId));
|
|
396
|
+
}
|
|
397
|
+
// Search filter
|
|
398
|
+
if (parsed.search) {
|
|
399
|
+
const searchPattern = `%${parsed.search}%`;
|
|
400
|
+
conditions.push(sql `(${projects.name} LIKE ${searchPattern} OR ${projects.key} LIKE ${searchPattern} OR ${projects.description} LIKE ${searchPattern})`);
|
|
401
|
+
}
|
|
402
|
+
const whereClause = conditions.length > 0 ? and(...conditions) : undefined;
|
|
403
|
+
// Sorting
|
|
404
|
+
let orderBy = desc(projects.createdAt);
|
|
405
|
+
if (parsed.sortBy === 'name') {
|
|
406
|
+
orderBy = parsed.sortOrder === 'desc' ? desc(projects.name) : asc(projects.name);
|
|
407
|
+
}
|
|
408
|
+
else if (parsed.sortBy === 'key') {
|
|
409
|
+
orderBy = parsed.sortOrder === 'desc' ? desc(projects.key) : asc(projects.key);
|
|
410
|
+
}
|
|
411
|
+
else if (parsed.sortBy === 'updatedAt') {
|
|
412
|
+
orderBy = parsed.sortOrder === 'desc' ? desc(projects.updatedAt) : asc(projects.updatedAt);
|
|
413
|
+
}
|
|
414
|
+
else if (parsed.sortBy === 'createdAt') {
|
|
415
|
+
orderBy = parsed.sortOrder === 'asc' ? asc(projects.createdAt) : desc(projects.createdAt);
|
|
416
|
+
}
|
|
417
|
+
const result = await db
|
|
418
|
+
.select()
|
|
419
|
+
.from(projects)
|
|
420
|
+
.where(whereClause)
|
|
421
|
+
.orderBy(orderBy)
|
|
422
|
+
.limit(parsed.limit || 50)
|
|
423
|
+
.offset(parsed.offset || 0);
|
|
424
|
+
const totalResult = await db.select({ count: count() }).from(projects).where(whereClause);
|
|
425
|
+
return {
|
|
426
|
+
projects: result.map(rowToProject),
|
|
427
|
+
total: Number(totalResult[0]?.count || 0),
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
// PROJECT EXTERNAL LINKS
|
|
431
|
+
/**
|
|
432
|
+
* Create an external link for a project (Linear Team, Jira Project, etc.)
|
|
433
|
+
*/
|
|
434
|
+
export async function createProjectExternalLink(projectId, input) {
|
|
435
|
+
const db = getDb();
|
|
436
|
+
if (!db)
|
|
437
|
+
throw new Error('Database not initialized');
|
|
438
|
+
const id = generateId();
|
|
439
|
+
const now = new Date();
|
|
440
|
+
await db.insert(projectExternalLinks).values({
|
|
441
|
+
id,
|
|
442
|
+
projectId,
|
|
443
|
+
platform: input.platform,
|
|
444
|
+
externalId: input.externalId,
|
|
445
|
+
externalUrl: input.externalUrl,
|
|
446
|
+
syncEnabled: true,
|
|
447
|
+
syncDirection: 'bidirectional',
|
|
448
|
+
createdAt: now,
|
|
449
|
+
});
|
|
450
|
+
return {
|
|
451
|
+
id,
|
|
452
|
+
projectId,
|
|
453
|
+
platform: input.platform,
|
|
454
|
+
externalId: input.externalId,
|
|
455
|
+
externalUrl: input.externalUrl,
|
|
456
|
+
syncEnabled: true,
|
|
457
|
+
syncDirection: 'bidirectional',
|
|
458
|
+
createdAt: now.toISOString(),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Get external links for a project
|
|
463
|
+
*/
|
|
464
|
+
export async function getProjectExternalLinks(projectId) {
|
|
465
|
+
const db = getDb();
|
|
466
|
+
if (!db)
|
|
467
|
+
throw new Error('Database not initialized');
|
|
468
|
+
const result = await db
|
|
469
|
+
.select()
|
|
470
|
+
.from(projectExternalLinks)
|
|
471
|
+
.where(eq(projectExternalLinks.projectId, projectId));
|
|
472
|
+
return result.map(rowToExternalLink);
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Find project by external ID (for sync)
|
|
476
|
+
*/
|
|
477
|
+
export async function findProjectByExternalId(platform, externalId) {
|
|
478
|
+
const db = getDb();
|
|
479
|
+
if (!db)
|
|
480
|
+
throw new Error('Database not initialized');
|
|
481
|
+
const linkResult = await db
|
|
482
|
+
.select()
|
|
483
|
+
.from(projectExternalLinks)
|
|
484
|
+
.where(and(eq(projectExternalLinks.platform, platform), eq(projectExternalLinks.externalId, externalId)))
|
|
485
|
+
.limit(1);
|
|
486
|
+
if (linkResult.length === 0)
|
|
487
|
+
return null;
|
|
488
|
+
return getProject(linkResult[0].projectId);
|
|
489
|
+
}
|
|
490
|
+
// SPRINTS CRUD
|
|
491
|
+
/**
|
|
492
|
+
* Create a new sprint for a project
|
|
493
|
+
*/
|
|
494
|
+
export async function createSprint(projectId, input) {
|
|
495
|
+
const parsed = CreateSprintSchema.parse(input);
|
|
496
|
+
const db = getDb();
|
|
497
|
+
if (!db)
|
|
498
|
+
throw new Error('Database not initialized');
|
|
499
|
+
// Verify project exists
|
|
500
|
+
const project = await getProject(projectId);
|
|
501
|
+
if (!project)
|
|
502
|
+
throw new Error(`Project ${projectId} not found`);
|
|
503
|
+
const id = generateId();
|
|
504
|
+
const sequence = await getNextSprintSequence(projectId);
|
|
505
|
+
const now = new Date();
|
|
506
|
+
const sprint = {
|
|
507
|
+
id,
|
|
508
|
+
sequence,
|
|
509
|
+
projectId,
|
|
510
|
+
name: parsed.name,
|
|
511
|
+
goal: parsed.goal,
|
|
512
|
+
description: parsed.description,
|
|
513
|
+
status: 'planning',
|
|
514
|
+
startDate: parsed.startDate,
|
|
515
|
+
endDate: parsed.endDate,
|
|
516
|
+
capacity: parsed.capacity,
|
|
517
|
+
createdAt: now.toISOString(),
|
|
518
|
+
updatedAt: now.toISOString(),
|
|
519
|
+
};
|
|
520
|
+
await db.insert(sprints).values({
|
|
521
|
+
id: sprint.id,
|
|
522
|
+
sequence: sprint.sequence,
|
|
523
|
+
projectId: sprint.projectId,
|
|
524
|
+
name: sprint.name,
|
|
525
|
+
goal: sprint.goal,
|
|
526
|
+
description: sprint.description,
|
|
527
|
+
status: sprint.status,
|
|
528
|
+
startDate: parsed.startDate ? new Date(parsed.startDate) : undefined,
|
|
529
|
+
endDate: parsed.endDate ? new Date(parsed.endDate) : undefined,
|
|
530
|
+
capacity: sprint.capacity,
|
|
531
|
+
createdAt: now,
|
|
532
|
+
updatedAt: now,
|
|
533
|
+
});
|
|
534
|
+
return sprint;
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Get a sprint by ID
|
|
538
|
+
*/
|
|
539
|
+
export async function getSprint(id) {
|
|
540
|
+
const db = getDb();
|
|
541
|
+
if (!db)
|
|
542
|
+
throw new Error('Database not initialized');
|
|
543
|
+
const result = await db.select().from(sprints).where(eq(sprints.id, id)).limit(1);
|
|
544
|
+
if (result.length === 0)
|
|
545
|
+
return null;
|
|
546
|
+
return rowToSprint(result[0]);
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Get a sprint with stats (ticket counts, burndown data)
|
|
550
|
+
*/
|
|
551
|
+
export async function getSprintWithStats(id) {
|
|
552
|
+
const sprint = await getSprint(id);
|
|
553
|
+
if (!sprint)
|
|
554
|
+
return null;
|
|
555
|
+
const db = getDb();
|
|
556
|
+
if (!db)
|
|
557
|
+
throw new Error('Database not initialized');
|
|
558
|
+
// Get ticket stats for this sprint
|
|
559
|
+
const ticketResults = await db
|
|
560
|
+
.select({
|
|
561
|
+
ticketId: sprintTickets.ticketId,
|
|
562
|
+
status: tickets.status,
|
|
563
|
+
estimate: tickets.estimate,
|
|
564
|
+
})
|
|
565
|
+
.from(sprintTickets)
|
|
566
|
+
.innerJoin(tickets, eq(sprintTickets.ticketId, tickets.id))
|
|
567
|
+
.where(eq(sprintTickets.sprintId, id));
|
|
568
|
+
let ticketCount = 0;
|
|
569
|
+
let completedCount = 0;
|
|
570
|
+
let totalPoints = 0;
|
|
571
|
+
let completedPoints = 0;
|
|
572
|
+
for (const row of ticketResults) {
|
|
573
|
+
ticketCount++;
|
|
574
|
+
const points = row.estimate || 0;
|
|
575
|
+
totalPoints += points;
|
|
576
|
+
if (row.status === 'done') {
|
|
577
|
+
completedCount++;
|
|
578
|
+
completedPoints += points;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return {
|
|
582
|
+
...sprint,
|
|
583
|
+
ticketCount,
|
|
584
|
+
completedCount,
|
|
585
|
+
totalPoints,
|
|
586
|
+
completedPoints,
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Update a sprint
|
|
591
|
+
*/
|
|
592
|
+
export async function updateSprint(id, input) {
|
|
593
|
+
const parsed = UpdateSprintSchema.parse(input);
|
|
594
|
+
const db = getDb();
|
|
595
|
+
if (!db)
|
|
596
|
+
throw new Error('Database not initialized');
|
|
597
|
+
const now = new Date();
|
|
598
|
+
const { startDate: _sd, endDate: _ed, ...rest } = parsed;
|
|
599
|
+
const updateData = {
|
|
600
|
+
...rest,
|
|
601
|
+
updatedAt: now,
|
|
602
|
+
};
|
|
603
|
+
// Convert date strings to Date objects
|
|
604
|
+
if (parsed.startDate !== undefined) {
|
|
605
|
+
updateData.startDate = parsed.startDate ? new Date(parsed.startDate) : null;
|
|
606
|
+
}
|
|
607
|
+
if (parsed.endDate !== undefined) {
|
|
608
|
+
updateData.endDate = parsed.endDate ? new Date(parsed.endDate) : null;
|
|
609
|
+
}
|
|
610
|
+
await db.update(sprints).set(updateData).where(eq(sprints.id, id));
|
|
611
|
+
const updated = await getSprint(id);
|
|
612
|
+
if (!updated)
|
|
613
|
+
throw new Error(`Sprint ${id} not found after update`);
|
|
614
|
+
return updated;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Start a sprint
|
|
618
|
+
*/
|
|
619
|
+
export async function startSprint(id) {
|
|
620
|
+
const db = getDb();
|
|
621
|
+
if (!db)
|
|
622
|
+
throw new Error('Database not initialized');
|
|
623
|
+
const sprint = await getSprint(id);
|
|
624
|
+
if (!sprint)
|
|
625
|
+
throw new Error(`Sprint ${id} not found`);
|
|
626
|
+
if (sprint.status !== 'planning') {
|
|
627
|
+
throw new Error(`Sprint ${id} cannot be started (current status: ${sprint.status})`);
|
|
628
|
+
}
|
|
629
|
+
const now = new Date();
|
|
630
|
+
await db
|
|
631
|
+
.update(sprints)
|
|
632
|
+
.set({
|
|
633
|
+
status: 'active',
|
|
634
|
+
startDate: sprint.startDate ? new Date(sprint.startDate) : now,
|
|
635
|
+
updatedAt: now,
|
|
636
|
+
})
|
|
637
|
+
.where(eq(sprints.id, id));
|
|
638
|
+
const updated = await getSprint(id);
|
|
639
|
+
if (!updated)
|
|
640
|
+
throw new Error(`Sprint ${id} not found after start`);
|
|
641
|
+
return updated;
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Complete a sprint
|
|
645
|
+
*/
|
|
646
|
+
export async function completeSprint(id) {
|
|
647
|
+
const db = getDb();
|
|
648
|
+
if (!db)
|
|
649
|
+
throw new Error('Database not initialized');
|
|
650
|
+
const sprint = await getSprint(id);
|
|
651
|
+
if (!sprint)
|
|
652
|
+
throw new Error(`Sprint ${id} not found`);
|
|
653
|
+
if (sprint.status !== 'active') {
|
|
654
|
+
throw new Error(`Sprint ${id} cannot be completed (current status: ${sprint.status})`);
|
|
655
|
+
}
|
|
656
|
+
const now = new Date();
|
|
657
|
+
await db
|
|
658
|
+
.update(sprints)
|
|
659
|
+
.set({
|
|
660
|
+
status: 'completed',
|
|
661
|
+
completedAt: now,
|
|
662
|
+
updatedAt: now,
|
|
663
|
+
})
|
|
664
|
+
.where(eq(sprints.id, id));
|
|
665
|
+
const updated = await getSprint(id);
|
|
666
|
+
if (!updated)
|
|
667
|
+
throw new Error(`Sprint ${id} not found after complete`);
|
|
668
|
+
return updated;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Cancel a sprint
|
|
672
|
+
*/
|
|
673
|
+
export async function cancelSprint(id) {
|
|
674
|
+
const db = getDb();
|
|
675
|
+
if (!db)
|
|
676
|
+
throw new Error('Database not initialized');
|
|
677
|
+
const now = new Date();
|
|
678
|
+
await db
|
|
679
|
+
.update(sprints)
|
|
680
|
+
.set({
|
|
681
|
+
status: 'cancelled',
|
|
682
|
+
updatedAt: now,
|
|
683
|
+
})
|
|
684
|
+
.where(eq(sprints.id, id));
|
|
685
|
+
const updated = await getSprint(id);
|
|
686
|
+
if (!updated)
|
|
687
|
+
throw new Error(`Sprint ${id} not found after cancel`);
|
|
688
|
+
return updated;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Delete a sprint
|
|
692
|
+
*/
|
|
693
|
+
export async function deleteSprint(id) {
|
|
694
|
+
const db = getDb();
|
|
695
|
+
if (!db)
|
|
696
|
+
throw new Error('Database not initialized');
|
|
697
|
+
// Remove all ticket assignments first
|
|
698
|
+
await db.delete(sprintTickets).where(eq(sprintTickets.sprintId, id));
|
|
699
|
+
// Delete sprint
|
|
700
|
+
await db.delete(sprints).where(eq(sprints.id, id));
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Query sprints with filters
|
|
705
|
+
*/
|
|
706
|
+
export async function querySprints(query = {}) {
|
|
707
|
+
const parsed = SprintQuerySchema.parse(query);
|
|
708
|
+
const db = getDb();
|
|
709
|
+
if (!db)
|
|
710
|
+
throw new Error('Database not initialized');
|
|
711
|
+
const conditions = [];
|
|
712
|
+
// Project filter
|
|
713
|
+
if (parsed.projectId) {
|
|
714
|
+
conditions.push(eq(sprints.projectId, parsed.projectId));
|
|
715
|
+
}
|
|
716
|
+
// Status filter
|
|
717
|
+
if (parsed.status) {
|
|
718
|
+
if (Array.isArray(parsed.status)) {
|
|
719
|
+
conditions.push(inArray(sprints.status, parsed.status));
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
conditions.push(eq(sprints.status, parsed.status));
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
// Search filter
|
|
726
|
+
if (parsed.search) {
|
|
727
|
+
const searchPattern = `%${parsed.search}%`;
|
|
728
|
+
conditions.push(sql `(${sprints.name} LIKE ${searchPattern} OR ${sprints.goal} LIKE ${searchPattern} OR ${sprints.description} LIKE ${searchPattern})`);
|
|
729
|
+
}
|
|
730
|
+
const whereClause = conditions.length > 0 ? and(...conditions) : undefined;
|
|
731
|
+
// Sorting
|
|
732
|
+
let orderBy = desc(sprints.createdAt);
|
|
733
|
+
if (parsed.sortBy === 'startDate') {
|
|
734
|
+
orderBy = parsed.sortOrder === 'desc' ? desc(sprints.startDate) : asc(sprints.startDate);
|
|
735
|
+
}
|
|
736
|
+
else if (parsed.sortBy === 'endDate') {
|
|
737
|
+
orderBy = parsed.sortOrder === 'desc' ? desc(sprints.endDate) : asc(sprints.endDate);
|
|
738
|
+
}
|
|
739
|
+
else if (parsed.sortBy === 'sequence') {
|
|
740
|
+
orderBy = parsed.sortOrder === 'desc' ? desc(sprints.sequence) : asc(sprints.sequence);
|
|
741
|
+
}
|
|
742
|
+
else if (parsed.sortBy === 'createdAt') {
|
|
743
|
+
orderBy = parsed.sortOrder === 'asc' ? asc(sprints.createdAt) : desc(sprints.createdAt);
|
|
744
|
+
}
|
|
745
|
+
const result = await db
|
|
746
|
+
.select()
|
|
747
|
+
.from(sprints)
|
|
748
|
+
.where(whereClause)
|
|
749
|
+
.orderBy(orderBy)
|
|
750
|
+
.limit(parsed.limit || 50)
|
|
751
|
+
.offset(parsed.offset || 0);
|
|
752
|
+
const totalResult = await db.select({ count: count() }).from(sprints).where(whereClause);
|
|
753
|
+
return {
|
|
754
|
+
sprints: result.map(rowToSprint),
|
|
755
|
+
total: Number(totalResult[0]?.count || 0),
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Get sprints for a project
|
|
760
|
+
*/
|
|
761
|
+
export async function getProjectSprints(projectId) {
|
|
762
|
+
const result = await querySprints({ projectId, sortBy: 'sequence', sortOrder: 'asc' });
|
|
763
|
+
return result.sprints;
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Get active sprint for a project
|
|
767
|
+
*/
|
|
768
|
+
export async function getActiveSprint(projectId) {
|
|
769
|
+
const result = await querySprints({ projectId, status: 'active', limit: 1 });
|
|
770
|
+
return result.sprints[0] || null;
|
|
771
|
+
}
|
|
772
|
+
// SPRINT-TICKET ASSIGNMENTS
|
|
773
|
+
/**
|
|
774
|
+
* Add tickets to a sprint
|
|
775
|
+
*/
|
|
776
|
+
export async function addTicketsToSprint(sprintId, input) {
|
|
777
|
+
const parsed = AddTicketsToSprintSchema.parse(input);
|
|
778
|
+
const db = getDb();
|
|
779
|
+
if (!db)
|
|
780
|
+
throw new Error('Database not initialized');
|
|
781
|
+
// Verify sprint exists
|
|
782
|
+
const sprint = await getSprint(sprintId);
|
|
783
|
+
if (!sprint)
|
|
784
|
+
throw new Error(`Sprint ${sprintId} not found`);
|
|
785
|
+
const now = new Date();
|
|
786
|
+
const results = [];
|
|
787
|
+
// Get current max sort order
|
|
788
|
+
const maxOrderResult = await db
|
|
789
|
+
.select({ maxOrder: sql `MAX(${sprintTickets.sortOrder})` })
|
|
790
|
+
.from(sprintTickets)
|
|
791
|
+
.where(eq(sprintTickets.sprintId, sprintId));
|
|
792
|
+
let nextOrder = (maxOrderResult[0]?.maxOrder || 0) + 1;
|
|
793
|
+
for (const ticketId of parsed.ticketIds) {
|
|
794
|
+
// Check if already assigned
|
|
795
|
+
const existing = await db
|
|
796
|
+
.select()
|
|
797
|
+
.from(sprintTickets)
|
|
798
|
+
.where(and(eq(sprintTickets.sprintId, sprintId), eq(sprintTickets.ticketId, ticketId)))
|
|
799
|
+
.limit(1);
|
|
800
|
+
if (existing.length > 0)
|
|
801
|
+
continue; // Skip if already assigned
|
|
802
|
+
const id = generateId();
|
|
803
|
+
await db.insert(sprintTickets).values({
|
|
804
|
+
id,
|
|
805
|
+
sprintId,
|
|
806
|
+
ticketId,
|
|
807
|
+
sortOrder: nextOrder,
|
|
808
|
+
addedAt: now,
|
|
809
|
+
});
|
|
810
|
+
results.push({
|
|
811
|
+
id,
|
|
812
|
+
sprintId,
|
|
813
|
+
ticketId,
|
|
814
|
+
sortOrder: nextOrder,
|
|
815
|
+
addedAt: now.toISOString(),
|
|
816
|
+
});
|
|
817
|
+
nextOrder++;
|
|
818
|
+
}
|
|
819
|
+
return results;
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Remove a ticket from a sprint
|
|
823
|
+
*/
|
|
824
|
+
export async function removeTicketFromSprint(sprintId, ticketId) {
|
|
825
|
+
const db = getDb();
|
|
826
|
+
if (!db)
|
|
827
|
+
throw new Error('Database not initialized');
|
|
828
|
+
await db
|
|
829
|
+
.delete(sprintTickets)
|
|
830
|
+
.where(and(eq(sprintTickets.sprintId, sprintId), eq(sprintTickets.ticketId, ticketId)));
|
|
831
|
+
return true;
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Get all tickets in a sprint
|
|
835
|
+
*/
|
|
836
|
+
export async function getSprintTickets(sprintId) {
|
|
837
|
+
const db = getDb();
|
|
838
|
+
if (!db)
|
|
839
|
+
throw new Error('Database not initialized');
|
|
840
|
+
const result = await db
|
|
841
|
+
.select({ ticketId: sprintTickets.ticketId })
|
|
842
|
+
.from(sprintTickets)
|
|
843
|
+
.where(eq(sprintTickets.sprintId, sprintId))
|
|
844
|
+
.orderBy(asc(sprintTickets.sortOrder));
|
|
845
|
+
return result.map((r) => r.ticketId);
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Reorder tickets in a sprint
|
|
849
|
+
*/
|
|
850
|
+
export async function reorderSprintTickets(sprintId, ticketOrder) {
|
|
851
|
+
const db = getDb();
|
|
852
|
+
if (!db)
|
|
853
|
+
throw new Error('Database not initialized');
|
|
854
|
+
// Update sort order for each ticket
|
|
855
|
+
for (let i = 0; i < ticketOrder.length; i++) {
|
|
856
|
+
await db
|
|
857
|
+
.update(sprintTickets)
|
|
858
|
+
.set({ sortOrder: i })
|
|
859
|
+
.where(and(eq(sprintTickets.sprintId, sprintId), eq(sprintTickets.ticketId, ticketOrder[i])));
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
// DEFAULT PROJECT MANAGEMENT
|
|
863
|
+
/**
|
|
864
|
+
* Get or create the default project
|
|
865
|
+
*/
|
|
866
|
+
export async function getOrCreateDefaultProject() {
|
|
867
|
+
const existing = await getProjectByKey('PC');
|
|
868
|
+
if (existing)
|
|
869
|
+
return existing;
|
|
870
|
+
return createProject({
|
|
871
|
+
key: 'PC',
|
|
872
|
+
name: 'profClaw',
|
|
873
|
+
description: 'Default project for profClaw tasks',
|
|
874
|
+
icon: '🚀',
|
|
875
|
+
color: '#6366f1',
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Migrate existing tickets to default project
|
|
880
|
+
*/
|
|
881
|
+
export async function migrateTicketsToDefaultProject() {
|
|
882
|
+
const db = getDb();
|
|
883
|
+
if (!db)
|
|
884
|
+
throw new Error('Database not initialized');
|
|
885
|
+
const defaultProject = await getOrCreateDefaultProject();
|
|
886
|
+
await db
|
|
887
|
+
.update(tickets)
|
|
888
|
+
.set({ projectId: defaultProject.id })
|
|
889
|
+
.where(sql `${tickets.projectId} IS NULL`);
|
|
890
|
+
// Get count of updated rows (libSQL might not return this directly)
|
|
891
|
+
const countResult = await db
|
|
892
|
+
.select({ count: count() })
|
|
893
|
+
.from(tickets)
|
|
894
|
+
.where(eq(tickets.projectId, defaultProject.id));
|
|
895
|
+
return { migrated: Number(countResult[0]?.count || 0) };
|
|
896
|
+
}
|
|
897
|
+
//# sourceMappingURL=index.js.map
|