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,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Skill Eligibility Checker
|
|
4
|
+
*
|
|
5
|
+
* Determines if a skill is eligible to run based on its requirements:
|
|
6
|
+
* - Required binaries (bins)
|
|
7
|
+
* - Any-of binaries (anyBins)
|
|
8
|
+
* - Environment variables (env)
|
|
9
|
+
* - Config paths (config)
|
|
10
|
+
* - Operating system (os)
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.SkillEligibilityChecker = void 0;
|
|
14
|
+
exports.getSkillEligibilityChecker = getSkillEligibilityChecker;
|
|
15
|
+
const child_process_1 = require("child_process");
|
|
16
|
+
const util_1 = require("util");
|
|
17
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
18
|
+
// Regex for valid binary names: alphanumeric, hyphens, underscores, dots
|
|
19
|
+
// This prevents command injection via malicious binary names
|
|
20
|
+
const VALID_BINARY_NAME = /^[a-zA-Z0-9._-]+$/;
|
|
21
|
+
/**
|
|
22
|
+
* Validate and sanitize a binary name to prevent command injection
|
|
23
|
+
* Returns null if the binary name is invalid/unsafe
|
|
24
|
+
*/
|
|
25
|
+
function sanitizeBinaryName(bin) {
|
|
26
|
+
if (!bin || typeof bin !== 'string') {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
// Trim whitespace
|
|
30
|
+
const trimmed = bin.trim();
|
|
31
|
+
// Check length limits (reasonable binary name length)
|
|
32
|
+
if (trimmed.length === 0 || trimmed.length > 256) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
// Validate against allowed pattern
|
|
36
|
+
if (!VALID_BINARY_NAME.test(trimmed)) {
|
|
37
|
+
console.warn(`[SkillEligibilityChecker] Invalid binary name rejected: ${bin}`);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return trimmed;
|
|
41
|
+
}
|
|
42
|
+
class SkillEligibilityChecker {
|
|
43
|
+
constructor(config) {
|
|
44
|
+
this.binCache = new Map();
|
|
45
|
+
this.config = config;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if a binary exists in PATH
|
|
49
|
+
*/
|
|
50
|
+
async checkBinary(bin) {
|
|
51
|
+
// Sanitize binary name to prevent command injection
|
|
52
|
+
const safeBin = sanitizeBinaryName(bin);
|
|
53
|
+
if (!safeBin) {
|
|
54
|
+
// Invalid binary name - treat as not found
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
// Check cache first
|
|
58
|
+
if (this.binCache.has(safeBin)) {
|
|
59
|
+
return this.binCache.get(safeBin);
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
// Use 'which' on Unix-like systems, 'where' on Windows
|
|
63
|
+
const command = process.platform === 'win32' ? `where ${safeBin}` : `which ${safeBin}`;
|
|
64
|
+
await execAsync(command);
|
|
65
|
+
this.binCache.set(safeBin, true);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
this.binCache.set(safeBin, false);
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if all specified binaries exist
|
|
75
|
+
*/
|
|
76
|
+
async checkAllBinaries(bins) {
|
|
77
|
+
const results = await Promise.all(bins.map(async (bin) => ({
|
|
78
|
+
bin,
|
|
79
|
+
exists: await this.checkBinary(bin),
|
|
80
|
+
})));
|
|
81
|
+
return {
|
|
82
|
+
found: results.filter((r) => r.exists).map((r) => r.bin),
|
|
83
|
+
missing: results.filter((r) => !r.exists).map((r) => r.bin),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if at least one of the specified binaries exists
|
|
88
|
+
*/
|
|
89
|
+
async checkAnyBinary(bins) {
|
|
90
|
+
const results = await Promise.all(bins.map(async (bin) => ({
|
|
91
|
+
bin,
|
|
92
|
+
exists: await this.checkBinary(bin),
|
|
93
|
+
})));
|
|
94
|
+
const found = results.filter((r) => r.exists).map((r) => r.bin);
|
|
95
|
+
// If any binary is found, none are "missing" for anyBins requirement
|
|
96
|
+
// If none are found, all are missing
|
|
97
|
+
const missing = found.length > 0 ? [] : bins;
|
|
98
|
+
return { found, missing };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Check if an environment variable is set
|
|
102
|
+
*/
|
|
103
|
+
checkEnvVar(envVar) {
|
|
104
|
+
const value = process.env[envVar];
|
|
105
|
+
return value !== undefined && value !== '';
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if all specified environment variables are set
|
|
109
|
+
*/
|
|
110
|
+
checkAllEnvVars(envVars) {
|
|
111
|
+
const found = [];
|
|
112
|
+
const missing = [];
|
|
113
|
+
for (const envVar of envVars) {
|
|
114
|
+
if (this.checkEnvVar(envVar)) {
|
|
115
|
+
found.push(envVar);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
missing.push(envVar);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return { found, missing };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Check if config path is truthy (placeholder for future config system)
|
|
125
|
+
*/
|
|
126
|
+
checkConfigPath(configPath) {
|
|
127
|
+
// TODO: Implement config path checking when config system is available
|
|
128
|
+
// For now, always return false (missing)
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if all specified config paths are truthy
|
|
133
|
+
*/
|
|
134
|
+
checkAllConfigPaths(configPaths) {
|
|
135
|
+
const found = [];
|
|
136
|
+
const missing = [];
|
|
137
|
+
for (const configPath of configPaths) {
|
|
138
|
+
if (this.checkConfigPath(configPath)) {
|
|
139
|
+
found.push(configPath);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
missing.push(configPath);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return { found, missing };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Check if current OS matches required OS
|
|
149
|
+
*/
|
|
150
|
+
checkOS(requiredOS) {
|
|
151
|
+
const current = process.platform;
|
|
152
|
+
const matches = requiredOS.length === 0 || requiredOS.includes(current);
|
|
153
|
+
return {
|
|
154
|
+
matches,
|
|
155
|
+
current,
|
|
156
|
+
missing: matches ? [] : requiredOS,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Check if a skill is blocked by allowlist/denylist
|
|
161
|
+
*/
|
|
162
|
+
isBlockedByList(skillId) {
|
|
163
|
+
if (!this.config)
|
|
164
|
+
return false;
|
|
165
|
+
// Check denylist first
|
|
166
|
+
if (this.config.denylist?.includes(skillId)) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
// Check allowlist (if set, skill must be in it)
|
|
170
|
+
if (this.config.allowlist && this.config.allowlist.length > 0) {
|
|
171
|
+
return !this.config.allowlist.includes(skillId);
|
|
172
|
+
}
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Check all requirements for a skill and return eligibility status
|
|
177
|
+
*/
|
|
178
|
+
async checkEligibility(skill) {
|
|
179
|
+
const missing = {
|
|
180
|
+
bins: [],
|
|
181
|
+
anyBins: [],
|
|
182
|
+
env: [],
|
|
183
|
+
config: [],
|
|
184
|
+
os: [],
|
|
185
|
+
};
|
|
186
|
+
const requires = skill.requires;
|
|
187
|
+
// Check required binaries
|
|
188
|
+
if (requires?.bins && requires.bins.length > 0) {
|
|
189
|
+
const binCheck = await this.checkAllBinaries(requires.bins);
|
|
190
|
+
missing.bins = binCheck.missing;
|
|
191
|
+
}
|
|
192
|
+
// Check any-of binaries
|
|
193
|
+
if (requires?.anyBins && requires.anyBins.length > 0) {
|
|
194
|
+
const anyBinCheck = await this.checkAnyBinary(requires.anyBins);
|
|
195
|
+
missing.anyBins = anyBinCheck.missing;
|
|
196
|
+
}
|
|
197
|
+
// Check environment variables
|
|
198
|
+
if (requires?.env && requires.env.length > 0) {
|
|
199
|
+
const envCheck = this.checkAllEnvVars(requires.env);
|
|
200
|
+
missing.env = envCheck.missing;
|
|
201
|
+
}
|
|
202
|
+
// Check config paths
|
|
203
|
+
if (requires?.config && requires.config.length > 0) {
|
|
204
|
+
const configCheck = this.checkAllConfigPaths(requires.config);
|
|
205
|
+
missing.config = configCheck.missing;
|
|
206
|
+
}
|
|
207
|
+
// Check OS
|
|
208
|
+
if (requires?.os && requires.os.length > 0) {
|
|
209
|
+
const osCheck = this.checkOS(requires.os);
|
|
210
|
+
missing.os = osCheck.missing;
|
|
211
|
+
}
|
|
212
|
+
// Check if skill is disabled
|
|
213
|
+
const disabled = skill.enabled === false;
|
|
214
|
+
// Check if blocked by allowlist/denylist
|
|
215
|
+
const blockedByAllowlist = this.isBlockedByList(skill.id);
|
|
216
|
+
// Skill is eligible if not disabled, not blocked, and no missing requirements
|
|
217
|
+
const hasMissingRequirements = missing.bins.length > 0 ||
|
|
218
|
+
missing.anyBins.length > 0 ||
|
|
219
|
+
missing.env.length > 0 ||
|
|
220
|
+
missing.config.length > 0 ||
|
|
221
|
+
missing.os.length > 0;
|
|
222
|
+
const eligible = !disabled && !blockedByAllowlist && !hasMissingRequirements;
|
|
223
|
+
return {
|
|
224
|
+
eligible,
|
|
225
|
+
disabled,
|
|
226
|
+
blockedByAllowlist,
|
|
227
|
+
missing,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Build a full status entry for a skill
|
|
232
|
+
*/
|
|
233
|
+
async buildStatusEntry(skill) {
|
|
234
|
+
const eligibility = await this.checkEligibility(skill);
|
|
235
|
+
const requires = skill.requires || {};
|
|
236
|
+
return {
|
|
237
|
+
...skill,
|
|
238
|
+
eligible: eligibility.eligible,
|
|
239
|
+
disabled: eligibility.disabled,
|
|
240
|
+
blockedByAllowlist: eligibility.blockedByAllowlist,
|
|
241
|
+
requirements: {
|
|
242
|
+
bins: requires.bins || [],
|
|
243
|
+
anyBins: requires.anyBins || [],
|
|
244
|
+
env: requires.env || [],
|
|
245
|
+
config: requires.config || [],
|
|
246
|
+
os: requires.os || [],
|
|
247
|
+
},
|
|
248
|
+
missing: eligibility.missing,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Build status entries for multiple skills
|
|
253
|
+
*/
|
|
254
|
+
async buildStatusEntries(skills) {
|
|
255
|
+
return Promise.all(skills.map((skill) => this.buildStatusEntry(skill)));
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Clear the binary cache (useful after installations)
|
|
259
|
+
*/
|
|
260
|
+
clearCache() {
|
|
261
|
+
this.binCache.clear();
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Update config (for allowlist/denylist changes)
|
|
265
|
+
*/
|
|
266
|
+
updateConfig(config) {
|
|
267
|
+
this.config = config;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
exports.SkillEligibilityChecker = SkillEligibilityChecker;
|
|
271
|
+
// Singleton instance
|
|
272
|
+
let instance = null;
|
|
273
|
+
function getSkillEligibilityChecker(config) {
|
|
274
|
+
if (!instance) {
|
|
275
|
+
instance = new SkillEligibilityChecker(config);
|
|
276
|
+
}
|
|
277
|
+
else if (config) {
|
|
278
|
+
instance.updateConfig(config);
|
|
279
|
+
}
|
|
280
|
+
return instance;
|
|
281
|
+
}
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Skill Registry Service
|
|
4
|
+
*
|
|
5
|
+
* Handles communication with the remote skill registry for:
|
|
6
|
+
* - Searching skills
|
|
7
|
+
* - Installing skills
|
|
8
|
+
* - Updating skills
|
|
9
|
+
* - Publishing skills (future)
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.SkillRegistry = void 0;
|
|
46
|
+
exports.getSkillRegistry = getSkillRegistry;
|
|
47
|
+
exports.resetSkillRegistry = resetSkillRegistry;
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const electron_1 = require("electron");
|
|
51
|
+
// Default registry URL - can be overridden via SKILLHUB_REGISTRY env var
|
|
52
|
+
const DEFAULT_REGISTRY_URL = process.env.SKILLHUB_REGISTRY || 'https://skill-hub.com/api';
|
|
53
|
+
const SKILLS_FOLDER_NAME = 'skills';
|
|
54
|
+
// Regex for valid skill IDs: lowercase alphanumeric, hyphens, underscores
|
|
55
|
+
// This prevents path traversal attacks via malicious skill IDs
|
|
56
|
+
const VALID_SKILL_ID = /^[a-z0-9_-]+$/;
|
|
57
|
+
/**
|
|
58
|
+
* Validate and sanitize a skill ID to prevent path traversal
|
|
59
|
+
* Returns null if the skill ID is invalid/unsafe
|
|
60
|
+
*/
|
|
61
|
+
function sanitizeSkillId(skillId) {
|
|
62
|
+
if (!skillId || typeof skillId !== 'string') {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
// Trim whitespace and convert to lowercase
|
|
66
|
+
const normalized = skillId.trim().toLowerCase();
|
|
67
|
+
// Check length limits
|
|
68
|
+
if (normalized.length === 0 || normalized.length > 128) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
// Reject path traversal attempts
|
|
72
|
+
if (normalized.includes('..') || normalized.includes('/') || normalized.includes('\\')) {
|
|
73
|
+
console.warn(`[SkillRegistry] Path traversal attempt rejected: ${skillId}`);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
// Validate against allowed pattern
|
|
77
|
+
if (!VALID_SKILL_ID.test(normalized)) {
|
|
78
|
+
console.warn(`[SkillRegistry] Invalid skill ID rejected: ${skillId}`);
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return normalized;
|
|
82
|
+
}
|
|
83
|
+
class SkillRegistry {
|
|
84
|
+
constructor(config) {
|
|
85
|
+
this.registryUrl = config?.registryUrl || DEFAULT_REGISTRY_URL;
|
|
86
|
+
this.managedSkillsDir =
|
|
87
|
+
config?.managedSkillsDir ||
|
|
88
|
+
path.join(electron_1.app.getPath('userData'), SKILLS_FOLDER_NAME);
|
|
89
|
+
// Ensure managed skills directory exists
|
|
90
|
+
this.ensureSkillsDirectory();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Ensure the managed skills directory exists
|
|
94
|
+
*/
|
|
95
|
+
ensureSkillsDirectory() {
|
|
96
|
+
if (!fs.existsSync(this.managedSkillsDir)) {
|
|
97
|
+
fs.mkdirSync(this.managedSkillsDir, { recursive: true });
|
|
98
|
+
console.log(`[SkillRegistry] Created managed skills directory: ${this.managedSkillsDir}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get the managed skills directory path
|
|
103
|
+
*/
|
|
104
|
+
getManagedSkillsDir() {
|
|
105
|
+
return this.managedSkillsDir;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Search the registry for skills
|
|
109
|
+
*/
|
|
110
|
+
async search(query, options) {
|
|
111
|
+
const page = options?.page ?? 1;
|
|
112
|
+
const pageSize = options?.pageSize ?? 20;
|
|
113
|
+
try {
|
|
114
|
+
const url = new URL(`${this.registryUrl}/skills/search`);
|
|
115
|
+
url.searchParams.set('q', query);
|
|
116
|
+
url.searchParams.set('page', String(page));
|
|
117
|
+
url.searchParams.set('pageSize', String(pageSize));
|
|
118
|
+
const response = await fetch(url.toString());
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
throw new Error(`Registry search failed: ${response.status} ${response.statusText}`);
|
|
121
|
+
}
|
|
122
|
+
const data = await response.json();
|
|
123
|
+
return data;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error('[SkillRegistry] Search failed:', error);
|
|
127
|
+
// Return empty result on error
|
|
128
|
+
return {
|
|
129
|
+
query,
|
|
130
|
+
total: 0,
|
|
131
|
+
page,
|
|
132
|
+
pageSize,
|
|
133
|
+
results: [],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get skill details from registry
|
|
139
|
+
*/
|
|
140
|
+
async getSkillDetails(skillId) {
|
|
141
|
+
// Validate skill ID
|
|
142
|
+
const safeId = sanitizeSkillId(skillId);
|
|
143
|
+
if (!safeId) {
|
|
144
|
+
console.error(`[SkillRegistry] Invalid skill ID: ${skillId}`);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const response = await fetch(`${this.registryUrl}/skills/${safeId}`);
|
|
149
|
+
if (!response.ok) {
|
|
150
|
+
if (response.status === 404) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
throw new Error(`Failed to get skill details: ${response.status}`);
|
|
154
|
+
}
|
|
155
|
+
return (await response.json());
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.error(`[SkillRegistry] Failed to get skill ${skillId}:`, error);
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Install a skill from the registry
|
|
164
|
+
*/
|
|
165
|
+
async install(skillId, version, onProgress) {
|
|
166
|
+
// Validate skill ID before any operations
|
|
167
|
+
const safeId = sanitizeSkillId(skillId);
|
|
168
|
+
if (!safeId) {
|
|
169
|
+
return { success: false, error: `Invalid skill ID: ${skillId}` };
|
|
170
|
+
}
|
|
171
|
+
const notify = (progress) => {
|
|
172
|
+
onProgress?.({
|
|
173
|
+
skillId: safeId,
|
|
174
|
+
status: 'downloading',
|
|
175
|
+
...progress,
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
try {
|
|
179
|
+
notify({ status: 'downloading', progress: 0, message: 'Fetching skill from registry...' });
|
|
180
|
+
// Fetch skill data from registry
|
|
181
|
+
const url = version
|
|
182
|
+
? `${this.registryUrl}/skills/${safeId}/download?version=${version}`
|
|
183
|
+
: `${this.registryUrl}/skills/${safeId}/download`;
|
|
184
|
+
const response = await fetch(url);
|
|
185
|
+
if (!response.ok) {
|
|
186
|
+
throw new Error(`Failed to download skill: ${response.status} ${response.statusText}`);
|
|
187
|
+
}
|
|
188
|
+
notify({ status: 'downloading', progress: 50, message: 'Downloading skill data...' });
|
|
189
|
+
const skillData = await response.json();
|
|
190
|
+
notify({ status: 'extracting', progress: 70, message: 'Processing skill...' });
|
|
191
|
+
// Validate skill data
|
|
192
|
+
if (!this.validateSkillData(skillData)) {
|
|
193
|
+
throw new Error('Invalid skill data received from registry');
|
|
194
|
+
}
|
|
195
|
+
notify({ status: 'installing', progress: 80, message: 'Installing skill...' });
|
|
196
|
+
// Save skill to managed skills directory (using validated safeId)
|
|
197
|
+
const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
|
|
198
|
+
const skill = {
|
|
199
|
+
...skillData,
|
|
200
|
+
source: 'managed',
|
|
201
|
+
filePath: skillPath,
|
|
202
|
+
};
|
|
203
|
+
fs.writeFileSync(skillPath, JSON.stringify(skill, null, 2), 'utf-8');
|
|
204
|
+
notify({ status: 'completed', progress: 100, message: 'Skill installed successfully' });
|
|
205
|
+
console.log(`[SkillRegistry] Installed skill: ${safeId} at ${skillPath}`);
|
|
206
|
+
return { success: true, skill };
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
210
|
+
console.error(`[SkillRegistry] Install failed for ${safeId}:`, errorMessage);
|
|
211
|
+
notify({ status: 'failed', progress: 0, message: errorMessage, error: errorMessage });
|
|
212
|
+
return { success: false, error: errorMessage };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Update a managed skill to the latest version
|
|
217
|
+
*/
|
|
218
|
+
async update(skillId, version, onProgress) {
|
|
219
|
+
// Validate skill ID
|
|
220
|
+
const safeId = sanitizeSkillId(skillId);
|
|
221
|
+
if (!safeId) {
|
|
222
|
+
return { success: false, error: `Invalid skill ID: ${skillId}` };
|
|
223
|
+
}
|
|
224
|
+
// Check if skill is installed
|
|
225
|
+
const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
|
|
226
|
+
if (!fs.existsSync(skillPath)) {
|
|
227
|
+
return { success: false, error: `Skill ${safeId} is not installed` };
|
|
228
|
+
}
|
|
229
|
+
// Re-install with latest version
|
|
230
|
+
return this.install(safeId, version, onProgress);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Update all managed skills
|
|
234
|
+
*/
|
|
235
|
+
async updateAll(onProgress) {
|
|
236
|
+
const updated = [];
|
|
237
|
+
const failed = [];
|
|
238
|
+
const managedSkills = this.listManagedSkills();
|
|
239
|
+
for (const skill of managedSkills) {
|
|
240
|
+
const result = await this.update(skill.id, undefined, (progress) => {
|
|
241
|
+
onProgress?.(skill.id, progress);
|
|
242
|
+
});
|
|
243
|
+
if (result.success) {
|
|
244
|
+
updated.push(skill.id);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
failed.push(skill.id);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return { updated, failed };
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Uninstall a managed skill
|
|
254
|
+
*/
|
|
255
|
+
uninstall(skillId) {
|
|
256
|
+
// Validate skill ID
|
|
257
|
+
const safeId = sanitizeSkillId(skillId);
|
|
258
|
+
if (!safeId) {
|
|
259
|
+
return { success: false, error: `Invalid skill ID: ${skillId}` };
|
|
260
|
+
}
|
|
261
|
+
const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
|
|
262
|
+
if (!fs.existsSync(skillPath)) {
|
|
263
|
+
return { success: false, error: `Skill ${safeId} is not installed` };
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
fs.unlinkSync(skillPath);
|
|
267
|
+
console.log(`[SkillRegistry] Uninstalled skill: ${safeId}`);
|
|
268
|
+
return { success: true };
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
272
|
+
console.error(`[SkillRegistry] Uninstall failed for ${safeId}:`, errorMessage);
|
|
273
|
+
return { success: false, error: errorMessage };
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* List all managed (installed from registry) skills
|
|
278
|
+
*/
|
|
279
|
+
listManagedSkills() {
|
|
280
|
+
const skills = [];
|
|
281
|
+
if (!fs.existsSync(this.managedSkillsDir)) {
|
|
282
|
+
return skills;
|
|
283
|
+
}
|
|
284
|
+
const files = fs.readdirSync(this.managedSkillsDir);
|
|
285
|
+
for (const file of files) {
|
|
286
|
+
if (!file.endsWith('.json'))
|
|
287
|
+
continue;
|
|
288
|
+
try {
|
|
289
|
+
const filePath = path.join(this.managedSkillsDir, file);
|
|
290
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
291
|
+
const skill = JSON.parse(content);
|
|
292
|
+
skill.filePath = filePath;
|
|
293
|
+
skill.source = 'managed';
|
|
294
|
+
skills.push(skill);
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
console.error(`[SkillRegistry] Failed to load managed skill ${file}:`, error);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return skills;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Check if a skill is installed
|
|
304
|
+
*/
|
|
305
|
+
isInstalled(skillId) {
|
|
306
|
+
// Validate skill ID
|
|
307
|
+
const safeId = sanitizeSkillId(skillId);
|
|
308
|
+
if (!safeId) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
|
|
312
|
+
return fs.existsSync(skillPath);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get installed skill version
|
|
316
|
+
*/
|
|
317
|
+
getInstalledVersion(skillId) {
|
|
318
|
+
// Validate skill ID
|
|
319
|
+
const safeId = sanitizeSkillId(skillId);
|
|
320
|
+
if (!safeId) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
const skillPath = path.join(this.managedSkillsDir, `${safeId}.json`);
|
|
324
|
+
if (!fs.existsSync(skillPath)) {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
try {
|
|
328
|
+
const content = fs.readFileSync(skillPath, 'utf-8');
|
|
329
|
+
const skill = JSON.parse(content);
|
|
330
|
+
return skill.metadata?.version || null;
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Check for available updates
|
|
338
|
+
*/
|
|
339
|
+
async checkForUpdates(skillId) {
|
|
340
|
+
// Validate skill ID (getInstalledVersion and getSkillDetails also validate, but check early)
|
|
341
|
+
const safeId = sanitizeSkillId(skillId);
|
|
342
|
+
if (!safeId) {
|
|
343
|
+
return { hasUpdate: false, currentVersion: null, latestVersion: null };
|
|
344
|
+
}
|
|
345
|
+
const currentVersion = this.getInstalledVersion(safeId);
|
|
346
|
+
const details = await this.getSkillDetails(safeId);
|
|
347
|
+
if (!details) {
|
|
348
|
+
return { hasUpdate: false, currentVersion, latestVersion: null };
|
|
349
|
+
}
|
|
350
|
+
const hasUpdate = currentVersion !== details.version;
|
|
351
|
+
return {
|
|
352
|
+
hasUpdate,
|
|
353
|
+
currentVersion,
|
|
354
|
+
latestVersion: details.version,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Validate skill data from registry
|
|
359
|
+
*/
|
|
360
|
+
validateSkillData(data) {
|
|
361
|
+
if (!data || typeof data !== 'object')
|
|
362
|
+
return false;
|
|
363
|
+
const skill = data;
|
|
364
|
+
return (typeof skill.id === 'string' &&
|
|
365
|
+
typeof skill.name === 'string' &&
|
|
366
|
+
typeof skill.description === 'string' &&
|
|
367
|
+
typeof skill.prompt === 'string');
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Update registry URL
|
|
371
|
+
*/
|
|
372
|
+
setRegistryUrl(url) {
|
|
373
|
+
this.registryUrl = url;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Get current registry URL
|
|
377
|
+
*/
|
|
378
|
+
getRegistryUrl() {
|
|
379
|
+
return this.registryUrl;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
exports.SkillRegistry = SkillRegistry;
|
|
383
|
+
// Singleton instance
|
|
384
|
+
let instance = null;
|
|
385
|
+
function getSkillRegistry(config) {
|
|
386
|
+
if (!instance) {
|
|
387
|
+
instance = new SkillRegistry(config);
|
|
388
|
+
}
|
|
389
|
+
return instance;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Reset the singleton instance (useful for testing)
|
|
393
|
+
*/
|
|
394
|
+
function resetSkillRegistry() {
|
|
395
|
+
instance = null;
|
|
396
|
+
}
|