@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/shared/utils.ts
CHANGED
|
@@ -346,6 +346,84 @@ export function createNormalizedMessage(fields: NormalizedMessageInput): Normali
|
|
|
346
346
|
};
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
+
/**
|
|
350
|
+
* Build the unified terminal `complete` lifecycle message.
|
|
351
|
+
*
|
|
352
|
+
* Contract: every provider run ends with exactly one `complete` (the
|
|
353
|
+
* abort-session handler emits it on behalf of cancelled runs, so aborted runs
|
|
354
|
+
* must NOT emit their own). The frontend treats `complete` as the only
|
|
355
|
+
* terminal signal and never needs provider-specific handling:
|
|
356
|
+
*
|
|
357
|
+
* - `sessionId` — the id the client knows this run by ('' if never discovered)
|
|
358
|
+
* - `actualSessionId` — canonical id after the run; equals `sessionId` unless
|
|
359
|
+
* the provider rewrote it mid-run
|
|
360
|
+
* - `exitCode` — 0 on success; a missing/null code (e.g. killed process)
|
|
361
|
+
* is reported as failure
|
|
362
|
+
* - `success` — exitCode === 0 and not aborted
|
|
363
|
+
* - `aborted` — run was cancelled by the user
|
|
364
|
+
*/
|
|
365
|
+
export function createCompleteMessage(opts: {
|
|
366
|
+
provider: NormalizedMessage['provider'];
|
|
367
|
+
sessionId?: string | null;
|
|
368
|
+
actualSessionId?: string | null;
|
|
369
|
+
exitCode?: number | null;
|
|
370
|
+
aborted?: boolean;
|
|
371
|
+
}): NormalizedMessage {
|
|
372
|
+
const exitCode = typeof opts.exitCode === 'number' ? opts.exitCode : 1;
|
|
373
|
+
const aborted = Boolean(opts.aborted);
|
|
374
|
+
|
|
375
|
+
return createNormalizedMessage({
|
|
376
|
+
kind: 'complete',
|
|
377
|
+
provider: opts.provider,
|
|
378
|
+
sessionId: opts.sessionId || null,
|
|
379
|
+
actualSessionId: opts.actualSessionId || opts.sessionId || null,
|
|
380
|
+
exitCode,
|
|
381
|
+
success: exitCode === 0 && !aborted,
|
|
382
|
+
aborted,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// ---------------------------
|
|
387
|
+
//----------------- CONVERSATION HISTORY PAGINATION UTILITIES ------------
|
|
388
|
+
/**
|
|
389
|
+
* Slices one page from the END of a chronologically ordered message list.
|
|
390
|
+
*
|
|
391
|
+
* This is the single pagination contract for conversation history across all
|
|
392
|
+
* providers: `offset = 0` returns the most recent `limit` items, increasing
|
|
393
|
+
* offsets walk backwards in time (for "scroll up to load older" UIs), and a
|
|
394
|
+
* `null` limit returns everything. Items must already be sorted oldest-first;
|
|
395
|
+
* the returned page preserves that order.
|
|
396
|
+
*
|
|
397
|
+
* Every provider history reader must use this helper instead of slicing
|
|
398
|
+
* manually so `offset`/`limit` query params behave identically regardless of
|
|
399
|
+
* which provider produced the session.
|
|
400
|
+
*/
|
|
401
|
+
export function sliceTailPage<T>(
|
|
402
|
+
items: T[],
|
|
403
|
+
limit: number | null,
|
|
404
|
+
offset: number,
|
|
405
|
+
): { page: T[]; hasMore: boolean } {
|
|
406
|
+
const total = items.length;
|
|
407
|
+
const normalizedOffset = Math.max(0, offset);
|
|
408
|
+
|
|
409
|
+
if (limit === null) {
|
|
410
|
+
// A null limit returns the full list; offset still trims newest entries
|
|
411
|
+
// so "everything before the page I already have" stays expressible.
|
|
412
|
+
const end = Math.max(0, total - normalizedOffset);
|
|
413
|
+
return {
|
|
414
|
+
page: items.slice(0, end),
|
|
415
|
+
hasMore: false,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const end = Math.max(0, total - normalizedOffset);
|
|
420
|
+
const start = Math.max(0, end - Math.max(0, limit));
|
|
421
|
+
return {
|
|
422
|
+
page: items.slice(start, end),
|
|
423
|
+
hasMore: start > 0,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
349
427
|
// ---------------------------
|
|
350
428
|
//----------------- MCP CONFIG PARSING UTILITIES ------------
|
|
351
429
|
/**
|
|
@@ -879,9 +957,25 @@ export async function readProviderSkillMarkdownDefinition(
|
|
|
879
957
|
skillPath: string,
|
|
880
958
|
): Promise<{ name: string; description: string }> {
|
|
881
959
|
const content = await readFile(skillPath, 'utf8');
|
|
960
|
+
return readProviderSkillMarkdownDefinitionFromContent(
|
|
961
|
+
content,
|
|
962
|
+
path.basename(path.dirname(skillPath)),
|
|
963
|
+
);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Reads the `name` and `description` fields from raw skill markdown content.
|
|
968
|
+
*
|
|
969
|
+
* This keeps filesystem discovery and newly uploaded skill creation aligned on
|
|
970
|
+
* the same front matter parsing rules. `fallbackName` is used when the markdown
|
|
971
|
+
* omits a `name` field so callers still get a stable, non-empty skill id.
|
|
972
|
+
*/
|
|
973
|
+
export function readProviderSkillMarkdownDefinitionFromContent(
|
|
974
|
+
content: string,
|
|
975
|
+
fallbackName: string,
|
|
976
|
+
): { name: string; description: string } {
|
|
882
977
|
const parsed = parseFrontMatter(content);
|
|
883
978
|
const data = readObjectRecord(parsed.data) ?? {};
|
|
884
|
-
const fallbackName = path.basename(path.dirname(skillPath));
|
|
885
979
|
|
|
886
980
|
return {
|
|
887
981
|
name: readOptionalString(data.name) ?? fallbackName,
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// Optional voice proxy — forwards STT/TTS to an OpenAI-compatible audio backend.
|
|
2
|
+
//
|
|
3
|
+
// The backend is whatever the user points at: OpenAI, Groq, or a local server
|
|
4
|
+
// (LocalAI / Speaches / Kokoro-FastAPI / openedai-speech / etc.). It must expose the
|
|
5
|
+
// standard OpenAI audio endpoints:
|
|
6
|
+
// POST {base}/audio/transcriptions (multipart 'file' + 'model') -> { text }
|
|
7
|
+
// POST {base}/audio/speech ({ model, voice, input }) -> audio bytes
|
|
8
|
+
//
|
|
9
|
+
// Config is resolved per-request from headers (set by the client's voice settings),
|
|
10
|
+
// falling back to server env defaults. Mounted at /api/voice behind authenticateToken.
|
|
11
|
+
import { Readable } from 'node:stream';
|
|
12
|
+
|
|
13
|
+
import express from 'express';
|
|
14
|
+
|
|
15
|
+
const ENV = {
|
|
16
|
+
baseUrl: (process.env.VOICE_API_BASE_URL || '').replace(/\/$/, ''),
|
|
17
|
+
apiKey: process.env.VOICE_API_KEY || '',
|
|
18
|
+
sttModel: process.env.VOICE_STT_MODEL || 'whisper-1',
|
|
19
|
+
ttsModel: process.env.VOICE_TTS_MODEL || 'tts-1',
|
|
20
|
+
ttsVoice: process.env.VOICE_TTS_VOICE || 'alloy',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the voice backend config for a request. Client headers (set from the
|
|
25
|
+
* user's in-app voice settings) take precedence over the server env defaults.
|
|
26
|
+
* @param {import('express').Request} req
|
|
27
|
+
* @returns {{baseUrl: string, apiKey: string, sttModel: string, ttsModel: string, ttsVoice: string, ttsFormat: string}}
|
|
28
|
+
*/
|
|
29
|
+
function resolveConfig(req) {
|
|
30
|
+
const h = req.headers;
|
|
31
|
+
return {
|
|
32
|
+
// Security: do not allow clients to control the outbound backend host.
|
|
33
|
+
// Always use the server-side configured base URL.
|
|
34
|
+
baseUrl: ENV.baseUrl,
|
|
35
|
+
apiKey: String(h['x-voice-api-key'] || '') || ENV.apiKey,
|
|
36
|
+
sttModel: String(h['x-voice-stt-model'] || '') || ENV.sttModel,
|
|
37
|
+
ttsModel: String(h['x-voice-tts-model'] || '') || ENV.ttsModel,
|
|
38
|
+
ttsVoice: String(h['x-voice-tts-voice'] || '') || ENV.ttsVoice,
|
|
39
|
+
ttsFormat: String(h['x-voice-tts-format'] || '').trim(),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const router = express.Router();
|
|
44
|
+
|
|
45
|
+
// Generous by default — local TTS can synthesize long messages at ~real-time on CPU.
|
|
46
|
+
// Guard against a non-numeric/zero override that would make setTimeout fire immediately.
|
|
47
|
+
const DEFAULT_VOICE_TIMEOUT_MS = 300000;
|
|
48
|
+
const _parsedTimeout = Number(process.env.VOICE_TIMEOUT_MS);
|
|
49
|
+
const VOICE_TIMEOUT_MS = Number.isFinite(_parsedTimeout) && _parsedTimeout > 0
|
|
50
|
+
? _parsedTimeout
|
|
51
|
+
: DEFAULT_VOICE_TIMEOUT_MS;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* fetch() with an AbortController timeout so a stalled backend can't hold the
|
|
55
|
+
* request open indefinitely. Aborts after VOICE_TIMEOUT_MS.
|
|
56
|
+
* @param {string} url
|
|
57
|
+
* @param {RequestInit} [options]
|
|
58
|
+
* @returns {Promise<Response>}
|
|
59
|
+
*/
|
|
60
|
+
async function fetchWithTimeout(url, options = {}) {
|
|
61
|
+
const parsed = new URL(url);
|
|
62
|
+
if (!['http:', 'https:'].includes(parsed.protocol) || !isAllowedBackendUrl(parsed.origin)) {
|
|
63
|
+
throw new Error('Blocked outbound voice backend URL');
|
|
64
|
+
}
|
|
65
|
+
const controller = new AbortController();
|
|
66
|
+
const timer = setTimeout(() => controller.abort(), VOICE_TIMEOUT_MS);
|
|
67
|
+
try {
|
|
68
|
+
return await fetch(parsed.toString(), { redirect: 'manual', ...options, signal: controller.signal });
|
|
69
|
+
} finally {
|
|
70
|
+
clearTimeout(timer);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Turn a backend fetch failure into a clear, actionable client response:
|
|
76
|
+
* 504 on timeout (AbortError), 502 otherwise.
|
|
77
|
+
* @param {import('express').Response} res
|
|
78
|
+
* @param {Error} e
|
|
79
|
+
*/
|
|
80
|
+
function backendError(res, e) {
|
|
81
|
+
if (e && e.name === 'AbortError') {
|
|
82
|
+
return res.status(504).json({
|
|
83
|
+
error: `Voice backend timed out after ${Math.round(VOICE_TIMEOUT_MS / 1000)}s. Check your voice backend.`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return res.status(502).json({ error: `Voice backend unreachable: ${e.message}` });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* SSRF guard for the user-configurable backend URL: allow http/https only and
|
|
91
|
+
* block the link-local / cloud-metadata range (169.254.x). localhost and private
|
|
92
|
+
* ranges are allowed on purpose so users can point at a local voice server
|
|
93
|
+
* (LocalAI, Speaches, Kokoro-FastAPI, etc.).
|
|
94
|
+
* @param {string} raw
|
|
95
|
+
* @returns {boolean}
|
|
96
|
+
*/
|
|
97
|
+
function isAllowedBackendUrl(raw) {
|
|
98
|
+
let u;
|
|
99
|
+
try {
|
|
100
|
+
u = new URL(raw);
|
|
101
|
+
} catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (u.protocol !== 'http:' && u.protocol !== 'https:') return false;
|
|
105
|
+
if (u.hostname === '169.254.169.254' || u.hostname.startsWith('169.254.')) return false;
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Relay an upstream (backend) error to the client without making an upstream
|
|
111
|
+
* 401/403 look like the user's own app login failed.
|
|
112
|
+
* @param {import('express').Response} res
|
|
113
|
+
* @param {number} status
|
|
114
|
+
* @param {string} [text]
|
|
115
|
+
*/
|
|
116
|
+
function upstreamError(res, status, text) {
|
|
117
|
+
if (status === 401 || status === 403) {
|
|
118
|
+
return res.status(502).json({ error: 'Voice backend rejected the request (check the API key).' });
|
|
119
|
+
}
|
|
120
|
+
return res.status(status).json({ error: text || 'voice backend error' });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let _upload = null;
|
|
124
|
+
/**
|
|
125
|
+
* Lazily build a memory-storage multer instance (25 MB cap) for audio uploads,
|
|
126
|
+
* so multer is only imported when the voice feature is actually used.
|
|
127
|
+
* @returns {Promise<import('multer').Multer>}
|
|
128
|
+
*/
|
|
129
|
+
async function getUpload() {
|
|
130
|
+
if (!_upload) {
|
|
131
|
+
const multer = (await import('multer')).default;
|
|
132
|
+
_upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 25 * 1024 * 1024 } });
|
|
133
|
+
}
|
|
134
|
+
return _upload;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Build the Authorization header for the backend, or an empty object when no
|
|
139
|
+
* key is configured (e.g. a local server that needs none).
|
|
140
|
+
* @param {string} apiKey
|
|
141
|
+
* @returns {Record<string, string>}
|
|
142
|
+
*/
|
|
143
|
+
function authHeader(apiKey) {
|
|
144
|
+
return apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* GET /api/voice/health -> { configured } (true when a backend base URL is set).
|
|
149
|
+
*/
|
|
150
|
+
router.get('/health', (req, res) => {
|
|
151
|
+
res.json({ configured: Boolean(resolveConfig(req).baseUrl) });
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* POST /api/voice/transcribe (multipart 'audio') -> { text }.
|
|
156
|
+
* Forwards the uploaded audio to the backend's /audio/transcriptions endpoint.
|
|
157
|
+
*/
|
|
158
|
+
router.post('/transcribe', async (req, res) => {
|
|
159
|
+
const cfg = resolveConfig(req);
|
|
160
|
+
if (!cfg.baseUrl) return res.status(503).json({ error: 'No voice backend configured' });
|
|
161
|
+
if (!isAllowedBackendUrl(cfg.baseUrl)) return res.status(400).json({ error: 'Invalid voice backend URL.' });
|
|
162
|
+
const upload = await getUpload();
|
|
163
|
+
upload.single('audio')(req, res, async (err) => {
|
|
164
|
+
if (err) return res.status(400).json({ error: err.message });
|
|
165
|
+
if (!req.file) return res.status(400).json({ error: 'No audio uploaded' });
|
|
166
|
+
try {
|
|
167
|
+
const fd = new FormData();
|
|
168
|
+
fd.append(
|
|
169
|
+
'file',
|
|
170
|
+
new Blob([req.file.buffer], { type: req.file.mimetype || 'audio/webm' }),
|
|
171
|
+
req.file.originalname || 'recording.webm',
|
|
172
|
+
);
|
|
173
|
+
fd.append('model', cfg.sttModel);
|
|
174
|
+
const r = await fetchWithTimeout(`${cfg.baseUrl}/audio/transcriptions`, {
|
|
175
|
+
method: 'POST',
|
|
176
|
+
headers: authHeader(cfg.apiKey),
|
|
177
|
+
body: fd,
|
|
178
|
+
});
|
|
179
|
+
const text = await r.text();
|
|
180
|
+
if (!r.ok) return upstreamError(res, r.status, text);
|
|
181
|
+
let data;
|
|
182
|
+
try { data = JSON.parse(text); } catch { data = { text }; }
|
|
183
|
+
res.json({ text: data.text ?? '' });
|
|
184
|
+
} catch (e) {
|
|
185
|
+
backendError(res, e);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* POST /api/voice/tts { text } -> audio bytes.
|
|
192
|
+
* Forwards the text to the backend's /audio/speech endpoint and streams the audio back.
|
|
193
|
+
*/
|
|
194
|
+
router.post('/tts', async (req, res) => {
|
|
195
|
+
const cfg = resolveConfig(req);
|
|
196
|
+
if (!cfg.baseUrl) return res.status(503).json({ error: 'No voice backend configured' });
|
|
197
|
+
if (!isAllowedBackendUrl(cfg.baseUrl)) return res.status(400).json({ error: 'Invalid voice backend URL.' });
|
|
198
|
+
const text = req.body?.text;
|
|
199
|
+
if (typeof text !== 'string' || !text.trim()) return res.status(400).json({ error: 'text required' });
|
|
200
|
+
try {
|
|
201
|
+
const r = await fetchWithTimeout(`${cfg.baseUrl}/audio/speech`, {
|
|
202
|
+
method: 'POST',
|
|
203
|
+
headers: { 'Content-Type': 'application/json', ...authHeader(cfg.apiKey) },
|
|
204
|
+
body: JSON.stringify({
|
|
205
|
+
model: cfg.ttsModel,
|
|
206
|
+
voice: cfg.ttsVoice,
|
|
207
|
+
input: text,
|
|
208
|
+
...(cfg.ttsFormat ? { response_format: cfg.ttsFormat } : {}),
|
|
209
|
+
}),
|
|
210
|
+
});
|
|
211
|
+
if (!r.ok) {
|
|
212
|
+
const errText = await r.text().catch(() => 'tts failed');
|
|
213
|
+
return upstreamError(res, r.status, errText);
|
|
214
|
+
}
|
|
215
|
+
res.setHeader('Content-Type', r.headers.get('content-type') || 'audio/mpeg');
|
|
216
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
217
|
+
if (!r.body) return res.end();
|
|
218
|
+
Readable.fromWeb(r.body).on('error', (error) => res.destroy(error)).pipe(res);
|
|
219
|
+
} catch (e) {
|
|
220
|
+
backendError(res, e);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
export default router;
|