@myrialabs/clopen 0.2.1 → 0.2.3
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/.dockerignore +5 -0
- package/.env.example +2 -5
- package/CONTRIBUTING.md +4 -0
- package/README.md +4 -2
- package/backend/{lib/auth → auth}/auth-service.ts +2 -2
- package/backend/{lib/chat → chat}/stream-manager.ts +1 -1
- package/backend/{lib/database → database}/queries/message-queries.ts +42 -0
- package/backend/{lib/database → database}/utils/connection.ts +5 -5
- package/backend/{lib/engine → engine}/adapters/claude/environment.ts +3 -4
- package/backend/{lib/engine → engine}/adapters/opencode/message-converter.ts +1 -1
- package/backend/{lib/engine → engine}/adapters/opencode/server.ts +7 -1
- package/backend/{lib/files → files}/file-watcher.ts +1 -1
- package/backend/{lib/git → git}/git-executor.ts +3 -2
- package/backend/index.ts +16 -16
- package/backend/{lib/mcp → mcp}/README.md +68 -79
- package/backend/{lib/mcp → mcp}/config.ts +1 -1
- package/backend/{lib/mcp → mcp}/servers/browser-automation/actions.ts +4 -4
- package/backend/{lib/mcp → mcp}/servers/browser-automation/browser.ts +3 -3
- package/backend/{lib/mcp → mcp}/servers/browser-automation/inspection.ts +3 -3
- package/backend/middleware/cors.ts +1 -1
- package/backend/middleware/error-handler.ts +1 -1
- package/backend/{lib/preview → preview}/browser/browser-preview-service.ts +1 -1
- package/backend/{lib/preview → preview}/browser/browser-tab-manager.ts +1 -1
- package/backend/{lib/preview → preview}/browser/types.ts +1 -1
- package/backend/{lib/project → project}/status-manager.ts +223 -223
- package/backend/{lib/snapshot → snapshot}/blob-store.ts +2 -2
- package/backend/{lib/terminal → terminal}/shell-utils.ts +1 -1
- package/backend/{lib/shared → utils}/env.ts +13 -15
- package/backend/{lib/shared → utils}/index.ts +4 -1
- package/backend/utils/paths.ts +11 -0
- package/backend/{lib/shared → utils}/port-utils.ts +19 -6
- package/backend/{lib/utils → utils}/ws.ts +2 -2
- package/backend/ws/README.md +9 -9
- package/backend/ws/auth/invites.ts +2 -2
- package/backend/ws/auth/login.ts +9 -9
- package/backend/ws/auth/status.ts +2 -2
- package/backend/ws/auth/users.ts +1 -1
- package/backend/ws/chat/background.ts +2 -2
- package/backend/ws/chat/stream.ts +3 -3
- package/backend/ws/engine/claude/accounts.ts +4 -4
- package/backend/ws/engine/claude/status.ts +1 -1
- package/backend/ws/files/read.ts +2 -2
- package/backend/ws/files/watch.ts +2 -2
- package/backend/ws/files/write.ts +1 -1
- package/backend/ws/git/branch.ts +2 -2
- package/backend/ws/git/commit.ts +2 -2
- package/backend/ws/git/conflict.ts +2 -2
- package/backend/ws/git/diff.ts +2 -2
- package/backend/ws/git/log.ts +2 -2
- package/backend/ws/git/remote.ts +2 -2
- package/backend/ws/git/staging.ts +2 -2
- package/backend/ws/git/status.ts +3 -3
- package/backend/ws/messages/crud.ts +53 -1
- package/backend/ws/preview/browser/cleanup.ts +2 -2
- package/backend/ws/preview/browser/console.ts +2 -2
- package/backend/ws/preview/browser/interact.ts +2 -2
- package/backend/ws/preview/browser/mcp.ts +1 -1
- package/backend/ws/preview/browser/native-ui.ts +2 -2
- package/backend/ws/preview/browser/stats.ts +2 -2
- package/backend/ws/preview/browser/tab-info.ts +2 -2
- package/backend/ws/preview/browser/tab.ts +2 -2
- package/backend/ws/preview/browser/webcodecs.ts +2 -2
- package/backend/ws/projects/crud.ts +3 -3
- package/backend/ws/projects/presence.ts +3 -3
- package/backend/ws/projects/status.ts +3 -3
- package/backend/ws/sessions/crud.ts +2 -2
- package/backend/ws/settings/crud.ts +2 -2
- package/backend/ws/snapshot/restore.ts +5 -5
- package/backend/ws/snapshot/timeline.ts +3 -3
- package/backend/ws/system/operations.ts +1 -1
- package/backend/ws/terminal/persistence.ts +3 -3
- package/backend/ws/terminal/session.ts +6 -6
- package/backend/ws/terminal/stream.ts +2 -2
- package/backend/ws/tunnel/operations.ts +1 -1
- package/backend/ws/user/crud.ts +4 -4
- package/bin/clopen.ts +15 -15
- package/docker-compose.yml +31 -0
- package/frontend/App.svelte +13 -13
- package/frontend/{lib/components → components}/auth/InvitePage.svelte +2 -2
- package/frontend/{lib/components → components}/auth/LoginPage.svelte +1 -1
- package/frontend/{lib/components → components}/auth/SetupPage.svelte +49 -17
- package/frontend/{lib/components → components}/chat/ChatInterface.svelte +14 -14
- package/frontend/{lib/components → components}/chat/formatters/ErrorMessage.svelte +1 -1
- package/frontend/{lib/components → components}/chat/formatters/MessageFormatter.svelte +4 -4
- package/frontend/{lib/components → components}/chat/formatters/TextMessage.svelte +1 -1
- package/frontend/{lib/components → components}/chat/formatters/Tools.svelte +1 -1
- package/frontend/{lib/components → components}/chat/input/ChatInput.svelte +12 -12
- package/frontend/{lib/components → components}/chat/input/components/ChatInputActions.svelte +1 -1
- package/frontend/{lib/components → components}/chat/input/components/EditModeIndicator.svelte +2 -2
- package/frontend/{lib/components → components}/chat/input/components/EngineModelPicker.svelte +9 -9
- package/frontend/{lib/components → components}/chat/input/components/FileAttachmentPreview.svelte +1 -1
- package/frontend/{lib/components → components}/chat/input/components/LoadingIndicator.svelte +2 -2
- package/frontend/{lib/components → components}/chat/input/composables/use-chat-actions.svelte.ts +8 -8
- package/frontend/{lib/components → components}/chat/input/composables/use-file-handling.svelte.ts +1 -1
- package/frontend/{lib/components → components}/chat/input/composables/use-input-state.svelte.ts +6 -6
- package/frontend/{lib/components → components}/chat/message/ChatMessage.svelte +8 -8
- package/frontend/{lib/components → components}/chat/message/ChatMessages.svelte +7 -7
- package/frontend/{lib/components → components}/chat/message/MessageBubble.svelte +1 -1
- package/frontend/{lib/components → components}/chat/message/MessageHeader.svelte +2 -2
- package/frontend/{lib/components → components}/chat/modal/DebugModal.svelte +2 -2
- package/frontend/{lib/components → components}/chat/modal/TokenUsageModal.svelte +2 -2
- package/frontend/{lib/components → components}/chat/tools/AskUserQuestionTool.svelte +4 -4
- package/frontend/{lib/components → components}/chat/tools/CustomMcpTool.svelte +1 -1
- package/frontend/{lib/components → components}/chat/tools/EditTool.svelte +1 -1
- package/frontend/{lib/components → components}/chat/tools/TodoWriteTool.svelte +1 -1
- package/frontend/{lib/components → components}/chat/tools/components/CodeBlock.svelte +2 -2
- package/frontend/{lib/components → components}/chat/tools/components/DiffBlock.svelte +1 -1
- package/frontend/{lib/components → components}/chat/tools/components/FileHeader.svelte +2 -2
- package/frontend/{lib/components → components}/chat/tools/components/InfoLine.svelte +1 -1
- package/frontend/{lib/components → components}/chat/widgets/FloatingTodoList.svelte +127 -13
- package/frontend/{lib/components → components}/chat/widgets/TokenUsage.svelte +4 -4
- package/frontend/{lib/components → components}/checkpoint/TimelineModal.svelte +10 -10
- package/frontend/{lib/components → components}/checkpoint/timeline/TimelineNode.svelte +1 -1
- package/frontend/{lib/components/common → components/common/display}/Icon.svelte +2 -2
- package/frontend/{lib/components/common → components/common/display}/PageTemplate.svelte +1 -1
- package/frontend/{lib/components/common → components/common/display}/ProjectUserAvatars.svelte +1 -1
- package/frontend/{lib/components/common → components/common/display}/ThemeToggle.svelte +1 -1
- package/frontend/{lib/components/common → components/common/editor}/MonacoEditor.svelte +2 -2
- package/frontend/{lib/components/common → components/common/feedback}/Alert.svelte +1 -1
- package/frontend/{lib/components/common → components/common/feedback}/ConnectionBanner.svelte +3 -3
- package/frontend/{lib/components/common → components/common/feedback}/LoadingScreen.svelte +1 -1
- package/frontend/{lib/components/common → components/common/feedback}/NotificationToast.svelte +2 -2
- package/frontend/{lib/components/common → components/common/feedback}/UpdateBanner.svelte +5 -5
- package/frontend/{lib/components/common → components/common/form}/Checkbox.svelte +1 -1
- package/frontend/{lib/components/common → components/common/form}/FolderBrowser.svelte +6 -6
- package/frontend/{lib/components/common → components/common/form}/Input.svelte +1 -1
- package/frontend/{lib/components/common → components/common/form}/ModelSelector.svelte +3 -3
- package/frontend/{lib/components/common → components/common/form}/Select.svelte +1 -1
- package/frontend/{lib/components/common → components/common/form}/Textarea.svelte +1 -1
- package/frontend/{lib/components/common → components/common/overlay}/Dialog.svelte +1 -1
- package/frontend/{lib/components/common → components/common/overlay}/Lightbox.svelte +3 -3
- package/frontend/{lib/components/common → components/common/overlay}/ModalProvider.svelte +2 -2
- package/frontend/{lib/components → components}/common/xterm/XTerm.svelte +5 -5
- package/frontend/{lib/components → components}/common/xterm/xterm-service.ts +2 -2
- package/frontend/{lib/components → components}/files/FileNode.svelte +3 -3
- package/frontend/{lib/components → components}/files/FileTree.svelte +5 -5
- package/frontend/{lib/components → components}/files/FileViewer.svelte +7 -7
- package/frontend/{lib/components → components}/files/SearchResults.svelte +3 -3
- package/frontend/{lib/components → components}/git/BranchManager.svelte +6 -6
- package/frontend/{lib/components → components}/git/ChangesSection.svelte +1 -1
- package/frontend/{lib/components → components}/git/CommitForm.svelte +1 -1
- package/frontend/{lib/components → components}/git/ConflictResolver.svelte +1 -1
- package/frontend/{lib/components → components}/git/DiffViewer.svelte +7 -7
- package/frontend/{lib/components → components}/git/FileChangeItem.svelte +3 -3
- package/frontend/{lib/components → components}/git/GitButton.svelte +1 -1
- package/frontend/{lib/components → components}/git/GitLog.svelte +2 -2
- package/frontend/{lib/components → components}/git/GitModal.svelte +3 -3
- package/frontend/{lib/components → components}/history/HistoryModal.svelte +41 -89
- package/frontend/{lib/components → components}/history/HistoryView.svelte +57 -104
- package/frontend/{lib/components → components}/index.ts +9 -9
- package/frontend/{lib/components → components}/preview/browser/BrowserPreview.svelte +3 -3
- package/frontend/{lib/components → components}/preview/browser/components/Canvas.svelte +2 -2
- package/frontend/{lib/components → components}/preview/browser/components/ConsolePanel.svelte +1 -1
- package/frontend/{lib/components → components}/preview/browser/components/Container.svelte +2 -2
- package/frontend/{lib/components → components}/preview/browser/components/ContextMenu.svelte +1 -1
- package/frontend/{lib/components → components}/preview/browser/components/SelectDropdown.svelte +1 -1
- package/frontend/{lib/components → components}/preview/browser/components/Toolbar.svelte +2 -2
- package/frontend/{lib/components → components}/preview/browser/core/cleanup.svelte.ts +1 -1
- package/frontend/{lib/components → components}/preview/browser/core/coordinator.svelte.ts +4 -4
- package/frontend/{lib/components → components}/preview/browser/core/interactions.svelte.ts +3 -3
- package/frontend/{lib/components → components}/preview/browser/core/mcp-handlers.svelte.ts +2 -2
- package/frontend/{lib/components → components}/preview/browser/core/native-ui-handlers.svelte.ts +2 -2
- package/frontend/{lib/components → components}/preview/browser/core/tab-manager.svelte.ts +1 -1
- package/frontend/{lib/components → components}/preview/browser/core/tab-operations.svelte.ts +3 -3
- package/frontend/{lib/components → components}/settings/SettingsModal.svelte +4 -4
- package/frontend/{lib/components → components}/settings/SettingsView.svelte +2 -2
- package/frontend/{lib/components → components}/settings/admin/InviteManagement.svelte +5 -5
- package/frontend/{lib/components → components}/settings/admin/UserManagement.svelte +5 -5
- package/frontend/{lib/components → components}/settings/appearance/AppearanceSettings.svelte +5 -5
- package/frontend/{lib/components → components}/settings/appearance/LayoutPresetSettings.svelte +3 -3
- package/frontend/{lib/components → components}/settings/appearance/LayoutPreview.svelte +1 -1
- package/frontend/{lib/components → components}/settings/engines/AIEnginesSettings.svelte +6 -6
- package/frontend/{lib/components → components}/settings/general/AdvancedSettings.svelte +5 -5
- package/frontend/{lib/components → components}/settings/general/AuthModeSettings.svelte +5 -5
- package/frontend/{lib/components → components}/settings/general/DataManagementSettings.svelte +9 -9
- package/frontend/{lib/components → components}/settings/general/UpdateSettings.svelte +3 -3
- package/frontend/{lib/components → components}/settings/model/ModelSettings.svelte +2 -2
- package/frontend/{lib/components → components}/settings/notifications/NotificationSettings.svelte +4 -4
- package/frontend/{lib/components → components}/settings/user/UserSettings.svelte +5 -5
- package/frontend/{lib/components → components}/terminal/Terminal.svelte +9 -9
- package/frontend/{lib/components → components}/terminal/TerminalTabs.svelte +1 -1
- package/frontend/{lib/components → components}/terminal/TerminalView.svelte +5 -5
- package/frontend/{lib/components → components}/tunnel/TunnelActive.svelte +3 -3
- package/frontend/{lib/components → components}/tunnel/TunnelButton.svelte +2 -2
- package/frontend/{lib/components → components}/tunnel/TunnelInactive.svelte +4 -4
- package/frontend/{lib/components → components}/tunnel/TunnelModal.svelte +2 -2
- package/frontend/{lib/components → components}/workspace/DesktopNavigator.svelte +372 -372
- package/frontend/{lib/components → components}/workspace/MobileNavigator.svelte +380 -380
- package/frontend/{lib/components → components}/workspace/PanelContainer.svelte +3 -3
- package/frontend/{lib/components → components}/workspace/PanelHeader.svelte +10 -10
- package/frontend/{lib/components → components}/workspace/ViewMenu.svelte +4 -4
- package/frontend/{lib/components → components}/workspace/WorkspaceLayout.svelte +17 -17
- package/frontend/{lib/components → components}/workspace/layout/DesktopLayout.svelte +1 -1
- package/frontend/{lib/components → components}/workspace/layout/MobileLayout.svelte +1 -1
- package/frontend/{lib/components → components}/workspace/layout/split-pane/Container.svelte +1 -1
- package/frontend/{lib/components → components}/workspace/layout/split-pane/Handle.svelte +2 -2
- package/frontend/{lib/components → components}/workspace/layout/split-pane/Layout.svelte +2 -2
- package/frontend/{lib/components → components}/workspace/panels/ChatPanel.svelte +14 -14
- package/frontend/{lib/components → components}/workspace/panels/FilesPanel.svelte +51 -13
- package/frontend/{lib/components → components}/workspace/panels/GitPanel.svelte +55 -17
- package/frontend/{lib/components → components}/workspace/panels/PreviewPanel.svelte +5 -5
- package/frontend/{lib/components → components}/workspace/panels/TerminalPanel.svelte +6 -6
- package/frontend/{lib/services → services}/chat/chat.service.ts +8 -8
- package/frontend/{lib/services → services}/notification/global-stream-monitor.ts +117 -117
- package/frontend/{lib/services → services}/notification/push.service.ts +1 -1
- package/frontend/{lib/services → services}/notification/sound.service.ts +1 -1
- package/frontend/{lib/services → services}/preview/browser/browser-console.service.ts +1 -1
- package/frontend/{lib/services → services}/preview/browser/browser-webcodecs.service.ts +1 -1
- package/frontend/{lib/services → services}/preview/browser/mcp-integration.svelte.ts +2 -2
- package/frontend/{lib/services → services}/project/status.service.ts +160 -160
- package/frontend/{lib/services → services}/snapshot/snapshot.service.ts +2 -2
- package/frontend/{lib/services → services}/terminal/background/index.ts +1 -1
- package/frontend/{lib/services → services}/terminal/background/session-restore.ts +1 -1
- package/frontend/{lib/services → services}/terminal/background/stream-manager.ts +1 -1
- package/frontend/{lib/services → services}/terminal/project.service.ts +2 -2
- package/frontend/{lib/services → services}/terminal/terminal.service.ts +2 -2
- package/frontend/{lib/stores → stores}/core/app.svelte.ts +1 -1
- package/frontend/{lib/stores → stores}/core/presence.svelte.ts +4 -4
- package/frontend/{lib/stores → stores}/core/projects.svelte.ts +5 -5
- package/frontend/{lib/stores → stores}/core/sessions.svelte.ts +3 -3
- package/frontend/{lib/stores → stores}/features/auth.svelte.ts +30 -2
- package/frontend/{lib/stores → stores}/features/claude-accounts.svelte.ts +1 -1
- package/frontend/{lib/stores → stores}/features/models.svelte.ts +1 -1
- package/frontend/{lib/stores → stores}/features/settings.svelte.ts +2 -2
- package/frontend/{lib/stores → stores}/features/terminal.svelte.ts +4 -4
- package/frontend/{lib/stores → stores}/features/tunnel.svelte.ts +1 -1
- package/frontend/{lib/stores → stores}/features/user.svelte.ts +1 -1
- package/frontend/{lib/stores → stores}/ui/edit-mode.svelte.ts +3 -3
- package/frontend/{lib/stores → stores}/ui/update.svelte.ts +8 -2
- package/frontend/{lib/utils → utils}/theme.ts +1 -1
- package/frontend/{lib/utils → utils}/ws.ts +1 -1
- package/package.json +2 -2
- package/scripts/dev.ts +4 -3
- package/scripts/generate-icons.ts +2 -2
- package/scripts/start.ts +24 -0
- package/shared/types/ui/icons.ts +4 -4
- package/shared/utils/anonymous-user.ts +1 -1
- package/shared/utils/ws-server.ts +3 -3
- package/vite.config.ts +2 -2
- /package/backend/{lib/auth → auth}/index.ts +0 -0
- /package/backend/{lib/auth → auth}/permissions.ts +0 -0
- /package/backend/{lib/auth → auth}/rate-limiter.ts +0 -0
- /package/backend/{lib/auth → auth}/tokens.ts +0 -0
- /package/backend/{lib/chat → chat}/helpers.ts +0 -0
- /package/backend/{lib/chat → chat}/index.ts +0 -0
- /package/backend/{lib/database → database}/README.md +0 -0
- /package/backend/{lib/database → database}/index.ts +0 -0
- /package/backend/{lib/database → database}/migrations/001_create_projects_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/002_create_chat_sessions_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/003_create_messages_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/004_create_prompt_templates_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/005_create_settings_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/006_add_user_to_messages.ts +0 -0
- /package/backend/{lib/database → database}/migrations/007_create_stream_states_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/008_create_message_snapshots_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/009_add_delta_snapshot_fields.ts +0 -0
- /package/backend/{lib/database → database}/migrations/010_add_soft_delete_and_branch_support.ts +0 -0
- /package/backend/{lib/database → database}/migrations/011_git_like_commit_graph.ts +0 -0
- /package/backend/{lib/database → database}/migrations/012_add_file_change_statistics.ts +0 -0
- /package/backend/{lib/database → database}/migrations/013_checkpoint_tree_state.ts +0 -0
- /package/backend/{lib/database → database}/migrations/014_add_engine_to_sessions.ts +0 -0
- /package/backend/{lib/database → database}/migrations/015_add_model_to_sessions.ts +0 -0
- /package/backend/{lib/database → database}/migrations/016_create_user_projects_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/017_add_current_session_to_user_projects.ts +0 -0
- /package/backend/{lib/database → database}/migrations/018_create_claude_accounts_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/019_add_claude_account_to_sessions.ts +0 -0
- /package/backend/{lib/database → database}/migrations/020_add_snapshot_tree_hash.ts +0 -0
- /package/backend/{lib/database → database}/migrations/021_drop_prompt_templates_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/022_add_snapshot_changes_column.ts +0 -0
- /package/backend/{lib/database → database}/migrations/023_create_user_unread_sessions_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/024_create_users_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/025_create_auth_sessions_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/026_create_invite_tokens_table.ts +0 -0
- /package/backend/{lib/database → database}/migrations/index.ts +0 -0
- /package/backend/{lib/database → database}/queries/auth-queries.ts +0 -0
- /package/backend/{lib/database → database}/queries/checkpoint-queries.ts +0 -0
- /package/backend/{lib/database → database}/queries/engine-queries.ts +0 -0
- /package/backend/{lib/database → database}/queries/index.ts +0 -0
- /package/backend/{lib/database → database}/queries/project-queries.ts +0 -0
- /package/backend/{lib/database → database}/queries/session-queries.ts +0 -0
- /package/backend/{lib/database → database}/queries/settings-queries.ts +0 -0
- /package/backend/{lib/database → database}/queries/snapshot-queries.ts +0 -0
- /package/backend/{lib/database → database}/queries/utils-queries.ts +0 -0
- /package/backend/{lib/database → database}/seeders/index.ts +0 -0
- /package/backend/{lib/database → database}/seeders/settings_seeder.ts +0 -0
- /package/backend/{lib/database → database}/utils/index.ts +0 -0
- /package/backend/{lib/database → database}/utils/migration-runner.ts +0 -0
- /package/backend/{lib/database → database}/utils/seeder-runner.ts +0 -0
- /package/backend/{lib/engine → engine}/adapters/claude/error-handler.ts +0 -0
- /package/backend/{lib/engine → engine}/adapters/claude/index.ts +0 -0
- /package/backend/{lib/engine → engine}/adapters/claude/path-utils.ts +0 -0
- /package/backend/{lib/engine → engine}/adapters/claude/stream.ts +0 -0
- /package/backend/{lib/engine → engine}/adapters/opencode/index.ts +0 -0
- /package/backend/{lib/engine → engine}/adapters/opencode/stream.ts +0 -0
- /package/backend/{lib/engine → engine}/index.ts +0 -0
- /package/backend/{lib/engine → engine}/types.ts +0 -0
- /package/backend/{lib/files → files}/file-operations.ts +0 -0
- /package/backend/{lib/files → files}/file-reading.ts +0 -0
- /package/backend/{lib/files → files}/path-browsing.ts +0 -0
- /package/backend/{lib/git → git}/git-parser.ts +0 -0
- /package/backend/{lib/git → git}/git-service.ts +0 -0
- /package/backend/{lib/mcp → mcp}/index.ts +0 -0
- /package/backend/{lib/mcp → mcp}/project-context.ts +0 -0
- /package/backend/{lib/mcp → mcp}/remote-server.ts +0 -0
- /package/backend/{lib/mcp → mcp}/servers/browser-automation/index.ts +0 -0
- /package/backend/{lib/mcp → mcp}/servers/helper.ts +0 -0
- /package/backend/{lib/mcp → mcp}/servers/index.ts +0 -0
- /package/backend/{lib/mcp → mcp}/servers/weather/get-temperature.ts +0 -0
- /package/backend/{lib/mcp → mcp}/servers/weather/index.ts +0 -0
- /package/backend/{lib/mcp → mcp}/types.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/browser-audio-capture.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/browser-console-manager.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/browser-dialog-handler.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/browser-interaction-handler.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/browser-mcp-control.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/browser-native-ui-handler.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/browser-navigation-tracker.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/browser-pool.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/browser-video-capture.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/scripts/audio-stream.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/scripts/cursor-tracking.ts +0 -0
- /package/backend/{lib/preview → preview}/browser/scripts/video-stream.ts +0 -0
- /package/backend/{lib/preview → preview}/index.ts +0 -0
- /package/backend/{lib/project → project}/index.ts +0 -0
- /package/backend/{lib/snapshot → snapshot}/gitignore.ts +0 -0
- /package/backend/{lib/snapshot → snapshot}/helpers.ts +0 -0
- /package/backend/{lib/snapshot → snapshot}/snapshot-service.ts +0 -0
- /package/backend/{lib/terminal → terminal}/helpers.ts +0 -0
- /package/backend/{lib/terminal → terminal}/index.ts +0 -0
- /package/backend/{lib/terminal → terminal}/pty-manager.ts +0 -0
- /package/backend/{lib/terminal → terminal}/pty-session-manager.ts +0 -0
- /package/backend/{lib/terminal → terminal}/stream-manager.ts +0 -0
- /package/backend/{lib/tunnel → tunnel}/global-tunnel-manager.ts +0 -0
- /package/backend/{lib/tunnel → tunnel}/project-tunnel-manager.ts +0 -0
- /package/backend/{lib/shared → utils}/process-manager.ts +0 -0
- /package/backend/{lib/user/helpers.ts → utils/user-helpers.ts} +0 -0
- /package/frontend/{lib/app-environment.ts → app-environment.ts} +0 -0
- /package/frontend/{lib/components → components}/chat/formatters/index.ts +0 -0
- /package/frontend/{lib/components → components}/chat/input/components/DragDropOverlay.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/input/composables/use-animations.svelte.ts +0 -0
- /package/frontend/{lib/components → components}/chat/input/composables/use-textarea-resize.svelte.ts +0 -0
- /package/frontend/{lib/components → components}/chat/message/DateSeparator.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/shared/index.ts +0 -0
- /package/frontend/{lib/components → components}/chat/shared/utils.ts +0 -0
- /package/frontend/{lib/components → components}/chat/tools/AgentTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/BashOutputTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/BashTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/EnterPlanModeTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/ExitPlanModeTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/GlobTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/GrepTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/ListMcpResourcesTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/NotebookEditTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/ReadMcpResourceTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/ReadTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/TaskStopTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/TaskTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/WebFetchTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/WebSearchTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/WriteTool.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/components/StatsBadges.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/components/TerminalCommand.svelte +0 -0
- /package/frontend/{lib/components → components}/chat/tools/components/index.ts +0 -0
- /package/frontend/{lib/components → components}/chat/tools/index.ts +0 -0
- /package/frontend/{lib/components → components}/checkpoint/timeline/TimelineEdge.svelte +0 -0
- /package/frontend/{lib/components → components}/checkpoint/timeline/TimelineGraph.svelte +0 -0
- /package/frontend/{lib/components → components}/checkpoint/timeline/TimelineVersionGroup.svelte +0 -0
- /package/frontend/{lib/components → components}/checkpoint/timeline/animation.ts +0 -0
- /package/frontend/{lib/components → components}/checkpoint/timeline/config.ts +0 -0
- /package/frontend/{lib/components → components}/checkpoint/timeline/graph-builder.ts +0 -0
- /package/frontend/{lib/components → components}/checkpoint/timeline/types.ts +0 -0
- /package/frontend/{lib/components → components}/checkpoint/timeline/utils.ts +0 -0
- /package/frontend/{lib/components/common → components/common/display}/AvatarBubble.svelte +0 -0
- /package/frontend/{lib/components/common → components/common/display}/Button.svelte +0 -0
- /package/frontend/{lib/components/common → components/common/display}/Card.svelte +0 -0
- /package/frontend/{lib/components/common → components/common/feedback}/LoadingSpinner.svelte +0 -0
- /package/frontend/{lib/components → components}/common/lucide-icons.ts +0 -0
- /package/frontend/{lib/components → components}/common/material-icons.ts +0 -0
- /package/frontend/{lib/components/common → components/common/overlay}/Modal.svelte +0 -0
- /package/frontend/{lib/components → components}/common/xterm/index.ts +0 -0
- /package/frontend/{lib/components → components}/common/xterm/terminal-config.ts +0 -0
- /package/frontend/{lib/components → components}/common/xterm/types.ts +0 -0
- /package/frontend/{lib/components → components}/preview/browser/components/VirtualCursor.svelte +0 -0
- /package/frontend/{lib/components → components}/preview/browser/core/stream-handler.svelte.ts +0 -0
- /package/frontend/{lib/components → components}/preview/index.ts +0 -0
- /package/frontend/{lib/components → components}/settings/account/AccountSettings.svelte +0 -0
- /package/frontend/{lib/components → components}/settings/general/GeneralSettings.svelte +0 -0
- /package/frontend/{lib/components → components}/settings/security/SecuritySettings.svelte +0 -0
- /package/frontend/{lib/components → components}/settings/system/SystemSettings.svelte +0 -0
- /package/frontend/{lib/components → components}/tunnel/TunnelQRCode.svelte +0 -0
- /package/frontend/{lib/services → services}/chat/index.ts +0 -0
- /package/frontend/{lib/services → services}/notification/index.ts +0 -0
- /package/frontend/{lib/services → services}/preview/index.ts +0 -0
- /package/frontend/{lib/services → services}/project/index.ts +0 -0
- /package/frontend/{lib/services → services}/terminal/index.ts +0 -0
- /package/frontend/{lib/services → services}/terminal/persistence.service.ts +0 -0
- /package/frontend/{lib/services → services}/terminal/session.service.ts +0 -0
- /package/frontend/{lib/stores → stores}/core/files.svelte.ts +0 -0
- /package/frontend/{lib/stores → stores}/ui/chat-input.svelte.ts +0 -0
- /package/frontend/{lib/stores → stores}/ui/chat-model.svelte.ts +0 -0
- /package/frontend/{lib/stores → stores}/ui/connection.svelte.ts +0 -0
- /package/frontend/{lib/stores → stores}/ui/dialog.svelte.ts +0 -0
- /package/frontend/{lib/stores → stores}/ui/notification.svelte.ts +0 -0
- /package/frontend/{lib/stores → stores}/ui/settings-modal.svelte.ts +0 -0
- /package/frontend/{lib/stores → stores}/ui/theme.svelte.ts +0 -0
- /package/frontend/{lib/stores → stores}/ui/workspace.svelte.ts +0 -0
- /package/frontend/{lib/utils → utils}/chat/date-separator.ts +0 -0
- /package/frontend/{lib/utils → utils}/chat/message-grouper.ts +0 -0
- /package/frontend/{lib/utils → utils}/chat/message-processor.ts +0 -0
- /package/frontend/{lib/utils → utils}/chat/tool-handler.ts +0 -0
- /package/frontend/{lib/utils → utils}/chat/virtual-scroll.svelte.ts +0 -0
- /package/frontend/{lib/utils → utils}/click-outside.ts +0 -0
- /package/frontend/{lib/utils → utils}/context-manager.ts +0 -0
- /package/frontend/{lib/utils → utils}/file-icon-mappings.ts +0 -0
- /package/frontend/{lib/utils → utils}/folder-icon-mappings.ts +0 -0
- /package/frontend/{lib/utils → utils}/git-status.ts +0 -0
- /package/frontend/{lib/types → utils}/native-ui.ts +0 -0
- /package/frontend/{lib/utils → utils}/platform.ts +0 -0
- /package/frontend/{lib/utils → utils}/port-check.ts +0 -0
- /package/frontend/{lib/constants/preview.ts → utils/preview-constants.ts} +0 -0
- /package/frontend/{lib/utils/terminalFormatter.ts → utils/terminal-formatter.ts} +0 -0
- /package/frontend/{lib/utils → utils}/tree-visualizer.ts +0 -0
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Global Stream Monitor Service
|
|
3
|
-
*
|
|
4
|
-
* Single source of truth for chat stream notifications (sound + push).
|
|
5
|
-
*
|
|
6
|
-
* Listens for backend events and triggers notifications for ALL projects —
|
|
7
|
-
* both active and non-active:
|
|
8
|
-
* - chat:stream-finished → stream completed/errored/cancelled
|
|
9
|
-
* - chat:waiting-input → AskUserQuestion requires user input
|
|
10
|
-
*
|
|
11
|
-
* The backend uses ws.emit.projectMembers() so notifications reach users
|
|
12
|
-
* even when they are on a different project or session.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { soundNotification, pushNotification } from '$frontend/
|
|
16
|
-
import { projectState } from '$frontend/
|
|
17
|
-
import { debug } from '$shared/utils/logger';
|
|
18
|
-
import ws from '$frontend/
|
|
19
|
-
|
|
20
|
-
class GlobalStreamMonitor {
|
|
21
|
-
private initialized = false;
|
|
22
|
-
|
|
23
|
-
/** Track notified AskUserQuestion tool_use IDs to ensure once-only notification */
|
|
24
|
-
private notifiedToolUseIds = new Set<string>();
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Initialize the monitor - subscribes to WS events.
|
|
28
|
-
* Safe to call multiple times (idempotent).
|
|
29
|
-
*/
|
|
30
|
-
initialize(): void {
|
|
31
|
-
if (this.initialized) return;
|
|
32
|
-
this.initialized = true;
|
|
33
|
-
|
|
34
|
-
debug.log('notification', 'GlobalStreamMonitor: Initializing WS listeners');
|
|
35
|
-
|
|
36
|
-
// Stream finished — notify on completion
|
|
37
|
-
ws.on('chat:stream-finished', async (data) => {
|
|
38
|
-
const { projectId, status, chatSessionId } = data;
|
|
39
|
-
|
|
40
|
-
debug.log('notification', 'GlobalStreamMonitor: Stream finished', { projectId, status });
|
|
41
|
-
|
|
42
|
-
// Clean up notified IDs for this session (stream is done)
|
|
43
|
-
this.clearSessionNotifications(chatSessionId);
|
|
44
|
-
|
|
45
|
-
// Play sound notification
|
|
46
|
-
try {
|
|
47
|
-
await soundNotification.play();
|
|
48
|
-
} catch (error) {
|
|
49
|
-
debug.error('notification', 'Error playing sound notification:', error);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Send push notification with project context
|
|
53
|
-
try {
|
|
54
|
-
const projectName = projectState.projects.find(p => p.id === projectId)?.name || 'Unknown';
|
|
55
|
-
|
|
56
|
-
if (status === 'completed') {
|
|
57
|
-
await pushNotification.sendChatComplete(`Chat response ready in "${projectName}"`);
|
|
58
|
-
} else if (status === 'error') {
|
|
59
|
-
await pushNotification.sendChatError(`Chat error in "${projectName}"`);
|
|
60
|
-
} else if (status === 'cancelled') {
|
|
61
|
-
await pushNotification.sendChatComplete(`Chat interrupted in "${projectName}"`);
|
|
62
|
-
}
|
|
63
|
-
} catch (error) {
|
|
64
|
-
debug.error('notification', 'Error sending push notification:', error);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// Waiting for input — notify once per AskUserQuestion
|
|
69
|
-
ws.on('chat:waiting-input', async (data) => {
|
|
70
|
-
const { projectId, chatSessionId, toolUseId } = data;
|
|
71
|
-
|
|
72
|
-
// Deduplicate: only notify once per tool_use ID
|
|
73
|
-
if (this.notifiedToolUseIds.has(toolUseId)) return;
|
|
74
|
-
this.notifiedToolUseIds.add(toolUseId);
|
|
75
|
-
|
|
76
|
-
debug.log('notification', 'GlobalStreamMonitor: Waiting for input', { projectId, chatSessionId, toolUseId });
|
|
77
|
-
|
|
78
|
-
// Play sound notification
|
|
79
|
-
try {
|
|
80
|
-
await soundNotification.play();
|
|
81
|
-
} catch (error) {
|
|
82
|
-
debug.error('notification', 'Error playing sound notification:', error);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Send push notification
|
|
86
|
-
try {
|
|
87
|
-
const projectName = projectState.projects.find(p => p.id === projectId)?.name || 'Unknown';
|
|
88
|
-
await pushNotification.sendChatComplete(`Waiting for your input in "${projectName}"`);
|
|
89
|
-
} catch (error) {
|
|
90
|
-
debug.error('notification', 'Error sending push notification:', error);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Remove tracked tool_use IDs for a finished session
|
|
97
|
-
*/
|
|
98
|
-
private clearSessionNotifications(chatSessionId: string): void {
|
|
99
|
-
// Tool IDs are globally unique, so a simple clear-on-stream-finish
|
|
100
|
-
// is enough — they won't collide across sessions.
|
|
101
|
-
// For long-running apps, periodically trim to avoid unbounded growth.
|
|
102
|
-
if (this.notifiedToolUseIds.size > 500) {
|
|
103
|
-
this.notifiedToolUseIds.clear();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Clear state (for cleanup/testing)
|
|
109
|
-
*/
|
|
110
|
-
clear(): void {
|
|
111
|
-
this.notifiedToolUseIds.clear();
|
|
112
|
-
debug.log('notification', 'GlobalStreamMonitor: Clearing state');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Export singleton instance
|
|
117
|
-
export const globalStreamMonitor = new GlobalStreamMonitor();
|
|
1
|
+
/**
|
|
2
|
+
* Global Stream Monitor Service
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for chat stream notifications (sound + push).
|
|
5
|
+
*
|
|
6
|
+
* Listens for backend events and triggers notifications for ALL projects —
|
|
7
|
+
* both active and non-active:
|
|
8
|
+
* - chat:stream-finished → stream completed/errored/cancelled
|
|
9
|
+
* - chat:waiting-input → AskUserQuestion requires user input
|
|
10
|
+
*
|
|
11
|
+
* The backend uses ws.emit.projectMembers() so notifications reach users
|
|
12
|
+
* even when they are on a different project or session.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { soundNotification, pushNotification } from '$frontend/services/notification';
|
|
16
|
+
import { projectState } from '$frontend/stores/core/projects.svelte';
|
|
17
|
+
import { debug } from '$shared/utils/logger';
|
|
18
|
+
import ws from '$frontend/utils/ws';
|
|
19
|
+
|
|
20
|
+
class GlobalStreamMonitor {
|
|
21
|
+
private initialized = false;
|
|
22
|
+
|
|
23
|
+
/** Track notified AskUserQuestion tool_use IDs to ensure once-only notification */
|
|
24
|
+
private notifiedToolUseIds = new Set<string>();
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Initialize the monitor - subscribes to WS events.
|
|
28
|
+
* Safe to call multiple times (idempotent).
|
|
29
|
+
*/
|
|
30
|
+
initialize(): void {
|
|
31
|
+
if (this.initialized) return;
|
|
32
|
+
this.initialized = true;
|
|
33
|
+
|
|
34
|
+
debug.log('notification', 'GlobalStreamMonitor: Initializing WS listeners');
|
|
35
|
+
|
|
36
|
+
// Stream finished — notify on completion
|
|
37
|
+
ws.on('chat:stream-finished', async (data) => {
|
|
38
|
+
const { projectId, status, chatSessionId } = data;
|
|
39
|
+
|
|
40
|
+
debug.log('notification', 'GlobalStreamMonitor: Stream finished', { projectId, status });
|
|
41
|
+
|
|
42
|
+
// Clean up notified IDs for this session (stream is done)
|
|
43
|
+
this.clearSessionNotifications(chatSessionId);
|
|
44
|
+
|
|
45
|
+
// Play sound notification
|
|
46
|
+
try {
|
|
47
|
+
await soundNotification.play();
|
|
48
|
+
} catch (error) {
|
|
49
|
+
debug.error('notification', 'Error playing sound notification:', error);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Send push notification with project context
|
|
53
|
+
try {
|
|
54
|
+
const projectName = projectState.projects.find(p => p.id === projectId)?.name || 'Unknown';
|
|
55
|
+
|
|
56
|
+
if (status === 'completed') {
|
|
57
|
+
await pushNotification.sendChatComplete(`Chat response ready in "${projectName}"`);
|
|
58
|
+
} else if (status === 'error') {
|
|
59
|
+
await pushNotification.sendChatError(`Chat error in "${projectName}"`);
|
|
60
|
+
} else if (status === 'cancelled') {
|
|
61
|
+
await pushNotification.sendChatComplete(`Chat interrupted in "${projectName}"`);
|
|
62
|
+
}
|
|
63
|
+
} catch (error) {
|
|
64
|
+
debug.error('notification', 'Error sending push notification:', error);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Waiting for input — notify once per AskUserQuestion
|
|
69
|
+
ws.on('chat:waiting-input', async (data) => {
|
|
70
|
+
const { projectId, chatSessionId, toolUseId } = data;
|
|
71
|
+
|
|
72
|
+
// Deduplicate: only notify once per tool_use ID
|
|
73
|
+
if (this.notifiedToolUseIds.has(toolUseId)) return;
|
|
74
|
+
this.notifiedToolUseIds.add(toolUseId);
|
|
75
|
+
|
|
76
|
+
debug.log('notification', 'GlobalStreamMonitor: Waiting for input', { projectId, chatSessionId, toolUseId });
|
|
77
|
+
|
|
78
|
+
// Play sound notification
|
|
79
|
+
try {
|
|
80
|
+
await soundNotification.play();
|
|
81
|
+
} catch (error) {
|
|
82
|
+
debug.error('notification', 'Error playing sound notification:', error);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Send push notification
|
|
86
|
+
try {
|
|
87
|
+
const projectName = projectState.projects.find(p => p.id === projectId)?.name || 'Unknown';
|
|
88
|
+
await pushNotification.sendChatComplete(`Waiting for your input in "${projectName}"`);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
debug.error('notification', 'Error sending push notification:', error);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Remove tracked tool_use IDs for a finished session
|
|
97
|
+
*/
|
|
98
|
+
private clearSessionNotifications(chatSessionId: string): void {
|
|
99
|
+
// Tool IDs are globally unique, so a simple clear-on-stream-finish
|
|
100
|
+
// is enough — they won't collide across sessions.
|
|
101
|
+
// For long-running apps, periodically trim to avoid unbounded growth.
|
|
102
|
+
if (this.notifiedToolUseIds.size > 500) {
|
|
103
|
+
this.notifiedToolUseIds.clear();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Clear state (for cleanup/testing)
|
|
109
|
+
*/
|
|
110
|
+
clear(): void {
|
|
111
|
+
this.notifiedToolUseIds.clear();
|
|
112
|
+
debug.log('notification', 'GlobalStreamMonitor: Clearing state');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Export singleton instance
|
|
117
|
+
export const globalStreamMonitor = new GlobalStreamMonitor();
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles native browser push notifications for chat responses
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { settings } from '$frontend/
|
|
7
|
+
import { settings } from '$frontend/stores/features/settings.svelte';
|
|
8
8
|
|
|
9
9
|
import { debug } from '$shared/utils/logger';
|
|
10
10
|
// Check if browser supports notifications
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Handles single audio notification for chat responses using local notification.ogg file
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { settings } from '$frontend/
|
|
7
|
+
import { settings } from '$frontend/stores/features/settings.svelte';
|
|
8
8
|
|
|
9
9
|
import { debug } from '$shared/utils/logger';
|
|
10
10
|
// Cache for audio element
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* opens the preview panel to display the session visually.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import ws from '$frontend/
|
|
9
|
-
import { showPanel } from '$frontend/
|
|
8
|
+
import ws from '$frontend/utils/ws';
|
|
9
|
+
import { showPanel } from '$frontend/stores/ui/workspace.svelte';
|
|
10
10
|
import { debug } from '$shared/utils/logger';
|
|
11
11
|
|
|
12
12
|
export interface MCPLaunchRequest {
|
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project Status Service
|
|
3
|
-
* Tracks active streams and user presence for projects via WebSocket
|
|
4
|
-
* Fully realtime - no cache, no polling
|
|
5
|
-
*
|
|
6
|
-
* Single event: `projects:presence-updated` contains full state
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { getOrCreateAnonymousUser, type AnonymousUser } from '$shared/utils/anonymous-user';
|
|
10
|
-
import ws from '$frontend/
|
|
11
|
-
import { debug } from '$shared/utils/logger';
|
|
12
|
-
|
|
13
|
-
export interface ProjectStatus {
|
|
14
|
-
projectId: string;
|
|
15
|
-
hasActiveStreams: boolean;
|
|
16
|
-
activeStreamCount: number;
|
|
17
|
-
activeUsers: { userId: string; userName: string }[];
|
|
18
|
-
streams: {
|
|
19
|
-
streamId: string;
|
|
20
|
-
chatSessionId: string;
|
|
21
|
-
status: string;
|
|
22
|
-
startedAt: string;
|
|
23
|
-
messagesCount: number;
|
|
24
|
-
isWaitingInput?: boolean;
|
|
25
|
-
}[];
|
|
26
|
-
/** Per-chat-session user presence: { chatSessionId → users[] } */
|
|
27
|
-
chatSessionUsers?: Record<string, { userId: string; userName: string }[]>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
class ProjectStatusService {
|
|
31
|
-
private currentUser: AnonymousUser | null = null;
|
|
32
|
-
private currentProjectId: string | null = null;
|
|
33
|
-
private initialized = false;
|
|
34
|
-
private statusUpdateCallbacks: Set<(statuses: ProjectStatus[]) => void> = new Set();
|
|
35
|
-
private unsubscribe: (() => void) | null = null;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Initialize the service - sets up WS listener
|
|
39
|
-
* Called automatically on first use
|
|
40
|
-
*/
|
|
41
|
-
async initialize(): Promise<void> {
|
|
42
|
-
if (typeof window === 'undefined' || this.initialized) return;
|
|
43
|
-
|
|
44
|
-
this.currentUser = await getOrCreateAnonymousUser();
|
|
45
|
-
debug.log('project', 'Initialized with user:', this.currentUser?.name);
|
|
46
|
-
|
|
47
|
-
this.unsubscribe = ws.on('projects:presence-updated', (data) => {
|
|
48
|
-
try {
|
|
49
|
-
if (data.type === 'presence-updated' && data.data) {
|
|
50
|
-
const statuses = Array.isArray(data.data) ? data.data : [data.data];
|
|
51
|
-
this.statusUpdateCallbacks.forEach(callback => {
|
|
52
|
-
try {
|
|
53
|
-
callback(statuses);
|
|
54
|
-
} catch (error) {
|
|
55
|
-
debug.error('project', 'Error in status callback:', error);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
} catch (error) {
|
|
60
|
-
debug.error('project', 'Error handling presence update:', error);
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
this.initialized = true;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private async ensureInitialized(): Promise<void> {
|
|
68
|
-
if (!this.initialized) {
|
|
69
|
-
await this.initialize();
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Subscribe to real-time presence updates
|
|
75
|
-
* Auto-initializes WS listener if not done yet
|
|
76
|
-
*/
|
|
77
|
-
onStatusUpdate(callback: (statuses: ProjectStatus[]) => void): () => void {
|
|
78
|
-
this.statusUpdateCallbacks.add(callback);
|
|
79
|
-
this.ensureInitialized();
|
|
80
|
-
|
|
81
|
-
return () => {
|
|
82
|
-
this.statusUpdateCallbacks.delete(callback);
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Join a project - start presence tracking
|
|
88
|
-
*/
|
|
89
|
-
async startTracking(projectId: string): Promise<void> {
|
|
90
|
-
if (typeof window === 'undefined') return;
|
|
91
|
-
|
|
92
|
-
await this.ensureInitialized();
|
|
93
|
-
|
|
94
|
-
if (this.currentProjectId && this.currentProjectId !== projectId) {
|
|
95
|
-
await this.stopTracking();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
this.currentProjectId = projectId;
|
|
99
|
-
|
|
100
|
-
if (this.currentUser) {
|
|
101
|
-
ws.emit('projects:join', {
|
|
102
|
-
userName: this.currentUser.name
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
document.addEventListener('visibilitychange', this.handleVisibilityChange);
|
|
107
|
-
window.addEventListener('beforeunload', this.handleBeforeUnload);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Leave a project - stop presence tracking
|
|
112
|
-
*/
|
|
113
|
-
async stopTracking(): Promise<void> {
|
|
114
|
-
if (this.currentProjectId && this.currentUser) {
|
|
115
|
-
// Send projectId explicitly because ws.setProject() may have already changed context
|
|
116
|
-
ws.emit('projects:leave', {
|
|
117
|
-
projectId: this.currentProjectId
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (typeof window !== 'undefined') {
|
|
122
|
-
document.removeEventListener('visibilitychange', this.handleVisibilityChange);
|
|
123
|
-
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
this.currentProjectId = null;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
cleanup(): void {
|
|
130
|
-
if (this.unsubscribe) {
|
|
131
|
-
this.unsubscribe();
|
|
132
|
-
this.unsubscribe = null;
|
|
133
|
-
}
|
|
134
|
-
this.statusUpdateCallbacks.clear();
|
|
135
|
-
this.initialized = false;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
private handleVisibilityChange = () => {
|
|
139
|
-
if (!document.hidden && this.currentProjectId && this.currentUser) {
|
|
140
|
-
ws.http('projects:update-presence', {
|
|
141
|
-
userName: this.currentUser.name,
|
|
142
|
-
action: 'update'
|
|
143
|
-
}).catch(() => {});
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
private handleBeforeUnload = () => {
|
|
148
|
-
if (this.currentProjectId && this.currentUser) {
|
|
149
|
-
ws.emit('projects:leave', {
|
|
150
|
-
projectId: this.currentProjectId
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
getCurrentUser(): AnonymousUser | null {
|
|
156
|
-
return this.currentUser;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export const projectStatusService = new ProjectStatusService();
|
|
1
|
+
/**
|
|
2
|
+
* Project Status Service
|
|
3
|
+
* Tracks active streams and user presence for projects via WebSocket
|
|
4
|
+
* Fully realtime - no cache, no polling
|
|
5
|
+
*
|
|
6
|
+
* Single event: `projects:presence-updated` contains full state
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { getOrCreateAnonymousUser, type AnonymousUser } from '$shared/utils/anonymous-user';
|
|
10
|
+
import ws from '$frontend/utils/ws';
|
|
11
|
+
import { debug } from '$shared/utils/logger';
|
|
12
|
+
|
|
13
|
+
export interface ProjectStatus {
|
|
14
|
+
projectId: string;
|
|
15
|
+
hasActiveStreams: boolean;
|
|
16
|
+
activeStreamCount: number;
|
|
17
|
+
activeUsers: { userId: string; userName: string }[];
|
|
18
|
+
streams: {
|
|
19
|
+
streamId: string;
|
|
20
|
+
chatSessionId: string;
|
|
21
|
+
status: string;
|
|
22
|
+
startedAt: string;
|
|
23
|
+
messagesCount: number;
|
|
24
|
+
isWaitingInput?: boolean;
|
|
25
|
+
}[];
|
|
26
|
+
/** Per-chat-session user presence: { chatSessionId → users[] } */
|
|
27
|
+
chatSessionUsers?: Record<string, { userId: string; userName: string }[]>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class ProjectStatusService {
|
|
31
|
+
private currentUser: AnonymousUser | null = null;
|
|
32
|
+
private currentProjectId: string | null = null;
|
|
33
|
+
private initialized = false;
|
|
34
|
+
private statusUpdateCallbacks: Set<(statuses: ProjectStatus[]) => void> = new Set();
|
|
35
|
+
private unsubscribe: (() => void) | null = null;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Initialize the service - sets up WS listener
|
|
39
|
+
* Called automatically on first use
|
|
40
|
+
*/
|
|
41
|
+
async initialize(): Promise<void> {
|
|
42
|
+
if (typeof window === 'undefined' || this.initialized) return;
|
|
43
|
+
|
|
44
|
+
this.currentUser = await getOrCreateAnonymousUser();
|
|
45
|
+
debug.log('project', 'Initialized with user:', this.currentUser?.name);
|
|
46
|
+
|
|
47
|
+
this.unsubscribe = ws.on('projects:presence-updated', (data) => {
|
|
48
|
+
try {
|
|
49
|
+
if (data.type === 'presence-updated' && data.data) {
|
|
50
|
+
const statuses = Array.isArray(data.data) ? data.data : [data.data];
|
|
51
|
+
this.statusUpdateCallbacks.forEach(callback => {
|
|
52
|
+
try {
|
|
53
|
+
callback(statuses);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
debug.error('project', 'Error in status callback:', error);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
debug.error('project', 'Error handling presence update:', error);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
this.initialized = true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private async ensureInitialized(): Promise<void> {
|
|
68
|
+
if (!this.initialized) {
|
|
69
|
+
await this.initialize();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Subscribe to real-time presence updates
|
|
75
|
+
* Auto-initializes WS listener if not done yet
|
|
76
|
+
*/
|
|
77
|
+
onStatusUpdate(callback: (statuses: ProjectStatus[]) => void): () => void {
|
|
78
|
+
this.statusUpdateCallbacks.add(callback);
|
|
79
|
+
this.ensureInitialized();
|
|
80
|
+
|
|
81
|
+
return () => {
|
|
82
|
+
this.statusUpdateCallbacks.delete(callback);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Join a project - start presence tracking
|
|
88
|
+
*/
|
|
89
|
+
async startTracking(projectId: string): Promise<void> {
|
|
90
|
+
if (typeof window === 'undefined') return;
|
|
91
|
+
|
|
92
|
+
await this.ensureInitialized();
|
|
93
|
+
|
|
94
|
+
if (this.currentProjectId && this.currentProjectId !== projectId) {
|
|
95
|
+
await this.stopTracking();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.currentProjectId = projectId;
|
|
99
|
+
|
|
100
|
+
if (this.currentUser) {
|
|
101
|
+
ws.emit('projects:join', {
|
|
102
|
+
userName: this.currentUser.name
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
document.addEventListener('visibilitychange', this.handleVisibilityChange);
|
|
107
|
+
window.addEventListener('beforeunload', this.handleBeforeUnload);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Leave a project - stop presence tracking
|
|
112
|
+
*/
|
|
113
|
+
async stopTracking(): Promise<void> {
|
|
114
|
+
if (this.currentProjectId && this.currentUser) {
|
|
115
|
+
// Send projectId explicitly because ws.setProject() may have already changed context
|
|
116
|
+
ws.emit('projects:leave', {
|
|
117
|
+
projectId: this.currentProjectId
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (typeof window !== 'undefined') {
|
|
122
|
+
document.removeEventListener('visibilitychange', this.handleVisibilityChange);
|
|
123
|
+
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.currentProjectId = null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
cleanup(): void {
|
|
130
|
+
if (this.unsubscribe) {
|
|
131
|
+
this.unsubscribe();
|
|
132
|
+
this.unsubscribe = null;
|
|
133
|
+
}
|
|
134
|
+
this.statusUpdateCallbacks.clear();
|
|
135
|
+
this.initialized = false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private handleVisibilityChange = () => {
|
|
139
|
+
if (!document.hidden && this.currentProjectId && this.currentUser) {
|
|
140
|
+
ws.http('projects:update-presence', {
|
|
141
|
+
userName: this.currentUser.name,
|
|
142
|
+
action: 'update'
|
|
143
|
+
}).catch(() => {});
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
private handleBeforeUnload = () => {
|
|
148
|
+
if (this.currentProjectId && this.currentUser) {
|
|
149
|
+
ws.emit('projects:leave', {
|
|
150
|
+
projectId: this.currentProjectId
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
getCurrentUser(): AnonymousUser | null {
|
|
156
|
+
return this.currentUser;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export const projectStatusService = new ProjectStatusService();
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* v2 adds conflict detection and session-scoped restore.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import ws from '$frontend/
|
|
9
|
-
import type { TimelineResponse } from '$frontend/
|
|
8
|
+
import ws from '$frontend/utils/ws';
|
|
9
|
+
import type { TimelineResponse } from '$frontend/components/checkpoint/timeline/types';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Conflict information for a single file
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { terminalSessionManager } from '../session.service';
|
|
7
7
|
import { terminalPersistenceManager } from '../persistence.service';
|
|
8
|
-
import { terminalStore } from '$frontend/
|
|
8
|
+
import { terminalStore } from '$frontend/stores/features/terminal.svelte';
|
|
9
9
|
|
|
10
10
|
// Import modular services
|
|
11
11
|
import { streamManager } from './stream-manager';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { terminalSessionManager } from '../session.service';
|
|
7
7
|
import { terminalPersistenceManager } from '../persistence.service';
|
|
8
|
-
import { terminalStore } from '$frontend/
|
|
8
|
+
import { terminalStore } from '$frontend/stores/features/terminal.svelte';
|
|
9
9
|
|
|
10
10
|
interface SessionToReconnect {
|
|
11
11
|
sessionId: string;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { terminalSessionManager } from '../session.service';
|
|
7
7
|
import { terminalPersistenceManager } from '../persistence.service';
|
|
8
|
-
import { terminalStore } from '$frontend/
|
|
8
|
+
import { terminalStore } from '$frontend/stores/features/terminal.svelte';
|
|
9
9
|
import type { TerminalLine } from '$shared/types/terminal';
|
|
10
10
|
|
|
11
11
|
export interface StreamInfo {
|