@cloudcli-ai/cloudcli 1.33.3 → 1.35.0
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/README.de.md +9 -1
- package/README.ja.md +8 -0
- package/README.ko.md +9 -1
- package/README.md +16 -3
- package/README.ru.md +9 -1
- package/README.tr.md +8 -1
- package/README.zh-CN.md +9 -1
- package/README.zh-TW.md +9 -1
- package/dist/api-docs.html +36 -18
- package/dist/assets/index-CtwxqzGG.js +1407 -0
- package/dist/assets/index-DlvtxFyt.css +32 -0
- package/dist/index.html +2 -2
- package/dist-server/server/browser-use-mcp.js +350 -0
- package/dist-server/server/browser-use-mcp.js.map +1 -0
- package/dist-server/server/claude-sdk.js +26 -6
- package/dist-server/server/claude-sdk.js.map +1 -1
- package/dist-server/server/cli.js +14 -6
- package/dist-server/server/cli.js.map +1 -1
- package/dist-server/server/computer-use-agent.js +242 -0
- package/dist-server/server/computer-use-agent.js.map +1 -0
- package/dist-server/server/computer-use-mcp.js +519 -0
- package/dist-server/server/computer-use-mcp.js.map +1 -0
- package/dist-server/server/cursor-cli.js +27 -11
- package/dist-server/server/cursor-cli.js.map +1 -1
- package/dist-server/server/gemini-cli.js +17 -2
- package/dist-server/server/gemini-cli.js.map +1 -1
- package/dist-server/server/index.js +149 -40
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/load-env.js +1 -1
- package/dist-server/server/load-env.js.map +1 -1
- package/dist-server/server/modules/browser-use/browser-use-mcp.routes.js +107 -0
- package/dist-server/server/modules/browser-use/browser-use-mcp.routes.js.map +1 -0
- package/dist-server/server/modules/browser-use/browser-use.routes.js +93 -0
- package/dist-server/server/modules/browser-use/browser-use.routes.js.map +1 -0
- package/dist-server/server/modules/browser-use/browser-use.service.js +688 -0
- package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -0
- package/dist-server/server/modules/browser-use/tests/browser-use.service.test.js +8 -0
- package/dist-server/server/modules/browser-use/tests/browser-use.service.test.js.map +1 -0
- package/dist-server/server/modules/computer-use/actions/raw-action-dispatcher.js +55 -0
- package/dist-server/server/modules/computer-use/actions/raw-action-dispatcher.js.map +1 -0
- package/dist-server/server/modules/computer-use/actions/raw-action-types.js +2 -0
- package/dist-server/server/modules/computer-use/actions/raw-action-types.js.map +1 -0
- package/dist-server/server/modules/computer-use/computer-executor.js +212 -0
- package/dist-server/server/modules/computer-use/computer-executor.js.map +1 -0
- package/dist-server/server/modules/computer-use/computer-semantics.service.js +422 -0
- package/dist-server/server/modules/computer-use/computer-semantics.service.js.map +1 -0
- package/dist-server/server/modules/computer-use/computer-use-mcp.routes.js +126 -0
- package/dist-server/server/modules/computer-use/computer-use-mcp.routes.js.map +1 -0
- package/dist-server/server/modules/computer-use/computer-use.routes.js +196 -0
- package/dist-server/server/modules/computer-use/computer-use.routes.js.map +1 -0
- package/dist-server/server/modules/computer-use/computer-use.service.js +759 -0
- package/dist-server/server/modules/computer-use/computer-use.service.js.map +1 -0
- package/dist-server/server/modules/computer-use/desktop-agent-relay.service.js +126 -0
- package/dist-server/server/modules/computer-use/desktop-agent-relay.service.js.map +1 -0
- package/dist-server/server/modules/computer-use/index.js +3 -0
- package/dist-server/server/modules/computer-use/index.js.map +1 -0
- package/dist-server/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.js +59 -0
- package/dist-server/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.js.map +1 -0
- package/dist-server/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.js +5 -0
- package/dist-server/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.js.map +1 -0
- package/dist-server/server/modules/computer-use/semantics/adapters/semantic-adapter.js +2 -0
- package/dist-server/server/modules/computer-use/semantics/adapters/semantic-adapter.js.map +1 -0
- package/dist-server/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.js +5 -0
- package/dist-server/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.js.map +1 -0
- package/dist-server/server/modules/computer-use/semantics/bin/darwin-arm64/CloudCLISemantics +0 -0
- package/dist-server/server/modules/computer-use/semantics/bin/darwin-x64/CloudCLISemantics +0 -0
- package/dist-server/server/modules/computer-use/semantics/bin/win32-arm64/CloudCLISemantics.exe +0 -0
- package/dist-server/server/modules/computer-use/semantics/bin/win32-x64/CloudCLISemantics.exe +0 -0
- package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-process.js +106 -0
- package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-process.js.map +1 -0
- package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.js +78 -0
- package/dist-server/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.js.map +1 -0
- package/dist-server/server/modules/computer-use/semantics/semantic-session-store.js +68 -0
- package/dist-server/server/modules/computer-use/semantics/semantic-session-store.js.map +1 -0
- package/dist-server/server/modules/computer-use/semantics/semantic-tool-dispatcher.js +16 -0
- package/dist-server/server/modules/computer-use/semantics/semantic-tool-dispatcher.js.map +1 -0
- package/dist-server/server/modules/computer-use/semantics/semantic-types.js +2 -0
- package/dist-server/server/modules/computer-use/semantics/semantic-types.js.map +1 -0
- package/dist-server/server/modules/database/index.js +1 -0
- package/dist-server/server/modules/database/index.js.map +1 -1
- package/dist-server/server/modules/database/migrations.js +23 -1
- package/dist-server/server/modules/database/migrations.js.map +1 -1
- package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js +100 -0
- package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js.map +1 -0
- package/dist-server/server/modules/database/repositories/notification-preferences.js +8 -0
- package/dist-server/server/modules/database/repositories/notification-preferences.js.map +1 -1
- package/dist-server/server/modules/database/repositories/sessions.db.js +173 -17
- package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
- package/dist-server/server/modules/database/schema.js +26 -0
- package/dist-server/server/modules/database/schema.js.map +1 -1
- package/dist-server/server/modules/database/tests/projects.db.integration.test.js.map +1 -0
- package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js +78 -0
- package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js.map +1 -0
- package/dist-server/server/modules/database/{repositories → tests}/sessions.db.integration.test.js +10 -0
- package/dist-server/server/modules/database/tests/sessions.db.integration.test.js.map +1 -0
- package/dist-server/server/modules/notifications/index.js +4 -0
- package/dist-server/server/modules/notifications/index.js.map +1 -0
- package/dist-server/server/modules/notifications/notifications.routes.js +115 -0
- package/dist-server/server/modules/notifications/notifications.routes.js.map +1 -0
- package/dist-server/server/modules/notifications/services/desktop-notification-clients.service.js +97 -0
- package/dist-server/server/modules/notifications/services/desktop-notification-clients.service.js.map +1 -0
- package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js +229 -0
- package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js.map +1 -0
- package/dist-server/server/modules/notifications/websocket/desktop-notifications-websocket.service.js +79 -0
- package/dist-server/server/modules/notifications/websocket/desktop-notifications-websocket.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-management.service.js +0 -4
- package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -1
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +10 -38
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -1
- package/dist-server/server/modules/providers/index.js +1 -0
- package/dist-server/server/modules/providers/index.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +5 -0
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +24 -1
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +9 -12
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +7 -0
- package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +7 -3
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +3 -9
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +7 -0
- package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +13 -22
- package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js +7 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js +5 -8
- package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +6 -6
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js +7 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +17 -3
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +9 -10
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +123 -1
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- package/dist-server/server/modules/providers/services/mcp.service.js +23 -0
- package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-capabilities.service.js +65 -0
- package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/provider-models.service.js +1 -1
- package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js +62 -23
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions.service.js +62 -4
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/skills.service.js +11 -0
- package/dist-server/server/modules/providers/services/skills.service.js.map +1 -1
- package/dist-server/server/modules/providers/shared/skills/skills.provider.js +163 -1
- package/dist-server/server/modules/providers/shared/skills/skills.provider.js.map +1 -1
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +45 -0
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/skills.test.js +160 -0
- package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
- package/dist-server/server/modules/websocket/index.js +1 -0
- package/dist-server/server/modules/websocket/index.js.map +1 -1
- package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +252 -0
- package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/chat-session-writer.service.js +105 -0
- package/dist-server/server/modules/websocket/services/chat-session-writer.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js +218 -156
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/desktop-agent-websocket.service.js +39 -0
- package/dist-server/server/modules/websocket/services/desktop-agent-websocket.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js +83 -31
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/websocket-server.service.js +10 -0
- package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -1
- package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js +216 -0
- package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js.map +1 -0
- package/dist-server/server/openai-codex.js +24 -14
- package/dist-server/server/openai-codex.js.map +1 -1
- package/dist-server/server/opencode-cli.js +21 -8
- package/dist-server/server/opencode-cli.js.map +1 -1
- package/dist-server/server/opencode-cli.test.js +19 -1
- package/dist-server/server/opencode-cli.test.js.map +1 -1
- package/dist-server/server/routes/agent.js +1 -1
- package/dist-server/server/routes/settings.js +1 -1
- package/dist-server/server/routes/settings.js.map +1 -1
- package/dist-server/server/services/notification-orchestrator.js +1 -176
- package/dist-server/server/services/notification-orchestrator.js.map +1 -1
- package/dist-server/server/services/tests/notification-orchestrator.test.js +64 -0
- package/dist-server/server/services/tests/notification-orchestrator.test.js.map +1 -0
- package/dist-server/server/shared/{claude-cli-path.test.js → tests/claude-cli-path.test.js} +1 -1
- package/dist-server/server/shared/tests/claude-cli-path.test.js.map +1 -0
- package/dist-server/server/shared/tests/slice-tail-page.test.js +35 -0
- package/dist-server/server/shared/tests/slice-tail-page.test.js.map +1 -0
- package/dist-server/server/shared/utils.js +73 -1
- package/dist-server/server/shared/utils.js.map +1 -1
- package/dist-server/server/voice-proxy.js +226 -0
- package/dist-server/server/voice-proxy.js.map +1 -0
- package/electron/assets/logo-macos.icns +0 -0
- package/electron/assets/logo-macos.png +0 -0
- package/electron/assets/logo-windows.ico +0 -0
- package/electron/cloud.js +260 -0
- package/electron/computerAgent.js +290 -0
- package/electron/desktopNotifications.js +378 -0
- package/electron/desktopWindow.js +781 -0
- package/electron/launcher/index.html +14 -0
- package/electron/launcher/launcher.css +801 -0
- package/electron/launcher/launcher.js +829 -0
- package/electron/localServer.js +550 -0
- package/electron/main.js +1060 -0
- package/electron/preload.cjs +63 -0
- package/electron/scripts/generate-macos-icon.js +62 -0
- package/electron/serverInstaller.js +277 -0
- package/electron/tabs.js +87 -0
- package/electron/viewHost.js +331 -0
- package/package.json +86 -5
- package/public/api-docs.html +36 -18
- package/scripts/build-computer-semantics.mjs +133 -0
- package/scripts/copy-computer-semantics-bin.mjs +24 -0
- package/scripts/release/build-server-bundle.js +176 -0
- package/scripts/release/prepare-desktop-app.js +158 -0
- package/server/browser-use-mcp.ts +384 -0
- package/server/claude-sdk.js +28 -6
- package/server/cli.js +15 -6
- package/server/computer-use-agent.ts +279 -0
- package/server/computer-use-mcp.ts +574 -0
- package/server/cursor-cli.js +27 -11
- package/server/gemini-cli.js +17 -2
- package/server/index.js +151 -47
- package/server/load-env.js +1 -1
- package/server/modules/browser-use/browser-use-mcp.routes.ts +120 -0
- package/server/modules/browser-use/browser-use.routes.ts +96 -0
- package/server/modules/browser-use/browser-use.service.ts +836 -0
- package/server/modules/browser-use/tests/browser-use.service.test.ts +10 -0
- package/server/modules/computer-use/actions/raw-action-dispatcher.ts +67 -0
- package/server/modules/computer-use/actions/raw-action-types.ts +28 -0
- package/server/modules/computer-use/computer-executor.ts +242 -0
- package/server/modules/computer-use/computer-semantics.service.ts +460 -0
- package/server/modules/computer-use/computer-use-mcp.routes.ts +141 -0
- package/server/modules/computer-use/computer-use.routes.ts +211 -0
- package/server/modules/computer-use/computer-use.service.ts +920 -0
- package/server/modules/computer-use/desktop-agent-relay.service.ts +158 -0
- package/server/modules/computer-use/index.ts +2 -0
- package/server/modules/computer-use/semantics/adapters/helper-semantic-adapter.ts +82 -0
- package/server/modules/computer-use/semantics/adapters/macos/macos-semantic-adapter.ts +5 -0
- package/server/modules/computer-use/semantics/adapters/semantic-adapter.ts +23 -0
- package/server/modules/computer-use/semantics/adapters/windows/windows-semantic-adapter.ts +5 -0
- package/server/modules/computer-use/semantics/bin/darwin-arm64/CloudCLISemantics +0 -0
- package/server/modules/computer-use/semantics/bin/darwin-x64/CloudCLISemantics +0 -0
- package/server/modules/computer-use/semantics/bin/win32-arm64/CloudCLISemantics.exe +0 -0
- package/server/modules/computer-use/semantics/bin/win32-x64/CloudCLISemantics.exe +0 -0
- package/server/modules/computer-use/semantics/helpers/macos/CloudCLISemantics.swift +467 -0
- package/server/modules/computer-use/semantics/helpers/semantic-helper-process.ts +124 -0
- package/server/modules/computer-use/semantics/helpers/semantic-helper-resolver.ts +97 -0
- package/server/modules/computer-use/semantics/helpers/windows/CloudCLISemantics.csproj +11 -0
- package/server/modules/computer-use/semantics/helpers/windows/Program.cs +534 -0
- package/server/modules/computer-use/semantics/semantic-session-store.ts +87 -0
- package/server/modules/computer-use/semantics/semantic-tool-dispatcher.ts +17 -0
- package/server/modules/computer-use/semantics/semantic-types.ts +58 -0
- package/server/modules/database/index.ts +1 -0
- package/server/modules/database/migrations.ts +25 -0
- package/server/modules/database/repositories/notification-channel-endpoints.ts +153 -0
- package/server/modules/database/repositories/notification-preferences.ts +12 -1
- package/server/modules/database/repositories/sessions.db.ts +227 -23
- package/server/modules/database/schema.ts +27 -0
- package/server/modules/database/tests/sessions-provider-mapping.test.ts +108 -0
- package/server/modules/database/{repositories → tests}/sessions.db.integration.test.ts +12 -0
- package/server/modules/notifications/index.ts +13 -0
- package/server/modules/notifications/notifications.routes.ts +127 -0
- package/server/modules/notifications/services/desktop-notification-clients.service.ts +124 -0
- package/server/modules/notifications/services/notification-orchestrator.service.js +288 -0
- package/server/modules/notifications/websocket/desktop-notifications-websocket.service.ts +109 -0
- package/server/modules/projects/services/project-management.service.ts +0 -8
- package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +12 -53
- package/server/modules/providers/README.md +1 -1
- package/server/modules/providers/index.ts +1 -0
- package/server/modules/providers/list/claude/claude-models.provider.ts +5 -0
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +26 -1
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +9 -14
- package/server/modules/providers/list/claude/claude-skills.provider.ts +8 -0
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +7 -3
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +3 -12
- package/server/modules/providers/list/codex/codex-skills.provider.ts +8 -0
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +13 -22
- package/server/modules/providers/list/cursor/cursor-skills.provider.ts +8 -0
- package/server/modules/providers/list/gemini/gemini-models.provider.ts +5 -8
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +6 -6
- package/server/modules/providers/list/gemini/gemini-skills.provider.ts +8 -0
- package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +18 -4
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +9 -12
- package/server/modules/providers/provider.routes.ts +167 -1
- package/server/modules/providers/services/mcp.service.ts +26 -0
- package/server/modules/providers/services/provider-capabilities.service.ts +91 -0
- package/server/modules/providers/services/provider-models.service.ts +1 -1
- package/server/modules/providers/services/sessions-watcher.service.ts +71 -25
- package/server/modules/providers/services/sessions.service.ts +79 -4
- package/server/modules/providers/services/skills.service.ts +25 -1
- package/server/modules/providers/shared/skills/skills.provider.ts +223 -0
- package/server/modules/providers/tests/opencode-sessions.test.ts +49 -0
- package/server/modules/providers/tests/skills.test.ts +212 -0
- package/server/modules/websocket/README.md +33 -27
- package/server/modules/websocket/index.ts +1 -0
- package/server/modules/websocket/services/chat-run-registry.service.ts +327 -0
- package/server/modules/websocket/services/chat-session-writer.service.ts +145 -0
- package/server/modules/websocket/services/chat-websocket.service.ts +292 -207
- package/server/modules/websocket/services/desktop-agent-websocket.service.ts +51 -0
- package/server/modules/websocket/services/shell-websocket.service.ts +108 -32
- package/server/modules/websocket/services/websocket-server.service.ts +12 -0
- package/server/modules/websocket/tests/chat-run-registry.test.ts +244 -0
- package/server/openai-codex.js +24 -14
- package/server/opencode-cli.js +21 -8
- package/server/opencode-cli.test.js +20 -1
- package/server/routes/agent.js +1 -1
- package/server/routes/settings.js +6 -1
- package/server/services/notification-orchestrator.js +3 -224
- package/server/services/tests/notification-orchestrator.test.js +80 -0
- package/server/shared/interfaces.ts +15 -0
- package/server/shared/tests/slice-tail-page.test.ts +42 -0
- package/server/shared/types.ts +84 -1
- package/server/shared/utils.ts +95 -1
- package/server/voice-proxy.js +224 -0
- package/dist/assets/index-73Xw3i9v.css +0 -32
- package/dist/assets/index-9n7A21AT.js +0 -1361
- package/dist/modelConstants.js +0 -848
- package/dist-server/server/modules/database/repositories/projects.db.integration.test.js.map +0 -1
- package/dist-server/server/modules/database/repositories/sessions.db.integration.test.js.map +0 -1
- package/dist-server/server/shared/claude-cli-path.test.js.map +0 -1
- package/public/modelConstants.js +0 -848
- /package/dist-server/server/modules/database/{repositories → tests}/projects.db.integration.test.js +0 -0
- /package/server/modules/database/{repositories → tests}/projects.db.integration.test.ts +0 -0
- /package/server/shared/{claude-cli-path.test.ts → tests/claude-cli-path.test.ts} +0 -0
package/server/gemini-cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import GeminiResponseHandler from './gemini-response-handler.js';
|
|
|
10
10
|
import { notifyRunFailed, notifyRunStopped } from './services/notification-orchestrator.js';
|
|
11
11
|
import { providerAuthService } from './modules/providers/services/provider-auth.service.js';
|
|
12
12
|
import { providerModelsService } from './modules/providers/services/provider-models.service.js';
|
|
13
|
-
import { createNormalizedMessage } from './shared/utils.js';
|
|
13
|
+
import { createCompleteMessage, createNormalizedMessage } from './shared/utils.js';
|
|
14
14
|
|
|
15
15
|
// Use cross-spawn on Windows for correct .cmd resolution (same pattern as cursor-cli.js)
|
|
16
16
|
const spawnFunction = process.platform === 'win32' ? crossSpawn : spawn;
|
|
@@ -129,6 +129,9 @@ async function spawnGemini(command, options = {}, ws) {
|
|
|
129
129
|
let capturedSessionId = sessionId; // Track session ID throughout the process
|
|
130
130
|
let sessionCreatedSent = false; // Track if we've already sent session-created event
|
|
131
131
|
let assistantBlocks = []; // Accumulate the full response blocks including tools
|
|
132
|
+
// Unified lifecycle contract: exactly one terminal `complete` per run
|
|
133
|
+
// (close and error handlers can both fire for spawn failures).
|
|
134
|
+
let completeSent = false;
|
|
132
135
|
|
|
133
136
|
// Use tools settings passed from frontend, or defaults
|
|
134
137
|
const settings = toolsSettings || {
|
|
@@ -486,7 +489,12 @@ async function spawnGemini(command, options = {}, ws) {
|
|
|
486
489
|
sessionManager.addMessage(finalSessionId, 'assistant', assistantBlocks);
|
|
487
490
|
}
|
|
488
491
|
|
|
489
|
-
|
|
492
|
+
// Terminal complete — skipped for aborted runs (abort-session
|
|
493
|
+
// already sent the aborted complete on this run's behalf).
|
|
494
|
+
if (!completeSent && !geminiProcess.aborted) {
|
|
495
|
+
completeSent = true;
|
|
496
|
+
ws.send(createCompleteMessage({ provider: 'gemini', sessionId: finalSessionId, exitCode: code }));
|
|
497
|
+
}
|
|
490
498
|
|
|
491
499
|
// Clean up temporary image files if any
|
|
492
500
|
if (geminiProcess.tempImagePaths && geminiProcess.tempImagePaths.length > 0) {
|
|
@@ -566,6 +574,10 @@ async function spawnGemini(command, options = {}, ws) {
|
|
|
566
574
|
|
|
567
575
|
const errorSessionId = typeof ws.getSessionId === 'function' ? ws.getSessionId() : finalSessionId;
|
|
568
576
|
ws.send(createNormalizedMessage({ kind: 'error', content: errorContent, sessionId: errorSessionId, provider: 'gemini' }));
|
|
577
|
+
if (!completeSent && !geminiProcess.aborted) {
|
|
578
|
+
completeSent = true;
|
|
579
|
+
ws.send(createCompleteMessage({ provider: 'gemini', sessionId: errorSessionId, exitCode: 1 }));
|
|
580
|
+
}
|
|
569
581
|
notifyTerminalState({ error });
|
|
570
582
|
|
|
571
583
|
reject(error);
|
|
@@ -590,6 +602,9 @@ function abortGeminiSession(sessionId) {
|
|
|
590
602
|
|
|
591
603
|
if (geminiProc) {
|
|
592
604
|
try {
|
|
605
|
+
// The abort handler sends the terminal complete (aborted: true);
|
|
606
|
+
// flag the process so its close handler does not emit a second one.
|
|
607
|
+
geminiProc.aborted = true;
|
|
593
608
|
geminiProc.kill('SIGTERM');
|
|
594
609
|
setTimeout(() => {
|
|
595
610
|
if (activeGeminiProcesses.has(processKey)) {
|
package/server/index.js
CHANGED
|
@@ -22,35 +22,24 @@ import { findAppRoot, getModuleDir } from './utils/runtime-paths.js';
|
|
|
22
22
|
import {
|
|
23
23
|
queryClaudeSDK,
|
|
24
24
|
abortClaudeSDKSession,
|
|
25
|
-
isClaudeSDKSessionActive,
|
|
26
|
-
getActiveClaudeSDKSessions,
|
|
27
25
|
resolveToolApproval,
|
|
28
26
|
getPendingApprovalsForSession,
|
|
29
|
-
reconnectSessionWriter,
|
|
30
27
|
} from './claude-sdk.js';
|
|
31
28
|
import {
|
|
32
29
|
spawnCursor,
|
|
33
30
|
abortCursorSession,
|
|
34
|
-
isCursorSessionActive,
|
|
35
|
-
getActiveCursorSessions,
|
|
36
31
|
} from './cursor-cli.js';
|
|
37
32
|
import {
|
|
38
33
|
queryCodex,
|
|
39
34
|
abortCodexSession,
|
|
40
|
-
isCodexSessionActive,
|
|
41
|
-
getActiveCodexSessions,
|
|
42
35
|
} from './openai-codex.js';
|
|
43
36
|
import {
|
|
44
37
|
spawnGemini,
|
|
45
38
|
abortGeminiSession,
|
|
46
|
-
isGeminiSessionActive,
|
|
47
|
-
getActiveGeminiSessions,
|
|
48
39
|
} from './gemini-cli.js';
|
|
49
40
|
import {
|
|
50
41
|
spawnOpenCode,
|
|
51
42
|
abortOpenCodeSession,
|
|
52
|
-
isOpenCodeSessionActive,
|
|
53
|
-
getActiveOpenCodeSessions,
|
|
54
43
|
} from './opencode-cli.js';
|
|
55
44
|
import sessionManager from './sessionManager.js';
|
|
56
45
|
import {
|
|
@@ -68,10 +57,18 @@ import commandsRoutes from './routes/commands.js';
|
|
|
68
57
|
import settingsRoutes from './routes/settings.js';
|
|
69
58
|
import agentRoutes from './routes/agent.js';
|
|
70
59
|
import projectModuleRoutes from './modules/projects/projects.routes.js';
|
|
60
|
+
import notificationRoutes from './modules/notifications/notifications.routes.js';
|
|
71
61
|
import userRoutes from './routes/user.js';
|
|
72
62
|
import geminiRoutes from './routes/gemini.js';
|
|
73
63
|
import pluginsRoutes from './routes/plugins.js';
|
|
74
64
|
import providerRoutes from './modules/providers/provider.routes.js';
|
|
65
|
+
import voiceRoutes from './voice-proxy.js';
|
|
66
|
+
import browserUseRoutes from './modules/browser-use/browser-use.routes.js';
|
|
67
|
+
import browserUseMcpRoutes from './modules/browser-use/browser-use-mcp.routes.js';
|
|
68
|
+
import { browserUseService } from './modules/browser-use/browser-use.service.js';
|
|
69
|
+
import computerUseRoutes from './modules/computer-use/computer-use.routes.js';
|
|
70
|
+
import computerUseMcpRoutes from './modules/computer-use/computer-use-mcp.routes.js';
|
|
71
|
+
import { computerUseService } from './modules/computer-use/computer-use.service.js';
|
|
75
72
|
import { startEnabledPluginServers, stopAllPlugins, getPluginPort } from './utils/plugin-process-manager.js';
|
|
76
73
|
import { initializeDatabase, projectsDb, sessionsDb } from './modules/database/index.js';
|
|
77
74
|
import { configureWebPush } from './services/vapid-keys.js';
|
|
@@ -84,6 +81,19 @@ const __dirname = getModuleDir(import.meta.url);
|
|
|
84
81
|
// Resolving the app root once keeps every repo-level lookup below aligned across both layouts.
|
|
85
82
|
const APP_ROOT = findAppRoot(__dirname);
|
|
86
83
|
const installMode = fs.existsSync(path.join(APP_ROOT, '.git')) ? 'git' : 'npm';
|
|
84
|
+
// Version of the code that is actually running, captured once at process
|
|
85
|
+
// startup. This intentionally does NOT re-read package.json per request: after
|
|
86
|
+
// an update replaces the files on disk, package.json reflects the NEW version
|
|
87
|
+
// while this long-lived process still runs the OLD code. The frontend bundle is
|
|
88
|
+
// rebuilt on update, so a mismatch between this value and the frontend's
|
|
89
|
+
// build-time version means the server was updated but not restarted.
|
|
90
|
+
const RUNNING_VERSION = (() => {
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(fs.readFileSync(path.join(APP_ROOT, 'package.json'), 'utf8')).version || null;
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
})();
|
|
87
97
|
const MAX_FILE_UPLOAD_SIZE_MB = 200;
|
|
88
98
|
const MAX_FILE_UPLOAD_SIZE_BYTES = MAX_FILE_UPLOAD_SIZE_MB * 1024 * 1024;
|
|
89
99
|
const MAX_FILE_UPLOAD_COUNT = 20;
|
|
@@ -105,32 +115,35 @@ const wss = createWebSocketServer(server, {
|
|
|
105
115
|
authenticateWebSocket,
|
|
106
116
|
},
|
|
107
117
|
chat: {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
spawnFns: {
|
|
119
|
+
claude: queryClaudeSDK,
|
|
120
|
+
cursor: spawnCursor,
|
|
121
|
+
codex: queryCodex,
|
|
122
|
+
gemini: spawnGemini,
|
|
123
|
+
opencode: spawnOpenCode,
|
|
124
|
+
},
|
|
125
|
+
abortFns: {
|
|
126
|
+
claude: abortClaudeSDKSession,
|
|
127
|
+
cursor: abortCursorSession,
|
|
128
|
+
codex: abortCodexSession,
|
|
129
|
+
gemini: abortGeminiSession,
|
|
130
|
+
opencode: abortOpenCodeSession,
|
|
131
|
+
},
|
|
118
132
|
resolveToolApproval,
|
|
119
|
-
isClaudeSDKSessionActive,
|
|
120
|
-
isCursorSessionActive,
|
|
121
|
-
isCodexSessionActive,
|
|
122
|
-
isGeminiSessionActive,
|
|
123
|
-
isOpenCodeSessionActive,
|
|
124
|
-
reconnectSessionWriter,
|
|
125
133
|
getPendingApprovalsForSession,
|
|
126
|
-
getActiveClaudeSDKSessions,
|
|
127
|
-
getActiveCursorSessions,
|
|
128
|
-
getActiveCodexSessions,
|
|
129
|
-
getActiveGeminiSessions,
|
|
130
|
-
getActiveOpenCodeSessions,
|
|
131
134
|
},
|
|
132
135
|
shell: {
|
|
133
|
-
|
|
136
|
+
resolveProviderSessionId: (sessionId, provider) => {
|
|
137
|
+
const dbSession = sessionsDb.getSessionById(sessionId);
|
|
138
|
+
const legacyGeminiSession =
|
|
139
|
+
provider === 'gemini' ? sessionManager.getSession(sessionId) : null;
|
|
140
|
+
|
|
141
|
+
if (dbSession) {
|
|
142
|
+
return dbSession.provider_session_id ?? legacyGeminiSession?.cliSessionId ?? null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return legacyGeminiSession?.cliSessionId;
|
|
146
|
+
},
|
|
134
147
|
stripAnsiSequences,
|
|
135
148
|
normalizeDetectedUrl,
|
|
136
149
|
extractUrlsFromText,
|
|
@@ -161,7 +174,8 @@ app.get('/health', (req, res) => {
|
|
|
161
174
|
res.json({
|
|
162
175
|
status: 'ok',
|
|
163
176
|
timestamp: new Date().toISOString(),
|
|
164
|
-
installMode
|
|
177
|
+
installMode,
|
|
178
|
+
version: RUNNING_VERSION
|
|
165
179
|
});
|
|
166
180
|
});
|
|
167
181
|
|
|
@@ -192,6 +206,8 @@ app.use('/api/commands', authenticateToken, commandsRoutes);
|
|
|
192
206
|
// Settings API Routes (protected)
|
|
193
207
|
app.use('/api/settings', authenticateToken, settingsRoutes);
|
|
194
208
|
|
|
209
|
+
app.use('/api/notifications', authenticateToken, notificationRoutes);
|
|
210
|
+
|
|
195
211
|
// User API Routes (protected)
|
|
196
212
|
app.use('/api/user', authenticateToken, userRoutes);
|
|
197
213
|
|
|
@@ -201,12 +217,26 @@ app.use('/api/gemini', authenticateToken, geminiRoutes);
|
|
|
201
217
|
// Plugins API Routes (protected)
|
|
202
218
|
app.use('/api/plugins', authenticateToken, pluginsRoutes);
|
|
203
219
|
|
|
220
|
+
// Browser MCP bridge API (local token protected)
|
|
221
|
+
app.use('/api/browser-use-mcp', browserUseMcpRoutes);
|
|
222
|
+
|
|
223
|
+
// Browser API Routes (protected)
|
|
224
|
+
app.use('/api/browser-use', authenticateToken, browserUseRoutes);
|
|
225
|
+
|
|
226
|
+
// Computer Use MCP bridge API (local token protected)
|
|
227
|
+
app.use('/api/computer-use-mcp', computerUseMcpRoutes);
|
|
228
|
+
|
|
229
|
+
// Computer Use API Routes (protected)
|
|
230
|
+
app.use('/api/computer-use', authenticateToken, computerUseRoutes);
|
|
231
|
+
|
|
204
232
|
// Unified provider MCP routes (protected)
|
|
205
233
|
app.use('/api/providers', authenticateToken, providerRoutes);
|
|
206
234
|
|
|
207
235
|
// Agent API Routes (uses API key authentication)
|
|
208
236
|
app.use('/api/agent', agentRoutes);
|
|
209
237
|
|
|
238
|
+
app.use('/api/voice', authenticateToken, voiceRoutes);
|
|
239
|
+
|
|
210
240
|
// Serve public files (like api-docs.html)
|
|
211
241
|
app.use(express.static(path.join(APP_ROOT, 'public')));
|
|
212
242
|
|
|
@@ -1143,7 +1173,6 @@ app.post('/api/projects/:projectId/upload-images', authenticateToken, async (req
|
|
|
1143
1173
|
app.get('/api/projects/:projectId/sessions/:sessionId/token-usage', authenticateToken, async (req, res) => {
|
|
1144
1174
|
try {
|
|
1145
1175
|
const { projectId, sessionId } = req.params;
|
|
1146
|
-
const { provider = 'claude' } = req.query;
|
|
1147
1176
|
const homeDir = os.homedir();
|
|
1148
1177
|
|
|
1149
1178
|
// Allow only safe characters in sessionId
|
|
@@ -1152,6 +1181,18 @@ app.get('/api/projects/:projectId/sessions/:sessionId/token-usage', authenticate
|
|
|
1152
1181
|
return res.status(400).json({ error: 'Invalid sessionId' });
|
|
1153
1182
|
}
|
|
1154
1183
|
|
|
1184
|
+
// Provider artifacts on disk (JSONL file names, OpenCode sqlite rows)
|
|
1185
|
+
// are keyed by the provider-native session id, while the caller sends
|
|
1186
|
+
// the app-facing id. Resolve provider and id mapping from the indexed
|
|
1187
|
+
// session row so the frontend does not choose provider-specific paths.
|
|
1188
|
+
const sessionRow = sessionsDb.getSessionById(safeSessionId);
|
|
1189
|
+
if (!sessionRow) {
|
|
1190
|
+
return res.status(404).json({ error: 'Session not found', sessionId: safeSessionId });
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
const provider = sessionRow.provider || 'claude';
|
|
1194
|
+
const providerNativeSessionId = sessionRow?.provider_session_id || safeSessionId;
|
|
1195
|
+
|
|
1155
1196
|
// Handle Cursor sessions - they use SQLite and don't have token usage info
|
|
1156
1197
|
if (provider === 'cursor') {
|
|
1157
1198
|
return res.json({
|
|
@@ -1252,7 +1293,7 @@ app.get('/api/projects/:projectId/sessions/:sessionId/token-usage', authenticate
|
|
|
1252
1293
|
tokens_cache_write AS cacheWriteTokens
|
|
1253
1294
|
FROM session
|
|
1254
1295
|
WHERE id = ?
|
|
1255
|
-
`).get(
|
|
1296
|
+
`).get(providerNativeSessionId);
|
|
1256
1297
|
|
|
1257
1298
|
if (!row) {
|
|
1258
1299
|
return res.status(404).json({ error: 'OpenCode session not found', sessionId: safeSessionId });
|
|
@@ -1293,7 +1334,7 @@ app.get('/api/projects/:projectId/sessions/:sessionId/token-usage', authenticate
|
|
|
1293
1334
|
if (entry.isDirectory()) {
|
|
1294
1335
|
const found = await findSessionFile(fullPath);
|
|
1295
1336
|
if (found) return found;
|
|
1296
|
-
} else if (entry.name.includes(
|
|
1337
|
+
} else if (entry.name.includes(providerNativeSessionId) && entry.name.endsWith('.jsonl')) {
|
|
1297
1338
|
return fullPath;
|
|
1298
1339
|
}
|
|
1299
1340
|
}
|
|
@@ -1377,12 +1418,19 @@ app.get('/api/projects/:projectId/sessions/:sessionId/token-usage', authenticate
|
|
|
1377
1418
|
const encodedPath = projectPath.replace(/[^a-zA-Z0-9-]/g, '-');
|
|
1378
1419
|
const projectDir = path.join(homeDir, '.claude', 'projects', encodedPath);
|
|
1379
1420
|
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
//
|
|
1383
|
-
|
|
1384
|
-
if (
|
|
1385
|
-
|
|
1421
|
+
// Prefer the indexed transcript path (already produced by the trusted
|
|
1422
|
+
// session synchronizer); fall back to the conventional location
|
|
1423
|
+
// derived from the provider-native session id.
|
|
1424
|
+
let jsonlPath = sessionRow?.jsonl_path;
|
|
1425
|
+
if (!jsonlPath) {
|
|
1426
|
+
jsonlPath = path.join(projectDir, `${providerNativeSessionId}.jsonl`);
|
|
1427
|
+
|
|
1428
|
+
// Constrain the constructed path to projectDir (the id is
|
|
1429
|
+
// caller-influenced in this fallback branch).
|
|
1430
|
+
const rel = path.relative(path.resolve(projectDir), path.resolve(jsonlPath));
|
|
1431
|
+
if (rel.startsWith('..') || path.isAbsolute(rel)) {
|
|
1432
|
+
return res.status(400).json({ error: 'Invalid path' });
|
|
1433
|
+
}
|
|
1386
1434
|
}
|
|
1387
1435
|
|
|
1388
1436
|
// Read and parse the JSONL file
|
|
@@ -1646,6 +1694,40 @@ const SERVER_PORT = process.env.SERVER_PORT || 3001;
|
|
|
1646
1694
|
const HOST = process.env.HOST || '0.0.0.0';
|
|
1647
1695
|
const DISPLAY_HOST = getConnectableHost(HOST);
|
|
1648
1696
|
const VITE_PORT = process.env.VITE_PORT || 5173;
|
|
1697
|
+
const LOCAL_SERVER_MARKER_PATH = path.join(os.homedir(), '.cloudcli', 'local-server.json');
|
|
1698
|
+
|
|
1699
|
+
async function writeLocalServerMarker() {
|
|
1700
|
+
const marker = {
|
|
1701
|
+
pid: process.pid,
|
|
1702
|
+
host: HOST,
|
|
1703
|
+
port: Number.parseInt(String(SERVER_PORT), 10),
|
|
1704
|
+
url: `http://${DISPLAY_HOST}:${SERVER_PORT}`,
|
|
1705
|
+
installMode,
|
|
1706
|
+
appRoot: APP_ROOT,
|
|
1707
|
+
updatedAt: new Date().toISOString(),
|
|
1708
|
+
};
|
|
1709
|
+
|
|
1710
|
+
await fsPromises.mkdir(path.dirname(LOCAL_SERVER_MARKER_PATH), { recursive: true });
|
|
1711
|
+
await fsPromises.writeFile(LOCAL_SERVER_MARKER_PATH, JSON.stringify(marker, null, 2), 'utf8');
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
async function removeLocalServerMarker() {
|
|
1715
|
+
try {
|
|
1716
|
+
const raw = await fsPromises.readFile(LOCAL_SERVER_MARKER_PATH, 'utf8');
|
|
1717
|
+
const marker = JSON.parse(raw);
|
|
1718
|
+
if (marker.pid && marker.pid !== process.pid) return;
|
|
1719
|
+
} catch (error) {
|
|
1720
|
+
if (error.code === 'ENOENT') return;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
try {
|
|
1724
|
+
await fsPromises.unlink(LOCAL_SERVER_MARKER_PATH);
|
|
1725
|
+
} catch (error) {
|
|
1726
|
+
if (error.code !== 'ENOENT') {
|
|
1727
|
+
console.warn('[WARN] Could not remove local server marker:', error.message);
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1649
1731
|
|
|
1650
1732
|
// Initialize database and start server
|
|
1651
1733
|
async function startServer() {
|
|
@@ -1672,6 +1754,9 @@ async function startServer() {
|
|
|
1672
1754
|
|
|
1673
1755
|
server.listen(SERVER_PORT, HOST, async () => {
|
|
1674
1756
|
const appInstallPath = APP_ROOT;
|
|
1757
|
+
await writeLocalServerMarker().catch((error) => {
|
|
1758
|
+
console.warn('[WARN] Could not write local server marker:', error.message);
|
|
1759
|
+
});
|
|
1675
1760
|
|
|
1676
1761
|
console.log('');
|
|
1677
1762
|
console.log(c.dim('═'.repeat(63)));
|
|
@@ -1694,12 +1779,31 @@ async function startServer() {
|
|
|
1694
1779
|
|
|
1695
1780
|
await closeSessionsWatcher();
|
|
1696
1781
|
// Clean up plugin processes on shutdown
|
|
1697
|
-
const
|
|
1698
|
-
|
|
1782
|
+
const shutdownRuntimeServices = async () => {
|
|
1783
|
+
try {
|
|
1784
|
+
await browserUseService.stopAllSessions();
|
|
1785
|
+
} catch (err) {
|
|
1786
|
+
console.error('[Browser] Error stopping sessions during shutdown:', err?.message || err);
|
|
1787
|
+
}
|
|
1788
|
+
try {
|
|
1789
|
+
await computerUseService.stopAllSessions();
|
|
1790
|
+
} catch (err) {
|
|
1791
|
+
console.error('[Computer Use] Error stopping sessions during shutdown:', err?.message || err);
|
|
1792
|
+
}
|
|
1793
|
+
try {
|
|
1794
|
+
await stopAllPlugins();
|
|
1795
|
+
} catch (err) {
|
|
1796
|
+
console.error('[Plugins] Error stopping plugins during shutdown:', err?.message || err);
|
|
1797
|
+
}
|
|
1798
|
+
try {
|
|
1799
|
+
await removeLocalServerMarker();
|
|
1800
|
+
} catch (err) {
|
|
1801
|
+
console.error('[Local Server] Error removing server marker during shutdown:', err?.message || err);
|
|
1802
|
+
}
|
|
1699
1803
|
process.exit(0);
|
|
1700
1804
|
};
|
|
1701
|
-
process.on('SIGTERM', () => void
|
|
1702
|
-
process.on('SIGINT', () => void
|
|
1805
|
+
process.on('SIGTERM', () => void shutdownRuntimeServices());
|
|
1806
|
+
process.on('SIGINT', () => void shutdownRuntimeServices());
|
|
1703
1807
|
} catch (error) {
|
|
1704
1808
|
console.error('[ERROR] Failed to start server:', error);
|
|
1705
1809
|
process.exit(1);
|
package/server/load-env.js
CHANGED
|
@@ -22,7 +22,7 @@ try {
|
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
} catch (e) {
|
|
25
|
-
console.
|
|
25
|
+
console.error('No .env file found or error reading it:', e.message);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// Keep the default database in a stable user-level location so rebuilding dist-server
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
|
|
3
|
+
import { browserUseService } from '@/modules/browser-use/browser-use.service.js';
|
|
4
|
+
|
|
5
|
+
const router = express.Router();
|
|
6
|
+
|
|
7
|
+
function readBearerToken(header: unknown): string | null {
|
|
8
|
+
if (typeof header !== 'string') {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const match = /^Bearer\s+(\S.*)$/i.exec(header.trim());
|
|
12
|
+
return match?.[1]?.trim() || null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
router.use((req, res, next) => {
|
|
16
|
+
const expected = browserUseService.getMcpToken();
|
|
17
|
+
const token = readBearerToken(req.headers.authorization) || String(req.headers['x-browser-use-mcp-token'] || '');
|
|
18
|
+
if (!token || token !== expected) {
|
|
19
|
+
res.status(401).json({ success: false, error: 'Invalid Browser MCP token.' });
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
next();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
router.post('/tools/:toolName', async (req, res) => {
|
|
26
|
+
try {
|
|
27
|
+
const input = (req.body && typeof req.body === 'object' ? req.body : {}) as Record<string, unknown>;
|
|
28
|
+
const sessionId = typeof input.sessionId === 'string' ? input.sessionId : '';
|
|
29
|
+
const toolName = req.params.toolName;
|
|
30
|
+
let result: unknown;
|
|
31
|
+
|
|
32
|
+
switch (toolName) {
|
|
33
|
+
case 'browser_create_session':
|
|
34
|
+
result = await browserUseService.createAgentSession({
|
|
35
|
+
profileName: typeof input.profileName === 'string' ? input.profileName : null,
|
|
36
|
+
});
|
|
37
|
+
break;
|
|
38
|
+
case 'browser_list_sessions':
|
|
39
|
+
result = await browserUseService.listAgentSessions();
|
|
40
|
+
break;
|
|
41
|
+
case 'browser_snapshot':
|
|
42
|
+
case 'browser_take_screenshot':
|
|
43
|
+
result = await browserUseService.agentSnapshot(sessionId);
|
|
44
|
+
break;
|
|
45
|
+
case 'browser_navigate':
|
|
46
|
+
result = await browserUseService.agentNavigate(sessionId, String(input.url || ''));
|
|
47
|
+
break;
|
|
48
|
+
case 'browser_click':
|
|
49
|
+
result = await browserUseService.agentClick(sessionId, {
|
|
50
|
+
selector: typeof input.selector === 'string' ? input.selector : undefined,
|
|
51
|
+
text: typeof input.text === 'string' ? input.text : undefined,
|
|
52
|
+
x: typeof input.x === 'number' ? input.x : undefined,
|
|
53
|
+
y: typeof input.y === 'number' ? input.y : undefined,
|
|
54
|
+
});
|
|
55
|
+
break;
|
|
56
|
+
case 'browser_type':
|
|
57
|
+
result = await browserUseService.agentType(sessionId, {
|
|
58
|
+
selector: typeof input.selector === 'string' ? input.selector : undefined,
|
|
59
|
+
text: String(input.text || ''),
|
|
60
|
+
submit: input.submit === true,
|
|
61
|
+
});
|
|
62
|
+
break;
|
|
63
|
+
case 'browser_fill_form':
|
|
64
|
+
result = await browserUseService.agentFillForm(
|
|
65
|
+
sessionId,
|
|
66
|
+
Array.isArray(input.fields)
|
|
67
|
+
? input.fields.map((field) => {
|
|
68
|
+
const record = field as Record<string, unknown>;
|
|
69
|
+
return {
|
|
70
|
+
selector: String(record.selector || ''),
|
|
71
|
+
value: String(record.value || ''),
|
|
72
|
+
};
|
|
73
|
+
})
|
|
74
|
+
: [],
|
|
75
|
+
);
|
|
76
|
+
break;
|
|
77
|
+
case 'browser_press_key':
|
|
78
|
+
result = await browserUseService.agentPressKey(sessionId, String(input.key || ''));
|
|
79
|
+
break;
|
|
80
|
+
case 'browser_select_option':
|
|
81
|
+
result = await browserUseService.agentSelectOption(
|
|
82
|
+
sessionId,
|
|
83
|
+
String(input.selector || ''),
|
|
84
|
+
Array.isArray(input.values) ? input.values.filter((value): value is string => typeof value === 'string') : [],
|
|
85
|
+
);
|
|
86
|
+
break;
|
|
87
|
+
case 'browser_wait_for':
|
|
88
|
+
result = await browserUseService.agentWaitFor(sessionId, {
|
|
89
|
+
text: typeof input.text === 'string' ? input.text : undefined,
|
|
90
|
+
url: typeof input.url === 'string' ? input.url : undefined,
|
|
91
|
+
timeoutMs: typeof input.timeoutMs === 'number' ? input.timeoutMs : undefined,
|
|
92
|
+
});
|
|
93
|
+
break;
|
|
94
|
+
case 'browser_tabs':
|
|
95
|
+
result = await browserUseService.agentTabs(sessionId, {
|
|
96
|
+
action: input.action === 'new' || input.action === 'select' || input.action === 'close' || input.action === 'list'
|
|
97
|
+
? input.action
|
|
98
|
+
: undefined,
|
|
99
|
+
index: typeof input.index === 'number' ? input.index : undefined,
|
|
100
|
+
url: typeof input.url === 'string' ? input.url : undefined,
|
|
101
|
+
});
|
|
102
|
+
break;
|
|
103
|
+
case 'browser_close_session':
|
|
104
|
+
result = await browserUseService.agentStopSession(sessionId);
|
|
105
|
+
break;
|
|
106
|
+
default:
|
|
107
|
+
res.status(404).json({ success: false, error: `Unknown Browser MCP tool "${toolName}".` });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
res.json({ success: true, data: result });
|
|
112
|
+
} catch (error) {
|
|
113
|
+
res.status(400).json({
|
|
114
|
+
success: false,
|
|
115
|
+
error: error instanceof Error ? error.message : 'Browser MCP tool failed.',
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
export default router;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
|
|
3
|
+
import { browserUseService } from '@/modules/browser-use/browser-use.service.js';
|
|
4
|
+
|
|
5
|
+
const router = express.Router();
|
|
6
|
+
|
|
7
|
+
function readParam(value: string | string[] | undefined): string {
|
|
8
|
+
return Array.isArray(value) ? value[0] || '' : value || '';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
router.get('/status', async (_req, res) => {
|
|
12
|
+
try {
|
|
13
|
+
res.json({ success: true, data: await browserUseService.getStatus() });
|
|
14
|
+
} catch (error) {
|
|
15
|
+
res.status(500).json({
|
|
16
|
+
success: false,
|
|
17
|
+
error: error instanceof Error ? error.message : 'Failed to load Browser status.',
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
router.get('/settings', async (_req, res) => {
|
|
23
|
+
try {
|
|
24
|
+
res.json({ success: true, data: { settings: await browserUseService.getSettings() } });
|
|
25
|
+
} catch (error) {
|
|
26
|
+
res.status(500).json({
|
|
27
|
+
success: false,
|
|
28
|
+
error: error instanceof Error ? error.message : 'Failed to load Browser settings.',
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
router.put('/settings', async (req, res) => {
|
|
34
|
+
try {
|
|
35
|
+
const settings = await browserUseService.updateSettings(req.body || {});
|
|
36
|
+
res.json({ success: true, data: { settings } });
|
|
37
|
+
} catch (error) {
|
|
38
|
+
res.status(400).json({
|
|
39
|
+
success: false,
|
|
40
|
+
error: error instanceof Error ? error.message : 'Failed to save Browser settings.',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
router.post('/runtime/install', async (_req, res) => {
|
|
46
|
+
try {
|
|
47
|
+
const result = await browserUseService.installRuntime();
|
|
48
|
+
res.status(result.success ? 200 : 500).json({
|
|
49
|
+
success: result.success,
|
|
50
|
+
data: result,
|
|
51
|
+
error: result.success ? undefined : result.message,
|
|
52
|
+
});
|
|
53
|
+
} catch (error) {
|
|
54
|
+
res.status(500).json({
|
|
55
|
+
success: false,
|
|
56
|
+
error: error instanceof Error ? error.message : 'Failed to install Browser runtime.',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
router.get('/sessions', async (_req, res) => {
|
|
62
|
+
try {
|
|
63
|
+
res.json({ success: true, data: { sessions: await browserUseService.listSessions() } });
|
|
64
|
+
} catch (error) {
|
|
65
|
+
res.status(401).json({
|
|
66
|
+
success: false,
|
|
67
|
+
error: error instanceof Error ? error.message : 'Failed to list browser sessions.',
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
router.post('/sessions/:sessionId/stop', async (req, res) => {
|
|
73
|
+
try {
|
|
74
|
+
const result = await browserUseService.stopSession(readParam(req.params.sessionId));
|
|
75
|
+
res.json({ success: true, data: result });
|
|
76
|
+
} catch (error) {
|
|
77
|
+
res.status(400).json({
|
|
78
|
+
success: false,
|
|
79
|
+
error: error instanceof Error ? error.message : 'Failed to stop browser session.',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
router.delete('/sessions/:sessionId', async (req, res) => {
|
|
85
|
+
try {
|
|
86
|
+
const result = await browserUseService.deleteSession(readParam(req.params.sessionId));
|
|
87
|
+
res.json({ success: true, data: result });
|
|
88
|
+
} catch (error) {
|
|
89
|
+
res.status(400).json({
|
|
90
|
+
success: false,
|
|
91
|
+
error: error instanceof Error ? error.message : 'Failed to delete browser session.',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export default router;
|