@myrialabs/clopen 0.0.1
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/.env.example +6 -0
- package/.github/workflows/release.yml +60 -0
- package/.github/workflows/test.yml +40 -0
- package/CONTRIBUTING.md +499 -0
- package/LICENSE +21 -0
- package/README.md +209 -0
- package/backend/index.ts +156 -0
- package/backend/lib/chat/helpers.ts +42 -0
- package/backend/lib/chat/index.ts +2 -0
- package/backend/lib/chat/stream-manager.ts +1126 -0
- package/backend/lib/database/README.md +77 -0
- package/backend/lib/database/index.ts +119 -0
- package/backend/lib/database/migrations/001_create_projects_table.ts +31 -0
- package/backend/lib/database/migrations/002_create_chat_sessions_table.ts +33 -0
- package/backend/lib/database/migrations/003_create_messages_table.ts +32 -0
- package/backend/lib/database/migrations/004_create_prompt_templates_table.ts +34 -0
- package/backend/lib/database/migrations/005_create_settings_table.ts +24 -0
- package/backend/lib/database/migrations/006_add_user_to_messages.ts +58 -0
- package/backend/lib/database/migrations/007_create_stream_states_table.ts +41 -0
- package/backend/lib/database/migrations/008_create_message_snapshots_table.ts +62 -0
- package/backend/lib/database/migrations/009_add_delta_snapshot_fields.ts +41 -0
- package/backend/lib/database/migrations/010_add_soft_delete_and_branch_support.ts +70 -0
- package/backend/lib/database/migrations/011_git_like_commit_graph.ts +156 -0
- package/backend/lib/database/migrations/012_add_file_change_statistics.ts +41 -0
- package/backend/lib/database/migrations/013_checkpoint_tree_state.ts +118 -0
- package/backend/lib/database/migrations/014_add_engine_to_sessions.ts +18 -0
- package/backend/lib/database/migrations/015_add_model_to_sessions.ts +18 -0
- package/backend/lib/database/migrations/016_create_user_projects_table.ts +34 -0
- package/backend/lib/database/migrations/017_add_current_session_to_user_projects.ts +32 -0
- package/backend/lib/database/migrations/018_create_claude_accounts_table.ts +24 -0
- package/backend/lib/database/migrations/019_add_claude_account_to_sessions.ts +18 -0
- package/backend/lib/database/migrations/020_add_snapshot_tree_hash.ts +32 -0
- package/backend/lib/database/migrations/021_drop_prompt_templates_table.ts +33 -0
- package/backend/lib/database/migrations/index.ts +154 -0
- package/backend/lib/database/queries/checkpoint-queries.ts +87 -0
- package/backend/lib/database/queries/engine-queries.ts +75 -0
- package/backend/lib/database/queries/index.ts +9 -0
- package/backend/lib/database/queries/message-queries.ts +472 -0
- package/backend/lib/database/queries/project-queries.ts +117 -0
- package/backend/lib/database/queries/session-queries.ts +271 -0
- package/backend/lib/database/queries/settings-queries.ts +34 -0
- package/backend/lib/database/queries/snapshot-queries.ts +326 -0
- package/backend/lib/database/queries/utils-queries.ts +59 -0
- package/backend/lib/database/seeders/index.ts +13 -0
- package/backend/lib/database/seeders/settings_seeder.ts +84 -0
- package/backend/lib/database/utils/connection.ts +174 -0
- package/backend/lib/database/utils/index.ts +4 -0
- package/backend/lib/database/utils/migration-runner.ts +118 -0
- package/backend/lib/database/utils/seeder-runner.ts +121 -0
- package/backend/lib/engine/adapters/claude/environment.ts +164 -0
- package/backend/lib/engine/adapters/claude/error-handler.ts +60 -0
- package/backend/lib/engine/adapters/claude/index.ts +1 -0
- package/backend/lib/engine/adapters/claude/path-utils.ts +38 -0
- package/backend/lib/engine/adapters/claude/stream.ts +177 -0
- package/backend/lib/engine/adapters/opencode/index.ts +2 -0
- package/backend/lib/engine/adapters/opencode/message-converter.ts +862 -0
- package/backend/lib/engine/adapters/opencode/server.ts +104 -0
- package/backend/lib/engine/adapters/opencode/stream.ts +755 -0
- package/backend/lib/engine/index.ts +196 -0
- package/backend/lib/engine/types.ts +58 -0
- package/backend/lib/files/file-operations.ts +478 -0
- package/backend/lib/files/file-reading.ts +308 -0
- package/backend/lib/files/file-watcher.ts +383 -0
- package/backend/lib/files/path-browsing.ts +382 -0
- package/backend/lib/git/git-executor.ts +88 -0
- package/backend/lib/git/git-parser.ts +411 -0
- package/backend/lib/git/git-service.ts +505 -0
- package/backend/lib/mcp/README.md +1144 -0
- package/backend/lib/mcp/config.ts +316 -0
- package/backend/lib/mcp/index.ts +35 -0
- package/backend/lib/mcp/project-context.ts +236 -0
- package/backend/lib/mcp/servers/browser-automation/actions.ts +156 -0
- package/backend/lib/mcp/servers/browser-automation/browser.ts +419 -0
- package/backend/lib/mcp/servers/browser-automation/index.ts +791 -0
- package/backend/lib/mcp/servers/browser-automation/inspection.ts +501 -0
- package/backend/lib/mcp/servers/helper.ts +143 -0
- package/backend/lib/mcp/servers/index.ts +45 -0
- package/backend/lib/mcp/servers/weather/get-temperature.ts +56 -0
- package/backend/lib/mcp/servers/weather/index.ts +31 -0
- package/backend/lib/mcp/stdio-server.ts +103 -0
- package/backend/lib/mcp/types.ts +65 -0
- package/backend/lib/preview/browser/browser-audio-capture.ts +86 -0
- package/backend/lib/preview/browser/browser-console-manager.ts +263 -0
- package/backend/lib/preview/browser/browser-dialog-handler.ts +222 -0
- package/backend/lib/preview/browser/browser-interaction-handler.ts +421 -0
- package/backend/lib/preview/browser/browser-mcp-control.ts +415 -0
- package/backend/lib/preview/browser/browser-native-ui-handler.ts +512 -0
- package/backend/lib/preview/browser/browser-navigation-tracker.ts +104 -0
- package/backend/lib/preview/browser/browser-pool.ts +357 -0
- package/backend/lib/preview/browser/browser-preview-service.ts +882 -0
- package/backend/lib/preview/browser/browser-tab-manager.ts +935 -0
- package/backend/lib/preview/browser/browser-video-capture.ts +695 -0
- package/backend/lib/preview/browser/scripts/audio-stream.ts +292 -0
- package/backend/lib/preview/browser/scripts/cursor-tracking.ts +85 -0
- package/backend/lib/preview/browser/scripts/video-stream.ts +438 -0
- package/backend/lib/preview/browser/types.ts +359 -0
- package/backend/lib/preview/index.ts +24 -0
- package/backend/lib/project/index.ts +2 -0
- package/backend/lib/project/status-manager.ts +182 -0
- package/backend/lib/shared/index.ts +2 -0
- package/backend/lib/shared/port-utils.ts +25 -0
- package/backend/lib/shared/process-manager.ts +281 -0
- package/backend/lib/snapshot/blob-store.ts +227 -0
- package/backend/lib/snapshot/gitignore.ts +307 -0
- package/backend/lib/snapshot/helpers.ts +397 -0
- package/backend/lib/snapshot/snapshot-service.ts +483 -0
- package/backend/lib/terminal/helpers.ts +14 -0
- package/backend/lib/terminal/index.ts +8 -0
- package/backend/lib/terminal/pty-manager.ts +4 -0
- package/backend/lib/terminal/pty-session-manager.ts +387 -0
- package/backend/lib/terminal/shell-utils.ts +313 -0
- package/backend/lib/terminal/stream-manager.ts +293 -0
- package/backend/lib/tunnel/global-tunnel-manager.ts +243 -0
- package/backend/lib/tunnel/project-tunnel-manager.ts +311 -0
- package/backend/lib/user/helpers.ts +87 -0
- package/backend/lib/utils/ws.ts +944 -0
- package/backend/lib/vite-dev.ts +353 -0
- package/backend/middleware/cors.ts +15 -0
- package/backend/middleware/error-handler.ts +49 -0
- package/backend/middleware/logger.ts +9 -0
- package/backend/types/api.ts +24 -0
- package/backend/ws/README.md +1505 -0
- package/backend/ws/chat/background.ts +198 -0
- package/backend/ws/chat/index.ts +21 -0
- package/backend/ws/chat/stream.ts +707 -0
- package/backend/ws/engine/claude/accounts.ts +401 -0
- package/backend/ws/engine/claude/index.ts +13 -0
- package/backend/ws/engine/claude/status.ts +43 -0
- package/backend/ws/engine/index.ts +14 -0
- package/backend/ws/engine/opencode/index.ts +11 -0
- package/backend/ws/engine/opencode/status.ts +30 -0
- package/backend/ws/engine/utils.ts +36 -0
- package/backend/ws/files/index.ts +30 -0
- package/backend/ws/files/read.ts +189 -0
- package/backend/ws/files/search.ts +453 -0
- package/backend/ws/files/watch.ts +124 -0
- package/backend/ws/files/write.ts +143 -0
- package/backend/ws/git/branch.ts +106 -0
- package/backend/ws/git/commit.ts +39 -0
- package/backend/ws/git/conflict.ts +68 -0
- package/backend/ws/git/diff.ts +69 -0
- package/backend/ws/git/index.ts +24 -0
- package/backend/ws/git/log.ts +41 -0
- package/backend/ws/git/remote.ts +214 -0
- package/backend/ws/git/staging.ts +84 -0
- package/backend/ws/git/status.ts +90 -0
- package/backend/ws/index.ts +69 -0
- package/backend/ws/mcp/index.ts +61 -0
- package/backend/ws/messages/crud.ts +74 -0
- package/backend/ws/messages/index.ts +14 -0
- package/backend/ws/preview/browser/cleanup.ts +129 -0
- package/backend/ws/preview/browser/console.ts +114 -0
- package/backend/ws/preview/browser/interact.ts +513 -0
- package/backend/ws/preview/browser/mcp.ts +129 -0
- package/backend/ws/preview/browser/native-ui.ts +235 -0
- package/backend/ws/preview/browser/stats.ts +55 -0
- package/backend/ws/preview/browser/tab-info.ts +126 -0
- package/backend/ws/preview/browser/tab.ts +166 -0
- package/backend/ws/preview/browser/webcodecs.ts +293 -0
- package/backend/ws/preview/index.ts +146 -0
- package/backend/ws/projects/crud.ts +113 -0
- package/backend/ws/projects/index.ts +25 -0
- package/backend/ws/projects/presence.ts +46 -0
- package/backend/ws/projects/status.ts +116 -0
- package/backend/ws/sessions/crud.ts +327 -0
- package/backend/ws/sessions/index.ts +33 -0
- package/backend/ws/settings/crud.ts +112 -0
- package/backend/ws/settings/index.ts +14 -0
- package/backend/ws/snapshot/index.ts +17 -0
- package/backend/ws/snapshot/restore.ts +173 -0
- package/backend/ws/snapshot/timeline.ts +141 -0
- package/backend/ws/system/index.ts +14 -0
- package/backend/ws/system/operations.ts +49 -0
- package/backend/ws/terminal/index.ts +40 -0
- package/backend/ws/terminal/persistence.ts +153 -0
- package/backend/ws/terminal/session.ts +382 -0
- package/backend/ws/terminal/stream.ts +79 -0
- package/backend/ws/tunnel/index.ts +14 -0
- package/backend/ws/tunnel/operations.ts +91 -0
- package/backend/ws/types.ts +20 -0
- package/backend/ws/user/crud.ts +156 -0
- package/backend/ws/user/index.ts +14 -0
- package/bin/clopen.ts +307 -0
- package/bun.lock +1352 -0
- package/frontend/App.svelte +34 -0
- package/frontend/app.css +313 -0
- package/frontend/lib/app-environment.ts +10 -0
- package/frontend/lib/components/chat/ChatInterface.svelte +407 -0
- package/frontend/lib/components/chat/formatters/ErrorMessage.svelte +57 -0
- package/frontend/lib/components/chat/formatters/MessageFormatter.svelte +224 -0
- package/frontend/lib/components/chat/formatters/TextMessage.svelte +395 -0
- package/frontend/lib/components/chat/formatters/Tools.svelte +70 -0
- package/frontend/lib/components/chat/formatters/index.ts +3 -0
- package/frontend/lib/components/chat/input/ChatInput.svelte +421 -0
- package/frontend/lib/components/chat/input/components/ChatInputActions.svelte +78 -0
- package/frontend/lib/components/chat/input/components/DragDropOverlay.svelte +30 -0
- package/frontend/lib/components/chat/input/components/EditModeIndicator.svelte +33 -0
- package/frontend/lib/components/chat/input/components/EngineModelPicker.svelte +619 -0
- package/frontend/lib/components/chat/input/components/FileAttachmentPreview.svelte +48 -0
- package/frontend/lib/components/chat/input/components/LoadingIndicator.svelte +31 -0
- package/frontend/lib/components/chat/input/composables/use-animations.svelte.ts +201 -0
- package/frontend/lib/components/chat/input/composables/use-chat-actions.svelte.ts +148 -0
- package/frontend/lib/components/chat/input/composables/use-file-handling.svelte.ts +216 -0
- package/frontend/lib/components/chat/input/composables/use-input-state.svelte.ts +357 -0
- package/frontend/lib/components/chat/input/composables/use-textarea-resize.svelte.ts +57 -0
- package/frontend/lib/components/chat/message/ChatMessage.svelte +478 -0
- package/frontend/lib/components/chat/message/ChatMessages.svelte +541 -0
- package/frontend/lib/components/chat/message/DateSeparator.svelte +86 -0
- package/frontend/lib/components/chat/message/MessageBubble.svelte +86 -0
- package/frontend/lib/components/chat/message/MessageHeader.svelte +157 -0
- package/frontend/lib/components/chat/modal/DebugModal.svelte +59 -0
- package/frontend/lib/components/chat/modal/TokenUsageModal.svelte +124 -0
- package/frontend/lib/components/chat/shared/index.ts +2 -0
- package/frontend/lib/components/chat/shared/utils.ts +116 -0
- package/frontend/lib/components/chat/tools/BashOutputTool.svelte +35 -0
- package/frontend/lib/components/chat/tools/BashTool.svelte +46 -0
- package/frontend/lib/components/chat/tools/CustomMcpTool.svelte +139 -0
- package/frontend/lib/components/chat/tools/EditTool.svelte +48 -0
- package/frontend/lib/components/chat/tools/ExitPlanModeTool.svelte +32 -0
- package/frontend/lib/components/chat/tools/GlobTool.svelte +51 -0
- package/frontend/lib/components/chat/tools/GrepTool.svelte +90 -0
- package/frontend/lib/components/chat/tools/KillShellTool.svelte +26 -0
- package/frontend/lib/components/chat/tools/ListMcpResourcesTool.svelte +31 -0
- package/frontend/lib/components/chat/tools/NotebookEditTool.svelte +38 -0
- package/frontend/lib/components/chat/tools/ReadMcpResourceTool.svelte +34 -0
- package/frontend/lib/components/chat/tools/ReadTool.svelte +41 -0
- package/frontend/lib/components/chat/tools/TaskTool.svelte +64 -0
- package/frontend/lib/components/chat/tools/TodoWriteTool.svelte +75 -0
- package/frontend/lib/components/chat/tools/WebFetchTool.svelte +35 -0
- package/frontend/lib/components/chat/tools/WebSearchTool.svelte +84 -0
- package/frontend/lib/components/chat/tools/WriteTool.svelte +33 -0
- package/frontend/lib/components/chat/tools/components/CodeBlock.svelte +79 -0
- package/frontend/lib/components/chat/tools/components/DiffBlock.svelte +408 -0
- package/frontend/lib/components/chat/tools/components/FileHeader.svelte +45 -0
- package/frontend/lib/components/chat/tools/components/InfoLine.svelte +19 -0
- package/frontend/lib/components/chat/tools/components/StatsBadges.svelte +27 -0
- package/frontend/lib/components/chat/tools/components/TerminalCommand.svelte +54 -0
- package/frontend/lib/components/chat/tools/components/index.ts +7 -0
- package/frontend/lib/components/chat/tools/index.ts +26 -0
- package/frontend/lib/components/chat/widgets/FloatingTodoList.svelte +249 -0
- package/frontend/lib/components/chat/widgets/TokenUsage.svelte +78 -0
- package/frontend/lib/components/checkpoint/TimelineModal.svelte +391 -0
- package/frontend/lib/components/checkpoint/timeline/TimelineEdge.svelte +26 -0
- package/frontend/lib/components/checkpoint/timeline/TimelineGraph.svelte +87 -0
- package/frontend/lib/components/checkpoint/timeline/TimelineNode.svelte +108 -0
- package/frontend/lib/components/checkpoint/timeline/TimelineVersionGroup.svelte +59 -0
- package/frontend/lib/components/checkpoint/timeline/animation.ts +168 -0
- package/frontend/lib/components/checkpoint/timeline/config.ts +44 -0
- package/frontend/lib/components/checkpoint/timeline/graph-builder.ts +304 -0
- package/frontend/lib/components/checkpoint/timeline/types.ts +65 -0
- package/frontend/lib/components/checkpoint/timeline/utils.ts +53 -0
- package/frontend/lib/components/common/Alert.svelte +139 -0
- package/frontend/lib/components/common/AvatarBubble.svelte +56 -0
- package/frontend/lib/components/common/Button.svelte +71 -0
- package/frontend/lib/components/common/Card.svelte +102 -0
- package/frontend/lib/components/common/Checkbox.svelte +48 -0
- package/frontend/lib/components/common/Dialog.svelte +249 -0
- package/frontend/lib/components/common/FolderBrowser.svelte +843 -0
- package/frontend/lib/components/common/Icon.svelte +58 -0
- package/frontend/lib/components/common/Input.svelte +72 -0
- package/frontend/lib/components/common/Lightbox.svelte +233 -0
- package/frontend/lib/components/common/LoadingScreen.svelte +52 -0
- package/frontend/lib/components/common/LoadingSpinner.svelte +48 -0
- package/frontend/lib/components/common/Modal.svelte +177 -0
- package/frontend/lib/components/common/ModalProvider.svelte +28 -0
- package/frontend/lib/components/common/ModelSelector.svelte +110 -0
- package/frontend/lib/components/common/MonacoEditor.svelte +569 -0
- package/frontend/lib/components/common/NotificationToast.svelte +113 -0
- package/frontend/lib/components/common/PageTemplate.svelte +76 -0
- package/frontend/lib/components/common/ProjectUserAvatars.svelte +79 -0
- package/frontend/lib/components/common/Select.svelte +98 -0
- package/frontend/lib/components/common/Textarea.svelte +80 -0
- package/frontend/lib/components/common/ThemeToggle.svelte +44 -0
- package/frontend/lib/components/common/lucide-icons.ts +1642 -0
- package/frontend/lib/components/common/material-icons.ts +1082 -0
- package/frontend/lib/components/common/xterm/XTerm.svelte +796 -0
- package/frontend/lib/components/common/xterm/index.ts +16 -0
- package/frontend/lib/components/common/xterm/terminal-config.ts +68 -0
- package/frontend/lib/components/common/xterm/types.ts +31 -0
- package/frontend/lib/components/common/xterm/xterm-service.ts +353 -0
- package/frontend/lib/components/files/FileNode.svelte +384 -0
- package/frontend/lib/components/files/FileTree.svelte +681 -0
- package/frontend/lib/components/files/FileViewer.svelte +728 -0
- package/frontend/lib/components/files/SearchResults.svelte +303 -0
- package/frontend/lib/components/git/BranchManager.svelte +458 -0
- package/frontend/lib/components/git/ChangesSection.svelte +107 -0
- package/frontend/lib/components/git/CommitForm.svelte +76 -0
- package/frontend/lib/components/git/ConflictResolver.svelte +158 -0
- package/frontend/lib/components/git/DiffViewer.svelte +364 -0
- package/frontend/lib/components/git/FileChangeItem.svelte +97 -0
- package/frontend/lib/components/git/GitButton.svelte +33 -0
- package/frontend/lib/components/git/GitLog.svelte +361 -0
- package/frontend/lib/components/git/GitModal.svelte +80 -0
- package/frontend/lib/components/history/HistoryModal.svelte +563 -0
- package/frontend/lib/components/history/HistoryView.svelte +615 -0
- package/frontend/lib/components/index.ts +34 -0
- package/frontend/lib/components/preview/browser/BrowserPreview.svelte +549 -0
- package/frontend/lib/components/preview/browser/components/Canvas.svelte +1058 -0
- package/frontend/lib/components/preview/browser/components/ConsolePanel.svelte +757 -0
- package/frontend/lib/components/preview/browser/components/Container.svelte +450 -0
- package/frontend/lib/components/preview/browser/components/ContextMenu.svelte +236 -0
- package/frontend/lib/components/preview/browser/components/SelectDropdown.svelte +224 -0
- package/frontend/lib/components/preview/browser/components/Toolbar.svelte +339 -0
- package/frontend/lib/components/preview/browser/components/VirtualCursor.svelte +36 -0
- package/frontend/lib/components/preview/browser/core/cleanup.svelte.ts +155 -0
- package/frontend/lib/components/preview/browser/core/coordinator.svelte.ts +837 -0
- package/frontend/lib/components/preview/browser/core/interactions.svelte.ts +113 -0
- package/frontend/lib/components/preview/browser/core/mcp-handlers.svelte.ts +296 -0
- package/frontend/lib/components/preview/browser/core/native-ui-handlers.svelte.ts +391 -0
- package/frontend/lib/components/preview/browser/core/stream-handler.svelte.ts +231 -0
- package/frontend/lib/components/preview/browser/core/tab-manager.svelte.ts +210 -0
- package/frontend/lib/components/preview/browser/core/tab-operations.svelte.ts +239 -0
- package/frontend/lib/components/preview/index.ts +2 -0
- package/frontend/lib/components/settings/SettingsModal.svelte +235 -0
- package/frontend/lib/components/settings/SettingsView.svelte +36 -0
- package/frontend/lib/components/settings/appearance/AppearanceSettings.svelte +51 -0
- package/frontend/lib/components/settings/appearance/LayoutPresetSettings.svelte +160 -0
- package/frontend/lib/components/settings/appearance/LayoutPreview.svelte +76 -0
- package/frontend/lib/components/settings/engines/AIEnginesSettings.svelte +917 -0
- package/frontend/lib/components/settings/general/AdvancedSettings.svelte +187 -0
- package/frontend/lib/components/settings/general/DataManagementSettings.svelte +203 -0
- package/frontend/lib/components/settings/general/GeneralSettings.svelte +10 -0
- package/frontend/lib/components/settings/model/ModelSettings.svelte +357 -0
- package/frontend/lib/components/settings/notifications/NotificationSettings.svelte +205 -0
- package/frontend/lib/components/settings/user/UserSettings.svelte +197 -0
- package/frontend/lib/components/terminal/Terminal.svelte +368 -0
- package/frontend/lib/components/terminal/TerminalTabs.svelte +87 -0
- package/frontend/lib/components/terminal/TerminalView.svelte +55 -0
- package/frontend/lib/components/tunnel/TunnelActive.svelte +142 -0
- package/frontend/lib/components/tunnel/TunnelButton.svelte +54 -0
- package/frontend/lib/components/tunnel/TunnelInactive.svelte +284 -0
- package/frontend/lib/components/tunnel/TunnelModal.svelte +47 -0
- package/frontend/lib/components/tunnel/TunnelQRCode.svelte +49 -0
- package/frontend/lib/components/workspace/DesktopNavigator.svelte +382 -0
- package/frontend/lib/components/workspace/MobileNavigator.svelte +403 -0
- package/frontend/lib/components/workspace/PanelContainer.svelte +100 -0
- package/frontend/lib/components/workspace/PanelHeader.svelte +505 -0
- package/frontend/lib/components/workspace/ViewMenu.svelte +162 -0
- package/frontend/lib/components/workspace/WorkspaceLayout.svelte +169 -0
- package/frontend/lib/components/workspace/layout/DesktopLayout.svelte +15 -0
- package/frontend/lib/components/workspace/layout/MobileLayout.svelte +17 -0
- package/frontend/lib/components/workspace/layout/split-pane/Container.svelte +42 -0
- package/frontend/lib/components/workspace/layout/split-pane/Handle.svelte +85 -0
- package/frontend/lib/components/workspace/layout/split-pane/Layout.svelte +37 -0
- package/frontend/lib/components/workspace/panels/ChatPanel.svelte +274 -0
- package/frontend/lib/components/workspace/panels/FilesPanel.svelte +1261 -0
- package/frontend/lib/components/workspace/panels/GitPanel.svelte +1560 -0
- package/frontend/lib/components/workspace/panels/PreviewPanel.svelte +150 -0
- package/frontend/lib/components/workspace/panels/TerminalPanel.svelte +73 -0
- package/frontend/lib/constants/preview.ts +45 -0
- package/frontend/lib/services/chat/chat.service.ts +704 -0
- package/frontend/lib/services/chat/index.ts +7 -0
- package/frontend/lib/services/notification/global-stream-monitor.ts +86 -0
- package/frontend/lib/services/notification/index.ts +8 -0
- package/frontend/lib/services/notification/push.service.ts +144 -0
- package/frontend/lib/services/notification/sound.service.ts +127 -0
- package/frontend/lib/services/preview/browser/browser-console.service.ts +61 -0
- package/frontend/lib/services/preview/browser/browser-webcodecs.service.ts +1499 -0
- package/frontend/lib/services/preview/browser/mcp-integration.svelte.ts +67 -0
- package/frontend/lib/services/preview/index.ts +23 -0
- package/frontend/lib/services/project/index.ts +8 -0
- package/frontend/lib/services/project/status.service.ts +159 -0
- package/frontend/lib/services/snapshot/snapshot.service.ts +47 -0
- package/frontend/lib/services/terminal/background/index.ts +130 -0
- package/frontend/lib/services/terminal/background/session-restore.ts +274 -0
- package/frontend/lib/services/terminal/background/stream-manager.ts +286 -0
- package/frontend/lib/services/terminal/index.ts +14 -0
- package/frontend/lib/services/terminal/persistence.service.ts +260 -0
- package/frontend/lib/services/terminal/project.service.ts +953 -0
- package/frontend/lib/services/terminal/session.service.ts +364 -0
- package/frontend/lib/services/terminal/terminal.service.ts +369 -0
- package/frontend/lib/stores/core/app.svelte.ts +117 -0
- package/frontend/lib/stores/core/files.svelte.ts +73 -0
- package/frontend/lib/stores/core/presence.svelte.ts +48 -0
- package/frontend/lib/stores/core/projects.svelte.ts +317 -0
- package/frontend/lib/stores/core/sessions.svelte.ts +383 -0
- package/frontend/lib/stores/features/claude-accounts.svelte.ts +58 -0
- package/frontend/lib/stores/features/models.svelte.ts +89 -0
- package/frontend/lib/stores/features/settings.svelte.ts +87 -0
- package/frontend/lib/stores/features/terminal.svelte.ts +701 -0
- package/frontend/lib/stores/features/tunnel.svelte.ts +161 -0
- package/frontend/lib/stores/features/user.svelte.ts +96 -0
- package/frontend/lib/stores/ui/chat-input.svelte.ts +57 -0
- package/frontend/lib/stores/ui/chat-model.svelte.ts +61 -0
- package/frontend/lib/stores/ui/dialog.svelte.ts +59 -0
- package/frontend/lib/stores/ui/edit-mode.svelte.ts +214 -0
- package/frontend/lib/stores/ui/notification.svelte.ts +166 -0
- package/frontend/lib/stores/ui/settings-modal.svelte.ts +88 -0
- package/frontend/lib/stores/ui/theme.svelte.ts +179 -0
- package/frontend/lib/stores/ui/workspace.svelte.ts +754 -0
- package/frontend/lib/types/native-ui.ts +73 -0
- package/frontend/lib/utils/chat/date-separator.ts +39 -0
- package/frontend/lib/utils/chat/message-grouper.ts +219 -0
- package/frontend/lib/utils/chat/message-processor.ts +135 -0
- package/frontend/lib/utils/chat/tool-handler.ts +161 -0
- package/frontend/lib/utils/chat/virtual-scroll.svelte.ts +142 -0
- package/frontend/lib/utils/click-outside.ts +20 -0
- package/frontend/lib/utils/context-manager.ts +257 -0
- package/frontend/lib/utils/file-icon-mappings.ts +769 -0
- package/frontend/lib/utils/folder-icon-mappings.ts +1030 -0
- package/frontend/lib/utils/git-status.ts +68 -0
- package/frontend/lib/utils/platform.ts +113 -0
- package/frontend/lib/utils/port-check.ts +65 -0
- package/frontend/lib/utils/terminalFormatter.ts +207 -0
- package/frontend/lib/utils/theme.ts +6 -0
- package/frontend/lib/utils/tree-visualizer.ts +320 -0
- package/frontend/lib/utils/ws.ts +44 -0
- package/frontend/main.ts +13 -0
- package/index.html +70 -0
- package/package.json +111 -0
- package/scripts/generate-icons.ts +87 -0
- package/scripts/pre-publish-check.sh +142 -0
- package/scripts/setup-hooks.sh +134 -0
- package/scripts/validate-branch-name.sh +47 -0
- package/scripts/validate-commit-msg.sh +42 -0
- package/shared/constants/engines.ts +134 -0
- package/shared/types/database/connection.ts +16 -0
- package/shared/types/database/index.ts +6 -0
- package/shared/types/database/schema.ts +141 -0
- package/shared/types/engine/index.ts +45 -0
- package/shared/types/filesystem/index.ts +22 -0
- package/shared/types/git.ts +171 -0
- package/shared/types/messaging/index.ts +239 -0
- package/shared/types/messaging/tool.ts +526 -0
- package/shared/types/network/api.ts +18 -0
- package/shared/types/network/index.ts +5 -0
- package/shared/types/stores/app.ts +23 -0
- package/shared/types/stores/dialog.ts +21 -0
- package/shared/types/stores/index.ts +3 -0
- package/shared/types/stores/settings.ts +15 -0
- package/shared/types/terminal/index.ts +44 -0
- package/shared/types/ui/components.ts +61 -0
- package/shared/types/ui/icons.ts +23 -0
- package/shared/types/ui/index.ts +22 -0
- package/shared/types/ui/notifications.ts +14 -0
- package/shared/types/ui/theme.ts +12 -0
- package/shared/types/websocket/index.ts +43 -0
- package/shared/types/window.d.ts +13 -0
- package/shared/utils/anonymous-user.ts +168 -0
- package/shared/utils/async.ts +10 -0
- package/shared/utils/diff-calculator.ts +184 -0
- package/shared/utils/file-type-detection.ts +166 -0
- package/shared/utils/logger.ts +158 -0
- package/shared/utils/message-formatter.ts +79 -0
- package/shared/utils/path.ts +47 -0
- package/shared/utils/ws-client.ts +768 -0
- package/shared/utils/ws-server.ts +660 -0
- package/static/audio/notification.ogg +0 -0
- package/static/favicon.svg +8 -0
- package/static/fonts/dm-sans/dm-sans-italic-latin-ext.woff2 +0 -0
- package/static/fonts/dm-sans/dm-sans-italic-latin.woff2 +0 -0
- package/static/fonts/dm-sans/dm-sans-normal-latin-ext.woff2 +0 -0
- package/static/fonts/dm-sans/dm-sans-normal-latin.woff2 +0 -0
- package/static/fonts/dm-sans.css +96 -0
- package/svelte.config.js +20 -0
- package/vite.config.ts +33 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { ToastNotification } from '$shared/types/ui/notifications';
|
|
2
|
+
|
|
3
|
+
// Notification store using Svelte 5 runes
|
|
4
|
+
export const notificationStore = $state({
|
|
5
|
+
notifications: [] as ToastNotification[],
|
|
6
|
+
maxNotifications: 5
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// Derived values as functions (cannot export derived state from modules)
|
|
10
|
+
export function hasNotifications() {
|
|
11
|
+
return notificationStore.notifications.length > 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function notificationCount() {
|
|
15
|
+
return notificationStore.notifications.length;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Notification management functions
|
|
19
|
+
export function addNotification(notification: Omit<ToastNotification, 'id'>) {
|
|
20
|
+
const newNotification: ToastNotification = {
|
|
21
|
+
id: Date.now().toString(),
|
|
22
|
+
...notification,
|
|
23
|
+
duration: notification.duration || 5000 // Default 5 seconds
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
notificationStore.notifications.push(newNotification);
|
|
27
|
+
|
|
28
|
+
// Remove oldest notification if we exceed max
|
|
29
|
+
if (notificationStore.notifications.length > notificationStore.maxNotifications) {
|
|
30
|
+
notificationStore.notifications.shift();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return newNotification;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function removeNotification(id: string) {
|
|
37
|
+
notificationStore.notifications = notificationStore.notifications.filter((n) => n.id !== id);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function clearNotifications() {
|
|
41
|
+
notificationStore.notifications = [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function updateNotification(id: string, updates: Partial<ToastNotification>) {
|
|
45
|
+
const index = notificationStore.notifications.findIndex((n) => n.id === id);
|
|
46
|
+
if (index !== -1) {
|
|
47
|
+
notificationStore.notifications[index] = {
|
|
48
|
+
...notificationStore.notifications[index],
|
|
49
|
+
...updates
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Convenience functions for different notification types
|
|
55
|
+
export function showSuccess(title: string, message: string, duration?: number) {
|
|
56
|
+
return addNotification({
|
|
57
|
+
type: 'success',
|
|
58
|
+
title,
|
|
59
|
+
message,
|
|
60
|
+
duration
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function showError(title: string, message: string, duration?: number) {
|
|
65
|
+
return addNotification({
|
|
66
|
+
type: 'error',
|
|
67
|
+
title,
|
|
68
|
+
message,
|
|
69
|
+
duration: duration || 8000 // Errors should stay longer
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function showWarning(title: string, message: string, duration?: number) {
|
|
74
|
+
return addNotification({
|
|
75
|
+
type: 'warning',
|
|
76
|
+
title,
|
|
77
|
+
message,
|
|
78
|
+
duration: duration || 6000
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function showInfo(title: string, message: string, duration?: number) {
|
|
83
|
+
return addNotification({
|
|
84
|
+
type: 'info',
|
|
85
|
+
title,
|
|
86
|
+
message,
|
|
87
|
+
duration
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Show notification with actions
|
|
92
|
+
export function showNotificationWithActions(
|
|
93
|
+
type: ToastNotification['type'],
|
|
94
|
+
title: string,
|
|
95
|
+
message: string,
|
|
96
|
+
actions: Array<{ label: string; action: () => void }>,
|
|
97
|
+
duration?: number
|
|
98
|
+
) {
|
|
99
|
+
return addNotification({
|
|
100
|
+
type,
|
|
101
|
+
title,
|
|
102
|
+
message,
|
|
103
|
+
actions,
|
|
104
|
+
duration: duration || 10000 // Notifications with actions should stay longer
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Show progress notification
|
|
109
|
+
export function showProgressNotification(title: string, message: string) {
|
|
110
|
+
return addNotification({
|
|
111
|
+
type: 'info',
|
|
112
|
+
title,
|
|
113
|
+
message,
|
|
114
|
+
duration: 0 // Don't auto-dismiss progress notifications
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Auto-dismiss notification after delay
|
|
119
|
+
export function autoRemoveNotification(id: string, delay: number) {
|
|
120
|
+
setTimeout(() => {
|
|
121
|
+
removeNotification(id);
|
|
122
|
+
}, delay);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Initialize notifications
|
|
126
|
+
export function initializeNotifications() {
|
|
127
|
+
// Clear any existing notifications on initialization
|
|
128
|
+
clearNotifications();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Handle global error notifications
|
|
132
|
+
export function showGlobalError(error: Error | string) {
|
|
133
|
+
const message = typeof error === 'string' ? error : error.message;
|
|
134
|
+
return showError('Error', message);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Handle API error notifications
|
|
138
|
+
export function showApiError(error: any) {
|
|
139
|
+
const message =
|
|
140
|
+
error?.response?.data?.message || error?.message || 'An unexpected error occurred';
|
|
141
|
+
return showError('API Error', message);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Handle network error notifications
|
|
145
|
+
export function showNetworkError() {
|
|
146
|
+
return showError('Network Error', 'Please check your internet connection and try again');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Handle validation error notifications
|
|
150
|
+
export function showValidationError(message: string) {
|
|
151
|
+
return showWarning('Validation Error', message);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Handle success operations
|
|
155
|
+
export function showOperationSuccess(operation: string) {
|
|
156
|
+
return showSuccess('Success', `${operation} completed successfully`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Handle file operation notifications
|
|
160
|
+
export function showFileOperationSuccess(operation: string, fileName: string) {
|
|
161
|
+
return showSuccess('File Operation', `${operation} "${fileName}" successfully`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function showFileOperationError(operation: string, fileName: string, error: string) {
|
|
165
|
+
return showError('File Operation Failed', `Failed to ${operation} "${fileName}": ${error}`);
|
|
166
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Modal Store - Svelte 5 Runes
|
|
3
|
+
* Controls the visibility and active section of the settings modal
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { IconName } from '$shared/types/ui/icons';
|
|
7
|
+
|
|
8
|
+
export type SettingsSection =
|
|
9
|
+
| 'model'
|
|
10
|
+
| 'engines'
|
|
11
|
+
| 'appearance'
|
|
12
|
+
| 'user'
|
|
13
|
+
| 'notifications'
|
|
14
|
+
| 'general';
|
|
15
|
+
|
|
16
|
+
interface SettingsModalState {
|
|
17
|
+
isOpen: boolean;
|
|
18
|
+
activeSection: SettingsSection;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Settings sections metadata
|
|
22
|
+
export const settingsSections: Array<{
|
|
23
|
+
id: SettingsSection;
|
|
24
|
+
label: string;
|
|
25
|
+
icon: IconName;
|
|
26
|
+
description: string;
|
|
27
|
+
}> = [
|
|
28
|
+
{
|
|
29
|
+
id: 'model',
|
|
30
|
+
label: 'Model',
|
|
31
|
+
icon: 'lucide:cpu',
|
|
32
|
+
description: 'Configure AI engine and model'
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'engines',
|
|
36
|
+
label: 'AI Engine',
|
|
37
|
+
icon: 'lucide:bot',
|
|
38
|
+
description: 'Installation and accounts'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'appearance',
|
|
42
|
+
label: 'Appearance',
|
|
43
|
+
icon: 'lucide:palette',
|
|
44
|
+
description: 'Theme and layout customization'
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'user',
|
|
48
|
+
label: 'User',
|
|
49
|
+
icon: 'lucide:user',
|
|
50
|
+
description: 'User profile settings'
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'notifications',
|
|
54
|
+
label: 'Notifications',
|
|
55
|
+
icon: 'lucide:bell',
|
|
56
|
+
description: 'Sound and push notifications'
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: 'general',
|
|
60
|
+
label: 'General',
|
|
61
|
+
icon: 'lucide:settings-2',
|
|
62
|
+
description: 'Data management and security'
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// Create the state using Svelte 5 runes
|
|
67
|
+
export const settingsModalState = $state<SettingsModalState>({
|
|
68
|
+
isOpen: false,
|
|
69
|
+
activeSection: 'model'
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Helper functions
|
|
73
|
+
export function openSettingsModal(section: SettingsSection = 'model') {
|
|
74
|
+
settingsModalState.isOpen = true;
|
|
75
|
+
settingsModalState.activeSection = section;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function closeSettingsModal() {
|
|
79
|
+
settingsModalState.isOpen = false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function setActiveSection(section: SettingsSection) {
|
|
83
|
+
settingsModalState.activeSection = section;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function toggleSettingsModal() {
|
|
87
|
+
settingsModalState.isOpen = !settingsModalState.isOpen;
|
|
88
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import type { Theme } from '$shared/types/ui';
|
|
2
|
+
|
|
3
|
+
// Theme store using Svelte 5 runes
|
|
4
|
+
export const themeStore = $state({
|
|
5
|
+
current: {
|
|
6
|
+
name: 'claude-modern',
|
|
7
|
+
primary: '#D97757',
|
|
8
|
+
secondary: '#4F46E5',
|
|
9
|
+
background: '#F9FAFB',
|
|
10
|
+
text: '#111827',
|
|
11
|
+
mode: 'light' as const
|
|
12
|
+
} as Theme,
|
|
13
|
+
isDark: false,
|
|
14
|
+
isSystemDark: false
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Derived values as functions (cannot export derived state from modules)
|
|
18
|
+
export function currentTheme() {
|
|
19
|
+
return themeStore.current;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function isDarkMode() {
|
|
23
|
+
return themeStore.isDark;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Theme presets
|
|
27
|
+
export const themes: Theme[] = [
|
|
28
|
+
{
|
|
29
|
+
name: 'claude-modern',
|
|
30
|
+
primary: '#D97757',
|
|
31
|
+
secondary: '#4F46E5',
|
|
32
|
+
background: '#F9FAFB',
|
|
33
|
+
text: '#111827',
|
|
34
|
+
mode: 'light'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'claude-dark',
|
|
38
|
+
primary: '#D97757',
|
|
39
|
+
secondary: '#4F46E5',
|
|
40
|
+
background: '#111827',
|
|
41
|
+
text: '#F9FAFB',
|
|
42
|
+
mode: 'dark'
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
// Theme functions using Tailwind CSS v4 approach with optimized transitions
|
|
47
|
+
export function setTheme(theme: Theme) {
|
|
48
|
+
themeStore.current = theme;
|
|
49
|
+
themeStore.isDark = theme.mode === 'dark';
|
|
50
|
+
|
|
51
|
+
// Apply theme to document using Tailwind v4 class-based dark mode
|
|
52
|
+
if (typeof window !== 'undefined') {
|
|
53
|
+
const htmlElement = document.documentElement;
|
|
54
|
+
|
|
55
|
+
// Disable transitions during theme switch for performance
|
|
56
|
+
htmlElement.classList.add('no-transitions');
|
|
57
|
+
|
|
58
|
+
// Force a reflow to ensure the no-transitions class is applied
|
|
59
|
+
htmlElement.offsetHeight;
|
|
60
|
+
|
|
61
|
+
// Tailwind v4 class-based approach: only add 'dark' class when in dark mode
|
|
62
|
+
// Light mode is the default state (no class needed)
|
|
63
|
+
if (theme.mode === 'dark') {
|
|
64
|
+
htmlElement.classList.add('dark');
|
|
65
|
+
} else {
|
|
66
|
+
htmlElement.classList.remove('dark');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Set CSS custom properties for dynamic accent colors
|
|
70
|
+
htmlElement.style.setProperty('--color-primary', theme.primary);
|
|
71
|
+
htmlElement.style.setProperty('--color-secondary', theme.secondary);
|
|
72
|
+
|
|
73
|
+
// Set color scheme for browser integration (important for form controls, scrollbars, etc.)
|
|
74
|
+
htmlElement.style.colorScheme = theme.mode === 'dark' ? 'dark' : 'light';
|
|
75
|
+
|
|
76
|
+
// Update meta theme-color for mobile browsers
|
|
77
|
+
updateThemeColor(theme.mode);
|
|
78
|
+
|
|
79
|
+
// Re-enable transitions after a short delay to allow theme to settle
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
htmlElement.classList.remove('no-transitions');
|
|
82
|
+
}, 50);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Save to localStorage
|
|
86
|
+
localStorage.setItem('claude-theme', JSON.stringify(theme));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Helper function to update theme color meta tag
|
|
90
|
+
function updateThemeColor(mode: 'light' | 'dark') {
|
|
91
|
+
let metaThemeColor = document.querySelector('meta[name="theme-color"]');
|
|
92
|
+
if (!metaThemeColor) {
|
|
93
|
+
metaThemeColor = document.createElement('meta');
|
|
94
|
+
metaThemeColor.setAttribute('name', 'theme-color');
|
|
95
|
+
document.head.appendChild(metaThemeColor);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Set appropriate theme color
|
|
99
|
+
const themeColor = mode === 'dark' ? '#0a0a0a' : '#ffffff';
|
|
100
|
+
metaThemeColor.setAttribute('content', themeColor);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function toggleDarkMode() {
|
|
104
|
+
// Toggle to opposite mode
|
|
105
|
+
const newMode: 'light' | 'dark' = themeStore.isDark ? 'light' : 'dark';
|
|
106
|
+
|
|
107
|
+
// Use predefined themes for consistency
|
|
108
|
+
const newTheme = newMode === 'dark' ? themes[1] : themes[0]; // claude-dark or claude-modern
|
|
109
|
+
|
|
110
|
+
setTheme(newTheme);
|
|
111
|
+
|
|
112
|
+
// Mark as manual theme choice
|
|
113
|
+
localStorage.setItem('claude-theme-manual', 'true');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function initializeTheme() {
|
|
117
|
+
if (typeof window === 'undefined') return;
|
|
118
|
+
|
|
119
|
+
// Check system preference
|
|
120
|
+
const isSystemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
121
|
+
themeStore.isSystemDark = isSystemDark;
|
|
122
|
+
|
|
123
|
+
// Check for saved theme preference
|
|
124
|
+
const savedTheme = localStorage.getItem('claude-theme');
|
|
125
|
+
const isManualTheme = localStorage.getItem('claude-theme-manual') === 'true';
|
|
126
|
+
|
|
127
|
+
let initialTheme: Theme;
|
|
128
|
+
|
|
129
|
+
if (savedTheme && isManualTheme) {
|
|
130
|
+
// Use saved manual theme preference
|
|
131
|
+
try {
|
|
132
|
+
initialTheme = JSON.parse(savedTheme);
|
|
133
|
+
} catch {
|
|
134
|
+
// Fallback to system preference if parsing fails
|
|
135
|
+
initialTheme = isSystemDark ? themes[1] : themes[0];
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
// Follow system preference
|
|
139
|
+
initialTheme = isSystemDark ? themes[1] : themes[0];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Sync store state with what was already applied by inline script
|
|
143
|
+
themeStore.current = initialTheme;
|
|
144
|
+
themeStore.isDark = initialTheme.mode === 'dark';
|
|
145
|
+
|
|
146
|
+
// Only apply theme if it differs from current DOM state to avoid redundant operations
|
|
147
|
+
const htmlElement = document.documentElement;
|
|
148
|
+
const isDarkCurrentlyApplied = htmlElement.classList.contains('dark');
|
|
149
|
+
|
|
150
|
+
if ((initialTheme.mode === 'dark') !== isDarkCurrentlyApplied) {
|
|
151
|
+
setTheme(initialTheme);
|
|
152
|
+
} else {
|
|
153
|
+
// Just set CSS custom properties since theme class is already correct
|
|
154
|
+
htmlElement.style.setProperty('--color-primary', initialTheme.primary);
|
|
155
|
+
htmlElement.style.setProperty('--color-secondary', initialTheme.secondary);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Listen for system theme changes
|
|
159
|
+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
|
160
|
+
themeStore.isSystemDark = e.matches;
|
|
161
|
+
|
|
162
|
+
// Only follow system if no manual theme was set
|
|
163
|
+
if (!localStorage.getItem('claude-theme-manual')) {
|
|
164
|
+
const newTheme = e.matches ? themes[1] : themes[0];
|
|
165
|
+
setTheme(newTheme);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function setManualTheme(theme: Theme) {
|
|
171
|
+
setTheme(theme);
|
|
172
|
+
localStorage.setItem('claude-theme-manual', 'true');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function useSystemTheme() {
|
|
176
|
+
localStorage.removeItem('claude-theme-manual');
|
|
177
|
+
const defaultTheme = themeStore.isSystemDark ? themes[1] : themes[0];
|
|
178
|
+
setTheme(defaultTheme);
|
|
179
|
+
}
|