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,1873 @@
|
|
|
1
|
+
import { drizzle } from "drizzle-orm/libsql";
|
|
2
|
+
import { createClient } from "@libsql/client";
|
|
3
|
+
import { eq, and, or, gte, lte, desc, asc, count, sql, } from "drizzle-orm";
|
|
4
|
+
import { randomUUID } from "crypto";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import * as schema from "./schema.js";
|
|
8
|
+
function isRecord(value) {
|
|
9
|
+
return typeof value === "object" && value !== null;
|
|
10
|
+
}
|
|
11
|
+
function getNumber(value, key) {
|
|
12
|
+
if (!isRecord(value))
|
|
13
|
+
return 0;
|
|
14
|
+
const candidate = value[key];
|
|
15
|
+
return typeof candidate === "number" ? candidate : 0;
|
|
16
|
+
}
|
|
17
|
+
function toSummary(row) {
|
|
18
|
+
return {
|
|
19
|
+
id: row.id,
|
|
20
|
+
taskId: row.taskId ?? undefined,
|
|
21
|
+
sessionId: row.sessionId ?? undefined,
|
|
22
|
+
createdAt: row.createdAt,
|
|
23
|
+
agent: row.agent,
|
|
24
|
+
model: row.model ?? undefined,
|
|
25
|
+
title: row.title,
|
|
26
|
+
whatChanged: row.whatChanged,
|
|
27
|
+
whyChanged: row.whyChanged ?? undefined,
|
|
28
|
+
howChanged: row.howChanged ?? undefined,
|
|
29
|
+
filesChanged: row.filesChanged,
|
|
30
|
+
decisions: row.decisions,
|
|
31
|
+
blockers: row.blockers,
|
|
32
|
+
artifacts: row.artifacts,
|
|
33
|
+
tokensUsed: row.tokensUsed,
|
|
34
|
+
cost: row.cost,
|
|
35
|
+
taskType: row.taskType ?? undefined,
|
|
36
|
+
component: row.component ?? undefined,
|
|
37
|
+
labels: row.labels ?? [],
|
|
38
|
+
linkedIssue: row.linkedIssue ?? undefined,
|
|
39
|
+
linkedPr: row.linkedPr ?? undefined,
|
|
40
|
+
repository: row.repository ?? undefined,
|
|
41
|
+
branch: row.branch ?? undefined,
|
|
42
|
+
rawOutput: row.rawOutput ?? undefined,
|
|
43
|
+
hasBlobOutput: row.hasBlobOutput ?? undefined,
|
|
44
|
+
metadata: row.metadata ?? undefined,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export class LibSQLAdapter {
|
|
48
|
+
_db = null;
|
|
49
|
+
_client = null;
|
|
50
|
+
dbUrl;
|
|
51
|
+
constructor(config = {}) {
|
|
52
|
+
const dbPath = config.dbPath || path.resolve(process.cwd(), "data", "profclaw.db");
|
|
53
|
+
this.dbUrl = `file:${dbPath}`;
|
|
54
|
+
}
|
|
55
|
+
async connect() {
|
|
56
|
+
const dbPath = this.dbUrl.replace("file:", "");
|
|
57
|
+
const dir = path.dirname(dbPath);
|
|
58
|
+
if (!fs.existsSync(dir) && dbPath !== ":memory:") {
|
|
59
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
this._client = createClient({ url: this.dbUrl });
|
|
62
|
+
this._db = drizzle(this.client, { schema });
|
|
63
|
+
// Ensure tables exist (POC auto-migration)
|
|
64
|
+
await this.initDatabase();
|
|
65
|
+
}
|
|
66
|
+
async initDatabase() {
|
|
67
|
+
await this.client.execute(`
|
|
68
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
69
|
+
id TEXT PRIMARY KEY,
|
|
70
|
+
title TEXT NOT NULL,
|
|
71
|
+
description TEXT,
|
|
72
|
+
prompt TEXT NOT NULL,
|
|
73
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
74
|
+
priority INTEGER NOT NULL DEFAULT 3,
|
|
75
|
+
source TEXT NOT NULL,
|
|
76
|
+
source_id TEXT,
|
|
77
|
+
source_url TEXT,
|
|
78
|
+
repository TEXT,
|
|
79
|
+
branch TEXT,
|
|
80
|
+
labels TEXT NOT NULL DEFAULT '[]',
|
|
81
|
+
assigned_agent TEXT,
|
|
82
|
+
assigned_agent_id TEXT,
|
|
83
|
+
ticket_id TEXT,
|
|
84
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
85
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
86
|
+
started_at INTEGER,
|
|
87
|
+
completed_at INTEGER,
|
|
88
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
89
|
+
result TEXT,
|
|
90
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
91
|
+
max_attempts INTEGER NOT NULL DEFAULT 3
|
|
92
|
+
)
|
|
93
|
+
`);
|
|
94
|
+
// Phase 17: Add ticket_id column migration for existing databases
|
|
95
|
+
try {
|
|
96
|
+
await this.client.execute(`ALTER TABLE tasks ADD COLUMN ticket_id TEXT`);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Column already exists - ignore
|
|
100
|
+
}
|
|
101
|
+
await this.client.execute(`
|
|
102
|
+
CREATE TABLE IF NOT EXISTS summaries (
|
|
103
|
+
id TEXT PRIMARY KEY,
|
|
104
|
+
task_id TEXT REFERENCES tasks(id),
|
|
105
|
+
session_id TEXT,
|
|
106
|
+
agent TEXT NOT NULL,
|
|
107
|
+
model TEXT,
|
|
108
|
+
title TEXT NOT NULL,
|
|
109
|
+
what_changed TEXT NOT NULL,
|
|
110
|
+
why_changed TEXT,
|
|
111
|
+
how_changed TEXT,
|
|
112
|
+
files_changed TEXT NOT NULL DEFAULT '[]',
|
|
113
|
+
decisions TEXT NOT NULL DEFAULT '[]',
|
|
114
|
+
blockers TEXT NOT NULL DEFAULT '[]',
|
|
115
|
+
artifacts TEXT NOT NULL DEFAULT '[]',
|
|
116
|
+
tokens_used TEXT,
|
|
117
|
+
cost TEXT,
|
|
118
|
+
task_type TEXT,
|
|
119
|
+
component TEXT,
|
|
120
|
+
labels TEXT NOT NULL DEFAULT '[]',
|
|
121
|
+
linked_issue TEXT,
|
|
122
|
+
linked_pr TEXT,
|
|
123
|
+
repository TEXT,
|
|
124
|
+
branch TEXT,
|
|
125
|
+
raw_output TEXT,
|
|
126
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
127
|
+
metadata TEXT
|
|
128
|
+
)
|
|
129
|
+
`);
|
|
130
|
+
await this.client.execute(`
|
|
131
|
+
CREATE TABLE IF NOT EXISTS embeddings (
|
|
132
|
+
id TEXT PRIMARY KEY,
|
|
133
|
+
entity_type TEXT NOT NULL,
|
|
134
|
+
entity_id TEXT NOT NULL,
|
|
135
|
+
embedding BLOB NOT NULL,
|
|
136
|
+
model TEXT NOT NULL,
|
|
137
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
138
|
+
)
|
|
139
|
+
`);
|
|
140
|
+
// Summary blobs table for large raw output (Phase 17)
|
|
141
|
+
await this.client.execute(`
|
|
142
|
+
CREATE TABLE IF NOT EXISTS summary_blobs (
|
|
143
|
+
id TEXT PRIMARY KEY,
|
|
144
|
+
summary_id TEXT NOT NULL REFERENCES summaries(id) ON DELETE CASCADE,
|
|
145
|
+
raw_output TEXT NOT NULL,
|
|
146
|
+
compressed_size INTEGER,
|
|
147
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
148
|
+
)
|
|
149
|
+
`);
|
|
150
|
+
// Add has_blob_output column to summaries if it doesn't exist
|
|
151
|
+
try {
|
|
152
|
+
await this.client.execute(`ALTER TABLE summaries ADD COLUMN has_blob_output INTEGER DEFAULT 0`);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Column already exists, ignore
|
|
156
|
+
}
|
|
157
|
+
await this.client.execute(`
|
|
158
|
+
CREATE TABLE IF NOT EXISTS settings (
|
|
159
|
+
key TEXT PRIMARY KEY,
|
|
160
|
+
value TEXT NOT NULL,
|
|
161
|
+
category TEXT NOT NULL,
|
|
162
|
+
is_secret INTEGER NOT NULL DEFAULT 0,
|
|
163
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
164
|
+
)
|
|
165
|
+
`);
|
|
166
|
+
await this.client.execute(`
|
|
167
|
+
CREATE TABLE IF NOT EXISTS api_tokens (
|
|
168
|
+
id TEXT PRIMARY KEY,
|
|
169
|
+
name TEXT NOT NULL,
|
|
170
|
+
token_hash TEXT NOT NULL,
|
|
171
|
+
scopes TEXT NOT NULL DEFAULT '[]',
|
|
172
|
+
last_used_at INTEGER,
|
|
173
|
+
expires_at INTEGER,
|
|
174
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
175
|
+
)
|
|
176
|
+
`);
|
|
177
|
+
await this.client.execute(`
|
|
178
|
+
CREATE TABLE IF NOT EXISTS github_tokens (
|
|
179
|
+
id TEXT PRIMARY KEY,
|
|
180
|
+
user_id TEXT NOT NULL DEFAULT 'default',
|
|
181
|
+
access_token TEXT NOT NULL,
|
|
182
|
+
token_type TEXT NOT NULL DEFAULT 'pat',
|
|
183
|
+
scopes TEXT,
|
|
184
|
+
github_username TEXT,
|
|
185
|
+
expires_at INTEGER,
|
|
186
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
187
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
188
|
+
)
|
|
189
|
+
`);
|
|
190
|
+
await this.client.execute(`
|
|
191
|
+
CREATE TABLE IF NOT EXISTS task_events (
|
|
192
|
+
id TEXT PRIMARY KEY,
|
|
193
|
+
task_id TEXT NOT NULL REFERENCES tasks(id),
|
|
194
|
+
type TEXT NOT NULL,
|
|
195
|
+
agent_id TEXT,
|
|
196
|
+
message TEXT,
|
|
197
|
+
metadata TEXT,
|
|
198
|
+
timestamp INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
199
|
+
)
|
|
200
|
+
`);
|
|
201
|
+
await this.client.execute(`
|
|
202
|
+
CREATE TABLE IF NOT EXISTS task_archives (
|
|
203
|
+
id TEXT PRIMARY KEY,
|
|
204
|
+
original_id TEXT NOT NULL,
|
|
205
|
+
title TEXT NOT NULL,
|
|
206
|
+
description TEXT,
|
|
207
|
+
prompt TEXT NOT NULL,
|
|
208
|
+
status TEXT NOT NULL,
|
|
209
|
+
priority INTEGER NOT NULL,
|
|
210
|
+
source TEXT NOT NULL,
|
|
211
|
+
source_id TEXT,
|
|
212
|
+
source_url TEXT,
|
|
213
|
+
repository TEXT,
|
|
214
|
+
branch TEXT,
|
|
215
|
+
labels TEXT NOT NULL DEFAULT '[]',
|
|
216
|
+
assigned_agent TEXT,
|
|
217
|
+
assigned_agent_id TEXT,
|
|
218
|
+
created_at INTEGER NOT NULL,
|
|
219
|
+
started_at INTEGER,
|
|
220
|
+
completed_at INTEGER,
|
|
221
|
+
archived_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
222
|
+
result TEXT,
|
|
223
|
+
metadata TEXT,
|
|
224
|
+
duration_ms INTEGER
|
|
225
|
+
)
|
|
226
|
+
`);
|
|
227
|
+
// === TICKET SYSTEM TABLES ===
|
|
228
|
+
await this.client.execute(`
|
|
229
|
+
CREATE TABLE IF NOT EXISTS tickets (
|
|
230
|
+
id TEXT PRIMARY KEY,
|
|
231
|
+
sequence INTEGER NOT NULL,
|
|
232
|
+
workspace_id TEXT,
|
|
233
|
+
title TEXT NOT NULL,
|
|
234
|
+
description TEXT NOT NULL DEFAULT '',
|
|
235
|
+
description_html TEXT,
|
|
236
|
+
type TEXT NOT NULL DEFAULT 'task',
|
|
237
|
+
priority TEXT NOT NULL DEFAULT 'medium',
|
|
238
|
+
status TEXT NOT NULL DEFAULT 'backlog',
|
|
239
|
+
labels TEXT NOT NULL DEFAULT '[]',
|
|
240
|
+
assignee TEXT,
|
|
241
|
+
assignee_agent TEXT,
|
|
242
|
+
parent_id TEXT REFERENCES tickets(id),
|
|
243
|
+
linked_prs TEXT NOT NULL DEFAULT '[]',
|
|
244
|
+
linked_commits TEXT NOT NULL DEFAULT '[]',
|
|
245
|
+
linked_branch TEXT,
|
|
246
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
247
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
248
|
+
started_at INTEGER,
|
|
249
|
+
completed_at INTEGER,
|
|
250
|
+
start_date INTEGER,
|
|
251
|
+
due_date INTEGER,
|
|
252
|
+
created_by TEXT NOT NULL DEFAULT 'human',
|
|
253
|
+
ai_agent TEXT,
|
|
254
|
+
ai_session_id TEXT,
|
|
255
|
+
ai_task_id TEXT REFERENCES tasks(id),
|
|
256
|
+
estimate INTEGER,
|
|
257
|
+
estimate_unit TEXT
|
|
258
|
+
)
|
|
259
|
+
`);
|
|
260
|
+
// Add start_date column to tickets if it doesn't exist
|
|
261
|
+
try {
|
|
262
|
+
await this.client.execute(`ALTER TABLE tickets ADD COLUMN start_date INTEGER`);
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
// Column already exists - ignore
|
|
266
|
+
}
|
|
267
|
+
await this.client.execute(`
|
|
268
|
+
CREATE TABLE IF NOT EXISTS ticket_external_links (
|
|
269
|
+
id TEXT PRIMARY KEY,
|
|
270
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
271
|
+
platform TEXT NOT NULL,
|
|
272
|
+
external_id TEXT NOT NULL,
|
|
273
|
+
external_url TEXT,
|
|
274
|
+
sync_enabled INTEGER NOT NULL DEFAULT 1,
|
|
275
|
+
sync_direction TEXT NOT NULL DEFAULT 'bidirectional',
|
|
276
|
+
last_synced_at INTEGER,
|
|
277
|
+
sync_error TEXT,
|
|
278
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
279
|
+
)
|
|
280
|
+
`);
|
|
281
|
+
await this.client.execute(`
|
|
282
|
+
CREATE TABLE IF NOT EXISTS ticket_comments (
|
|
283
|
+
id TEXT PRIMARY KEY,
|
|
284
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
285
|
+
content TEXT NOT NULL,
|
|
286
|
+
content_html TEXT,
|
|
287
|
+
author_type TEXT NOT NULL DEFAULT 'human',
|
|
288
|
+
author_name TEXT NOT NULL,
|
|
289
|
+
author_platform TEXT NOT NULL,
|
|
290
|
+
author_avatar_url TEXT,
|
|
291
|
+
source TEXT NOT NULL DEFAULT 'profclaw',
|
|
292
|
+
external_id TEXT,
|
|
293
|
+
is_ai_response INTEGER NOT NULL DEFAULT 0,
|
|
294
|
+
responding_to TEXT REFERENCES ticket_comments(id),
|
|
295
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
296
|
+
updated_at INTEGER
|
|
297
|
+
)
|
|
298
|
+
`);
|
|
299
|
+
await this.client.execute(`
|
|
300
|
+
CREATE TABLE IF NOT EXISTS ticket_relations (
|
|
301
|
+
id TEXT PRIMARY KEY,
|
|
302
|
+
source_ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
303
|
+
target_ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
304
|
+
relation_type TEXT NOT NULL,
|
|
305
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
306
|
+
)
|
|
307
|
+
`);
|
|
308
|
+
await this.client.execute(`
|
|
309
|
+
CREATE TABLE IF NOT EXISTS ticket_history (
|
|
310
|
+
id TEXT PRIMARY KEY,
|
|
311
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
312
|
+
field TEXT NOT NULL,
|
|
313
|
+
old_value TEXT,
|
|
314
|
+
new_value TEXT,
|
|
315
|
+
changed_by_type TEXT NOT NULL DEFAULT 'human',
|
|
316
|
+
changed_by_name TEXT NOT NULL,
|
|
317
|
+
changed_by_platform TEXT NOT NULL DEFAULT 'profclaw',
|
|
318
|
+
timestamp INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
319
|
+
)
|
|
320
|
+
`);
|
|
321
|
+
await this.client.execute(`
|
|
322
|
+
CREATE TABLE IF NOT EXISTS ticket_watchers (
|
|
323
|
+
id TEXT PRIMARY KEY,
|
|
324
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
325
|
+
user_id TEXT NOT NULL,
|
|
326
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
327
|
+
)
|
|
328
|
+
`);
|
|
329
|
+
await this.client.execute(`
|
|
330
|
+
CREATE TABLE IF NOT EXISTS ticket_assignees (
|
|
331
|
+
id TEXT PRIMARY KEY,
|
|
332
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
333
|
+
user_id TEXT NOT NULL,
|
|
334
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
335
|
+
)
|
|
336
|
+
`);
|
|
337
|
+
await this.client.execute(`
|
|
338
|
+
CREATE TABLE IF NOT EXISTS ticket_mentions (
|
|
339
|
+
id TEXT PRIMARY KEY,
|
|
340
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
341
|
+
user_id TEXT NOT NULL,
|
|
342
|
+
source TEXT NOT NULL,
|
|
343
|
+
source_id TEXT,
|
|
344
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
345
|
+
)
|
|
346
|
+
`);
|
|
347
|
+
await this.client.execute(`
|
|
348
|
+
CREATE TABLE IF NOT EXISTS ticket_attachments (
|
|
349
|
+
id TEXT PRIMARY KEY,
|
|
350
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
351
|
+
file_name TEXT NOT NULL,
|
|
352
|
+
file_type TEXT,
|
|
353
|
+
file_size INTEGER,
|
|
354
|
+
url TEXT NOT NULL,
|
|
355
|
+
storage_path TEXT,
|
|
356
|
+
uploaded_by TEXT,
|
|
357
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
358
|
+
)
|
|
359
|
+
`);
|
|
360
|
+
await this.client.execute(`
|
|
361
|
+
CREATE TABLE IF NOT EXISTS ticket_reactions (
|
|
362
|
+
id TEXT PRIMARY KEY,
|
|
363
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
364
|
+
user_id TEXT NOT NULL,
|
|
365
|
+
emoji TEXT NOT NULL,
|
|
366
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
367
|
+
)
|
|
368
|
+
`);
|
|
369
|
+
await this.client.execute(`
|
|
370
|
+
CREATE TABLE IF NOT EXISTS ticket_sequence (
|
|
371
|
+
workspace_id TEXT PRIMARY KEY DEFAULT 'default',
|
|
372
|
+
last_sequence INTEGER NOT NULL DEFAULT 0
|
|
373
|
+
)
|
|
374
|
+
`);
|
|
375
|
+
// === PROJECTS & SPRINTS TABLES ===
|
|
376
|
+
await this.client.execute(`
|
|
377
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
378
|
+
id TEXT PRIMARY KEY,
|
|
379
|
+
sequence INTEGER NOT NULL,
|
|
380
|
+
workspace_id TEXT DEFAULT 'default',
|
|
381
|
+
key TEXT NOT NULL UNIQUE,
|
|
382
|
+
name TEXT NOT NULL,
|
|
383
|
+
description TEXT,
|
|
384
|
+
icon TEXT DEFAULT '📋',
|
|
385
|
+
color TEXT DEFAULT '#6366f1',
|
|
386
|
+
default_assignee TEXT,
|
|
387
|
+
default_agent TEXT,
|
|
388
|
+
default_labels TEXT DEFAULT '[]',
|
|
389
|
+
cycle_view INTEGER DEFAULT 1,
|
|
390
|
+
board_view INTEGER DEFAULT 1,
|
|
391
|
+
lead TEXT,
|
|
392
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
393
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
394
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
395
|
+
archived_at INTEGER
|
|
396
|
+
)
|
|
397
|
+
`);
|
|
398
|
+
await this.client.execute(`
|
|
399
|
+
CREATE TABLE IF NOT EXISTS project_sequence (
|
|
400
|
+
workspace_id TEXT PRIMARY KEY DEFAULT 'default',
|
|
401
|
+
last_sequence INTEGER NOT NULL DEFAULT 0
|
|
402
|
+
)
|
|
403
|
+
`);
|
|
404
|
+
await this.client.execute(`
|
|
405
|
+
CREATE TABLE IF NOT EXISTS states (
|
|
406
|
+
id TEXT PRIMARY KEY,
|
|
407
|
+
project_id TEXT REFERENCES projects(id),
|
|
408
|
+
name TEXT NOT NULL,
|
|
409
|
+
slug TEXT NOT NULL,
|
|
410
|
+
color TEXT NOT NULL DEFAULT '#6B7280',
|
|
411
|
+
description TEXT,
|
|
412
|
+
state_group TEXT NOT NULL,
|
|
413
|
+
is_default INTEGER NOT NULL DEFAULT 0,
|
|
414
|
+
sequence INTEGER NOT NULL DEFAULT 65535,
|
|
415
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
416
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
417
|
+
)
|
|
418
|
+
`);
|
|
419
|
+
await this.client.execute(`
|
|
420
|
+
CREATE TABLE IF NOT EXISTS project_external_links (
|
|
421
|
+
id TEXT PRIMARY KEY,
|
|
422
|
+
project_id TEXT NOT NULL REFERENCES projects(id),
|
|
423
|
+
platform TEXT NOT NULL,
|
|
424
|
+
external_id TEXT NOT NULL,
|
|
425
|
+
external_url TEXT,
|
|
426
|
+
sync_enabled INTEGER NOT NULL DEFAULT 1,
|
|
427
|
+
sync_direction TEXT NOT NULL DEFAULT 'bidirectional',
|
|
428
|
+
last_synced_at INTEGER,
|
|
429
|
+
sync_error TEXT,
|
|
430
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
431
|
+
)
|
|
432
|
+
`);
|
|
433
|
+
await this.client.execute(`
|
|
434
|
+
CREATE TABLE IF NOT EXISTS sprints (
|
|
435
|
+
id TEXT PRIMARY KEY,
|
|
436
|
+
sequence INTEGER NOT NULL,
|
|
437
|
+
project_id TEXT NOT NULL REFERENCES projects(id),
|
|
438
|
+
name TEXT NOT NULL,
|
|
439
|
+
goal TEXT,
|
|
440
|
+
description TEXT,
|
|
441
|
+
status TEXT NOT NULL DEFAULT 'planning',
|
|
442
|
+
start_date INTEGER,
|
|
443
|
+
end_date INTEGER,
|
|
444
|
+
capacity INTEGER,
|
|
445
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
446
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
447
|
+
completed_at INTEGER
|
|
448
|
+
)
|
|
449
|
+
`);
|
|
450
|
+
await this.client.execute(`
|
|
451
|
+
CREATE TABLE IF NOT EXISTS sprint_sequence (
|
|
452
|
+
project_id TEXT PRIMARY KEY,
|
|
453
|
+
last_sequence INTEGER NOT NULL DEFAULT 0
|
|
454
|
+
)
|
|
455
|
+
`);
|
|
456
|
+
await this.client.execute(`
|
|
457
|
+
CREATE TABLE IF NOT EXISTS sprint_tickets (
|
|
458
|
+
id TEXT PRIMARY KEY,
|
|
459
|
+
sprint_id TEXT NOT NULL REFERENCES sprints(id),
|
|
460
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id),
|
|
461
|
+
sort_order INTEGER DEFAULT 0,
|
|
462
|
+
added_at INTEGER DEFAULT CURRENT_TIMESTAMP
|
|
463
|
+
)
|
|
464
|
+
`);
|
|
465
|
+
// === USER AUTHENTICATION TABLES ===
|
|
466
|
+
await this.client.execute(`
|
|
467
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
468
|
+
id TEXT PRIMARY KEY,
|
|
469
|
+
email TEXT NOT NULL UNIQUE,
|
|
470
|
+
email_verified INTEGER DEFAULT 0,
|
|
471
|
+
password_hash TEXT,
|
|
472
|
+
name TEXT NOT NULL,
|
|
473
|
+
avatar_url TEXT,
|
|
474
|
+
bio TEXT,
|
|
475
|
+
timezone TEXT DEFAULT 'UTC',
|
|
476
|
+
locale TEXT DEFAULT 'en',
|
|
477
|
+
role TEXT NOT NULL DEFAULT 'user',
|
|
478
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
479
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
480
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
481
|
+
last_login_at INTEGER,
|
|
482
|
+
onboarding_completed INTEGER DEFAULT 0,
|
|
483
|
+
recovery_codes TEXT,
|
|
484
|
+
password_reset_token TEXT,
|
|
485
|
+
password_reset_expires INTEGER
|
|
486
|
+
)
|
|
487
|
+
`);
|
|
488
|
+
await this.client.execute(`
|
|
489
|
+
CREATE TABLE IF NOT EXISTS oauth_accounts (
|
|
490
|
+
id TEXT PRIMARY KEY,
|
|
491
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
492
|
+
provider TEXT NOT NULL,
|
|
493
|
+
provider_account_id TEXT NOT NULL,
|
|
494
|
+
provider_username TEXT,
|
|
495
|
+
access_token TEXT NOT NULL,
|
|
496
|
+
refresh_token TEXT,
|
|
497
|
+
token_type TEXT DEFAULT 'bearer',
|
|
498
|
+
scope TEXT,
|
|
499
|
+
expires_at INTEGER,
|
|
500
|
+
provider_data TEXT,
|
|
501
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
502
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
503
|
+
)
|
|
504
|
+
`);
|
|
505
|
+
await this.client.execute(`
|
|
506
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
507
|
+
id TEXT PRIMARY KEY,
|
|
508
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
509
|
+
token TEXT NOT NULL UNIQUE,
|
|
510
|
+
user_agent TEXT,
|
|
511
|
+
ip_address TEXT,
|
|
512
|
+
device_name TEXT,
|
|
513
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
514
|
+
expires_at INTEGER NOT NULL,
|
|
515
|
+
last_active_at INTEGER DEFAULT CURRENT_TIMESTAMP
|
|
516
|
+
)
|
|
517
|
+
`);
|
|
518
|
+
await this.client.execute(`
|
|
519
|
+
CREATE TABLE IF NOT EXISTS user_preferences (
|
|
520
|
+
id TEXT PRIMARY KEY,
|
|
521
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE UNIQUE,
|
|
522
|
+
theme TEXT DEFAULT 'system',
|
|
523
|
+
accent_color TEXT DEFAULT '#6366f1',
|
|
524
|
+
font_size TEXT DEFAULT 'medium',
|
|
525
|
+
email_notifications INTEGER DEFAULT 1,
|
|
526
|
+
push_notifications INTEGER DEFAULT 1,
|
|
527
|
+
notify_on_mention INTEGER DEFAULT 1,
|
|
528
|
+
notify_on_assign INTEGER DEFAULT 1,
|
|
529
|
+
notify_on_comment INTEGER DEFAULT 0,
|
|
530
|
+
default_agent TEXT DEFAULT 'claude',
|
|
531
|
+
ai_auto_suggest INTEGER DEFAULT 1,
|
|
532
|
+
ai_response_length TEXT DEFAULT 'balanced',
|
|
533
|
+
editor_mode TEXT DEFAULT 'markdown',
|
|
534
|
+
tab_size INTEGER DEFAULT 2,
|
|
535
|
+
extra_settings TEXT DEFAULT '{}',
|
|
536
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
537
|
+
)
|
|
538
|
+
`);
|
|
539
|
+
await this.client.execute(`
|
|
540
|
+
CREATE TABLE IF NOT EXISTS user_api_keys (
|
|
541
|
+
id TEXT PRIMARY KEY,
|
|
542
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
543
|
+
name TEXT NOT NULL,
|
|
544
|
+
key_hash TEXT NOT NULL,
|
|
545
|
+
key_prefix TEXT NOT NULL,
|
|
546
|
+
scopes TEXT DEFAULT '["read"]',
|
|
547
|
+
last_used_at INTEGER,
|
|
548
|
+
usage_count INTEGER DEFAULT 0,
|
|
549
|
+
expires_at INTEGER,
|
|
550
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
551
|
+
revoked_at INTEGER
|
|
552
|
+
)
|
|
553
|
+
`);
|
|
554
|
+
// === LABELS SYSTEM TABLES ===
|
|
555
|
+
await this.client.execute(`
|
|
556
|
+
CREATE TABLE IF NOT EXISTS labels (
|
|
557
|
+
id TEXT PRIMARY KEY,
|
|
558
|
+
project_id TEXT REFERENCES projects(id),
|
|
559
|
+
name TEXT NOT NULL,
|
|
560
|
+
description TEXT,
|
|
561
|
+
color TEXT NOT NULL DEFAULT '#6B7280',
|
|
562
|
+
parent_id TEXT REFERENCES labels(id),
|
|
563
|
+
sort_order INTEGER NOT NULL DEFAULT 65535,
|
|
564
|
+
external_source TEXT,
|
|
565
|
+
external_id TEXT,
|
|
566
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
567
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
568
|
+
)
|
|
569
|
+
`);
|
|
570
|
+
await this.client.execute(`
|
|
571
|
+
CREATE TABLE IF NOT EXISTS ticket_labels (
|
|
572
|
+
id TEXT PRIMARY KEY,
|
|
573
|
+
ticket_id TEXT NOT NULL REFERENCES tickets(id) ON DELETE CASCADE,
|
|
574
|
+
label_id TEXT NOT NULL REFERENCES labels(id) ON DELETE CASCADE,
|
|
575
|
+
added_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
576
|
+
)
|
|
577
|
+
`);
|
|
578
|
+
// === GITHUB SYNC TRACKING TABLES ===
|
|
579
|
+
await this.client.execute(`
|
|
580
|
+
CREATE TABLE IF NOT EXISTS github_repository_syncs (
|
|
581
|
+
id TEXT PRIMARY KEY,
|
|
582
|
+
project_id TEXT NOT NULL REFERENCES projects(id),
|
|
583
|
+
repository_id INTEGER NOT NULL,
|
|
584
|
+
repository_name TEXT NOT NULL,
|
|
585
|
+
owner TEXT NOT NULL,
|
|
586
|
+
default_branch TEXT DEFAULT 'main',
|
|
587
|
+
sync_issues INTEGER NOT NULL DEFAULT 1,
|
|
588
|
+
sync_prs INTEGER NOT NULL DEFAULT 0,
|
|
589
|
+
auto_label_id TEXT REFERENCES labels(id),
|
|
590
|
+
last_sync_at INTEGER,
|
|
591
|
+
last_sync_status TEXT NOT NULL DEFAULT 'idle',
|
|
592
|
+
last_sync_error TEXT,
|
|
593
|
+
items_synced INTEGER NOT NULL DEFAULT 0,
|
|
594
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
595
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
596
|
+
)
|
|
597
|
+
`);
|
|
598
|
+
await this.client.execute(`
|
|
599
|
+
CREATE TABLE IF NOT EXISTS github_comment_syncs (
|
|
600
|
+
id TEXT PRIMARY KEY,
|
|
601
|
+
ticket_external_link_id TEXT NOT NULL REFERENCES ticket_external_links(id),
|
|
602
|
+
comment_id TEXT NOT NULL REFERENCES ticket_comments(id),
|
|
603
|
+
github_comment_id INTEGER NOT NULL,
|
|
604
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
605
|
+
)
|
|
606
|
+
`);
|
|
607
|
+
// === CRON / SCHEDULED JOBS TABLES ===
|
|
608
|
+
await this.client.execute(`
|
|
609
|
+
CREATE TABLE IF NOT EXISTS scheduled_jobs (
|
|
610
|
+
id TEXT PRIMARY KEY,
|
|
611
|
+
name TEXT NOT NULL,
|
|
612
|
+
description TEXT,
|
|
613
|
+
cron_expression TEXT,
|
|
614
|
+
interval_ms INTEGER,
|
|
615
|
+
run_at INTEGER,
|
|
616
|
+
timezone TEXT NOT NULL DEFAULT 'UTC',
|
|
617
|
+
event_trigger TEXT,
|
|
618
|
+
job_type TEXT NOT NULL,
|
|
619
|
+
payload TEXT NOT NULL,
|
|
620
|
+
template_id TEXT,
|
|
621
|
+
labels TEXT NOT NULL DEFAULT '[]',
|
|
622
|
+
delivery TEXT,
|
|
623
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
624
|
+
user_id TEXT,
|
|
625
|
+
project_id TEXT,
|
|
626
|
+
created_by TEXT NOT NULL DEFAULT 'human',
|
|
627
|
+
last_run_at INTEGER,
|
|
628
|
+
last_run_status TEXT,
|
|
629
|
+
last_run_error TEXT,
|
|
630
|
+
last_run_duration_ms INTEGER,
|
|
631
|
+
next_run_at INTEGER,
|
|
632
|
+
run_count INTEGER NOT NULL DEFAULT 0,
|
|
633
|
+
success_count INTEGER NOT NULL DEFAULT 0,
|
|
634
|
+
failure_count INTEGER NOT NULL DEFAULT 0,
|
|
635
|
+
max_runs INTEGER,
|
|
636
|
+
max_failures INTEGER,
|
|
637
|
+
expires_at INTEGER,
|
|
638
|
+
retry_on_failure INTEGER NOT NULL DEFAULT 1,
|
|
639
|
+
retry_delay_ms INTEGER DEFAULT 60000,
|
|
640
|
+
retry_backoff_multiplier INTEGER DEFAULT 2,
|
|
641
|
+
retry_max_delay_ms INTEGER DEFAULT 3600000,
|
|
642
|
+
current_retry_count INTEGER DEFAULT 0,
|
|
643
|
+
delete_on_complete INTEGER DEFAULT 0,
|
|
644
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
645
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
646
|
+
archived_at INTEGER
|
|
647
|
+
)
|
|
648
|
+
`);
|
|
649
|
+
await this.client.execute(`
|
|
650
|
+
CREATE TABLE IF NOT EXISTS job_run_history (
|
|
651
|
+
id TEXT PRIMARY KEY,
|
|
652
|
+
job_id TEXT NOT NULL REFERENCES scheduled_jobs(id) ON DELETE CASCADE,
|
|
653
|
+
started_at INTEGER NOT NULL,
|
|
654
|
+
completed_at INTEGER,
|
|
655
|
+
duration_ms INTEGER,
|
|
656
|
+
status TEXT NOT NULL,
|
|
657
|
+
output TEXT,
|
|
658
|
+
error TEXT,
|
|
659
|
+
triggered_by TEXT NOT NULL DEFAULT 'schedule',
|
|
660
|
+
event_data TEXT
|
|
661
|
+
)
|
|
662
|
+
`);
|
|
663
|
+
await this.client.execute(`
|
|
664
|
+
CREATE TABLE IF NOT EXISTS job_templates (
|
|
665
|
+
id TEXT PRIMARY KEY,
|
|
666
|
+
name TEXT NOT NULL,
|
|
667
|
+
description TEXT,
|
|
668
|
+
icon TEXT DEFAULT 'zap',
|
|
669
|
+
category TEXT NOT NULL DEFAULT 'custom',
|
|
670
|
+
user_id TEXT,
|
|
671
|
+
project_id TEXT,
|
|
672
|
+
job_type TEXT NOT NULL,
|
|
673
|
+
payload_template TEXT NOT NULL,
|
|
674
|
+
suggested_cron TEXT,
|
|
675
|
+
suggested_interval_ms INTEGER,
|
|
676
|
+
default_retry_policy TEXT,
|
|
677
|
+
default_delivery TEXT,
|
|
678
|
+
is_built_in INTEGER DEFAULT 0,
|
|
679
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
680
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
681
|
+
)
|
|
682
|
+
`);
|
|
683
|
+
await this.client.execute(`
|
|
684
|
+
CREATE TABLE IF NOT EXISTS dead_letter_tasks (
|
|
685
|
+
id TEXT PRIMARY KEY,
|
|
686
|
+
task_id TEXT NOT NULL,
|
|
687
|
+
title TEXT NOT NULL,
|
|
688
|
+
description TEXT,
|
|
689
|
+
prompt TEXT NOT NULL,
|
|
690
|
+
source TEXT NOT NULL,
|
|
691
|
+
source_id TEXT,
|
|
692
|
+
source_url TEXT,
|
|
693
|
+
repository TEXT,
|
|
694
|
+
branch TEXT,
|
|
695
|
+
labels TEXT NOT NULL DEFAULT '[]',
|
|
696
|
+
assigned_agent TEXT,
|
|
697
|
+
priority INTEGER NOT NULL DEFAULT 3,
|
|
698
|
+
attempts INTEGER NOT NULL,
|
|
699
|
+
max_attempts INTEGER NOT NULL,
|
|
700
|
+
last_error_code TEXT NOT NULL,
|
|
701
|
+
last_error_message TEXT NOT NULL,
|
|
702
|
+
last_error_stack TEXT,
|
|
703
|
+
retry_count INTEGER NOT NULL DEFAULT 0,
|
|
704
|
+
last_retry_at INTEGER,
|
|
705
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
706
|
+
resolved_at INTEGER,
|
|
707
|
+
resolved_by TEXT,
|
|
708
|
+
resolution_note TEXT,
|
|
709
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
710
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
711
|
+
task_created_at INTEGER,
|
|
712
|
+
task_started_at INTEGER
|
|
713
|
+
)
|
|
714
|
+
`);
|
|
715
|
+
// === AGENT SESSIONS TABLES (Phase 23) ===
|
|
716
|
+
await this.client.execute(`
|
|
717
|
+
CREATE TABLE IF NOT EXISTS agent_sessions (
|
|
718
|
+
id TEXT PRIMARY KEY,
|
|
719
|
+
parent_session_id TEXT REFERENCES agent_sessions(id),
|
|
720
|
+
conversation_id TEXT NOT NULL,
|
|
721
|
+
name TEXT NOT NULL,
|
|
722
|
+
description TEXT,
|
|
723
|
+
goal TEXT,
|
|
724
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
725
|
+
depth INTEGER NOT NULL DEFAULT 0,
|
|
726
|
+
current_step INTEGER NOT NULL DEFAULT 0,
|
|
727
|
+
max_steps INTEGER NOT NULL DEFAULT 20,
|
|
728
|
+
used_budget INTEGER NOT NULL DEFAULT 0,
|
|
729
|
+
max_budget INTEGER NOT NULL DEFAULT 20000,
|
|
730
|
+
final_result TEXT,
|
|
731
|
+
stop_reason TEXT,
|
|
732
|
+
allowed_tools TEXT,
|
|
733
|
+
disallowed_tools TEXT,
|
|
734
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
735
|
+
started_at INTEGER,
|
|
736
|
+
completed_at INTEGER,
|
|
737
|
+
updated_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
738
|
+
metadata TEXT NOT NULL DEFAULT '{}'
|
|
739
|
+
)
|
|
740
|
+
`);
|
|
741
|
+
await this.client.execute(`
|
|
742
|
+
CREATE TABLE IF NOT EXISTS session_messages (
|
|
743
|
+
id TEXT PRIMARY KEY,
|
|
744
|
+
from_session_id TEXT NOT NULL REFERENCES agent_sessions(id),
|
|
745
|
+
to_session_id TEXT NOT NULL REFERENCES agent_sessions(id),
|
|
746
|
+
type TEXT NOT NULL DEFAULT 'message',
|
|
747
|
+
subject TEXT,
|
|
748
|
+
content TEXT NOT NULL,
|
|
749
|
+
priority INTEGER NOT NULL DEFAULT 5,
|
|
750
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
751
|
+
reply_to_message_id TEXT REFERENCES session_messages(id),
|
|
752
|
+
expires_at INTEGER,
|
|
753
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
754
|
+
delivered_at INTEGER,
|
|
755
|
+
read_at INTEGER
|
|
756
|
+
)
|
|
757
|
+
`);
|
|
758
|
+
// Invite codes table (invite-only registration)
|
|
759
|
+
await this.client.execute(`
|
|
760
|
+
CREATE TABLE IF NOT EXISTS invite_codes (
|
|
761
|
+
id TEXT PRIMARY KEY,
|
|
762
|
+
code_hash TEXT NOT NULL UNIQUE,
|
|
763
|
+
created_by TEXT NOT NULL,
|
|
764
|
+
used_by TEXT,
|
|
765
|
+
used_at INTEGER,
|
|
766
|
+
expires_at INTEGER,
|
|
767
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
768
|
+
label TEXT
|
|
769
|
+
)
|
|
770
|
+
`);
|
|
771
|
+
// In-app notifications table
|
|
772
|
+
await this.client.execute(`
|
|
773
|
+
CREATE TABLE IF NOT EXISTS notifications (
|
|
774
|
+
id TEXT PRIMARY KEY,
|
|
775
|
+
user_id TEXT,
|
|
776
|
+
title TEXT NOT NULL,
|
|
777
|
+
description TEXT,
|
|
778
|
+
type TEXT NOT NULL DEFAULT 'info',
|
|
779
|
+
category TEXT NOT NULL DEFAULT 'system',
|
|
780
|
+
entity_type TEXT,
|
|
781
|
+
entity_id TEXT,
|
|
782
|
+
read INTEGER NOT NULL DEFAULT 0,
|
|
783
|
+
created_at INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
784
|
+
)
|
|
785
|
+
`);
|
|
786
|
+
await this.client.execute(`
|
|
787
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON notifications(user_id)
|
|
788
|
+
`);
|
|
789
|
+
await this.client.execute(`
|
|
790
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_read ON notifications(read)
|
|
791
|
+
`);
|
|
792
|
+
// Add new columns to scheduled_jobs if they don't exist
|
|
793
|
+
try {
|
|
794
|
+
await this.client.execute(`ALTER TABLE scheduled_jobs ADD COLUMN labels TEXT NOT NULL DEFAULT '[]'`);
|
|
795
|
+
}
|
|
796
|
+
catch {
|
|
797
|
+
// Column already exists, ignore
|
|
798
|
+
}
|
|
799
|
+
try {
|
|
800
|
+
await this.client.execute(`ALTER TABLE scheduled_jobs ADD COLUMN archived_at INTEGER`);
|
|
801
|
+
}
|
|
802
|
+
catch {
|
|
803
|
+
// Column already exists, ignore
|
|
804
|
+
}
|
|
805
|
+
try {
|
|
806
|
+
await this.client.execute(`ALTER TABLE scheduled_jobs ADD COLUMN last_run_duration_ms INTEGER`);
|
|
807
|
+
}
|
|
808
|
+
catch {
|
|
809
|
+
// Column already exists, ignore
|
|
810
|
+
}
|
|
811
|
+
try {
|
|
812
|
+
await this.client.execute(`ALTER TABLE scheduled_jobs ADD COLUMN retry_delay_ms INTEGER DEFAULT 60000`);
|
|
813
|
+
}
|
|
814
|
+
catch {
|
|
815
|
+
// Column already exists, ignore
|
|
816
|
+
}
|
|
817
|
+
// Create indexes for task_events
|
|
818
|
+
await this.client.execute(`
|
|
819
|
+
CREATE INDEX IF NOT EXISTS idx_task_events_task_id ON task_events(task_id)
|
|
820
|
+
`);
|
|
821
|
+
await this.client.execute(`
|
|
822
|
+
CREATE INDEX IF NOT EXISTS idx_task_events_type ON task_events(type)
|
|
823
|
+
`);
|
|
824
|
+
// Create index for task→ticket relationship (Phase 17)
|
|
825
|
+
await this.client.execute(`
|
|
826
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_ticket_id ON tasks(ticket_id)
|
|
827
|
+
`);
|
|
828
|
+
// Create indexes for summary_blobs (Phase 17)
|
|
829
|
+
await this.client.execute(`
|
|
830
|
+
CREATE INDEX IF NOT EXISTS idx_summary_blobs_summary_id ON summary_blobs(summary_id)
|
|
831
|
+
`);
|
|
832
|
+
// Create indexes for tickets
|
|
833
|
+
await this.client.execute(`
|
|
834
|
+
CREATE INDEX IF NOT EXISTS idx_tickets_status ON tickets(status)
|
|
835
|
+
`);
|
|
836
|
+
await this.client.execute(`
|
|
837
|
+
CREATE INDEX IF NOT EXISTS idx_tickets_type ON tickets(type)
|
|
838
|
+
`);
|
|
839
|
+
await this.client.execute(`
|
|
840
|
+
CREATE INDEX IF NOT EXISTS idx_tickets_assignee_agent ON tickets(assignee_agent)
|
|
841
|
+
`);
|
|
842
|
+
await this.client.execute(`
|
|
843
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_external_links_ticket_id ON ticket_external_links(ticket_id)
|
|
844
|
+
`);
|
|
845
|
+
await this.client.execute(`
|
|
846
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_external_links_platform ON ticket_external_links(platform, external_id)
|
|
847
|
+
`);
|
|
848
|
+
await this.client.execute(`
|
|
849
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_comments_ticket_id ON ticket_comments(ticket_id)
|
|
850
|
+
`);
|
|
851
|
+
await this.client.execute(`
|
|
852
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_history_ticket_id ON ticket_history(ticket_id)
|
|
853
|
+
`);
|
|
854
|
+
// Create indexes for projects
|
|
855
|
+
await this.client.execute(`
|
|
856
|
+
CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status)
|
|
857
|
+
`);
|
|
858
|
+
await this.client.execute(`
|
|
859
|
+
CREATE INDEX IF NOT EXISTS idx_projects_workspace_id ON projects(workspace_id)
|
|
860
|
+
`);
|
|
861
|
+
await this.client.execute(`
|
|
862
|
+
CREATE INDEX IF NOT EXISTS idx_project_external_links_project_id ON project_external_links(project_id)
|
|
863
|
+
`);
|
|
864
|
+
await this.client.execute(`
|
|
865
|
+
CREATE INDEX IF NOT EXISTS idx_project_external_links_platform ON project_external_links(platform, external_id)
|
|
866
|
+
`);
|
|
867
|
+
// Create indexes for sprints
|
|
868
|
+
await this.client.execute(`
|
|
869
|
+
CREATE INDEX IF NOT EXISTS idx_sprints_project_id ON sprints(project_id)
|
|
870
|
+
`);
|
|
871
|
+
await this.client.execute(`
|
|
872
|
+
CREATE INDEX IF NOT EXISTS idx_sprints_status ON sprints(status)
|
|
873
|
+
`);
|
|
874
|
+
await this.client.execute(`
|
|
875
|
+
CREATE INDEX IF NOT EXISTS idx_sprint_tickets_sprint_id ON sprint_tickets(sprint_id)
|
|
876
|
+
`);
|
|
877
|
+
await this.client.execute(`
|
|
878
|
+
CREATE INDEX IF NOT EXISTS idx_sprint_tickets_ticket_id ON sprint_tickets(ticket_id)
|
|
879
|
+
`);
|
|
880
|
+
// Create indexes for users/auth
|
|
881
|
+
await this.client.execute(`
|
|
882
|
+
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)
|
|
883
|
+
`);
|
|
884
|
+
await this.client.execute(`
|
|
885
|
+
CREATE INDEX IF NOT EXISTS idx_oauth_accounts_user_id ON oauth_accounts(user_id)
|
|
886
|
+
`);
|
|
887
|
+
await this.client.execute(`
|
|
888
|
+
CREATE INDEX IF NOT EXISTS idx_oauth_accounts_provider ON oauth_accounts(provider, provider_account_id)
|
|
889
|
+
`);
|
|
890
|
+
await this.client.execute(`
|
|
891
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id)
|
|
892
|
+
`);
|
|
893
|
+
await this.client.execute(`
|
|
894
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_token ON sessions(token)
|
|
895
|
+
`);
|
|
896
|
+
await this.client.execute(`
|
|
897
|
+
CREATE INDEX IF NOT EXISTS idx_user_api_keys_user_id ON user_api_keys(user_id)
|
|
898
|
+
`);
|
|
899
|
+
// Add project_id column to tickets table if it doesn't exist
|
|
900
|
+
try {
|
|
901
|
+
await this.client.execute(`ALTER TABLE tickets ADD COLUMN project_id TEXT REFERENCES projects(id)`);
|
|
902
|
+
}
|
|
903
|
+
catch {
|
|
904
|
+
// Column already exists, ignore
|
|
905
|
+
}
|
|
906
|
+
await this.client.execute(`
|
|
907
|
+
CREATE INDEX IF NOT EXISTS idx_tickets_project_id ON tickets(project_id)
|
|
908
|
+
`);
|
|
909
|
+
// Create indexes for labels
|
|
910
|
+
await this.client.execute(`
|
|
911
|
+
CREATE INDEX IF NOT EXISTS idx_labels_project_id ON labels(project_id)
|
|
912
|
+
`);
|
|
913
|
+
await this.client.execute(`
|
|
914
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_labels_name_project ON labels(project_id, name) WHERE project_id IS NOT NULL
|
|
915
|
+
`);
|
|
916
|
+
await this.client.execute(`
|
|
917
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_labels_ticket_id ON ticket_labels(ticket_id)
|
|
918
|
+
`);
|
|
919
|
+
await this.client.execute(`
|
|
920
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_labels_label_id ON ticket_labels(label_id)
|
|
921
|
+
`);
|
|
922
|
+
await this.client.execute(`
|
|
923
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_ticket_labels_unique ON ticket_labels(ticket_id, label_id)
|
|
924
|
+
`);
|
|
925
|
+
// Create indexes for GitHub sync
|
|
926
|
+
await this.client.execute(`
|
|
927
|
+
CREATE INDEX IF NOT EXISTS idx_github_repo_syncs_project_id ON github_repository_syncs(project_id)
|
|
928
|
+
`);
|
|
929
|
+
await this.client.execute(`
|
|
930
|
+
CREATE INDEX IF NOT EXISTS idx_github_comment_syncs_link_id ON github_comment_syncs(ticket_external_link_id)
|
|
931
|
+
`);
|
|
932
|
+
await this.client.execute(`
|
|
933
|
+
CREATE INDEX IF NOT EXISTS idx_github_comment_syncs_github_id ON github_comment_syncs(github_comment_id)
|
|
934
|
+
`);
|
|
935
|
+
// Create indexes for scheduled_jobs
|
|
936
|
+
await this.client.execute(`
|
|
937
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_jobs_status ON scheduled_jobs(status)
|
|
938
|
+
`);
|
|
939
|
+
await this.client.execute(`
|
|
940
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_jobs_job_type ON scheduled_jobs(job_type)
|
|
941
|
+
`);
|
|
942
|
+
await this.client.execute(`
|
|
943
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_jobs_next_run ON scheduled_jobs(next_run_at)
|
|
944
|
+
`);
|
|
945
|
+
await this.client.execute(`
|
|
946
|
+
CREATE INDEX IF NOT EXISTS idx_job_run_history_job_id ON job_run_history(job_id)
|
|
947
|
+
`);
|
|
948
|
+
await this.client.execute(`
|
|
949
|
+
CREATE INDEX IF NOT EXISTS idx_job_run_history_status ON job_run_history(status)
|
|
950
|
+
`);
|
|
951
|
+
// Composite index for efficient count queries (Phase 17: enables computing counts instead of storing)
|
|
952
|
+
await this.client.execute(`
|
|
953
|
+
CREATE INDEX IF NOT EXISTS idx_job_run_history_job_status ON job_run_history(job_id, status)
|
|
954
|
+
`);
|
|
955
|
+
await this.client.execute(`
|
|
956
|
+
CREATE INDEX IF NOT EXISTS idx_job_templates_category ON job_templates(category)
|
|
957
|
+
`);
|
|
958
|
+
// Create indexes for states/relations
|
|
959
|
+
await this.client.execute(`
|
|
960
|
+
CREATE INDEX IF NOT EXISTS idx_states_project_id ON states(project_id)
|
|
961
|
+
`);
|
|
962
|
+
await this.client.execute(`
|
|
963
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_relations_source ON ticket_relations(source_ticket_id)
|
|
964
|
+
`);
|
|
965
|
+
await this.client.execute(`
|
|
966
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_relations_target ON ticket_relations(target_ticket_id)
|
|
967
|
+
`);
|
|
968
|
+
// Create indexes for agent sessions
|
|
969
|
+
await this.client.execute(`
|
|
970
|
+
CREATE INDEX IF NOT EXISTS idx_agent_sessions_parent ON agent_sessions(parent_session_id)
|
|
971
|
+
`);
|
|
972
|
+
await this.client.execute(`
|
|
973
|
+
CREATE INDEX IF NOT EXISTS idx_agent_sessions_conversation ON agent_sessions(conversation_id)
|
|
974
|
+
`);
|
|
975
|
+
await this.client.execute(`
|
|
976
|
+
CREATE INDEX IF NOT EXISTS idx_session_messages_to ON session_messages(to_session_id)
|
|
977
|
+
`);
|
|
978
|
+
await this.client.execute(`
|
|
979
|
+
CREATE INDEX IF NOT EXISTS idx_session_messages_status ON session_messages(status)
|
|
980
|
+
`);
|
|
981
|
+
// Create indexes for DLQ
|
|
982
|
+
await this.client.execute(`
|
|
983
|
+
CREATE INDEX IF NOT EXISTS idx_dead_letter_tasks_status ON dead_letter_tasks(status)
|
|
984
|
+
`);
|
|
985
|
+
await this.client.execute(`
|
|
986
|
+
CREATE INDEX IF NOT EXISTS idx_dead_letter_tasks_task_id ON dead_letter_tasks(task_id)
|
|
987
|
+
`);
|
|
988
|
+
// === EXPERIENCE STORE (Phase 19, Category 5) ===
|
|
989
|
+
await this.client.execute(`
|
|
990
|
+
CREATE TABLE IF NOT EXISTS experiences (
|
|
991
|
+
id TEXT PRIMARY KEY,
|
|
992
|
+
type TEXT NOT NULL,
|
|
993
|
+
intent TEXT NOT NULL,
|
|
994
|
+
solution TEXT NOT NULL,
|
|
995
|
+
success_score REAL NOT NULL DEFAULT 1.0,
|
|
996
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
997
|
+
source_conversation_id TEXT NOT NULL DEFAULT '',
|
|
998
|
+
user_id TEXT,
|
|
999
|
+
created_at INTEGER NOT NULL,
|
|
1000
|
+
last_used_at INTEGER NOT NULL,
|
|
1001
|
+
use_count INTEGER NOT NULL DEFAULT 1,
|
|
1002
|
+
weight REAL NOT NULL DEFAULT 1.0
|
|
1003
|
+
)
|
|
1004
|
+
`);
|
|
1005
|
+
await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_experiences_type ON experiences(type)`);
|
|
1006
|
+
await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_experiences_intent ON experiences(intent)`);
|
|
1007
|
+
await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_experiences_user ON experiences(user_id)`);
|
|
1008
|
+
await this.client.execute(`CREATE INDEX IF NOT EXISTS idx_experiences_weight ON experiences(weight)`);
|
|
1009
|
+
}
|
|
1010
|
+
get db() {
|
|
1011
|
+
if (!this._db)
|
|
1012
|
+
throw new Error("Database not connected. Call connect() first.");
|
|
1013
|
+
return this._db;
|
|
1014
|
+
}
|
|
1015
|
+
get client() {
|
|
1016
|
+
if (!this._client)
|
|
1017
|
+
throw new Error("Client not connected. Call connect() first.");
|
|
1018
|
+
return this._client;
|
|
1019
|
+
}
|
|
1020
|
+
getDb() {
|
|
1021
|
+
return this.db;
|
|
1022
|
+
}
|
|
1023
|
+
getClient() {
|
|
1024
|
+
return this.client;
|
|
1025
|
+
}
|
|
1026
|
+
async disconnect() {
|
|
1027
|
+
if (this._client) {
|
|
1028
|
+
await this._client.close();
|
|
1029
|
+
this._client = null;
|
|
1030
|
+
this._db = null;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
// === Tasks ===
|
|
1034
|
+
async createTask(input) {
|
|
1035
|
+
const inputWithExtras = input;
|
|
1036
|
+
const id = inputWithExtras.id || randomUUID();
|
|
1037
|
+
const now = new Date();
|
|
1038
|
+
const newTask = {
|
|
1039
|
+
...input,
|
|
1040
|
+
id,
|
|
1041
|
+
status: inputWithExtras.status || "pending",
|
|
1042
|
+
createdAt: now,
|
|
1043
|
+
updatedAt: now,
|
|
1044
|
+
attempts: 0,
|
|
1045
|
+
maxAttempts: 3,
|
|
1046
|
+
};
|
|
1047
|
+
await this.db.insert(schema.tasks).values(newTask);
|
|
1048
|
+
return newTask;
|
|
1049
|
+
}
|
|
1050
|
+
async getTask(id) {
|
|
1051
|
+
const results = await this.db
|
|
1052
|
+
.select()
|
|
1053
|
+
.from(schema.tasks)
|
|
1054
|
+
.where(eq(schema.tasks.id, id));
|
|
1055
|
+
return results[0] || null;
|
|
1056
|
+
}
|
|
1057
|
+
async updateTask(id, updates) {
|
|
1058
|
+
const now = new Date();
|
|
1059
|
+
await this.db
|
|
1060
|
+
.update(schema.tasks)
|
|
1061
|
+
.set({ ...updates, updatedAt: now })
|
|
1062
|
+
.where(eq(schema.tasks.id, id));
|
|
1063
|
+
const updated = await this.getTask(id);
|
|
1064
|
+
if (!updated)
|
|
1065
|
+
throw new Error(`Task ${id} not found after update`);
|
|
1066
|
+
return updated;
|
|
1067
|
+
}
|
|
1068
|
+
async deleteTask(id) {
|
|
1069
|
+
await this.db
|
|
1070
|
+
.delete(schema.tasks)
|
|
1071
|
+
.where(eq(schema.tasks.id, id));
|
|
1072
|
+
// LibSQL results might be different from better-sqlite3
|
|
1073
|
+
return true;
|
|
1074
|
+
}
|
|
1075
|
+
async getTasks(query) {
|
|
1076
|
+
let whereClause = undefined;
|
|
1077
|
+
if (query?.status) {
|
|
1078
|
+
whereClause = eq(schema.tasks.status, query.status);
|
|
1079
|
+
}
|
|
1080
|
+
const tasks = await this.db
|
|
1081
|
+
.select()
|
|
1082
|
+
.from(schema.tasks)
|
|
1083
|
+
.where(whereClause)
|
|
1084
|
+
.limit(query?.limit || 50)
|
|
1085
|
+
.offset(query?.offset || 0)
|
|
1086
|
+
.orderBy(desc(schema.tasks.createdAt));
|
|
1087
|
+
const totalRes = await this.db
|
|
1088
|
+
.select({ value: count() })
|
|
1089
|
+
.from(schema.tasks)
|
|
1090
|
+
.where(whereClause);
|
|
1091
|
+
return {
|
|
1092
|
+
tasks: tasks,
|
|
1093
|
+
total: totalRes[0].value,
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
// === Summaries ===
|
|
1097
|
+
async createSummary(input) {
|
|
1098
|
+
const id = randomUUID();
|
|
1099
|
+
const now = new Date();
|
|
1100
|
+
// Extract rawOutput to store separately in blob table
|
|
1101
|
+
const { rawOutput, ...summaryData } = input;
|
|
1102
|
+
const hasBlob = !!rawOutput && rawOutput.length > 0;
|
|
1103
|
+
const newSummary = {
|
|
1104
|
+
...summaryData,
|
|
1105
|
+
id,
|
|
1106
|
+
createdAt: now,
|
|
1107
|
+
filesChanged: input.filesChanged || [],
|
|
1108
|
+
decisions: input.decisions || [],
|
|
1109
|
+
blockers: input.blockers || [],
|
|
1110
|
+
artifacts: input.artifacts || [],
|
|
1111
|
+
labels: input.labels || [],
|
|
1112
|
+
hasBlobOutput: hasBlob,
|
|
1113
|
+
rawOutput: null, // Don't store in main table anymore
|
|
1114
|
+
};
|
|
1115
|
+
await this.db.insert(schema.summaries).values(newSummary);
|
|
1116
|
+
// Store raw output in separate blob table
|
|
1117
|
+
if (hasBlob && rawOutput) {
|
|
1118
|
+
await this.db.insert(schema.summaryBlobs).values({
|
|
1119
|
+
id: randomUUID(),
|
|
1120
|
+
summaryId: id,
|
|
1121
|
+
rawOutput,
|
|
1122
|
+
compressedSize: rawOutput.length, // Future: actual compressed size
|
|
1123
|
+
createdAt: now,
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
return { ...newSummary, createdAt: now, rawOutput: undefined };
|
|
1127
|
+
}
|
|
1128
|
+
async getSummary(id, includeRawOutput = false) {
|
|
1129
|
+
const results = await this.db
|
|
1130
|
+
.select()
|
|
1131
|
+
.from(schema.summaries)
|
|
1132
|
+
.where(eq(schema.summaries.id, id));
|
|
1133
|
+
const summary = results[0];
|
|
1134
|
+
if (!summary)
|
|
1135
|
+
return null;
|
|
1136
|
+
// Fetch raw output from blob table if requested
|
|
1137
|
+
if (includeRawOutput && summary.hasBlobOutput) {
|
|
1138
|
+
const blob = await this.db
|
|
1139
|
+
.select()
|
|
1140
|
+
.from(schema.summaryBlobs)
|
|
1141
|
+
.where(eq(schema.summaryBlobs.summaryId, id))
|
|
1142
|
+
.limit(1);
|
|
1143
|
+
if (blob[0]) {
|
|
1144
|
+
return { ...summary, rawOutput: blob[0].rawOutput };
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
// Strip rawOutput from response if not requested (for backward compat with old data)
|
|
1148
|
+
if (!includeRawOutput) {
|
|
1149
|
+
return { ...summary, rawOutput: undefined };
|
|
1150
|
+
}
|
|
1151
|
+
return summary;
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Get raw output for a summary (lazy loading)
|
|
1155
|
+
*/
|
|
1156
|
+
async getSummaryRawOutput(summaryId) {
|
|
1157
|
+
// First check blob table (new storage)
|
|
1158
|
+
const blob = await this.db
|
|
1159
|
+
.select()
|
|
1160
|
+
.from(schema.summaryBlobs)
|
|
1161
|
+
.where(eq(schema.summaryBlobs.summaryId, summaryId))
|
|
1162
|
+
.limit(1);
|
|
1163
|
+
if (blob[0]) {
|
|
1164
|
+
return blob[0].rawOutput;
|
|
1165
|
+
}
|
|
1166
|
+
// Fallback to inline rawOutput for old summaries
|
|
1167
|
+
const summary = await this.db
|
|
1168
|
+
.select({ rawOutput: schema.summaries.rawOutput })
|
|
1169
|
+
.from(schema.summaries)
|
|
1170
|
+
.where(eq(schema.summaries.id, summaryId))
|
|
1171
|
+
.limit(1);
|
|
1172
|
+
return summary[0]?.rawOutput || null;
|
|
1173
|
+
}
|
|
1174
|
+
async getTaskSummaries(taskId) {
|
|
1175
|
+
return await this.db
|
|
1176
|
+
.select()
|
|
1177
|
+
.from(schema.summaries)
|
|
1178
|
+
.where(eq(schema.summaries.taskId, taskId))
|
|
1179
|
+
.orderBy(desc(schema.summaries.createdAt));
|
|
1180
|
+
}
|
|
1181
|
+
async querySummaries(query) {
|
|
1182
|
+
const conditions = [];
|
|
1183
|
+
if (query.taskId)
|
|
1184
|
+
conditions.push(eq(schema.summaries.taskId, query.taskId));
|
|
1185
|
+
if (query.sessionId)
|
|
1186
|
+
conditions.push(eq(schema.summaries.sessionId, query.sessionId));
|
|
1187
|
+
if (query.agent)
|
|
1188
|
+
conditions.push(eq(schema.summaries.agent, query.agent));
|
|
1189
|
+
if (query.taskType)
|
|
1190
|
+
conditions.push(eq(schema.summaries.taskType, query.taskType));
|
|
1191
|
+
if (query.component)
|
|
1192
|
+
conditions.push(eq(schema.summaries.component, query.component));
|
|
1193
|
+
if (query.repository)
|
|
1194
|
+
conditions.push(eq(schema.summaries.repository, query.repository));
|
|
1195
|
+
if (query.from)
|
|
1196
|
+
conditions.push(gte(schema.summaries.createdAt, query.from));
|
|
1197
|
+
if (query.to)
|
|
1198
|
+
conditions.push(lte(schema.summaries.createdAt, query.to));
|
|
1199
|
+
if (query.search) {
|
|
1200
|
+
const searchPattern = `%${query.search}%`;
|
|
1201
|
+
conditions.push(sql `(${schema.summaries.title} LIKE ${searchPattern} OR ${schema.summaries.whatChanged} LIKE ${searchPattern} OR ${schema.summaries.whyChanged} LIKE ${searchPattern} OR ${schema.summaries.howChanged} LIKE ${searchPattern} OR ${schema.summaries.rawOutput} LIKE ${searchPattern})`);
|
|
1202
|
+
}
|
|
1203
|
+
// Cursor-based pagination (Phase 17)
|
|
1204
|
+
if (query.cursorCreatedAt && query.cursorId) {
|
|
1205
|
+
const cursorTime = query.cursorCreatedAt;
|
|
1206
|
+
const cursorId = query.cursorId;
|
|
1207
|
+
const isDesc = query.sortOrder !== "asc";
|
|
1208
|
+
if (isDesc) {
|
|
1209
|
+
conditions.push(or(sql `${schema.summaries.createdAt} < ${cursorTime}`, and(sql `${schema.summaries.createdAt} = ${cursorTime}`, sql `${schema.summaries.id} < ${cursorId}`)));
|
|
1210
|
+
}
|
|
1211
|
+
else {
|
|
1212
|
+
conditions.push(or(sql `${schema.summaries.createdAt} > ${cursorTime}`, and(sql `${schema.summaries.createdAt} = ${cursorTime}`, sql `${schema.summaries.id} > ${cursorId}`)));
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
const whereClause = conditions.length > 0 ? and(...conditions) : undefined;
|
|
1216
|
+
const useCursor = !!(query.cursorCreatedAt && query.cursorId);
|
|
1217
|
+
// When using cursor, don't use offset (cursor already filters)
|
|
1218
|
+
const summaries = useCursor
|
|
1219
|
+
? await this.db
|
|
1220
|
+
.select()
|
|
1221
|
+
.from(schema.summaries)
|
|
1222
|
+
.where(whereClause)
|
|
1223
|
+
.limit(query.limit || 50)
|
|
1224
|
+
.orderBy(query.sortOrder === "asc"
|
|
1225
|
+
? asc(schema.summaries.createdAt)
|
|
1226
|
+
: desc(schema.summaries.createdAt))
|
|
1227
|
+
: await this.db
|
|
1228
|
+
.select()
|
|
1229
|
+
.from(schema.summaries)
|
|
1230
|
+
.where(whereClause)
|
|
1231
|
+
.limit(query.limit || 50)
|
|
1232
|
+
.offset(query.offset || 0)
|
|
1233
|
+
.orderBy(query.sortOrder === "asc"
|
|
1234
|
+
? asc(schema.summaries.createdAt)
|
|
1235
|
+
: desc(schema.summaries.createdAt));
|
|
1236
|
+
const totalRes = await this.db
|
|
1237
|
+
.select({ value: count() })
|
|
1238
|
+
.from(schema.summaries)
|
|
1239
|
+
.where(whereClause);
|
|
1240
|
+
return {
|
|
1241
|
+
summaries: summaries,
|
|
1242
|
+
total: totalRes[0].value,
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
async deleteSummary(id) {
|
|
1246
|
+
await this.db.delete(schema.summaries).where(eq(schema.summaries.id, id));
|
|
1247
|
+
return true;
|
|
1248
|
+
}
|
|
1249
|
+
async getSummaryStats() {
|
|
1250
|
+
// 1. Get totals and counts using SQL aggregation (Phase 17 optimization)
|
|
1251
|
+
const [counts] = await this.db
|
|
1252
|
+
.select({
|
|
1253
|
+
totalCount: count(),
|
|
1254
|
+
totalTokens: sql `SUM(CAST(json_extract(${schema.summaries.tokensUsed}, '$.total') AS INTEGER))`,
|
|
1255
|
+
totalCost: sql `SUM(CAST(json_extract(${schema.summaries.cost}, '$.amount') AS REAL))`,
|
|
1256
|
+
})
|
|
1257
|
+
.from(schema.summaries);
|
|
1258
|
+
// 2. Get distributions
|
|
1259
|
+
const agentStats = await this.db
|
|
1260
|
+
.select({
|
|
1261
|
+
agent: schema.summaries.agent,
|
|
1262
|
+
count: count(),
|
|
1263
|
+
})
|
|
1264
|
+
.from(schema.summaries)
|
|
1265
|
+
.groupBy(schema.summaries.agent);
|
|
1266
|
+
const typeStats = await this.db
|
|
1267
|
+
.select({
|
|
1268
|
+
type: schema.summaries.taskType,
|
|
1269
|
+
count: count(),
|
|
1270
|
+
})
|
|
1271
|
+
.from(schema.summaries)
|
|
1272
|
+
.groupBy(schema.summaries.taskType);
|
|
1273
|
+
const componentStats = await this.db
|
|
1274
|
+
.select({
|
|
1275
|
+
component: schema.summaries.component,
|
|
1276
|
+
count: count(),
|
|
1277
|
+
})
|
|
1278
|
+
.from(schema.summaries)
|
|
1279
|
+
.groupBy(schema.summaries.component);
|
|
1280
|
+
// 3. Get files changed count (requires custom SQL for JSON array length)
|
|
1281
|
+
const [filesRes] = await this.db
|
|
1282
|
+
.select({
|
|
1283
|
+
totalFiles: sql `SUM(json_array_length(${schema.summaries.filesChanged}))`,
|
|
1284
|
+
})
|
|
1285
|
+
.from(schema.summaries);
|
|
1286
|
+
const byAgent = {};
|
|
1287
|
+
agentStats.forEach((s) => {
|
|
1288
|
+
byAgent[s.agent] = s.count;
|
|
1289
|
+
});
|
|
1290
|
+
const byTaskType = {};
|
|
1291
|
+
typeStats.forEach((s) => {
|
|
1292
|
+
if (s.type)
|
|
1293
|
+
byTaskType[s.type] = s.count;
|
|
1294
|
+
});
|
|
1295
|
+
const byComponent = {};
|
|
1296
|
+
componentStats.forEach((s) => {
|
|
1297
|
+
if (s.component)
|
|
1298
|
+
byComponent[s.component] = s.count;
|
|
1299
|
+
});
|
|
1300
|
+
return {
|
|
1301
|
+
totalCount: counts.totalCount || 0,
|
|
1302
|
+
byAgent,
|
|
1303
|
+
byTaskType,
|
|
1304
|
+
byComponent,
|
|
1305
|
+
totalTokens: Number(counts.totalTokens || 0),
|
|
1306
|
+
totalCost: Number(counts.totalCost || 0),
|
|
1307
|
+
averageDuration: 0,
|
|
1308
|
+
filesChangedCount: Number(filesRes.totalFiles || 0),
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
async healthCheck() {
|
|
1312
|
+
const start = Date.now();
|
|
1313
|
+
try {
|
|
1314
|
+
await this.client.execute("SELECT 1");
|
|
1315
|
+
return { healthy: true, latencyMs: Date.now() - start };
|
|
1316
|
+
}
|
|
1317
|
+
catch {
|
|
1318
|
+
return { healthy: false, latencyMs: Date.now() - start };
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
async getAgentStats() {
|
|
1322
|
+
const results = await this.db
|
|
1323
|
+
.select({
|
|
1324
|
+
agent: schema.tasks.assignedAgent,
|
|
1325
|
+
status: schema.tasks.status,
|
|
1326
|
+
count: count(),
|
|
1327
|
+
avgDuration: sql `AVG(${schema.tasks.completedAt} - ${schema.tasks.startedAt})`,
|
|
1328
|
+
lastActivity: sql `MAX(${schema.tasks.updatedAt})`,
|
|
1329
|
+
})
|
|
1330
|
+
.from(schema.tasks)
|
|
1331
|
+
.where(sql `${schema.tasks.assignedAgent} IS NOT NULL`)
|
|
1332
|
+
.groupBy(schema.tasks.assignedAgent, schema.tasks.status);
|
|
1333
|
+
const stats = {};
|
|
1334
|
+
for (const row of results) {
|
|
1335
|
+
if (!row.agent)
|
|
1336
|
+
continue;
|
|
1337
|
+
if (!stats[row.agent]) {
|
|
1338
|
+
stats[row.agent] = {
|
|
1339
|
+
completed: 0,
|
|
1340
|
+
failed: 0,
|
|
1341
|
+
avgDuration: 0,
|
|
1342
|
+
lastActivity: null,
|
|
1343
|
+
};
|
|
1344
|
+
}
|
|
1345
|
+
if (row.status === "completed") {
|
|
1346
|
+
stats[row.agent].completed = row.count;
|
|
1347
|
+
stats[row.agent].avgDuration = row.avgDuration || 0;
|
|
1348
|
+
}
|
|
1349
|
+
else if (row.status === "failed") {
|
|
1350
|
+
stats[row.agent].failed = row.count;
|
|
1351
|
+
}
|
|
1352
|
+
if (row.lastActivity) {
|
|
1353
|
+
const lastActivity = new Date(row.lastActivity);
|
|
1354
|
+
if (!stats[row.agent].lastActivity ||
|
|
1355
|
+
lastActivity > stats[row.agent].lastActivity) {
|
|
1356
|
+
stats[row.agent].lastActivity = lastActivity;
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
return stats;
|
|
1361
|
+
}
|
|
1362
|
+
async getCostAnalytics() {
|
|
1363
|
+
const daily = {};
|
|
1364
|
+
const byModel = {};
|
|
1365
|
+
const byAgent = {};
|
|
1366
|
+
let totalCost = 0;
|
|
1367
|
+
let totalTokens = 0;
|
|
1368
|
+
// Helper to accumulate into the aggregation maps
|
|
1369
|
+
const accumulate = (date, model, agent, cost, tokens) => {
|
|
1370
|
+
totalCost += cost;
|
|
1371
|
+
totalTokens += tokens;
|
|
1372
|
+
if (!daily[date])
|
|
1373
|
+
daily[date] = { cost: 0, tokens: 0 };
|
|
1374
|
+
daily[date].cost += cost;
|
|
1375
|
+
daily[date].tokens += tokens;
|
|
1376
|
+
if (!byModel[model])
|
|
1377
|
+
byModel[model] = { cost: 0, tokens: 0 };
|
|
1378
|
+
byModel[model].cost += cost;
|
|
1379
|
+
byModel[model].tokens += tokens;
|
|
1380
|
+
if (!byAgent[agent])
|
|
1381
|
+
byAgent[agent] = { cost: 0, tokens: 0 };
|
|
1382
|
+
byAgent[agent].cost += cost;
|
|
1383
|
+
byAgent[agent].tokens += tokens;
|
|
1384
|
+
};
|
|
1385
|
+
// Source 1: Summaries table (queue task results)
|
|
1386
|
+
const all = await this.db.select().from(schema.summaries);
|
|
1387
|
+
for (const s of all) {
|
|
1388
|
+
if (!s.createdAt)
|
|
1389
|
+
continue;
|
|
1390
|
+
const date = s.createdAt.toISOString().split("T")[0];
|
|
1391
|
+
const model = s.model || "unknown";
|
|
1392
|
+
const agent = s.agent || "unknown";
|
|
1393
|
+
const costObj = s.cost;
|
|
1394
|
+
const tokensObj = s.tokensUsed;
|
|
1395
|
+
const cost = costObj?.amount || 0;
|
|
1396
|
+
const tokens = tokensObj?.total || 0;
|
|
1397
|
+
accumulate(date, model, agent, cost, tokens);
|
|
1398
|
+
}
|
|
1399
|
+
// Source 2: Conversation messages (chat/agentic sessions)
|
|
1400
|
+
try {
|
|
1401
|
+
const chatRows = await this.client.execute(`SELECT created_at, model, total_tokens, prompt_tokens, completion_tokens, cost
|
|
1402
|
+
FROM conversation_messages
|
|
1403
|
+
WHERE total_tokens > 0 AND role = 'assistant'`);
|
|
1404
|
+
for (const row of chatRows.rows) {
|
|
1405
|
+
const createdAt = row.created_at;
|
|
1406
|
+
if (!createdAt)
|
|
1407
|
+
continue;
|
|
1408
|
+
const date = createdAt.split("T")[0];
|
|
1409
|
+
const model = row.model || "unknown";
|
|
1410
|
+
const tokens = Number(row.total_tokens) || 0;
|
|
1411
|
+
const cost = Number(row.cost) || 0;
|
|
1412
|
+
accumulate(date, model, "chat", cost, tokens);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
catch {
|
|
1416
|
+
// conversation_messages table may not exist yet — skip silently
|
|
1417
|
+
}
|
|
1418
|
+
const dailyArray = Object.entries(daily)
|
|
1419
|
+
.map(([date, data]) => ({ date, ...data }))
|
|
1420
|
+
.sort((a, b) => a.date.localeCompare(b.date));
|
|
1421
|
+
return {
|
|
1422
|
+
daily: dailyArray,
|
|
1423
|
+
byModel,
|
|
1424
|
+
byAgent,
|
|
1425
|
+
totalCost,
|
|
1426
|
+
totalTokens,
|
|
1427
|
+
};
|
|
1428
|
+
}
|
|
1429
|
+
// === Vector Search ===
|
|
1430
|
+
async storeEmbedding(id, entityType, entityId, embedding, model) {
|
|
1431
|
+
// Convert float array to Buffer/Uint8Array for blob storage
|
|
1432
|
+
const float32Array = new Float32Array(embedding);
|
|
1433
|
+
const buffer = Buffer.from(float32Array.buffer);
|
|
1434
|
+
await this.db.insert(schema.embeddings).values({
|
|
1435
|
+
id,
|
|
1436
|
+
entityType,
|
|
1437
|
+
entityId,
|
|
1438
|
+
embedding: buffer,
|
|
1439
|
+
model,
|
|
1440
|
+
createdAt: new Date(),
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
async searchSimilar(entityType, embedding, limit = 5) {
|
|
1444
|
+
// Basic implementation: fetch all embeddings of that type and compute cosine similarity in-memory
|
|
1445
|
+
// In Phase 10.3 we would use sqlite-vec or libsql vector search if available.
|
|
1446
|
+
const allEmbeddings = await this.db
|
|
1447
|
+
.select()
|
|
1448
|
+
.from(schema.embeddings)
|
|
1449
|
+
.where(eq(schema.embeddings.entityType, entityType));
|
|
1450
|
+
if (allEmbeddings.length === 0)
|
|
1451
|
+
return [];
|
|
1452
|
+
const targetVector = new Float32Array(embedding);
|
|
1453
|
+
const results = allEmbeddings.map((row) => {
|
|
1454
|
+
const rowVector = new Float32Array(row.embedding.buffer, row.embedding.byteOffset, row.embedding.byteLength / 4);
|
|
1455
|
+
const distance = this.cosineSimilarity(targetVector, rowVector);
|
|
1456
|
+
return {
|
|
1457
|
+
entityId: row.entityId,
|
|
1458
|
+
distance,
|
|
1459
|
+
};
|
|
1460
|
+
});
|
|
1461
|
+
// Sort by descending similarity (1.0 is identical)
|
|
1462
|
+
results.sort((a, b) => b.distance - a.distance);
|
|
1463
|
+
return results.slice(0, limit);
|
|
1464
|
+
}
|
|
1465
|
+
cosineSimilarity(vecA, vecB) {
|
|
1466
|
+
if (vecA.length !== vecB.length)
|
|
1467
|
+
return 0;
|
|
1468
|
+
let dotProduct = 0;
|
|
1469
|
+
let normA = 0;
|
|
1470
|
+
let normB = 0;
|
|
1471
|
+
for (let i = 0; i < vecA.length; i++) {
|
|
1472
|
+
dotProduct += vecA[i] * vecB[i];
|
|
1473
|
+
normA += vecA[i] * vecA[i];
|
|
1474
|
+
normB += vecB[i] * vecB[i];
|
|
1475
|
+
}
|
|
1476
|
+
const norm = Math.sqrt(normA) * Math.sqrt(normB);
|
|
1477
|
+
return norm === 0 ? 0 : dotProduct / norm;
|
|
1478
|
+
}
|
|
1479
|
+
// === Generic SQL Operations ===
|
|
1480
|
+
async query(sql, params) {
|
|
1481
|
+
const result = await this.client.execute({
|
|
1482
|
+
sql,
|
|
1483
|
+
args: params || [],
|
|
1484
|
+
});
|
|
1485
|
+
return result.rows;
|
|
1486
|
+
}
|
|
1487
|
+
async execute(sql, params) {
|
|
1488
|
+
await this.client.execute({
|
|
1489
|
+
sql,
|
|
1490
|
+
args: params || [],
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
// === Task Events (Audit Log) ===
|
|
1494
|
+
async recordTaskEvent(event) {
|
|
1495
|
+
const id = randomUUID();
|
|
1496
|
+
await this.db.insert(schema.taskEvents).values({
|
|
1497
|
+
id,
|
|
1498
|
+
taskId: event.taskId,
|
|
1499
|
+
type: event.type,
|
|
1500
|
+
agentId: event.agentId,
|
|
1501
|
+
message: event.message,
|
|
1502
|
+
metadata: event.metadata,
|
|
1503
|
+
timestamp: new Date(),
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
async getTaskEvents(taskId) {
|
|
1507
|
+
const results = await this.db
|
|
1508
|
+
.select()
|
|
1509
|
+
.from(schema.taskEvents)
|
|
1510
|
+
.where(eq(schema.taskEvents.taskId, taskId))
|
|
1511
|
+
.orderBy(asc(schema.taskEvents.timestamp));
|
|
1512
|
+
return results.map((row) => ({
|
|
1513
|
+
id: row.id,
|
|
1514
|
+
taskId: row.taskId,
|
|
1515
|
+
type: row.type,
|
|
1516
|
+
timestamp: row.timestamp,
|
|
1517
|
+
agentId: row.agentId ?? undefined,
|
|
1518
|
+
message: row.message ?? undefined,
|
|
1519
|
+
metadata: row.metadata ?? undefined,
|
|
1520
|
+
}));
|
|
1521
|
+
}
|
|
1522
|
+
// === Task Analytics ===
|
|
1523
|
+
async getTaskAnalytics() {
|
|
1524
|
+
const allTasks = await this.db.select().from(schema.tasks);
|
|
1525
|
+
// Initialize counters
|
|
1526
|
+
const byStatus = {};
|
|
1527
|
+
const byPriority = {};
|
|
1528
|
+
const bySource = {};
|
|
1529
|
+
const byAgent = {};
|
|
1530
|
+
const daily = {};
|
|
1531
|
+
let totalDuration = 0;
|
|
1532
|
+
let durationCount = 0;
|
|
1533
|
+
let minDuration = Infinity;
|
|
1534
|
+
let maxDuration = 0;
|
|
1535
|
+
let recentCompletions = 0;
|
|
1536
|
+
let recentFailures = 0;
|
|
1537
|
+
const now = Date.now();
|
|
1538
|
+
const oneDayAgo = now - 24 * 60 * 60 * 1000;
|
|
1539
|
+
const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1000;
|
|
1540
|
+
for (const task of allTasks) {
|
|
1541
|
+
// Status counts
|
|
1542
|
+
byStatus[task.status] = (byStatus[task.status] || 0) + 1;
|
|
1543
|
+
// Priority counts
|
|
1544
|
+
byPriority[task.priority] = (byPriority[task.priority] || 0) + 1;
|
|
1545
|
+
// Source counts
|
|
1546
|
+
bySource[task.source] = (bySource[task.source] || 0) + 1;
|
|
1547
|
+
// Agent stats
|
|
1548
|
+
if (task.assignedAgent) {
|
|
1549
|
+
if (!byAgent[task.assignedAgent]) {
|
|
1550
|
+
byAgent[task.assignedAgent] = {
|
|
1551
|
+
count: 0,
|
|
1552
|
+
completed: 0,
|
|
1553
|
+
failed: 0,
|
|
1554
|
+
totalDuration: 0,
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
byAgent[task.assignedAgent].count++;
|
|
1558
|
+
if (task.status === "completed")
|
|
1559
|
+
byAgent[task.assignedAgent].completed++;
|
|
1560
|
+
if (task.status === "failed")
|
|
1561
|
+
byAgent[task.assignedAgent].failed++;
|
|
1562
|
+
// Duration for this agent
|
|
1563
|
+
if (task.startedAt && task.completedAt) {
|
|
1564
|
+
const startTime = task.startedAt instanceof Date
|
|
1565
|
+
? task.startedAt.getTime()
|
|
1566
|
+
: new Date(task.startedAt).getTime();
|
|
1567
|
+
const endTime = task.completedAt instanceof Date
|
|
1568
|
+
? task.completedAt.getTime()
|
|
1569
|
+
: new Date(task.completedAt).getTime();
|
|
1570
|
+
const duration = endTime - startTime;
|
|
1571
|
+
if (duration > 0) {
|
|
1572
|
+
byAgent[task.assignedAgent].totalDuration += duration;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
// Duration stats
|
|
1577
|
+
if (task.startedAt && task.completedAt) {
|
|
1578
|
+
const startTime = task.startedAt instanceof Date
|
|
1579
|
+
? task.startedAt.getTime()
|
|
1580
|
+
: new Date(task.startedAt).getTime();
|
|
1581
|
+
const endTime = task.completedAt instanceof Date
|
|
1582
|
+
? task.completedAt.getTime()
|
|
1583
|
+
: new Date(task.completedAt).getTime();
|
|
1584
|
+
const duration = endTime - startTime;
|
|
1585
|
+
if (duration > 0) {
|
|
1586
|
+
totalDuration += duration;
|
|
1587
|
+
durationCount++;
|
|
1588
|
+
minDuration = Math.min(minDuration, duration);
|
|
1589
|
+
maxDuration = Math.max(maxDuration, duration);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
// Daily stats (last 30 days)
|
|
1593
|
+
const createdTime = task.createdAt instanceof Date
|
|
1594
|
+
? task.createdAt.getTime()
|
|
1595
|
+
: new Date(task.createdAt).getTime();
|
|
1596
|
+
if (createdTime >= thirtyDaysAgo) {
|
|
1597
|
+
const dateStr = new Date(createdTime).toISOString().split("T")[0];
|
|
1598
|
+
if (!daily[dateStr])
|
|
1599
|
+
daily[dateStr] = { created: 0, completed: 0, failed: 0 };
|
|
1600
|
+
daily[dateStr].created++;
|
|
1601
|
+
}
|
|
1602
|
+
if (task.completedAt) {
|
|
1603
|
+
const completedTime = task.completedAt instanceof Date
|
|
1604
|
+
? task.completedAt.getTime()
|
|
1605
|
+
: new Date(task.completedAt).getTime();
|
|
1606
|
+
if (completedTime >= thirtyDaysAgo) {
|
|
1607
|
+
const dateStr = new Date(completedTime).toISOString().split("T")[0];
|
|
1608
|
+
if (!daily[dateStr])
|
|
1609
|
+
daily[dateStr] = { created: 0, completed: 0, failed: 0 };
|
|
1610
|
+
if (task.status === "completed") {
|
|
1611
|
+
daily[dateStr].completed++;
|
|
1612
|
+
if (completedTime >= oneDayAgo)
|
|
1613
|
+
recentCompletions++;
|
|
1614
|
+
}
|
|
1615
|
+
else if (task.status === "failed") {
|
|
1616
|
+
daily[dateStr].failed++;
|
|
1617
|
+
if (completedTime >= oneDayAgo)
|
|
1618
|
+
recentFailures++;
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
const totalTasks = allTasks.length;
|
|
1624
|
+
const completedTasks = byStatus["completed"] || 0;
|
|
1625
|
+
const failedTasks = byStatus["failed"] || 0;
|
|
1626
|
+
const pendingTasks = (byStatus["pending"] || 0) + (byStatus["queued"] || 0);
|
|
1627
|
+
const inProgressTasks = (byStatus["in_progress"] || 0) + (byStatus["assigned"] || 0);
|
|
1628
|
+
const cancelledTasks = byStatus["cancelled"] || 0;
|
|
1629
|
+
const successRate = totalTasks > 0
|
|
1630
|
+
? (completedTasks / (completedTasks + failedTasks)) * 100
|
|
1631
|
+
: 0;
|
|
1632
|
+
// Convert byAgent to expected format
|
|
1633
|
+
const byAgentFormatted = {};
|
|
1634
|
+
for (const [agent, stats] of Object.entries(byAgent)) {
|
|
1635
|
+
const total = stats.completed + stats.failed;
|
|
1636
|
+
byAgentFormatted[agent] = {
|
|
1637
|
+
count: stats.count,
|
|
1638
|
+
successRate: total > 0 ? (stats.completed / total) * 100 : 0,
|
|
1639
|
+
avgDurationMs: stats.completed > 0 ? stats.totalDuration / stats.completed : 0,
|
|
1640
|
+
};
|
|
1641
|
+
}
|
|
1642
|
+
// Convert daily to array
|
|
1643
|
+
const dailyArray = Object.entries(daily)
|
|
1644
|
+
.map(([date, data]) => ({ date, ...data }))
|
|
1645
|
+
.sort((a, b) => a.date.localeCompare(b.date));
|
|
1646
|
+
return {
|
|
1647
|
+
totalTasks,
|
|
1648
|
+
completedTasks,
|
|
1649
|
+
failedTasks,
|
|
1650
|
+
pendingTasks,
|
|
1651
|
+
inProgressTasks,
|
|
1652
|
+
cancelledTasks,
|
|
1653
|
+
successRate: Number.isNaN(successRate)
|
|
1654
|
+
? 0
|
|
1655
|
+
: Math.round(successRate * 100) / 100,
|
|
1656
|
+
avgDurationMs: durationCount > 0 ? Math.round(totalDuration / durationCount) : 0,
|
|
1657
|
+
minDurationMs: minDuration === Infinity ? 0 : minDuration,
|
|
1658
|
+
maxDurationMs: maxDuration,
|
|
1659
|
+
byStatus,
|
|
1660
|
+
byPriority,
|
|
1661
|
+
bySource,
|
|
1662
|
+
byAgent: byAgentFormatted,
|
|
1663
|
+
daily: dailyArray,
|
|
1664
|
+
recentCompletions,
|
|
1665
|
+
recentFailures,
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
// === Advanced Task Filtering ===
|
|
1669
|
+
async getTasksFiltered(options) {
|
|
1670
|
+
const conditions = [];
|
|
1671
|
+
// Status filter (supports array)
|
|
1672
|
+
if (options.status) {
|
|
1673
|
+
if (Array.isArray(options.status)) {
|
|
1674
|
+
conditions.push(sql `${schema.tasks.status} IN (${sql.join(options.status.map((s) => sql `${s}`), sql `, `)})`);
|
|
1675
|
+
}
|
|
1676
|
+
else {
|
|
1677
|
+
conditions.push(eq(schema.tasks.status, options.status));
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
// Priority filter (supports array)
|
|
1681
|
+
if (options.priority !== undefined) {
|
|
1682
|
+
if (Array.isArray(options.priority)) {
|
|
1683
|
+
conditions.push(sql `${schema.tasks.priority} IN (${sql.join(options.priority.map((p) => sql `${p}`), sql `, `)})`);
|
|
1684
|
+
}
|
|
1685
|
+
else {
|
|
1686
|
+
conditions.push(eq(schema.tasks.priority, options.priority));
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
// Source filter (supports array)
|
|
1690
|
+
if (options.source) {
|
|
1691
|
+
if (Array.isArray(options.source)) {
|
|
1692
|
+
conditions.push(sql `${schema.tasks.source} IN (${sql.join(options.source.map((s) => sql `${s}`), sql `, `)})`);
|
|
1693
|
+
}
|
|
1694
|
+
else {
|
|
1695
|
+
conditions.push(eq(schema.tasks.source, options.source));
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
// Agent filter
|
|
1699
|
+
if (options.agent) {
|
|
1700
|
+
conditions.push(eq(schema.tasks.assignedAgent, options.agent));
|
|
1701
|
+
}
|
|
1702
|
+
// Repository filter
|
|
1703
|
+
if (options.repository) {
|
|
1704
|
+
conditions.push(eq(schema.tasks.repository, options.repository));
|
|
1705
|
+
}
|
|
1706
|
+
// Date range filters
|
|
1707
|
+
if (options.createdAfter) {
|
|
1708
|
+
conditions.push(gte(schema.tasks.createdAt, options.createdAfter));
|
|
1709
|
+
}
|
|
1710
|
+
if (options.createdBefore) {
|
|
1711
|
+
conditions.push(lte(schema.tasks.createdAt, options.createdBefore));
|
|
1712
|
+
}
|
|
1713
|
+
if (options.completedAfter) {
|
|
1714
|
+
conditions.push(gte(schema.tasks.completedAt, options.completedAfter));
|
|
1715
|
+
}
|
|
1716
|
+
if (options.completedBefore) {
|
|
1717
|
+
conditions.push(lte(schema.tasks.completedAt, options.completedBefore));
|
|
1718
|
+
}
|
|
1719
|
+
// Labels filter (JSON array contains)
|
|
1720
|
+
if (options.labels && options.labels.length > 0) {
|
|
1721
|
+
for (const label of options.labels) {
|
|
1722
|
+
conditions.push(sql `${schema.tasks.labels} LIKE ${`%"${label}"%`}`);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
// Text search
|
|
1726
|
+
if (options.searchQuery) {
|
|
1727
|
+
const searchPattern = `%${options.searchQuery}%`;
|
|
1728
|
+
conditions.push(sql `(${schema.tasks.title} LIKE ${searchPattern} OR ${schema.tasks.description} LIKE ${searchPattern} OR ${schema.tasks.prompt} LIKE ${searchPattern})`);
|
|
1729
|
+
}
|
|
1730
|
+
// Cursor-based pagination (Phase 17)
|
|
1731
|
+
// When cursor is provided, filter for items "after" the cursor
|
|
1732
|
+
if (options.cursorCreatedAt && options.cursorId) {
|
|
1733
|
+
const cursorTime = options.cursorCreatedAt;
|
|
1734
|
+
const cursorId = options.cursorId;
|
|
1735
|
+
const isDesc = options.sortOrder !== "asc";
|
|
1736
|
+
if (isDesc) {
|
|
1737
|
+
conditions.push(or(sql `${schema.tasks.createdAt} < ${cursorTime}`, and(sql `${schema.tasks.createdAt} = ${cursorTime}`, sql `${schema.tasks.id} < ${cursorId}`)));
|
|
1738
|
+
}
|
|
1739
|
+
else {
|
|
1740
|
+
conditions.push(or(sql `${schema.tasks.createdAt} > ${cursorTime}`, and(sql `${schema.tasks.createdAt} = ${cursorTime}`, sql `${schema.tasks.id} > ${cursorId}`)));
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
const whereClause = conditions.length > 0 ? and(...conditions) : undefined;
|
|
1744
|
+
let orderByColumn = schema.tasks.createdAt;
|
|
1745
|
+
if (options.sortBy === "updatedAt")
|
|
1746
|
+
orderByColumn = schema.tasks.updatedAt;
|
|
1747
|
+
else if (options.sortBy === "priority")
|
|
1748
|
+
orderByColumn = schema.tasks.priority;
|
|
1749
|
+
else if (options.sortBy === "completedAt")
|
|
1750
|
+
orderByColumn = schema.tasks.completedAt;
|
|
1751
|
+
const orderFn = options.sortOrder === "asc" ? asc : desc;
|
|
1752
|
+
const useCursor = !!(options.cursorCreatedAt && options.cursorId);
|
|
1753
|
+
// When using cursor, don't use offset (cursor already filters)
|
|
1754
|
+
const tasks = useCursor
|
|
1755
|
+
? await this.db
|
|
1756
|
+
.select()
|
|
1757
|
+
.from(schema.tasks)
|
|
1758
|
+
.where(whereClause)
|
|
1759
|
+
.limit(options.limit || 50)
|
|
1760
|
+
.orderBy(orderFn(orderByColumn))
|
|
1761
|
+
: await this.db
|
|
1762
|
+
.select()
|
|
1763
|
+
.from(schema.tasks)
|
|
1764
|
+
.where(whereClause)
|
|
1765
|
+
.limit(options.limit || 50)
|
|
1766
|
+
.offset(options.offset || 0)
|
|
1767
|
+
.orderBy(orderFn(orderByColumn));
|
|
1768
|
+
const totalRes = await this.db
|
|
1769
|
+
.select({ value: count() })
|
|
1770
|
+
.from(schema.tasks)
|
|
1771
|
+
.where(whereClause);
|
|
1772
|
+
return {
|
|
1773
|
+
tasks: tasks,
|
|
1774
|
+
total: Number(totalRes[0]?.value ?? 0),
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
// === Task Archival ===
|
|
1778
|
+
async archiveOldTasks(olderThanDays) {
|
|
1779
|
+
const cutoffDate = new Date();
|
|
1780
|
+
cutoffDate.setDate(cutoffDate.getDate() - olderThanDays);
|
|
1781
|
+
// Find tasks to archive (completed or failed, older than cutoff)
|
|
1782
|
+
const tasksToArchive = await this.db
|
|
1783
|
+
.select()
|
|
1784
|
+
.from(schema.tasks)
|
|
1785
|
+
.where(and(sql `${schema.tasks.status} IN ('completed', 'failed', 'cancelled')`, lte(schema.tasks.completedAt, cutoffDate)));
|
|
1786
|
+
let archived = 0;
|
|
1787
|
+
for (const task of tasksToArchive) {
|
|
1788
|
+
// Calculate duration
|
|
1789
|
+
let durationMs = null;
|
|
1790
|
+
if (task.startedAt && task.completedAt) {
|
|
1791
|
+
const startTime = task.startedAt instanceof Date
|
|
1792
|
+
? task.startedAt.getTime()
|
|
1793
|
+
: new Date(String(task.startedAt)).getTime();
|
|
1794
|
+
const endTime = task.completedAt instanceof Date
|
|
1795
|
+
? task.completedAt.getTime()
|
|
1796
|
+
: new Date(String(task.completedAt)).getTime();
|
|
1797
|
+
durationMs = endTime - startTime;
|
|
1798
|
+
}
|
|
1799
|
+
// Insert into archive
|
|
1800
|
+
await this.db.insert(schema.taskArchives).values({
|
|
1801
|
+
id: randomUUID(),
|
|
1802
|
+
originalId: task.id,
|
|
1803
|
+
title: task.title,
|
|
1804
|
+
description: task.description,
|
|
1805
|
+
prompt: task.prompt,
|
|
1806
|
+
status: task.status,
|
|
1807
|
+
priority: task.priority,
|
|
1808
|
+
source: task.source,
|
|
1809
|
+
sourceId: task.sourceId,
|
|
1810
|
+
sourceUrl: task.sourceUrl,
|
|
1811
|
+
repository: task.repository,
|
|
1812
|
+
branch: task.branch,
|
|
1813
|
+
labels: task.labels,
|
|
1814
|
+
assignedAgent: task.assignedAgent,
|
|
1815
|
+
assignedAgentId: task.assignedAgentId,
|
|
1816
|
+
createdAt: task.createdAt,
|
|
1817
|
+
startedAt: task.startedAt,
|
|
1818
|
+
completedAt: task.completedAt,
|
|
1819
|
+
archivedAt: new Date(),
|
|
1820
|
+
result: task.result,
|
|
1821
|
+
metadata: task.metadata,
|
|
1822
|
+
durationMs,
|
|
1823
|
+
});
|
|
1824
|
+
// Delete from tasks table
|
|
1825
|
+
await this.db.delete(schema.tasks).where(eq(schema.tasks.id, task.id));
|
|
1826
|
+
archived++;
|
|
1827
|
+
}
|
|
1828
|
+
return { archived };
|
|
1829
|
+
}
|
|
1830
|
+
async getArchivedTasks(options) {
|
|
1831
|
+
const archived = await this.db
|
|
1832
|
+
.select()
|
|
1833
|
+
.from(schema.taskArchives)
|
|
1834
|
+
.limit(options.limit || 50)
|
|
1835
|
+
.offset(options.offset || 0)
|
|
1836
|
+
.orderBy(desc(schema.taskArchives.archivedAt));
|
|
1837
|
+
const totalRes = await this.db
|
|
1838
|
+
.select({ value: count() })
|
|
1839
|
+
.from(schema.taskArchives);
|
|
1840
|
+
const tasks = archived.map((a) => ({
|
|
1841
|
+
id: a.originalId,
|
|
1842
|
+
title: a.title,
|
|
1843
|
+
description: a.description,
|
|
1844
|
+
prompt: a.prompt,
|
|
1845
|
+
status: a.status,
|
|
1846
|
+
priority: a.priority,
|
|
1847
|
+
source: a.source,
|
|
1848
|
+
sourceId: a.sourceId,
|
|
1849
|
+
sourceUrl: a.sourceUrl,
|
|
1850
|
+
repository: a.repository,
|
|
1851
|
+
branch: a.branch,
|
|
1852
|
+
labels: a.labels || [],
|
|
1853
|
+
assignedAgent: a.assignedAgent,
|
|
1854
|
+
assignedAgentId: a.assignedAgentId,
|
|
1855
|
+
createdAt: a.createdAt,
|
|
1856
|
+
updatedAt: a.createdAt,
|
|
1857
|
+
startedAt: a.startedAt,
|
|
1858
|
+
completedAt: a.completedAt,
|
|
1859
|
+
result: a.result,
|
|
1860
|
+
metadata: a.metadata || {},
|
|
1861
|
+
attempts: 0,
|
|
1862
|
+
maxAttempts: 3,
|
|
1863
|
+
_archived: true,
|
|
1864
|
+
_archivedAt: a.archivedAt,
|
|
1865
|
+
_durationMs: a.durationMs,
|
|
1866
|
+
}));
|
|
1867
|
+
return {
|
|
1868
|
+
tasks: tasks,
|
|
1869
|
+
total: totalRes[0].value,
|
|
1870
|
+
};
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
//# sourceMappingURL=libsql.js.map
|