@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.
Files changed (456) hide show
  1. package/.env.example +6 -0
  2. package/.github/workflows/release.yml +60 -0
  3. package/.github/workflows/test.yml +40 -0
  4. package/CONTRIBUTING.md +499 -0
  5. package/LICENSE +21 -0
  6. package/README.md +209 -0
  7. package/backend/index.ts +156 -0
  8. package/backend/lib/chat/helpers.ts +42 -0
  9. package/backend/lib/chat/index.ts +2 -0
  10. package/backend/lib/chat/stream-manager.ts +1126 -0
  11. package/backend/lib/database/README.md +77 -0
  12. package/backend/lib/database/index.ts +119 -0
  13. package/backend/lib/database/migrations/001_create_projects_table.ts +31 -0
  14. package/backend/lib/database/migrations/002_create_chat_sessions_table.ts +33 -0
  15. package/backend/lib/database/migrations/003_create_messages_table.ts +32 -0
  16. package/backend/lib/database/migrations/004_create_prompt_templates_table.ts +34 -0
  17. package/backend/lib/database/migrations/005_create_settings_table.ts +24 -0
  18. package/backend/lib/database/migrations/006_add_user_to_messages.ts +58 -0
  19. package/backend/lib/database/migrations/007_create_stream_states_table.ts +41 -0
  20. package/backend/lib/database/migrations/008_create_message_snapshots_table.ts +62 -0
  21. package/backend/lib/database/migrations/009_add_delta_snapshot_fields.ts +41 -0
  22. package/backend/lib/database/migrations/010_add_soft_delete_and_branch_support.ts +70 -0
  23. package/backend/lib/database/migrations/011_git_like_commit_graph.ts +156 -0
  24. package/backend/lib/database/migrations/012_add_file_change_statistics.ts +41 -0
  25. package/backend/lib/database/migrations/013_checkpoint_tree_state.ts +118 -0
  26. package/backend/lib/database/migrations/014_add_engine_to_sessions.ts +18 -0
  27. package/backend/lib/database/migrations/015_add_model_to_sessions.ts +18 -0
  28. package/backend/lib/database/migrations/016_create_user_projects_table.ts +34 -0
  29. package/backend/lib/database/migrations/017_add_current_session_to_user_projects.ts +32 -0
  30. package/backend/lib/database/migrations/018_create_claude_accounts_table.ts +24 -0
  31. package/backend/lib/database/migrations/019_add_claude_account_to_sessions.ts +18 -0
  32. package/backend/lib/database/migrations/020_add_snapshot_tree_hash.ts +32 -0
  33. package/backend/lib/database/migrations/021_drop_prompt_templates_table.ts +33 -0
  34. package/backend/lib/database/migrations/index.ts +154 -0
  35. package/backend/lib/database/queries/checkpoint-queries.ts +87 -0
  36. package/backend/lib/database/queries/engine-queries.ts +75 -0
  37. package/backend/lib/database/queries/index.ts +9 -0
  38. package/backend/lib/database/queries/message-queries.ts +472 -0
  39. package/backend/lib/database/queries/project-queries.ts +117 -0
  40. package/backend/lib/database/queries/session-queries.ts +271 -0
  41. package/backend/lib/database/queries/settings-queries.ts +34 -0
  42. package/backend/lib/database/queries/snapshot-queries.ts +326 -0
  43. package/backend/lib/database/queries/utils-queries.ts +59 -0
  44. package/backend/lib/database/seeders/index.ts +13 -0
  45. package/backend/lib/database/seeders/settings_seeder.ts +84 -0
  46. package/backend/lib/database/utils/connection.ts +174 -0
  47. package/backend/lib/database/utils/index.ts +4 -0
  48. package/backend/lib/database/utils/migration-runner.ts +118 -0
  49. package/backend/lib/database/utils/seeder-runner.ts +121 -0
  50. package/backend/lib/engine/adapters/claude/environment.ts +164 -0
  51. package/backend/lib/engine/adapters/claude/error-handler.ts +60 -0
  52. package/backend/lib/engine/adapters/claude/index.ts +1 -0
  53. package/backend/lib/engine/adapters/claude/path-utils.ts +38 -0
  54. package/backend/lib/engine/adapters/claude/stream.ts +177 -0
  55. package/backend/lib/engine/adapters/opencode/index.ts +2 -0
  56. package/backend/lib/engine/adapters/opencode/message-converter.ts +862 -0
  57. package/backend/lib/engine/adapters/opencode/server.ts +104 -0
  58. package/backend/lib/engine/adapters/opencode/stream.ts +755 -0
  59. package/backend/lib/engine/index.ts +196 -0
  60. package/backend/lib/engine/types.ts +58 -0
  61. package/backend/lib/files/file-operations.ts +478 -0
  62. package/backend/lib/files/file-reading.ts +308 -0
  63. package/backend/lib/files/file-watcher.ts +383 -0
  64. package/backend/lib/files/path-browsing.ts +382 -0
  65. package/backend/lib/git/git-executor.ts +88 -0
  66. package/backend/lib/git/git-parser.ts +411 -0
  67. package/backend/lib/git/git-service.ts +505 -0
  68. package/backend/lib/mcp/README.md +1144 -0
  69. package/backend/lib/mcp/config.ts +316 -0
  70. package/backend/lib/mcp/index.ts +35 -0
  71. package/backend/lib/mcp/project-context.ts +236 -0
  72. package/backend/lib/mcp/servers/browser-automation/actions.ts +156 -0
  73. package/backend/lib/mcp/servers/browser-automation/browser.ts +419 -0
  74. package/backend/lib/mcp/servers/browser-automation/index.ts +791 -0
  75. package/backend/lib/mcp/servers/browser-automation/inspection.ts +501 -0
  76. package/backend/lib/mcp/servers/helper.ts +143 -0
  77. package/backend/lib/mcp/servers/index.ts +45 -0
  78. package/backend/lib/mcp/servers/weather/get-temperature.ts +56 -0
  79. package/backend/lib/mcp/servers/weather/index.ts +31 -0
  80. package/backend/lib/mcp/stdio-server.ts +103 -0
  81. package/backend/lib/mcp/types.ts +65 -0
  82. package/backend/lib/preview/browser/browser-audio-capture.ts +86 -0
  83. package/backend/lib/preview/browser/browser-console-manager.ts +263 -0
  84. package/backend/lib/preview/browser/browser-dialog-handler.ts +222 -0
  85. package/backend/lib/preview/browser/browser-interaction-handler.ts +421 -0
  86. package/backend/lib/preview/browser/browser-mcp-control.ts +415 -0
  87. package/backend/lib/preview/browser/browser-native-ui-handler.ts +512 -0
  88. package/backend/lib/preview/browser/browser-navigation-tracker.ts +104 -0
  89. package/backend/lib/preview/browser/browser-pool.ts +357 -0
  90. package/backend/lib/preview/browser/browser-preview-service.ts +882 -0
  91. package/backend/lib/preview/browser/browser-tab-manager.ts +935 -0
  92. package/backend/lib/preview/browser/browser-video-capture.ts +695 -0
  93. package/backend/lib/preview/browser/scripts/audio-stream.ts +292 -0
  94. package/backend/lib/preview/browser/scripts/cursor-tracking.ts +85 -0
  95. package/backend/lib/preview/browser/scripts/video-stream.ts +438 -0
  96. package/backend/lib/preview/browser/types.ts +359 -0
  97. package/backend/lib/preview/index.ts +24 -0
  98. package/backend/lib/project/index.ts +2 -0
  99. package/backend/lib/project/status-manager.ts +182 -0
  100. package/backend/lib/shared/index.ts +2 -0
  101. package/backend/lib/shared/port-utils.ts +25 -0
  102. package/backend/lib/shared/process-manager.ts +281 -0
  103. package/backend/lib/snapshot/blob-store.ts +227 -0
  104. package/backend/lib/snapshot/gitignore.ts +307 -0
  105. package/backend/lib/snapshot/helpers.ts +397 -0
  106. package/backend/lib/snapshot/snapshot-service.ts +483 -0
  107. package/backend/lib/terminal/helpers.ts +14 -0
  108. package/backend/lib/terminal/index.ts +8 -0
  109. package/backend/lib/terminal/pty-manager.ts +4 -0
  110. package/backend/lib/terminal/pty-session-manager.ts +387 -0
  111. package/backend/lib/terminal/shell-utils.ts +313 -0
  112. package/backend/lib/terminal/stream-manager.ts +293 -0
  113. package/backend/lib/tunnel/global-tunnel-manager.ts +243 -0
  114. package/backend/lib/tunnel/project-tunnel-manager.ts +311 -0
  115. package/backend/lib/user/helpers.ts +87 -0
  116. package/backend/lib/utils/ws.ts +944 -0
  117. package/backend/lib/vite-dev.ts +353 -0
  118. package/backend/middleware/cors.ts +15 -0
  119. package/backend/middleware/error-handler.ts +49 -0
  120. package/backend/middleware/logger.ts +9 -0
  121. package/backend/types/api.ts +24 -0
  122. package/backend/ws/README.md +1505 -0
  123. package/backend/ws/chat/background.ts +198 -0
  124. package/backend/ws/chat/index.ts +21 -0
  125. package/backend/ws/chat/stream.ts +707 -0
  126. package/backend/ws/engine/claude/accounts.ts +401 -0
  127. package/backend/ws/engine/claude/index.ts +13 -0
  128. package/backend/ws/engine/claude/status.ts +43 -0
  129. package/backend/ws/engine/index.ts +14 -0
  130. package/backend/ws/engine/opencode/index.ts +11 -0
  131. package/backend/ws/engine/opencode/status.ts +30 -0
  132. package/backend/ws/engine/utils.ts +36 -0
  133. package/backend/ws/files/index.ts +30 -0
  134. package/backend/ws/files/read.ts +189 -0
  135. package/backend/ws/files/search.ts +453 -0
  136. package/backend/ws/files/watch.ts +124 -0
  137. package/backend/ws/files/write.ts +143 -0
  138. package/backend/ws/git/branch.ts +106 -0
  139. package/backend/ws/git/commit.ts +39 -0
  140. package/backend/ws/git/conflict.ts +68 -0
  141. package/backend/ws/git/diff.ts +69 -0
  142. package/backend/ws/git/index.ts +24 -0
  143. package/backend/ws/git/log.ts +41 -0
  144. package/backend/ws/git/remote.ts +214 -0
  145. package/backend/ws/git/staging.ts +84 -0
  146. package/backend/ws/git/status.ts +90 -0
  147. package/backend/ws/index.ts +69 -0
  148. package/backend/ws/mcp/index.ts +61 -0
  149. package/backend/ws/messages/crud.ts +74 -0
  150. package/backend/ws/messages/index.ts +14 -0
  151. package/backend/ws/preview/browser/cleanup.ts +129 -0
  152. package/backend/ws/preview/browser/console.ts +114 -0
  153. package/backend/ws/preview/browser/interact.ts +513 -0
  154. package/backend/ws/preview/browser/mcp.ts +129 -0
  155. package/backend/ws/preview/browser/native-ui.ts +235 -0
  156. package/backend/ws/preview/browser/stats.ts +55 -0
  157. package/backend/ws/preview/browser/tab-info.ts +126 -0
  158. package/backend/ws/preview/browser/tab.ts +166 -0
  159. package/backend/ws/preview/browser/webcodecs.ts +293 -0
  160. package/backend/ws/preview/index.ts +146 -0
  161. package/backend/ws/projects/crud.ts +113 -0
  162. package/backend/ws/projects/index.ts +25 -0
  163. package/backend/ws/projects/presence.ts +46 -0
  164. package/backend/ws/projects/status.ts +116 -0
  165. package/backend/ws/sessions/crud.ts +327 -0
  166. package/backend/ws/sessions/index.ts +33 -0
  167. package/backend/ws/settings/crud.ts +112 -0
  168. package/backend/ws/settings/index.ts +14 -0
  169. package/backend/ws/snapshot/index.ts +17 -0
  170. package/backend/ws/snapshot/restore.ts +173 -0
  171. package/backend/ws/snapshot/timeline.ts +141 -0
  172. package/backend/ws/system/index.ts +14 -0
  173. package/backend/ws/system/operations.ts +49 -0
  174. package/backend/ws/terminal/index.ts +40 -0
  175. package/backend/ws/terminal/persistence.ts +153 -0
  176. package/backend/ws/terminal/session.ts +382 -0
  177. package/backend/ws/terminal/stream.ts +79 -0
  178. package/backend/ws/tunnel/index.ts +14 -0
  179. package/backend/ws/tunnel/operations.ts +91 -0
  180. package/backend/ws/types.ts +20 -0
  181. package/backend/ws/user/crud.ts +156 -0
  182. package/backend/ws/user/index.ts +14 -0
  183. package/bin/clopen.ts +307 -0
  184. package/bun.lock +1352 -0
  185. package/frontend/App.svelte +34 -0
  186. package/frontend/app.css +313 -0
  187. package/frontend/lib/app-environment.ts +10 -0
  188. package/frontend/lib/components/chat/ChatInterface.svelte +407 -0
  189. package/frontend/lib/components/chat/formatters/ErrorMessage.svelte +57 -0
  190. package/frontend/lib/components/chat/formatters/MessageFormatter.svelte +224 -0
  191. package/frontend/lib/components/chat/formatters/TextMessage.svelte +395 -0
  192. package/frontend/lib/components/chat/formatters/Tools.svelte +70 -0
  193. package/frontend/lib/components/chat/formatters/index.ts +3 -0
  194. package/frontend/lib/components/chat/input/ChatInput.svelte +421 -0
  195. package/frontend/lib/components/chat/input/components/ChatInputActions.svelte +78 -0
  196. package/frontend/lib/components/chat/input/components/DragDropOverlay.svelte +30 -0
  197. package/frontend/lib/components/chat/input/components/EditModeIndicator.svelte +33 -0
  198. package/frontend/lib/components/chat/input/components/EngineModelPicker.svelte +619 -0
  199. package/frontend/lib/components/chat/input/components/FileAttachmentPreview.svelte +48 -0
  200. package/frontend/lib/components/chat/input/components/LoadingIndicator.svelte +31 -0
  201. package/frontend/lib/components/chat/input/composables/use-animations.svelte.ts +201 -0
  202. package/frontend/lib/components/chat/input/composables/use-chat-actions.svelte.ts +148 -0
  203. package/frontend/lib/components/chat/input/composables/use-file-handling.svelte.ts +216 -0
  204. package/frontend/lib/components/chat/input/composables/use-input-state.svelte.ts +357 -0
  205. package/frontend/lib/components/chat/input/composables/use-textarea-resize.svelte.ts +57 -0
  206. package/frontend/lib/components/chat/message/ChatMessage.svelte +478 -0
  207. package/frontend/lib/components/chat/message/ChatMessages.svelte +541 -0
  208. package/frontend/lib/components/chat/message/DateSeparator.svelte +86 -0
  209. package/frontend/lib/components/chat/message/MessageBubble.svelte +86 -0
  210. package/frontend/lib/components/chat/message/MessageHeader.svelte +157 -0
  211. package/frontend/lib/components/chat/modal/DebugModal.svelte +59 -0
  212. package/frontend/lib/components/chat/modal/TokenUsageModal.svelte +124 -0
  213. package/frontend/lib/components/chat/shared/index.ts +2 -0
  214. package/frontend/lib/components/chat/shared/utils.ts +116 -0
  215. package/frontend/lib/components/chat/tools/BashOutputTool.svelte +35 -0
  216. package/frontend/lib/components/chat/tools/BashTool.svelte +46 -0
  217. package/frontend/lib/components/chat/tools/CustomMcpTool.svelte +139 -0
  218. package/frontend/lib/components/chat/tools/EditTool.svelte +48 -0
  219. package/frontend/lib/components/chat/tools/ExitPlanModeTool.svelte +32 -0
  220. package/frontend/lib/components/chat/tools/GlobTool.svelte +51 -0
  221. package/frontend/lib/components/chat/tools/GrepTool.svelte +90 -0
  222. package/frontend/lib/components/chat/tools/KillShellTool.svelte +26 -0
  223. package/frontend/lib/components/chat/tools/ListMcpResourcesTool.svelte +31 -0
  224. package/frontend/lib/components/chat/tools/NotebookEditTool.svelte +38 -0
  225. package/frontend/lib/components/chat/tools/ReadMcpResourceTool.svelte +34 -0
  226. package/frontend/lib/components/chat/tools/ReadTool.svelte +41 -0
  227. package/frontend/lib/components/chat/tools/TaskTool.svelte +64 -0
  228. package/frontend/lib/components/chat/tools/TodoWriteTool.svelte +75 -0
  229. package/frontend/lib/components/chat/tools/WebFetchTool.svelte +35 -0
  230. package/frontend/lib/components/chat/tools/WebSearchTool.svelte +84 -0
  231. package/frontend/lib/components/chat/tools/WriteTool.svelte +33 -0
  232. package/frontend/lib/components/chat/tools/components/CodeBlock.svelte +79 -0
  233. package/frontend/lib/components/chat/tools/components/DiffBlock.svelte +408 -0
  234. package/frontend/lib/components/chat/tools/components/FileHeader.svelte +45 -0
  235. package/frontend/lib/components/chat/tools/components/InfoLine.svelte +19 -0
  236. package/frontend/lib/components/chat/tools/components/StatsBadges.svelte +27 -0
  237. package/frontend/lib/components/chat/tools/components/TerminalCommand.svelte +54 -0
  238. package/frontend/lib/components/chat/tools/components/index.ts +7 -0
  239. package/frontend/lib/components/chat/tools/index.ts +26 -0
  240. package/frontend/lib/components/chat/widgets/FloatingTodoList.svelte +249 -0
  241. package/frontend/lib/components/chat/widgets/TokenUsage.svelte +78 -0
  242. package/frontend/lib/components/checkpoint/TimelineModal.svelte +391 -0
  243. package/frontend/lib/components/checkpoint/timeline/TimelineEdge.svelte +26 -0
  244. package/frontend/lib/components/checkpoint/timeline/TimelineGraph.svelte +87 -0
  245. package/frontend/lib/components/checkpoint/timeline/TimelineNode.svelte +108 -0
  246. package/frontend/lib/components/checkpoint/timeline/TimelineVersionGroup.svelte +59 -0
  247. package/frontend/lib/components/checkpoint/timeline/animation.ts +168 -0
  248. package/frontend/lib/components/checkpoint/timeline/config.ts +44 -0
  249. package/frontend/lib/components/checkpoint/timeline/graph-builder.ts +304 -0
  250. package/frontend/lib/components/checkpoint/timeline/types.ts +65 -0
  251. package/frontend/lib/components/checkpoint/timeline/utils.ts +53 -0
  252. package/frontend/lib/components/common/Alert.svelte +139 -0
  253. package/frontend/lib/components/common/AvatarBubble.svelte +56 -0
  254. package/frontend/lib/components/common/Button.svelte +71 -0
  255. package/frontend/lib/components/common/Card.svelte +102 -0
  256. package/frontend/lib/components/common/Checkbox.svelte +48 -0
  257. package/frontend/lib/components/common/Dialog.svelte +249 -0
  258. package/frontend/lib/components/common/FolderBrowser.svelte +843 -0
  259. package/frontend/lib/components/common/Icon.svelte +58 -0
  260. package/frontend/lib/components/common/Input.svelte +72 -0
  261. package/frontend/lib/components/common/Lightbox.svelte +233 -0
  262. package/frontend/lib/components/common/LoadingScreen.svelte +52 -0
  263. package/frontend/lib/components/common/LoadingSpinner.svelte +48 -0
  264. package/frontend/lib/components/common/Modal.svelte +177 -0
  265. package/frontend/lib/components/common/ModalProvider.svelte +28 -0
  266. package/frontend/lib/components/common/ModelSelector.svelte +110 -0
  267. package/frontend/lib/components/common/MonacoEditor.svelte +569 -0
  268. package/frontend/lib/components/common/NotificationToast.svelte +113 -0
  269. package/frontend/lib/components/common/PageTemplate.svelte +76 -0
  270. package/frontend/lib/components/common/ProjectUserAvatars.svelte +79 -0
  271. package/frontend/lib/components/common/Select.svelte +98 -0
  272. package/frontend/lib/components/common/Textarea.svelte +80 -0
  273. package/frontend/lib/components/common/ThemeToggle.svelte +44 -0
  274. package/frontend/lib/components/common/lucide-icons.ts +1642 -0
  275. package/frontend/lib/components/common/material-icons.ts +1082 -0
  276. package/frontend/lib/components/common/xterm/XTerm.svelte +796 -0
  277. package/frontend/lib/components/common/xterm/index.ts +16 -0
  278. package/frontend/lib/components/common/xterm/terminal-config.ts +68 -0
  279. package/frontend/lib/components/common/xterm/types.ts +31 -0
  280. package/frontend/lib/components/common/xterm/xterm-service.ts +353 -0
  281. package/frontend/lib/components/files/FileNode.svelte +384 -0
  282. package/frontend/lib/components/files/FileTree.svelte +681 -0
  283. package/frontend/lib/components/files/FileViewer.svelte +728 -0
  284. package/frontend/lib/components/files/SearchResults.svelte +303 -0
  285. package/frontend/lib/components/git/BranchManager.svelte +458 -0
  286. package/frontend/lib/components/git/ChangesSection.svelte +107 -0
  287. package/frontend/lib/components/git/CommitForm.svelte +76 -0
  288. package/frontend/lib/components/git/ConflictResolver.svelte +158 -0
  289. package/frontend/lib/components/git/DiffViewer.svelte +364 -0
  290. package/frontend/lib/components/git/FileChangeItem.svelte +97 -0
  291. package/frontend/lib/components/git/GitButton.svelte +33 -0
  292. package/frontend/lib/components/git/GitLog.svelte +361 -0
  293. package/frontend/lib/components/git/GitModal.svelte +80 -0
  294. package/frontend/lib/components/history/HistoryModal.svelte +563 -0
  295. package/frontend/lib/components/history/HistoryView.svelte +615 -0
  296. package/frontend/lib/components/index.ts +34 -0
  297. package/frontend/lib/components/preview/browser/BrowserPreview.svelte +549 -0
  298. package/frontend/lib/components/preview/browser/components/Canvas.svelte +1058 -0
  299. package/frontend/lib/components/preview/browser/components/ConsolePanel.svelte +757 -0
  300. package/frontend/lib/components/preview/browser/components/Container.svelte +450 -0
  301. package/frontend/lib/components/preview/browser/components/ContextMenu.svelte +236 -0
  302. package/frontend/lib/components/preview/browser/components/SelectDropdown.svelte +224 -0
  303. package/frontend/lib/components/preview/browser/components/Toolbar.svelte +339 -0
  304. package/frontend/lib/components/preview/browser/components/VirtualCursor.svelte +36 -0
  305. package/frontend/lib/components/preview/browser/core/cleanup.svelte.ts +155 -0
  306. package/frontend/lib/components/preview/browser/core/coordinator.svelte.ts +837 -0
  307. package/frontend/lib/components/preview/browser/core/interactions.svelte.ts +113 -0
  308. package/frontend/lib/components/preview/browser/core/mcp-handlers.svelte.ts +296 -0
  309. package/frontend/lib/components/preview/browser/core/native-ui-handlers.svelte.ts +391 -0
  310. package/frontend/lib/components/preview/browser/core/stream-handler.svelte.ts +231 -0
  311. package/frontend/lib/components/preview/browser/core/tab-manager.svelte.ts +210 -0
  312. package/frontend/lib/components/preview/browser/core/tab-operations.svelte.ts +239 -0
  313. package/frontend/lib/components/preview/index.ts +2 -0
  314. package/frontend/lib/components/settings/SettingsModal.svelte +235 -0
  315. package/frontend/lib/components/settings/SettingsView.svelte +36 -0
  316. package/frontend/lib/components/settings/appearance/AppearanceSettings.svelte +51 -0
  317. package/frontend/lib/components/settings/appearance/LayoutPresetSettings.svelte +160 -0
  318. package/frontend/lib/components/settings/appearance/LayoutPreview.svelte +76 -0
  319. package/frontend/lib/components/settings/engines/AIEnginesSettings.svelte +917 -0
  320. package/frontend/lib/components/settings/general/AdvancedSettings.svelte +187 -0
  321. package/frontend/lib/components/settings/general/DataManagementSettings.svelte +203 -0
  322. package/frontend/lib/components/settings/general/GeneralSettings.svelte +10 -0
  323. package/frontend/lib/components/settings/model/ModelSettings.svelte +357 -0
  324. package/frontend/lib/components/settings/notifications/NotificationSettings.svelte +205 -0
  325. package/frontend/lib/components/settings/user/UserSettings.svelte +197 -0
  326. package/frontend/lib/components/terminal/Terminal.svelte +368 -0
  327. package/frontend/lib/components/terminal/TerminalTabs.svelte +87 -0
  328. package/frontend/lib/components/terminal/TerminalView.svelte +55 -0
  329. package/frontend/lib/components/tunnel/TunnelActive.svelte +142 -0
  330. package/frontend/lib/components/tunnel/TunnelButton.svelte +54 -0
  331. package/frontend/lib/components/tunnel/TunnelInactive.svelte +284 -0
  332. package/frontend/lib/components/tunnel/TunnelModal.svelte +47 -0
  333. package/frontend/lib/components/tunnel/TunnelQRCode.svelte +49 -0
  334. package/frontend/lib/components/workspace/DesktopNavigator.svelte +382 -0
  335. package/frontend/lib/components/workspace/MobileNavigator.svelte +403 -0
  336. package/frontend/lib/components/workspace/PanelContainer.svelte +100 -0
  337. package/frontend/lib/components/workspace/PanelHeader.svelte +505 -0
  338. package/frontend/lib/components/workspace/ViewMenu.svelte +162 -0
  339. package/frontend/lib/components/workspace/WorkspaceLayout.svelte +169 -0
  340. package/frontend/lib/components/workspace/layout/DesktopLayout.svelte +15 -0
  341. package/frontend/lib/components/workspace/layout/MobileLayout.svelte +17 -0
  342. package/frontend/lib/components/workspace/layout/split-pane/Container.svelte +42 -0
  343. package/frontend/lib/components/workspace/layout/split-pane/Handle.svelte +85 -0
  344. package/frontend/lib/components/workspace/layout/split-pane/Layout.svelte +37 -0
  345. package/frontend/lib/components/workspace/panels/ChatPanel.svelte +274 -0
  346. package/frontend/lib/components/workspace/panels/FilesPanel.svelte +1261 -0
  347. package/frontend/lib/components/workspace/panels/GitPanel.svelte +1560 -0
  348. package/frontend/lib/components/workspace/panels/PreviewPanel.svelte +150 -0
  349. package/frontend/lib/components/workspace/panels/TerminalPanel.svelte +73 -0
  350. package/frontend/lib/constants/preview.ts +45 -0
  351. package/frontend/lib/services/chat/chat.service.ts +704 -0
  352. package/frontend/lib/services/chat/index.ts +7 -0
  353. package/frontend/lib/services/notification/global-stream-monitor.ts +86 -0
  354. package/frontend/lib/services/notification/index.ts +8 -0
  355. package/frontend/lib/services/notification/push.service.ts +144 -0
  356. package/frontend/lib/services/notification/sound.service.ts +127 -0
  357. package/frontend/lib/services/preview/browser/browser-console.service.ts +61 -0
  358. package/frontend/lib/services/preview/browser/browser-webcodecs.service.ts +1499 -0
  359. package/frontend/lib/services/preview/browser/mcp-integration.svelte.ts +67 -0
  360. package/frontend/lib/services/preview/index.ts +23 -0
  361. package/frontend/lib/services/project/index.ts +8 -0
  362. package/frontend/lib/services/project/status.service.ts +159 -0
  363. package/frontend/lib/services/snapshot/snapshot.service.ts +47 -0
  364. package/frontend/lib/services/terminal/background/index.ts +130 -0
  365. package/frontend/lib/services/terminal/background/session-restore.ts +274 -0
  366. package/frontend/lib/services/terminal/background/stream-manager.ts +286 -0
  367. package/frontend/lib/services/terminal/index.ts +14 -0
  368. package/frontend/lib/services/terminal/persistence.service.ts +260 -0
  369. package/frontend/lib/services/terminal/project.service.ts +953 -0
  370. package/frontend/lib/services/terminal/session.service.ts +364 -0
  371. package/frontend/lib/services/terminal/terminal.service.ts +369 -0
  372. package/frontend/lib/stores/core/app.svelte.ts +117 -0
  373. package/frontend/lib/stores/core/files.svelte.ts +73 -0
  374. package/frontend/lib/stores/core/presence.svelte.ts +48 -0
  375. package/frontend/lib/stores/core/projects.svelte.ts +317 -0
  376. package/frontend/lib/stores/core/sessions.svelte.ts +383 -0
  377. package/frontend/lib/stores/features/claude-accounts.svelte.ts +58 -0
  378. package/frontend/lib/stores/features/models.svelte.ts +89 -0
  379. package/frontend/lib/stores/features/settings.svelte.ts +87 -0
  380. package/frontend/lib/stores/features/terminal.svelte.ts +701 -0
  381. package/frontend/lib/stores/features/tunnel.svelte.ts +161 -0
  382. package/frontend/lib/stores/features/user.svelte.ts +96 -0
  383. package/frontend/lib/stores/ui/chat-input.svelte.ts +57 -0
  384. package/frontend/lib/stores/ui/chat-model.svelte.ts +61 -0
  385. package/frontend/lib/stores/ui/dialog.svelte.ts +59 -0
  386. package/frontend/lib/stores/ui/edit-mode.svelte.ts +214 -0
  387. package/frontend/lib/stores/ui/notification.svelte.ts +166 -0
  388. package/frontend/lib/stores/ui/settings-modal.svelte.ts +88 -0
  389. package/frontend/lib/stores/ui/theme.svelte.ts +179 -0
  390. package/frontend/lib/stores/ui/workspace.svelte.ts +754 -0
  391. package/frontend/lib/types/native-ui.ts +73 -0
  392. package/frontend/lib/utils/chat/date-separator.ts +39 -0
  393. package/frontend/lib/utils/chat/message-grouper.ts +219 -0
  394. package/frontend/lib/utils/chat/message-processor.ts +135 -0
  395. package/frontend/lib/utils/chat/tool-handler.ts +161 -0
  396. package/frontend/lib/utils/chat/virtual-scroll.svelte.ts +142 -0
  397. package/frontend/lib/utils/click-outside.ts +20 -0
  398. package/frontend/lib/utils/context-manager.ts +257 -0
  399. package/frontend/lib/utils/file-icon-mappings.ts +769 -0
  400. package/frontend/lib/utils/folder-icon-mappings.ts +1030 -0
  401. package/frontend/lib/utils/git-status.ts +68 -0
  402. package/frontend/lib/utils/platform.ts +113 -0
  403. package/frontend/lib/utils/port-check.ts +65 -0
  404. package/frontend/lib/utils/terminalFormatter.ts +207 -0
  405. package/frontend/lib/utils/theme.ts +6 -0
  406. package/frontend/lib/utils/tree-visualizer.ts +320 -0
  407. package/frontend/lib/utils/ws.ts +44 -0
  408. package/frontend/main.ts +13 -0
  409. package/index.html +70 -0
  410. package/package.json +111 -0
  411. package/scripts/generate-icons.ts +87 -0
  412. package/scripts/pre-publish-check.sh +142 -0
  413. package/scripts/setup-hooks.sh +134 -0
  414. package/scripts/validate-branch-name.sh +47 -0
  415. package/scripts/validate-commit-msg.sh +42 -0
  416. package/shared/constants/engines.ts +134 -0
  417. package/shared/types/database/connection.ts +16 -0
  418. package/shared/types/database/index.ts +6 -0
  419. package/shared/types/database/schema.ts +141 -0
  420. package/shared/types/engine/index.ts +45 -0
  421. package/shared/types/filesystem/index.ts +22 -0
  422. package/shared/types/git.ts +171 -0
  423. package/shared/types/messaging/index.ts +239 -0
  424. package/shared/types/messaging/tool.ts +526 -0
  425. package/shared/types/network/api.ts +18 -0
  426. package/shared/types/network/index.ts +5 -0
  427. package/shared/types/stores/app.ts +23 -0
  428. package/shared/types/stores/dialog.ts +21 -0
  429. package/shared/types/stores/index.ts +3 -0
  430. package/shared/types/stores/settings.ts +15 -0
  431. package/shared/types/terminal/index.ts +44 -0
  432. package/shared/types/ui/components.ts +61 -0
  433. package/shared/types/ui/icons.ts +23 -0
  434. package/shared/types/ui/index.ts +22 -0
  435. package/shared/types/ui/notifications.ts +14 -0
  436. package/shared/types/ui/theme.ts +12 -0
  437. package/shared/types/websocket/index.ts +43 -0
  438. package/shared/types/window.d.ts +13 -0
  439. package/shared/utils/anonymous-user.ts +168 -0
  440. package/shared/utils/async.ts +10 -0
  441. package/shared/utils/diff-calculator.ts +184 -0
  442. package/shared/utils/file-type-detection.ts +166 -0
  443. package/shared/utils/logger.ts +158 -0
  444. package/shared/utils/message-formatter.ts +79 -0
  445. package/shared/utils/path.ts +47 -0
  446. package/shared/utils/ws-client.ts +768 -0
  447. package/shared/utils/ws-server.ts +660 -0
  448. package/static/audio/notification.ogg +0 -0
  449. package/static/favicon.svg +8 -0
  450. package/static/fonts/dm-sans/dm-sans-italic-latin-ext.woff2 +0 -0
  451. package/static/fonts/dm-sans/dm-sans-italic-latin.woff2 +0 -0
  452. package/static/fonts/dm-sans/dm-sans-normal-latin-ext.woff2 +0 -0
  453. package/static/fonts/dm-sans/dm-sans-normal-latin.woff2 +0 -0
  454. package/static/fonts/dm-sans.css +96 -0
  455. package/svelte.config.js +20 -0
  456. package/vite.config.ts +33 -0
@@ -0,0 +1,166 @@
1
+ import { fileTypeFromBuffer } from 'file-type';
2
+ import isTextPath from 'is-text-path';
3
+
4
+ import { debug } from '$shared/utils/logger';
5
+ /**
6
+ * Simple and reliable text file detection using external libraries
7
+ */
8
+ export async function isTextFile(filePath: string): Promise<boolean> {
9
+ try {
10
+ // Fast path: check by extension first (covers 90% of cases)
11
+ if (isTextPath(filePath)) {
12
+ return true;
13
+ }
14
+
15
+ const file = Bun.file(filePath);
16
+ const buffer = Buffer.from(await file.arrayBuffer());
17
+
18
+ // Empty files are text
19
+ if (buffer.length === 0) {
20
+ return true;
21
+ }
22
+
23
+ // Let file-type check for binary formats
24
+ const detectedType = await fileTypeFromBuffer(buffer);
25
+ if (detectedType) {
26
+ // If it detected something, check if content is actually text
27
+ return isContentText(buffer);
28
+ }
29
+
30
+ // Unknown format - analyze content
31
+ return isContentText(buffer);
32
+
33
+ } catch (error) {
34
+ debug.error('file', 'Error checking if file is text:', error);
35
+ return false;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Simple content analysis for text detection
41
+ */
42
+ function isContentText(buffer: Buffer): boolean {
43
+ const sample = buffer.slice(0, Math.min(8192, buffer.length));
44
+ let textBytes = 0;
45
+ let nullBytes = 0;
46
+
47
+ for (let i = 0; i < sample.length; i++) {
48
+ const byte = sample[i];
49
+
50
+ if (byte === 0) {
51
+ nullBytes++;
52
+ } else if (
53
+ (byte >= 0x20 && byte <= 0x7E) || // Printable ASCII
54
+ byte === 0x09 || byte === 0x0A || byte === 0x0D || // Whitespace
55
+ byte >= 0x80 // UTF-8 or other text encodings
56
+ ) {
57
+ textBytes++;
58
+ }
59
+ }
60
+
61
+ const textRatio = textBytes / sample.length;
62
+ const nullRatio = nullBytes / sample.length;
63
+
64
+ // Handle UTF-16 (has many nulls but in pattern)
65
+ if (nullRatio > 0.3) {
66
+ return isLikelyUTF16(sample);
67
+ }
68
+
69
+ // If mostly text characters, it's text
70
+ return textRatio > 0.7;
71
+ }
72
+
73
+ /**
74
+ * Check if buffer might be UTF-16
75
+ */
76
+ function isLikelyUTF16(buffer: Buffer): boolean {
77
+ // Check for BOM
78
+ if (buffer.length >= 2) {
79
+ if ((buffer[0] === 0xFF && buffer[1] === 0xFE) ||
80
+ (buffer[0] === 0xFE && buffer[1] === 0xFF)) {
81
+ return true;
82
+ }
83
+ }
84
+
85
+ // Check for alternating null pattern
86
+ let evenNulls = 0;
87
+ let oddNulls = 0;
88
+
89
+ for (let i = 0; i < Math.min(200, buffer.length); i++) {
90
+ if (buffer[i] === 0) {
91
+ if (i % 2 === 0) evenNulls++;
92
+ else oddNulls++;
93
+ }
94
+ }
95
+
96
+ // UTF-16 has nulls mostly on one side
97
+ return Math.abs(evenNulls - oddNulls) > (evenNulls + oddNulls) * 0.6;
98
+ }
99
+
100
+ /**
101
+ * Auto-detect encoding and read file content
102
+ */
103
+ export async function readFileWithEncoding(filePath: string): Promise<{ content: string; detectedEncoding: string }> {
104
+ try {
105
+ const file = Bun.file(filePath);
106
+ const buffer = Buffer.from(await file.arrayBuffer());
107
+
108
+ // Check BOM for encoding
109
+ if (buffer.length >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) {
110
+ return {
111
+ content: buffer.subarray(3).toString('utf8'),
112
+ detectedEncoding: 'utf-8'
113
+ };
114
+ }
115
+
116
+ if (buffer.length >= 2) {
117
+ if (buffer[0] === 0xFF && buffer[1] === 0xFE) {
118
+ return {
119
+ content: buffer.subarray(2).toString('utf16le'),
120
+ detectedEncoding: 'utf16le'
121
+ };
122
+ }
123
+ if (buffer[0] === 0xFE && buffer[1] === 0xFF) {
124
+ // Convert UTF-16 BE to LE
125
+ const swapped = Buffer.alloc(buffer.length - 2);
126
+ for (let i = 2; i < buffer.length - 1; i += 2) {
127
+ swapped[i - 2] = buffer[i + 1];
128
+ swapped[i - 1] = buffer[i];
129
+ }
130
+ return {
131
+ content: swapped.toString('utf16le'),
132
+ detectedEncoding: 'utf16be'
133
+ };
134
+ }
135
+ }
136
+
137
+ // Try UTF-8, fallback to latin1 if invalid
138
+ const utf8Content = buffer.toString('utf8');
139
+ if (!utf8Content.includes('\ufffd')) {
140
+ return { content: utf8Content, detectedEncoding: 'utf-8' };
141
+ }
142
+
143
+ // Check if it's UTF-16 without BOM
144
+ if (isLikelyUTF16(buffer)) {
145
+ return {
146
+ content: buffer.toString('utf16le'),
147
+ detectedEncoding: 'utf16le'
148
+ };
149
+ }
150
+
151
+ // Fallback to latin1
152
+ return {
153
+ content: buffer.toString('latin1'),
154
+ detectedEncoding: 'latin1'
155
+ };
156
+
157
+ } catch (error) {
158
+ debug.error('file', 'Error reading file with encoding:', error);
159
+ const file = Bun.file(filePath);
160
+ const buffer = Buffer.from(await file.arrayBuffer());
161
+ return {
162
+ content: buffer.toString('latin1'),
163
+ detectedEncoding: 'latin1'
164
+ };
165
+ }
166
+ }
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Custom Logger Module - debug
3
+ *
4
+ * Provides filtered logging capabilities with label-based categorization.
5
+ * All logs can be filtered by label, method type, and text content.
6
+ *
7
+ * Label Categories (22 total):
8
+ * - Communication & Real-time: WebSocket, MCP operations
9
+ * - File Operations: File I/O operations
10
+ * - Chat & Notifications: Messages and notifications
11
+ * - Terminal: Shell/PTY operations
12
+ * - Preview: Browser preview and video encoding
13
+ * - Data Persistence: Database, migrations, snapshots, checkpoints
14
+ * - Engine & Processing: Engine operations
15
+ * - User & Session: User and session management
16
+ * - Configuration & Settings: Settings
17
+ * - Infrastructure & Utilities: Server, git, project ops
18
+ * - Frontend/UI State: Workspace and checkpoint UI state
19
+ */
20
+
21
+ export type LogLabel =
22
+ // Chat
23
+ | 'chat'
24
+ | 'checkpoint'
25
+ | 'snapshot'
26
+
27
+ // Preview
28
+ | 'preview'
29
+ | 'webcodecs'
30
+
31
+ // File
32
+ | 'file'
33
+
34
+ // Terminal
35
+ | 'terminal'
36
+
37
+ // Git
38
+ | 'git'
39
+
40
+ // Communication
41
+ | 'websocket'
42
+ | 'mcp'
43
+ | 'notification'
44
+
45
+ // Configuration
46
+ | 'project'
47
+ | 'workspace'
48
+ | 'settings'
49
+ | 'engine'
50
+ | 'tunnel'
51
+
52
+ // User
53
+ | 'user'
54
+ | 'session'
55
+
56
+ // System
57
+ | 'server'
58
+ | 'database'
59
+ | 'migration'
60
+ | 'seeder';
61
+ export type LogMethod = 'log' | 'info' | 'warn' | 'error' | 'debug' | 'trace';
62
+
63
+ interface LoggerConfig {
64
+ enabled: boolean; // Global enable/disable based on NODE_ENV (production = disabled)
65
+ filterLabels: LogLabel[] | null; // null = show all, array = only show specified labels
66
+ filterMethods: LogMethod[] | null; // null = show all, array = only show specified methods
67
+ filterText: string | null; // null = no text filter, string = only show logs containing this text (case-sensitive)
68
+ }
69
+
70
+ // Default configuration - null means no filtering
71
+ // enabled = true in development, false in production
72
+ const config: LoggerConfig = {
73
+ enabled: process.env.NODE_ENV !== 'production',
74
+ filterLabels: ['snapshot', 'checkpoint', 'chat'],
75
+ // filterLabels: ['file'],
76
+ filterMethods: null,
77
+ filterText: null
78
+ };
79
+
80
+ /**
81
+ * Check if a log should be displayed based on current filters
82
+ */
83
+ function shouldLog(label: LogLabel, method: LogMethod, args: any[]): boolean {
84
+ // Global enable/disable check first
85
+ if (!config.enabled) {
86
+ return false;
87
+ }
88
+
89
+ // Filter by label
90
+ if (config.filterLabels !== null && !config.filterLabels.includes(label)) {
91
+ return false;
92
+ }
93
+
94
+ // Filter by method
95
+ if (config.filterMethods !== null && !config.filterMethods.includes(method)) {
96
+ return false;
97
+ }
98
+
99
+ // Filter by text (case-sensitive)
100
+ if (config.filterText !== null) {
101
+ // Convert all arguments to string for searching
102
+ const argsString = args
103
+ .map((arg) => {
104
+ if (typeof arg === 'object') {
105
+ try {
106
+ return JSON.stringify(arg);
107
+ } catch {
108
+ return String(arg);
109
+ }
110
+ }
111
+ return String(arg);
112
+ })
113
+ .join(' ');
114
+
115
+ // Case-sensitive search
116
+ if (!argsString.includes(config.filterText)) {
117
+ return false;
118
+ }
119
+ }
120
+
121
+ return true;
122
+ }
123
+
124
+ /**
125
+ * Format log output with label prefix
126
+ */
127
+ function formatOutput(label: LogLabel, args: any[]): any[] {
128
+ const d = new Date();
129
+ const timestamp =
130
+ `${String(d.getHours()).padStart(2, '0')}:` +
131
+ `${String(d.getMinutes()).padStart(2, '0')}:` +
132
+ `${String(d.getSeconds()).padStart(2, '0')}.` +
133
+ `${String(d.getMilliseconds()).padStart(3, '0')}`;
134
+
135
+ return [`[${timestamp}] [${label}]`, ...args];
136
+ }
137
+
138
+ /**
139
+ * Core logging function
140
+ */
141
+ function createLogMethod(method: LogMethod) {
142
+ return (label: LogLabel, ...args: any[]): void => {
143
+ if (shouldLog(label, method, args)) {
144
+ const output = formatOutput(label, args);
145
+ console[method](...output);
146
+ }
147
+ };
148
+ }
149
+
150
+ // Export the debug logger object
151
+ export const debug = {
152
+ log: createLogMethod('log'),
153
+ info: createLogMethod('info'),
154
+ warn: createLogMethod('warn'),
155
+ error: createLogMethod('error'),
156
+ debug: createLogMethod('debug'),
157
+ trace: createLogMethod('trace'),
158
+ };
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Message Formatter - Single source of truth for SDK message formatting
3
+ *
4
+ * Converts raw data → SDKMessageFormatter with metadata.
5
+ * Used by ALL paths that return messages to the frontend:
6
+ * - Backend: message-queries.ts, messages/crud.ts
7
+ * - Frontend: chat.service.ts (stream transport → metadata)
8
+ *
9
+ * This ensures stream response and DB response produce identical structure.
10
+ */
11
+
12
+ import type { DatabaseMessage, SDKMessageFormatter } from '$shared/types/database/schema';
13
+ import type { EngineSDKMessage } from '$shared/types/messaging';
14
+
15
+ /**
16
+ * Format a DatabaseMessage into SDKMessageFormatter
17
+ * Parses sdk_message JSON and attaches system metadata
18
+ */
19
+ export function formatDatabaseMessage(
20
+ msg: DatabaseMessage,
21
+ overrides?: {
22
+ sender_id?: string | null;
23
+ sender_name?: string | null;
24
+ }
25
+ ): SDKMessageFormatter {
26
+ const sdkMessage = JSON.parse(msg.sdk_message) as EngineSDKMessage;
27
+
28
+ return {
29
+ ...sdkMessage,
30
+ metadata: {
31
+ ...buildMetadataFromDb(msg, overrides),
32
+ ...(sdkMessage.metadata?.reasoning && { reasoning: true }),
33
+ }
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Build metadata object from DatabaseMessage fields
39
+ * This is the SINGLE definition of what metadata contains from DB
40
+ */
41
+ export function buildMetadataFromDb(
42
+ msg: DatabaseMessage,
43
+ overrides?: {
44
+ sender_id?: string | null;
45
+ sender_name?: string | null;
46
+ }
47
+ ): NonNullable<SDKMessageFormatter['metadata']> {
48
+ return {
49
+ message_id: msg.id,
50
+ created_at: msg.timestamp,
51
+ parent_message_id: msg.parent_message_id || null,
52
+ sender_id: overrides?.sender_id ?? msg.sender_id ?? null,
53
+ sender_name: overrides?.sender_name ?? msg.sender_name ?? null,
54
+ };
55
+ }
56
+
57
+ /**
58
+ * Build metadata from stream transport fields (used by frontend during stream)
59
+ * Produces identical structure as buildMetadataFromDb
60
+ */
61
+ export function buildMetadataFromTransport(transport: {
62
+ message_id?: string;
63
+ timestamp?: string;
64
+ parent_message_id?: string | null;
65
+ sender_id?: string | null;
66
+ sender_name?: string | null;
67
+ engine?: string;
68
+ reasoning?: boolean;
69
+ }): NonNullable<SDKMessageFormatter['metadata']> {
70
+ return {
71
+ message_id: transport.message_id || undefined,
72
+ created_at: transport.timestamp || new Date().toISOString(),
73
+ parent_message_id: transport.parent_message_id ?? null,
74
+ sender_id: transport.sender_id ?? null,
75
+ sender_name: transport.sender_name ?? null,
76
+ engine: transport.engine,
77
+ ...(transport.reasoning && { reasoning: true }),
78
+ };
79
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Shared path normalization utilities.
3
+ * Normalizes path separators to forward slashes for consistent display and comparison.
4
+ */
5
+
6
+ /**
7
+ * Normalize path separators to forward slash and strip trailing slashes.
8
+ * Keeps trailing slash only for drive roots like "C:/".
9
+ */
10
+ export function normalizePath(p: string): string {
11
+ let n = p.replace(/\\/g, '/');
12
+ // Keep trailing slash only for drive roots like "C:/"
13
+ if (n.length > 1 && !n.match(/^[A-Za-z]:\/$/)) {
14
+ n = n.replace(/\/+$/, '');
15
+ }
16
+ return n;
17
+ }
18
+
19
+ /**
20
+ * Compare two paths, case-insensitively on Windows paths.
21
+ */
22
+ export function pathsEqual(a: string, b: string): boolean {
23
+ const na = normalizePath(a);
24
+ const nb = normalizePath(b);
25
+ if (/^[A-Za-z]:/.test(na) || /^[A-Za-z]:/.test(nb)) {
26
+ return na.toLowerCase() === nb.toLowerCase();
27
+ }
28
+ return na === nb;
29
+ }
30
+
31
+ /**
32
+ * Get relative path from a base path, normalized with forward slashes.
33
+ */
34
+ export function getRelativePath(fullPath: string, basePath: string): string {
35
+ const normalizedFull = normalizePath(fullPath);
36
+ const normalizedBase = normalizePath(basePath);
37
+
38
+ if (normalizedFull.startsWith(normalizedBase)) {
39
+ let rel = normalizedFull.slice(normalizedBase.length);
40
+ if (rel.startsWith('/')) {
41
+ rel = rel.slice(1);
42
+ }
43
+ return rel;
44
+ }
45
+
46
+ return normalizePath(fullPath);
47
+ }