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,686 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import {
|
|
3
|
+
getModel,
|
|
4
|
+
getModels,
|
|
5
|
+
complete as piAiComplete,
|
|
6
|
+
type Model,
|
|
7
|
+
type Message as PiAiMessage,
|
|
8
|
+
type Context as PiAiContext,
|
|
9
|
+
type Tool as PiAiTool,
|
|
10
|
+
} from '@mariozechner/pi-ai';
|
|
11
|
+
import {
|
|
12
|
+
LLMProvider,
|
|
13
|
+
LLMProviderConfig,
|
|
14
|
+
LLMRequest,
|
|
15
|
+
LLMResponse,
|
|
16
|
+
LLMContent,
|
|
17
|
+
LLMMessage,
|
|
18
|
+
LLMTool,
|
|
19
|
+
LLMToolResult,
|
|
20
|
+
} from './types';
|
|
21
|
+
import { OpenAIOAuth, OpenAIOAuthTokens } from './openai-oauth';
|
|
22
|
+
|
|
23
|
+
// Default model for openai-codex (ChatGPT backend)
|
|
24
|
+
const DEFAULT_CODEX_MODEL = 'gpt-5.1-codex-mini';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* OpenAI API provider implementation
|
|
28
|
+
* Supports both API key and OAuth token authentication
|
|
29
|
+
* - API Key: Uses OpenAI SDK directly with api.openai.com
|
|
30
|
+
* - OAuth: Uses pi-ai SDK with ChatGPT backend (chatgpt.com/backend-api/)
|
|
31
|
+
*/
|
|
32
|
+
export class OpenAIProvider implements LLMProvider {
|
|
33
|
+
readonly type = 'openai' as const;
|
|
34
|
+
private client: OpenAI | null = null;
|
|
35
|
+
private authMethod: 'api_key' | 'oauth';
|
|
36
|
+
private oauthTokens?: OpenAIOAuthTokens;
|
|
37
|
+
private model: string;
|
|
38
|
+
|
|
39
|
+
constructor(config: LLMProviderConfig) {
|
|
40
|
+
const apiKey = config.openaiApiKey;
|
|
41
|
+
const accessToken = config.openaiAccessToken;
|
|
42
|
+
const refreshToken = config.openaiRefreshToken;
|
|
43
|
+
const tokenExpiresAt = config.openaiTokenExpiresAt;
|
|
44
|
+
this.model = config.model;
|
|
45
|
+
|
|
46
|
+
if (accessToken && refreshToken) {
|
|
47
|
+
// Use OAuth - will use pi-ai SDK for API calls
|
|
48
|
+
this.oauthTokens = {
|
|
49
|
+
access_token: accessToken,
|
|
50
|
+
refresh_token: refreshToken,
|
|
51
|
+
expires_at: tokenExpiresAt || 0, // Use stored expiry or 0 if not available
|
|
52
|
+
};
|
|
53
|
+
this.authMethod = 'oauth';
|
|
54
|
+
console.log(`[OpenAI] Using OAuth authentication with pi-ai SDK (token expires: ${tokenExpiresAt ? new Date(tokenExpiresAt).toISOString() : 'unknown'})`);
|
|
55
|
+
} else if (apiKey) {
|
|
56
|
+
// Use API key - standard OpenAI SDK
|
|
57
|
+
this.client = new OpenAI({ apiKey });
|
|
58
|
+
this.authMethod = 'api_key';
|
|
59
|
+
console.log('[OpenAI] Using API key authentication');
|
|
60
|
+
} else {
|
|
61
|
+
throw new Error('OpenAI authentication required. Use API key or sign in with ChatGPT.');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async createMessage(request: LLMRequest): Promise<LLMResponse> {
|
|
66
|
+
if (this.authMethod === 'oauth') {
|
|
67
|
+
return this.createMessageWithOAuth(request);
|
|
68
|
+
} else {
|
|
69
|
+
return this.createMessageWithApiKey(request);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Create message using API key (standard OpenAI SDK)
|
|
75
|
+
*/
|
|
76
|
+
private async createMessageWithApiKey(request: LLMRequest): Promise<LLMResponse> {
|
|
77
|
+
if (!this.client) {
|
|
78
|
+
throw new Error('OpenAI client not initialized');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const messages = this.convertMessages(request.messages, request.system);
|
|
82
|
+
const tools = request.tools ? this.convertTools(request.tools) : undefined;
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
console.log(`[OpenAI] Calling API with model: ${request.model}`);
|
|
86
|
+
|
|
87
|
+
const response = await this.client.chat.completions.create(
|
|
88
|
+
{
|
|
89
|
+
model: request.model,
|
|
90
|
+
max_tokens: request.maxTokens,
|
|
91
|
+
messages,
|
|
92
|
+
...(tools && tools.length > 0 && { tools }),
|
|
93
|
+
},
|
|
94
|
+
request.signal ? { signal: request.signal } : undefined
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return this.convertResponse(response);
|
|
98
|
+
} catch (error: any) {
|
|
99
|
+
// Handle abort errors gracefully
|
|
100
|
+
if (error.name === 'AbortError' || error.message?.includes('aborted')) {
|
|
101
|
+
console.log(`[OpenAI] Request aborted`);
|
|
102
|
+
throw new Error('Request cancelled');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.error(`[OpenAI] API error:`, {
|
|
106
|
+
status: error.status,
|
|
107
|
+
message: error.message,
|
|
108
|
+
type: error.type || error.name,
|
|
109
|
+
});
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Map public model names to openai-codex model IDs
|
|
116
|
+
*/
|
|
117
|
+
private mapToCodexModel(modelId: string): string {
|
|
118
|
+
// Map common public model names to ChatGPT internal models
|
|
119
|
+
const modelMap: Record<string, string> = {
|
|
120
|
+
// Map gpt-4o models to gpt-5.1
|
|
121
|
+
'gpt-4o': 'gpt-5.1',
|
|
122
|
+
'gpt-4o-mini': 'gpt-5.1-codex-mini',
|
|
123
|
+
// Map o1/reasoning models to gpt-5.2
|
|
124
|
+
'o1': 'gpt-5.2',
|
|
125
|
+
'o1-mini': 'gpt-5.2-codex',
|
|
126
|
+
'o1-preview': 'gpt-5.2',
|
|
127
|
+
// Default mappings
|
|
128
|
+
'gpt-4-turbo': 'gpt-5.1',
|
|
129
|
+
'gpt-4': 'gpt-5.1',
|
|
130
|
+
'gpt-3.5-turbo': 'gpt-5.1-codex-mini',
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return modelMap[modelId] || modelId;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Create message using OAuth (pi-ai SDK with ChatGPT backend)
|
|
138
|
+
*/
|
|
139
|
+
private async createMessageWithOAuth(request: LLMRequest): Promise<LLMResponse> {
|
|
140
|
+
if (!this.oauthTokens) {
|
|
141
|
+
throw new Error('OAuth tokens not available');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
// Map model ID to ChatGPT internal model
|
|
146
|
+
const codexModelId = this.mapToCodexModel(request.model);
|
|
147
|
+
console.log(`[OpenAI] Calling ChatGPT backend with model: ${codexModelId} (requested: ${request.model})`);
|
|
148
|
+
|
|
149
|
+
// Get the model object from pi-ai SDK
|
|
150
|
+
let model: Model<any>;
|
|
151
|
+
try {
|
|
152
|
+
// Get available models and find one that matches
|
|
153
|
+
const availableModels = getModels('openai-codex');
|
|
154
|
+
const found = availableModels.find(m => m.id === codexModelId);
|
|
155
|
+
if (found) {
|
|
156
|
+
model = found;
|
|
157
|
+
} else {
|
|
158
|
+
// Use default if not found
|
|
159
|
+
console.log(`[OpenAI] Model ${codexModelId} not found, using default: ${DEFAULT_CODEX_MODEL}`);
|
|
160
|
+
model = availableModels.find(m => m.id === DEFAULT_CODEX_MODEL) || availableModels[0];
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
console.error('[OpenAI] Failed to get model from pi-ai SDK:', e);
|
|
164
|
+
throw new Error(`Model not available: ${codexModelId}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Convert messages to pi-ai format
|
|
168
|
+
const piAiMessages = this.convertMessagesToPiAi(request.messages);
|
|
169
|
+
|
|
170
|
+
// Convert tools to pi-ai format
|
|
171
|
+
const piAiTools = request.tools ? this.convertToolsToPiAi(request.tools) : undefined;
|
|
172
|
+
|
|
173
|
+
// Get API key from OAuth tokens (with auto-refresh)
|
|
174
|
+
const { apiKey, newTokens } = await OpenAIOAuth.getApiKeyFromTokens(this.oauthTokens);
|
|
175
|
+
|
|
176
|
+
// Update tokens if they were refreshed
|
|
177
|
+
if (newTokens) {
|
|
178
|
+
this.oauthTokens = newTokens;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Build context
|
|
182
|
+
const context: PiAiContext = {
|
|
183
|
+
systemPrompt: request.system,
|
|
184
|
+
messages: piAiMessages,
|
|
185
|
+
tools: piAiTools,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Make the API call using pi-ai SDK
|
|
189
|
+
const response = await piAiComplete(model, context, {
|
|
190
|
+
apiKey,
|
|
191
|
+
maxTokens: request.maxTokens,
|
|
192
|
+
signal: request.signal,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Convert pi-ai response to our format
|
|
196
|
+
return this.convertPiAiResponse(response);
|
|
197
|
+
} catch (error: any) {
|
|
198
|
+
// Handle abort errors gracefully
|
|
199
|
+
if (error.name === 'AbortError' || error.message?.includes('aborted')) {
|
|
200
|
+
console.log(`[OpenAI] Request aborted`);
|
|
201
|
+
throw new Error('Request cancelled');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
console.error(`[OpenAI] ChatGPT API error:`, {
|
|
205
|
+
message: error.message,
|
|
206
|
+
type: error.type || error.name,
|
|
207
|
+
});
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async testConnection(): Promise<{ success: boolean; error?: string }> {
|
|
213
|
+
try {
|
|
214
|
+
if (this.authMethod === 'oauth') {
|
|
215
|
+
// For OAuth, try to get the API key and make a simple request
|
|
216
|
+
if (!this.oauthTokens) {
|
|
217
|
+
return { success: false, error: 'OAuth tokens not available' };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const { apiKey } = await OpenAIOAuth.getApiKeyFromTokens(this.oauthTokens);
|
|
221
|
+
|
|
222
|
+
// Get a model from the available models
|
|
223
|
+
const availableModels = getModels('openai-codex');
|
|
224
|
+
const model = availableModels.find(m => m.id === DEFAULT_CODEX_MODEL) || availableModels[0];
|
|
225
|
+
|
|
226
|
+
await piAiComplete(
|
|
227
|
+
model,
|
|
228
|
+
{
|
|
229
|
+
messages: [{
|
|
230
|
+
role: 'user',
|
|
231
|
+
content: [{ type: 'text', text: 'Hi' }],
|
|
232
|
+
timestamp: Date.now(),
|
|
233
|
+
}],
|
|
234
|
+
},
|
|
235
|
+
{ apiKey, maxTokens: 10 }
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
return { success: true };
|
|
239
|
+
} else {
|
|
240
|
+
// For API key, use standard OpenAI SDK
|
|
241
|
+
if (!this.client) {
|
|
242
|
+
return { success: false, error: 'OpenAI client not initialized' };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
await this.client.chat.completions.create({
|
|
246
|
+
model: 'gpt-4o-mini',
|
|
247
|
+
max_tokens: 10,
|
|
248
|
+
messages: [{ role: 'user', content: 'Hi' }],
|
|
249
|
+
});
|
|
250
|
+
return { success: true };
|
|
251
|
+
}
|
|
252
|
+
} catch (error: any) {
|
|
253
|
+
return {
|
|
254
|
+
success: false,
|
|
255
|
+
error: error.message || 'Failed to connect to OpenAI API',
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Get available models
|
|
262
|
+
* For API key: uses the models.list API
|
|
263
|
+
* For OAuth: uses pi-ai SDK's model list for openai-codex provider
|
|
264
|
+
*/
|
|
265
|
+
async getAvailableModels(): Promise<Array<{ id: string; name: string; description: string }>> {
|
|
266
|
+
// For OAuth authentication, use pi-ai SDK's model list
|
|
267
|
+
if (this.authMethod === 'oauth') {
|
|
268
|
+
console.log('[OpenAI] Using OAuth - fetching models from pi-ai SDK...');
|
|
269
|
+
|
|
270
|
+
try {
|
|
271
|
+
// Get models from pi-ai SDK for openai-codex provider
|
|
272
|
+
const piAiModels = getModels('openai-codex');
|
|
273
|
+
|
|
274
|
+
const models = piAiModels.map((m) => ({
|
|
275
|
+
id: m.id,
|
|
276
|
+
name: m.name || this.formatModelName(m.id),
|
|
277
|
+
description: this.getModelDescription(m.id),
|
|
278
|
+
}));
|
|
279
|
+
|
|
280
|
+
// Sort by priority
|
|
281
|
+
models.sort((a, b) => {
|
|
282
|
+
const priority = (id: string) => {
|
|
283
|
+
if (id.includes('5.1-codex-mini')) return 0;
|
|
284
|
+
if (id.includes('5.1-codex-max')) return 1;
|
|
285
|
+
if (id === 'gpt-5.1') return 2;
|
|
286
|
+
if (id.includes('5.2-codex')) return 3;
|
|
287
|
+
if (id === 'gpt-5.2') return 4;
|
|
288
|
+
return 5;
|
|
289
|
+
};
|
|
290
|
+
return priority(a.id) - priority(b.id);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
console.log(`[OpenAI] Found ${models.length} models via pi-ai SDK`);
|
|
294
|
+
return models;
|
|
295
|
+
} catch (error) {
|
|
296
|
+
console.error('[OpenAI] Failed to get models from pi-ai SDK:', error);
|
|
297
|
+
// Return defaults on error
|
|
298
|
+
return this.getDefaultCodexModels();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// For API key authentication, use the standard models list API
|
|
303
|
+
if (this.client) {
|
|
304
|
+
try {
|
|
305
|
+
const response = await this.client.models.list();
|
|
306
|
+
const models = response.data
|
|
307
|
+
.filter((m) => m.id.startsWith('gpt-') || m.id.startsWith('o1') || m.id.startsWith('o3'))
|
|
308
|
+
.map((m) => ({
|
|
309
|
+
id: m.id,
|
|
310
|
+
name: this.formatModelName(m.id),
|
|
311
|
+
description: this.getModelDescription(m.id),
|
|
312
|
+
}))
|
|
313
|
+
.sort((a, b) => {
|
|
314
|
+
const priority = (id: string) => {
|
|
315
|
+
if (id.includes('gpt-4o')) return 0;
|
|
316
|
+
if (id.includes('gpt-4')) return 1;
|
|
317
|
+
if (id.includes('gpt-3.5')) return 2;
|
|
318
|
+
if (id.includes('o1')) return 3;
|
|
319
|
+
if (id.includes('o3')) return 4;
|
|
320
|
+
return 5;
|
|
321
|
+
};
|
|
322
|
+
return priority(a.id) - priority(b.id);
|
|
323
|
+
});
|
|
324
|
+
return models;
|
|
325
|
+
} catch (error: any) {
|
|
326
|
+
console.error('Failed to fetch OpenAI models:', error);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Return defaults if nothing else works
|
|
331
|
+
return this.getDefaultModels();
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
private getDefaultModels(): Array<{ id: string; name: string; description: string }> {
|
|
335
|
+
return [
|
|
336
|
+
{ id: 'gpt-4o', name: 'GPT-4o', description: 'Most capable model for complex tasks' },
|
|
337
|
+
{ id: 'gpt-4o-mini', name: 'GPT-4o Mini', description: 'Fast and affordable for most tasks' },
|
|
338
|
+
{ id: 'o1', name: 'o1', description: 'Advanced reasoning model' },
|
|
339
|
+
{ id: 'o1-mini', name: 'o1 Mini', description: 'Fast reasoning model' },
|
|
340
|
+
{ id: 'gpt-4-turbo', name: 'GPT-4 Turbo', description: 'Previous generation flagship' },
|
|
341
|
+
{ id: 'gpt-3.5-turbo', name: 'GPT-3.5 Turbo', description: 'Fast and cost-effective' },
|
|
342
|
+
];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
private getDefaultCodexModels(): Array<{ id: string; name: string; description: string }> {
|
|
346
|
+
return [
|
|
347
|
+
{ id: 'gpt-5.1-codex-mini', name: 'GPT-5.1 Codex Mini', description: 'Fast and efficient for most tasks' },
|
|
348
|
+
{ id: 'gpt-5.1-codex-max', name: 'GPT-5.1 Codex Max', description: 'Maximum capability for complex tasks' },
|
|
349
|
+
{ id: 'gpt-5.1', name: 'GPT-5.1', description: 'Balanced performance and capability' },
|
|
350
|
+
{ id: 'gpt-5.2-codex', name: 'GPT-5.2 Codex', description: 'Advanced reasoning model' },
|
|
351
|
+
{ id: 'gpt-5.2', name: 'GPT-5.2', description: 'Most advanced reasoning' },
|
|
352
|
+
];
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
private formatModelName(modelId: string): string {
|
|
356
|
+
// Format model ID to display name
|
|
357
|
+
if (modelId === 'gpt-4o') return 'GPT-4o';
|
|
358
|
+
if (modelId === 'gpt-4o-mini') return 'GPT-4o Mini';
|
|
359
|
+
if (modelId.includes('gpt-4o-')) return `GPT-4o (${modelId.replace('gpt-4o-', '')})`;
|
|
360
|
+
if (modelId === 'gpt-4-turbo') return 'GPT-4 Turbo';
|
|
361
|
+
if (modelId.includes('gpt-4-turbo-')) return `GPT-4 Turbo (${modelId.replace('gpt-4-turbo-', '')})`;
|
|
362
|
+
if (modelId === 'gpt-4') return 'GPT-4';
|
|
363
|
+
if (modelId.includes('gpt-4-')) return `GPT-4 (${modelId.replace('gpt-4-', '')})`;
|
|
364
|
+
if (modelId === 'gpt-3.5-turbo') return 'GPT-3.5 Turbo';
|
|
365
|
+
if (modelId.includes('gpt-3.5-turbo-')) return `GPT-3.5 Turbo (${modelId.replace('gpt-3.5-turbo-', '')})`;
|
|
366
|
+
if (modelId === 'o1') return 'o1';
|
|
367
|
+
if (modelId === 'o1-mini') return 'o1 Mini';
|
|
368
|
+
if (modelId === 'o1-preview') return 'o1 Preview';
|
|
369
|
+
if (modelId === 'o3-mini') return 'o3 Mini';
|
|
370
|
+
// ChatGPT internal models
|
|
371
|
+
if (modelId === 'gpt-5.1') return 'GPT-5.1';
|
|
372
|
+
if (modelId === 'gpt-5.1-codex-mini') return 'GPT-5.1 Codex Mini';
|
|
373
|
+
if (modelId === 'gpt-5.1-codex-max') return 'GPT-5.1 Codex Max';
|
|
374
|
+
if (modelId === 'gpt-5.2') return 'GPT-5.2';
|
|
375
|
+
if (modelId === 'gpt-5.2-codex') return 'GPT-5.2 Codex';
|
|
376
|
+
return modelId;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
private getModelDescription(modelId: string): string {
|
|
380
|
+
if (modelId.includes('gpt-4o') && !modelId.includes('mini')) return 'Most capable model for complex tasks';
|
|
381
|
+
if (modelId.includes('gpt-4o-mini')) return 'Fast and affordable for most tasks';
|
|
382
|
+
if (modelId.includes('gpt-4-turbo')) return 'Previous generation flagship';
|
|
383
|
+
if (modelId.includes('gpt-4')) return 'High capability model';
|
|
384
|
+
if (modelId.includes('gpt-3.5')) return 'Fast and cost-effective';
|
|
385
|
+
if (modelId === 'o1' || modelId === 'o1-preview') return 'Advanced reasoning model';
|
|
386
|
+
if (modelId === 'o1-mini') return 'Fast reasoning model';
|
|
387
|
+
if (modelId.includes('o3')) return 'Next generation reasoning';
|
|
388
|
+
// ChatGPT internal models
|
|
389
|
+
if (modelId === 'gpt-5.1') return 'Balanced performance and capability';
|
|
390
|
+
if (modelId === 'gpt-5.1-codex-mini') return 'Fast and efficient for most tasks';
|
|
391
|
+
if (modelId === 'gpt-5.1-codex-max') return 'Maximum capability for complex tasks';
|
|
392
|
+
if (modelId === 'gpt-5.2') return 'Most advanced reasoning';
|
|
393
|
+
if (modelId === 'gpt-5.2-codex') return 'Advanced reasoning model';
|
|
394
|
+
return 'OpenAI model';
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Convert messages to pi-ai SDK format
|
|
399
|
+
*/
|
|
400
|
+
private convertMessagesToPiAi(messages: LLMMessage[]): PiAiMessage[] {
|
|
401
|
+
const result: PiAiMessage[] = [];
|
|
402
|
+
const now = Date.now();
|
|
403
|
+
|
|
404
|
+
for (const msg of messages) {
|
|
405
|
+
if (typeof msg.content === 'string') {
|
|
406
|
+
if (msg.role === 'user') {
|
|
407
|
+
result.push({
|
|
408
|
+
role: 'user',
|
|
409
|
+
content: [{ type: 'text', text: msg.content }],
|
|
410
|
+
timestamp: now,
|
|
411
|
+
});
|
|
412
|
+
} else {
|
|
413
|
+
// Assistant message
|
|
414
|
+
result.push({
|
|
415
|
+
role: 'assistant',
|
|
416
|
+
content: [{ type: 'text', text: msg.content }],
|
|
417
|
+
api: 'openai-codex-responses',
|
|
418
|
+
provider: 'openai-codex',
|
|
419
|
+
model: this.model,
|
|
420
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
421
|
+
stopReason: 'stop',
|
|
422
|
+
timestamp: now,
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
} else if (Array.isArray(msg.content)) {
|
|
426
|
+
// Check if this is a tool result array
|
|
427
|
+
const toolResults = msg.content.filter((item): item is LLMToolResult => item.type === 'tool_result');
|
|
428
|
+
|
|
429
|
+
if (toolResults.length > 0) {
|
|
430
|
+
// Convert tool results to pi-ai format
|
|
431
|
+
for (const toolResult of toolResults) {
|
|
432
|
+
result.push({
|
|
433
|
+
role: 'toolResult',
|
|
434
|
+
toolCallId: toolResult.tool_use_id,
|
|
435
|
+
toolName: '', // Will be filled by the SDK
|
|
436
|
+
content: [{ type: 'text', text: toolResult.content }],
|
|
437
|
+
isError: toolResult.is_error || false,
|
|
438
|
+
timestamp: now,
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
} else {
|
|
442
|
+
// Handle mixed content (text and tool_use)
|
|
443
|
+
if (msg.role === 'user') {
|
|
444
|
+
const textContent = msg.content
|
|
445
|
+
.filter((item) => item.type === 'text')
|
|
446
|
+
.map((item) => ({ type: 'text' as const, text: (item as any).text }));
|
|
447
|
+
|
|
448
|
+
if (textContent.length > 0) {
|
|
449
|
+
result.push({
|
|
450
|
+
role: 'user',
|
|
451
|
+
content: textContent,
|
|
452
|
+
timestamp: now,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
} else {
|
|
456
|
+
// Assistant message with tool calls
|
|
457
|
+
const content: any[] = [];
|
|
458
|
+
|
|
459
|
+
for (const item of msg.content) {
|
|
460
|
+
if (item.type === 'text') {
|
|
461
|
+
content.push({ type: 'text', text: (item as any).text });
|
|
462
|
+
} else if (item.type === 'tool_use') {
|
|
463
|
+
content.push({
|
|
464
|
+
type: 'toolCall',
|
|
465
|
+
id: (item as any).id,
|
|
466
|
+
name: (item as any).name,
|
|
467
|
+
arguments: (item as any).input,
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (content.length > 0) {
|
|
473
|
+
result.push({
|
|
474
|
+
role: 'assistant',
|
|
475
|
+
content,
|
|
476
|
+
api: 'openai-codex-responses',
|
|
477
|
+
provider: 'openai-codex',
|
|
478
|
+
model: this.model,
|
|
479
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
480
|
+
stopReason: 'stop',
|
|
481
|
+
timestamp: now,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return result;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Convert tools to pi-ai SDK format
|
|
494
|
+
*/
|
|
495
|
+
private convertToolsToPiAi(tools: LLMTool[]): PiAiTool[] {
|
|
496
|
+
return tools.map((tool) => ({
|
|
497
|
+
name: tool.name,
|
|
498
|
+
description: tool.description,
|
|
499
|
+
parameters: tool.input_schema as any,
|
|
500
|
+
}));
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Convert pi-ai response to our format
|
|
505
|
+
*/
|
|
506
|
+
private convertPiAiResponse(response: any): LLMResponse {
|
|
507
|
+
const content: LLMContent[] = [];
|
|
508
|
+
|
|
509
|
+
if (response.content) {
|
|
510
|
+
for (const block of response.content) {
|
|
511
|
+
if (block.type === 'text') {
|
|
512
|
+
content.push({
|
|
513
|
+
type: 'text',
|
|
514
|
+
text: block.text,
|
|
515
|
+
});
|
|
516
|
+
} else if (block.type === 'toolCall') {
|
|
517
|
+
content.push({
|
|
518
|
+
type: 'tool_use',
|
|
519
|
+
id: block.id,
|
|
520
|
+
name: block.name,
|
|
521
|
+
input: block.arguments || {},
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Map stop reason
|
|
528
|
+
let stopReason: LLMResponse['stopReason'] = 'end_turn';
|
|
529
|
+
if (response.stopReason === 'toolUse') {
|
|
530
|
+
stopReason = 'tool_use';
|
|
531
|
+
} else if (response.stopReason === 'length') {
|
|
532
|
+
stopReason = 'max_tokens';
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return {
|
|
536
|
+
content,
|
|
537
|
+
stopReason,
|
|
538
|
+
usage: response.usage
|
|
539
|
+
? {
|
|
540
|
+
inputTokens: response.usage.input || 0,
|
|
541
|
+
outputTokens: response.usage.output || 0,
|
|
542
|
+
}
|
|
543
|
+
: undefined,
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Convert messages to OpenAI format (for API key auth)
|
|
549
|
+
*/
|
|
550
|
+
private convertMessages(messages: LLMMessage[], system?: string): OpenAI.ChatCompletionMessageParam[] {
|
|
551
|
+
const result: OpenAI.ChatCompletionMessageParam[] = [];
|
|
552
|
+
|
|
553
|
+
// Add system message first if provided
|
|
554
|
+
if (system) {
|
|
555
|
+
result.push({
|
|
556
|
+
role: 'system',
|
|
557
|
+
content: system,
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
for (const msg of messages) {
|
|
562
|
+
if (typeof msg.content === 'string') {
|
|
563
|
+
result.push({
|
|
564
|
+
role: msg.role,
|
|
565
|
+
content: msg.content,
|
|
566
|
+
});
|
|
567
|
+
} else if (Array.isArray(msg.content)) {
|
|
568
|
+
// Check if this is a tool result array
|
|
569
|
+
const toolResults = msg.content.filter((item): item is LLMToolResult => item.type === 'tool_result');
|
|
570
|
+
|
|
571
|
+
if (toolResults.length > 0) {
|
|
572
|
+
// Convert tool results to OpenAI format
|
|
573
|
+
for (const toolResult of toolResults) {
|
|
574
|
+
result.push({
|
|
575
|
+
role: 'tool',
|
|
576
|
+
tool_call_id: toolResult.tool_use_id,
|
|
577
|
+
content: toolResult.content,
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
} else {
|
|
581
|
+
// Handle mixed content (text and tool_use)
|
|
582
|
+
const textContent = msg.content
|
|
583
|
+
.filter((item) => item.type === 'text')
|
|
584
|
+
.map((item) => (item as { type: 'text'; text: string }).text)
|
|
585
|
+
.join('\n');
|
|
586
|
+
|
|
587
|
+
const toolUses = msg.content.filter((item) => item.type === 'tool_use');
|
|
588
|
+
|
|
589
|
+
if (msg.role === 'assistant') {
|
|
590
|
+
const assistantMsg: OpenAI.ChatCompletionAssistantMessageParam = {
|
|
591
|
+
role: 'assistant',
|
|
592
|
+
content: textContent || null,
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
if (toolUses.length > 0) {
|
|
596
|
+
assistantMsg.tool_calls = toolUses.map((tool) => ({
|
|
597
|
+
id: (tool as any).id,
|
|
598
|
+
type: 'function' as const,
|
|
599
|
+
function: {
|
|
600
|
+
name: (tool as any).name,
|
|
601
|
+
arguments: JSON.stringify((tool as any).input),
|
|
602
|
+
},
|
|
603
|
+
}));
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
result.push(assistantMsg);
|
|
607
|
+
} else {
|
|
608
|
+
result.push({
|
|
609
|
+
role: msg.role,
|
|
610
|
+
content: textContent,
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
return result;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
private convertTools(tools: LLMTool[]): OpenAI.ChatCompletionTool[] {
|
|
621
|
+
return tools.map((tool) => ({
|
|
622
|
+
type: 'function' as const,
|
|
623
|
+
function: {
|
|
624
|
+
name: tool.name,
|
|
625
|
+
description: tool.description,
|
|
626
|
+
parameters: tool.input_schema,
|
|
627
|
+
},
|
|
628
|
+
}));
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
private convertResponse(response: OpenAI.ChatCompletion): LLMResponse {
|
|
632
|
+
const choice = response.choices[0];
|
|
633
|
+
const content: LLMContent[] = [];
|
|
634
|
+
|
|
635
|
+
// Add text content if present
|
|
636
|
+
if (choice.message.content) {
|
|
637
|
+
content.push({
|
|
638
|
+
type: 'text',
|
|
639
|
+
text: choice.message.content,
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// Add tool calls if present
|
|
644
|
+
if (choice.message.tool_calls) {
|
|
645
|
+
for (const toolCall of choice.message.tool_calls) {
|
|
646
|
+
// Only handle function-type tool calls
|
|
647
|
+
if (toolCall.type === 'function') {
|
|
648
|
+
content.push({
|
|
649
|
+
type: 'tool_use',
|
|
650
|
+
id: toolCall.id,
|
|
651
|
+
name: toolCall.function.name,
|
|
652
|
+
input: JSON.parse(toolCall.function.arguments || '{}'),
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
return {
|
|
659
|
+
content,
|
|
660
|
+
stopReason: this.mapStopReason(choice.finish_reason),
|
|
661
|
+
usage: response.usage
|
|
662
|
+
? {
|
|
663
|
+
inputTokens: response.usage.prompt_tokens,
|
|
664
|
+
outputTokens: response.usage.completion_tokens,
|
|
665
|
+
}
|
|
666
|
+
: undefined,
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
private mapStopReason(
|
|
671
|
+
reason: OpenAI.ChatCompletion.Choice['finish_reason']
|
|
672
|
+
): LLMResponse['stopReason'] {
|
|
673
|
+
switch (reason) {
|
|
674
|
+
case 'stop':
|
|
675
|
+
return 'end_turn';
|
|
676
|
+
case 'tool_calls':
|
|
677
|
+
return 'tool_use';
|
|
678
|
+
case 'length':
|
|
679
|
+
return 'max_tokens';
|
|
680
|
+
case 'content_filter':
|
|
681
|
+
return 'stop_sequence';
|
|
682
|
+
default:
|
|
683
|
+
return 'end_turn';
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|