@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
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { WebSocket } from 'ws';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
registerDesktopNotificationClient,
|
|
5
|
+
unregisterDesktopNotificationClient,
|
|
6
|
+
} from '@/modules/notifications/services/desktop-notification-clients.service.js';
|
|
7
|
+
import type { AuthenticatedWebSocketRequest } from '@/shared/types.js';
|
|
8
|
+
import { parseIncomingJsonObject } from '@/shared/utils.js';
|
|
9
|
+
|
|
10
|
+
type DesktopNotificationRegisterMessage = {
|
|
11
|
+
type?: unknown;
|
|
12
|
+
kind?: unknown;
|
|
13
|
+
deviceId?: unknown;
|
|
14
|
+
label?: unknown;
|
|
15
|
+
platform?: unknown;
|
|
16
|
+
appVersion?: unknown;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function readRequestUserId(request: AuthenticatedWebSocketRequest): number | null {
|
|
20
|
+
const user = request.user;
|
|
21
|
+
const rawUserId = typeof user?.id === 'number' || typeof user?.id === 'string'
|
|
22
|
+
? user.id
|
|
23
|
+
: typeof user?.userId === 'number' || typeof user?.userId === 'string'
|
|
24
|
+
? user.userId
|
|
25
|
+
: null;
|
|
26
|
+
const numericUserId = Number(rawUserId);
|
|
27
|
+
return Number.isInteger(numericUserId) && numericUserId > 0 ? numericUserId : null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function readOptionalString(value: unknown): string | null {
|
|
31
|
+
if (typeof value !== 'string') return null;
|
|
32
|
+
const normalized = value.trim();
|
|
33
|
+
return normalized || null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function sendJson(ws: WebSocket, payload: unknown): void {
|
|
37
|
+
if (ws.readyState === ws.OPEN) {
|
|
38
|
+
ws.send(JSON.stringify(payload));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function handleDesktopNotificationsConnection(
|
|
43
|
+
ws: WebSocket,
|
|
44
|
+
request: AuthenticatedWebSocketRequest
|
|
45
|
+
): void {
|
|
46
|
+
const userId = readRequestUserId(request);
|
|
47
|
+
if (!userId) {
|
|
48
|
+
ws.close(1008, 'Missing authenticated user');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let registered = false;
|
|
53
|
+
|
|
54
|
+
ws.on('message', (rawMessage) => {
|
|
55
|
+
const data = parseIncomingJsonObject(rawMessage) as DesktopNotificationRegisterMessage | null;
|
|
56
|
+
if (!data) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const type = typeof data.type === 'string' ? data.type : typeof data.kind === 'string' ? data.kind : '';
|
|
61
|
+
if (type === 'notification_ack') {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (type !== 'register' || registered) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const deviceId = readOptionalString(data.deviceId);
|
|
70
|
+
if (!deviceId) {
|
|
71
|
+
sendJson(ws, {
|
|
72
|
+
type: 'error',
|
|
73
|
+
code: 'DEVICE_ID_REQUIRED',
|
|
74
|
+
message: 'Desktop notification registration requires deviceId.',
|
|
75
|
+
});
|
|
76
|
+
ws.close(1008, 'Missing deviceId');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const device = registerDesktopNotificationClient({
|
|
81
|
+
userId,
|
|
82
|
+
deviceId,
|
|
83
|
+
label: readOptionalString(data.label),
|
|
84
|
+
platform: readOptionalString(data.platform),
|
|
85
|
+
appVersion: readOptionalString(data.appVersion),
|
|
86
|
+
ws,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (!device) {
|
|
90
|
+
ws.close(1011, 'Registration failed');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
registered = true;
|
|
95
|
+
sendJson(ws, {
|
|
96
|
+
type: 'registered',
|
|
97
|
+
deviceId: device.endpoint_id,
|
|
98
|
+
enabled: Boolean(device.enabled),
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
ws.on('close', () => {
|
|
103
|
+
unregisterDesktopNotificationClient(ws);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
ws.on('error', () => {
|
|
107
|
+
unregisterDesktopNotificationClient(ws);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
@@ -30,10 +30,6 @@ type ProjectApiView = {
|
|
|
30
30
|
isArchived: boolean;
|
|
31
31
|
isStarred: boolean;
|
|
32
32
|
sessions: [];
|
|
33
|
-
cursorSessions: [];
|
|
34
|
-
codexSessions: [];
|
|
35
|
-
geminiSessions: [];
|
|
36
|
-
opencodeSessions: [];
|
|
37
33
|
sessionMeta: {
|
|
38
34
|
hasMore: false;
|
|
39
35
|
total: 0;
|
|
@@ -82,10 +78,6 @@ function mapProjectRowToApiView(projectRow: ProjectRepositoryRow): ProjectApiVie
|
|
|
82
78
|
isArchived: Boolean(projectRow.isArchived),
|
|
83
79
|
isStarred: Boolean(projectRow.isStarred),
|
|
84
80
|
sessions: [],
|
|
85
|
-
cursorSessions: [],
|
|
86
|
-
codexSessions: [],
|
|
87
|
-
geminiSessions: [],
|
|
88
|
-
opencodeSessions: [],
|
|
89
81
|
sessionMeta: {
|
|
90
82
|
hasMore: false,
|
|
91
83
|
total: 0,
|
|
@@ -9,13 +9,12 @@ import { AppError } from '@/shared/utils.js';
|
|
|
9
9
|
|
|
10
10
|
type SessionSummary = {
|
|
11
11
|
id: string;
|
|
12
|
+
provider: string;
|
|
12
13
|
summary: string;
|
|
13
14
|
messageCount: number;
|
|
14
15
|
lastActivity: string;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
|
-
type SessionsByProvider = Record<'claude' | 'cursor' | 'codex' | 'gemini' | 'opencode', SessionSummary[]>;
|
|
18
|
-
|
|
19
18
|
type SessionRepositoryRow = {
|
|
20
19
|
provider: string;
|
|
21
20
|
session_id: string;
|
|
@@ -31,10 +30,6 @@ export type ProjectListItem = {
|
|
|
31
30
|
fullPath: string;
|
|
32
31
|
isStarred: boolean;
|
|
33
32
|
sessions: SessionSummary[];
|
|
34
|
-
cursorSessions: SessionSummary[];
|
|
35
|
-
codexSessions: SessionSummary[];
|
|
36
|
-
geminiSessions: SessionSummary[];
|
|
37
|
-
opencodeSessions: SessionSummary[];
|
|
38
33
|
sessionMeta: {
|
|
39
34
|
hasMore: boolean;
|
|
40
35
|
total: number;
|
|
@@ -64,7 +59,7 @@ type SessionPaginationOptions = {
|
|
|
64
59
|
};
|
|
65
60
|
|
|
66
61
|
type ProjectSessionsPageResult = {
|
|
67
|
-
|
|
62
|
+
sessions: SessionSummary[];
|
|
68
63
|
total: number;
|
|
69
64
|
hasMore: boolean;
|
|
70
65
|
};
|
|
@@ -72,10 +67,6 @@ type ProjectSessionsPageResult = {
|
|
|
72
67
|
export type ProjectSessionsPageApiView = {
|
|
73
68
|
projectId: string;
|
|
74
69
|
sessions: SessionSummary[];
|
|
75
|
-
cursorSessions: SessionSummary[];
|
|
76
|
-
codexSessions: SessionSummary[];
|
|
77
|
-
geminiSessions: SessionSummary[];
|
|
78
|
-
opencodeSessions: SessionSummary[];
|
|
79
70
|
sessionMeta: {
|
|
80
71
|
hasMore: boolean;
|
|
81
72
|
total: number;
|
|
@@ -129,39 +120,18 @@ function normalizeSessionPagination(options: SessionPaginationOptions = {}): { l
|
|
|
129
120
|
function mapSessionRowToSummary(row: SessionRepositoryRow): SessionSummary {
|
|
130
121
|
return {
|
|
131
122
|
id: row.session_id,
|
|
123
|
+
provider: row.provider,
|
|
132
124
|
summary: row.custom_name || '',
|
|
133
125
|
messageCount: 0,
|
|
134
126
|
lastActivity: row.updated_at ?? row.created_at ?? new Date().toISOString(),
|
|
135
127
|
};
|
|
136
128
|
}
|
|
137
129
|
|
|
138
|
-
function bucketSessionRowsByProvider(rows: SessionRepositoryRow[]): SessionsByProvider {
|
|
139
|
-
const byProvider: SessionsByProvider = {
|
|
140
|
-
claude: [],
|
|
141
|
-
cursor: [],
|
|
142
|
-
codex: [],
|
|
143
|
-
gemini: [],
|
|
144
|
-
opencode: [],
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
for (const row of rows) {
|
|
148
|
-
const provider = row.provider as keyof SessionsByProvider;
|
|
149
|
-
const bucket = byProvider[provider];
|
|
150
|
-
if (!bucket) {
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
bucket.push(mapSessionRowToSummary(row));
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return byProvider;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
130
|
function readProjectSessionsIncludingArchived(projectPath: string): ProjectSessionsPageResult {
|
|
161
131
|
const rows = sessionsDb.getSessionsByProjectPathIncludingArchived(projectPath) as SessionRepositoryRow[];
|
|
162
132
|
|
|
163
133
|
return {
|
|
164
|
-
|
|
134
|
+
sessions: rows.map(mapSessionRowToSummary),
|
|
165
135
|
total: rows.length,
|
|
166
136
|
hasMore: false,
|
|
167
137
|
};
|
|
@@ -183,16 +153,17 @@ function readProjectSessionsPageByPath(
|
|
|
183
153
|
const total = sessionsDb.countSessionsByProjectPath(projectPath);
|
|
184
154
|
|
|
185
155
|
return {
|
|
186
|
-
|
|
156
|
+
sessions: rows.map(mapSessionRowToSummary),
|
|
187
157
|
total,
|
|
188
158
|
hasMore: pagination.offset + rows.length < total,
|
|
189
159
|
};
|
|
190
160
|
}
|
|
191
161
|
|
|
192
|
-
// Broadcast progress to all connected WebSocket clients
|
|
162
|
+
// Broadcast progress to all connected WebSocket clients.
|
|
163
|
+
// Uses the unified `kind` envelope like every other websocket frame.
|
|
193
164
|
function broadcastProgress(progress: ProgressUpdate) {
|
|
194
165
|
const message = JSON.stringify({
|
|
195
|
-
|
|
166
|
+
kind: 'loading_progress',
|
|
196
167
|
...progress,
|
|
197
168
|
});
|
|
198
169
|
|
|
@@ -204,7 +175,7 @@ function broadcastProgress(progress: ProgressUpdate) {
|
|
|
204
175
|
}
|
|
205
176
|
|
|
206
177
|
/**
|
|
207
|
-
* Reads all projects from DB and returns
|
|
178
|
+
* Reads all projects from DB and returns normalized session summaries.
|
|
208
179
|
*/
|
|
209
180
|
export async function getProjectsWithSessions(
|
|
210
181
|
options: GetProjectsWithSessionsOptions = {}
|
|
@@ -252,11 +223,7 @@ export async function getProjectsWithSessions(
|
|
|
252
223
|
displayName,
|
|
253
224
|
fullPath: projectPath,
|
|
254
225
|
isStarred: Boolean(row.isStarred),
|
|
255
|
-
sessions: sessionsPage.
|
|
256
|
-
cursorSessions: sessionsPage.sessionsByProvider.cursor,
|
|
257
|
-
codexSessions: sessionsPage.sessionsByProvider.codex,
|
|
258
|
-
geminiSessions: sessionsPage.sessionsByProvider.gemini,
|
|
259
|
-
opencodeSessions: sessionsPage.sessionsByProvider.opencode,
|
|
226
|
+
sessions: sessionsPage.sessions,
|
|
260
227
|
sessionMeta: {
|
|
261
228
|
hasMore: sessionsPage.hasMore,
|
|
262
229
|
total: sessionsPage.total,
|
|
@@ -309,11 +276,7 @@ export async function getArchivedProjectsWithSessions(
|
|
|
309
276
|
fullPath: row.project_path,
|
|
310
277
|
isStarred: Boolean(row.isStarred),
|
|
311
278
|
isArchived: true,
|
|
312
|
-
sessions: sessionsPage.
|
|
313
|
-
cursorSessions: sessionsPage.sessionsByProvider.cursor,
|
|
314
|
-
codexSessions: sessionsPage.sessionsByProvider.codex,
|
|
315
|
-
geminiSessions: sessionsPage.sessionsByProvider.gemini,
|
|
316
|
-
opencodeSessions: sessionsPage.sessionsByProvider.opencode,
|
|
279
|
+
sessions: sessionsPage.sessions,
|
|
317
280
|
sessionMeta: {
|
|
318
281
|
hasMore: sessionsPage.hasMore,
|
|
319
282
|
total: sessionsPage.total,
|
|
@@ -342,11 +305,7 @@ export async function getProjectSessionsPage(
|
|
|
342
305
|
const sessionsPage = readProjectSessionsPageByPath(projectRow.project_path, options);
|
|
343
306
|
return {
|
|
344
307
|
projectId: projectRow.project_id,
|
|
345
|
-
sessions: sessionsPage.
|
|
346
|
-
cursorSessions: sessionsPage.sessionsByProvider.cursor,
|
|
347
|
-
codexSessions: sessionsPage.sessionsByProvider.codex,
|
|
348
|
-
geminiSessions: sessionsPage.sessionsByProvider.gemini,
|
|
349
|
-
opencodeSessions: sessionsPage.sessionsByProvider.opencode,
|
|
308
|
+
sessions: sessionsPage.sessions,
|
|
350
309
|
sessionMeta: {
|
|
351
310
|
hasMore: sessionsPage.hasMore,
|
|
352
311
|
total: sessionsPage.total,
|
|
@@ -83,7 +83,7 @@ The existing provider folders are `claude`, `codex`, `cursor`, `gemini`, and
|
|
|
83
83
|
- Update `server/modules/providers/provider.routes.ts`.
|
|
84
84
|
- Update `server/routes/agent.js` if the provider is launchable from the agent runtime.
|
|
85
85
|
- Update `server/index.js` if the provider needs runtime boot or shutdown wiring.
|
|
86
|
-
- Update `public/
|
|
86
|
+
- Update the `PROVIDER_ORDER` list in `public/api-docs.html` if the provider should appear in the public API docs.
|
|
87
87
|
- Update `src/components/chat/hooks/useChatProviderState.ts` and
|
|
88
88
|
`src/components/chat/view/subcomponents/ProviderSelectionEmptyState.tsx` if
|
|
89
89
|
the provider should be selectable in chat.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { sessionSynchronizerService } from './services/session-synchronizer.service.js';
|
|
2
2
|
export { providerSkillsService } from './services/skills.service.js';
|
|
3
|
+
export { providerMcpService } from './services/mcp.service.js';
|
|
3
4
|
|
|
4
5
|
export { initializeSessionsWatcher } from './services/sessions-watcher.service.js';
|
|
5
6
|
export { closeSessionsWatcher } from './services/sessions-watcher.service.js';
|
|
@@ -20,6 +20,11 @@ export const CLAUDE_FALLBACK_MODELS: ProviderModelsDefinition = {
|
|
|
20
20
|
label: 'Default (recommended)',
|
|
21
21
|
description: 'Use the default model (currently Opus 4.8 (1M context)) · $5/$25 per Mtok',
|
|
22
22
|
},
|
|
23
|
+
{
|
|
24
|
+
value: 'fable',
|
|
25
|
+
label: 'Fable',
|
|
26
|
+
description: 'Fable 5 · Most capable for your hardest and longest-running tasks · Uses your limits ~2× faster than Opus',
|
|
27
|
+
},
|
|
23
28
|
{
|
|
24
29
|
value: "sonnet",
|
|
25
30
|
label: "Sonnet",
|
|
@@ -25,6 +25,21 @@ export class ClaudeSessionSynchronizer implements IProviderSessionSynchronizer {
|
|
|
25
25
|
private readonly provider = 'claude' as const;
|
|
26
26
|
private readonly claudeHome = path.join(os.homedir(), '.claude');
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Returns true when a JSONL file is a subagent transcript rather than a
|
|
30
|
+
* top-level session.
|
|
31
|
+
*
|
|
32
|
+
* Claude stores subagent transcripts under a `subagents/` directory, e.g.
|
|
33
|
+
* `~/.claude/projects/<encoded-cwd>/<session-id>/subagents/agent-<id>.jsonl`.
|
|
34
|
+
* Those files repeat the parent session's `sessionId`, so indexing them as
|
|
35
|
+
* standalone sessions overwrites the parent row's `jsonl_path` and corrupts
|
|
36
|
+
* the main session record. The recursive scan in `synchronize()` reaches
|
|
37
|
+
* them, so both entry points must skip them.
|
|
38
|
+
*/
|
|
39
|
+
private isSubagentTranscript(filePath: string): boolean {
|
|
40
|
+
return path.normalize(filePath).split(path.sep).includes('subagents');
|
|
41
|
+
}
|
|
42
|
+
|
|
28
43
|
/**
|
|
29
44
|
* Scans ~/.claude/projects and upserts discovered sessions into DB.
|
|
30
45
|
*/
|
|
@@ -38,6 +53,10 @@ export class ClaudeSessionSynchronizer implements IProviderSessionSynchronizer {
|
|
|
38
53
|
|
|
39
54
|
let processed = 0;
|
|
40
55
|
for (const filePath of files) {
|
|
56
|
+
if (this.isSubagentTranscript(filePath)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
41
60
|
const parsed = await this.processSessionFile(filePath, nameMap);
|
|
42
61
|
if (!parsed) {
|
|
43
62
|
continue;
|
|
@@ -66,6 +85,9 @@ export class ClaudeSessionSynchronizer implements IProviderSessionSynchronizer {
|
|
|
66
85
|
if (!filePath.endsWith('.jsonl')) {
|
|
67
86
|
return null;
|
|
68
87
|
}
|
|
88
|
+
if (this.isSubagentTranscript(filePath)) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
69
91
|
|
|
70
92
|
const nameMap = await buildLookupMap(path.join(this.claudeHome, 'history.jsonl'), 'sessionId', 'display');
|
|
71
93
|
const parsed = await this.processSessionFile(filePath, nameMap);
|
|
@@ -111,7 +133,10 @@ export class ClaudeSessionSynchronizer implements IProviderSessionSynchronizer {
|
|
|
111
133
|
return null;
|
|
112
134
|
}
|
|
113
135
|
|
|
114
|
-
|
|
136
|
+
// App-created sessions are keyed by an app id, so disk-discovered provider
|
|
137
|
+
// ids must be resolved through the provider-id mapping first.
|
|
138
|
+
const existingSession = sessionsDb.getSessionByProviderSessionId(parsed.sessionId)
|
|
139
|
+
?? sessionsDb.getSessionById(parsed.sessionId);
|
|
115
140
|
const existingSessionName = existingSession?.custom_name;
|
|
116
141
|
if (existingSessionName && existingSessionName !== 'Untitled Claude Session') {
|
|
117
142
|
return {
|
|
@@ -5,7 +5,7 @@ import readline from 'node:readline';
|
|
|
5
5
|
|
|
6
6
|
import type { IProviderSessions } from '@/shared/interfaces.js';
|
|
7
7
|
import type { AnyRecord, FetchHistoryOptions, FetchHistoryResult, NormalizedMessage } from '@/shared/types.js';
|
|
8
|
-
import { createNormalizedMessage, generateMessageId, readObjectRecord } from '@/shared/utils.js';
|
|
8
|
+
import { createNormalizedMessage, generateMessageId, readObjectRecord, sliceTailPage } from '@/shared/utils.js';
|
|
9
9
|
import { sessionsDb } from '@/modules/database/index.js';
|
|
10
10
|
|
|
11
11
|
const PROVIDER = 'claude';
|
|
@@ -103,10 +103,13 @@ async function parseAgentTools(filePath: string): Promise<AnyRecord[]> {
|
|
|
103
103
|
|
|
104
104
|
async function getSessionMessages(
|
|
105
105
|
sessionId: string,
|
|
106
|
+
providerSessionId: string,
|
|
106
107
|
limit: number | null,
|
|
107
108
|
offset: number,
|
|
108
109
|
): Promise<ClaudeHistoryMessagesResult> {
|
|
109
110
|
try {
|
|
111
|
+
// The DB row is keyed by the app-facing session id, while the JSONL rows
|
|
112
|
+
// on disk carry the provider-native id — both ids are needed here.
|
|
110
113
|
const jsonLPath = sessionsDb.getSessionById(sessionId)?.jsonl_path;
|
|
111
114
|
|
|
112
115
|
if (!jsonLPath) {
|
|
@@ -133,7 +136,7 @@ async function getSessionMessages(
|
|
|
133
136
|
|
|
134
137
|
try {
|
|
135
138
|
const entry = JSON.parse(line) as AnyRecord;
|
|
136
|
-
if (entry.sessionId ===
|
|
139
|
+
if (entry.sessionId === providerSessionId) {
|
|
137
140
|
messages.push(entry);
|
|
138
141
|
}
|
|
139
142
|
} catch {
|
|
@@ -553,12 +556,13 @@ export class ClaudeSessionsProvider implements IProviderSessions {
|
|
|
553
556
|
options: FetchHistoryOptions = {},
|
|
554
557
|
): Promise<FetchHistoryResult> {
|
|
555
558
|
const { limit = null, offset = 0 } = options;
|
|
559
|
+
const providerSessionId = options.providerSessionId ?? sessionId;
|
|
556
560
|
|
|
557
561
|
let result: ClaudeHistoryResult;
|
|
558
562
|
try {
|
|
559
563
|
// Load full history first so `total` reflects frontend-normalized messages,
|
|
560
564
|
// not raw JSONL records.
|
|
561
|
-
result = await getSessionMessages(sessionId, null, 0);
|
|
565
|
+
result = await getSessionMessages(sessionId, providerSessionId, null, 0);
|
|
562
566
|
} catch (error) {
|
|
563
567
|
const message = error instanceof Error ? error.message : String(error);
|
|
564
568
|
console.warn(`[ClaudeProvider] Failed to load session ${sessionId}:`, message);
|
|
@@ -606,7 +610,6 @@ export class ClaudeSessionsProvider implements IProviderSessions {
|
|
|
606
610
|
}
|
|
607
611
|
}
|
|
608
612
|
|
|
609
|
-
const totalNormalized = normalized.length;
|
|
610
613
|
let total = 0;
|
|
611
614
|
for (const msg of normalized) {
|
|
612
615
|
if (msg.kind !== 'tool_result') {
|
|
@@ -615,18 +618,10 @@ export class ClaudeSessionsProvider implements IProviderSessions {
|
|
|
615
618
|
}
|
|
616
619
|
const normalizedOffset = Math.max(0, offset);
|
|
617
620
|
const normalizedLimit = limit === null ? null : Math.max(0, limit);
|
|
618
|
-
const
|
|
619
|
-
? normalized
|
|
620
|
-
: normalized.slice(
|
|
621
|
-
Math.max(0, totalNormalized - normalizedOffset - normalizedLimit),
|
|
622
|
-
Math.max(0, totalNormalized - normalizedOffset),
|
|
623
|
-
);
|
|
624
|
-
const hasMore = normalizedLimit === null
|
|
625
|
-
? false
|
|
626
|
-
: Math.max(0, totalNormalized - normalizedOffset - normalizedLimit) > 0;
|
|
621
|
+
const { page, hasMore } = sliceTailPage(normalized, normalizedLimit, normalizedOffset);
|
|
627
622
|
|
|
628
623
|
return {
|
|
629
|
-
messages,
|
|
624
|
+
messages: page,
|
|
630
625
|
total,
|
|
631
626
|
hasMore,
|
|
632
627
|
offset: normalizedOffset,
|
|
@@ -99,6 +99,14 @@ export class ClaudeSkillsProvider extends SkillsProvider {
|
|
|
99
99
|
];
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
protected async getGlobalSkillSource(): Promise<ProviderSkillSource> {
|
|
103
|
+
return {
|
|
104
|
+
scope: 'user',
|
|
105
|
+
rootDir: path.join(getClaudeHomePath(), 'skills'),
|
|
106
|
+
commandPrefix: '/',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
102
110
|
private async listPluginSkills(claudeHomePath: string): Promise<ProviderSkill[]> {
|
|
103
111
|
const settings = await readJsonConfig(path.join(claudeHomePath, 'settings.json'));
|
|
104
112
|
const enabledPlugins = readObjectRecord(settings.enabledPlugins);
|
|
@@ -43,11 +43,12 @@ export class CodexSessionSynchronizer implements IProviderSessionSynchronizer {
|
|
|
43
43
|
continue;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const existingSession = sessionsDb.
|
|
46
|
+
const existingSession = sessionsDb.getSessionByProviderSessionId(parsed.sessionId)
|
|
47
|
+
?? sessionsDb.getSessionById(parsed.sessionId);
|
|
47
48
|
if (existingSession) {
|
|
48
49
|
// If session name is untitled and we now have a name, update it
|
|
49
50
|
if (existingSession.custom_name === 'Untitled Codex Session' && parsed.sessionName && parsed.sessionName !== 'Untitled Codex Session') {
|
|
50
|
-
sessionsDb.updateSessionCustomName(
|
|
51
|
+
sessionsDb.updateSessionCustomName(existingSession.session_id, parsed.sessionName);
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
|
|
@@ -120,7 +121,10 @@ export class CodexSessionSynchronizer implements IProviderSessionSynchronizer {
|
|
|
120
121
|
return null;
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
|
|
124
|
+
// App-created sessions are keyed by an app id, so disk-discovered provider
|
|
125
|
+
// ids must be resolved through the provider-id mapping first.
|
|
126
|
+
const existingSession = sessionsDb.getSessionByProviderSessionId(parsed.sessionId)
|
|
127
|
+
?? sessionsDb.getSessionById(parsed.sessionId);
|
|
124
128
|
const existingSessionName = existingSession?.custom_name;
|
|
125
129
|
if (existingSessionName && existingSessionName !== 'Untitled Codex Session') {
|
|
126
130
|
return {
|
|
@@ -4,7 +4,7 @@ import readline from 'node:readline';
|
|
|
4
4
|
import { sessionsDb } from '@/modules/database/index.js';
|
|
5
5
|
import type { IProviderSessions } from '@/shared/interfaces.js';
|
|
6
6
|
import type { AnyRecord, FetchHistoryOptions, FetchHistoryResult, NormalizedMessage } from '@/shared/types.js';
|
|
7
|
-
import { createNormalizedMessage, generateMessageId, readObjectRecord } from '@/shared/utils.js';
|
|
7
|
+
import { createNormalizedMessage, generateMessageId, readObjectRecord, sliceTailPage } from '@/shared/utils.js';
|
|
8
8
|
|
|
9
9
|
const PROVIDER = 'codex';
|
|
10
10
|
|
|
@@ -552,7 +552,6 @@ export class CodexSessionsProvider implements IProviderSessions {
|
|
|
552
552
|
}
|
|
553
553
|
}
|
|
554
554
|
|
|
555
|
-
const totalNormalized = normalized.length;
|
|
556
555
|
let total = 0;
|
|
557
556
|
for (const msg of normalized) {
|
|
558
557
|
if (msg.kind !== 'tool_result') {
|
|
@@ -561,18 +560,10 @@ export class CodexSessionsProvider implements IProviderSessions {
|
|
|
561
560
|
}
|
|
562
561
|
const normalizedOffset = Math.max(0, offset);
|
|
563
562
|
const normalizedLimit = limit === null ? null : Math.max(0, limit);
|
|
564
|
-
const
|
|
565
|
-
? normalized
|
|
566
|
-
: normalized.slice(
|
|
567
|
-
Math.max(0, totalNormalized - normalizedOffset - normalizedLimit),
|
|
568
|
-
Math.max(0, totalNormalized - normalizedOffset),
|
|
569
|
-
);
|
|
570
|
-
const hasMore = normalizedLimit === null
|
|
571
|
-
? false
|
|
572
|
-
: Math.max(0, totalNormalized - normalizedOffset - normalizedLimit) > 0;
|
|
563
|
+
const { page, hasMore } = sliceTailPage(normalized, normalizedLimit, normalizedOffset);
|
|
573
564
|
|
|
574
565
|
return {
|
|
575
|
-
messages,
|
|
566
|
+
messages: page,
|
|
576
567
|
total,
|
|
577
568
|
hasMore,
|
|
578
569
|
offset: normalizedOffset,
|
|
@@ -57,4 +57,12 @@ export class CodexSkillsProvider extends SkillsProvider {
|
|
|
57
57
|
|
|
58
58
|
return sources;
|
|
59
59
|
}
|
|
60
|
+
|
|
61
|
+
protected async getGlobalSkillSource(): Promise<ProviderSkillSource> {
|
|
62
|
+
return {
|
|
63
|
+
scope: 'user',
|
|
64
|
+
rootDir: path.join(os.homedir(), '.agents', 'skills'),
|
|
65
|
+
commandPrefix: '$',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
60
68
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
generateMessageId,
|
|
10
10
|
readObjectRecord,
|
|
11
11
|
sanitizeLeafDirectoryName,
|
|
12
|
+
sliceTailPage,
|
|
12
13
|
} from '@/shared/utils.js';
|
|
13
14
|
|
|
14
15
|
const PROVIDER = 'cursor';
|
|
@@ -363,42 +364,32 @@ export class CursorSessionsProvider implements IProviderSessions {
|
|
|
363
364
|
|
|
364
365
|
/**
|
|
365
366
|
* Fetches and paginates Cursor session history from its project-scoped store.db.
|
|
367
|
+
*
|
|
368
|
+
* Pagination follows the shared tail contract (`sliceTailPage`): offset 0 is
|
|
369
|
+
* the most recent page, matching every other provider.
|
|
366
370
|
*/
|
|
367
371
|
async fetchHistory(
|
|
368
372
|
sessionId: string,
|
|
369
373
|
options: FetchHistoryOptions = {},
|
|
370
374
|
): Promise<FetchHistoryResult> {
|
|
371
375
|
const { projectPath = '', limit = null, offset = 0 } = options;
|
|
376
|
+
// The store.db folder on disk is named after the provider-native id, not
|
|
377
|
+
// the app-facing session id this method is addressed with.
|
|
378
|
+
const providerSessionId = options.providerSessionId ?? sessionId;
|
|
372
379
|
|
|
373
380
|
try {
|
|
374
|
-
const blobs = await this.loadCursorBlobs(
|
|
381
|
+
const blobs = await this.loadCursorBlobs(providerSessionId, projectPath);
|
|
375
382
|
const allNormalized = this.normalizeCursorBlobs(blobs, sessionId);
|
|
376
383
|
const renderableMessages = allNormalized.filter((msg) => msg.kind !== 'tool_result');
|
|
377
384
|
const total = renderableMessages.length;
|
|
378
|
-
|
|
379
|
-
if (limit !== null) {
|
|
380
|
-
const start = offset;
|
|
381
|
-
const page = limit === 0
|
|
382
|
-
? []
|
|
383
|
-
: renderableMessages.slice(start, start + limit);
|
|
384
|
-
const hasMore = limit === 0
|
|
385
|
-
? start < total
|
|
386
|
-
: start + limit < total;
|
|
387
|
-
return {
|
|
388
|
-
messages: page,
|
|
389
|
-
total,
|
|
390
|
-
hasMore,
|
|
391
|
-
offset,
|
|
392
|
-
limit,
|
|
393
|
-
};
|
|
394
|
-
}
|
|
385
|
+
const { page, hasMore } = sliceTailPage(renderableMessages, limit, offset);
|
|
395
386
|
|
|
396
387
|
return {
|
|
397
|
-
messages:
|
|
388
|
+
messages: page,
|
|
398
389
|
total,
|
|
399
|
-
hasMore
|
|
400
|
-
offset
|
|
401
|
-
limit
|
|
390
|
+
hasMore,
|
|
391
|
+
offset,
|
|
392
|
+
limit,
|
|
402
393
|
};
|
|
403
394
|
} catch (error) {
|
|
404
395
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -28,4 +28,12 @@ export class CursorSkillsProvider extends SkillsProvider {
|
|
|
28
28
|
},
|
|
29
29
|
];
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
protected async getGlobalSkillSource(): Promise<ProviderSkillSource> {
|
|
33
|
+
return {
|
|
34
|
+
scope: 'user',
|
|
35
|
+
rootDir: path.join(os.homedir(), '.cursor', 'skills'),
|
|
36
|
+
commandPrefix: '/',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
31
39
|
}
|
|
@@ -12,17 +12,14 @@ import {
|
|
|
12
12
|
|
|
13
13
|
export const GEMINI_FALLBACK_MODELS: ProviderModelsDefinition = {
|
|
14
14
|
OPTIONS: [
|
|
15
|
-
{ value: 'gemini-3.1-pro-preview', label: 'Gemini 3.1 Pro Preview' },
|
|
16
|
-
{ value: 'gemini-3-pro-preview', label: 'Gemini 3 Pro Preview' },
|
|
17
15
|
{ value: 'gemini-3-flash-preview', label: 'Gemini 3 Flash Preview' },
|
|
16
|
+
{ value: 'gemini-3.1-flash-lite-preview', label: 'Gemini 3.1 Flash Lite Preview' },
|
|
18
17
|
{ value: 'gemini-2.5-flash', label: 'Gemini 2.5 Flash' },
|
|
19
|
-
{ value: 'gemini-2.5-
|
|
20
|
-
{ value: '
|
|
21
|
-
{ value: '
|
|
22
|
-
{ value: 'gemini-2.0-pro-exp', label: 'Gemini 2.0 Pro Experimental' },
|
|
23
|
-
{ value: 'gemini-2.0-flash-thinking-exp', label: 'Gemini 2.0 Flash Thinking' },
|
|
18
|
+
{ value: 'gemini-2.5-flash-lite', label: 'Gemini 2.5 Flash Lite' },
|
|
19
|
+
{ value: 'gemma-4-31b-it', label: 'Gemma 4 31B IT' },
|
|
20
|
+
{ value: 'gemma-4-26b-a4b-it', label: 'Gemma 4 26B A4B IT' },
|
|
24
21
|
],
|
|
25
|
-
DEFAULT: 'gemini-3
|
|
22
|
+
DEFAULT: 'gemini-3-flash-preview',
|
|
26
23
|
};
|
|
27
24
|
|
|
28
25
|
export class GeminiProviderModels implements IProviderModels {
|