@myrialabs/clopen 0.0.4 โ 0.0.6
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 +5 -5
- package/.github/workflows/{release.yml โ ci.yml} +86 -60
- package/CONTRIBUTING.md +499 -499
- package/LICENSE +21 -21
- package/README.md +209 -209
- package/backend/index.ts +168 -156
- package/backend/lib/chat/helpers.ts +42 -42
- package/backend/lib/chat/index.ts +1 -1
- package/backend/lib/chat/stream-manager.ts +1126 -1126
- package/backend/lib/database/README.md +76 -76
- package/backend/lib/database/index.ts +118 -118
- package/backend/lib/database/migrations/001_create_projects_table.ts +30 -30
- package/backend/lib/database/migrations/002_create_chat_sessions_table.ts +32 -32
- package/backend/lib/database/migrations/003_create_messages_table.ts +31 -31
- package/backend/lib/database/migrations/004_create_prompt_templates_table.ts +34 -34
- package/backend/lib/database/migrations/005_create_settings_table.ts +23 -23
- package/backend/lib/database/migrations/006_add_user_to_messages.ts +57 -57
- package/backend/lib/database/migrations/007_create_stream_states_table.ts +40 -40
- package/backend/lib/database/migrations/008_create_message_snapshots_table.ts +61 -61
- package/backend/lib/database/migrations/009_add_delta_snapshot_fields.ts +41 -41
- package/backend/lib/database/migrations/010_add_soft_delete_and_branch_support.ts +70 -70
- package/backend/lib/database/migrations/011_git_like_commit_graph.ts +156 -156
- package/backend/lib/database/migrations/012_add_file_change_statistics.ts +41 -41
- package/backend/lib/database/migrations/013_checkpoint_tree_state.ts +118 -118
- package/backend/lib/database/migrations/014_add_engine_to_sessions.ts +18 -18
- package/backend/lib/database/migrations/015_add_model_to_sessions.ts +18 -18
- package/backend/lib/database/migrations/016_create_user_projects_table.ts +34 -34
- package/backend/lib/database/migrations/017_add_current_session_to_user_projects.ts +32 -32
- package/backend/lib/database/migrations/018_create_claude_accounts_table.ts +24 -24
- package/backend/lib/database/migrations/019_add_claude_account_to_sessions.ts +18 -18
- package/backend/lib/database/migrations/020_add_snapshot_tree_hash.ts +32 -32
- package/backend/lib/database/migrations/021_drop_prompt_templates_table.ts +33 -33
- package/backend/lib/database/migrations/index.ts +153 -153
- package/backend/lib/database/queries/checkpoint-queries.ts +87 -87
- package/backend/lib/database/queries/engine-queries.ts +75 -75
- package/backend/lib/database/queries/index.ts +8 -8
- package/backend/lib/database/queries/message-queries.ts +471 -471
- package/backend/lib/database/queries/project-queries.ts +117 -117
- package/backend/lib/database/queries/session-queries.ts +270 -270
- package/backend/lib/database/queries/settings-queries.ts +33 -33
- package/backend/lib/database/queries/snapshot-queries.ts +325 -325
- package/backend/lib/database/queries/utils-queries.ts +58 -58
- package/backend/lib/database/seeders/index.ts +12 -12
- package/backend/lib/database/seeders/settings_seeder.ts +83 -83
- package/backend/lib/database/utils/connection.ts +173 -173
- package/backend/lib/database/utils/index.ts +3 -3
- package/backend/lib/database/utils/migration-runner.ts +117 -117
- package/backend/lib/database/utils/seeder-runner.ts +120 -120
- package/backend/lib/engine/adapters/claude/environment.ts +160 -164
- package/backend/lib/engine/adapters/claude/error-handler.ts +60 -60
- package/backend/lib/engine/adapters/claude/index.ts +1 -1
- package/backend/lib/engine/adapters/claude/path-utils.ts +38 -38
- package/backend/lib/engine/adapters/claude/stream.ts +177 -177
- package/backend/lib/engine/adapters/opencode/index.ts +2 -2
- package/backend/lib/engine/adapters/opencode/message-converter.ts +862 -862
- package/backend/lib/engine/adapters/opencode/server.ts +104 -104
- package/backend/lib/engine/adapters/opencode/stream.ts +755 -755
- package/backend/lib/engine/index.ts +196 -196
- package/backend/lib/engine/types.ts +58 -58
- package/backend/lib/files/file-operations.ts +478 -478
- package/backend/lib/files/file-reading.ts +308 -308
- package/backend/lib/files/file-watcher.ts +383 -383
- package/backend/lib/files/path-browsing.ts +382 -382
- package/backend/lib/git/git-executor.ts +89 -88
- package/backend/lib/git/git-parser.ts +411 -411
- package/backend/lib/git/git-service.ts +505 -505
- package/backend/lib/mcp/README.md +1144 -1144
- package/backend/lib/mcp/config.ts +317 -316
- package/backend/lib/mcp/index.ts +35 -35
- package/backend/lib/mcp/project-context.ts +236 -236
- package/backend/lib/mcp/servers/browser-automation/actions.ts +156 -156
- package/backend/lib/mcp/servers/browser-automation/browser.ts +419 -419
- package/backend/lib/mcp/servers/browser-automation/index.ts +791 -791
- package/backend/lib/mcp/servers/browser-automation/inspection.ts +501 -501
- package/backend/lib/mcp/servers/helper.ts +143 -143
- package/backend/lib/mcp/servers/index.ts +44 -44
- package/backend/lib/mcp/servers/weather/get-temperature.ts +56 -56
- package/backend/lib/mcp/servers/weather/index.ts +31 -31
- package/backend/lib/mcp/stdio-server.ts +103 -103
- package/backend/lib/mcp/types.ts +65 -65
- package/backend/lib/preview/browser/browser-audio-capture.ts +86 -86
- package/backend/lib/preview/browser/browser-console-manager.ts +262 -262
- package/backend/lib/preview/browser/browser-dialog-handler.ts +222 -222
- package/backend/lib/preview/browser/browser-interaction-handler.ts +421 -421
- package/backend/lib/preview/browser/browser-mcp-control.ts +415 -415
- package/backend/lib/preview/browser/browser-native-ui-handler.ts +512 -512
- package/backend/lib/preview/browser/browser-navigation-tracker.ts +103 -103
- package/backend/lib/preview/browser/browser-pool.ts +357 -357
- package/backend/lib/preview/browser/browser-preview-service.ts +882 -882
- package/backend/lib/preview/browser/browser-tab-manager.ts +935 -935
- package/backend/lib/preview/browser/browser-video-capture.ts +695 -695
- package/backend/lib/preview/browser/scripts/audio-stream.ts +292 -292
- package/backend/lib/preview/browser/scripts/cursor-tracking.ts +85 -85
- package/backend/lib/preview/browser/scripts/video-stream.ts +438 -438
- package/backend/lib/preview/browser/types.ts +359 -359
- package/backend/lib/preview/index.ts +23 -23
- package/backend/lib/project/index.ts +1 -1
- package/backend/lib/project/status-manager.ts +181 -181
- package/backend/lib/shared/env.ts +117 -0
- package/backend/lib/shared/index.ts +5 -2
- package/backend/lib/shared/port-utils.ts +25 -25
- package/backend/lib/shared/process-manager.ts +280 -280
- package/backend/lib/snapshot/blob-store.ts +227 -227
- package/backend/lib/snapshot/gitignore.ts +307 -307
- package/backend/lib/snapshot/helpers.ts +397 -397
- package/backend/lib/snapshot/snapshot-service.ts +483 -483
- package/backend/lib/terminal/helpers.ts +14 -14
- package/backend/lib/terminal/index.ts +7 -7
- package/backend/lib/terminal/pty-manager.ts +3 -3
- package/backend/lib/terminal/pty-session-manager.ts +370 -387
- package/backend/lib/terminal/shell-utils.ts +315 -312
- package/backend/lib/terminal/stream-manager.ts +292 -292
- package/backend/lib/tunnel/global-tunnel-manager.ts +266 -243
- package/backend/lib/tunnel/project-tunnel-manager.ts +311 -311
- package/backend/lib/user/helpers.ts +87 -87
- package/backend/lib/utils/ws.ts +944 -944
- package/backend/lib/vite-dev.ts +295 -295
- package/backend/middleware/cors.ts +16 -15
- package/backend/middleware/error-handler.ts +50 -49
- package/backend/middleware/logger.ts +9 -9
- package/backend/types/api.ts +24 -24
- package/backend/ws/README.md +1505 -1505
- package/backend/ws/chat/background.ts +198 -198
- package/backend/ws/chat/index.ts +21 -21
- package/backend/ws/chat/stream.ts +707 -707
- package/backend/ws/engine/claude/accounts.ts +399 -401
- package/backend/ws/engine/claude/index.ts +13 -13
- package/backend/ws/engine/claude/status.ts +43 -43
- package/backend/ws/engine/index.ts +14 -14
- package/backend/ws/engine/opencode/index.ts +11 -11
- package/backend/ws/engine/opencode/status.ts +30 -30
- package/backend/ws/engine/utils.ts +36 -36
- package/backend/ws/files/index.ts +30 -30
- package/backend/ws/files/read.ts +189 -189
- package/backend/ws/files/search.ts +453 -453
- package/backend/ws/files/watch.ts +124 -124
- package/backend/ws/files/write.ts +143 -143
- package/backend/ws/git/branch.ts +106 -106
- package/backend/ws/git/commit.ts +39 -39
- package/backend/ws/git/conflict.ts +68 -68
- package/backend/ws/git/diff.ts +69 -69
- package/backend/ws/git/index.ts +24 -24
- package/backend/ws/git/log.ts +41 -41
- package/backend/ws/git/remote.ts +214 -214
- package/backend/ws/git/staging.ts +84 -84
- package/backend/ws/git/status.ts +90 -90
- package/backend/ws/index.ts +69 -69
- package/backend/ws/mcp/index.ts +61 -61
- package/backend/ws/messages/crud.ts +74 -74
- package/backend/ws/messages/index.ts +14 -14
- package/backend/ws/preview/browser/cleanup.ts +129 -129
- package/backend/ws/preview/browser/console.ts +114 -114
- package/backend/ws/preview/browser/interact.ts +513 -513
- package/backend/ws/preview/browser/mcp.ts +129 -129
- package/backend/ws/preview/browser/native-ui.ts +235 -235
- package/backend/ws/preview/browser/stats.ts +55 -55
- package/backend/ws/preview/browser/tab-info.ts +126 -126
- package/backend/ws/preview/browser/tab.ts +166 -166
- package/backend/ws/preview/browser/webcodecs.ts +293 -293
- package/backend/ws/preview/index.ts +146 -146
- package/backend/ws/projects/crud.ts +113 -113
- package/backend/ws/projects/index.ts +25 -25
- package/backend/ws/projects/presence.ts +46 -46
- package/backend/ws/projects/status.ts +116 -116
- package/backend/ws/sessions/crud.ts +327 -327
- package/backend/ws/sessions/index.ts +33 -33
- package/backend/ws/settings/crud.ts +112 -112
- package/backend/ws/settings/index.ts +14 -14
- package/backend/ws/snapshot/index.ts +17 -17
- package/backend/ws/snapshot/restore.ts +173 -173
- package/backend/ws/snapshot/timeline.ts +141 -141
- package/backend/ws/system/index.ts +14 -14
- package/backend/ws/system/operations.ts +49 -49
- package/backend/ws/terminal/index.ts +40 -40
- package/backend/ws/terminal/persistence.ts +153 -153
- package/backend/ws/terminal/session.ts +382 -382
- package/backend/ws/terminal/stream.ts +79 -79
- package/backend/ws/tunnel/index.ts +14 -14
- package/backend/ws/tunnel/operations.ts +91 -91
- package/backend/ws/types.ts +20 -20
- package/backend/ws/user/crud.ts +156 -156
- package/backend/ws/user/index.ts +14 -14
- package/bin/clopen.ts +307 -307
- package/bun.lock +1353 -1352
- package/frontend/App.svelte +38 -34
- package/frontend/app.css +313 -313
- package/frontend/lib/app-environment.ts +10 -10
- package/frontend/lib/components/chat/ChatInterface.svelte +406 -406
- package/frontend/lib/components/chat/formatters/ErrorMessage.svelte +56 -56
- package/frontend/lib/components/chat/formatters/MessageFormatter.svelte +223 -223
- package/frontend/lib/components/chat/formatters/TextMessage.svelte +394 -394
- package/frontend/lib/components/chat/formatters/Tools.svelte +69 -69
- package/frontend/lib/components/chat/formatters/index.ts +2 -2
- package/frontend/lib/components/chat/input/ChatInput.svelte +421 -421
- package/frontend/lib/components/chat/input/components/ChatInputActions.svelte +78 -78
- package/frontend/lib/components/chat/input/components/DragDropOverlay.svelte +30 -30
- package/frontend/lib/components/chat/input/components/EditModeIndicator.svelte +33 -33
- package/frontend/lib/components/chat/input/components/EngineModelPicker.svelte +619 -619
- package/frontend/lib/components/chat/input/components/FileAttachmentPreview.svelte +48 -48
- package/frontend/lib/components/chat/input/components/LoadingIndicator.svelte +31 -31
- package/frontend/lib/components/chat/input/composables/use-animations.svelte.ts +201 -201
- package/frontend/lib/components/chat/input/composables/use-chat-actions.svelte.ts +148 -148
- package/frontend/lib/components/chat/input/composables/use-file-handling.svelte.ts +216 -216
- package/frontend/lib/components/chat/input/composables/use-input-state.svelte.ts +357 -357
- package/frontend/lib/components/chat/input/composables/use-textarea-resize.svelte.ts +57 -57
- package/frontend/lib/components/chat/message/ChatMessage.svelte +478 -478
- package/frontend/lib/components/chat/message/ChatMessages.svelte +541 -541
- package/frontend/lib/components/chat/message/DateSeparator.svelte +86 -86
- package/frontend/lib/components/chat/message/MessageBubble.svelte +86 -86
- package/frontend/lib/components/chat/message/MessageHeader.svelte +157 -157
- package/frontend/lib/components/chat/modal/DebugModal.svelte +59 -59
- package/frontend/lib/components/chat/modal/TokenUsageModal.svelte +124 -124
- package/frontend/lib/components/chat/shared/index.ts +1 -1
- package/frontend/lib/components/chat/shared/utils.ts +115 -115
- package/frontend/lib/components/chat/tools/BashOutputTool.svelte +35 -35
- package/frontend/lib/components/chat/tools/BashTool.svelte +45 -45
- package/frontend/lib/components/chat/tools/CustomMcpTool.svelte +139 -139
- package/frontend/lib/components/chat/tools/EditTool.svelte +47 -47
- package/frontend/lib/components/chat/tools/ExitPlanModeTool.svelte +31 -31
- package/frontend/lib/components/chat/tools/GlobTool.svelte +50 -50
- package/frontend/lib/components/chat/tools/GrepTool.svelte +89 -89
- package/frontend/lib/components/chat/tools/KillShellTool.svelte +25 -25
- package/frontend/lib/components/chat/tools/ListMcpResourcesTool.svelte +30 -30
- package/frontend/lib/components/chat/tools/NotebookEditTool.svelte +37 -37
- package/frontend/lib/components/chat/tools/ReadMcpResourceTool.svelte +33 -33
- package/frontend/lib/components/chat/tools/ReadTool.svelte +40 -40
- package/frontend/lib/components/chat/tools/TaskTool.svelte +63 -63
- package/frontend/lib/components/chat/tools/TodoWriteTool.svelte +74 -74
- package/frontend/lib/components/chat/tools/WebFetchTool.svelte +34 -34
- package/frontend/lib/components/chat/tools/WebSearchTool.svelte +83 -83
- package/frontend/lib/components/chat/tools/WriteTool.svelte +32 -32
- package/frontend/lib/components/chat/tools/components/CodeBlock.svelte +78 -78
- package/frontend/lib/components/chat/tools/components/DiffBlock.svelte +407 -407
- package/frontend/lib/components/chat/tools/components/FileHeader.svelte +45 -45
- package/frontend/lib/components/chat/tools/components/InfoLine.svelte +18 -18
- package/frontend/lib/components/chat/tools/components/StatsBadges.svelte +26 -26
- package/frontend/lib/components/chat/tools/components/TerminalCommand.svelte +53 -53
- package/frontend/lib/components/chat/tools/components/index.ts +7 -7
- package/frontend/lib/components/chat/tools/index.ts +25 -25
- package/frontend/lib/components/chat/widgets/FloatingTodoList.svelte +248 -248
- package/frontend/lib/components/chat/widgets/TokenUsage.svelte +78 -78
- package/frontend/lib/components/checkpoint/TimelineModal.svelte +391 -391
- package/frontend/lib/components/checkpoint/timeline/TimelineEdge.svelte +26 -26
- package/frontend/lib/components/checkpoint/timeline/TimelineGraph.svelte +86 -86
- package/frontend/lib/components/checkpoint/timeline/TimelineNode.svelte +108 -108
- package/frontend/lib/components/checkpoint/timeline/TimelineVersionGroup.svelte +59 -59
- package/frontend/lib/components/checkpoint/timeline/animation.ts +168 -168
- package/frontend/lib/components/checkpoint/timeline/config.ts +44 -44
- package/frontend/lib/components/checkpoint/timeline/graph-builder.ts +304 -304
- package/frontend/lib/components/checkpoint/timeline/types.ts +65 -65
- package/frontend/lib/components/checkpoint/timeline/utils.ts +53 -53
- package/frontend/lib/components/common/Alert.svelte +138 -138
- package/frontend/lib/components/common/AvatarBubble.svelte +55 -55
- package/frontend/lib/components/common/Button.svelte +71 -71
- package/frontend/lib/components/common/Card.svelte +102 -102
- package/frontend/lib/components/common/Checkbox.svelte +48 -48
- package/frontend/lib/components/common/Dialog.svelte +248 -248
- package/frontend/lib/components/common/FolderBrowser.svelte +842 -842
- package/frontend/lib/components/common/Icon.svelte +57 -57
- package/frontend/lib/components/common/Input.svelte +72 -72
- package/frontend/lib/components/common/Lightbox.svelte +232 -232
- package/frontend/lib/components/common/LoadingScreen.svelte +52 -52
- package/frontend/lib/components/common/LoadingSpinner.svelte +48 -48
- package/frontend/lib/components/common/Modal.svelte +177 -177
- package/frontend/lib/components/common/ModalProvider.svelte +27 -27
- package/frontend/lib/components/common/ModelSelector.svelte +110 -110
- package/frontend/lib/components/common/MonacoEditor.svelte +568 -568
- package/frontend/lib/components/common/NotificationToast.svelte +113 -113
- package/frontend/lib/components/common/PageTemplate.svelte +75 -75
- package/frontend/lib/components/common/ProjectUserAvatars.svelte +79 -79
- package/frontend/lib/components/common/Select.svelte +97 -97
- package/frontend/lib/components/common/Textarea.svelte +79 -79
- package/frontend/lib/components/common/ThemeToggle.svelte +44 -44
- package/frontend/lib/components/common/lucide-icons.ts +1642 -1642
- package/frontend/lib/components/common/material-icons.ts +1082 -1082
- package/frontend/lib/components/common/xterm/XTerm.svelte +809 -795
- package/frontend/lib/components/common/xterm/index.ts +15 -15
- package/frontend/lib/components/common/xterm/terminal-config.ts +67 -67
- package/frontend/lib/components/common/xterm/types.ts +30 -30
- package/frontend/lib/components/common/xterm/xterm-service.ts +379 -353
- package/frontend/lib/components/files/FileNode.svelte +383 -383
- package/frontend/lib/components/files/FileTree.svelte +681 -681
- package/frontend/lib/components/files/FileViewer.svelte +728 -728
- package/frontend/lib/components/files/SearchResults.svelte +303 -303
- package/frontend/lib/components/git/BranchManager.svelte +458 -458
- package/frontend/lib/components/git/ChangesSection.svelte +107 -107
- package/frontend/lib/components/git/CommitForm.svelte +76 -76
- package/frontend/lib/components/git/ConflictResolver.svelte +158 -158
- package/frontend/lib/components/git/DiffViewer.svelte +364 -364
- package/frontend/lib/components/git/FileChangeItem.svelte +97 -97
- package/frontend/lib/components/git/GitButton.svelte +33 -33
- package/frontend/lib/components/git/GitLog.svelte +361 -361
- package/frontend/lib/components/git/GitModal.svelte +80 -80
- package/frontend/lib/components/history/HistoryModal.svelte +563 -563
- package/frontend/lib/components/history/HistoryView.svelte +614 -614
- package/frontend/lib/components/index.ts +34 -34
- package/frontend/lib/components/preview/browser/BrowserPreview.svelte +549 -549
- package/frontend/lib/components/preview/browser/components/Canvas.svelte +1058 -1058
- package/frontend/lib/components/preview/browser/components/ConsolePanel.svelte +756 -756
- package/frontend/lib/components/preview/browser/components/Container.svelte +450 -450
- package/frontend/lib/components/preview/browser/components/ContextMenu.svelte +236 -236
- package/frontend/lib/components/preview/browser/components/SelectDropdown.svelte +224 -224
- package/frontend/lib/components/preview/browser/components/Toolbar.svelte +338 -338
- package/frontend/lib/components/preview/browser/components/VirtualCursor.svelte +35 -35
- package/frontend/lib/components/preview/browser/core/cleanup.svelte.ts +155 -155
- package/frontend/lib/components/preview/browser/core/coordinator.svelte.ts +837 -837
- package/frontend/lib/components/preview/browser/core/interactions.svelte.ts +113 -113
- package/frontend/lib/components/preview/browser/core/mcp-handlers.svelte.ts +296 -296
- package/frontend/lib/components/preview/browser/core/native-ui-handlers.svelte.ts +391 -391
- package/frontend/lib/components/preview/browser/core/stream-handler.svelte.ts +231 -231
- package/frontend/lib/components/preview/browser/core/tab-manager.svelte.ts +210 -210
- package/frontend/lib/components/preview/browser/core/tab-operations.svelte.ts +239 -239
- package/frontend/lib/components/preview/index.ts +1 -1
- package/frontend/lib/components/settings/SettingsModal.svelte +235 -235
- package/frontend/lib/components/settings/SettingsView.svelte +36 -36
- package/frontend/lib/components/settings/appearance/AppearanceSettings.svelte +51 -51
- package/frontend/lib/components/settings/appearance/LayoutPresetSettings.svelte +160 -160
- package/frontend/lib/components/settings/appearance/LayoutPreview.svelte +76 -76
- package/frontend/lib/components/settings/engines/AIEnginesSettings.svelte +917 -917
- package/frontend/lib/components/settings/general/AdvancedSettings.svelte +187 -187
- package/frontend/lib/components/settings/general/DataManagementSettings.svelte +203 -203
- package/frontend/lib/components/settings/general/GeneralSettings.svelte +10 -10
- package/frontend/lib/components/settings/model/ModelSettings.svelte +357 -357
- package/frontend/lib/components/settings/notifications/NotificationSettings.svelte +205 -205
- package/frontend/lib/components/settings/user/UserSettings.svelte +197 -197
- package/frontend/lib/components/terminal/Terminal.svelte +367 -367
- package/frontend/lib/components/terminal/TerminalTabs.svelte +87 -87
- package/frontend/lib/components/terminal/TerminalView.svelte +54 -54
- package/frontend/lib/components/tunnel/TunnelActive.svelte +157 -142
- package/frontend/lib/components/tunnel/TunnelButton.svelte +60 -54
- package/frontend/lib/components/tunnel/TunnelInactive.svelte +285 -284
- package/frontend/lib/components/tunnel/TunnelModal.svelte +48 -47
- package/frontend/lib/components/tunnel/TunnelQRCode.svelte +49 -49
- package/frontend/lib/components/workspace/DesktopNavigator.svelte +382 -382
- package/frontend/lib/components/workspace/MobileNavigator.svelte +394 -403
- package/frontend/lib/components/workspace/PanelContainer.svelte +100 -100
- package/frontend/lib/components/workspace/PanelHeader.svelte +505 -505
- package/frontend/lib/components/workspace/ViewMenu.svelte +162 -162
- package/frontend/lib/components/workspace/WorkspaceLayout.svelte +169 -169
- package/frontend/lib/components/workspace/layout/DesktopLayout.svelte +15 -15
- package/frontend/lib/components/workspace/layout/MobileLayout.svelte +17 -17
- package/frontend/lib/components/workspace/layout/split-pane/Container.svelte +42 -42
- package/frontend/lib/components/workspace/layout/split-pane/Handle.svelte +84 -84
- package/frontend/lib/components/workspace/layout/split-pane/Layout.svelte +37 -37
- package/frontend/lib/components/workspace/panels/ChatPanel.svelte +274 -274
- package/frontend/lib/components/workspace/panels/FilesPanel.svelte +1261 -1261
- package/frontend/lib/components/workspace/panels/GitPanel.svelte +1560 -1560
- package/frontend/lib/components/workspace/panels/PreviewPanel.svelte +150 -150
- package/frontend/lib/components/workspace/panels/TerminalPanel.svelte +73 -73
- package/frontend/lib/constants/preview.ts +44 -44
- package/frontend/lib/services/chat/chat.service.ts +704 -704
- package/frontend/lib/services/chat/index.ts +6 -6
- package/frontend/lib/services/notification/global-stream-monitor.ts +86 -86
- package/frontend/lib/services/notification/index.ts +7 -7
- package/frontend/lib/services/notification/push.service.ts +143 -143
- package/frontend/lib/services/notification/sound.service.ts +126 -126
- package/frontend/lib/services/preview/browser/browser-console.service.ts +61 -61
- package/frontend/lib/services/preview/browser/browser-webcodecs.service.ts +1499 -1499
- package/frontend/lib/services/preview/browser/mcp-integration.svelte.ts +67 -67
- package/frontend/lib/services/preview/index.ts +22 -22
- package/frontend/lib/services/project/index.ts +7 -7
- package/frontend/lib/services/project/status.service.ts +159 -159
- package/frontend/lib/services/snapshot/snapshot.service.ts +47 -47
- package/frontend/lib/services/terminal/background/index.ts +129 -129
- package/frontend/lib/services/terminal/background/session-restore.ts +273 -273
- package/frontend/lib/services/terminal/background/stream-manager.ts +285 -285
- package/frontend/lib/services/terminal/index.ts +13 -13
- package/frontend/lib/services/terminal/persistence.service.ts +260 -260
- package/frontend/lib/services/terminal/project.service.ts +952 -952
- package/frontend/lib/services/terminal/session.service.ts +363 -363
- package/frontend/lib/services/terminal/terminal.service.ts +369 -369
- package/frontend/lib/stores/core/app.svelte.ts +117 -117
- package/frontend/lib/stores/core/files.svelte.ts +72 -72
- package/frontend/lib/stores/core/presence.svelte.ts +48 -48
- package/frontend/lib/stores/core/projects.svelte.ts +317 -317
- package/frontend/lib/stores/core/sessions.svelte.ts +383 -383
- package/frontend/lib/stores/features/claude-accounts.svelte.ts +58 -58
- package/frontend/lib/stores/features/models.svelte.ts +89 -89
- package/frontend/lib/stores/features/settings.svelte.ts +87 -87
- package/frontend/lib/stores/features/terminal.svelte.ts +700 -700
- package/frontend/lib/stores/features/tunnel.svelte.ts +163 -161
- package/frontend/lib/stores/features/user.svelte.ts +95 -95
- package/frontend/lib/stores/ui/chat-input.svelte.ts +56 -56
- package/frontend/lib/stores/ui/chat-model.svelte.ts +61 -61
- package/frontend/lib/stores/ui/dialog.svelte.ts +58 -58
- package/frontend/lib/stores/ui/edit-mode.svelte.ts +214 -214
- package/frontend/lib/stores/ui/notification.svelte.ts +166 -166
- package/frontend/lib/stores/ui/settings-modal.svelte.ts +88 -88
- package/frontend/lib/stores/ui/theme.svelte.ts +179 -179
- package/frontend/lib/stores/ui/workspace.svelte.ts +754 -754
- package/frontend/lib/types/native-ui.ts +73 -73
- package/frontend/lib/utils/chat/date-separator.ts +38 -38
- package/frontend/lib/utils/chat/message-grouper.ts +218 -218
- package/frontend/lib/utils/chat/message-processor.ts +134 -134
- package/frontend/lib/utils/chat/tool-handler.ts +160 -160
- package/frontend/lib/utils/chat/virtual-scroll.svelte.ts +142 -142
- package/frontend/lib/utils/click-outside.ts +20 -20
- package/frontend/lib/utils/context-manager.ts +256 -256
- package/frontend/lib/utils/file-icon-mappings.ts +768 -768
- package/frontend/lib/utils/folder-icon-mappings.ts +1029 -1029
- package/frontend/lib/utils/git-status.ts +68 -68
- package/frontend/lib/utils/platform.ts +112 -112
- package/frontend/lib/utils/port-check.ts +64 -64
- package/frontend/lib/utils/terminalFormatter.ts +206 -206
- package/frontend/lib/utils/theme.ts +6 -6
- package/frontend/lib/utils/tree-visualizer.ts +320 -320
- package/frontend/lib/utils/ws.ts +44 -44
- package/frontend/main.ts +13 -13
- package/index.html +70 -70
- package/package.json +111 -111
- package/scripts/generate-icons.ts +86 -86
- package/scripts/pre-publish-check.sh +142 -142
- package/scripts/setup-hooks.sh +134 -134
- package/scripts/validate-branch-name.sh +47 -47
- package/scripts/validate-commit-msg.sh +42 -42
- package/shared/constants/engines.ts +134 -134
- package/shared/types/database/connection.ts +15 -15
- package/shared/types/database/index.ts +5 -5
- package/shared/types/database/schema.ts +140 -140
- package/shared/types/engine/index.ts +45 -45
- package/shared/types/filesystem/index.ts +21 -21
- package/shared/types/git.ts +171 -171
- package/shared/types/messaging/index.ts +238 -238
- package/shared/types/messaging/tool.ts +525 -525
- package/shared/types/network/api.ts +17 -17
- package/shared/types/network/index.ts +4 -4
- package/shared/types/stores/app.ts +22 -22
- package/shared/types/stores/dialog.ts +20 -20
- package/shared/types/stores/index.ts +2 -2
- package/shared/types/stores/settings.ts +15 -15
- package/shared/types/terminal/index.ts +43 -43
- package/shared/types/ui/components.ts +60 -60
- package/shared/types/ui/icons.ts +22 -22
- package/shared/types/ui/index.ts +21 -21
- package/shared/types/ui/notifications.ts +13 -13
- package/shared/types/ui/theme.ts +11 -11
- package/shared/types/websocket/index.ts +43 -43
- package/shared/types/window.d.ts +12 -12
- package/shared/utils/anonymous-user.ts +167 -167
- package/shared/utils/async.ts +10 -10
- package/shared/utils/diff-calculator.ts +184 -184
- package/shared/utils/file-type-detection.ts +165 -165
- package/shared/utils/logger.ts +144 -158
- package/shared/utils/message-formatter.ts +79 -79
- package/shared/utils/path.ts +47 -47
- package/shared/utils/ws-client.ts +768 -768
- package/shared/utils/ws-server.ts +660 -660
- package/static/favicon.svg +7 -7
- package/static/fonts/dm-sans.css +96 -96
- package/svelte.config.js +20 -20
- package/tsconfig.json +41 -41
- package/vite.config.ts +33 -33
- package/.github/workflows/test.yml +0 -40
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
import { getDatabase } from '../index';
|
|
2
|
-
import type { DatabaseMessage } from '$shared/types/database/schema';
|
|
3
|
-
|
|
4
|
-
import { debug } from '$shared/utils/logger';
|
|
5
|
-
export const dbUtils = {
|
|
6
|
-
// Get dashboard statistics
|
|
7
|
-
getStats(): {
|
|
8
|
-
totalProjects: number;
|
|
9
|
-
totalSessions: number;
|
|
10
|
-
totalMessages: number;
|
|
11
|
-
} {
|
|
12
|
-
const db = getDatabase();
|
|
13
|
-
|
|
14
|
-
const totalProjects = (db.prepare('SELECT COUNT(*) as count FROM projects').get() as { count: number }).count;
|
|
15
|
-
const totalSessions = (db.prepare('SELECT COUNT(*) as count FROM chat_sessions').get() as { count: number }).count;
|
|
16
|
-
const totalMessages = (db.prepare('SELECT COUNT(*) as count FROM messages').get() as { count: number }).count;
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
totalProjects,
|
|
20
|
-
totalSessions,
|
|
21
|
-
totalMessages
|
|
22
|
-
};
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
// Search across messages
|
|
26
|
-
searchMessages(query: string, limit: number = 50): (DatabaseMessage & { project_name: string })[] {
|
|
27
|
-
const db = getDatabase();
|
|
28
|
-
return db.prepare(`
|
|
29
|
-
SELECT m.*, p.name as project_name
|
|
30
|
-
FROM messages m
|
|
31
|
-
JOIN chat_sessions cs ON m.session_id = cs.id
|
|
32
|
-
JOIN projects p ON cs.project_id = p.id
|
|
33
|
-
WHERE m.content LIKE ?
|
|
34
|
-
ORDER BY m.timestamp DESC
|
|
35
|
-
LIMIT ?
|
|
36
|
-
`).all(`%${query}%`, limit) as (DatabaseMessage & { project_name: string })[];
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
// Clean up old data
|
|
40
|
-
cleanupOldData(daysOld: number = 30): void {
|
|
41
|
-
const db = getDatabase();
|
|
42
|
-
const cutoffDate = new Date();
|
|
43
|
-
cutoffDate.setDate(cutoffDate.getDate() - daysOld);
|
|
44
|
-
const cutoff = cutoffDate.toISOString();
|
|
45
|
-
|
|
46
|
-
// Delete old ended sessions and their messages
|
|
47
|
-
const oldSessions = db.prepare(`
|
|
48
|
-
SELECT id FROM chat_sessions
|
|
49
|
-
WHERE ended_at IS NOT NULL AND ended_at < ?
|
|
50
|
-
`).all(cutoff) as { id: string }[];
|
|
51
|
-
|
|
52
|
-
for (const session of oldSessions) {
|
|
53
|
-
db.prepare('DELETE FROM messages WHERE session_id = ?').run(session.id);
|
|
54
|
-
db.prepare('DELETE FROM chat_sessions WHERE id = ?').run(session.id);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
debug.log('database', `โ
Cleaned up ${oldSessions.length} old sessions`);
|
|
58
|
-
}
|
|
1
|
+
import { getDatabase } from '../index';
|
|
2
|
+
import type { DatabaseMessage } from '$shared/types/database/schema';
|
|
3
|
+
|
|
4
|
+
import { debug } from '$shared/utils/logger';
|
|
5
|
+
export const dbUtils = {
|
|
6
|
+
// Get dashboard statistics
|
|
7
|
+
getStats(): {
|
|
8
|
+
totalProjects: number;
|
|
9
|
+
totalSessions: number;
|
|
10
|
+
totalMessages: number;
|
|
11
|
+
} {
|
|
12
|
+
const db = getDatabase();
|
|
13
|
+
|
|
14
|
+
const totalProjects = (db.prepare('SELECT COUNT(*) as count FROM projects').get() as { count: number }).count;
|
|
15
|
+
const totalSessions = (db.prepare('SELECT COUNT(*) as count FROM chat_sessions').get() as { count: number }).count;
|
|
16
|
+
const totalMessages = (db.prepare('SELECT COUNT(*) as count FROM messages').get() as { count: number }).count;
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
totalProjects,
|
|
20
|
+
totalSessions,
|
|
21
|
+
totalMessages
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// Search across messages
|
|
26
|
+
searchMessages(query: string, limit: number = 50): (DatabaseMessage & { project_name: string })[] {
|
|
27
|
+
const db = getDatabase();
|
|
28
|
+
return db.prepare(`
|
|
29
|
+
SELECT m.*, p.name as project_name
|
|
30
|
+
FROM messages m
|
|
31
|
+
JOIN chat_sessions cs ON m.session_id = cs.id
|
|
32
|
+
JOIN projects p ON cs.project_id = p.id
|
|
33
|
+
WHERE m.content LIKE ?
|
|
34
|
+
ORDER BY m.timestamp DESC
|
|
35
|
+
LIMIT ?
|
|
36
|
+
`).all(`%${query}%`, limit) as (DatabaseMessage & { project_name: string })[];
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
// Clean up old data
|
|
40
|
+
cleanupOldData(daysOld: number = 30): void {
|
|
41
|
+
const db = getDatabase();
|
|
42
|
+
const cutoffDate = new Date();
|
|
43
|
+
cutoffDate.setDate(cutoffDate.getDate() - daysOld);
|
|
44
|
+
const cutoff = cutoffDate.toISOString();
|
|
45
|
+
|
|
46
|
+
// Delete old ended sessions and their messages
|
|
47
|
+
const oldSessions = db.prepare(`
|
|
48
|
+
SELECT id FROM chat_sessions
|
|
49
|
+
WHERE ended_at IS NOT NULL AND ended_at < ?
|
|
50
|
+
`).all(cutoff) as { id: string }[];
|
|
51
|
+
|
|
52
|
+
for (const session of oldSessions) {
|
|
53
|
+
db.prepare('DELETE FROM messages WHERE session_id = ?').run(session.id);
|
|
54
|
+
db.prepare('DELETE FROM chat_sessions WHERE id = ?').run(session.id);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
debug.log('database', `โ
Cleaned up ${oldSessions.length} old sessions`);
|
|
58
|
+
}
|
|
59
59
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
// Import all seeders
|
|
2
|
-
import * as settingsSeeder from './settings_seeder';
|
|
3
|
-
|
|
4
|
-
// Export all seeders
|
|
5
|
-
export const seeders = [
|
|
6
|
-
{
|
|
7
|
-
name: 'settings',
|
|
8
|
-
description: settingsSeeder.description,
|
|
9
|
-
seed: settingsSeeder.seed
|
|
10
|
-
}
|
|
11
|
-
];
|
|
12
|
-
|
|
1
|
+
// Import all seeders
|
|
2
|
+
import * as settingsSeeder from './settings_seeder';
|
|
3
|
+
|
|
4
|
+
// Export all seeders
|
|
5
|
+
export const seeders = [
|
|
6
|
+
{
|
|
7
|
+
name: 'settings',
|
|
8
|
+
description: settingsSeeder.description,
|
|
9
|
+
seed: settingsSeeder.seed
|
|
10
|
+
}
|
|
11
|
+
];
|
|
12
|
+
|
|
13
13
|
export default seeders;
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
import type { DatabaseConnection } from '$shared/types/database/connection';
|
|
2
|
-
|
|
3
|
-
import { debug } from '$shared/utils/logger';
|
|
4
|
-
export const seed = (db: DatabaseConnection): void => {
|
|
5
|
-
debug.log('seeder', '๐ฑ Seeding default settings...');
|
|
6
|
-
|
|
7
|
-
const now = new Date().toISOString();
|
|
8
|
-
|
|
9
|
-
// Insert default settings
|
|
10
|
-
const insertSetting = db.prepare(`
|
|
11
|
-
INSERT INTO settings (key, value, updated_at)
|
|
12
|
-
VALUES (?, ?, ?)
|
|
13
|
-
`);
|
|
14
|
-
|
|
15
|
-
const defaultSettings = [
|
|
16
|
-
{
|
|
17
|
-
key: 'claude_model',
|
|
18
|
-
value: 'sonnet',
|
|
19
|
-
description: 'Default Claude model for chat'
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
key: 'max_tokens',
|
|
23
|
-
value: '4000',
|
|
24
|
-
description: 'Maximum tokens per response'
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
key: 'temperature',
|
|
28
|
-
value: '0.3',
|
|
29
|
-
description: 'AI response creativity (0.0 - 1.0)'
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
key: 'auto_save_sessions',
|
|
33
|
-
value: 'true',
|
|
34
|
-
description: 'Automatically save chat sessions'
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
key: 'file_watch_enabled',
|
|
38
|
-
value: 'true',
|
|
39
|
-
description: 'Enable file system watching'
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
key: 'theme',
|
|
43
|
-
value: 'system',
|
|
44
|
-
description: 'UI theme preference (light/dark/system)'
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
key: 'session_timeout',
|
|
48
|
-
value: '3600000',
|
|
49
|
-
description: 'Session timeout in milliseconds (1 hour)'
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
key: 'enable_notifications',
|
|
53
|
-
value: 'true',
|
|
54
|
-
description: 'Enable desktop notifications'
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
key: 'auto_cleanup_old_sessions',
|
|
58
|
-
value: 'false',
|
|
59
|
-
description: 'Automatically clean up old chat sessions'
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
key: 'default_project_template',
|
|
63
|
-
value: 'svelte',
|
|
64
|
-
description: 'Default template for new projects'
|
|
65
|
-
}
|
|
66
|
-
];
|
|
67
|
-
|
|
68
|
-
for (const setting of defaultSettings) {
|
|
69
|
-
try {
|
|
70
|
-
insertSetting.run(setting.key, setting.value, now);
|
|
71
|
-
} catch (error) {
|
|
72
|
-
// Skip if setting already exists
|
|
73
|
-
if (error instanceof Error && error.message.includes('UNIQUE constraint failed')) {
|
|
74
|
-
debug.log('seeder', `โน๏ธ Setting ${setting.key} already exists, skipping`);
|
|
75
|
-
} else {
|
|
76
|
-
throw error;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
debug.log('seeder', `โ
Seeded ${defaultSettings.length} default settings`);
|
|
82
|
-
};
|
|
83
|
-
|
|
1
|
+
import type { DatabaseConnection } from '$shared/types/database/connection';
|
|
2
|
+
|
|
3
|
+
import { debug } from '$shared/utils/logger';
|
|
4
|
+
export const seed = (db: DatabaseConnection): void => {
|
|
5
|
+
debug.log('seeder', '๐ฑ Seeding default settings...');
|
|
6
|
+
|
|
7
|
+
const now = new Date().toISOString();
|
|
8
|
+
|
|
9
|
+
// Insert default settings
|
|
10
|
+
const insertSetting = db.prepare(`
|
|
11
|
+
INSERT INTO settings (key, value, updated_at)
|
|
12
|
+
VALUES (?, ?, ?)
|
|
13
|
+
`);
|
|
14
|
+
|
|
15
|
+
const defaultSettings = [
|
|
16
|
+
{
|
|
17
|
+
key: 'claude_model',
|
|
18
|
+
value: 'sonnet',
|
|
19
|
+
description: 'Default Claude model for chat'
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
key: 'max_tokens',
|
|
23
|
+
value: '4000',
|
|
24
|
+
description: 'Maximum tokens per response'
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
key: 'temperature',
|
|
28
|
+
value: '0.3',
|
|
29
|
+
description: 'AI response creativity (0.0 - 1.0)'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
key: 'auto_save_sessions',
|
|
33
|
+
value: 'true',
|
|
34
|
+
description: 'Automatically save chat sessions'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
key: 'file_watch_enabled',
|
|
38
|
+
value: 'true',
|
|
39
|
+
description: 'Enable file system watching'
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
key: 'theme',
|
|
43
|
+
value: 'system',
|
|
44
|
+
description: 'UI theme preference (light/dark/system)'
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
key: 'session_timeout',
|
|
48
|
+
value: '3600000',
|
|
49
|
+
description: 'Session timeout in milliseconds (1 hour)'
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
key: 'enable_notifications',
|
|
53
|
+
value: 'true',
|
|
54
|
+
description: 'Enable desktop notifications'
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
key: 'auto_cleanup_old_sessions',
|
|
58
|
+
value: 'false',
|
|
59
|
+
description: 'Automatically clean up old chat sessions'
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
key: 'default_project_template',
|
|
63
|
+
value: 'svelte',
|
|
64
|
+
description: 'Default template for new projects'
|
|
65
|
+
}
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
for (const setting of defaultSettings) {
|
|
69
|
+
try {
|
|
70
|
+
insertSetting.run(setting.key, setting.value, now);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
// Skip if setting already exists
|
|
73
|
+
if (error instanceof Error && error.message.includes('UNIQUE constraint failed')) {
|
|
74
|
+
debug.log('seeder', `โน๏ธ Setting ${setting.key} already exists, skipping`);
|
|
75
|
+
} else {
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
debug.log('seeder', `โ
Seeded ${defaultSettings.length} default settings`);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
84
|
export const description = 'Seed default application settings and configuration';
|
|
@@ -1,174 +1,174 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import { homedir } from 'os';
|
|
3
|
-
import { Database } from 'bun:sqlite';
|
|
4
|
-
import type { DatabaseConnection } from '$shared/types/database/connection';
|
|
5
|
-
|
|
6
|
-
import { debug } from '$shared/utils/logger';
|
|
7
|
-
export class DatabaseManager {
|
|
8
|
-
private static instance: DatabaseManager | null = null;
|
|
9
|
-
private db: DatabaseConnection | null = null;
|
|
10
|
-
private readonly dbPath: string;
|
|
11
|
-
|
|
12
|
-
private constructor() {
|
|
13
|
-
const clopenDir = join(homedir(), '.clopen');
|
|
14
|
-
this.dbPath = join(clopenDir, 'app.db');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static getInstance(): DatabaseManager {
|
|
18
|
-
if (!DatabaseManager.instance) {
|
|
19
|
-
DatabaseManager.instance = new DatabaseManager();
|
|
20
|
-
}
|
|
21
|
-
return DatabaseManager.instance;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async connect(): Promise<DatabaseConnection> {
|
|
25
|
-
if (this.db) {
|
|
26
|
-
return this.db;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
debug.log('database', '๐ Connecting to database...');
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
// Create ~/.clopen directory if it doesn't exist
|
|
33
|
-
const clopenDir = join(homedir(), '.clopen');
|
|
34
|
-
const dirFile = Bun.file(clopenDir);
|
|
35
|
-
|
|
36
|
-
// Check if directory exists, if not create it
|
|
37
|
-
try {
|
|
38
|
-
await dirFile.stat();
|
|
39
|
-
} catch {
|
|
40
|
-
// Directory doesn't exist, create using Bun.write workaround
|
|
41
|
-
const tempFile = join(clopenDir, '.init');
|
|
42
|
-
await Bun.write(tempFile, '');
|
|
43
|
-
// Remove the temp file
|
|
44
|
-
try {
|
|
45
|
-
const tempFileHandle = Bun.file(tempFile);
|
|
46
|
-
if (await tempFileHandle.exists()) {
|
|
47
|
-
if (process.platform === 'win32') {
|
|
48
|
-
await Bun.spawn(['cmd', '/c', 'del', '/f', '/q', tempFile.replace(/\//g, '\\')], {
|
|
49
|
-
stdout: 'ignore',
|
|
50
|
-
stderr: 'ignore'
|
|
51
|
-
}).exited;
|
|
52
|
-
} else {
|
|
53
|
-
await Bun.spawn(['rm', '-f', tempFile], {
|
|
54
|
-
stdout: 'ignore',
|
|
55
|
-
stderr: 'ignore'
|
|
56
|
-
}).exited;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
} catch {
|
|
60
|
-
// Ignore cleanup errors
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Use Bun's native SQLite exclusively
|
|
65
|
-
this.db = new Database(this.dbPath);
|
|
66
|
-
|
|
67
|
-
// Configure database for optimal performance
|
|
68
|
-
this.configurePragmas();
|
|
69
|
-
|
|
70
|
-
debug.log('database', `โ
Connected to database at: ${this.dbPath}`);
|
|
71
|
-
return this.db;
|
|
72
|
-
|
|
73
|
-
} catch (error) {
|
|
74
|
-
debug.error('database', 'โ Failed to connect to database:', error);
|
|
75
|
-
throw error;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
private configurePragmas(): void {
|
|
80
|
-
if (!this.db) return;
|
|
81
|
-
|
|
82
|
-
debug.log('database', 'โ๏ธ Configuring database pragmas...');
|
|
83
|
-
|
|
84
|
-
// Bun SQLite uses exec for pragmas
|
|
85
|
-
this.db.exec('PRAGMA journal_mode = WAL');
|
|
86
|
-
this.db.exec('PRAGMA synchronous = NORMAL');
|
|
87
|
-
this.db.exec('PRAGMA cache_size = 1000000');
|
|
88
|
-
this.db.exec('PRAGMA temp_store = memory');
|
|
89
|
-
this.db.exec('PRAGMA foreign_keys = ON');
|
|
90
|
-
|
|
91
|
-
debug.log('database', 'โ
Database pragmas configured');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
getConnection(): DatabaseConnection {
|
|
95
|
-
if (!this.db) {
|
|
96
|
-
throw new Error('Database not connected. Call connect() first.');
|
|
97
|
-
}
|
|
98
|
-
return this.db;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
isConnected(): boolean {
|
|
102
|
-
return this.db !== null;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
close(): void {
|
|
106
|
-
if (this.db) {
|
|
107
|
-
debug.log('database', '๐ Closing database connection...');
|
|
108
|
-
this.db.close();
|
|
109
|
-
this.db = null;
|
|
110
|
-
debug.log('database', 'โ
Database connection closed');
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
getPath(): string {
|
|
115
|
-
return this.dbPath;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async resetDatabase(): Promise<void> {
|
|
119
|
-
debug.log('database', 'โ ๏ธ Resetting database (dropping all tables)...');
|
|
120
|
-
|
|
121
|
-
if (!this.db) {
|
|
122
|
-
throw new Error('Database not connected');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Drop all tables
|
|
126
|
-
const tables = this.db.prepare(`
|
|
127
|
-
SELECT name FROM sqlite_master
|
|
128
|
-
WHERE type='table' AND name NOT LIKE 'sqlite_%'
|
|
129
|
-
`).all() as { name: string }[];
|
|
130
|
-
|
|
131
|
-
for (const table of tables) {
|
|
132
|
-
debug.log('database', `๐๏ธ Dropping table: ${table.name}`);
|
|
133
|
-
this.db.exec(`DROP TABLE IF EXISTS ${table.name}`);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
debug.log('database', 'โ
Database reset completed');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async vacuum(): Promise<void> {
|
|
140
|
-
debug.log('database', '๐งน Running database vacuum...');
|
|
141
|
-
|
|
142
|
-
if (!this.db) {
|
|
143
|
-
throw new Error('Database not connected');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
this.db.exec('VACUUM');
|
|
147
|
-
debug.log('database', 'โ
Database vacuum completed');
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
getDatabaseInfo(): object {
|
|
151
|
-
if (!this.db) {
|
|
152
|
-
throw new Error('Database not connected');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Helper to get pragma values with Bun SQLite
|
|
156
|
-
const getPragma = (name: string) => {
|
|
157
|
-
const result = this.db!.query(`PRAGMA ${name}`).get() as any;
|
|
158
|
-
return result ? Object.values(result)[0] : null;
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
return {
|
|
162
|
-
path: this.dbPath,
|
|
163
|
-
journalMode: getPragma('journal_mode'),
|
|
164
|
-
synchronous: getPragma('synchronous'),
|
|
165
|
-
cacheSize: getPragma('cache_size'),
|
|
166
|
-
tempStore: getPragma('temp_store'),
|
|
167
|
-
foreignKeys: getPragma('foreign_keys'),
|
|
168
|
-
userVersion: getPragma('user_version'),
|
|
169
|
-
pageSize: getPragma('page_size'),
|
|
170
|
-
pageCount: getPragma('page_count'),
|
|
171
|
-
freelistCount: getPragma('freelist_count')
|
|
172
|
-
};
|
|
173
|
-
}
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { Database } from 'bun:sqlite';
|
|
4
|
+
import type { DatabaseConnection } from '$shared/types/database/connection';
|
|
5
|
+
|
|
6
|
+
import { debug } from '$shared/utils/logger';
|
|
7
|
+
export class DatabaseManager {
|
|
8
|
+
private static instance: DatabaseManager | null = null;
|
|
9
|
+
private db: DatabaseConnection | null = null;
|
|
10
|
+
private readonly dbPath: string;
|
|
11
|
+
|
|
12
|
+
private constructor() {
|
|
13
|
+
const clopenDir = join(homedir(), '.clopen');
|
|
14
|
+
this.dbPath = join(clopenDir, 'app.db');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static getInstance(): DatabaseManager {
|
|
18
|
+
if (!DatabaseManager.instance) {
|
|
19
|
+
DatabaseManager.instance = new DatabaseManager();
|
|
20
|
+
}
|
|
21
|
+
return DatabaseManager.instance;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async connect(): Promise<DatabaseConnection> {
|
|
25
|
+
if (this.db) {
|
|
26
|
+
return this.db;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
debug.log('database', '๐ Connecting to database...');
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
// Create ~/.clopen directory if it doesn't exist
|
|
33
|
+
const clopenDir = join(homedir(), '.clopen');
|
|
34
|
+
const dirFile = Bun.file(clopenDir);
|
|
35
|
+
|
|
36
|
+
// Check if directory exists, if not create it
|
|
37
|
+
try {
|
|
38
|
+
await dirFile.stat();
|
|
39
|
+
} catch {
|
|
40
|
+
// Directory doesn't exist, create using Bun.write workaround
|
|
41
|
+
const tempFile = join(clopenDir, '.init');
|
|
42
|
+
await Bun.write(tempFile, '');
|
|
43
|
+
// Remove the temp file
|
|
44
|
+
try {
|
|
45
|
+
const tempFileHandle = Bun.file(tempFile);
|
|
46
|
+
if (await tempFileHandle.exists()) {
|
|
47
|
+
if (process.platform === 'win32') {
|
|
48
|
+
await Bun.spawn(['cmd', '/c', 'del', '/f', '/q', tempFile.replace(/\//g, '\\')], {
|
|
49
|
+
stdout: 'ignore',
|
|
50
|
+
stderr: 'ignore'
|
|
51
|
+
}).exited;
|
|
52
|
+
} else {
|
|
53
|
+
await Bun.spawn(['rm', '-f', tempFile], {
|
|
54
|
+
stdout: 'ignore',
|
|
55
|
+
stderr: 'ignore'
|
|
56
|
+
}).exited;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
// Ignore cleanup errors
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Use Bun's native SQLite exclusively
|
|
65
|
+
this.db = new Database(this.dbPath);
|
|
66
|
+
|
|
67
|
+
// Configure database for optimal performance
|
|
68
|
+
this.configurePragmas();
|
|
69
|
+
|
|
70
|
+
debug.log('database', `โ
Connected to database at: ${this.dbPath}`);
|
|
71
|
+
return this.db;
|
|
72
|
+
|
|
73
|
+
} catch (error) {
|
|
74
|
+
debug.error('database', 'โ Failed to connect to database:', error);
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private configurePragmas(): void {
|
|
80
|
+
if (!this.db) return;
|
|
81
|
+
|
|
82
|
+
debug.log('database', 'โ๏ธ Configuring database pragmas...');
|
|
83
|
+
|
|
84
|
+
// Bun SQLite uses exec for pragmas
|
|
85
|
+
this.db.exec('PRAGMA journal_mode = WAL');
|
|
86
|
+
this.db.exec('PRAGMA synchronous = NORMAL');
|
|
87
|
+
this.db.exec('PRAGMA cache_size = 1000000');
|
|
88
|
+
this.db.exec('PRAGMA temp_store = memory');
|
|
89
|
+
this.db.exec('PRAGMA foreign_keys = ON');
|
|
90
|
+
|
|
91
|
+
debug.log('database', 'โ
Database pragmas configured');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
getConnection(): DatabaseConnection {
|
|
95
|
+
if (!this.db) {
|
|
96
|
+
throw new Error('Database not connected. Call connect() first.');
|
|
97
|
+
}
|
|
98
|
+
return this.db;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
isConnected(): boolean {
|
|
102
|
+
return this.db !== null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
close(): void {
|
|
106
|
+
if (this.db) {
|
|
107
|
+
debug.log('database', '๐ Closing database connection...');
|
|
108
|
+
this.db.close();
|
|
109
|
+
this.db = null;
|
|
110
|
+
debug.log('database', 'โ
Database connection closed');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getPath(): string {
|
|
115
|
+
return this.dbPath;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async resetDatabase(): Promise<void> {
|
|
119
|
+
debug.log('database', 'โ ๏ธ Resetting database (dropping all tables)...');
|
|
120
|
+
|
|
121
|
+
if (!this.db) {
|
|
122
|
+
throw new Error('Database not connected');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Drop all tables
|
|
126
|
+
const tables = this.db.prepare(`
|
|
127
|
+
SELECT name FROM sqlite_master
|
|
128
|
+
WHERE type='table' AND name NOT LIKE 'sqlite_%'
|
|
129
|
+
`).all() as { name: string }[];
|
|
130
|
+
|
|
131
|
+
for (const table of tables) {
|
|
132
|
+
debug.log('database', `๐๏ธ Dropping table: ${table.name}`);
|
|
133
|
+
this.db.exec(`DROP TABLE IF EXISTS ${table.name}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
debug.log('database', 'โ
Database reset completed');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async vacuum(): Promise<void> {
|
|
140
|
+
debug.log('database', '๐งน Running database vacuum...');
|
|
141
|
+
|
|
142
|
+
if (!this.db) {
|
|
143
|
+
throw new Error('Database not connected');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
this.db.exec('VACUUM');
|
|
147
|
+
debug.log('database', 'โ
Database vacuum completed');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
getDatabaseInfo(): object {
|
|
151
|
+
if (!this.db) {
|
|
152
|
+
throw new Error('Database not connected');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Helper to get pragma values with Bun SQLite
|
|
156
|
+
const getPragma = (name: string) => {
|
|
157
|
+
const result = this.db!.query(`PRAGMA ${name}`).get() as any;
|
|
158
|
+
return result ? Object.values(result)[0] : null;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
path: this.dbPath,
|
|
163
|
+
journalMode: getPragma('journal_mode'),
|
|
164
|
+
synchronous: getPragma('synchronous'),
|
|
165
|
+
cacheSize: getPragma('cache_size'),
|
|
166
|
+
tempStore: getPragma('temp_store'),
|
|
167
|
+
foreignKeys: getPragma('foreign_keys'),
|
|
168
|
+
userVersion: getPragma('user_version'),
|
|
169
|
+
pageSize: getPragma('page_size'),
|
|
170
|
+
pageCount: getPragma('page_count'),
|
|
171
|
+
freelistCount: getPragma('freelist_count')
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
174
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Export all database utilities
|
|
2
|
-
export { DatabaseManager } from './connection';
|
|
3
|
-
export { MigrationRunner } from './migration-runner';
|
|
1
|
+
// Export all database utilities
|
|
2
|
+
export { DatabaseManager } from './connection';
|
|
3
|
+
export { MigrationRunner } from './migration-runner';
|
|
4
4
|
export { SeederRunner } from './seeder-runner';
|