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,410 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SandboxRunner - Secure execution environment for shell commands
|
|
4
|
+
*
|
|
5
|
+
* This file maintains backward compatibility by re-exporting the refactored sandbox system.
|
|
6
|
+
*
|
|
7
|
+
* The sandbox system now supports:
|
|
8
|
+
* - macOS sandbox-exec profiles (native, preferred on macOS)
|
|
9
|
+
* - Docker containers (cross-platform, Linux/Windows)
|
|
10
|
+
* - No sandbox fallback (with timeout and output limits)
|
|
11
|
+
*
|
|
12
|
+
* Use createSandbox() from sandbox-factory.ts for new code.
|
|
13
|
+
*/
|
|
14
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
17
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
18
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
19
|
+
}
|
|
20
|
+
Object.defineProperty(o, k2, desc);
|
|
21
|
+
}) : (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
o[k2] = m[k];
|
|
24
|
+
}));
|
|
25
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
26
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
27
|
+
}) : function(o, v) {
|
|
28
|
+
o["default"] = v;
|
|
29
|
+
});
|
|
30
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
31
|
+
var ownKeys = function(o) {
|
|
32
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
33
|
+
var ar = [];
|
|
34
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
35
|
+
return ar;
|
|
36
|
+
};
|
|
37
|
+
return ownKeys(o);
|
|
38
|
+
};
|
|
39
|
+
return function (mod) {
|
|
40
|
+
if (mod && mod.__esModule) return mod;
|
|
41
|
+
var result = {};
|
|
42
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
43
|
+
__setModuleDefault(result, mod);
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
})();
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.SandboxRunner = exports.DockerSandbox = exports.MacOSSandbox = exports.NoSandbox = exports.isDockerAvailable = exports.detectAvailableSandbox = exports.createSandbox = void 0;
|
|
49
|
+
exports.createSandboxRunner = createSandboxRunner;
|
|
50
|
+
// Re-export the sandbox factory and types for backward compatibility
|
|
51
|
+
// Note: SandboxOptions and SandboxResult are defined locally below to avoid conflicts
|
|
52
|
+
var sandbox_factory_1 = require("./sandbox-factory");
|
|
53
|
+
Object.defineProperty(exports, "createSandbox", { enumerable: true, get: function () { return sandbox_factory_1.createSandbox; } });
|
|
54
|
+
Object.defineProperty(exports, "detectAvailableSandbox", { enumerable: true, get: function () { return sandbox_factory_1.detectAvailableSandbox; } });
|
|
55
|
+
Object.defineProperty(exports, "isDockerAvailable", { enumerable: true, get: function () { return sandbox_factory_1.isDockerAvailable; } });
|
|
56
|
+
Object.defineProperty(exports, "NoSandbox", { enumerable: true, get: function () { return sandbox_factory_1.NoSandbox; } });
|
|
57
|
+
var macos_sandbox_1 = require("./macos-sandbox");
|
|
58
|
+
Object.defineProperty(exports, "MacOSSandbox", { enumerable: true, get: function () { return macos_sandbox_1.MacOSSandbox; } });
|
|
59
|
+
var docker_sandbox_1 = require("./docker-sandbox");
|
|
60
|
+
Object.defineProperty(exports, "DockerSandbox", { enumerable: true, get: function () { return docker_sandbox_1.DockerSandbox; } });
|
|
61
|
+
const child_process_1 = require("child_process");
|
|
62
|
+
const path = __importStar(require("path"));
|
|
63
|
+
const fs = __importStar(require("fs"));
|
|
64
|
+
const os = __importStar(require("os"));
|
|
65
|
+
/**
|
|
66
|
+
* Default sandbox options
|
|
67
|
+
*/
|
|
68
|
+
const DEFAULT_OPTIONS = {
|
|
69
|
+
cwd: process.cwd(),
|
|
70
|
+
timeout: 5 * 60 * 1000, // 5 minutes
|
|
71
|
+
maxOutputSize: 100 * 1024, // 100KB
|
|
72
|
+
allowNetwork: false,
|
|
73
|
+
allowedReadPaths: [],
|
|
74
|
+
allowedWritePaths: [],
|
|
75
|
+
envPassthrough: ['PATH', 'HOME', 'USER', 'SHELL', 'LANG', 'TERM', 'TMPDIR'],
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* SandboxRunner manages secure command execution
|
|
79
|
+
*/
|
|
80
|
+
class SandboxRunner {
|
|
81
|
+
constructor(workspace) {
|
|
82
|
+
this.workspace = workspace;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Initialize sandbox environment
|
|
86
|
+
*/
|
|
87
|
+
async initialize() {
|
|
88
|
+
// Generate sandbox profile for this workspace
|
|
89
|
+
this.sandboxProfile = this.generateSandboxProfile();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Execute a command in the sandbox
|
|
93
|
+
*/
|
|
94
|
+
async execute(command, args = [], options = {}) {
|
|
95
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
96
|
+
// Determine working directory
|
|
97
|
+
const cwd = opts.cwd || this.workspace.path;
|
|
98
|
+
// Validate working directory is within allowed paths
|
|
99
|
+
if (!this.isPathAllowed(cwd, 'read')) {
|
|
100
|
+
return {
|
|
101
|
+
exitCode: 1,
|
|
102
|
+
stdout: '',
|
|
103
|
+
stderr: `Working directory not allowed: ${cwd}`,
|
|
104
|
+
killed: false,
|
|
105
|
+
timedOut: false,
|
|
106
|
+
error: 'Path access denied',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// Build minimal, safe environment
|
|
110
|
+
const env = this.buildSafeEnvironment(opts.envPassthrough);
|
|
111
|
+
// Check if we can use macOS sandbox-exec
|
|
112
|
+
const useSandboxExec = process.platform === 'darwin' && this.sandboxProfile;
|
|
113
|
+
let proc;
|
|
114
|
+
const spawnOptions = {
|
|
115
|
+
cwd,
|
|
116
|
+
env,
|
|
117
|
+
shell: true,
|
|
118
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
119
|
+
};
|
|
120
|
+
if (useSandboxExec && this.sandboxProfile) {
|
|
121
|
+
// Use sandbox-exec on macOS
|
|
122
|
+
const profilePath = this.writeTempProfile();
|
|
123
|
+
proc = (0, child_process_1.spawn)('sandbox-exec', ['-f', profilePath, '/bin/sh', '-c', `${command} ${args.join(' ')}`], spawnOptions);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// Fallback: execute without OS-level sandboxing (still has resource limits)
|
|
127
|
+
proc = (0, child_process_1.spawn)('/bin/sh', ['-c', `${command} ${args.join(' ')}`], spawnOptions);
|
|
128
|
+
}
|
|
129
|
+
return new Promise((resolve) => {
|
|
130
|
+
let stdout = '';
|
|
131
|
+
let stderr = '';
|
|
132
|
+
let killed = false;
|
|
133
|
+
let timedOut = false;
|
|
134
|
+
// Timeout handler
|
|
135
|
+
const timeoutHandle = setTimeout(() => {
|
|
136
|
+
timedOut = true;
|
|
137
|
+
killed = true;
|
|
138
|
+
proc.kill('SIGKILL');
|
|
139
|
+
}, opts.timeout);
|
|
140
|
+
// Collect stdout
|
|
141
|
+
proc.stdout?.on('data', (data) => {
|
|
142
|
+
const chunk = data.toString();
|
|
143
|
+
if (stdout.length + chunk.length <= opts.maxOutputSize) {
|
|
144
|
+
stdout += chunk;
|
|
145
|
+
}
|
|
146
|
+
else if (stdout.length < opts.maxOutputSize) {
|
|
147
|
+
stdout += chunk.slice(0, opts.maxOutputSize - stdout.length);
|
|
148
|
+
stdout += '\n[Output truncated]';
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
// Collect stderr
|
|
152
|
+
proc.stderr?.on('data', (data) => {
|
|
153
|
+
const chunk = data.toString();
|
|
154
|
+
if (stderr.length + chunk.length <= opts.maxOutputSize) {
|
|
155
|
+
stderr += chunk;
|
|
156
|
+
}
|
|
157
|
+
else if (stderr.length < opts.maxOutputSize) {
|
|
158
|
+
stderr += chunk.slice(0, opts.maxOutputSize - stderr.length);
|
|
159
|
+
stderr += '\n[Output truncated]';
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
// Process completion
|
|
163
|
+
proc.on('close', (code) => {
|
|
164
|
+
clearTimeout(timeoutHandle);
|
|
165
|
+
resolve({
|
|
166
|
+
exitCode: code ?? 1,
|
|
167
|
+
stdout,
|
|
168
|
+
stderr,
|
|
169
|
+
killed,
|
|
170
|
+
timedOut,
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
// Process error
|
|
174
|
+
proc.on('error', (err) => {
|
|
175
|
+
clearTimeout(timeoutHandle);
|
|
176
|
+
resolve({
|
|
177
|
+
exitCode: 1,
|
|
178
|
+
stdout,
|
|
179
|
+
stderr: err.message,
|
|
180
|
+
killed,
|
|
181
|
+
timedOut,
|
|
182
|
+
error: err.message,
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Execute code in sandbox (for future scripting support)
|
|
189
|
+
*/
|
|
190
|
+
async executeCode(code, language) {
|
|
191
|
+
// Create temp file with code
|
|
192
|
+
const ext = language === 'python' ? '.py' : '.js';
|
|
193
|
+
const tempFile = path.join(os.tmpdir(), `cowork_script_${Date.now()}${ext}`);
|
|
194
|
+
try {
|
|
195
|
+
fs.writeFileSync(tempFile, code, 'utf8');
|
|
196
|
+
const interpreter = language === 'python' ? 'python3' : 'node';
|
|
197
|
+
return await this.execute(interpreter, [tempFile], {
|
|
198
|
+
timeout: 60 * 1000, // 1 minute for scripts
|
|
199
|
+
allowNetwork: false,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
finally {
|
|
203
|
+
// Cleanup temp file
|
|
204
|
+
try {
|
|
205
|
+
fs.unlinkSync(tempFile);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
// Ignore cleanup errors
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Cleanup sandbox resources
|
|
214
|
+
*/
|
|
215
|
+
cleanup() {
|
|
216
|
+
// Clean up any temp files or resources
|
|
217
|
+
this.sandboxProfile = undefined;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Check if a path is allowed based on workspace permissions
|
|
221
|
+
*/
|
|
222
|
+
isPathAllowed(targetPath, mode) {
|
|
223
|
+
const normalizedTarget = path.resolve(targetPath);
|
|
224
|
+
const normalizedWorkspace = path.resolve(this.workspace.path);
|
|
225
|
+
// Always allow paths within workspace
|
|
226
|
+
if (normalizedTarget.startsWith(normalizedWorkspace)) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
// Check unrestricted access
|
|
230
|
+
if (this.workspace.permissions.unrestrictedFileAccess) {
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
// Check allowed paths
|
|
234
|
+
const allowedPaths = this.workspace.permissions.allowedPaths || [];
|
|
235
|
+
for (const allowed of allowedPaths) {
|
|
236
|
+
const normalizedAllowed = path.resolve(allowed);
|
|
237
|
+
if (normalizedTarget.startsWith(normalizedAllowed)) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// System paths for read-only access
|
|
242
|
+
if (mode === 'read') {
|
|
243
|
+
const systemReadPaths = [
|
|
244
|
+
'/usr/bin',
|
|
245
|
+
'/usr/local/bin',
|
|
246
|
+
'/bin',
|
|
247
|
+
'/usr/lib',
|
|
248
|
+
'/System',
|
|
249
|
+
os.tmpdir(),
|
|
250
|
+
];
|
|
251
|
+
for (const sysPath of systemReadPaths) {
|
|
252
|
+
if (normalizedTarget.startsWith(sysPath)) {
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Build a minimal, safe environment for command execution
|
|
261
|
+
*/
|
|
262
|
+
buildSafeEnvironment(passthrough) {
|
|
263
|
+
const safeEnv = {};
|
|
264
|
+
// Only pass through allowed environment variables
|
|
265
|
+
for (const key of passthrough) {
|
|
266
|
+
if (process.env[key]) {
|
|
267
|
+
safeEnv[key] = process.env[key];
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Set safe defaults
|
|
271
|
+
safeEnv.HOME = process.env.HOME || os.homedir();
|
|
272
|
+
safeEnv.USER = process.env.USER || os.userInfo().username;
|
|
273
|
+
safeEnv.SHELL = process.env.SHELL || '/bin/bash';
|
|
274
|
+
safeEnv.TERM = 'xterm-256color';
|
|
275
|
+
safeEnv.LANG = process.env.LANG || 'en_US.UTF-8';
|
|
276
|
+
safeEnv.TMPDIR = os.tmpdir();
|
|
277
|
+
// Minimal PATH with only standard locations
|
|
278
|
+
safeEnv.PATH = [
|
|
279
|
+
'/usr/local/bin',
|
|
280
|
+
'/usr/bin',
|
|
281
|
+
'/bin',
|
|
282
|
+
'/usr/sbin',
|
|
283
|
+
'/sbin',
|
|
284
|
+
].join(':');
|
|
285
|
+
// Add homebrew paths on macOS
|
|
286
|
+
if (process.platform === 'darwin') {
|
|
287
|
+
safeEnv.PATH = `/opt/homebrew/bin:/opt/homebrew/sbin:${safeEnv.PATH}`;
|
|
288
|
+
}
|
|
289
|
+
return safeEnv;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Generate macOS sandbox-exec profile
|
|
293
|
+
*/
|
|
294
|
+
generateSandboxProfile() {
|
|
295
|
+
const workspacePath = this.workspace.path;
|
|
296
|
+
const permissions = this.workspace.permissions;
|
|
297
|
+
const tempDir = os.tmpdir();
|
|
298
|
+
const homeDir = os.homedir();
|
|
299
|
+
let profile = `(version 1)
|
|
300
|
+
(deny default)
|
|
301
|
+
|
|
302
|
+
; Allow basic process operations
|
|
303
|
+
(allow process-fork)
|
|
304
|
+
(allow process-exec)
|
|
305
|
+
(allow signal)
|
|
306
|
+
|
|
307
|
+
; Allow sysctl for system info
|
|
308
|
+
(allow sysctl-read)
|
|
309
|
+
|
|
310
|
+
; Allow reading system libraries and binaries
|
|
311
|
+
(allow file-read*
|
|
312
|
+
(subpath "/usr/lib")
|
|
313
|
+
(subpath "/usr/bin")
|
|
314
|
+
(subpath "/bin")
|
|
315
|
+
(subpath "/usr/local")
|
|
316
|
+
(subpath "/System")
|
|
317
|
+
(subpath "/Library/Frameworks")
|
|
318
|
+
(subpath "/Applications/Xcode.app")
|
|
319
|
+
(subpath "/private/var/db")
|
|
320
|
+
(literal "/dev/null")
|
|
321
|
+
(literal "/dev/urandom")
|
|
322
|
+
(literal "/dev/random")
|
|
323
|
+
(subpath "/private/tmp")
|
|
324
|
+
(subpath "${tempDir}")
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
; Allow homebrew on macOS
|
|
328
|
+
(allow file-read* (subpath "/opt/homebrew"))
|
|
329
|
+
|
|
330
|
+
; Allow reading workspace
|
|
331
|
+
(allow file-read* (subpath "${workspacePath}"))
|
|
332
|
+
`;
|
|
333
|
+
// Allow writing to workspace if permitted
|
|
334
|
+
if (permissions.write) {
|
|
335
|
+
profile += `
|
|
336
|
+
; Allow writing to workspace
|
|
337
|
+
(allow file-write* (subpath "${workspacePath}"))
|
|
338
|
+
`;
|
|
339
|
+
}
|
|
340
|
+
// Allow writing to temp directories
|
|
341
|
+
profile += `
|
|
342
|
+
; Allow writing to temp directories
|
|
343
|
+
(allow file-write*
|
|
344
|
+
(subpath "/private/tmp")
|
|
345
|
+
(subpath "${tempDir}")
|
|
346
|
+
(subpath "/private/var/folders")
|
|
347
|
+
)
|
|
348
|
+
`;
|
|
349
|
+
// Allow network if permitted
|
|
350
|
+
if (permissions.network) {
|
|
351
|
+
profile += `
|
|
352
|
+
; Allow network access
|
|
353
|
+
(allow network*)
|
|
354
|
+
`;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
profile += `
|
|
358
|
+
; Deny network access (except localhost)
|
|
359
|
+
(deny network*)
|
|
360
|
+
(allow network* (local ip "localhost:*"))
|
|
361
|
+
`;
|
|
362
|
+
}
|
|
363
|
+
// Allow additional read paths
|
|
364
|
+
const allowedPaths = permissions.allowedPaths || [];
|
|
365
|
+
for (const allowedPath of allowedPaths) {
|
|
366
|
+
profile += `(allow file-read* (subpath "${allowedPath}"))\n`;
|
|
367
|
+
if (permissions.write) {
|
|
368
|
+
profile += `(allow file-write* (subpath "${allowedPath}"))\n`;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
// Allow mach services needed for basic operation
|
|
372
|
+
profile += `
|
|
373
|
+
; Allow essential mach services
|
|
374
|
+
(allow mach-lookup
|
|
375
|
+
(global-name "com.apple.CoreServices.coreservicesd")
|
|
376
|
+
(global-name "com.apple.SecurityServer")
|
|
377
|
+
(global-name "com.apple.system.logger")
|
|
378
|
+
(global-name "com.apple.cfprefsd.daemon")
|
|
379
|
+
(global-name "com.apple.cfprefsd.agent")
|
|
380
|
+
)
|
|
381
|
+
`;
|
|
382
|
+
return profile;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Write sandbox profile to temp file
|
|
386
|
+
*/
|
|
387
|
+
writeTempProfile() {
|
|
388
|
+
const profilePath = path.join(os.tmpdir(), `cowork_sandbox_${Date.now()}.sb`);
|
|
389
|
+
fs.writeFileSync(profilePath, this.sandboxProfile, 'utf8');
|
|
390
|
+
// Schedule cleanup
|
|
391
|
+
setTimeout(() => {
|
|
392
|
+
try {
|
|
393
|
+
fs.unlinkSync(profilePath);
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
// Ignore cleanup errors
|
|
397
|
+
}
|
|
398
|
+
}, 60 * 1000); // Clean up after 1 minute
|
|
399
|
+
return profilePath;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
exports.SandboxRunner = SandboxRunner;
|
|
403
|
+
/**
|
|
404
|
+
* Create a sandboxed command executor for a workspace
|
|
405
|
+
*/
|
|
406
|
+
async function createSandboxRunner(workspace) {
|
|
407
|
+
const runner = new SandboxRunner(workspace);
|
|
408
|
+
await runner.initialize();
|
|
409
|
+
return runner;
|
|
410
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sandbox Factory
|
|
4
|
+
*
|
|
5
|
+
* Provides a unified interface for sandbox implementations and factory
|
|
6
|
+
* function to create the appropriate sandbox based on platform and availability.
|
|
7
|
+
*
|
|
8
|
+
* Supports:
|
|
9
|
+
* - macOS sandbox-exec (native, preferred on macOS)
|
|
10
|
+
* - Docker containers (cross-platform)
|
|
11
|
+
* - No sandbox (fallback)
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.NoSandbox = void 0;
|
|
15
|
+
exports.isDockerAvailable = isDockerAvailable;
|
|
16
|
+
exports.detectAvailableSandbox = detectAvailableSandbox;
|
|
17
|
+
exports.createSandbox = createSandbox;
|
|
18
|
+
exports.resetDockerCache = resetDockerCache;
|
|
19
|
+
const macos_sandbox_1 = require("./macos-sandbox");
|
|
20
|
+
const docker_sandbox_1 = require("./docker-sandbox");
|
|
21
|
+
const child_process_1 = require("child_process");
|
|
22
|
+
const security_utils_1 = require("./security-utils");
|
|
23
|
+
/**
|
|
24
|
+
* No-op sandbox implementation for when sandboxing is unavailable
|
|
25
|
+
* Still enforces timeouts and output limits, but no OS-level isolation
|
|
26
|
+
*/
|
|
27
|
+
class NoSandbox {
|
|
28
|
+
constructor(workspace) {
|
|
29
|
+
this.type = 'none';
|
|
30
|
+
this.workspace = workspace;
|
|
31
|
+
}
|
|
32
|
+
async initialize() {
|
|
33
|
+
// No initialization needed
|
|
34
|
+
}
|
|
35
|
+
async execute(command, args = [], options = {}) {
|
|
36
|
+
const timeout = options.timeout ?? 5 * 60 * 1000;
|
|
37
|
+
const maxOutputSize = options.maxOutputSize ?? 100 * 1024;
|
|
38
|
+
const cwd = options.cwd || this.workspace.path;
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
let stdout = '';
|
|
41
|
+
let stderr = '';
|
|
42
|
+
let killed = false;
|
|
43
|
+
let timedOut = false;
|
|
44
|
+
const proc = (0, child_process_1.spawn)('/bin/sh', ['-c', `${command} ${args.join(' ')}`], {
|
|
45
|
+
cwd,
|
|
46
|
+
shell: true,
|
|
47
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
48
|
+
});
|
|
49
|
+
const timeoutHandle = setTimeout(() => {
|
|
50
|
+
timedOut = true;
|
|
51
|
+
killed = true;
|
|
52
|
+
proc.kill('SIGKILL');
|
|
53
|
+
}, timeout);
|
|
54
|
+
proc.stdout?.on('data', (data) => {
|
|
55
|
+
const chunk = data.toString();
|
|
56
|
+
if (stdout.length + chunk.length <= maxOutputSize) {
|
|
57
|
+
stdout += chunk;
|
|
58
|
+
}
|
|
59
|
+
else if (stdout.length < maxOutputSize) {
|
|
60
|
+
stdout += chunk.slice(0, maxOutputSize - stdout.length);
|
|
61
|
+
stdout += '\n[Output truncated]';
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
proc.stderr?.on('data', (data) => {
|
|
65
|
+
const chunk = data.toString();
|
|
66
|
+
if (stderr.length + chunk.length <= maxOutputSize) {
|
|
67
|
+
stderr += chunk;
|
|
68
|
+
}
|
|
69
|
+
else if (stderr.length < maxOutputSize) {
|
|
70
|
+
stderr += chunk.slice(0, maxOutputSize - stderr.length);
|
|
71
|
+
stderr += '\n[Output truncated]';
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
proc.on('close', (code) => {
|
|
75
|
+
clearTimeout(timeoutHandle);
|
|
76
|
+
resolve({
|
|
77
|
+
exitCode: code ?? 1,
|
|
78
|
+
stdout,
|
|
79
|
+
stderr,
|
|
80
|
+
killed,
|
|
81
|
+
timedOut,
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
proc.on('error', (err) => {
|
|
85
|
+
clearTimeout(timeoutHandle);
|
|
86
|
+
resolve({
|
|
87
|
+
exitCode: 1,
|
|
88
|
+
stdout,
|
|
89
|
+
stderr: err.message,
|
|
90
|
+
killed,
|
|
91
|
+
timedOut,
|
|
92
|
+
error: err.message,
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
async executeCode(code, language) {
|
|
98
|
+
const ext = language === 'python' ? '.py' : '.js';
|
|
99
|
+
const { filePath, cleanup } = (0, security_utils_1.createSecureTempFile)(ext, code);
|
|
100
|
+
try {
|
|
101
|
+
const interpreter = language === 'python' ? 'python3' : 'node';
|
|
102
|
+
return await this.execute(interpreter, [filePath], {
|
|
103
|
+
timeout: 60 * 1000,
|
|
104
|
+
allowNetwork: false,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
cleanup();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
cleanup() {
|
|
112
|
+
// No cleanup needed
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.NoSandbox = NoSandbox;
|
|
116
|
+
/**
|
|
117
|
+
* Cached Docker availability status
|
|
118
|
+
*/
|
|
119
|
+
let dockerAvailable = null;
|
|
120
|
+
let dockerCheckPromise = null;
|
|
121
|
+
/**
|
|
122
|
+
* Check if Docker is available and running
|
|
123
|
+
*/
|
|
124
|
+
async function isDockerAvailable() {
|
|
125
|
+
// Return cached result if available
|
|
126
|
+
if (dockerAvailable !== null) {
|
|
127
|
+
return dockerAvailable;
|
|
128
|
+
}
|
|
129
|
+
// Return existing promise if check is in progress
|
|
130
|
+
if (dockerCheckPromise) {
|
|
131
|
+
return dockerCheckPromise;
|
|
132
|
+
}
|
|
133
|
+
dockerCheckPromise = new Promise((resolve) => {
|
|
134
|
+
const proc = (0, child_process_1.spawn)('docker', ['info'], {
|
|
135
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
136
|
+
});
|
|
137
|
+
let resolved = false;
|
|
138
|
+
const timeout = setTimeout(() => {
|
|
139
|
+
if (!resolved) {
|
|
140
|
+
resolved = true;
|
|
141
|
+
proc.kill();
|
|
142
|
+
dockerAvailable = false;
|
|
143
|
+
resolve(false);
|
|
144
|
+
}
|
|
145
|
+
}, 5000);
|
|
146
|
+
proc.on('close', (code) => {
|
|
147
|
+
clearTimeout(timeout);
|
|
148
|
+
if (!resolved) {
|
|
149
|
+
resolved = true;
|
|
150
|
+
dockerAvailable = code === 0;
|
|
151
|
+
resolve(dockerAvailable);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
proc.on('error', () => {
|
|
155
|
+
clearTimeout(timeout);
|
|
156
|
+
if (!resolved) {
|
|
157
|
+
resolved = true;
|
|
158
|
+
dockerAvailable = false;
|
|
159
|
+
resolve(false);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
return dockerCheckPromise;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Detect the best available sandbox type for the current platform
|
|
167
|
+
*/
|
|
168
|
+
async function detectAvailableSandbox() {
|
|
169
|
+
// On macOS, prefer native sandbox-exec
|
|
170
|
+
if (process.platform === 'darwin') {
|
|
171
|
+
return 'macos';
|
|
172
|
+
}
|
|
173
|
+
// On other platforms, check for Docker
|
|
174
|
+
if (await isDockerAvailable()) {
|
|
175
|
+
return 'docker';
|
|
176
|
+
}
|
|
177
|
+
// Fallback to no sandbox
|
|
178
|
+
return 'none';
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Create a sandbox instance for the given workspace
|
|
182
|
+
*
|
|
183
|
+
* @param workspace - The workspace to create a sandbox for
|
|
184
|
+
* @param preferredType - Optional preferred sandbox type (overrides auto-detection)
|
|
185
|
+
* @returns An initialized sandbox instance
|
|
186
|
+
*/
|
|
187
|
+
async function createSandbox(workspace, preferredType) {
|
|
188
|
+
let sandboxType;
|
|
189
|
+
if (preferredType && preferredType !== 'auto') {
|
|
190
|
+
// Validate the preferred type is available
|
|
191
|
+
if (preferredType === 'macos' && process.platform !== 'darwin') {
|
|
192
|
+
console.warn('macOS sandbox requested but not on macOS, falling back to auto-detect');
|
|
193
|
+
sandboxType = await detectAvailableSandbox();
|
|
194
|
+
}
|
|
195
|
+
else if (preferredType === 'docker' && !(await isDockerAvailable())) {
|
|
196
|
+
console.warn('Docker sandbox requested but Docker not available, falling back to auto-detect');
|
|
197
|
+
sandboxType = await detectAvailableSandbox();
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
sandboxType = preferredType;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
sandboxType = await detectAvailableSandbox();
|
|
205
|
+
}
|
|
206
|
+
let sandbox;
|
|
207
|
+
switch (sandboxType) {
|
|
208
|
+
case 'macos':
|
|
209
|
+
sandbox = new macos_sandbox_1.MacOSSandbox(workspace);
|
|
210
|
+
break;
|
|
211
|
+
case 'docker':
|
|
212
|
+
sandbox = new docker_sandbox_1.DockerSandbox(workspace);
|
|
213
|
+
break;
|
|
214
|
+
case 'none':
|
|
215
|
+
default:
|
|
216
|
+
sandbox = new NoSandbox(workspace);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
await sandbox.initialize();
|
|
220
|
+
return sandbox;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Reset Docker availability cache (useful for testing or after Docker installation)
|
|
224
|
+
*/
|
|
225
|
+
function resetDockerCache() {
|
|
226
|
+
dockerAvailable = null;
|
|
227
|
+
dockerCheckPromise = null;
|
|
228
|
+
}
|