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,596 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Microsoft Teams Channel Adapter
|
|
4
|
+
*
|
|
5
|
+
* Implements the ChannelAdapter interface using Microsoft Bot Framework SDK.
|
|
6
|
+
* Supports direct messages, channel mentions, and group chats.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.TeamsAdapter = void 0;
|
|
43
|
+
exports.createTeamsAdapter = createTeamsAdapter;
|
|
44
|
+
const botbuilder_1 = require("botbuilder");
|
|
45
|
+
const http = __importStar(require("http"));
|
|
46
|
+
const fs = __importStar(require("fs"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
/**
|
|
49
|
+
* Simple TTL cache for message deduplication
|
|
50
|
+
*/
|
|
51
|
+
class MessageDeduplicationCache {
|
|
52
|
+
constructor(ttlMs = 60000) {
|
|
53
|
+
this.cache = new Map();
|
|
54
|
+
this.ttlMs = ttlMs;
|
|
55
|
+
// Cleanup expired entries every minute
|
|
56
|
+
setInterval(() => this.cleanup(), 60000);
|
|
57
|
+
}
|
|
58
|
+
has(messageId) {
|
|
59
|
+
const timestamp = this.cache.get(messageId);
|
|
60
|
+
if (!timestamp)
|
|
61
|
+
return false;
|
|
62
|
+
if (Date.now() - timestamp > this.ttlMs) {
|
|
63
|
+
this.cache.delete(messageId);
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
add(messageId) {
|
|
69
|
+
this.cache.set(messageId, Date.now());
|
|
70
|
+
}
|
|
71
|
+
cleanup() {
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
for (const [key, timestamp] of this.cache.entries()) {
|
|
74
|
+
if (now - timestamp > this.ttlMs) {
|
|
75
|
+
this.cache.delete(key);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
class TeamsAdapter {
|
|
81
|
+
constructor(config) {
|
|
82
|
+
this.type = 'teams';
|
|
83
|
+
this.adapter = null;
|
|
84
|
+
this.server = null;
|
|
85
|
+
this._status = 'disconnected';
|
|
86
|
+
this.messageHandlers = [];
|
|
87
|
+
this.errorHandlers = [];
|
|
88
|
+
this.statusHandlers = [];
|
|
89
|
+
this.conversationReferences = new Map();
|
|
90
|
+
this.reconnectAttempts = 0;
|
|
91
|
+
this.reconnectTimer = null;
|
|
92
|
+
this.config = config;
|
|
93
|
+
this.deduplicationCache = new MessageDeduplicationCache();
|
|
94
|
+
}
|
|
95
|
+
get status() {
|
|
96
|
+
return this._status;
|
|
97
|
+
}
|
|
98
|
+
get botUsername() {
|
|
99
|
+
return this._botUsername;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Connect to Microsoft Teams via Bot Framework
|
|
103
|
+
*/
|
|
104
|
+
async connect() {
|
|
105
|
+
if (this._status === 'connected' || this._status === 'connecting') {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
this.setStatus('connecting');
|
|
109
|
+
try {
|
|
110
|
+
// Create Bot Framework authentication
|
|
111
|
+
const botFrameworkAuth = new botbuilder_1.ConfigurationBotFrameworkAuthentication({
|
|
112
|
+
MicrosoftAppId: this.config.appId,
|
|
113
|
+
MicrosoftAppPassword: this.config.appPassword,
|
|
114
|
+
MicrosoftAppTenantId: this.config.tenantId,
|
|
115
|
+
MicrosoftAppType: this.config.tenantId ? 'SingleTenant' : 'MultiTenant',
|
|
116
|
+
});
|
|
117
|
+
// Create the adapter
|
|
118
|
+
this.adapter = new botbuilder_1.CloudAdapter(botFrameworkAuth);
|
|
119
|
+
// Set up error handling for the adapter
|
|
120
|
+
this.adapter.onTurnError = async (context, error) => {
|
|
121
|
+
console.error('Teams adapter turn error:', error);
|
|
122
|
+
this.handleError(error, 'turnError');
|
|
123
|
+
// Send error message to user
|
|
124
|
+
try {
|
|
125
|
+
await context.sendActivity('Sorry, something went wrong processing your message.');
|
|
126
|
+
}
|
|
127
|
+
catch (sendError) {
|
|
128
|
+
console.error('Failed to send error message:', sendError);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
// Set bot info from config
|
|
132
|
+
this._botUsername = this.config.displayName || 'Teams Bot';
|
|
133
|
+
// Start the HTTP server for receiving webhooks
|
|
134
|
+
await this.startWebhookServer();
|
|
135
|
+
console.log(`Teams bot "${this._botUsername}" is connected on port ${this.config.webhookPort || 3978}`);
|
|
136
|
+
this.setStatus('connected');
|
|
137
|
+
this.reconnectAttempts = 0;
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
141
|
+
this.setStatus('error', err);
|
|
142
|
+
this.scheduleReconnect();
|
|
143
|
+
throw err;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Start the webhook server to receive messages from Teams
|
|
148
|
+
*/
|
|
149
|
+
async startWebhookServer() {
|
|
150
|
+
const port = this.config.webhookPort || 3978;
|
|
151
|
+
return new Promise((resolve, reject) => {
|
|
152
|
+
this.server = http.createServer(async (req, res) => {
|
|
153
|
+
if (req.method === 'POST' && req.url === '/api/messages') {
|
|
154
|
+
let body = '';
|
|
155
|
+
req.on('data', chunk => {
|
|
156
|
+
body += chunk.toString();
|
|
157
|
+
});
|
|
158
|
+
req.on('end', async () => {
|
|
159
|
+
try {
|
|
160
|
+
await this.processIncomingActivity(req, res, body);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
console.error('Error processing Teams message:', error);
|
|
164
|
+
res.writeHead(500);
|
|
165
|
+
res.end('Internal Server Error');
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
else if (req.method === 'GET' && req.url === '/api/health') {
|
|
170
|
+
// Health check endpoint
|
|
171
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
172
|
+
res.end(JSON.stringify({ status: 'ok', bot: this._botUsername }));
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
res.writeHead(404);
|
|
176
|
+
res.end('Not Found');
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
this.server.on('error', (error) => {
|
|
180
|
+
if (error.code === 'EADDRINUSE') {
|
|
181
|
+
reject(new Error(`Port ${port} is already in use. Please choose a different webhook port.`));
|
|
182
|
+
}
|
|
183
|
+
else if (error.code === 'EACCES') {
|
|
184
|
+
reject(new Error(`Permission denied to use port ${port}. Try a port above 1024.`));
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
reject(error);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
this.server.listen(port, () => {
|
|
191
|
+
console.log(`Teams webhook server listening on port ${port}`);
|
|
192
|
+
resolve();
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Process incoming activity from Teams
|
|
198
|
+
*/
|
|
199
|
+
async processIncomingActivity(req, res, body) {
|
|
200
|
+
if (!this.adapter) {
|
|
201
|
+
res.writeHead(500);
|
|
202
|
+
res.end('Adapter not initialized');
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
const activity = JSON.parse(body);
|
|
207
|
+
// Create a fake request object for the adapter
|
|
208
|
+
const fakeReq = {
|
|
209
|
+
body: activity,
|
|
210
|
+
headers: req.headers,
|
|
211
|
+
method: req.method,
|
|
212
|
+
};
|
|
213
|
+
await this.adapter.process(fakeReq, res, async (context) => {
|
|
214
|
+
await this.handleActivity(context);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
console.error('Error parsing Teams activity:', error);
|
|
219
|
+
res.writeHead(400);
|
|
220
|
+
res.end('Bad Request');
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Handle incoming activity from Teams
|
|
225
|
+
*/
|
|
226
|
+
async handleActivity(context) {
|
|
227
|
+
const activity = context.activity;
|
|
228
|
+
// Store conversation reference for proactive messaging
|
|
229
|
+
const conversationRef = botbuilder_1.TurnContext.getConversationReference(activity);
|
|
230
|
+
this.conversationReferences.set(activity.conversation.id, conversationRef);
|
|
231
|
+
// Handle different activity types
|
|
232
|
+
switch (activity.type) {
|
|
233
|
+
case botbuilder_1.ActivityTypes.Message:
|
|
234
|
+
await this.handleMessage(context, activity);
|
|
235
|
+
break;
|
|
236
|
+
case botbuilder_1.ActivityTypes.ConversationUpdate:
|
|
237
|
+
await this.handleConversationUpdate(context, activity);
|
|
238
|
+
break;
|
|
239
|
+
case botbuilder_1.ActivityTypes.MessageReaction:
|
|
240
|
+
// Handle reactions if needed
|
|
241
|
+
break;
|
|
242
|
+
default:
|
|
243
|
+
// Log unhandled activity types for debugging
|
|
244
|
+
console.log(`Unhandled activity type: ${activity.type}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Handle incoming message activity
|
|
249
|
+
*/
|
|
250
|
+
async handleMessage(context, activity) {
|
|
251
|
+
// Skip if no text content
|
|
252
|
+
if (!activity.text) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
// Deduplication check
|
|
256
|
+
const messageId = activity.id || `${activity.conversation.id}-${activity.timestamp}`;
|
|
257
|
+
if (this.config.deduplicationEnabled !== false && this.deduplicationCache.has(messageId)) {
|
|
258
|
+
console.log(`Skipping duplicate Teams message: ${messageId}`);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
this.deduplicationCache.add(messageId);
|
|
262
|
+
// Remove bot mention from text
|
|
263
|
+
let text = activity.text;
|
|
264
|
+
if (activity.entities) {
|
|
265
|
+
for (const entity of activity.entities) {
|
|
266
|
+
if (entity.type === 'mention' && entity.mentioned?.id === activity.recipient?.id) {
|
|
267
|
+
// Remove the mention from the text
|
|
268
|
+
const mentionText = entity.text || '';
|
|
269
|
+
text = text.replace(mentionText, '').trim();
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Skip empty messages after removing mentions
|
|
274
|
+
if (!text.trim()) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
// Get user info
|
|
278
|
+
const userName = activity.from?.name || 'Unknown User';
|
|
279
|
+
const userId = activity.from?.id || '';
|
|
280
|
+
// Map to IncomingMessage format
|
|
281
|
+
const incomingMessage = {
|
|
282
|
+
messageId: messageId,
|
|
283
|
+
channel: 'teams',
|
|
284
|
+
userId: userId,
|
|
285
|
+
userName: userName,
|
|
286
|
+
chatId: activity.conversation.id,
|
|
287
|
+
text: text.trim(),
|
|
288
|
+
timestamp: activity.timestamp ? new Date(activity.timestamp) : new Date(),
|
|
289
|
+
replyTo: activity.replyToId,
|
|
290
|
+
threadId: activity.conversation.id,
|
|
291
|
+
raw: activity,
|
|
292
|
+
};
|
|
293
|
+
console.log(`Processing Teams message from ${userName}: ${text.slice(0, 50)}...`);
|
|
294
|
+
await this.handleIncomingMessage(incomingMessage);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Handle conversation update activity (new members, etc.)
|
|
298
|
+
*/
|
|
299
|
+
async handleConversationUpdate(context, activity) {
|
|
300
|
+
// Welcome new members
|
|
301
|
+
if (activity.membersAdded) {
|
|
302
|
+
for (const member of activity.membersAdded) {
|
|
303
|
+
// Don't welcome the bot itself
|
|
304
|
+
if (member.id !== activity.recipient?.id) {
|
|
305
|
+
// Could send a welcome message here if desired
|
|
306
|
+
console.log(`New member added to conversation: ${member.name}`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Schedule reconnection with exponential backoff
|
|
313
|
+
*/
|
|
314
|
+
scheduleReconnect() {
|
|
315
|
+
if (!this.config.autoReconnect)
|
|
316
|
+
return;
|
|
317
|
+
const maxAttempts = this.config.maxReconnectAttempts || 5;
|
|
318
|
+
if (this.reconnectAttempts >= maxAttempts) {
|
|
319
|
+
console.error(`Teams: Max reconnection attempts (${maxAttempts}) reached`);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000);
|
|
323
|
+
this.reconnectAttempts++;
|
|
324
|
+
console.log(`Teams: Scheduling reconnection attempt ${this.reconnectAttempts} in ${delay}ms`);
|
|
325
|
+
if (this.reconnectTimer) {
|
|
326
|
+
clearTimeout(this.reconnectTimer);
|
|
327
|
+
}
|
|
328
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
329
|
+
try {
|
|
330
|
+
await this.connect();
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
console.error('Teams reconnection failed:', error);
|
|
334
|
+
}
|
|
335
|
+
}, delay);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Disconnect from Teams
|
|
339
|
+
*/
|
|
340
|
+
async disconnect() {
|
|
341
|
+
if (this.reconnectTimer) {
|
|
342
|
+
clearTimeout(this.reconnectTimer);
|
|
343
|
+
this.reconnectTimer = null;
|
|
344
|
+
}
|
|
345
|
+
if (this.server) {
|
|
346
|
+
await new Promise((resolve) => {
|
|
347
|
+
this.server.close(() => resolve());
|
|
348
|
+
});
|
|
349
|
+
this.server = null;
|
|
350
|
+
}
|
|
351
|
+
this.adapter = null;
|
|
352
|
+
this._botUsername = undefined;
|
|
353
|
+
this._botId = undefined;
|
|
354
|
+
this.conversationReferences.clear();
|
|
355
|
+
this.setStatus('disconnected');
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Send a message to a Teams conversation
|
|
359
|
+
*/
|
|
360
|
+
async sendMessage(message) {
|
|
361
|
+
if (!this.adapter || this._status !== 'connected') {
|
|
362
|
+
throw new Error('Teams bot is not connected');
|
|
363
|
+
}
|
|
364
|
+
// Get conversation reference
|
|
365
|
+
const conversationRef = this.conversationReferences.get(message.chatId);
|
|
366
|
+
if (!conversationRef) {
|
|
367
|
+
throw new Error(`No conversation reference found for chat: ${message.chatId}`);
|
|
368
|
+
}
|
|
369
|
+
// Process text for Teams compatibility
|
|
370
|
+
let processedText = message.text;
|
|
371
|
+
if (message.parseMode === 'markdown') {
|
|
372
|
+
processedText = this.convertMarkdownForTeams(message.text);
|
|
373
|
+
}
|
|
374
|
+
// Teams has a 28KB limit per message, but practical limit is ~4000 chars for readability
|
|
375
|
+
const chunks = this.splitMessage(processedText, 4000);
|
|
376
|
+
let lastMessageId = '';
|
|
377
|
+
try {
|
|
378
|
+
for (const chunk of chunks) {
|
|
379
|
+
await this.adapter.continueConversationAsync(this.config.appId, conversationRef, async (context) => {
|
|
380
|
+
const response = await context.sendActivity(botbuilder_1.MessageFactory.text(chunk));
|
|
381
|
+
lastMessageId = response?.id || '';
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
387
|
+
console.error('Error sending Teams message:', errorMessage);
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
return lastMessageId;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Convert GitHub-flavored markdown to Teams format
|
|
394
|
+
* Teams supports a subset of markdown
|
|
395
|
+
*/
|
|
396
|
+
convertMarkdownForTeams(text) {
|
|
397
|
+
let result = text;
|
|
398
|
+
// Teams supports basic markdown: **bold**, *italic*, ~~strikethrough~~, `code`, ```code blocks```
|
|
399
|
+
// No conversion needed for these
|
|
400
|
+
// Convert horizontal rules
|
|
401
|
+
result = result.replace(/^[-*]{3,}$/gm, '───────────────────');
|
|
402
|
+
return result;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Split message into chunks respecting Teams message limit
|
|
406
|
+
*/
|
|
407
|
+
splitMessage(text, maxLength) {
|
|
408
|
+
if (text.length <= maxLength) {
|
|
409
|
+
return [text];
|
|
410
|
+
}
|
|
411
|
+
const chunks = [];
|
|
412
|
+
let remaining = text;
|
|
413
|
+
while (remaining.length > 0) {
|
|
414
|
+
if (remaining.length <= maxLength) {
|
|
415
|
+
chunks.push(remaining);
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
// Find a good breaking point (newline or space)
|
|
419
|
+
let breakIndex = remaining.lastIndexOf('\n', maxLength);
|
|
420
|
+
if (breakIndex === -1 || breakIndex < maxLength / 2) {
|
|
421
|
+
breakIndex = remaining.lastIndexOf(' ', maxLength);
|
|
422
|
+
}
|
|
423
|
+
if (breakIndex === -1 || breakIndex < maxLength / 2) {
|
|
424
|
+
breakIndex = maxLength;
|
|
425
|
+
}
|
|
426
|
+
chunks.push(remaining.substring(0, breakIndex));
|
|
427
|
+
remaining = remaining.substring(breakIndex).trimStart();
|
|
428
|
+
}
|
|
429
|
+
return chunks;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Edit an existing message
|
|
433
|
+
*/
|
|
434
|
+
async editMessage(chatId, messageId, text) {
|
|
435
|
+
if (!this.adapter || this._status !== 'connected') {
|
|
436
|
+
throw new Error('Teams bot is not connected');
|
|
437
|
+
}
|
|
438
|
+
const conversationRef = this.conversationReferences.get(chatId);
|
|
439
|
+
if (!conversationRef) {
|
|
440
|
+
throw new Error(`No conversation reference found for chat: ${chatId}`);
|
|
441
|
+
}
|
|
442
|
+
await this.adapter.continueConversationAsync(this.config.appId, conversationRef, async (context) => {
|
|
443
|
+
const activity = botbuilder_1.MessageFactory.text(text);
|
|
444
|
+
activity.id = messageId;
|
|
445
|
+
await context.updateActivity(activity);
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Delete a message
|
|
450
|
+
*/
|
|
451
|
+
async deleteMessage(chatId, messageId) {
|
|
452
|
+
if (!this.adapter || this._status !== 'connected') {
|
|
453
|
+
throw new Error('Teams bot is not connected');
|
|
454
|
+
}
|
|
455
|
+
const conversationRef = this.conversationReferences.get(chatId);
|
|
456
|
+
if (!conversationRef) {
|
|
457
|
+
throw new Error(`No conversation reference found for chat: ${chatId}`);
|
|
458
|
+
}
|
|
459
|
+
await this.adapter.continueConversationAsync(this.config.appId, conversationRef, async (context) => {
|
|
460
|
+
await context.deleteActivity(messageId);
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Send a document/file to a conversation
|
|
465
|
+
*/
|
|
466
|
+
async sendDocument(chatId, filePath, caption) {
|
|
467
|
+
if (!this.adapter || this._status !== 'connected') {
|
|
468
|
+
throw new Error('Teams bot is not connected');
|
|
469
|
+
}
|
|
470
|
+
// Check if file exists
|
|
471
|
+
if (!fs.existsSync(filePath)) {
|
|
472
|
+
throw new Error(`File not found: ${filePath}`);
|
|
473
|
+
}
|
|
474
|
+
const conversationRef = this.conversationReferences.get(chatId);
|
|
475
|
+
if (!conversationRef) {
|
|
476
|
+
throw new Error(`No conversation reference found for chat: ${chatId}`);
|
|
477
|
+
}
|
|
478
|
+
const fileName = path.basename(filePath);
|
|
479
|
+
const fileBuffer = fs.readFileSync(filePath);
|
|
480
|
+
const base64Content = fileBuffer.toString('base64');
|
|
481
|
+
const contentType = this.getContentType(fileName);
|
|
482
|
+
let lastMessageId = '';
|
|
483
|
+
await this.adapter.continueConversationAsync(this.config.appId, conversationRef, async (context) => {
|
|
484
|
+
// Create attachment
|
|
485
|
+
const attachment = {
|
|
486
|
+
name: fileName,
|
|
487
|
+
contentType: contentType,
|
|
488
|
+
contentUrl: `data:${contentType};base64,${base64Content}`,
|
|
489
|
+
};
|
|
490
|
+
const activity = botbuilder_1.MessageFactory.attachment(attachment, caption);
|
|
491
|
+
const response = await context.sendActivity(activity);
|
|
492
|
+
lastMessageId = response?.id || '';
|
|
493
|
+
});
|
|
494
|
+
return lastMessageId;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Get content type from file extension
|
|
498
|
+
*/
|
|
499
|
+
getContentType(fileName) {
|
|
500
|
+
const ext = path.extname(fileName).toLowerCase();
|
|
501
|
+
const contentTypes = {
|
|
502
|
+
'.pdf': 'application/pdf',
|
|
503
|
+
'.doc': 'application/msword',
|
|
504
|
+
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
505
|
+
'.xls': 'application/vnd.ms-excel',
|
|
506
|
+
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
507
|
+
'.ppt': 'application/vnd.ms-powerpoint',
|
|
508
|
+
'.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
509
|
+
'.png': 'image/png',
|
|
510
|
+
'.jpg': 'image/jpeg',
|
|
511
|
+
'.jpeg': 'image/jpeg',
|
|
512
|
+
'.gif': 'image/gif',
|
|
513
|
+
'.txt': 'text/plain',
|
|
514
|
+
'.json': 'application/json',
|
|
515
|
+
'.xml': 'application/xml',
|
|
516
|
+
'.zip': 'application/zip',
|
|
517
|
+
};
|
|
518
|
+
return contentTypes[ext] || 'application/octet-stream';
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Register a message handler
|
|
522
|
+
*/
|
|
523
|
+
onMessage(handler) {
|
|
524
|
+
this.messageHandlers.push(handler);
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Register an error handler
|
|
528
|
+
*/
|
|
529
|
+
onError(handler) {
|
|
530
|
+
this.errorHandlers.push(handler);
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Register a status change handler
|
|
534
|
+
*/
|
|
535
|
+
onStatusChange(handler) {
|
|
536
|
+
this.statusHandlers.push(handler);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Get channel info
|
|
540
|
+
*/
|
|
541
|
+
async getInfo() {
|
|
542
|
+
return {
|
|
543
|
+
type: 'teams',
|
|
544
|
+
status: this._status,
|
|
545
|
+
botId: this.config.appId,
|
|
546
|
+
botUsername: this._botUsername,
|
|
547
|
+
botDisplayName: this._botUsername,
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
// Private helper methods
|
|
551
|
+
async handleIncomingMessage(message) {
|
|
552
|
+
for (const handler of this.messageHandlers) {
|
|
553
|
+
try {
|
|
554
|
+
await handler(message);
|
|
555
|
+
}
|
|
556
|
+
catch (error) {
|
|
557
|
+
console.error('Error in message handler:', error);
|
|
558
|
+
this.handleError(error instanceof Error ? error : new Error(String(error)), 'messageHandler');
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
handleError(error, context) {
|
|
563
|
+
for (const handler of this.errorHandlers) {
|
|
564
|
+
try {
|
|
565
|
+
handler(error, context);
|
|
566
|
+
}
|
|
567
|
+
catch (e) {
|
|
568
|
+
console.error('Error in error handler:', e);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
setStatus(status, error) {
|
|
573
|
+
this._status = status;
|
|
574
|
+
for (const handler of this.statusHandlers) {
|
|
575
|
+
try {
|
|
576
|
+
handler(status, error);
|
|
577
|
+
}
|
|
578
|
+
catch (e) {
|
|
579
|
+
console.error('Error in status handler:', e);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
exports.TeamsAdapter = TeamsAdapter;
|
|
585
|
+
/**
|
|
586
|
+
* Create a Teams adapter from configuration
|
|
587
|
+
*/
|
|
588
|
+
function createTeamsAdapter(config) {
|
|
589
|
+
if (!config.appId) {
|
|
590
|
+
throw new Error('Microsoft App ID is required');
|
|
591
|
+
}
|
|
592
|
+
if (!config.appPassword) {
|
|
593
|
+
throw new Error('Microsoft App Password is required');
|
|
594
|
+
}
|
|
595
|
+
return new TeamsAdapter(config);
|
|
596
|
+
}
|