cowork-os 0.3.21
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/LICENSE +21 -0
- package/README.md +1638 -0
- package/bin/cowork.js +42 -0
- package/build/entitlements.mac.plist +16 -0
- package/build/icon.icns +0 -0
- package/build/icon.png +0 -0
- package/dist/electron/electron/activity/ActivityRepository.js +190 -0
- package/dist/electron/electron/agent/browser/browser-service.js +639 -0
- package/dist/electron/electron/agent/context-manager.js +225 -0
- package/dist/electron/electron/agent/custom-skill-loader.js +566 -0
- package/dist/electron/electron/agent/daemon.js +975 -0
- package/dist/electron/electron/agent/executor.js +3561 -0
- package/dist/electron/electron/agent/llm/anthropic-provider.js +155 -0
- package/dist/electron/electron/agent/llm/bedrock-provider.js +202 -0
- package/dist/electron/electron/agent/llm/gemini-provider.js +375 -0
- package/dist/electron/electron/agent/llm/index.js +34 -0
- package/dist/electron/electron/agent/llm/ollama-provider.js +263 -0
- package/dist/electron/electron/agent/llm/openai-oauth.js +101 -0
- package/dist/electron/electron/agent/llm/openai-provider.js +657 -0
- package/dist/electron/electron/agent/llm/openrouter-provider.js +232 -0
- package/dist/electron/electron/agent/llm/pricing.js +160 -0
- package/dist/electron/electron/agent/llm/provider-factory.js +880 -0
- package/dist/electron/electron/agent/llm/types.js +178 -0
- package/dist/electron/electron/agent/queue-manager.js +378 -0
- package/dist/electron/electron/agent/sandbox/docker-sandbox.js +402 -0
- package/dist/electron/electron/agent/sandbox/macos-sandbox.js +407 -0
- package/dist/electron/electron/agent/sandbox/runner.js +410 -0
- package/dist/electron/electron/agent/sandbox/sandbox-factory.js +228 -0
- package/dist/electron/electron/agent/sandbox/security-utils.js +258 -0
- package/dist/electron/electron/agent/search/brave-provider.js +119 -0
- package/dist/electron/electron/agent/search/google-provider.js +100 -0
- package/dist/electron/electron/agent/search/index.js +28 -0
- package/dist/electron/electron/agent/search/provider-factory.js +395 -0
- package/dist/electron/electron/agent/search/serpapi-provider.js +112 -0
- package/dist/electron/electron/agent/search/tavily-provider.js +90 -0
- package/dist/electron/electron/agent/search/types.js +40 -0
- package/dist/electron/electron/agent/security/index.js +12 -0
- package/dist/electron/electron/agent/security/input-sanitizer.js +303 -0
- package/dist/electron/electron/agent/security/output-filter.js +217 -0
- package/dist/electron/electron/agent/skill-eligibility.js +281 -0
- package/dist/electron/electron/agent/skill-registry.js +396 -0
- package/dist/electron/electron/agent/skills/document.js +878 -0
- package/dist/electron/electron/agent/skills/image-generator.js +225 -0
- package/dist/electron/electron/agent/skills/organizer.js +141 -0
- package/dist/electron/electron/agent/skills/presentation.js +367 -0
- package/dist/electron/electron/agent/skills/spreadsheet.js +165 -0
- package/dist/electron/electron/agent/tools/browser-tools.js +523 -0
- package/dist/electron/electron/agent/tools/builtin-settings.js +384 -0
- package/dist/electron/electron/agent/tools/canvas-tools.js +530 -0
- package/dist/electron/electron/agent/tools/cron-tools.js +577 -0
- package/dist/electron/electron/agent/tools/edit-tools.js +194 -0
- package/dist/electron/electron/agent/tools/file-tools.js +719 -0
- package/dist/electron/electron/agent/tools/glob-tools.js +283 -0
- package/dist/electron/electron/agent/tools/grep-tools.js +387 -0
- package/dist/electron/electron/agent/tools/image-tools.js +111 -0
- package/dist/electron/electron/agent/tools/mention-tools.js +282 -0
- package/dist/electron/electron/agent/tools/node-tools.js +476 -0
- package/dist/electron/electron/agent/tools/registry.js +2719 -0
- package/dist/electron/electron/agent/tools/search-tools.js +91 -0
- package/dist/electron/electron/agent/tools/shell-tools.js +574 -0
- package/dist/electron/electron/agent/tools/skill-tools.js +274 -0
- package/dist/electron/electron/agent/tools/system-tools.js +578 -0
- package/dist/electron/electron/agent/tools/web-fetch-tools.js +444 -0
- package/dist/electron/electron/agent/tools/x-tools.js +264 -0
- package/dist/electron/electron/agents/AgentRoleRepository.js +420 -0
- package/dist/electron/electron/agents/HeartbeatService.js +356 -0
- package/dist/electron/electron/agents/MentionRepository.js +197 -0
- package/dist/electron/electron/agents/TaskSubscriptionRepository.js +168 -0
- package/dist/electron/electron/agents/WorkingStateRepository.js +229 -0
- package/dist/electron/electron/canvas/canvas-manager.js +714 -0
- package/dist/electron/electron/canvas/canvas-preload.js +53 -0
- package/dist/electron/electron/canvas/canvas-protocol.js +195 -0
- package/dist/electron/electron/canvas/canvas-store.js +174 -0
- package/dist/electron/electron/canvas/index.js +13 -0
- package/dist/electron/electron/control-plane/client.js +364 -0
- package/dist/electron/electron/control-plane/handlers.js +572 -0
- package/dist/electron/electron/control-plane/index.js +41 -0
- package/dist/electron/electron/control-plane/node-manager.js +264 -0
- package/dist/electron/electron/control-plane/protocol.js +194 -0
- package/dist/electron/electron/control-plane/remote-client.js +437 -0
- package/dist/electron/electron/control-plane/server.js +640 -0
- package/dist/electron/electron/control-plane/settings.js +369 -0
- package/dist/electron/electron/control-plane/ssh-tunnel.js +549 -0
- package/dist/electron/electron/cron/index.js +30 -0
- package/dist/electron/electron/cron/schedule.js +190 -0
- package/dist/electron/electron/cron/service.js +614 -0
- package/dist/electron/electron/cron/store.js +155 -0
- package/dist/electron/electron/cron/types.js +82 -0
- package/dist/electron/electron/cron/webhook.js +258 -0
- package/dist/electron/electron/database/SecureSettingsRepository.js +444 -0
- package/dist/electron/electron/database/TaskLabelRepository.js +120 -0
- package/dist/electron/electron/database/repositories.js +1781 -0
- package/dist/electron/electron/database/schema.js +978 -0
- package/dist/electron/electron/extensions/index.js +33 -0
- package/dist/electron/electron/extensions/loader.js +313 -0
- package/dist/electron/electron/extensions/registry.js +485 -0
- package/dist/electron/electron/extensions/types.js +11 -0
- package/dist/electron/electron/gateway/channel-registry.js +1102 -0
- package/dist/electron/electron/gateway/channels/bluebubbles-client.js +479 -0
- package/dist/electron/electron/gateway/channels/bluebubbles.js +432 -0
- package/dist/electron/electron/gateway/channels/discord.js +975 -0
- package/dist/electron/electron/gateway/channels/email-client.js +593 -0
- package/dist/electron/electron/gateway/channels/email.js +443 -0
- package/dist/electron/electron/gateway/channels/google-chat.js +631 -0
- package/dist/electron/electron/gateway/channels/imessage-client.js +363 -0
- package/dist/electron/electron/gateway/channels/imessage.js +465 -0
- package/dist/electron/electron/gateway/channels/index.js +36 -0
- package/dist/electron/electron/gateway/channels/line-client.js +470 -0
- package/dist/electron/electron/gateway/channels/line.js +479 -0
- package/dist/electron/electron/gateway/channels/matrix-client.js +432 -0
- package/dist/electron/electron/gateway/channels/matrix.js +592 -0
- package/dist/electron/electron/gateway/channels/mattermost-client.js +394 -0
- package/dist/electron/electron/gateway/channels/mattermost.js +496 -0
- package/dist/electron/electron/gateway/channels/signal-client.js +500 -0
- package/dist/electron/electron/gateway/channels/signal.js +582 -0
- package/dist/electron/electron/gateway/channels/slack.js +415 -0
- package/dist/electron/electron/gateway/channels/teams.js +596 -0
- package/dist/electron/electron/gateway/channels/telegram.js +1390 -0
- package/dist/electron/electron/gateway/channels/twitch-client.js +502 -0
- package/dist/electron/electron/gateway/channels/twitch.js +396 -0
- package/dist/electron/electron/gateway/channels/types.js +8 -0
- package/dist/electron/electron/gateway/channels/whatsapp.js +953 -0
- package/dist/electron/electron/gateway/context-policy.js +268 -0
- package/dist/electron/electron/gateway/index.js +1063 -0
- package/dist/electron/electron/gateway/infrastructure.js +496 -0
- package/dist/electron/electron/gateway/router.js +2700 -0
- package/dist/electron/electron/gateway/security.js +375 -0
- package/dist/electron/electron/gateway/session.js +115 -0
- package/dist/electron/electron/gateway/tunnel.js +503 -0
- package/dist/electron/electron/guardrails/guardrail-manager.js +348 -0
- package/dist/electron/electron/hooks/gmail-watcher.js +300 -0
- package/dist/electron/electron/hooks/index.js +46 -0
- package/dist/electron/electron/hooks/mappings.js +381 -0
- package/dist/electron/electron/hooks/server.js +480 -0
- package/dist/electron/electron/hooks/settings.js +447 -0
- package/dist/electron/electron/hooks/types.js +41 -0
- package/dist/electron/electron/ipc/canvas-handlers.js +158 -0
- package/dist/electron/electron/ipc/handlers.js +3138 -0
- package/dist/electron/electron/ipc/mission-control-handlers.js +141 -0
- package/dist/electron/electron/main.js +448 -0
- package/dist/electron/electron/mcp/client/MCPClientManager.js +330 -0
- package/dist/electron/electron/mcp/client/MCPServerConnection.js +437 -0
- package/dist/electron/electron/mcp/client/transports/SSETransport.js +304 -0
- package/dist/electron/electron/mcp/client/transports/StdioTransport.js +307 -0
- package/dist/electron/electron/mcp/client/transports/WebSocketTransport.js +329 -0
- package/dist/electron/electron/mcp/host/MCPHostServer.js +354 -0
- package/dist/electron/electron/mcp/host/ToolAdapter.js +100 -0
- package/dist/electron/electron/mcp/registry/MCPRegistryManager.js +497 -0
- package/dist/electron/electron/mcp/settings.js +446 -0
- package/dist/electron/electron/mcp/types.js +59 -0
- package/dist/electron/electron/memory/MemoryService.js +435 -0
- package/dist/electron/electron/notifications/index.js +17 -0
- package/dist/electron/electron/notifications/service.js +118 -0
- package/dist/electron/electron/notifications/store.js +144 -0
- package/dist/electron/electron/preload.js +842 -0
- package/dist/electron/electron/reports/StandupReportService.js +272 -0
- package/dist/electron/electron/security/concurrency.js +293 -0
- package/dist/electron/electron/security/index.js +15 -0
- package/dist/electron/electron/security/policy-manager.js +435 -0
- package/dist/electron/electron/settings/appearance-manager.js +193 -0
- package/dist/electron/electron/settings/personality-manager.js +724 -0
- package/dist/electron/electron/settings/x-manager.js +58 -0
- package/dist/electron/electron/tailscale/exposure.js +188 -0
- package/dist/electron/electron/tailscale/index.js +28 -0
- package/dist/electron/electron/tailscale/settings.js +205 -0
- package/dist/electron/electron/tailscale/tailscale.js +355 -0
- package/dist/electron/electron/tray/QuickInputWindow.js +568 -0
- package/dist/electron/electron/tray/TrayManager.js +895 -0
- package/dist/electron/electron/tray/index.js +9 -0
- package/dist/electron/electron/updater/index.js +6 -0
- package/dist/electron/electron/updater/update-manager.js +418 -0
- package/dist/electron/electron/utils/env-migration.js +209 -0
- package/dist/electron/electron/utils/process.js +102 -0
- package/dist/electron/electron/utils/rate-limiter.js +104 -0
- package/dist/electron/electron/utils/validation.js +419 -0
- package/dist/electron/electron/utils/x-cli.js +177 -0
- package/dist/electron/electron/voice/VoiceService.js +507 -0
- package/dist/electron/electron/voice/index.js +14 -0
- package/dist/electron/electron/voice/voice-settings-manager.js +359 -0
- package/dist/electron/shared/channelMessages.js +170 -0
- package/dist/electron/shared/types.js +1185 -0
- package/package.json +159 -0
- package/resources/skills/1password.json +10 -0
- package/resources/skills/add-documentation.json +31 -0
- package/resources/skills/analyze-csv.json +17 -0
- package/resources/skills/apple-notes.json +10 -0
- package/resources/skills/apple-reminders.json +10 -0
- package/resources/skills/auto-commenter.json +10 -0
- package/resources/skills/bear-notes.json +10 -0
- package/resources/skills/bird.json +35 -0
- package/resources/skills/blogwatcher.json +10 -0
- package/resources/skills/blucli.json +10 -0
- package/resources/skills/bluebubbles.json +10 -0
- package/resources/skills/camsnap.json +10 -0
- package/resources/skills/clean-imports.json +18 -0
- package/resources/skills/code-review.json +18 -0
- package/resources/skills/coding-agent.json +10 -0
- package/resources/skills/compare-files.json +23 -0
- package/resources/skills/convert-code.json +34 -0
- package/resources/skills/create-changelog.json +24 -0
- package/resources/skills/debug-error.json +17 -0
- package/resources/skills/dependency-check.json +10 -0
- package/resources/skills/discord.json +10 -0
- package/resources/skills/eightctl.json +10 -0
- package/resources/skills/explain-code.json +29 -0
- package/resources/skills/extract-todos.json +18 -0
- package/resources/skills/food-order.json +10 -0
- package/resources/skills/gemini.json +10 -0
- package/resources/skills/generate-readme.json +10 -0
- package/resources/skills/gifgrep.json +10 -0
- package/resources/skills/git-commit.json +10 -0
- package/resources/skills/github.json +10 -0
- package/resources/skills/gog.json +10 -0
- package/resources/skills/goplaces.json +10 -0
- package/resources/skills/himalaya.json +10 -0
- package/resources/skills/imsg.json +10 -0
- package/resources/skills/karpathy-guidelines.json +12 -0
- package/resources/skills/last30days.json +26 -0
- package/resources/skills/local-places.json +10 -0
- package/resources/skills/mcporter.json +10 -0
- package/resources/skills/model-usage.json +10 -0
- package/resources/skills/nano-banana-pro.json +10 -0
- package/resources/skills/nano-pdf.json +10 -0
- package/resources/skills/notion.json +10 -0
- package/resources/skills/obsidian.json +10 -0
- package/resources/skills/openai-image-gen.json +10 -0
- package/resources/skills/openai-whisper-api.json +10 -0
- package/resources/skills/openai-whisper.json +10 -0
- package/resources/skills/openhue.json +10 -0
- package/resources/skills/oracle.json +10 -0
- package/resources/skills/ordercli.json +10 -0
- package/resources/skills/peekaboo.json +10 -0
- package/resources/skills/project-structure.json +10 -0
- package/resources/skills/proofread.json +17 -0
- package/resources/skills/refactor-code.json +31 -0
- package/resources/skills/rename-symbol.json +23 -0
- package/resources/skills/sag.json +10 -0
- package/resources/skills/security-audit.json +18 -0
- package/resources/skills/session-logs.json +10 -0
- package/resources/skills/sherpa-onnx-tts.json +10 -0
- package/resources/skills/skill-creator.json +15 -0
- package/resources/skills/skill-hub.json +29 -0
- package/resources/skills/slack.json +10 -0
- package/resources/skills/songsee.json +10 -0
- package/resources/skills/sonoscli.json +10 -0
- package/resources/skills/spotify-player.json +10 -0
- package/resources/skills/startup-cfo.json +55 -0
- package/resources/skills/summarize-folder.json +18 -0
- package/resources/skills/summarize.json +10 -0
- package/resources/skills/things-mac.json +10 -0
- package/resources/skills/tmux.json +10 -0
- package/resources/skills/translate.json +36 -0
- package/resources/skills/trello.json +10 -0
- package/resources/skills/video-frames.json +10 -0
- package/resources/skills/voice-call.json +10 -0
- package/resources/skills/wacli.json +10 -0
- package/resources/skills/weather.json +10 -0
- package/resources/skills/write-tests.json +31 -0
- package/src/electron/activity/ActivityRepository.ts +238 -0
- package/src/electron/agent/browser/browser-service.ts +721 -0
- package/src/electron/agent/context-manager.ts +257 -0
- package/src/electron/agent/custom-skill-loader.ts +634 -0
- package/src/electron/agent/daemon.ts +1097 -0
- package/src/electron/agent/executor.ts +4017 -0
- package/src/electron/agent/llm/anthropic-provider.ts +175 -0
- package/src/electron/agent/llm/bedrock-provider.ts +236 -0
- package/src/electron/agent/llm/gemini-provider.ts +422 -0
- package/src/electron/agent/llm/index.ts +9 -0
- package/src/electron/agent/llm/ollama-provider.ts +347 -0
- package/src/electron/agent/llm/openai-oauth.ts +127 -0
- package/src/electron/agent/llm/openai-provider.ts +686 -0
- package/src/electron/agent/llm/openrouter-provider.ts +273 -0
- package/src/electron/agent/llm/pricing.ts +180 -0
- package/src/electron/agent/llm/provider-factory.ts +971 -0
- package/src/electron/agent/llm/types.ts +291 -0
- package/src/electron/agent/queue-manager.ts +408 -0
- package/src/electron/agent/sandbox/docker-sandbox.ts +453 -0
- package/src/electron/agent/sandbox/macos-sandbox.ts +426 -0
- package/src/electron/agent/sandbox/runner.ts +453 -0
- package/src/electron/agent/sandbox/sandbox-factory.ts +337 -0
- package/src/electron/agent/sandbox/security-utils.ts +251 -0
- package/src/electron/agent/search/brave-provider.ts +141 -0
- package/src/electron/agent/search/google-provider.ts +131 -0
- package/src/electron/agent/search/index.ts +6 -0
- package/src/electron/agent/search/provider-factory.ts +450 -0
- package/src/electron/agent/search/serpapi-provider.ts +138 -0
- package/src/electron/agent/search/tavily-provider.ts +108 -0
- package/src/electron/agent/search/types.ts +118 -0
- package/src/electron/agent/security/index.ts +20 -0
- package/src/electron/agent/security/input-sanitizer.ts +380 -0
- package/src/electron/agent/security/output-filter.ts +259 -0
- package/src/electron/agent/skill-eligibility.ts +334 -0
- package/src/electron/agent/skill-registry.ts +457 -0
- package/src/electron/agent/skills/document.ts +1070 -0
- package/src/electron/agent/skills/image-generator.ts +272 -0
- package/src/electron/agent/skills/organizer.ts +131 -0
- package/src/electron/agent/skills/presentation.ts +418 -0
- package/src/electron/agent/skills/spreadsheet.ts +166 -0
- package/src/electron/agent/tools/browser-tools.ts +546 -0
- package/src/electron/agent/tools/builtin-settings.ts +422 -0
- package/src/electron/agent/tools/canvas-tools.ts +572 -0
- package/src/electron/agent/tools/cron-tools.ts +723 -0
- package/src/electron/agent/tools/edit-tools.ts +196 -0
- package/src/electron/agent/tools/file-tools.ts +811 -0
- package/src/electron/agent/tools/glob-tools.ts +303 -0
- package/src/electron/agent/tools/grep-tools.ts +432 -0
- package/src/electron/agent/tools/image-tools.ts +126 -0
- package/src/electron/agent/tools/mention-tools.ts +371 -0
- package/src/electron/agent/tools/node-tools.ts +550 -0
- package/src/electron/agent/tools/registry.ts +3052 -0
- package/src/electron/agent/tools/search-tools.ts +111 -0
- package/src/electron/agent/tools/shell-tools.ts +651 -0
- package/src/electron/agent/tools/skill-tools.ts +340 -0
- package/src/electron/agent/tools/system-tools.ts +665 -0
- package/src/electron/agent/tools/web-fetch-tools.ts +528 -0
- package/src/electron/agent/tools/x-tools.ts +267 -0
- package/src/electron/agents/AgentRoleRepository.ts +557 -0
- package/src/electron/agents/HeartbeatService.ts +469 -0
- package/src/electron/agents/MentionRepository.ts +242 -0
- package/src/electron/agents/TaskSubscriptionRepository.ts +231 -0
- package/src/electron/agents/WorkingStateRepository.ts +278 -0
- package/src/electron/canvas/canvas-manager.ts +818 -0
- package/src/electron/canvas/canvas-preload.ts +102 -0
- package/src/electron/canvas/canvas-protocol.ts +174 -0
- package/src/electron/canvas/canvas-store.ts +200 -0
- package/src/electron/canvas/index.ts +8 -0
- package/src/electron/control-plane/client.ts +527 -0
- package/src/electron/control-plane/handlers.ts +723 -0
- package/src/electron/control-plane/index.ts +51 -0
- package/src/electron/control-plane/node-manager.ts +322 -0
- package/src/electron/control-plane/protocol.ts +269 -0
- package/src/electron/control-plane/remote-client.ts +517 -0
- package/src/electron/control-plane/server.ts +853 -0
- package/src/electron/control-plane/settings.ts +401 -0
- package/src/electron/control-plane/ssh-tunnel.ts +624 -0
- package/src/electron/cron/index.ts +9 -0
- package/src/electron/cron/schedule.ts +217 -0
- package/src/electron/cron/service.ts +743 -0
- package/src/electron/cron/store.ts +165 -0
- package/src/electron/cron/types.ts +291 -0
- package/src/electron/cron/webhook.ts +303 -0
- package/src/electron/database/SecureSettingsRepository.ts +514 -0
- package/src/electron/database/TaskLabelRepository.ts +148 -0
- package/src/electron/database/repositories.ts +2397 -0
- package/src/electron/database/schema.ts +1017 -0
- package/src/electron/extensions/index.ts +18 -0
- package/src/electron/extensions/loader.ts +336 -0
- package/src/electron/extensions/registry.ts +546 -0
- package/src/electron/extensions/types.ts +372 -0
- package/src/electron/gateway/channel-registry.ts +1267 -0
- package/src/electron/gateway/channels/bluebubbles-client.ts +641 -0
- package/src/electron/gateway/channels/bluebubbles.ts +509 -0
- package/src/electron/gateway/channels/discord.ts +1150 -0
- package/src/electron/gateway/channels/email-client.ts +708 -0
- package/src/electron/gateway/channels/email.ts +516 -0
- package/src/electron/gateway/channels/google-chat.ts +760 -0
- package/src/electron/gateway/channels/imessage-client.ts +473 -0
- package/src/electron/gateway/channels/imessage.ts +520 -0
- package/src/electron/gateway/channels/index.ts +21 -0
- package/src/electron/gateway/channels/line-client.ts +598 -0
- package/src/electron/gateway/channels/line.ts +559 -0
- package/src/electron/gateway/channels/matrix-client.ts +632 -0
- package/src/electron/gateway/channels/matrix.ts +655 -0
- package/src/electron/gateway/channels/mattermost-client.ts +526 -0
- package/src/electron/gateway/channels/mattermost.ts +550 -0
- package/src/electron/gateway/channels/signal-client.ts +722 -0
- package/src/electron/gateway/channels/signal.ts +666 -0
- package/src/electron/gateway/channels/slack.ts +458 -0
- package/src/electron/gateway/channels/teams.ts +681 -0
- package/src/electron/gateway/channels/telegram.ts +1727 -0
- package/src/electron/gateway/channels/twitch-client.ts +665 -0
- package/src/electron/gateway/channels/twitch.ts +468 -0
- package/src/electron/gateway/channels/types.ts +1002 -0
- package/src/electron/gateway/channels/whatsapp.ts +1101 -0
- package/src/electron/gateway/context-policy.ts +382 -0
- package/src/electron/gateway/index.ts +1274 -0
- package/src/electron/gateway/infrastructure.ts +645 -0
- package/src/electron/gateway/router.ts +3206 -0
- package/src/electron/gateway/security.ts +422 -0
- package/src/electron/gateway/session.ts +144 -0
- package/src/electron/gateway/tunnel.ts +626 -0
- package/src/electron/guardrails/guardrail-manager.ts +380 -0
- package/src/electron/hooks/gmail-watcher.ts +355 -0
- package/src/electron/hooks/index.ts +30 -0
- package/src/electron/hooks/mappings.ts +404 -0
- package/src/electron/hooks/server.ts +574 -0
- package/src/electron/hooks/settings.ts +466 -0
- package/src/electron/hooks/types.ts +245 -0
- package/src/electron/ipc/canvas-handlers.ts +223 -0
- package/src/electron/ipc/handlers.ts +3661 -0
- package/src/electron/ipc/mission-control-handlers.ts +182 -0
- package/src/electron/main.ts +496 -0
- package/src/electron/mcp/client/MCPClientManager.ts +406 -0
- package/src/electron/mcp/client/MCPServerConnection.ts +514 -0
- package/src/electron/mcp/client/transports/SSETransport.ts +360 -0
- package/src/electron/mcp/client/transports/StdioTransport.ts +355 -0
- package/src/electron/mcp/client/transports/WebSocketTransport.ts +384 -0
- package/src/electron/mcp/host/MCPHostServer.ts +388 -0
- package/src/electron/mcp/host/ToolAdapter.ts +140 -0
- package/src/electron/mcp/registry/MCPRegistryManager.ts +565 -0
- package/src/electron/mcp/settings.ts +468 -0
- package/src/electron/mcp/types.ts +371 -0
- package/src/electron/memory/MemoryService.ts +523 -0
- package/src/electron/notifications/index.ts +16 -0
- package/src/electron/notifications/service.ts +161 -0
- package/src/electron/notifications/store.ts +163 -0
- package/src/electron/preload.ts +2845 -0
- package/src/electron/reports/StandupReportService.ts +356 -0
- package/src/electron/security/concurrency.ts +333 -0
- package/src/electron/security/index.ts +17 -0
- package/src/electron/security/policy-manager.ts +539 -0
- package/src/electron/settings/appearance-manager.ts +182 -0
- package/src/electron/settings/personality-manager.ts +800 -0
- package/src/electron/settings/x-manager.ts +62 -0
- package/src/electron/tailscale/exposure.ts +262 -0
- package/src/electron/tailscale/index.ts +34 -0
- package/src/electron/tailscale/settings.ts +218 -0
- package/src/electron/tailscale/tailscale.ts +379 -0
- package/src/electron/tray/QuickInputWindow.ts +609 -0
- package/src/electron/tray/TrayManager.ts +1005 -0
- package/src/electron/tray/index.ts +6 -0
- package/src/electron/updater/index.ts +1 -0
- package/src/electron/updater/update-manager.ts +447 -0
- package/src/electron/utils/env-migration.ts +203 -0
- package/src/electron/utils/process.ts +124 -0
- package/src/electron/utils/rate-limiter.ts +130 -0
- package/src/electron/utils/validation.ts +493 -0
- package/src/electron/utils/x-cli.ts +198 -0
- package/src/electron/voice/VoiceService.ts +583 -0
- package/src/electron/voice/index.ts +9 -0
- package/src/electron/voice/voice-settings-manager.ts +403 -0
- package/src/renderer/App.tsx +775 -0
- package/src/renderer/components/ActivityFeed.tsx +407 -0
- package/src/renderer/components/ActivityFeedItem.tsx +285 -0
- package/src/renderer/components/AgentRoleCard.tsx +343 -0
- package/src/renderer/components/AgentRoleEditor.tsx +805 -0
- package/src/renderer/components/AgentSquadSettings.tsx +295 -0
- package/src/renderer/components/AgentWorkingStatePanel.tsx +411 -0
- package/src/renderer/components/AppearanceSettings.tsx +122 -0
- package/src/renderer/components/ApprovalDialog.tsx +100 -0
- package/src/renderer/components/BlueBubblesSettings.tsx +505 -0
- package/src/renderer/components/BuiltinToolsSettings.tsx +307 -0
- package/src/renderer/components/CanvasPreview.tsx +1189 -0
- package/src/renderer/components/CommandOutput.tsx +202 -0
- package/src/renderer/components/ContextPolicySettings.tsx +523 -0
- package/src/renderer/components/ControlPlaneSettings.tsx +1134 -0
- package/src/renderer/components/DisclaimerModal.tsx +124 -0
- package/src/renderer/components/DiscordSettings.tsx +436 -0
- package/src/renderer/components/EmailSettings.tsx +606 -0
- package/src/renderer/components/ExtensionsSettings.tsx +542 -0
- package/src/renderer/components/FileViewer.tsx +224 -0
- package/src/renderer/components/GoogleChatSettings.tsx +535 -0
- package/src/renderer/components/GuardrailSettings.tsx +487 -0
- package/src/renderer/components/HooksSettings.tsx +581 -0
- package/src/renderer/components/ImessageSettings.tsx +484 -0
- package/src/renderer/components/LineSettings.tsx +483 -0
- package/src/renderer/components/MCPRegistryBrowser.tsx +386 -0
- package/src/renderer/components/MCPSettings.tsx +943 -0
- package/src/renderer/components/MainContent.tsx +2433 -0
- package/src/renderer/components/MatrixSettings.tsx +510 -0
- package/src/renderer/components/MattermostSettings.tsx +473 -0
- package/src/renderer/components/MemorySettings.tsx +247 -0
- package/src/renderer/components/MentionBadge.tsx +87 -0
- package/src/renderer/components/MentionInput.tsx +409 -0
- package/src/renderer/components/MentionList.tsx +476 -0
- package/src/renderer/components/MissionControlPanel.tsx +1995 -0
- package/src/renderer/components/NodesSettings.tsx +316 -0
- package/src/renderer/components/NotificationPanel.tsx +481 -0
- package/src/renderer/components/Onboarding/AwakeningOrb.tsx +44 -0
- package/src/renderer/components/Onboarding/Onboarding.tsx +443 -0
- package/src/renderer/components/Onboarding/TypewriterText.tsx +102 -0
- package/src/renderer/components/Onboarding/index.ts +3 -0
- package/src/renderer/components/OnboardingModal.tsx +698 -0
- package/src/renderer/components/PairingCodeDisplay.tsx +324 -0
- package/src/renderer/components/PersonalitySettings.tsx +597 -0
- package/src/renderer/components/QueueSettings.tsx +119 -0
- package/src/renderer/components/QuickTaskFAB.tsx +71 -0
- package/src/renderer/components/RightPanel.tsx +413 -0
- package/src/renderer/components/ScheduledTasksSettings.tsx +1328 -0
- package/src/renderer/components/SearchSettings.tsx +328 -0
- package/src/renderer/components/Settings.tsx +1504 -0
- package/src/renderer/components/Sidebar.tsx +344 -0
- package/src/renderer/components/SignalSettings.tsx +673 -0
- package/src/renderer/components/SkillHubBrowser.tsx +458 -0
- package/src/renderer/components/SkillParameterModal.tsx +185 -0
- package/src/renderer/components/SkillsSettings.tsx +451 -0
- package/src/renderer/components/SlackSettings.tsx +442 -0
- package/src/renderer/components/StandupReportViewer.tsx +614 -0
- package/src/renderer/components/TaskBoard.tsx +498 -0
- package/src/renderer/components/TaskBoardCard.tsx +357 -0
- package/src/renderer/components/TaskBoardColumn.tsx +211 -0
- package/src/renderer/components/TaskLabelManager.tsx +472 -0
- package/src/renderer/components/TaskQueuePanel.tsx +144 -0
- package/src/renderer/components/TaskQuickActions.tsx +492 -0
- package/src/renderer/components/TaskTimeline.tsx +216 -0
- package/src/renderer/components/TaskView.tsx +162 -0
- package/src/renderer/components/TeamsSettings.tsx +518 -0
- package/src/renderer/components/TelegramSettings.tsx +421 -0
- package/src/renderer/components/Toast.tsx +76 -0
- package/src/renderer/components/TraySettings.tsx +189 -0
- package/src/renderer/components/TwitchSettings.tsx +511 -0
- package/src/renderer/components/UpdateSettings.tsx +295 -0
- package/src/renderer/components/VoiceIndicator.tsx +270 -0
- package/src/renderer/components/VoiceSettings.tsx +867 -0
- package/src/renderer/components/WhatsAppSettings.tsx +721 -0
- package/src/renderer/components/WorkingStateEditor.tsx +309 -0
- package/src/renderer/components/WorkingStateHistory.tsx +481 -0
- package/src/renderer/components/WorkspaceSelector.tsx +150 -0
- package/src/renderer/components/XSettings.tsx +311 -0
- package/src/renderer/global.d.ts +9 -0
- package/src/renderer/hooks/useAgentContext.ts +153 -0
- package/src/renderer/hooks/useOnboardingFlow.ts +548 -0
- package/src/renderer/hooks/useVoiceInput.ts +268 -0
- package/src/renderer/index.html +12 -0
- package/src/renderer/main.tsx +10 -0
- package/src/renderer/public/cowork-os-logo.png +0 -0
- package/src/renderer/quick-input.html +164 -0
- package/src/renderer/styles/index.css +14504 -0
- package/src/renderer/utils/agentMessages.ts +749 -0
- package/src/renderer/utils/voice-directives.ts +169 -0
- package/src/shared/channelMessages.ts +213 -0
- package/src/shared/types.ts +3608 -0
- package/tsconfig.electron.json +26 -0
- package/tsconfig.json +26 -0
- package/tsconfig.node.json +10 -0
- package/vite.config.ts +23 -0
|
@@ -0,0 +1,978 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DatabaseManager = void 0;
|
|
7
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const electron_1 = require("electron");
|
|
11
|
+
class DatabaseManager {
|
|
12
|
+
constructor() {
|
|
13
|
+
const userDataPath = electron_1.app.getPath('userData');
|
|
14
|
+
// Run migration from old cowork-oss directory before opening database
|
|
15
|
+
this.migrateFromLegacyDirectory(userDataPath);
|
|
16
|
+
const dbPath = path_1.default.join(userDataPath, 'cowork-os.db');
|
|
17
|
+
this.db = new better_sqlite3_1.default(dbPath);
|
|
18
|
+
this.initializeSchema();
|
|
19
|
+
// Store as singleton instance
|
|
20
|
+
DatabaseManager.instance = this;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get the singleton instance of DatabaseManager.
|
|
24
|
+
* Must be called after the instance has been created in main.ts.
|
|
25
|
+
*/
|
|
26
|
+
static getInstance() {
|
|
27
|
+
if (!DatabaseManager.instance) {
|
|
28
|
+
throw new Error('DatabaseManager has not been initialized. Call new DatabaseManager() first in main.ts.');
|
|
29
|
+
}
|
|
30
|
+
return DatabaseManager.instance;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Migrate data from the old cowork-oss directory to the new cowork-os directory.
|
|
34
|
+
* This ensures users don't lose their data when upgrading.
|
|
35
|
+
*/
|
|
36
|
+
migrateFromLegacyDirectory(newDataPath) {
|
|
37
|
+
// Normalize path - remove trailing slash if present
|
|
38
|
+
const normalizedNewPath = newDataPath.replace(/\/+$/, '');
|
|
39
|
+
// Determine the old directory path
|
|
40
|
+
// Handle both 'cowork-os' and 'cowork-os/' patterns
|
|
41
|
+
const oldDataPath = normalizedNewPath.replace(/cowork-os$/, 'cowork-oss');
|
|
42
|
+
// Verify the replacement actually happened (paths should be different)
|
|
43
|
+
if (oldDataPath === normalizedNewPath) {
|
|
44
|
+
console.log('[DatabaseManager] Cannot determine legacy path from:', newDataPath);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Check if old directory exists
|
|
48
|
+
if (!fs_1.default.existsSync(oldDataPath)) {
|
|
49
|
+
console.log('[DatabaseManager] No legacy directory found at:', oldDataPath);
|
|
50
|
+
return; // No legacy data to migrate
|
|
51
|
+
}
|
|
52
|
+
const newDbPath = path_1.default.join(normalizedNewPath, 'cowork-os.db');
|
|
53
|
+
const oldDbPath = path_1.default.join(oldDataPath, 'cowork-oss.db');
|
|
54
|
+
const migrationMarker = path_1.default.join(normalizedNewPath, '.migrated-from-cowork-oss');
|
|
55
|
+
// Check if migration already completed with current version
|
|
56
|
+
if (fs_1.default.existsSync(migrationMarker)) {
|
|
57
|
+
try {
|
|
58
|
+
const markerContent = fs_1.default.readFileSync(migrationMarker, 'utf-8');
|
|
59
|
+
const markerData = JSON.parse(markerContent);
|
|
60
|
+
if (markerData.version >= DatabaseManager.MIGRATION_VERSION) {
|
|
61
|
+
return; // Already migrated with current or newer version
|
|
62
|
+
}
|
|
63
|
+
console.log('[DatabaseManager] Re-running migration (version upgrade)...');
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Old format marker (just a date string) - re-run migration
|
|
67
|
+
console.log('[DatabaseManager] Re-running migration (old marker format)...');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
console.log('[DatabaseManager] Migrating data from cowork-oss to cowork-os...');
|
|
71
|
+
console.log('[DatabaseManager] Old path:', oldDataPath);
|
|
72
|
+
console.log('[DatabaseManager] New path:', normalizedNewPath);
|
|
73
|
+
let migrationSuccessful = true;
|
|
74
|
+
const migratedFiles = [];
|
|
75
|
+
const migratedDirs = [];
|
|
76
|
+
try {
|
|
77
|
+
// Ensure new directory exists
|
|
78
|
+
if (!fs_1.default.existsSync(normalizedNewPath)) {
|
|
79
|
+
fs_1.default.mkdirSync(normalizedNewPath, { recursive: true });
|
|
80
|
+
}
|
|
81
|
+
// 1. Migrate database if old exists and new doesn't (or new is smaller)
|
|
82
|
+
if (fs_1.default.existsSync(oldDbPath)) {
|
|
83
|
+
const oldDbSize = fs_1.default.statSync(oldDbPath).size;
|
|
84
|
+
const newDbExists = fs_1.default.existsSync(newDbPath);
|
|
85
|
+
const newDbSize = newDbExists ? fs_1.default.statSync(newDbPath).size : 0;
|
|
86
|
+
// Copy if new doesn't exist, or old is significantly larger (has more data)
|
|
87
|
+
if (!newDbExists || oldDbSize > newDbSize) {
|
|
88
|
+
console.log(`[DatabaseManager] Copying database (old: ${oldDbSize} bytes, new: ${newDbSize} bytes)...`);
|
|
89
|
+
fs_1.default.copyFileSync(oldDbPath, newDbPath);
|
|
90
|
+
migratedFiles.push('cowork-os.db');
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.log('[DatabaseManager] Database already exists and is larger, skipping...');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// 2. Migrate settings files - copy if old exists and (new doesn't exist OR old is larger)
|
|
97
|
+
const settingsFiles = [
|
|
98
|
+
'appearance-settings.json',
|
|
99
|
+
'builtin-tools-settings.json',
|
|
100
|
+
'claude-auth.enc',
|
|
101
|
+
'control-plane-settings.json',
|
|
102
|
+
'guardrail-settings.json',
|
|
103
|
+
'hooks-settings.json',
|
|
104
|
+
'llm-settings.json',
|
|
105
|
+
'mcp-settings.json',
|
|
106
|
+
'personality-settings.json',
|
|
107
|
+
'search-settings.json',
|
|
108
|
+
];
|
|
109
|
+
for (const file of settingsFiles) {
|
|
110
|
+
const oldFile = path_1.default.join(oldDataPath, file);
|
|
111
|
+
const newFile = path_1.default.join(normalizedNewPath, file);
|
|
112
|
+
if (fs_1.default.existsSync(oldFile)) {
|
|
113
|
+
const oldSize = fs_1.default.statSync(oldFile).size;
|
|
114
|
+
const newExists = fs_1.default.existsSync(newFile);
|
|
115
|
+
const newSize = newExists ? fs_1.default.statSync(newFile).size : 0;
|
|
116
|
+
// Copy if new doesn't exist, or old file is larger (has more data)
|
|
117
|
+
if (!newExists || oldSize > newSize) {
|
|
118
|
+
console.log(`[DatabaseManager] Migrating ${file} (old: ${oldSize} bytes, new: ${newSize} bytes)...`);
|
|
119
|
+
fs_1.default.copyFileSync(oldFile, newFile);
|
|
120
|
+
migratedFiles.push(file);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// 3. Migrate directories (skills, whatsapp-auth, cron, canvas, notifications)
|
|
125
|
+
const directories = ['skills', 'whatsapp-auth', 'cron', 'canvas', 'notifications'];
|
|
126
|
+
for (const dir of directories) {
|
|
127
|
+
const oldDir = path_1.default.join(oldDataPath, dir);
|
|
128
|
+
const newDir = path_1.default.join(normalizedNewPath, dir);
|
|
129
|
+
if (fs_1.default.existsSync(oldDir) && fs_1.default.statSync(oldDir).isDirectory()) {
|
|
130
|
+
const oldDirCount = this.countFilesRecursive(oldDir);
|
|
131
|
+
const newDirExists = fs_1.default.existsSync(newDir);
|
|
132
|
+
const newDirCount = newDirExists ? this.countFilesRecursive(newDir) : 0;
|
|
133
|
+
// Copy if new doesn't exist, is empty, or has significantly fewer files
|
|
134
|
+
if (!newDirExists || newDirCount === 0 || oldDirCount > newDirCount * 2) {
|
|
135
|
+
console.log(`[DatabaseManager] Migrating ${dir}/ (old: ${oldDirCount} files, new: ${newDirCount} files)...`);
|
|
136
|
+
this.copyDirectoryRecursive(oldDir, newDir);
|
|
137
|
+
migratedDirs.push(dir);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Create migration marker with version info
|
|
142
|
+
const markerData = {
|
|
143
|
+
version: DatabaseManager.MIGRATION_VERSION,
|
|
144
|
+
timestamp: new Date().toISOString(),
|
|
145
|
+
migratedFiles,
|
|
146
|
+
migratedDirs,
|
|
147
|
+
};
|
|
148
|
+
fs_1.default.writeFileSync(migrationMarker, JSON.stringify(markerData, null, 2));
|
|
149
|
+
console.log('[DatabaseManager] Migration completed successfully.');
|
|
150
|
+
console.log('[DatabaseManager] Migrated files:', migratedFiles);
|
|
151
|
+
console.log('[DatabaseManager] Migrated directories:', migratedDirs);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
console.error('[DatabaseManager] Migration failed:', error);
|
|
155
|
+
migrationSuccessful = false;
|
|
156
|
+
// Don't create marker if migration failed - allows retry on next startup
|
|
157
|
+
}
|
|
158
|
+
if (!migrationSuccessful) {
|
|
159
|
+
console.warn('[DatabaseManager] Migration incomplete - will retry on next startup');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Count files recursively in a directory
|
|
164
|
+
*/
|
|
165
|
+
countFilesRecursive(dirPath) {
|
|
166
|
+
let count = 0;
|
|
167
|
+
try {
|
|
168
|
+
const entries = fs_1.default.readdirSync(dirPath, { withFileTypes: true });
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
if (entry.isDirectory()) {
|
|
171
|
+
count += this.countFilesRecursive(path_1.default.join(dirPath, entry.name));
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
count++;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// Directory might not be readable
|
|
180
|
+
}
|
|
181
|
+
return count;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Recursively copy a directory
|
|
185
|
+
*/
|
|
186
|
+
copyDirectoryRecursive(src, dest) {
|
|
187
|
+
if (!fs_1.default.existsSync(dest)) {
|
|
188
|
+
fs_1.default.mkdirSync(dest, { recursive: true });
|
|
189
|
+
}
|
|
190
|
+
const entries = fs_1.default.readdirSync(src, { withFileTypes: true });
|
|
191
|
+
for (const entry of entries) {
|
|
192
|
+
const srcPath = path_1.default.join(src, entry.name);
|
|
193
|
+
const destPath = path_1.default.join(dest, entry.name);
|
|
194
|
+
if (entry.isDirectory()) {
|
|
195
|
+
this.copyDirectoryRecursive(srcPath, destPath);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
fs_1.default.copyFileSync(srcPath, destPath);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
initializeSchema() {
|
|
203
|
+
// Create tables
|
|
204
|
+
this.db.exec(`
|
|
205
|
+
CREATE TABLE IF NOT EXISTS workspaces (
|
|
206
|
+
id TEXT PRIMARY KEY,
|
|
207
|
+
name TEXT NOT NULL,
|
|
208
|
+
path TEXT NOT NULL UNIQUE,
|
|
209
|
+
created_at INTEGER NOT NULL,
|
|
210
|
+
permissions TEXT NOT NULL
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
214
|
+
id TEXT PRIMARY KEY,
|
|
215
|
+
title TEXT NOT NULL,
|
|
216
|
+
prompt TEXT NOT NULL,
|
|
217
|
+
status TEXT NOT NULL,
|
|
218
|
+
workspace_id TEXT NOT NULL,
|
|
219
|
+
created_at INTEGER NOT NULL,
|
|
220
|
+
updated_at INTEGER NOT NULL,
|
|
221
|
+
completed_at INTEGER,
|
|
222
|
+
budget_tokens INTEGER,
|
|
223
|
+
budget_cost REAL,
|
|
224
|
+
error TEXT,
|
|
225
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id)
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
CREATE TABLE IF NOT EXISTS task_events (
|
|
229
|
+
id TEXT PRIMARY KEY,
|
|
230
|
+
task_id TEXT NOT NULL,
|
|
231
|
+
timestamp INTEGER NOT NULL,
|
|
232
|
+
type TEXT NOT NULL,
|
|
233
|
+
payload TEXT NOT NULL,
|
|
234
|
+
FOREIGN KEY (task_id) REFERENCES tasks(id)
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
CREATE TABLE IF NOT EXISTS artifacts (
|
|
238
|
+
id TEXT PRIMARY KEY,
|
|
239
|
+
task_id TEXT NOT NULL,
|
|
240
|
+
path TEXT NOT NULL,
|
|
241
|
+
mime_type TEXT NOT NULL,
|
|
242
|
+
sha256 TEXT NOT NULL,
|
|
243
|
+
size INTEGER NOT NULL,
|
|
244
|
+
created_at INTEGER NOT NULL,
|
|
245
|
+
FOREIGN KEY (task_id) REFERENCES tasks(id)
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
CREATE TABLE IF NOT EXISTS approvals (
|
|
249
|
+
id TEXT PRIMARY KEY,
|
|
250
|
+
task_id TEXT NOT NULL,
|
|
251
|
+
type TEXT NOT NULL,
|
|
252
|
+
description TEXT NOT NULL,
|
|
253
|
+
details TEXT NOT NULL,
|
|
254
|
+
status TEXT NOT NULL,
|
|
255
|
+
requested_at INTEGER NOT NULL,
|
|
256
|
+
resolved_at INTEGER,
|
|
257
|
+
FOREIGN KEY (task_id) REFERENCES tasks(id)
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
CREATE TABLE IF NOT EXISTS skills (
|
|
261
|
+
id TEXT PRIMARY KEY,
|
|
262
|
+
name TEXT NOT NULL UNIQUE,
|
|
263
|
+
description TEXT NOT NULL,
|
|
264
|
+
category TEXT NOT NULL,
|
|
265
|
+
prompt TEXT NOT NULL,
|
|
266
|
+
script_path TEXT,
|
|
267
|
+
parameters TEXT
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
CREATE TABLE IF NOT EXISTS llm_models (
|
|
271
|
+
id TEXT PRIMARY KEY,
|
|
272
|
+
key TEXT NOT NULL UNIQUE,
|
|
273
|
+
display_name TEXT NOT NULL,
|
|
274
|
+
description TEXT NOT NULL,
|
|
275
|
+
anthropic_model_id TEXT NOT NULL,
|
|
276
|
+
bedrock_model_id TEXT NOT NULL,
|
|
277
|
+
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
278
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
279
|
+
created_at INTEGER NOT NULL,
|
|
280
|
+
updated_at INTEGER NOT NULL
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
-- Indexes for performance
|
|
284
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
285
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_workspace ON tasks(workspace_id);
|
|
286
|
+
CREATE INDEX IF NOT EXISTS idx_task_events_task ON task_events(task_id);
|
|
287
|
+
CREATE INDEX IF NOT EXISTS idx_artifacts_task ON artifacts(task_id);
|
|
288
|
+
CREATE INDEX IF NOT EXISTS idx_approvals_task ON approvals(task_id);
|
|
289
|
+
CREATE INDEX IF NOT EXISTS idx_approvals_status ON approvals(status);
|
|
290
|
+
CREATE INDEX IF NOT EXISTS idx_llm_models_active ON llm_models(is_active);
|
|
291
|
+
|
|
292
|
+
-- Channel Gateway tables
|
|
293
|
+
CREATE TABLE IF NOT EXISTS channels (
|
|
294
|
+
id TEXT PRIMARY KEY,
|
|
295
|
+
type TEXT NOT NULL,
|
|
296
|
+
name TEXT NOT NULL,
|
|
297
|
+
enabled INTEGER NOT NULL DEFAULT 0,
|
|
298
|
+
config TEXT NOT NULL,
|
|
299
|
+
security_config TEXT NOT NULL,
|
|
300
|
+
status TEXT NOT NULL DEFAULT 'disconnected',
|
|
301
|
+
bot_username TEXT,
|
|
302
|
+
created_at INTEGER NOT NULL,
|
|
303
|
+
updated_at INTEGER NOT NULL
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
CREATE TABLE IF NOT EXISTS channel_users (
|
|
307
|
+
id TEXT PRIMARY KEY,
|
|
308
|
+
channel_id TEXT NOT NULL,
|
|
309
|
+
channel_user_id TEXT NOT NULL,
|
|
310
|
+
display_name TEXT NOT NULL,
|
|
311
|
+
username TEXT,
|
|
312
|
+
allowed INTEGER NOT NULL DEFAULT 0,
|
|
313
|
+
pairing_code TEXT,
|
|
314
|
+
pairing_attempts INTEGER NOT NULL DEFAULT 0,
|
|
315
|
+
pairing_expires_at INTEGER,
|
|
316
|
+
created_at INTEGER NOT NULL,
|
|
317
|
+
last_seen_at INTEGER NOT NULL,
|
|
318
|
+
FOREIGN KEY (channel_id) REFERENCES channels(id),
|
|
319
|
+
UNIQUE(channel_id, channel_user_id)
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
CREATE TABLE IF NOT EXISTS channel_sessions (
|
|
323
|
+
id TEXT PRIMARY KEY,
|
|
324
|
+
channel_id TEXT NOT NULL,
|
|
325
|
+
chat_id TEXT NOT NULL,
|
|
326
|
+
user_id TEXT,
|
|
327
|
+
task_id TEXT,
|
|
328
|
+
workspace_id TEXT,
|
|
329
|
+
state TEXT NOT NULL DEFAULT 'idle',
|
|
330
|
+
context TEXT,
|
|
331
|
+
created_at INTEGER NOT NULL,
|
|
332
|
+
last_activity_at INTEGER NOT NULL,
|
|
333
|
+
FOREIGN KEY (channel_id) REFERENCES channels(id),
|
|
334
|
+
FOREIGN KEY (user_id) REFERENCES channel_users(id),
|
|
335
|
+
FOREIGN KEY (task_id) REFERENCES tasks(id),
|
|
336
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id)
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
CREATE TABLE IF NOT EXISTS channel_messages (
|
|
340
|
+
id TEXT PRIMARY KEY,
|
|
341
|
+
channel_id TEXT NOT NULL,
|
|
342
|
+
session_id TEXT,
|
|
343
|
+
channel_message_id TEXT NOT NULL,
|
|
344
|
+
chat_id TEXT NOT NULL,
|
|
345
|
+
user_id TEXT,
|
|
346
|
+
direction TEXT NOT NULL,
|
|
347
|
+
content TEXT NOT NULL,
|
|
348
|
+
attachments TEXT,
|
|
349
|
+
timestamp INTEGER NOT NULL,
|
|
350
|
+
FOREIGN KEY (channel_id) REFERENCES channels(id),
|
|
351
|
+
FOREIGN KEY (session_id) REFERENCES channel_sessions(id),
|
|
352
|
+
FOREIGN KEY (user_id) REFERENCES channel_users(id)
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
-- Channel indexes
|
|
356
|
+
CREATE INDEX IF NOT EXISTS idx_channels_type ON channels(type);
|
|
357
|
+
CREATE INDEX IF NOT EXISTS idx_channels_enabled ON channels(enabled);
|
|
358
|
+
CREATE INDEX IF NOT EXISTS idx_channel_users_channel ON channel_users(channel_id);
|
|
359
|
+
CREATE INDEX IF NOT EXISTS idx_channel_users_allowed ON channel_users(allowed);
|
|
360
|
+
CREATE INDEX IF NOT EXISTS idx_channel_sessions_channel ON channel_sessions(channel_id);
|
|
361
|
+
CREATE INDEX IF NOT EXISTS idx_channel_sessions_task ON channel_sessions(task_id);
|
|
362
|
+
CREATE INDEX IF NOT EXISTS idx_channel_sessions_state ON channel_sessions(state);
|
|
363
|
+
CREATE INDEX IF NOT EXISTS idx_channel_messages_session ON channel_messages(session_id);
|
|
364
|
+
CREATE INDEX IF NOT EXISTS idx_channel_messages_chat ON channel_messages(chat_id);
|
|
365
|
+
|
|
366
|
+
-- Gateway Infrastructure Tables
|
|
367
|
+
|
|
368
|
+
-- Message Queue for reliable delivery
|
|
369
|
+
CREATE TABLE IF NOT EXISTS message_queue (
|
|
370
|
+
id TEXT PRIMARY KEY,
|
|
371
|
+
channel_type TEXT NOT NULL,
|
|
372
|
+
chat_id TEXT NOT NULL,
|
|
373
|
+
message TEXT NOT NULL,
|
|
374
|
+
priority INTEGER NOT NULL DEFAULT 0,
|
|
375
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
376
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
377
|
+
max_attempts INTEGER NOT NULL DEFAULT 3,
|
|
378
|
+
last_attempt_at INTEGER,
|
|
379
|
+
error TEXT,
|
|
380
|
+
created_at INTEGER NOT NULL,
|
|
381
|
+
scheduled_at INTEGER
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
-- Scheduled Messages
|
|
385
|
+
CREATE TABLE IF NOT EXISTS scheduled_messages (
|
|
386
|
+
id TEXT PRIMARY KEY,
|
|
387
|
+
channel_type TEXT NOT NULL,
|
|
388
|
+
chat_id TEXT NOT NULL,
|
|
389
|
+
message TEXT NOT NULL,
|
|
390
|
+
scheduled_at INTEGER NOT NULL,
|
|
391
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
392
|
+
sent_message_id TEXT,
|
|
393
|
+
error TEXT,
|
|
394
|
+
created_at INTEGER NOT NULL
|
|
395
|
+
);
|
|
396
|
+
|
|
397
|
+
-- Delivery Tracking
|
|
398
|
+
CREATE TABLE IF NOT EXISTS delivery_tracking (
|
|
399
|
+
id TEXT PRIMARY KEY,
|
|
400
|
+
channel_type TEXT NOT NULL,
|
|
401
|
+
chat_id TEXT NOT NULL,
|
|
402
|
+
message_id TEXT NOT NULL,
|
|
403
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
404
|
+
sent_at INTEGER,
|
|
405
|
+
delivered_at INTEGER,
|
|
406
|
+
read_at INTEGER,
|
|
407
|
+
error TEXT,
|
|
408
|
+
created_at INTEGER NOT NULL
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
-- Rate Limits
|
|
412
|
+
CREATE TABLE IF NOT EXISTS rate_limits (
|
|
413
|
+
id TEXT PRIMARY KEY,
|
|
414
|
+
channel_type TEXT NOT NULL,
|
|
415
|
+
user_id TEXT NOT NULL,
|
|
416
|
+
message_count INTEGER NOT NULL DEFAULT 0,
|
|
417
|
+
window_start INTEGER NOT NULL,
|
|
418
|
+
is_limited INTEGER NOT NULL DEFAULT 0,
|
|
419
|
+
limit_expires_at INTEGER,
|
|
420
|
+
UNIQUE(channel_type, user_id)
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
-- Audit Log
|
|
424
|
+
CREATE TABLE IF NOT EXISTS audit_log (
|
|
425
|
+
id TEXT PRIMARY KEY,
|
|
426
|
+
timestamp INTEGER NOT NULL,
|
|
427
|
+
action TEXT NOT NULL,
|
|
428
|
+
channel_type TEXT,
|
|
429
|
+
user_id TEXT,
|
|
430
|
+
chat_id TEXT,
|
|
431
|
+
details TEXT,
|
|
432
|
+
severity TEXT NOT NULL DEFAULT 'info'
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
-- Gateway Infrastructure Indexes
|
|
436
|
+
CREATE INDEX IF NOT EXISTS idx_message_queue_status ON message_queue(status);
|
|
437
|
+
CREATE INDEX IF NOT EXISTS idx_message_queue_scheduled ON message_queue(scheduled_at);
|
|
438
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_messages_status ON scheduled_messages(status);
|
|
439
|
+
CREATE INDEX IF NOT EXISTS idx_scheduled_messages_scheduled ON scheduled_messages(scheduled_at);
|
|
440
|
+
CREATE INDEX IF NOT EXISTS idx_delivery_tracking_status ON delivery_tracking(status);
|
|
441
|
+
CREATE INDEX IF NOT EXISTS idx_delivery_tracking_message ON delivery_tracking(message_id);
|
|
442
|
+
CREATE INDEX IF NOT EXISTS idx_rate_limits_user ON rate_limits(channel_type, user_id);
|
|
443
|
+
CREATE INDEX IF NOT EXISTS idx_audit_log_timestamp ON audit_log(timestamp);
|
|
444
|
+
CREATE INDEX IF NOT EXISTS idx_audit_log_action ON audit_log(action);
|
|
445
|
+
CREATE INDEX IF NOT EXISTS idx_audit_log_user ON audit_log(user_id);
|
|
446
|
+
|
|
447
|
+
-- Memory System Tables
|
|
448
|
+
|
|
449
|
+
-- Core memories table for persistent context
|
|
450
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
451
|
+
id TEXT PRIMARY KEY,
|
|
452
|
+
workspace_id TEXT NOT NULL,
|
|
453
|
+
task_id TEXT,
|
|
454
|
+
type TEXT NOT NULL,
|
|
455
|
+
content TEXT NOT NULL,
|
|
456
|
+
summary TEXT,
|
|
457
|
+
tokens INTEGER NOT NULL DEFAULT 0,
|
|
458
|
+
is_compressed INTEGER NOT NULL DEFAULT 0,
|
|
459
|
+
is_private INTEGER NOT NULL DEFAULT 0,
|
|
460
|
+
created_at INTEGER NOT NULL,
|
|
461
|
+
updated_at INTEGER NOT NULL,
|
|
462
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id),
|
|
463
|
+
FOREIGN KEY (task_id) REFERENCES tasks(id)
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
-- Aggregated semantic summaries
|
|
467
|
+
CREATE TABLE IF NOT EXISTS memory_summaries (
|
|
468
|
+
id TEXT PRIMARY KEY,
|
|
469
|
+
workspace_id TEXT NOT NULL,
|
|
470
|
+
time_period TEXT NOT NULL,
|
|
471
|
+
period_start INTEGER NOT NULL,
|
|
472
|
+
period_end INTEGER NOT NULL,
|
|
473
|
+
summary TEXT NOT NULL,
|
|
474
|
+
memory_ids TEXT NOT NULL,
|
|
475
|
+
tokens INTEGER NOT NULL DEFAULT 0,
|
|
476
|
+
created_at INTEGER NOT NULL,
|
|
477
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id)
|
|
478
|
+
);
|
|
479
|
+
|
|
480
|
+
-- Per-workspace memory settings
|
|
481
|
+
CREATE TABLE IF NOT EXISTS memory_settings (
|
|
482
|
+
workspace_id TEXT PRIMARY KEY,
|
|
483
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
484
|
+
auto_capture INTEGER NOT NULL DEFAULT 1,
|
|
485
|
+
compression_enabled INTEGER NOT NULL DEFAULT 1,
|
|
486
|
+
retention_days INTEGER NOT NULL DEFAULT 90,
|
|
487
|
+
max_storage_mb INTEGER NOT NULL DEFAULT 100,
|
|
488
|
+
privacy_mode TEXT NOT NULL DEFAULT 'normal',
|
|
489
|
+
excluded_patterns TEXT,
|
|
490
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id)
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
-- Memory System Indexes
|
|
494
|
+
CREATE INDEX IF NOT EXISTS idx_memories_workspace ON memories(workspace_id);
|
|
495
|
+
CREATE INDEX IF NOT EXISTS idx_memories_task ON memories(task_id);
|
|
496
|
+
CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(type);
|
|
497
|
+
CREATE INDEX IF NOT EXISTS idx_memories_created ON memories(created_at);
|
|
498
|
+
CREATE INDEX IF NOT EXISTS idx_memories_compressed ON memories(is_compressed);
|
|
499
|
+
CREATE INDEX IF NOT EXISTS idx_memory_summaries_workspace ON memory_summaries(workspace_id);
|
|
500
|
+
CREATE INDEX IF NOT EXISTS idx_memory_summaries_period ON memory_summaries(time_period, period_start);
|
|
501
|
+
`);
|
|
502
|
+
// Initialize FTS5 for memory search (separate exec to handle if not supported)
|
|
503
|
+
this.initializeMemoryFTS();
|
|
504
|
+
// Run migrations for Goal Mode columns (SQLite ALTER TABLE ADD COLUMN is safe if column exists)
|
|
505
|
+
this.runMigrations();
|
|
506
|
+
// Seed default models if table is empty
|
|
507
|
+
this.seedDefaultModels();
|
|
508
|
+
}
|
|
509
|
+
initializeMemoryFTS() {
|
|
510
|
+
// Create FTS5 virtual table for full-text search on memories
|
|
511
|
+
// Using external content table pattern for efficiency
|
|
512
|
+
try {
|
|
513
|
+
this.db.exec(`
|
|
514
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
515
|
+
content,
|
|
516
|
+
summary,
|
|
517
|
+
content='memories',
|
|
518
|
+
content_rowid='rowid'
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
-- Trigger to keep FTS in sync on INSERT
|
|
522
|
+
CREATE TRIGGER IF NOT EXISTS memories_fts_insert AFTER INSERT ON memories BEGIN
|
|
523
|
+
INSERT INTO memories_fts(rowid, content, summary)
|
|
524
|
+
VALUES (NEW.rowid, NEW.content, NEW.summary);
|
|
525
|
+
END;
|
|
526
|
+
|
|
527
|
+
-- Trigger to keep FTS in sync on DELETE
|
|
528
|
+
CREATE TRIGGER IF NOT EXISTS memories_fts_delete AFTER DELETE ON memories BEGIN
|
|
529
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, summary)
|
|
530
|
+
VALUES('delete', OLD.rowid, OLD.content, OLD.summary);
|
|
531
|
+
END;
|
|
532
|
+
|
|
533
|
+
-- Trigger to keep FTS in sync on UPDATE
|
|
534
|
+
CREATE TRIGGER IF NOT EXISTS memories_fts_update AFTER UPDATE ON memories BEGIN
|
|
535
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, summary)
|
|
536
|
+
VALUES('delete', OLD.rowid, OLD.content, OLD.summary);
|
|
537
|
+
INSERT INTO memories_fts(rowid, content, summary)
|
|
538
|
+
VALUES (NEW.rowid, NEW.content, NEW.summary);
|
|
539
|
+
END;
|
|
540
|
+
`);
|
|
541
|
+
}
|
|
542
|
+
catch (error) {
|
|
543
|
+
// FTS5 might not be available in all SQLite builds
|
|
544
|
+
console.warn('[DatabaseManager] FTS5 initialization failed, full-text search will be disabled:', error);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
runMigrations() {
|
|
548
|
+
// Migration: Add Goal Mode columns to tasks table
|
|
549
|
+
// SQLite ALTER TABLE ADD COLUMN fails if column exists, so we catch and ignore
|
|
550
|
+
const goalModeColumns = [
|
|
551
|
+
'ALTER TABLE tasks ADD COLUMN success_criteria TEXT',
|
|
552
|
+
'ALTER TABLE tasks ADD COLUMN max_attempts INTEGER DEFAULT 3',
|
|
553
|
+
'ALTER TABLE tasks ADD COLUMN current_attempt INTEGER DEFAULT 1',
|
|
554
|
+
];
|
|
555
|
+
for (const sql of goalModeColumns) {
|
|
556
|
+
try {
|
|
557
|
+
this.db.exec(sql);
|
|
558
|
+
}
|
|
559
|
+
catch {
|
|
560
|
+
// Column already exists, ignore
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
// Migration: Add Sub-Agent / Parallel Agent columns to tasks table
|
|
564
|
+
const subAgentColumns = [
|
|
565
|
+
'ALTER TABLE tasks ADD COLUMN parent_task_id TEXT REFERENCES tasks(id)',
|
|
566
|
+
'ALTER TABLE tasks ADD COLUMN agent_type TEXT DEFAULT "main"',
|
|
567
|
+
'ALTER TABLE tasks ADD COLUMN agent_config TEXT',
|
|
568
|
+
'ALTER TABLE tasks ADD COLUMN depth INTEGER DEFAULT 0',
|
|
569
|
+
'ALTER TABLE tasks ADD COLUMN result_summary TEXT',
|
|
570
|
+
];
|
|
571
|
+
for (const sql of subAgentColumns) {
|
|
572
|
+
try {
|
|
573
|
+
this.db.exec(sql);
|
|
574
|
+
}
|
|
575
|
+
catch {
|
|
576
|
+
// Column already exists, ignore
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
// Add index for parent_task_id lookups
|
|
580
|
+
try {
|
|
581
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_task_id)');
|
|
582
|
+
}
|
|
583
|
+
catch {
|
|
584
|
+
// Index already exists, ignore
|
|
585
|
+
}
|
|
586
|
+
// Migration: Create agent_roles table for Agent Squad feature
|
|
587
|
+
try {
|
|
588
|
+
this.db.exec(`
|
|
589
|
+
CREATE TABLE IF NOT EXISTS agent_roles (
|
|
590
|
+
id TEXT PRIMARY KEY,
|
|
591
|
+
name TEXT NOT NULL UNIQUE,
|
|
592
|
+
display_name TEXT NOT NULL,
|
|
593
|
+
description TEXT,
|
|
594
|
+
icon TEXT DEFAULT '🤖',
|
|
595
|
+
color TEXT DEFAULT '#6366f1',
|
|
596
|
+
personality_id TEXT,
|
|
597
|
+
model_key TEXT,
|
|
598
|
+
provider_type TEXT,
|
|
599
|
+
system_prompt TEXT,
|
|
600
|
+
capabilities TEXT NOT NULL,
|
|
601
|
+
tool_restrictions TEXT,
|
|
602
|
+
is_system INTEGER NOT NULL DEFAULT 0,
|
|
603
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
604
|
+
sort_order INTEGER NOT NULL DEFAULT 100,
|
|
605
|
+
created_at INTEGER NOT NULL,
|
|
606
|
+
updated_at INTEGER NOT NULL
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
CREATE INDEX IF NOT EXISTS idx_agent_roles_active ON agent_roles(is_active);
|
|
610
|
+
CREATE INDEX IF NOT EXISTS idx_agent_roles_name ON agent_roles(name);
|
|
611
|
+
`);
|
|
612
|
+
}
|
|
613
|
+
catch {
|
|
614
|
+
// Table already exists, ignore
|
|
615
|
+
}
|
|
616
|
+
// Migration: Add assigned_agent_role_id to tasks table
|
|
617
|
+
const agentRoleColumns = [
|
|
618
|
+
'ALTER TABLE tasks ADD COLUMN assigned_agent_role_id TEXT REFERENCES agent_roles(id)',
|
|
619
|
+
'ALTER TABLE tasks ADD COLUMN board_column TEXT DEFAULT "backlog"',
|
|
620
|
+
'ALTER TABLE tasks ADD COLUMN priority INTEGER DEFAULT 0',
|
|
621
|
+
];
|
|
622
|
+
for (const sql of agentRoleColumns) {
|
|
623
|
+
try {
|
|
624
|
+
this.db.exec(sql);
|
|
625
|
+
}
|
|
626
|
+
catch {
|
|
627
|
+
// Column already exists, ignore
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
// Add index for agent role lookups on tasks
|
|
631
|
+
try {
|
|
632
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_agent_role ON tasks(assigned_agent_role_id)');
|
|
633
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_board_column ON tasks(board_column)');
|
|
634
|
+
}
|
|
635
|
+
catch {
|
|
636
|
+
// Index already exists, ignore
|
|
637
|
+
}
|
|
638
|
+
// Migration: Create activity_feed table for cross-agent activity stream
|
|
639
|
+
try {
|
|
640
|
+
this.db.exec(`
|
|
641
|
+
CREATE TABLE IF NOT EXISTS activity_feed (
|
|
642
|
+
id TEXT PRIMARY KEY,
|
|
643
|
+
workspace_id TEXT NOT NULL,
|
|
644
|
+
task_id TEXT,
|
|
645
|
+
agent_role_id TEXT,
|
|
646
|
+
actor_type TEXT NOT NULL,
|
|
647
|
+
activity_type TEXT NOT NULL,
|
|
648
|
+
title TEXT NOT NULL,
|
|
649
|
+
description TEXT,
|
|
650
|
+
metadata TEXT,
|
|
651
|
+
is_read INTEGER DEFAULT 0,
|
|
652
|
+
is_pinned INTEGER DEFAULT 0,
|
|
653
|
+
created_at INTEGER NOT NULL,
|
|
654
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id),
|
|
655
|
+
FOREIGN KEY (task_id) REFERENCES tasks(id),
|
|
656
|
+
FOREIGN KEY (agent_role_id) REFERENCES agent_roles(id)
|
|
657
|
+
);
|
|
658
|
+
|
|
659
|
+
CREATE INDEX IF NOT EXISTS idx_activity_workspace ON activity_feed(workspace_id, created_at DESC);
|
|
660
|
+
CREATE INDEX IF NOT EXISTS idx_activity_unread ON activity_feed(workspace_id, is_read);
|
|
661
|
+
CREATE INDEX IF NOT EXISTS idx_activity_type ON activity_feed(activity_type);
|
|
662
|
+
`);
|
|
663
|
+
}
|
|
664
|
+
catch {
|
|
665
|
+
// Table already exists, ignore
|
|
666
|
+
}
|
|
667
|
+
// Migration: Create agent_mentions table for inter-agent communication
|
|
668
|
+
try {
|
|
669
|
+
this.db.exec(`
|
|
670
|
+
CREATE TABLE IF NOT EXISTS agent_mentions (
|
|
671
|
+
id TEXT PRIMARY KEY,
|
|
672
|
+
workspace_id TEXT NOT NULL,
|
|
673
|
+
task_id TEXT NOT NULL,
|
|
674
|
+
from_agent_role_id TEXT,
|
|
675
|
+
to_agent_role_id TEXT NOT NULL,
|
|
676
|
+
mention_type TEXT NOT NULL,
|
|
677
|
+
context TEXT,
|
|
678
|
+
status TEXT DEFAULT 'pending',
|
|
679
|
+
created_at INTEGER NOT NULL,
|
|
680
|
+
acknowledged_at INTEGER,
|
|
681
|
+
completed_at INTEGER,
|
|
682
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id),
|
|
683
|
+
FOREIGN KEY (task_id) REFERENCES tasks(id),
|
|
684
|
+
FOREIGN KEY (from_agent_role_id) REFERENCES agent_roles(id),
|
|
685
|
+
FOREIGN KEY (to_agent_role_id) REFERENCES agent_roles(id)
|
|
686
|
+
);
|
|
687
|
+
|
|
688
|
+
CREATE INDEX IF NOT EXISTS idx_mentions_to_agent ON agent_mentions(to_agent_role_id, status);
|
|
689
|
+
CREATE INDEX IF NOT EXISTS idx_mentions_task ON agent_mentions(task_id);
|
|
690
|
+
CREATE INDEX IF NOT EXISTS idx_mentions_workspace ON agent_mentions(workspace_id, created_at DESC);
|
|
691
|
+
`);
|
|
692
|
+
}
|
|
693
|
+
catch {
|
|
694
|
+
// Table already exists, ignore
|
|
695
|
+
}
|
|
696
|
+
// Migration: Add mentioned_agent_role_ids to tasks table
|
|
697
|
+
try {
|
|
698
|
+
this.db.exec('ALTER TABLE tasks ADD COLUMN mentioned_agent_role_ids TEXT');
|
|
699
|
+
}
|
|
700
|
+
catch {
|
|
701
|
+
// Column already exists, ignore
|
|
702
|
+
}
|
|
703
|
+
// Migration: Add task board columns to tasks table (Phase 1.4)
|
|
704
|
+
try {
|
|
705
|
+
this.db.exec('ALTER TABLE tasks ADD COLUMN board_column TEXT DEFAULT \'backlog\'');
|
|
706
|
+
}
|
|
707
|
+
catch {
|
|
708
|
+
// Column already exists, ignore
|
|
709
|
+
}
|
|
710
|
+
try {
|
|
711
|
+
this.db.exec('ALTER TABLE tasks ADD COLUMN priority INTEGER DEFAULT 0');
|
|
712
|
+
}
|
|
713
|
+
catch {
|
|
714
|
+
// Column already exists, ignore
|
|
715
|
+
}
|
|
716
|
+
try {
|
|
717
|
+
this.db.exec('ALTER TABLE tasks ADD COLUMN labels TEXT');
|
|
718
|
+
}
|
|
719
|
+
catch {
|
|
720
|
+
// Column already exists, ignore
|
|
721
|
+
}
|
|
722
|
+
try {
|
|
723
|
+
this.db.exec('ALTER TABLE tasks ADD COLUMN due_date INTEGER');
|
|
724
|
+
}
|
|
725
|
+
catch {
|
|
726
|
+
// Column already exists, ignore
|
|
727
|
+
}
|
|
728
|
+
try {
|
|
729
|
+
this.db.exec('ALTER TABLE tasks ADD COLUMN estimated_minutes INTEGER');
|
|
730
|
+
}
|
|
731
|
+
catch {
|
|
732
|
+
// Column already exists, ignore
|
|
733
|
+
}
|
|
734
|
+
try {
|
|
735
|
+
this.db.exec('ALTER TABLE tasks ADD COLUMN actual_minutes INTEGER');
|
|
736
|
+
}
|
|
737
|
+
catch {
|
|
738
|
+
// Column already exists, ignore
|
|
739
|
+
}
|
|
740
|
+
// Migration: Create task_labels table for custom labels
|
|
741
|
+
try {
|
|
742
|
+
this.db.exec(`
|
|
743
|
+
CREATE TABLE IF NOT EXISTS task_labels (
|
|
744
|
+
id TEXT PRIMARY KEY,
|
|
745
|
+
workspace_id TEXT NOT NULL,
|
|
746
|
+
name TEXT NOT NULL,
|
|
747
|
+
color TEXT DEFAULT '#6366f1',
|
|
748
|
+
created_at INTEGER NOT NULL,
|
|
749
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id),
|
|
750
|
+
UNIQUE(workspace_id, name)
|
|
751
|
+
);
|
|
752
|
+
|
|
753
|
+
CREATE INDEX IF NOT EXISTS idx_task_labels_workspace ON task_labels(workspace_id);
|
|
754
|
+
`);
|
|
755
|
+
}
|
|
756
|
+
catch {
|
|
757
|
+
// Table already exists, ignore
|
|
758
|
+
}
|
|
759
|
+
// Migration: Create index for task board queries
|
|
760
|
+
try {
|
|
761
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_board ON tasks(workspace_id, board_column)');
|
|
762
|
+
}
|
|
763
|
+
catch {
|
|
764
|
+
// Index already exists, ignore
|
|
765
|
+
}
|
|
766
|
+
try {
|
|
767
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority DESC)');
|
|
768
|
+
}
|
|
769
|
+
catch {
|
|
770
|
+
// Index already exists, ignore
|
|
771
|
+
}
|
|
772
|
+
// Migration: Create agent_working_state table (Phase 1.5)
|
|
773
|
+
try {
|
|
774
|
+
this.db.exec(`
|
|
775
|
+
CREATE TABLE IF NOT EXISTS agent_working_state (
|
|
776
|
+
id TEXT PRIMARY KEY,
|
|
777
|
+
agent_role_id TEXT NOT NULL,
|
|
778
|
+
workspace_id TEXT NOT NULL,
|
|
779
|
+
task_id TEXT,
|
|
780
|
+
state_type TEXT NOT NULL,
|
|
781
|
+
content TEXT NOT NULL,
|
|
782
|
+
file_references TEXT,
|
|
783
|
+
is_current INTEGER DEFAULT 1,
|
|
784
|
+
created_at INTEGER NOT NULL,
|
|
785
|
+
updated_at INTEGER NOT NULL,
|
|
786
|
+
FOREIGN KEY (agent_role_id) REFERENCES agent_roles(id),
|
|
787
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id),
|
|
788
|
+
FOREIGN KEY (task_id) REFERENCES tasks(id)
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
CREATE INDEX IF NOT EXISTS idx_working_state_agent ON agent_working_state(agent_role_id, workspace_id, is_current);
|
|
792
|
+
CREATE INDEX IF NOT EXISTS idx_working_state_task ON agent_working_state(task_id);
|
|
793
|
+
`);
|
|
794
|
+
}
|
|
795
|
+
catch {
|
|
796
|
+
// Table already exists, ignore
|
|
797
|
+
}
|
|
798
|
+
// Migration: Create context_policies table for per-context security (DM vs group)
|
|
799
|
+
try {
|
|
800
|
+
this.db.exec(`
|
|
801
|
+
CREATE TABLE IF NOT EXISTS context_policies (
|
|
802
|
+
id TEXT PRIMARY KEY,
|
|
803
|
+
channel_id TEXT NOT NULL,
|
|
804
|
+
context_type TEXT NOT NULL CHECK(context_type IN ('dm', 'group')),
|
|
805
|
+
security_mode TEXT NOT NULL DEFAULT 'pairing' CHECK(security_mode IN ('open', 'allowlist', 'pairing')),
|
|
806
|
+
tool_restrictions TEXT,
|
|
807
|
+
created_at INTEGER NOT NULL,
|
|
808
|
+
updated_at INTEGER NOT NULL,
|
|
809
|
+
FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE CASCADE,
|
|
810
|
+
UNIQUE(channel_id, context_type)
|
|
811
|
+
);
|
|
812
|
+
|
|
813
|
+
CREATE INDEX IF NOT EXISTS idx_context_policies_channel ON context_policies(channel_id);
|
|
814
|
+
`);
|
|
815
|
+
}
|
|
816
|
+
catch {
|
|
817
|
+
// Table already exists, ignore
|
|
818
|
+
}
|
|
819
|
+
// Migration: Add shell_enabled and debug_mode columns to channel_sessions
|
|
820
|
+
try {
|
|
821
|
+
this.db.exec('ALTER TABLE channel_sessions ADD COLUMN shell_enabled INTEGER DEFAULT 0');
|
|
822
|
+
}
|
|
823
|
+
catch {
|
|
824
|
+
// Column already exists, ignore
|
|
825
|
+
}
|
|
826
|
+
try {
|
|
827
|
+
this.db.exec('ALTER TABLE channel_sessions ADD COLUMN debug_mode INTEGER DEFAULT 0');
|
|
828
|
+
}
|
|
829
|
+
catch {
|
|
830
|
+
// Column already exists, ignore
|
|
831
|
+
}
|
|
832
|
+
// Migration: Add lockout_until column to channel_users
|
|
833
|
+
// Separates brute-force lockout timestamp from pairing code expiration
|
|
834
|
+
try {
|
|
835
|
+
this.db.exec('ALTER TABLE channel_users ADD COLUMN lockout_until INTEGER');
|
|
836
|
+
}
|
|
837
|
+
catch {
|
|
838
|
+
// Column already exists, ignore
|
|
839
|
+
}
|
|
840
|
+
// ============ Secure Settings Table ============
|
|
841
|
+
// All settings are encrypted using OS keychain (Electron safeStorage)
|
|
842
|
+
// Only this app can decrypt the values
|
|
843
|
+
try {
|
|
844
|
+
this.db.exec(`
|
|
845
|
+
CREATE TABLE IF NOT EXISTS secure_settings (
|
|
846
|
+
id TEXT PRIMARY KEY,
|
|
847
|
+
category TEXT NOT NULL,
|
|
848
|
+
encrypted_data TEXT NOT NULL,
|
|
849
|
+
checksum TEXT NOT NULL,
|
|
850
|
+
created_at INTEGER NOT NULL,
|
|
851
|
+
updated_at INTEGER NOT NULL,
|
|
852
|
+
UNIQUE(category)
|
|
853
|
+
);
|
|
854
|
+
|
|
855
|
+
CREATE INDEX IF NOT EXISTS idx_secure_settings_category ON secure_settings(category);
|
|
856
|
+
`);
|
|
857
|
+
}
|
|
858
|
+
catch {
|
|
859
|
+
// Table already exists, ignore
|
|
860
|
+
}
|
|
861
|
+
// ============ Mission Control Migrations ============
|
|
862
|
+
// Migration: Add heartbeat and autonomy columns to agent_roles
|
|
863
|
+
const missionControlColumns = [
|
|
864
|
+
'ALTER TABLE agent_roles ADD COLUMN autonomy_level TEXT DEFAULT \'specialist\'',
|
|
865
|
+
'ALTER TABLE agent_roles ADD COLUMN soul TEXT',
|
|
866
|
+
'ALTER TABLE agent_roles ADD COLUMN heartbeat_enabled INTEGER DEFAULT 0',
|
|
867
|
+
'ALTER TABLE agent_roles ADD COLUMN heartbeat_interval_minutes INTEGER DEFAULT 15',
|
|
868
|
+
'ALTER TABLE agent_roles ADD COLUMN heartbeat_stagger_offset INTEGER DEFAULT 0',
|
|
869
|
+
'ALTER TABLE agent_roles ADD COLUMN last_heartbeat_at INTEGER',
|
|
870
|
+
'ALTER TABLE agent_roles ADD COLUMN heartbeat_status TEXT DEFAULT \'idle\'',
|
|
871
|
+
];
|
|
872
|
+
for (const sql of missionControlColumns) {
|
|
873
|
+
try {
|
|
874
|
+
this.db.exec(sql);
|
|
875
|
+
}
|
|
876
|
+
catch {
|
|
877
|
+
// Column already exists, ignore
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
// Migration: Create task_subscriptions table for thread subscriptions
|
|
881
|
+
try {
|
|
882
|
+
this.db.exec(`
|
|
883
|
+
CREATE TABLE IF NOT EXISTS task_subscriptions (
|
|
884
|
+
id TEXT PRIMARY KEY,
|
|
885
|
+
task_id TEXT NOT NULL,
|
|
886
|
+
agent_role_id TEXT NOT NULL,
|
|
887
|
+
subscription_reason TEXT NOT NULL,
|
|
888
|
+
subscribed_at INTEGER NOT NULL,
|
|
889
|
+
FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
|
|
890
|
+
FOREIGN KEY (agent_role_id) REFERENCES agent_roles(id) ON DELETE CASCADE,
|
|
891
|
+
UNIQUE(task_id, agent_role_id)
|
|
892
|
+
);
|
|
893
|
+
|
|
894
|
+
CREATE INDEX IF NOT EXISTS idx_task_subscriptions_task ON task_subscriptions(task_id);
|
|
895
|
+
CREATE INDEX IF NOT EXISTS idx_task_subscriptions_agent ON task_subscriptions(agent_role_id);
|
|
896
|
+
`);
|
|
897
|
+
}
|
|
898
|
+
catch {
|
|
899
|
+
// Table already exists, ignore
|
|
900
|
+
}
|
|
901
|
+
// Migration: Create standup_reports table for daily standups
|
|
902
|
+
try {
|
|
903
|
+
this.db.exec(`
|
|
904
|
+
CREATE TABLE IF NOT EXISTS standup_reports (
|
|
905
|
+
id TEXT PRIMARY KEY,
|
|
906
|
+
workspace_id TEXT NOT NULL,
|
|
907
|
+
report_date TEXT NOT NULL,
|
|
908
|
+
completed_task_ids TEXT,
|
|
909
|
+
in_progress_task_ids TEXT,
|
|
910
|
+
blocked_task_ids TEXT,
|
|
911
|
+
summary TEXT NOT NULL,
|
|
912
|
+
delivered_to_channel TEXT,
|
|
913
|
+
created_at INTEGER NOT NULL,
|
|
914
|
+
FOREIGN KEY (workspace_id) REFERENCES workspaces(id),
|
|
915
|
+
UNIQUE(workspace_id, report_date)
|
|
916
|
+
);
|
|
917
|
+
|
|
918
|
+
CREATE INDEX IF NOT EXISTS idx_standup_reports_workspace ON standup_reports(workspace_id);
|
|
919
|
+
CREATE INDEX IF NOT EXISTS idx_standup_reports_date ON standup_reports(report_date);
|
|
920
|
+
`);
|
|
921
|
+
}
|
|
922
|
+
catch {
|
|
923
|
+
// Table already exists, ignore
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
seedDefaultModels() {
|
|
927
|
+
const count = this.db.prepare('SELECT COUNT(*) as count FROM llm_models').get();
|
|
928
|
+
if (count.count === 0) {
|
|
929
|
+
const now = Date.now();
|
|
930
|
+
const models = [
|
|
931
|
+
{
|
|
932
|
+
id: 'model-opus-4-5',
|
|
933
|
+
key: 'opus-4-5',
|
|
934
|
+
displayName: 'Opus 4.5',
|
|
935
|
+
description: 'Most capable for complex work',
|
|
936
|
+
anthropicModelId: 'claude-opus-4-5-20250514',
|
|
937
|
+
bedrockModelId: 'us.anthropic.claude-opus-4-5-20250514-v1:0',
|
|
938
|
+
sortOrder: 1,
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
id: 'model-sonnet-4-5',
|
|
942
|
+
key: 'sonnet-4-5',
|
|
943
|
+
displayName: 'Sonnet 4.5',
|
|
944
|
+
description: 'Best for everyday tasks',
|
|
945
|
+
anthropicModelId: 'claude-sonnet-4-5-20250514',
|
|
946
|
+
bedrockModelId: 'us.anthropic.claude-sonnet-4-5-20250514-v1:0',
|
|
947
|
+
sortOrder: 2,
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
id: 'model-haiku-4-5',
|
|
951
|
+
key: 'haiku-4-5',
|
|
952
|
+
displayName: 'Haiku 4.5',
|
|
953
|
+
description: 'Fastest for quick answers',
|
|
954
|
+
anthropicModelId: 'claude-haiku-4-5-20250514',
|
|
955
|
+
bedrockModelId: 'us.anthropic.claude-haiku-4-5-20250514-v1:0',
|
|
956
|
+
sortOrder: 3,
|
|
957
|
+
},
|
|
958
|
+
];
|
|
959
|
+
const stmt = this.db.prepare(`
|
|
960
|
+
INSERT INTO llm_models (id, key, display_name, description, anthropic_model_id, bedrock_model_id, sort_order, is_active, created_at, updated_at)
|
|
961
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?)
|
|
962
|
+
`);
|
|
963
|
+
for (const model of models) {
|
|
964
|
+
stmt.run(model.id, model.key, model.displayName, model.description, model.anthropicModelId, model.bedrockModelId, model.sortOrder, now, now);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
getDatabase() {
|
|
969
|
+
return this.db;
|
|
970
|
+
}
|
|
971
|
+
close() {
|
|
972
|
+
this.db.close();
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
exports.DatabaseManager = DatabaseManager;
|
|
976
|
+
DatabaseManager.instance = null;
|
|
977
|
+
// Migration version - increment this to force re-migration for users with partial migrations
|
|
978
|
+
DatabaseManager.MIGRATION_VERSION = 2;
|