@myrialabs/clopen 0.2.1 → 0.2.2

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 (413) hide show
  1. package/backend/{lib/auth → auth}/auth-service.ts +2 -2
  2. package/backend/{lib/chat → chat}/stream-manager.ts +1 -1
  3. package/backend/{lib/engine → engine}/adapters/claude/environment.ts +1 -1
  4. package/backend/{lib/engine → engine}/adapters/opencode/message-converter.ts +1 -1
  5. package/backend/{lib/files → files}/file-watcher.ts +1 -1
  6. package/backend/{lib/git → git}/git-executor.ts +1 -1
  7. package/backend/index.ts +7 -7
  8. package/backend/{lib/mcp → mcp}/README.md +68 -79
  9. package/backend/{lib/mcp → mcp}/config.ts +1 -1
  10. package/backend/{lib/mcp → mcp}/servers/browser-automation/actions.ts +4 -4
  11. package/backend/{lib/mcp → mcp}/servers/browser-automation/browser.ts +3 -3
  12. package/backend/{lib/mcp → mcp}/servers/browser-automation/inspection.ts +3 -3
  13. package/backend/middleware/cors.ts +1 -1
  14. package/backend/middleware/error-handler.ts +1 -1
  15. package/backend/{lib/preview → preview}/browser/browser-preview-service.ts +1 -1
  16. package/backend/{lib/preview → preview}/browser/browser-tab-manager.ts +1 -1
  17. package/backend/{lib/preview → preview}/browser/types.ts +1 -1
  18. package/backend/{lib/project → project}/status-manager.ts +223 -223
  19. package/backend/{lib/terminal → terminal}/shell-utils.ts +1 -1
  20. package/backend/{lib/utils → utils}/ws.ts +2 -2
  21. package/backend/ws/README.md +9 -9
  22. package/backend/ws/auth/invites.ts +2 -2
  23. package/backend/ws/auth/login.ts +9 -9
  24. package/backend/ws/auth/status.ts +2 -2
  25. package/backend/ws/auth/users.ts +1 -1
  26. package/backend/ws/chat/background.ts +2 -2
  27. package/backend/ws/chat/stream.ts +3 -3
  28. package/backend/ws/engine/claude/accounts.ts +4 -4
  29. package/backend/ws/engine/claude/status.ts +1 -1
  30. package/backend/ws/files/read.ts +2 -2
  31. package/backend/ws/files/watch.ts +2 -2
  32. package/backend/ws/files/write.ts +1 -1
  33. package/backend/ws/git/branch.ts +2 -2
  34. package/backend/ws/git/commit.ts +2 -2
  35. package/backend/ws/git/conflict.ts +2 -2
  36. package/backend/ws/git/diff.ts +2 -2
  37. package/backend/ws/git/log.ts +2 -2
  38. package/backend/ws/git/remote.ts +2 -2
  39. package/backend/ws/git/staging.ts +2 -2
  40. package/backend/ws/git/status.ts +3 -3
  41. package/backend/ws/messages/crud.ts +1 -1
  42. package/backend/ws/preview/browser/cleanup.ts +2 -2
  43. package/backend/ws/preview/browser/console.ts +2 -2
  44. package/backend/ws/preview/browser/interact.ts +2 -2
  45. package/backend/ws/preview/browser/mcp.ts +1 -1
  46. package/backend/ws/preview/browser/native-ui.ts +2 -2
  47. package/backend/ws/preview/browser/stats.ts +2 -2
  48. package/backend/ws/preview/browser/tab-info.ts +2 -2
  49. package/backend/ws/preview/browser/tab.ts +2 -2
  50. package/backend/ws/preview/browser/webcodecs.ts +2 -2
  51. package/backend/ws/projects/crud.ts +3 -3
  52. package/backend/ws/projects/presence.ts +3 -3
  53. package/backend/ws/projects/status.ts +3 -3
  54. package/backend/ws/sessions/crud.ts +2 -2
  55. package/backend/ws/settings/crud.ts +2 -2
  56. package/backend/ws/snapshot/restore.ts +5 -5
  57. package/backend/ws/snapshot/timeline.ts +3 -3
  58. package/backend/ws/system/operations.ts +1 -1
  59. package/backend/ws/terminal/persistence.ts +3 -3
  60. package/backend/ws/terminal/session.ts +6 -6
  61. package/backend/ws/terminal/stream.ts +2 -2
  62. package/backend/ws/tunnel/operations.ts +1 -1
  63. package/backend/ws/user/crud.ts +4 -4
  64. package/frontend/App.svelte +13 -13
  65. package/frontend/{lib/components → components}/auth/InvitePage.svelte +2 -2
  66. package/frontend/{lib/components → components}/auth/LoginPage.svelte +1 -1
  67. package/frontend/{lib/components → components}/auth/SetupPage.svelte +6 -6
  68. package/frontend/{lib/components → components}/chat/ChatInterface.svelte +14 -14
  69. package/frontend/{lib/components → components}/chat/formatters/ErrorMessage.svelte +1 -1
  70. package/frontend/{lib/components → components}/chat/formatters/MessageFormatter.svelte +4 -4
  71. package/frontend/{lib/components → components}/chat/formatters/TextMessage.svelte +1 -1
  72. package/frontend/{lib/components → components}/chat/formatters/Tools.svelte +1 -1
  73. package/frontend/{lib/components → components}/chat/input/ChatInput.svelte +12 -12
  74. package/frontend/{lib/components → components}/chat/input/components/ChatInputActions.svelte +1 -1
  75. package/frontend/{lib/components → components}/chat/input/components/EditModeIndicator.svelte +2 -2
  76. package/frontend/{lib/components → components}/chat/input/components/EngineModelPicker.svelte +9 -9
  77. package/frontend/{lib/components → components}/chat/input/components/FileAttachmentPreview.svelte +1 -1
  78. package/frontend/{lib/components → components}/chat/input/components/LoadingIndicator.svelte +2 -2
  79. package/frontend/{lib/components → components}/chat/input/composables/use-chat-actions.svelte.ts +8 -8
  80. package/frontend/{lib/components → components}/chat/input/composables/use-file-handling.svelte.ts +1 -1
  81. package/frontend/{lib/components → components}/chat/input/composables/use-input-state.svelte.ts +6 -6
  82. package/frontend/{lib/components → components}/chat/message/ChatMessage.svelte +8 -8
  83. package/frontend/{lib/components → components}/chat/message/ChatMessages.svelte +7 -7
  84. package/frontend/{lib/components → components}/chat/message/MessageBubble.svelte +1 -1
  85. package/frontend/{lib/components → components}/chat/message/MessageHeader.svelte +2 -2
  86. package/frontend/{lib/components → components}/chat/modal/DebugModal.svelte +2 -2
  87. package/frontend/{lib/components → components}/chat/modal/TokenUsageModal.svelte +2 -2
  88. package/frontend/{lib/components → components}/chat/tools/AskUserQuestionTool.svelte +4 -4
  89. package/frontend/{lib/components → components}/chat/tools/CustomMcpTool.svelte +1 -1
  90. package/frontend/{lib/components → components}/chat/tools/EditTool.svelte +1 -1
  91. package/frontend/{lib/components → components}/chat/tools/TodoWriteTool.svelte +1 -1
  92. package/frontend/{lib/components → components}/chat/tools/components/CodeBlock.svelte +2 -2
  93. package/frontend/{lib/components → components}/chat/tools/components/DiffBlock.svelte +1 -1
  94. package/frontend/{lib/components → components}/chat/tools/components/FileHeader.svelte +2 -2
  95. package/frontend/{lib/components → components}/chat/tools/components/InfoLine.svelte +1 -1
  96. package/frontend/{lib/components → components}/chat/widgets/FloatingTodoList.svelte +3 -3
  97. package/frontend/{lib/components → components}/chat/widgets/TokenUsage.svelte +4 -4
  98. package/frontend/{lib/components → components}/checkpoint/TimelineModal.svelte +10 -10
  99. package/frontend/{lib/components → components}/checkpoint/timeline/TimelineNode.svelte +1 -1
  100. package/frontend/{lib/components/common → components/common/display}/Icon.svelte +2 -2
  101. package/frontend/{lib/components/common → components/common/display}/PageTemplate.svelte +1 -1
  102. package/frontend/{lib/components/common → components/common/display}/ProjectUserAvatars.svelte +1 -1
  103. package/frontend/{lib/components/common → components/common/display}/ThemeToggle.svelte +1 -1
  104. package/frontend/{lib/components/common → components/common/editor}/MonacoEditor.svelte +2 -2
  105. package/frontend/{lib/components/common → components/common/feedback}/Alert.svelte +1 -1
  106. package/frontend/{lib/components/common → components/common/feedback}/ConnectionBanner.svelte +3 -3
  107. package/frontend/{lib/components/common → components/common/feedback}/LoadingScreen.svelte +1 -1
  108. package/frontend/{lib/components/common → components/common/feedback}/NotificationToast.svelte +2 -2
  109. package/frontend/{lib/components/common → components/common/feedback}/UpdateBanner.svelte +3 -3
  110. package/frontend/{lib/components/common → components/common/form}/Checkbox.svelte +1 -1
  111. package/frontend/{lib/components/common → components/common/form}/FolderBrowser.svelte +6 -6
  112. package/frontend/{lib/components/common → components/common/form}/Input.svelte +1 -1
  113. package/frontend/{lib/components/common → components/common/form}/ModelSelector.svelte +3 -3
  114. package/frontend/{lib/components/common → components/common/form}/Select.svelte +1 -1
  115. package/frontend/{lib/components/common → components/common/form}/Textarea.svelte +1 -1
  116. package/frontend/{lib/components/common → components/common/overlay}/Dialog.svelte +1 -1
  117. package/frontend/{lib/components/common → components/common/overlay}/Lightbox.svelte +3 -3
  118. package/frontend/{lib/components/common → components/common/overlay}/ModalProvider.svelte +2 -2
  119. package/frontend/{lib/components → components}/common/xterm/XTerm.svelte +5 -5
  120. package/frontend/{lib/components → components}/common/xterm/xterm-service.ts +2 -2
  121. package/frontend/{lib/components → components}/files/FileNode.svelte +3 -3
  122. package/frontend/{lib/components → components}/files/FileTree.svelte +5 -5
  123. package/frontend/{lib/components → components}/files/FileViewer.svelte +7 -7
  124. package/frontend/{lib/components → components}/files/SearchResults.svelte +3 -3
  125. package/frontend/{lib/components → components}/git/BranchManager.svelte +6 -6
  126. package/frontend/{lib/components → components}/git/ChangesSection.svelte +1 -1
  127. package/frontend/{lib/components → components}/git/CommitForm.svelte +1 -1
  128. package/frontend/{lib/components → components}/git/ConflictResolver.svelte +1 -1
  129. package/frontend/{lib/components → components}/git/DiffViewer.svelte +7 -7
  130. package/frontend/{lib/components → components}/git/FileChangeItem.svelte +3 -3
  131. package/frontend/{lib/components → components}/git/GitButton.svelte +1 -1
  132. package/frontend/{lib/components → components}/git/GitLog.svelte +2 -2
  133. package/frontend/{lib/components → components}/git/GitModal.svelte +3 -3
  134. package/frontend/{lib/components → components}/history/HistoryModal.svelte +11 -11
  135. package/frontend/{lib/components → components}/history/HistoryView.svelte +12 -12
  136. package/frontend/{lib/components → components}/index.ts +9 -9
  137. package/frontend/{lib/components → components}/preview/browser/BrowserPreview.svelte +3 -3
  138. package/frontend/{lib/components → components}/preview/browser/components/Canvas.svelte +2 -2
  139. package/frontend/{lib/components → components}/preview/browser/components/ConsolePanel.svelte +1 -1
  140. package/frontend/{lib/components → components}/preview/browser/components/Container.svelte +2 -2
  141. package/frontend/{lib/components → components}/preview/browser/components/ContextMenu.svelte +1 -1
  142. package/frontend/{lib/components → components}/preview/browser/components/SelectDropdown.svelte +1 -1
  143. package/frontend/{lib/components → components}/preview/browser/components/Toolbar.svelte +2 -2
  144. package/frontend/{lib/components → components}/preview/browser/core/cleanup.svelte.ts +1 -1
  145. package/frontend/{lib/components → components}/preview/browser/core/coordinator.svelte.ts +4 -4
  146. package/frontend/{lib/components → components}/preview/browser/core/interactions.svelte.ts +3 -3
  147. package/frontend/{lib/components → components}/preview/browser/core/mcp-handlers.svelte.ts +2 -2
  148. package/frontend/{lib/components → components}/preview/browser/core/native-ui-handlers.svelte.ts +2 -2
  149. package/frontend/{lib/components → components}/preview/browser/core/tab-manager.svelte.ts +1 -1
  150. package/frontend/{lib/components → components}/preview/browser/core/tab-operations.svelte.ts +3 -3
  151. package/frontend/{lib/components → components}/settings/SettingsModal.svelte +4 -4
  152. package/frontend/{lib/components → components}/settings/SettingsView.svelte +2 -2
  153. package/frontend/{lib/components → components}/settings/admin/InviteManagement.svelte +5 -5
  154. package/frontend/{lib/components → components}/settings/admin/UserManagement.svelte +5 -5
  155. package/frontend/{lib/components → components}/settings/appearance/AppearanceSettings.svelte +3 -3
  156. package/frontend/{lib/components → components}/settings/appearance/LayoutPresetSettings.svelte +3 -3
  157. package/frontend/{lib/components → components}/settings/appearance/LayoutPreview.svelte +1 -1
  158. package/frontend/{lib/components → components}/settings/engines/AIEnginesSettings.svelte +6 -6
  159. package/frontend/{lib/components → components}/settings/general/AdvancedSettings.svelte +5 -5
  160. package/frontend/{lib/components → components}/settings/general/AuthModeSettings.svelte +5 -5
  161. package/frontend/{lib/components → components}/settings/general/DataManagementSettings.svelte +9 -9
  162. package/frontend/{lib/components → components}/settings/general/UpdateSettings.svelte +3 -3
  163. package/frontend/{lib/components → components}/settings/model/ModelSettings.svelte +2 -2
  164. package/frontend/{lib/components → components}/settings/notifications/NotificationSettings.svelte +4 -4
  165. package/frontend/{lib/components → components}/settings/user/UserSettings.svelte +5 -5
  166. package/frontend/{lib/components → components}/terminal/Terminal.svelte +9 -9
  167. package/frontend/{lib/components → components}/terminal/TerminalTabs.svelte +1 -1
  168. package/frontend/{lib/components → components}/terminal/TerminalView.svelte +5 -5
  169. package/frontend/{lib/components → components}/tunnel/TunnelActive.svelte +3 -3
  170. package/frontend/{lib/components → components}/tunnel/TunnelButton.svelte +2 -2
  171. package/frontend/{lib/components → components}/tunnel/TunnelInactive.svelte +4 -4
  172. package/frontend/{lib/components → components}/tunnel/TunnelModal.svelte +2 -2
  173. package/frontend/{lib/components → components}/workspace/DesktopNavigator.svelte +372 -372
  174. package/frontend/{lib/components → components}/workspace/MobileNavigator.svelte +380 -380
  175. package/frontend/{lib/components → components}/workspace/PanelContainer.svelte +3 -3
  176. package/frontend/{lib/components → components}/workspace/PanelHeader.svelte +10 -10
  177. package/frontend/{lib/components → components}/workspace/ViewMenu.svelte +4 -4
  178. package/frontend/{lib/components → components}/workspace/WorkspaceLayout.svelte +17 -17
  179. package/frontend/{lib/components → components}/workspace/layout/DesktopLayout.svelte +1 -1
  180. package/frontend/{lib/components → components}/workspace/layout/MobileLayout.svelte +1 -1
  181. package/frontend/{lib/components → components}/workspace/layout/split-pane/Container.svelte +1 -1
  182. package/frontend/{lib/components → components}/workspace/layout/split-pane/Handle.svelte +2 -2
  183. package/frontend/{lib/components → components}/workspace/layout/split-pane/Layout.svelte +2 -2
  184. package/frontend/{lib/components → components}/workspace/panels/ChatPanel.svelte +14 -14
  185. package/frontend/{lib/components → components}/workspace/panels/FilesPanel.svelte +10 -10
  186. package/frontend/{lib/components → components}/workspace/panels/GitPanel.svelte +14 -14
  187. package/frontend/{lib/components → components}/workspace/panels/PreviewPanel.svelte +5 -5
  188. package/frontend/{lib/components → components}/workspace/panels/TerminalPanel.svelte +6 -6
  189. package/frontend/{lib/services → services}/chat/chat.service.ts +8 -8
  190. package/frontend/{lib/services → services}/notification/global-stream-monitor.ts +117 -117
  191. package/frontend/{lib/services → services}/notification/push.service.ts +1 -1
  192. package/frontend/{lib/services → services}/notification/sound.service.ts +1 -1
  193. package/frontend/{lib/services → services}/preview/browser/browser-console.service.ts +1 -1
  194. package/frontend/{lib/services → services}/preview/browser/browser-webcodecs.service.ts +1 -1
  195. package/frontend/{lib/services → services}/preview/browser/mcp-integration.svelte.ts +2 -2
  196. package/frontend/{lib/services → services}/project/status.service.ts +160 -160
  197. package/frontend/{lib/services → services}/snapshot/snapshot.service.ts +2 -2
  198. package/frontend/{lib/services → services}/terminal/background/index.ts +1 -1
  199. package/frontend/{lib/services → services}/terminal/background/session-restore.ts +1 -1
  200. package/frontend/{lib/services → services}/terminal/background/stream-manager.ts +1 -1
  201. package/frontend/{lib/services → services}/terminal/project.service.ts +2 -2
  202. package/frontend/{lib/services → services}/terminal/terminal.service.ts +2 -2
  203. package/frontend/{lib/stores → stores}/core/app.svelte.ts +1 -1
  204. package/frontend/{lib/stores → stores}/core/presence.svelte.ts +4 -4
  205. package/frontend/{lib/stores → stores}/core/projects.svelte.ts +5 -5
  206. package/frontend/{lib/stores → stores}/core/sessions.svelte.ts +3 -3
  207. package/frontend/{lib/stores → stores}/features/auth.svelte.ts +2 -2
  208. package/frontend/{lib/stores → stores}/features/claude-accounts.svelte.ts +1 -1
  209. package/frontend/{lib/stores → stores}/features/models.svelte.ts +1 -1
  210. package/frontend/{lib/stores → stores}/features/settings.svelte.ts +2 -2
  211. package/frontend/{lib/stores → stores}/features/terminal.svelte.ts +4 -4
  212. package/frontend/{lib/stores → stores}/features/tunnel.svelte.ts +1 -1
  213. package/frontend/{lib/stores → stores}/features/user.svelte.ts +1 -1
  214. package/frontend/{lib/stores → stores}/ui/edit-mode.svelte.ts +3 -3
  215. package/frontend/{lib/stores → stores}/ui/update.svelte.ts +2 -2
  216. package/frontend/{lib/utils → utils}/theme.ts +1 -1
  217. package/frontend/{lib/utils → utils}/ws.ts +1 -1
  218. package/package.json +1 -1
  219. package/scripts/dev.ts +1 -1
  220. package/scripts/generate-icons.ts +2 -2
  221. package/shared/types/ui/icons.ts +4 -4
  222. package/shared/utils/anonymous-user.ts +1 -1
  223. package/shared/utils/ws-server.ts +3 -3
  224. /package/backend/{lib/auth → auth}/index.ts +0 -0
  225. /package/backend/{lib/auth → auth}/permissions.ts +0 -0
  226. /package/backend/{lib/auth → auth}/rate-limiter.ts +0 -0
  227. /package/backend/{lib/auth → auth}/tokens.ts +0 -0
  228. /package/backend/{lib/chat → chat}/helpers.ts +0 -0
  229. /package/backend/{lib/chat → chat}/index.ts +0 -0
  230. /package/backend/{lib/database → database}/README.md +0 -0
  231. /package/backend/{lib/database → database}/index.ts +0 -0
  232. /package/backend/{lib/database → database}/migrations/001_create_projects_table.ts +0 -0
  233. /package/backend/{lib/database → database}/migrations/002_create_chat_sessions_table.ts +0 -0
  234. /package/backend/{lib/database → database}/migrations/003_create_messages_table.ts +0 -0
  235. /package/backend/{lib/database → database}/migrations/004_create_prompt_templates_table.ts +0 -0
  236. /package/backend/{lib/database → database}/migrations/005_create_settings_table.ts +0 -0
  237. /package/backend/{lib/database → database}/migrations/006_add_user_to_messages.ts +0 -0
  238. /package/backend/{lib/database → database}/migrations/007_create_stream_states_table.ts +0 -0
  239. /package/backend/{lib/database → database}/migrations/008_create_message_snapshots_table.ts +0 -0
  240. /package/backend/{lib/database → database}/migrations/009_add_delta_snapshot_fields.ts +0 -0
  241. /package/backend/{lib/database → database}/migrations/010_add_soft_delete_and_branch_support.ts +0 -0
  242. /package/backend/{lib/database → database}/migrations/011_git_like_commit_graph.ts +0 -0
  243. /package/backend/{lib/database → database}/migrations/012_add_file_change_statistics.ts +0 -0
  244. /package/backend/{lib/database → database}/migrations/013_checkpoint_tree_state.ts +0 -0
  245. /package/backend/{lib/database → database}/migrations/014_add_engine_to_sessions.ts +0 -0
  246. /package/backend/{lib/database → database}/migrations/015_add_model_to_sessions.ts +0 -0
  247. /package/backend/{lib/database → database}/migrations/016_create_user_projects_table.ts +0 -0
  248. /package/backend/{lib/database → database}/migrations/017_add_current_session_to_user_projects.ts +0 -0
  249. /package/backend/{lib/database → database}/migrations/018_create_claude_accounts_table.ts +0 -0
  250. /package/backend/{lib/database → database}/migrations/019_add_claude_account_to_sessions.ts +0 -0
  251. /package/backend/{lib/database → database}/migrations/020_add_snapshot_tree_hash.ts +0 -0
  252. /package/backend/{lib/database → database}/migrations/021_drop_prompt_templates_table.ts +0 -0
  253. /package/backend/{lib/database → database}/migrations/022_add_snapshot_changes_column.ts +0 -0
  254. /package/backend/{lib/database → database}/migrations/023_create_user_unread_sessions_table.ts +0 -0
  255. /package/backend/{lib/database → database}/migrations/024_create_users_table.ts +0 -0
  256. /package/backend/{lib/database → database}/migrations/025_create_auth_sessions_table.ts +0 -0
  257. /package/backend/{lib/database → database}/migrations/026_create_invite_tokens_table.ts +0 -0
  258. /package/backend/{lib/database → database}/migrations/index.ts +0 -0
  259. /package/backend/{lib/database → database}/queries/auth-queries.ts +0 -0
  260. /package/backend/{lib/database → database}/queries/checkpoint-queries.ts +0 -0
  261. /package/backend/{lib/database → database}/queries/engine-queries.ts +0 -0
  262. /package/backend/{lib/database → database}/queries/index.ts +0 -0
  263. /package/backend/{lib/database → database}/queries/message-queries.ts +0 -0
  264. /package/backend/{lib/database → database}/queries/project-queries.ts +0 -0
  265. /package/backend/{lib/database → database}/queries/session-queries.ts +0 -0
  266. /package/backend/{lib/database → database}/queries/settings-queries.ts +0 -0
  267. /package/backend/{lib/database → database}/queries/snapshot-queries.ts +0 -0
  268. /package/backend/{lib/database → database}/queries/utils-queries.ts +0 -0
  269. /package/backend/{lib/database → database}/seeders/index.ts +0 -0
  270. /package/backend/{lib/database → database}/seeders/settings_seeder.ts +0 -0
  271. /package/backend/{lib/database → database}/utils/connection.ts +0 -0
  272. /package/backend/{lib/database → database}/utils/index.ts +0 -0
  273. /package/backend/{lib/database → database}/utils/migration-runner.ts +0 -0
  274. /package/backend/{lib/database → database}/utils/seeder-runner.ts +0 -0
  275. /package/backend/{lib/engine → engine}/adapters/claude/error-handler.ts +0 -0
  276. /package/backend/{lib/engine → engine}/adapters/claude/index.ts +0 -0
  277. /package/backend/{lib/engine → engine}/adapters/claude/path-utils.ts +0 -0
  278. /package/backend/{lib/engine → engine}/adapters/claude/stream.ts +0 -0
  279. /package/backend/{lib/engine → engine}/adapters/opencode/index.ts +0 -0
  280. /package/backend/{lib/engine → engine}/adapters/opencode/server.ts +0 -0
  281. /package/backend/{lib/engine → engine}/adapters/opencode/stream.ts +0 -0
  282. /package/backend/{lib/engine → engine}/index.ts +0 -0
  283. /package/backend/{lib/engine → engine}/types.ts +0 -0
  284. /package/backend/{lib/files → files}/file-operations.ts +0 -0
  285. /package/backend/{lib/files → files}/file-reading.ts +0 -0
  286. /package/backend/{lib/files → files}/path-browsing.ts +0 -0
  287. /package/backend/{lib/git → git}/git-parser.ts +0 -0
  288. /package/backend/{lib/git → git}/git-service.ts +0 -0
  289. /package/backend/{lib/mcp → mcp}/index.ts +0 -0
  290. /package/backend/{lib/mcp → mcp}/project-context.ts +0 -0
  291. /package/backend/{lib/mcp → mcp}/remote-server.ts +0 -0
  292. /package/backend/{lib/mcp → mcp}/servers/browser-automation/index.ts +0 -0
  293. /package/backend/{lib/mcp → mcp}/servers/helper.ts +0 -0
  294. /package/backend/{lib/mcp → mcp}/servers/index.ts +0 -0
  295. /package/backend/{lib/mcp → mcp}/servers/weather/get-temperature.ts +0 -0
  296. /package/backend/{lib/mcp → mcp}/servers/weather/index.ts +0 -0
  297. /package/backend/{lib/mcp → mcp}/types.ts +0 -0
  298. /package/backend/{lib/preview → preview}/browser/browser-audio-capture.ts +0 -0
  299. /package/backend/{lib/preview → preview}/browser/browser-console-manager.ts +0 -0
  300. /package/backend/{lib/preview → preview}/browser/browser-dialog-handler.ts +0 -0
  301. /package/backend/{lib/preview → preview}/browser/browser-interaction-handler.ts +0 -0
  302. /package/backend/{lib/preview → preview}/browser/browser-mcp-control.ts +0 -0
  303. /package/backend/{lib/preview → preview}/browser/browser-native-ui-handler.ts +0 -0
  304. /package/backend/{lib/preview → preview}/browser/browser-navigation-tracker.ts +0 -0
  305. /package/backend/{lib/preview → preview}/browser/browser-pool.ts +0 -0
  306. /package/backend/{lib/preview → preview}/browser/browser-video-capture.ts +0 -0
  307. /package/backend/{lib/preview → preview}/browser/scripts/audio-stream.ts +0 -0
  308. /package/backend/{lib/preview → preview}/browser/scripts/cursor-tracking.ts +0 -0
  309. /package/backend/{lib/preview → preview}/browser/scripts/video-stream.ts +0 -0
  310. /package/backend/{lib/preview → preview}/index.ts +0 -0
  311. /package/backend/{lib/project → project}/index.ts +0 -0
  312. /package/backend/{lib/snapshot → snapshot}/blob-store.ts +0 -0
  313. /package/backend/{lib/snapshot → snapshot}/gitignore.ts +0 -0
  314. /package/backend/{lib/snapshot → snapshot}/helpers.ts +0 -0
  315. /package/backend/{lib/snapshot → snapshot}/snapshot-service.ts +0 -0
  316. /package/backend/{lib/terminal → terminal}/helpers.ts +0 -0
  317. /package/backend/{lib/terminal → terminal}/index.ts +0 -0
  318. /package/backend/{lib/terminal → terminal}/pty-manager.ts +0 -0
  319. /package/backend/{lib/terminal → terminal}/pty-session-manager.ts +0 -0
  320. /package/backend/{lib/terminal → terminal}/stream-manager.ts +0 -0
  321. /package/backend/{lib/tunnel → tunnel}/global-tunnel-manager.ts +0 -0
  322. /package/backend/{lib/tunnel → tunnel}/project-tunnel-manager.ts +0 -0
  323. /package/backend/{lib/shared → utils}/env.ts +0 -0
  324. /package/backend/{lib/shared → utils}/index.ts +0 -0
  325. /package/backend/{lib/shared → utils}/port-utils.ts +0 -0
  326. /package/backend/{lib/shared → utils}/process-manager.ts +0 -0
  327. /package/backend/{lib/user/helpers.ts → utils/user-helpers.ts} +0 -0
  328. /package/frontend/{lib/app-environment.ts → app-environment.ts} +0 -0
  329. /package/frontend/{lib/components → components}/chat/formatters/index.ts +0 -0
  330. /package/frontend/{lib/components → components}/chat/input/components/DragDropOverlay.svelte +0 -0
  331. /package/frontend/{lib/components → components}/chat/input/composables/use-animations.svelte.ts +0 -0
  332. /package/frontend/{lib/components → components}/chat/input/composables/use-textarea-resize.svelte.ts +0 -0
  333. /package/frontend/{lib/components → components}/chat/message/DateSeparator.svelte +0 -0
  334. /package/frontend/{lib/components → components}/chat/shared/index.ts +0 -0
  335. /package/frontend/{lib/components → components}/chat/shared/utils.ts +0 -0
  336. /package/frontend/{lib/components → components}/chat/tools/AgentTool.svelte +0 -0
  337. /package/frontend/{lib/components → components}/chat/tools/BashOutputTool.svelte +0 -0
  338. /package/frontend/{lib/components → components}/chat/tools/BashTool.svelte +0 -0
  339. /package/frontend/{lib/components → components}/chat/tools/EnterPlanModeTool.svelte +0 -0
  340. /package/frontend/{lib/components → components}/chat/tools/ExitPlanModeTool.svelte +0 -0
  341. /package/frontend/{lib/components → components}/chat/tools/GlobTool.svelte +0 -0
  342. /package/frontend/{lib/components → components}/chat/tools/GrepTool.svelte +0 -0
  343. /package/frontend/{lib/components → components}/chat/tools/ListMcpResourcesTool.svelte +0 -0
  344. /package/frontend/{lib/components → components}/chat/tools/NotebookEditTool.svelte +0 -0
  345. /package/frontend/{lib/components → components}/chat/tools/ReadMcpResourceTool.svelte +0 -0
  346. /package/frontend/{lib/components → components}/chat/tools/ReadTool.svelte +0 -0
  347. /package/frontend/{lib/components → components}/chat/tools/TaskStopTool.svelte +0 -0
  348. /package/frontend/{lib/components → components}/chat/tools/TaskTool.svelte +0 -0
  349. /package/frontend/{lib/components → components}/chat/tools/WebFetchTool.svelte +0 -0
  350. /package/frontend/{lib/components → components}/chat/tools/WebSearchTool.svelte +0 -0
  351. /package/frontend/{lib/components → components}/chat/tools/WriteTool.svelte +0 -0
  352. /package/frontend/{lib/components → components}/chat/tools/components/StatsBadges.svelte +0 -0
  353. /package/frontend/{lib/components → components}/chat/tools/components/TerminalCommand.svelte +0 -0
  354. /package/frontend/{lib/components → components}/chat/tools/components/index.ts +0 -0
  355. /package/frontend/{lib/components → components}/chat/tools/index.ts +0 -0
  356. /package/frontend/{lib/components → components}/checkpoint/timeline/TimelineEdge.svelte +0 -0
  357. /package/frontend/{lib/components → components}/checkpoint/timeline/TimelineGraph.svelte +0 -0
  358. /package/frontend/{lib/components → components}/checkpoint/timeline/TimelineVersionGroup.svelte +0 -0
  359. /package/frontend/{lib/components → components}/checkpoint/timeline/animation.ts +0 -0
  360. /package/frontend/{lib/components → components}/checkpoint/timeline/config.ts +0 -0
  361. /package/frontend/{lib/components → components}/checkpoint/timeline/graph-builder.ts +0 -0
  362. /package/frontend/{lib/components → components}/checkpoint/timeline/types.ts +0 -0
  363. /package/frontend/{lib/components → components}/checkpoint/timeline/utils.ts +0 -0
  364. /package/frontend/{lib/components/common → components/common/display}/AvatarBubble.svelte +0 -0
  365. /package/frontend/{lib/components/common → components/common/display}/Button.svelte +0 -0
  366. /package/frontend/{lib/components/common → components/common/display}/Card.svelte +0 -0
  367. /package/frontend/{lib/components/common → components/common/feedback}/LoadingSpinner.svelte +0 -0
  368. /package/frontend/{lib/components → components}/common/lucide-icons.ts +0 -0
  369. /package/frontend/{lib/components → components}/common/material-icons.ts +0 -0
  370. /package/frontend/{lib/components/common → components/common/overlay}/Modal.svelte +0 -0
  371. /package/frontend/{lib/components → components}/common/xterm/index.ts +0 -0
  372. /package/frontend/{lib/components → components}/common/xterm/terminal-config.ts +0 -0
  373. /package/frontend/{lib/components → components}/common/xterm/types.ts +0 -0
  374. /package/frontend/{lib/components → components}/preview/browser/components/VirtualCursor.svelte +0 -0
  375. /package/frontend/{lib/components → components}/preview/browser/core/stream-handler.svelte.ts +0 -0
  376. /package/frontend/{lib/components → components}/preview/index.ts +0 -0
  377. /package/frontend/{lib/components → components}/settings/account/AccountSettings.svelte +0 -0
  378. /package/frontend/{lib/components → components}/settings/general/GeneralSettings.svelte +0 -0
  379. /package/frontend/{lib/components → components}/settings/security/SecuritySettings.svelte +0 -0
  380. /package/frontend/{lib/components → components}/settings/system/SystemSettings.svelte +0 -0
  381. /package/frontend/{lib/components → components}/tunnel/TunnelQRCode.svelte +0 -0
  382. /package/frontend/{lib/services → services}/chat/index.ts +0 -0
  383. /package/frontend/{lib/services → services}/notification/index.ts +0 -0
  384. /package/frontend/{lib/services → services}/preview/index.ts +0 -0
  385. /package/frontend/{lib/services → services}/project/index.ts +0 -0
  386. /package/frontend/{lib/services → services}/terminal/index.ts +0 -0
  387. /package/frontend/{lib/services → services}/terminal/persistence.service.ts +0 -0
  388. /package/frontend/{lib/services → services}/terminal/session.service.ts +0 -0
  389. /package/frontend/{lib/stores → stores}/core/files.svelte.ts +0 -0
  390. /package/frontend/{lib/stores → stores}/ui/chat-input.svelte.ts +0 -0
  391. /package/frontend/{lib/stores → stores}/ui/chat-model.svelte.ts +0 -0
  392. /package/frontend/{lib/stores → stores}/ui/connection.svelte.ts +0 -0
  393. /package/frontend/{lib/stores → stores}/ui/dialog.svelte.ts +0 -0
  394. /package/frontend/{lib/stores → stores}/ui/notification.svelte.ts +0 -0
  395. /package/frontend/{lib/stores → stores}/ui/settings-modal.svelte.ts +0 -0
  396. /package/frontend/{lib/stores → stores}/ui/theme.svelte.ts +0 -0
  397. /package/frontend/{lib/stores → stores}/ui/workspace.svelte.ts +0 -0
  398. /package/frontend/{lib/utils → utils}/chat/date-separator.ts +0 -0
  399. /package/frontend/{lib/utils → utils}/chat/message-grouper.ts +0 -0
  400. /package/frontend/{lib/utils → utils}/chat/message-processor.ts +0 -0
  401. /package/frontend/{lib/utils → utils}/chat/tool-handler.ts +0 -0
  402. /package/frontend/{lib/utils → utils}/chat/virtual-scroll.svelte.ts +0 -0
  403. /package/frontend/{lib/utils → utils}/click-outside.ts +0 -0
  404. /package/frontend/{lib/utils → utils}/context-manager.ts +0 -0
  405. /package/frontend/{lib/utils → utils}/file-icon-mappings.ts +0 -0
  406. /package/frontend/{lib/utils → utils}/folder-icon-mappings.ts +0 -0
  407. /package/frontend/{lib/utils → utils}/git-status.ts +0 -0
  408. /package/frontend/{lib/types → utils}/native-ui.ts +0 -0
  409. /package/frontend/{lib/utils → utils}/platform.ts +0 -0
  410. /package/frontend/{lib/utils → utils}/port-check.ts +0 -0
  411. /package/frontend/{lib/constants/preview.ts → utils/preview-constants.ts} +0 -0
  412. /package/frontend/{lib/utils/terminalFormatter.ts → utils/terminal-formatter.ts} +0 -0
  413. /package/frontend/{lib/utils → utils}/tree-visualizer.ts +0 -0
@@ -1,380 +1,380 @@
1
- <script lang="ts">
2
- import Icon from '$frontend/lib/components/common/Icon.svelte';
3
- import Modal from '$frontend/lib/components/common/Modal.svelte';
4
- import Dialog from '$frontend/lib/components/common/Dialog.svelte';
5
- import {
6
- workspaceState,
7
- setActiveMobilePanel,
8
- type PanelId
9
- } from '$frontend/lib/stores/ui/workspace.svelte';
10
- import { projectState, removeProject } from '$frontend/lib/stores/core/projects.svelte';
11
- import { presenceState, getProjectStatusColor } from '$frontend/lib/stores/core/presence.svelte';
12
- import { openSettingsModal } from '$frontend/lib/stores/ui/settings-modal.svelte';
13
- import { addNotification } from '$frontend/lib/stores/ui/notification.svelte';
14
- import type { IconName } from '$shared/types/ui/icons';
15
- import TunnelButton from '$frontend/lib/components/tunnel/TunnelButton.svelte';
16
- import TunnelModal from '$frontend/lib/components/tunnel/TunnelModal.svelte';
17
- import type { Project } from '$shared/types/database/schema';
18
- import FolderBrowser from '$frontend/lib/components/common/FolderBrowser.svelte';
19
- import ProjectUserAvatars from '$frontend/lib/components/common/ProjectUserAvatars.svelte';
20
- import ws from '$frontend/lib/utils/ws';
21
- import { debug } from '$shared/utils/logger';
22
-
23
- // Modal states
24
- let showTunnelModal = $state(false);
25
-
26
- // Project dropdown state
27
- let showProjectMenu = $state(false);
28
- let showFolderBrowser = $state(false);
29
- let showDeleteDialog = $state(false);
30
- let projectToDelete = $state<Project | null>(null);
31
- let searchQuery = $state('');
32
-
33
- // Get current project status from shared store
34
- const currentProjectStatus = $derived(
35
- projectState.currentProject?.id
36
- ? presenceState.statuses.get(projectState.currentProject.id)
37
- : undefined
38
- );
39
-
40
- const panels: { id: PanelId; icon: IconName; label: string }[] = [
41
- { id: 'chat', icon: 'lucide:bot', label: 'AI' },
42
- { id: 'files', icon: 'lucide:folder', label: 'Files' },
43
- { id: 'git', icon: 'lucide:git-branch', label: 'Source Control' },
44
- { id: 'terminal', icon: 'lucide:terminal', label: 'Terminal' },
45
- { id: 'preview', icon: 'lucide:globe', label: 'Preview' }
46
- ];
47
-
48
- // Filtered projects based on search query
49
- const filteredProjects = $derived(() => {
50
- if (!searchQuery.trim()) return projectState.projects;
51
- const query = searchQuery.toLowerCase();
52
- return projectState.projects.filter(
53
- (p) => p.name.toLowerCase().includes(query) || p.path.toLowerCase().includes(query)
54
- );
55
- });
56
-
57
- function selectPanel(panelId: PanelId) {
58
- setActiveMobilePanel(panelId);
59
- }
60
-
61
- function toggleProjectMenu() {
62
- showProjectMenu = !showProjectMenu;
63
- if (!showProjectMenu) {
64
- searchQuery = '';
65
- }
66
- }
67
-
68
- // Status color for project indicator — uses shared helper from presence store
69
-
70
- function openAddProject() {
71
- showProjectMenu = false;
72
- showFolderBrowser = true;
73
- }
74
-
75
- function closeFolderBrowser() {
76
- showFolderBrowser = false;
77
- }
78
-
79
- function closeProjectMenu() {
80
- showProjectMenu = false;
81
- searchQuery = '';
82
- }
83
-
84
- function handleDeleteClick(project: Project, event: MouseEvent) {
85
- event.stopPropagation();
86
- projectToDelete = project;
87
- showDeleteDialog = true;
88
- }
89
-
90
- async function confirmDeleteProject() {
91
- if (!projectToDelete) return;
92
- const deleteId = projectToDelete.id!;
93
-
94
- try {
95
- await ws.http('projects:delete', { id: deleteId });
96
- removeProject(deleteId);
97
- showDeleteDialog = false;
98
- projectToDelete = null;
99
- } catch (error) {
100
- debug.error('workspace', 'Failed to delete project:', error);
101
- addNotification({
102
- type: 'error',
103
- title: 'Error',
104
- message: 'Failed to delete project',
105
- duration: 5000
106
- });
107
- }
108
- }
109
-
110
- function closeDeleteDialog() {
111
- showDeleteDialog = false;
112
- projectToDelete = null;
113
- }
114
-
115
- async function createProjectFromFolder(folderPath: string, folderName: string) {
116
- try {
117
- showFolderBrowser = false;
118
-
119
- const projects = await ws.http('projects:list', {});
120
-
121
- const existingProject = projects
122
- ? projects.find((p: any) => p.path === folderPath)
123
- : null;
124
-
125
- if (existingProject) {
126
- const { setCurrentProject } = await import('$frontend/lib/stores/core/projects.svelte');
127
- setCurrentProject(existingProject);
128
- return;
129
- }
130
-
131
- const newProject = await ws.http('projects:create', { name: folderName, path: folderPath });
132
-
133
- if (newProject) {
134
- const { setCurrentProject } = await import('$frontend/lib/stores/core/projects.svelte');
135
- setCurrentProject(newProject);
136
- }
137
- } catch (error) {
138
- console.error('Failed to create project:', error);
139
- }
140
- }
141
- </script>
142
-
143
- <header
144
- class="flex items-center bg-white/90 dark:bg-slate-900/98 py-2 px-3 gap-2 relative z-30"
145
- >
146
- <!-- Project Selector -->
147
- <button
148
- type="button"
149
- class="flex items-center gap-2 px-3 py-2.5 bg-slate-100/80 dark:bg-slate-800/80 border border-slate-200 dark:border-slate-800 rounded-lg text-slate-900 dark:text-slate-100 text-sm font-medium cursor-pointer transition-all duration-150 flex-1 min-w-0 active:bg-violet-500/10"
150
- onclick={toggleProjectMenu}
151
- aria-expanded={showProjectMenu}
152
- aria-haspopup="menu"
153
- >
154
- <div class="relative shrink-0"><Icon name="lucide:folder-open" class="w-4 h-4" /><span class="absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-slate-100 dark:border-slate-800 {getProjectStatusColor(projectState.currentProject?.id ?? '')}"></span></div>
155
- <span class="flex-1 text-left overflow-hidden text-ellipsis whitespace-nowrap">
156
- {projectState.currentProject?.name ?? 'No Project'}
157
- </span>
158
- <div class="shrink-0" onclick={(e) => e.stopPropagation()}>
159
- <ProjectUserAvatars projectStatus={currentProjectStatus} maxVisible={2} />
160
- </div>
161
- <Icon name="lucide:chevron-down" class="w-3 h-3 opacity-60 shrink-0" />
162
- </button>
163
-
164
- <!-- Panel Tabs (Icon Only) -->
165
- <div
166
- class="flex gap-1 bg-slate-100/80 dark:bg-slate-800/50 p-1 border border-slate-200 dark:border-slate-800 rounded-lg"
167
- role="tablist"
168
- aria-label="Panel Tabs"
169
- >
170
- {#each panels as panel}
171
- <button
172
- type="button"
173
- class="flex items-center justify-center w-9 h-8 bg-transparent border-none rounded-md text-slate-500 cursor-pointer transition-all duration-150
174
- {workspaceState.activeMobilePanel === panel.id
175
- ? 'bg-violet-500/10 dark:bg-violet-500/20 text-slate-900 dark:text-slate-100 shadow-violet-500/20'
176
- : 'active:bg-violet-500/10'}"
177
- role="tab"
178
- aria-selected={workspaceState.activeMobilePanel === panel.id}
179
- aria-controls={`panel-${panel.id}`}
180
- aria-label={panel.label}
181
- title={panel.label}
182
- onclick={() => selectPanel(panel.id)}
183
- >
184
- <Icon name={panel.icon} class="w-5 h-5" />
185
- </button>
186
- {/each}
187
- </div>
188
-
189
- <!-- Action Buttons -->
190
- <div
191
- class="flex gap-1 bg-slate-100/80 dark:bg-slate-800/50 p-1 border border-slate-200 dark:border-slate-800 rounded-lg"
192
- role="tablist"
193
- aria-label="Action Buttons"
194
- >
195
- <!-- Tunnel Button -->
196
- <TunnelButton collapsed={true} onClick={() => (showTunnelModal = true)} mobile={true} />
197
-
198
- <!-- Settings Button -->
199
- <button
200
- type="button"
201
- class="flex items-center justify-center w-9 h-8 bg-transparent border-none rounded-md text-slate-500 cursor-pointer transition-all duration-150 active:bg-violet-500/10"
202
- role="tab"
203
- onclick={() => openSettingsModal()}
204
- aria-label="Settings"
205
- title="Settings"
206
- >
207
- <Icon name="lucide:settings" class="w-5 h-5" />
208
- </button>
209
- </div>
210
- </header>
211
-
212
- <!-- Project Selection Modal -->
213
- <Modal bind:isOpen={showProjectMenu} onClose={closeProjectMenu} size="md">
214
- {#snippet header()}
215
- <div class="flex items-center justify-between px-4 py-3 md:px-6 md:py-4">
216
- <h2 class="text-base md:text-lg font-bold text-slate-900 dark:text-slate-100">Projects</h2>
217
- <div class="flex items-center gap-2">
218
- <button
219
- type="button"
220
- class="flex items-center justify-center w-8 h-8 bg-violet-500/10 dark:bg-violet-500/15 border border-violet-500/20 rounded-lg text-violet-600 dark:text-violet-400 cursor-pointer transition-all duration-150 hover:bg-violet-500/20"
221
- onclick={openAddProject}
222
- aria-label="Add project"
223
- title="Add project"
224
- >
225
- <Icon name="lucide:plus" class="w-4 h-4" />
226
- </button>
227
- <button
228
- type="button"
229
- class="p-1.5 md:p-2 rounded-lg text-slate-500 hover:text-slate-900 dark:hover:text-slate-100 hover:bg-violet-500/10 transition-colors"
230
- onclick={closeProjectMenu}
231
- aria-label="Close modal"
232
- >
233
- <svg class="w-4 h-4 md:w-5 md:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
234
- <path
235
- stroke-linecap="round"
236
- stroke-linejoin="round"
237
- stroke-width="2"
238
- d="M6 18L18 6M6 6l12 12"
239
- />
240
- </svg>
241
- </button>
242
- </div>
243
- </div>
244
- {/snippet}
245
-
246
- {#snippet children()}
247
- <!-- Search Box -->
248
- {#if projectState.projects.length > 0}
249
- <div class="mb-4">
250
- <div
251
- class="flex items-center gap-2 py-2.5 px-3.5 bg-slate-100/80 dark:bg-slate-800/80 border border-slate-200 dark:border-slate-800 rounded-lg"
252
- >
253
- <Icon name="lucide:search" class="w-4 h-4 text-slate-500 dark:text-slate-400 shrink-0" />
254
- <input
255
- type="text"
256
- bind:value={searchQuery}
257
- placeholder="Search projects..."
258
- class="flex-1 bg-transparent border-none outline-none text-slate-900 dark:text-slate-100 text-sm placeholder:text-slate-500 dark:placeholder:text-slate-400"
259
- />
260
- {#if searchQuery}
261
- <button
262
- type="button"
263
- class="flex items-center justify-center w-5 h-5 bg-transparent border-none rounded text-slate-400 cursor-pointer transition-all duration-150 hover:text-slate-600 dark:hover:text-slate-300"
264
- onclick={() => (searchQuery = '')}
265
- aria-label="Clear search"
266
- >
267
- <Icon name="lucide:x" class="w-3.5 h-3.5" />
268
- </button>
269
- {/if}
270
- </div>
271
- </div>
272
- {/if}
273
-
274
- {#if projectState.projects.length === 0}
275
- <div class="flex flex-col items-center gap-3 py-8 text-slate-600 dark:text-slate-500 text-sm">
276
- <Icon name="lucide:folder-x" class="w-12 h-12 text-slate-400 opacity-40" />
277
- <p class="font-medium">No projects yet</p>
278
- <p class="text-xs text-slate-500 dark:text-slate-500">Create your first project below</p>
279
- </div>
280
- {:else}
281
- <div class="space-y-2">
282
- {#each filteredProjects() as project (project.id)}
283
- {@const isActive = projectState.currentProject?.id === project.id}
284
- <div
285
- class="flex items-center gap-2 w-full p-3 bg-transparent border border-slate-200 dark:border-slate-700 rounded-lg text-slate-900 dark:text-slate-100 text-sm text-left transition-all duration-150
286
- {isActive
287
- ? 'border-violet-300 dark:border-violet-600 bg-violet-50 dark:bg-violet-900/10'
288
- : ''}"
289
- >
290
- <button
291
- type="button"
292
- class="flex items-center gap-3 flex-1 min-w-0 bg-transparent border-none cursor-pointer text-left"
293
- onclick={() => {
294
- import('$frontend/lib/stores/core/projects.svelte').then((m) =>
295
- m.setCurrentProject(project)
296
- );
297
- closeProjectMenu();
298
- }}
299
- >
300
- <div
301
- class="relative w-8 h-8 {isActive
302
- ? 'bg-violet-200 dark:bg-violet-800/30'
303
- : 'bg-violet-100 dark:bg-violet-900/20'} rounded-lg flex items-center justify-center flex-shrink-0"
304
- >
305
- <Icon name="lucide:folder" class="text-violet-600 dark:text-violet-400 w-4 h-4" />
306
- <span
307
- class="absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-white dark:border-slate-900 {getProjectStatusColor(project.id ?? '')}"
308
- ></span>
309
- </div>
310
- <div class="flex-1 min-w-0">
311
- <div class="flex items-center gap-2">
312
- <p class="font-semibold text-slate-900 dark:text-slate-100 truncate">
313
- {project.name}
314
- </p>
315
- {#if isActive}
316
- <span
317
- class="inline-flex items-center gap-1 px-2 py-0.5 bg-green-100 dark:bg-green-900/20 text-green-700 dark:text-green-300 text-xs font-medium rounded-full"
318
- >
319
- <Icon name="lucide:circle-check" class="w-3 h-3" />
320
- Active
321
- </span>
322
- {/if}
323
- </div>
324
- <p class="text-xs text-slate-500 dark:text-slate-400 truncate font-mono">
325
- {project.path}
326
- </p>
327
- </div>
328
- </button>
329
- <ProjectUserAvatars projectStatus={presenceState.statuses.get(project.id ?? '')} maxVisible={2} />
330
- <button
331
- type="button"
332
- class="flex items-center justify-center w-8 h-8 bg-transparent border-none rounded-lg text-slate-400 dark:text-slate-500 cursor-pointer transition-all duration-150 hover:bg-red-500/15 hover:text-red-500 shrink-0"
333
- onclick={(e) => handleDeleteClick(project, e)}
334
- aria-label="Delete project"
335
- title="Delete"
336
- >
337
- <Icon name="lucide:trash-2" class="w-4 h-4" />
338
- </button>
339
- </div>
340
- {:else}
341
- <div
342
- class="flex flex-col items-center gap-2 py-8 text-slate-500 dark:text-slate-400 text-sm"
343
- >
344
- <Icon name="lucide:search-x" class="w-10 h-10 opacity-40" />
345
- <p class="font-medium">No projects found</p>
346
- <button
347
- type="button"
348
- class="text-xs text-violet-600 dark:text-violet-400 underline cursor-pointer hover:text-violet-700 dark:hover:text-violet-300"
349
- onclick={() => (searchQuery = '')}
350
- >
351
- Clear search
352
- </button>
353
- </div>
354
- {/each}
355
- </div>
356
- {/if}
357
- {/snippet}
358
- </Modal>
359
-
360
- <!-- Folder Browser -->
361
- <FolderBrowser
362
- bind:isOpen={showFolderBrowser}
363
- onClose={closeFolderBrowser}
364
- onSelect={createProjectFromFolder}
365
- />
366
-
367
- <!-- Delete Confirmation Dialog -->
368
- <Dialog
369
- bind:isOpen={showDeleteDialog}
370
- onClose={closeDeleteDialog}
371
- type="error"
372
- title="Delete Project"
373
- message='This will remove "{projectToDelete?.name}" from your project list. The actual project files on disk will not be deleted.'
374
- confirmText="Delete"
375
- cancelText="Cancel"
376
- onConfirm={confirmDeleteProject}
377
- />
378
-
379
- <!-- Tunnel Modal -->
380
- <TunnelModal bind:isOpen={showTunnelModal} onClose={() => (showTunnelModal = false)} />
1
+ <script lang="ts">
2
+ import Icon from '$frontend/components/common/display/Icon.svelte';
3
+ import Modal from '$frontend/components/common/overlay/Modal.svelte';
4
+ import Dialog from '$frontend/components/common/overlay/Dialog.svelte';
5
+ import {
6
+ workspaceState,
7
+ setActiveMobilePanel,
8
+ type PanelId
9
+ } from '$frontend/stores/ui/workspace.svelte';
10
+ import { projectState, removeProject } from '$frontend/stores/core/projects.svelte';
11
+ import { presenceState, getProjectStatusColor } from '$frontend/stores/core/presence.svelte';
12
+ import { openSettingsModal } from '$frontend/stores/ui/settings-modal.svelte';
13
+ import { addNotification } from '$frontend/stores/ui/notification.svelte';
14
+ import type { IconName } from '$shared/types/ui/icons';
15
+ import TunnelButton from '$frontend/components/tunnel/TunnelButton.svelte';
16
+ import TunnelModal from '$frontend/components/tunnel/TunnelModal.svelte';
17
+ import type { Project } from '$shared/types/database/schema';
18
+ import FolderBrowser from '$frontend/components/common/form/FolderBrowser.svelte';
19
+ import ProjectUserAvatars from '$frontend/components/common/display/ProjectUserAvatars.svelte';
20
+ import ws from '$frontend/utils/ws';
21
+ import { debug } from '$shared/utils/logger';
22
+
23
+ // Modal states
24
+ let showTunnelModal = $state(false);
25
+
26
+ // Project dropdown state
27
+ let showProjectMenu = $state(false);
28
+ let showFolderBrowser = $state(false);
29
+ let showDeleteDialog = $state(false);
30
+ let projectToDelete = $state<Project | null>(null);
31
+ let searchQuery = $state('');
32
+
33
+ // Get current project status from shared store
34
+ const currentProjectStatus = $derived(
35
+ projectState.currentProject?.id
36
+ ? presenceState.statuses.get(projectState.currentProject.id)
37
+ : undefined
38
+ );
39
+
40
+ const panels: { id: PanelId; icon: IconName; label: string }[] = [
41
+ { id: 'chat', icon: 'lucide:bot', label: 'AI' },
42
+ { id: 'files', icon: 'lucide:folder', label: 'Files' },
43
+ { id: 'git', icon: 'lucide:git-branch', label: 'Source Control' },
44
+ { id: 'terminal', icon: 'lucide:terminal', label: 'Terminal' },
45
+ { id: 'preview', icon: 'lucide:globe', label: 'Preview' }
46
+ ];
47
+
48
+ // Filtered projects based on search query
49
+ const filteredProjects = $derived(() => {
50
+ if (!searchQuery.trim()) return projectState.projects;
51
+ const query = searchQuery.toLowerCase();
52
+ return projectState.projects.filter(
53
+ (p) => p.name.toLowerCase().includes(query) || p.path.toLowerCase().includes(query)
54
+ );
55
+ });
56
+
57
+ function selectPanel(panelId: PanelId) {
58
+ setActiveMobilePanel(panelId);
59
+ }
60
+
61
+ function toggleProjectMenu() {
62
+ showProjectMenu = !showProjectMenu;
63
+ if (!showProjectMenu) {
64
+ searchQuery = '';
65
+ }
66
+ }
67
+
68
+ // Status color for project indicator — uses shared helper from presence store
69
+
70
+ function openAddProject() {
71
+ showProjectMenu = false;
72
+ showFolderBrowser = true;
73
+ }
74
+
75
+ function closeFolderBrowser() {
76
+ showFolderBrowser = false;
77
+ }
78
+
79
+ function closeProjectMenu() {
80
+ showProjectMenu = false;
81
+ searchQuery = '';
82
+ }
83
+
84
+ function handleDeleteClick(project: Project, event: MouseEvent) {
85
+ event.stopPropagation();
86
+ projectToDelete = project;
87
+ showDeleteDialog = true;
88
+ }
89
+
90
+ async function confirmDeleteProject() {
91
+ if (!projectToDelete) return;
92
+ const deleteId = projectToDelete.id!;
93
+
94
+ try {
95
+ await ws.http('projects:delete', { id: deleteId });
96
+ removeProject(deleteId);
97
+ showDeleteDialog = false;
98
+ projectToDelete = null;
99
+ } catch (error) {
100
+ debug.error('workspace', 'Failed to delete project:', error);
101
+ addNotification({
102
+ type: 'error',
103
+ title: 'Error',
104
+ message: 'Failed to delete project',
105
+ duration: 5000
106
+ });
107
+ }
108
+ }
109
+
110
+ function closeDeleteDialog() {
111
+ showDeleteDialog = false;
112
+ projectToDelete = null;
113
+ }
114
+
115
+ async function createProjectFromFolder(folderPath: string, folderName: string) {
116
+ try {
117
+ showFolderBrowser = false;
118
+
119
+ const projects = await ws.http('projects:list', {});
120
+
121
+ const existingProject = projects
122
+ ? projects.find((p: any) => p.path === folderPath)
123
+ : null;
124
+
125
+ if (existingProject) {
126
+ const { setCurrentProject } = await import('$frontend/stores/core/projects.svelte');
127
+ setCurrentProject(existingProject);
128
+ return;
129
+ }
130
+
131
+ const newProject = await ws.http('projects:create', { name: folderName, path: folderPath });
132
+
133
+ if (newProject) {
134
+ const { setCurrentProject } = await import('$frontend/stores/core/projects.svelte');
135
+ setCurrentProject(newProject);
136
+ }
137
+ } catch (error) {
138
+ console.error('Failed to create project:', error);
139
+ }
140
+ }
141
+ </script>
142
+
143
+ <header
144
+ class="flex items-center bg-white/90 dark:bg-slate-900/98 py-2 px-3 gap-2 relative z-30"
145
+ >
146
+ <!-- Project Selector -->
147
+ <button
148
+ type="button"
149
+ class="flex items-center gap-2 px-3 py-2.5 bg-slate-100/80 dark:bg-slate-800/80 border border-slate-200 dark:border-slate-800 rounded-lg text-slate-900 dark:text-slate-100 text-sm font-medium cursor-pointer transition-all duration-150 flex-1 min-w-0 active:bg-violet-500/10"
150
+ onclick={toggleProjectMenu}
151
+ aria-expanded={showProjectMenu}
152
+ aria-haspopup="menu"
153
+ >
154
+ <div class="relative shrink-0"><Icon name="lucide:folder-open" class="w-4 h-4" /><span class="absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-slate-100 dark:border-slate-800 {getProjectStatusColor(projectState.currentProject?.id ?? '')}"></span></div>
155
+ <span class="flex-1 text-left overflow-hidden text-ellipsis whitespace-nowrap">
156
+ {projectState.currentProject?.name ?? 'No Project'}
157
+ </span>
158
+ <div class="shrink-0" onclick={(e) => e.stopPropagation()}>
159
+ <ProjectUserAvatars projectStatus={currentProjectStatus} maxVisible={2} />
160
+ </div>
161
+ <Icon name="lucide:chevron-down" class="w-3 h-3 opacity-60 shrink-0" />
162
+ </button>
163
+
164
+ <!-- Panel Tabs (Icon Only) -->
165
+ <div
166
+ class="flex gap-1 bg-slate-100/80 dark:bg-slate-800/50 p-1 border border-slate-200 dark:border-slate-800 rounded-lg"
167
+ role="tablist"
168
+ aria-label="Panel Tabs"
169
+ >
170
+ {#each panels as panel}
171
+ <button
172
+ type="button"
173
+ class="flex items-center justify-center w-9 h-8 bg-transparent border-none rounded-md text-slate-500 cursor-pointer transition-all duration-150
174
+ {workspaceState.activeMobilePanel === panel.id
175
+ ? 'bg-violet-500/10 dark:bg-violet-500/20 text-slate-900 dark:text-slate-100 shadow-violet-500/20'
176
+ : 'active:bg-violet-500/10'}"
177
+ role="tab"
178
+ aria-selected={workspaceState.activeMobilePanel === panel.id}
179
+ aria-controls={`panel-${panel.id}`}
180
+ aria-label={panel.label}
181
+ title={panel.label}
182
+ onclick={() => selectPanel(panel.id)}
183
+ >
184
+ <Icon name={panel.icon} class="w-5 h-5" />
185
+ </button>
186
+ {/each}
187
+ </div>
188
+
189
+ <!-- Action Buttons -->
190
+ <div
191
+ class="flex gap-1 bg-slate-100/80 dark:bg-slate-800/50 p-1 border border-slate-200 dark:border-slate-800 rounded-lg"
192
+ role="tablist"
193
+ aria-label="Action Buttons"
194
+ >
195
+ <!-- Tunnel Button -->
196
+ <TunnelButton collapsed={true} onClick={() => (showTunnelModal = true)} mobile={true} />
197
+
198
+ <!-- Settings Button -->
199
+ <button
200
+ type="button"
201
+ class="flex items-center justify-center w-9 h-8 bg-transparent border-none rounded-md text-slate-500 cursor-pointer transition-all duration-150 active:bg-violet-500/10"
202
+ role="tab"
203
+ onclick={() => openSettingsModal()}
204
+ aria-label="Settings"
205
+ title="Settings"
206
+ >
207
+ <Icon name="lucide:settings" class="w-5 h-5" />
208
+ </button>
209
+ </div>
210
+ </header>
211
+
212
+ <!-- Project Selection Modal -->
213
+ <Modal bind:isOpen={showProjectMenu} onClose={closeProjectMenu} size="md">
214
+ {#snippet header()}
215
+ <div class="flex items-center justify-between px-4 py-3 md:px-6 md:py-4">
216
+ <h2 class="text-base md:text-lg font-bold text-slate-900 dark:text-slate-100">Projects</h2>
217
+ <div class="flex items-center gap-2">
218
+ <button
219
+ type="button"
220
+ class="flex items-center justify-center w-8 h-8 bg-violet-500/10 dark:bg-violet-500/15 border border-violet-500/20 rounded-lg text-violet-600 dark:text-violet-400 cursor-pointer transition-all duration-150 hover:bg-violet-500/20"
221
+ onclick={openAddProject}
222
+ aria-label="Add project"
223
+ title="Add project"
224
+ >
225
+ <Icon name="lucide:plus" class="w-4 h-4" />
226
+ </button>
227
+ <button
228
+ type="button"
229
+ class="p-1.5 md:p-2 rounded-lg text-slate-500 hover:text-slate-900 dark:hover:text-slate-100 hover:bg-violet-500/10 transition-colors"
230
+ onclick={closeProjectMenu}
231
+ aria-label="Close modal"
232
+ >
233
+ <svg class="w-4 h-4 md:w-5 md:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
234
+ <path
235
+ stroke-linecap="round"
236
+ stroke-linejoin="round"
237
+ stroke-width="2"
238
+ d="M6 18L18 6M6 6l12 12"
239
+ />
240
+ </svg>
241
+ </button>
242
+ </div>
243
+ </div>
244
+ {/snippet}
245
+
246
+ {#snippet children()}
247
+ <!-- Search Box -->
248
+ {#if projectState.projects.length > 0}
249
+ <div class="mb-4">
250
+ <div
251
+ class="flex items-center gap-2 py-2.5 px-3.5 bg-slate-100/80 dark:bg-slate-800/80 border border-slate-200 dark:border-slate-800 rounded-lg"
252
+ >
253
+ <Icon name="lucide:search" class="w-4 h-4 text-slate-500 dark:text-slate-400 shrink-0" />
254
+ <input
255
+ type="text"
256
+ bind:value={searchQuery}
257
+ placeholder="Search projects..."
258
+ class="flex-1 bg-transparent border-none outline-none text-slate-900 dark:text-slate-100 text-sm placeholder:text-slate-500 dark:placeholder:text-slate-400"
259
+ />
260
+ {#if searchQuery}
261
+ <button
262
+ type="button"
263
+ class="flex items-center justify-center w-5 h-5 bg-transparent border-none rounded text-slate-400 cursor-pointer transition-all duration-150 hover:text-slate-600 dark:hover:text-slate-300"
264
+ onclick={() => (searchQuery = '')}
265
+ aria-label="Clear search"
266
+ >
267
+ <Icon name="lucide:x" class="w-3.5 h-3.5" />
268
+ </button>
269
+ {/if}
270
+ </div>
271
+ </div>
272
+ {/if}
273
+
274
+ {#if projectState.projects.length === 0}
275
+ <div class="flex flex-col items-center gap-3 py-8 text-slate-600 dark:text-slate-500 text-sm">
276
+ <Icon name="lucide:folder-x" class="w-12 h-12 text-slate-400 opacity-40" />
277
+ <p class="font-medium">No projects yet</p>
278
+ <p class="text-xs text-slate-500 dark:text-slate-500">Create your first project below</p>
279
+ </div>
280
+ {:else}
281
+ <div class="space-y-2">
282
+ {#each filteredProjects() as project (project.id)}
283
+ {@const isActive = projectState.currentProject?.id === project.id}
284
+ <div
285
+ class="flex items-center gap-2 w-full p-3 bg-transparent border border-slate-200 dark:border-slate-700 rounded-lg text-slate-900 dark:text-slate-100 text-sm text-left transition-all duration-150
286
+ {isActive
287
+ ? 'border-violet-300 dark:border-violet-600 bg-violet-50 dark:bg-violet-900/10'
288
+ : ''}"
289
+ >
290
+ <button
291
+ type="button"
292
+ class="flex items-center gap-3 flex-1 min-w-0 bg-transparent border-none cursor-pointer text-left"
293
+ onclick={() => {
294
+ import('$frontend/stores/core/projects.svelte').then((m) =>
295
+ m.setCurrentProject(project)
296
+ );
297
+ closeProjectMenu();
298
+ }}
299
+ >
300
+ <div
301
+ class="relative w-8 h-8 {isActive
302
+ ? 'bg-violet-200 dark:bg-violet-800/30'
303
+ : 'bg-violet-100 dark:bg-violet-900/20'} rounded-lg flex items-center justify-center flex-shrink-0"
304
+ >
305
+ <Icon name="lucide:folder" class="text-violet-600 dark:text-violet-400 w-4 h-4" />
306
+ <span
307
+ class="absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 rounded-full border-2 border-white dark:border-slate-900 {getProjectStatusColor(project.id ?? '')}"
308
+ ></span>
309
+ </div>
310
+ <div class="flex-1 min-w-0">
311
+ <div class="flex items-center gap-2">
312
+ <p class="font-semibold text-slate-900 dark:text-slate-100 truncate">
313
+ {project.name}
314
+ </p>
315
+ {#if isActive}
316
+ <span
317
+ class="inline-flex items-center gap-1 px-2 py-0.5 bg-green-100 dark:bg-green-900/20 text-green-700 dark:text-green-300 text-xs font-medium rounded-full"
318
+ >
319
+ <Icon name="lucide:circle-check" class="w-3 h-3" />
320
+ Active
321
+ </span>
322
+ {/if}
323
+ </div>
324
+ <p class="text-xs text-slate-500 dark:text-slate-400 truncate font-mono">
325
+ {project.path}
326
+ </p>
327
+ </div>
328
+ </button>
329
+ <ProjectUserAvatars projectStatus={presenceState.statuses.get(project.id ?? '')} maxVisible={2} />
330
+ <button
331
+ type="button"
332
+ class="flex items-center justify-center w-8 h-8 bg-transparent border-none rounded-lg text-slate-400 dark:text-slate-500 cursor-pointer transition-all duration-150 hover:bg-red-500/15 hover:text-red-500 shrink-0"
333
+ onclick={(e) => handleDeleteClick(project, e)}
334
+ aria-label="Delete project"
335
+ title="Delete"
336
+ >
337
+ <Icon name="lucide:trash-2" class="w-4 h-4" />
338
+ </button>
339
+ </div>
340
+ {:else}
341
+ <div
342
+ class="flex flex-col items-center gap-2 py-8 text-slate-500 dark:text-slate-400 text-sm"
343
+ >
344
+ <Icon name="lucide:search-x" class="w-10 h-10 opacity-40" />
345
+ <p class="font-medium">No projects found</p>
346
+ <button
347
+ type="button"
348
+ class="text-xs text-violet-600 dark:text-violet-400 underline cursor-pointer hover:text-violet-700 dark:hover:text-violet-300"
349
+ onclick={() => (searchQuery = '')}
350
+ >
351
+ Clear search
352
+ </button>
353
+ </div>
354
+ {/each}
355
+ </div>
356
+ {/if}
357
+ {/snippet}
358
+ </Modal>
359
+
360
+ <!-- Folder Browser -->
361
+ <FolderBrowser
362
+ bind:isOpen={showFolderBrowser}
363
+ onClose={closeFolderBrowser}
364
+ onSelect={createProjectFromFolder}
365
+ />
366
+
367
+ <!-- Delete Confirmation Dialog -->
368
+ <Dialog
369
+ bind:isOpen={showDeleteDialog}
370
+ onClose={closeDeleteDialog}
371
+ type="error"
372
+ title="Delete Project"
373
+ message='This will remove "{projectToDelete?.name}" from your project list. The actual project files on disk will not be deleted.'
374
+ confirmText="Delete"
375
+ cancelText="Cancel"
376
+ onConfirm={confirmDeleteProject}
377
+ />
378
+
379
+ <!-- Tunnel Modal -->
380
+ <TunnelModal bind:isOpen={showTunnelModal} onClose={() => (showTunnelModal = false)} />