@myrialabs/clopen 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (422) hide show
  1. package/.dockerignore +5 -0
  2. package/.env.example +2 -5
  3. package/CONTRIBUTING.md +4 -0
  4. package/README.md +4 -2
  5. package/backend/{lib/auth → auth}/auth-service.ts +2 -2
  6. package/backend/{lib/chat → chat}/stream-manager.ts +1 -1
  7. package/backend/{lib/database → database}/queries/message-queries.ts +42 -0
  8. package/backend/{lib/database → database}/utils/connection.ts +5 -5
  9. package/backend/{lib/engine → engine}/adapters/claude/environment.ts +3 -4
  10. package/backend/{lib/engine → engine}/adapters/opencode/message-converter.ts +1 -1
  11. package/backend/{lib/engine → engine}/adapters/opencode/server.ts +7 -1
  12. package/backend/{lib/files → files}/file-watcher.ts +1 -1
  13. package/backend/{lib/git → git}/git-executor.ts +3 -2
  14. package/backend/index.ts +16 -16
  15. package/backend/{lib/mcp → mcp}/README.md +68 -79
  16. package/backend/{lib/mcp → mcp}/config.ts +1 -1
  17. package/backend/{lib/mcp → mcp}/servers/browser-automation/actions.ts +4 -4
  18. package/backend/{lib/mcp → mcp}/servers/browser-automation/browser.ts +3 -3
  19. package/backend/{lib/mcp → mcp}/servers/browser-automation/inspection.ts +3 -3
  20. package/backend/middleware/cors.ts +1 -1
  21. package/backend/middleware/error-handler.ts +1 -1
  22. package/backend/{lib/preview → preview}/browser/browser-preview-service.ts +1 -1
  23. package/backend/{lib/preview → preview}/browser/browser-tab-manager.ts +1 -1
  24. package/backend/{lib/preview → preview}/browser/types.ts +1 -1
  25. package/backend/{lib/project → project}/status-manager.ts +223 -223
  26. package/backend/{lib/snapshot → snapshot}/blob-store.ts +2 -2
  27. package/backend/{lib/terminal → terminal}/shell-utils.ts +1 -1
  28. package/backend/{lib/shared → utils}/env.ts +13 -15
  29. package/backend/{lib/shared → utils}/index.ts +4 -1
  30. package/backend/utils/paths.ts +11 -0
  31. package/backend/{lib/shared → utils}/port-utils.ts +19 -6
  32. package/backend/{lib/utils → utils}/ws.ts +2 -2
  33. package/backend/ws/README.md +9 -9
  34. package/backend/ws/auth/invites.ts +2 -2
  35. package/backend/ws/auth/login.ts +9 -9
  36. package/backend/ws/auth/status.ts +2 -2
  37. package/backend/ws/auth/users.ts +1 -1
  38. package/backend/ws/chat/background.ts +2 -2
  39. package/backend/ws/chat/stream.ts +3 -3
  40. package/backend/ws/engine/claude/accounts.ts +4 -4
  41. package/backend/ws/engine/claude/status.ts +1 -1
  42. package/backend/ws/files/read.ts +2 -2
  43. package/backend/ws/files/watch.ts +2 -2
  44. package/backend/ws/files/write.ts +1 -1
  45. package/backend/ws/git/branch.ts +2 -2
  46. package/backend/ws/git/commit.ts +2 -2
  47. package/backend/ws/git/conflict.ts +2 -2
  48. package/backend/ws/git/diff.ts +2 -2
  49. package/backend/ws/git/log.ts +2 -2
  50. package/backend/ws/git/remote.ts +2 -2
  51. package/backend/ws/git/staging.ts +2 -2
  52. package/backend/ws/git/status.ts +3 -3
  53. package/backend/ws/messages/crud.ts +53 -1
  54. package/backend/ws/preview/browser/cleanup.ts +2 -2
  55. package/backend/ws/preview/browser/console.ts +2 -2
  56. package/backend/ws/preview/browser/interact.ts +2 -2
  57. package/backend/ws/preview/browser/mcp.ts +1 -1
  58. package/backend/ws/preview/browser/native-ui.ts +2 -2
  59. package/backend/ws/preview/browser/stats.ts +2 -2
  60. package/backend/ws/preview/browser/tab-info.ts +2 -2
  61. package/backend/ws/preview/browser/tab.ts +2 -2
  62. package/backend/ws/preview/browser/webcodecs.ts +2 -2
  63. package/backend/ws/projects/crud.ts +3 -3
  64. package/backend/ws/projects/presence.ts +3 -3
  65. package/backend/ws/projects/status.ts +3 -3
  66. package/backend/ws/sessions/crud.ts +2 -2
  67. package/backend/ws/settings/crud.ts +2 -2
  68. package/backend/ws/snapshot/restore.ts +5 -5
  69. package/backend/ws/snapshot/timeline.ts +3 -3
  70. package/backend/ws/system/operations.ts +1 -1
  71. package/backend/ws/terminal/persistence.ts +3 -3
  72. package/backend/ws/terminal/session.ts +6 -6
  73. package/backend/ws/terminal/stream.ts +2 -2
  74. package/backend/ws/tunnel/operations.ts +1 -1
  75. package/backend/ws/user/crud.ts +4 -4
  76. package/bin/clopen.ts +15 -15
  77. package/docker-compose.yml +31 -0
  78. package/frontend/App.svelte +13 -13
  79. package/frontend/{lib/components → components}/auth/InvitePage.svelte +2 -2
  80. package/frontend/{lib/components → components}/auth/LoginPage.svelte +1 -1
  81. package/frontend/{lib/components → components}/auth/SetupPage.svelte +49 -17
  82. package/frontend/{lib/components → components}/chat/ChatInterface.svelte +14 -14
  83. package/frontend/{lib/components → components}/chat/formatters/ErrorMessage.svelte +1 -1
  84. package/frontend/{lib/components → components}/chat/formatters/MessageFormatter.svelte +4 -4
  85. package/frontend/{lib/components → components}/chat/formatters/TextMessage.svelte +1 -1
  86. package/frontend/{lib/components → components}/chat/formatters/Tools.svelte +1 -1
  87. package/frontend/{lib/components → components}/chat/input/ChatInput.svelte +12 -12
  88. package/frontend/{lib/components → components}/chat/input/components/ChatInputActions.svelte +1 -1
  89. package/frontend/{lib/components → components}/chat/input/components/EditModeIndicator.svelte +2 -2
  90. package/frontend/{lib/components → components}/chat/input/components/EngineModelPicker.svelte +9 -9
  91. package/frontend/{lib/components → components}/chat/input/components/FileAttachmentPreview.svelte +1 -1
  92. package/frontend/{lib/components → components}/chat/input/components/LoadingIndicator.svelte +2 -2
  93. package/frontend/{lib/components → components}/chat/input/composables/use-chat-actions.svelte.ts +8 -8
  94. package/frontend/{lib/components → components}/chat/input/composables/use-file-handling.svelte.ts +1 -1
  95. package/frontend/{lib/components → components}/chat/input/composables/use-input-state.svelte.ts +6 -6
  96. package/frontend/{lib/components → components}/chat/message/ChatMessage.svelte +8 -8
  97. package/frontend/{lib/components → components}/chat/message/ChatMessages.svelte +7 -7
  98. package/frontend/{lib/components → components}/chat/message/MessageBubble.svelte +1 -1
  99. package/frontend/{lib/components → components}/chat/message/MessageHeader.svelte +2 -2
  100. package/frontend/{lib/components → components}/chat/modal/DebugModal.svelte +2 -2
  101. package/frontend/{lib/components → components}/chat/modal/TokenUsageModal.svelte +2 -2
  102. package/frontend/{lib/components → components}/chat/tools/AskUserQuestionTool.svelte +4 -4
  103. package/frontend/{lib/components → components}/chat/tools/CustomMcpTool.svelte +1 -1
  104. package/frontend/{lib/components → components}/chat/tools/EditTool.svelte +1 -1
  105. package/frontend/{lib/components → components}/chat/tools/TodoWriteTool.svelte +1 -1
  106. package/frontend/{lib/components → components}/chat/tools/components/CodeBlock.svelte +2 -2
  107. package/frontend/{lib/components → components}/chat/tools/components/DiffBlock.svelte +1 -1
  108. package/frontend/{lib/components → components}/chat/tools/components/FileHeader.svelte +2 -2
  109. package/frontend/{lib/components → components}/chat/tools/components/InfoLine.svelte +1 -1
  110. package/frontend/{lib/components → components}/chat/widgets/FloatingTodoList.svelte +127 -13
  111. package/frontend/{lib/components → components}/chat/widgets/TokenUsage.svelte +4 -4
  112. package/frontend/{lib/components → components}/checkpoint/TimelineModal.svelte +10 -10
  113. package/frontend/{lib/components → components}/checkpoint/timeline/TimelineNode.svelte +1 -1
  114. package/frontend/{lib/components/common → components/common/display}/Icon.svelte +2 -2
  115. package/frontend/{lib/components/common → components/common/display}/PageTemplate.svelte +1 -1
  116. package/frontend/{lib/components/common → components/common/display}/ProjectUserAvatars.svelte +1 -1
  117. package/frontend/{lib/components/common → components/common/display}/ThemeToggle.svelte +1 -1
  118. package/frontend/{lib/components/common → components/common/editor}/MonacoEditor.svelte +2 -2
  119. package/frontend/{lib/components/common → components/common/feedback}/Alert.svelte +1 -1
  120. package/frontend/{lib/components/common → components/common/feedback}/ConnectionBanner.svelte +3 -3
  121. package/frontend/{lib/components/common → components/common/feedback}/LoadingScreen.svelte +1 -1
  122. package/frontend/{lib/components/common → components/common/feedback}/NotificationToast.svelte +2 -2
  123. package/frontend/{lib/components/common → components/common/feedback}/UpdateBanner.svelte +5 -5
  124. package/frontend/{lib/components/common → components/common/form}/Checkbox.svelte +1 -1
  125. package/frontend/{lib/components/common → components/common/form}/FolderBrowser.svelte +6 -6
  126. package/frontend/{lib/components/common → components/common/form}/Input.svelte +1 -1
  127. package/frontend/{lib/components/common → components/common/form}/ModelSelector.svelte +3 -3
  128. package/frontend/{lib/components/common → components/common/form}/Select.svelte +1 -1
  129. package/frontend/{lib/components/common → components/common/form}/Textarea.svelte +1 -1
  130. package/frontend/{lib/components/common → components/common/overlay}/Dialog.svelte +1 -1
  131. package/frontend/{lib/components/common → components/common/overlay}/Lightbox.svelte +3 -3
  132. package/frontend/{lib/components/common → components/common/overlay}/ModalProvider.svelte +2 -2
  133. package/frontend/{lib/components → components}/common/xterm/XTerm.svelte +5 -5
  134. package/frontend/{lib/components → components}/common/xterm/xterm-service.ts +2 -2
  135. package/frontend/{lib/components → components}/files/FileNode.svelte +3 -3
  136. package/frontend/{lib/components → components}/files/FileTree.svelte +5 -5
  137. package/frontend/{lib/components → components}/files/FileViewer.svelte +7 -7
  138. package/frontend/{lib/components → components}/files/SearchResults.svelte +3 -3
  139. package/frontend/{lib/components → components}/git/BranchManager.svelte +6 -6
  140. package/frontend/{lib/components → components}/git/ChangesSection.svelte +1 -1
  141. package/frontend/{lib/components → components}/git/CommitForm.svelte +1 -1
  142. package/frontend/{lib/components → components}/git/ConflictResolver.svelte +1 -1
  143. package/frontend/{lib/components → components}/git/DiffViewer.svelte +7 -7
  144. package/frontend/{lib/components → components}/git/FileChangeItem.svelte +3 -3
  145. package/frontend/{lib/components → components}/git/GitButton.svelte +1 -1
  146. package/frontend/{lib/components → components}/git/GitLog.svelte +2 -2
  147. package/frontend/{lib/components → components}/git/GitModal.svelte +3 -3
  148. package/frontend/{lib/components → components}/history/HistoryModal.svelte +41 -89
  149. package/frontend/{lib/components → components}/history/HistoryView.svelte +57 -104
  150. package/frontend/{lib/components → components}/index.ts +9 -9
  151. package/frontend/{lib/components → components}/preview/browser/BrowserPreview.svelte +3 -3
  152. package/frontend/{lib/components → components}/preview/browser/components/Canvas.svelte +2 -2
  153. package/frontend/{lib/components → components}/preview/browser/components/ConsolePanel.svelte +1 -1
  154. package/frontend/{lib/components → components}/preview/browser/components/Container.svelte +2 -2
  155. package/frontend/{lib/components → components}/preview/browser/components/ContextMenu.svelte +1 -1
  156. package/frontend/{lib/components → components}/preview/browser/components/SelectDropdown.svelte +1 -1
  157. package/frontend/{lib/components → components}/preview/browser/components/Toolbar.svelte +2 -2
  158. package/frontend/{lib/components → components}/preview/browser/core/cleanup.svelte.ts +1 -1
  159. package/frontend/{lib/components → components}/preview/browser/core/coordinator.svelte.ts +4 -4
  160. package/frontend/{lib/components → components}/preview/browser/core/interactions.svelte.ts +3 -3
  161. package/frontend/{lib/components → components}/preview/browser/core/mcp-handlers.svelte.ts +2 -2
  162. package/frontend/{lib/components → components}/preview/browser/core/native-ui-handlers.svelte.ts +2 -2
  163. package/frontend/{lib/components → components}/preview/browser/core/tab-manager.svelte.ts +1 -1
  164. package/frontend/{lib/components → components}/preview/browser/core/tab-operations.svelte.ts +3 -3
  165. package/frontend/{lib/components → components}/settings/SettingsModal.svelte +4 -4
  166. package/frontend/{lib/components → components}/settings/SettingsView.svelte +2 -2
  167. package/frontend/{lib/components → components}/settings/admin/InviteManagement.svelte +5 -5
  168. package/frontend/{lib/components → components}/settings/admin/UserManagement.svelte +5 -5
  169. package/frontend/{lib/components → components}/settings/appearance/AppearanceSettings.svelte +5 -5
  170. package/frontend/{lib/components → components}/settings/appearance/LayoutPresetSettings.svelte +3 -3
  171. package/frontend/{lib/components → components}/settings/appearance/LayoutPreview.svelte +1 -1
  172. package/frontend/{lib/components → components}/settings/engines/AIEnginesSettings.svelte +6 -6
  173. package/frontend/{lib/components → components}/settings/general/AdvancedSettings.svelte +5 -5
  174. package/frontend/{lib/components → components}/settings/general/AuthModeSettings.svelte +5 -5
  175. package/frontend/{lib/components → components}/settings/general/DataManagementSettings.svelte +9 -9
  176. package/frontend/{lib/components → components}/settings/general/UpdateSettings.svelte +3 -3
  177. package/frontend/{lib/components → components}/settings/model/ModelSettings.svelte +2 -2
  178. package/frontend/{lib/components → components}/settings/notifications/NotificationSettings.svelte +4 -4
  179. package/frontend/{lib/components → components}/settings/user/UserSettings.svelte +5 -5
  180. package/frontend/{lib/components → components}/terminal/Terminal.svelte +9 -9
  181. package/frontend/{lib/components → components}/terminal/TerminalTabs.svelte +1 -1
  182. package/frontend/{lib/components → components}/terminal/TerminalView.svelte +5 -5
  183. package/frontend/{lib/components → components}/tunnel/TunnelActive.svelte +3 -3
  184. package/frontend/{lib/components → components}/tunnel/TunnelButton.svelte +2 -2
  185. package/frontend/{lib/components → components}/tunnel/TunnelInactive.svelte +4 -4
  186. package/frontend/{lib/components → components}/tunnel/TunnelModal.svelte +2 -2
  187. package/frontend/{lib/components → components}/workspace/DesktopNavigator.svelte +372 -372
  188. package/frontend/{lib/components → components}/workspace/MobileNavigator.svelte +380 -380
  189. package/frontend/{lib/components → components}/workspace/PanelContainer.svelte +3 -3
  190. package/frontend/{lib/components → components}/workspace/PanelHeader.svelte +10 -10
  191. package/frontend/{lib/components → components}/workspace/ViewMenu.svelte +4 -4
  192. package/frontend/{lib/components → components}/workspace/WorkspaceLayout.svelte +17 -17
  193. package/frontend/{lib/components → components}/workspace/layout/DesktopLayout.svelte +1 -1
  194. package/frontend/{lib/components → components}/workspace/layout/MobileLayout.svelte +1 -1
  195. package/frontend/{lib/components → components}/workspace/layout/split-pane/Container.svelte +1 -1
  196. package/frontend/{lib/components → components}/workspace/layout/split-pane/Handle.svelte +2 -2
  197. package/frontend/{lib/components → components}/workspace/layout/split-pane/Layout.svelte +2 -2
  198. package/frontend/{lib/components → components}/workspace/panels/ChatPanel.svelte +14 -14
  199. package/frontend/{lib/components → components}/workspace/panels/FilesPanel.svelte +51 -13
  200. package/frontend/{lib/components → components}/workspace/panels/GitPanel.svelte +55 -17
  201. package/frontend/{lib/components → components}/workspace/panels/PreviewPanel.svelte +5 -5
  202. package/frontend/{lib/components → components}/workspace/panels/TerminalPanel.svelte +6 -6
  203. package/frontend/{lib/services → services}/chat/chat.service.ts +8 -8
  204. package/frontend/{lib/services → services}/notification/global-stream-monitor.ts +117 -117
  205. package/frontend/{lib/services → services}/notification/push.service.ts +1 -1
  206. package/frontend/{lib/services → services}/notification/sound.service.ts +1 -1
  207. package/frontend/{lib/services → services}/preview/browser/browser-console.service.ts +1 -1
  208. package/frontend/{lib/services → services}/preview/browser/browser-webcodecs.service.ts +1 -1
  209. package/frontend/{lib/services → services}/preview/browser/mcp-integration.svelte.ts +2 -2
  210. package/frontend/{lib/services → services}/project/status.service.ts +160 -160
  211. package/frontend/{lib/services → services}/snapshot/snapshot.service.ts +2 -2
  212. package/frontend/{lib/services → services}/terminal/background/index.ts +1 -1
  213. package/frontend/{lib/services → services}/terminal/background/session-restore.ts +1 -1
  214. package/frontend/{lib/services → services}/terminal/background/stream-manager.ts +1 -1
  215. package/frontend/{lib/services → services}/terminal/project.service.ts +2 -2
  216. package/frontend/{lib/services → services}/terminal/terminal.service.ts +2 -2
  217. package/frontend/{lib/stores → stores}/core/app.svelte.ts +1 -1
  218. package/frontend/{lib/stores → stores}/core/presence.svelte.ts +4 -4
  219. package/frontend/{lib/stores → stores}/core/projects.svelte.ts +5 -5
  220. package/frontend/{lib/stores → stores}/core/sessions.svelte.ts +3 -3
  221. package/frontend/{lib/stores → stores}/features/auth.svelte.ts +30 -2
  222. package/frontend/{lib/stores → stores}/features/claude-accounts.svelte.ts +1 -1
  223. package/frontend/{lib/stores → stores}/features/models.svelte.ts +1 -1
  224. package/frontend/{lib/stores → stores}/features/settings.svelte.ts +2 -2
  225. package/frontend/{lib/stores → stores}/features/terminal.svelte.ts +4 -4
  226. package/frontend/{lib/stores → stores}/features/tunnel.svelte.ts +1 -1
  227. package/frontend/{lib/stores → stores}/features/user.svelte.ts +1 -1
  228. package/frontend/{lib/stores → stores}/ui/edit-mode.svelte.ts +3 -3
  229. package/frontend/{lib/stores → stores}/ui/update.svelte.ts +8 -2
  230. package/frontend/{lib/utils → utils}/theme.ts +1 -1
  231. package/frontend/{lib/utils → utils}/ws.ts +1 -1
  232. package/package.json +2 -2
  233. package/scripts/dev.ts +4 -3
  234. package/scripts/generate-icons.ts +2 -2
  235. package/scripts/start.ts +24 -0
  236. package/shared/types/ui/icons.ts +4 -4
  237. package/shared/utils/anonymous-user.ts +1 -1
  238. package/shared/utils/ws-server.ts +3 -3
  239. package/vite.config.ts +2 -2
  240. /package/backend/{lib/auth → auth}/index.ts +0 -0
  241. /package/backend/{lib/auth → auth}/permissions.ts +0 -0
  242. /package/backend/{lib/auth → auth}/rate-limiter.ts +0 -0
  243. /package/backend/{lib/auth → auth}/tokens.ts +0 -0
  244. /package/backend/{lib/chat → chat}/helpers.ts +0 -0
  245. /package/backend/{lib/chat → chat}/index.ts +0 -0
  246. /package/backend/{lib/database → database}/README.md +0 -0
  247. /package/backend/{lib/database → database}/index.ts +0 -0
  248. /package/backend/{lib/database → database}/migrations/001_create_projects_table.ts +0 -0
  249. /package/backend/{lib/database → database}/migrations/002_create_chat_sessions_table.ts +0 -0
  250. /package/backend/{lib/database → database}/migrations/003_create_messages_table.ts +0 -0
  251. /package/backend/{lib/database → database}/migrations/004_create_prompt_templates_table.ts +0 -0
  252. /package/backend/{lib/database → database}/migrations/005_create_settings_table.ts +0 -0
  253. /package/backend/{lib/database → database}/migrations/006_add_user_to_messages.ts +0 -0
  254. /package/backend/{lib/database → database}/migrations/007_create_stream_states_table.ts +0 -0
  255. /package/backend/{lib/database → database}/migrations/008_create_message_snapshots_table.ts +0 -0
  256. /package/backend/{lib/database → database}/migrations/009_add_delta_snapshot_fields.ts +0 -0
  257. /package/backend/{lib/database → database}/migrations/010_add_soft_delete_and_branch_support.ts +0 -0
  258. /package/backend/{lib/database → database}/migrations/011_git_like_commit_graph.ts +0 -0
  259. /package/backend/{lib/database → database}/migrations/012_add_file_change_statistics.ts +0 -0
  260. /package/backend/{lib/database → database}/migrations/013_checkpoint_tree_state.ts +0 -0
  261. /package/backend/{lib/database → database}/migrations/014_add_engine_to_sessions.ts +0 -0
  262. /package/backend/{lib/database → database}/migrations/015_add_model_to_sessions.ts +0 -0
  263. /package/backend/{lib/database → database}/migrations/016_create_user_projects_table.ts +0 -0
  264. /package/backend/{lib/database → database}/migrations/017_add_current_session_to_user_projects.ts +0 -0
  265. /package/backend/{lib/database → database}/migrations/018_create_claude_accounts_table.ts +0 -0
  266. /package/backend/{lib/database → database}/migrations/019_add_claude_account_to_sessions.ts +0 -0
  267. /package/backend/{lib/database → database}/migrations/020_add_snapshot_tree_hash.ts +0 -0
  268. /package/backend/{lib/database → database}/migrations/021_drop_prompt_templates_table.ts +0 -0
  269. /package/backend/{lib/database → database}/migrations/022_add_snapshot_changes_column.ts +0 -0
  270. /package/backend/{lib/database → database}/migrations/023_create_user_unread_sessions_table.ts +0 -0
  271. /package/backend/{lib/database → database}/migrations/024_create_users_table.ts +0 -0
  272. /package/backend/{lib/database → database}/migrations/025_create_auth_sessions_table.ts +0 -0
  273. /package/backend/{lib/database → database}/migrations/026_create_invite_tokens_table.ts +0 -0
  274. /package/backend/{lib/database → database}/migrations/index.ts +0 -0
  275. /package/backend/{lib/database → database}/queries/auth-queries.ts +0 -0
  276. /package/backend/{lib/database → database}/queries/checkpoint-queries.ts +0 -0
  277. /package/backend/{lib/database → database}/queries/engine-queries.ts +0 -0
  278. /package/backend/{lib/database → database}/queries/index.ts +0 -0
  279. /package/backend/{lib/database → database}/queries/project-queries.ts +0 -0
  280. /package/backend/{lib/database → database}/queries/session-queries.ts +0 -0
  281. /package/backend/{lib/database → database}/queries/settings-queries.ts +0 -0
  282. /package/backend/{lib/database → database}/queries/snapshot-queries.ts +0 -0
  283. /package/backend/{lib/database → database}/queries/utils-queries.ts +0 -0
  284. /package/backend/{lib/database → database}/seeders/index.ts +0 -0
  285. /package/backend/{lib/database → database}/seeders/settings_seeder.ts +0 -0
  286. /package/backend/{lib/database → database}/utils/index.ts +0 -0
  287. /package/backend/{lib/database → database}/utils/migration-runner.ts +0 -0
  288. /package/backend/{lib/database → database}/utils/seeder-runner.ts +0 -0
  289. /package/backend/{lib/engine → engine}/adapters/claude/error-handler.ts +0 -0
  290. /package/backend/{lib/engine → engine}/adapters/claude/index.ts +0 -0
  291. /package/backend/{lib/engine → engine}/adapters/claude/path-utils.ts +0 -0
  292. /package/backend/{lib/engine → engine}/adapters/claude/stream.ts +0 -0
  293. /package/backend/{lib/engine → engine}/adapters/opencode/index.ts +0 -0
  294. /package/backend/{lib/engine → engine}/adapters/opencode/stream.ts +0 -0
  295. /package/backend/{lib/engine → engine}/index.ts +0 -0
  296. /package/backend/{lib/engine → engine}/types.ts +0 -0
  297. /package/backend/{lib/files → files}/file-operations.ts +0 -0
  298. /package/backend/{lib/files → files}/file-reading.ts +0 -0
  299. /package/backend/{lib/files → files}/path-browsing.ts +0 -0
  300. /package/backend/{lib/git → git}/git-parser.ts +0 -0
  301. /package/backend/{lib/git → git}/git-service.ts +0 -0
  302. /package/backend/{lib/mcp → mcp}/index.ts +0 -0
  303. /package/backend/{lib/mcp → mcp}/project-context.ts +0 -0
  304. /package/backend/{lib/mcp → mcp}/remote-server.ts +0 -0
  305. /package/backend/{lib/mcp → mcp}/servers/browser-automation/index.ts +0 -0
  306. /package/backend/{lib/mcp → mcp}/servers/helper.ts +0 -0
  307. /package/backend/{lib/mcp → mcp}/servers/index.ts +0 -0
  308. /package/backend/{lib/mcp → mcp}/servers/weather/get-temperature.ts +0 -0
  309. /package/backend/{lib/mcp → mcp}/servers/weather/index.ts +0 -0
  310. /package/backend/{lib/mcp → mcp}/types.ts +0 -0
  311. /package/backend/{lib/preview → preview}/browser/browser-audio-capture.ts +0 -0
  312. /package/backend/{lib/preview → preview}/browser/browser-console-manager.ts +0 -0
  313. /package/backend/{lib/preview → preview}/browser/browser-dialog-handler.ts +0 -0
  314. /package/backend/{lib/preview → preview}/browser/browser-interaction-handler.ts +0 -0
  315. /package/backend/{lib/preview → preview}/browser/browser-mcp-control.ts +0 -0
  316. /package/backend/{lib/preview → preview}/browser/browser-native-ui-handler.ts +0 -0
  317. /package/backend/{lib/preview → preview}/browser/browser-navigation-tracker.ts +0 -0
  318. /package/backend/{lib/preview → preview}/browser/browser-pool.ts +0 -0
  319. /package/backend/{lib/preview → preview}/browser/browser-video-capture.ts +0 -0
  320. /package/backend/{lib/preview → preview}/browser/scripts/audio-stream.ts +0 -0
  321. /package/backend/{lib/preview → preview}/browser/scripts/cursor-tracking.ts +0 -0
  322. /package/backend/{lib/preview → preview}/browser/scripts/video-stream.ts +0 -0
  323. /package/backend/{lib/preview → preview}/index.ts +0 -0
  324. /package/backend/{lib/project → project}/index.ts +0 -0
  325. /package/backend/{lib/snapshot → snapshot}/gitignore.ts +0 -0
  326. /package/backend/{lib/snapshot → snapshot}/helpers.ts +0 -0
  327. /package/backend/{lib/snapshot → snapshot}/snapshot-service.ts +0 -0
  328. /package/backend/{lib/terminal → terminal}/helpers.ts +0 -0
  329. /package/backend/{lib/terminal → terminal}/index.ts +0 -0
  330. /package/backend/{lib/terminal → terminal}/pty-manager.ts +0 -0
  331. /package/backend/{lib/terminal → terminal}/pty-session-manager.ts +0 -0
  332. /package/backend/{lib/terminal → terminal}/stream-manager.ts +0 -0
  333. /package/backend/{lib/tunnel → tunnel}/global-tunnel-manager.ts +0 -0
  334. /package/backend/{lib/tunnel → tunnel}/project-tunnel-manager.ts +0 -0
  335. /package/backend/{lib/shared → utils}/process-manager.ts +0 -0
  336. /package/backend/{lib/user/helpers.ts → utils/user-helpers.ts} +0 -0
  337. /package/frontend/{lib/app-environment.ts → app-environment.ts} +0 -0
  338. /package/frontend/{lib/components → components}/chat/formatters/index.ts +0 -0
  339. /package/frontend/{lib/components → components}/chat/input/components/DragDropOverlay.svelte +0 -0
  340. /package/frontend/{lib/components → components}/chat/input/composables/use-animations.svelte.ts +0 -0
  341. /package/frontend/{lib/components → components}/chat/input/composables/use-textarea-resize.svelte.ts +0 -0
  342. /package/frontend/{lib/components → components}/chat/message/DateSeparator.svelte +0 -0
  343. /package/frontend/{lib/components → components}/chat/shared/index.ts +0 -0
  344. /package/frontend/{lib/components → components}/chat/shared/utils.ts +0 -0
  345. /package/frontend/{lib/components → components}/chat/tools/AgentTool.svelte +0 -0
  346. /package/frontend/{lib/components → components}/chat/tools/BashOutputTool.svelte +0 -0
  347. /package/frontend/{lib/components → components}/chat/tools/BashTool.svelte +0 -0
  348. /package/frontend/{lib/components → components}/chat/tools/EnterPlanModeTool.svelte +0 -0
  349. /package/frontend/{lib/components → components}/chat/tools/ExitPlanModeTool.svelte +0 -0
  350. /package/frontend/{lib/components → components}/chat/tools/GlobTool.svelte +0 -0
  351. /package/frontend/{lib/components → components}/chat/tools/GrepTool.svelte +0 -0
  352. /package/frontend/{lib/components → components}/chat/tools/ListMcpResourcesTool.svelte +0 -0
  353. /package/frontend/{lib/components → components}/chat/tools/NotebookEditTool.svelte +0 -0
  354. /package/frontend/{lib/components → components}/chat/tools/ReadMcpResourceTool.svelte +0 -0
  355. /package/frontend/{lib/components → components}/chat/tools/ReadTool.svelte +0 -0
  356. /package/frontend/{lib/components → components}/chat/tools/TaskStopTool.svelte +0 -0
  357. /package/frontend/{lib/components → components}/chat/tools/TaskTool.svelte +0 -0
  358. /package/frontend/{lib/components → components}/chat/tools/WebFetchTool.svelte +0 -0
  359. /package/frontend/{lib/components → components}/chat/tools/WebSearchTool.svelte +0 -0
  360. /package/frontend/{lib/components → components}/chat/tools/WriteTool.svelte +0 -0
  361. /package/frontend/{lib/components → components}/chat/tools/components/StatsBadges.svelte +0 -0
  362. /package/frontend/{lib/components → components}/chat/tools/components/TerminalCommand.svelte +0 -0
  363. /package/frontend/{lib/components → components}/chat/tools/components/index.ts +0 -0
  364. /package/frontend/{lib/components → components}/chat/tools/index.ts +0 -0
  365. /package/frontend/{lib/components → components}/checkpoint/timeline/TimelineEdge.svelte +0 -0
  366. /package/frontend/{lib/components → components}/checkpoint/timeline/TimelineGraph.svelte +0 -0
  367. /package/frontend/{lib/components → components}/checkpoint/timeline/TimelineVersionGroup.svelte +0 -0
  368. /package/frontend/{lib/components → components}/checkpoint/timeline/animation.ts +0 -0
  369. /package/frontend/{lib/components → components}/checkpoint/timeline/config.ts +0 -0
  370. /package/frontend/{lib/components → components}/checkpoint/timeline/graph-builder.ts +0 -0
  371. /package/frontend/{lib/components → components}/checkpoint/timeline/types.ts +0 -0
  372. /package/frontend/{lib/components → components}/checkpoint/timeline/utils.ts +0 -0
  373. /package/frontend/{lib/components/common → components/common/display}/AvatarBubble.svelte +0 -0
  374. /package/frontend/{lib/components/common → components/common/display}/Button.svelte +0 -0
  375. /package/frontend/{lib/components/common → components/common/display}/Card.svelte +0 -0
  376. /package/frontend/{lib/components/common → components/common/feedback}/LoadingSpinner.svelte +0 -0
  377. /package/frontend/{lib/components → components}/common/lucide-icons.ts +0 -0
  378. /package/frontend/{lib/components → components}/common/material-icons.ts +0 -0
  379. /package/frontend/{lib/components/common → components/common/overlay}/Modal.svelte +0 -0
  380. /package/frontend/{lib/components → components}/common/xterm/index.ts +0 -0
  381. /package/frontend/{lib/components → components}/common/xterm/terminal-config.ts +0 -0
  382. /package/frontend/{lib/components → components}/common/xterm/types.ts +0 -0
  383. /package/frontend/{lib/components → components}/preview/browser/components/VirtualCursor.svelte +0 -0
  384. /package/frontend/{lib/components → components}/preview/browser/core/stream-handler.svelte.ts +0 -0
  385. /package/frontend/{lib/components → components}/preview/index.ts +0 -0
  386. /package/frontend/{lib/components → components}/settings/account/AccountSettings.svelte +0 -0
  387. /package/frontend/{lib/components → components}/settings/general/GeneralSettings.svelte +0 -0
  388. /package/frontend/{lib/components → components}/settings/security/SecuritySettings.svelte +0 -0
  389. /package/frontend/{lib/components → components}/settings/system/SystemSettings.svelte +0 -0
  390. /package/frontend/{lib/components → components}/tunnel/TunnelQRCode.svelte +0 -0
  391. /package/frontend/{lib/services → services}/chat/index.ts +0 -0
  392. /package/frontend/{lib/services → services}/notification/index.ts +0 -0
  393. /package/frontend/{lib/services → services}/preview/index.ts +0 -0
  394. /package/frontend/{lib/services → services}/project/index.ts +0 -0
  395. /package/frontend/{lib/services → services}/terminal/index.ts +0 -0
  396. /package/frontend/{lib/services → services}/terminal/persistence.service.ts +0 -0
  397. /package/frontend/{lib/services → services}/terminal/session.service.ts +0 -0
  398. /package/frontend/{lib/stores → stores}/core/files.svelte.ts +0 -0
  399. /package/frontend/{lib/stores → stores}/ui/chat-input.svelte.ts +0 -0
  400. /package/frontend/{lib/stores → stores}/ui/chat-model.svelte.ts +0 -0
  401. /package/frontend/{lib/stores → stores}/ui/connection.svelte.ts +0 -0
  402. /package/frontend/{lib/stores → stores}/ui/dialog.svelte.ts +0 -0
  403. /package/frontend/{lib/stores → stores}/ui/notification.svelte.ts +0 -0
  404. /package/frontend/{lib/stores → stores}/ui/settings-modal.svelte.ts +0 -0
  405. /package/frontend/{lib/stores → stores}/ui/theme.svelte.ts +0 -0
  406. /package/frontend/{lib/stores → stores}/ui/workspace.svelte.ts +0 -0
  407. /package/frontend/{lib/utils → utils}/chat/date-separator.ts +0 -0
  408. /package/frontend/{lib/utils → utils}/chat/message-grouper.ts +0 -0
  409. /package/frontend/{lib/utils → utils}/chat/message-processor.ts +0 -0
  410. /package/frontend/{lib/utils → utils}/chat/tool-handler.ts +0 -0
  411. /package/frontend/{lib/utils → utils}/chat/virtual-scroll.svelte.ts +0 -0
  412. /package/frontend/{lib/utils → utils}/click-outside.ts +0 -0
  413. /package/frontend/{lib/utils → utils}/context-manager.ts +0 -0
  414. /package/frontend/{lib/utils → utils}/file-icon-mappings.ts +0 -0
  415. /package/frontend/{lib/utils → utils}/folder-icon-mappings.ts +0 -0
  416. /package/frontend/{lib/utils → utils}/git-status.ts +0 -0
  417. /package/frontend/{lib/types → utils}/native-ui.ts +0 -0
  418. /package/frontend/{lib/utils → utils}/platform.ts +0 -0
  419. /package/frontend/{lib/utils → utils}/port-check.ts +0 -0
  420. /package/frontend/{lib/constants/preview.ts → utils/preview-constants.ts} +0 -0
  421. /package/frontend/{lib/utils/terminalFormatter.ts → utils/terminal-formatter.ts} +0 -0
  422. /package/frontend/{lib/utils → utils}/tree-visualizer.ts +0 -0
@@ -1,117 +1,117 @@
1
- /**
2
- * Global Stream Monitor Service
3
- *
4
- * Single source of truth for chat stream notifications (sound + push).
5
- *
6
- * Listens for backend events and triggers notifications for ALL projects —
7
- * both active and non-active:
8
- * - chat:stream-finished → stream completed/errored/cancelled
9
- * - chat:waiting-input → AskUserQuestion requires user input
10
- *
11
- * The backend uses ws.emit.projectMembers() so notifications reach users
12
- * even when they are on a different project or session.
13
- */
14
-
15
- import { soundNotification, pushNotification } from '$frontend/lib/services/notification';
16
- import { projectState } from '$frontend/lib/stores/core/projects.svelte';
17
- import { debug } from '$shared/utils/logger';
18
- import ws from '$frontend/lib/utils/ws';
19
-
20
- class GlobalStreamMonitor {
21
- private initialized = false;
22
-
23
- /** Track notified AskUserQuestion tool_use IDs to ensure once-only notification */
24
- private notifiedToolUseIds = new Set<string>();
25
-
26
- /**
27
- * Initialize the monitor - subscribes to WS events.
28
- * Safe to call multiple times (idempotent).
29
- */
30
- initialize(): void {
31
- if (this.initialized) return;
32
- this.initialized = true;
33
-
34
- debug.log('notification', 'GlobalStreamMonitor: Initializing WS listeners');
35
-
36
- // Stream finished — notify on completion
37
- ws.on('chat:stream-finished', async (data) => {
38
- const { projectId, status, chatSessionId } = data;
39
-
40
- debug.log('notification', 'GlobalStreamMonitor: Stream finished', { projectId, status });
41
-
42
- // Clean up notified IDs for this session (stream is done)
43
- this.clearSessionNotifications(chatSessionId);
44
-
45
- // Play sound notification
46
- try {
47
- await soundNotification.play();
48
- } catch (error) {
49
- debug.error('notification', 'Error playing sound notification:', error);
50
- }
51
-
52
- // Send push notification with project context
53
- try {
54
- const projectName = projectState.projects.find(p => p.id === projectId)?.name || 'Unknown';
55
-
56
- if (status === 'completed') {
57
- await pushNotification.sendChatComplete(`Chat response ready in "${projectName}"`);
58
- } else if (status === 'error') {
59
- await pushNotification.sendChatError(`Chat error in "${projectName}"`);
60
- } else if (status === 'cancelled') {
61
- await pushNotification.sendChatComplete(`Chat interrupted in "${projectName}"`);
62
- }
63
- } catch (error) {
64
- debug.error('notification', 'Error sending push notification:', error);
65
- }
66
- });
67
-
68
- // Waiting for input — notify once per AskUserQuestion
69
- ws.on('chat:waiting-input', async (data) => {
70
- const { projectId, chatSessionId, toolUseId } = data;
71
-
72
- // Deduplicate: only notify once per tool_use ID
73
- if (this.notifiedToolUseIds.has(toolUseId)) return;
74
- this.notifiedToolUseIds.add(toolUseId);
75
-
76
- debug.log('notification', 'GlobalStreamMonitor: Waiting for input', { projectId, chatSessionId, toolUseId });
77
-
78
- // Play sound notification
79
- try {
80
- await soundNotification.play();
81
- } catch (error) {
82
- debug.error('notification', 'Error playing sound notification:', error);
83
- }
84
-
85
- // Send push notification
86
- try {
87
- const projectName = projectState.projects.find(p => p.id === projectId)?.name || 'Unknown';
88
- await pushNotification.sendChatComplete(`Waiting for your input in "${projectName}"`);
89
- } catch (error) {
90
- debug.error('notification', 'Error sending push notification:', error);
91
- }
92
- });
93
- }
94
-
95
- /**
96
- * Remove tracked tool_use IDs for a finished session
97
- */
98
- private clearSessionNotifications(chatSessionId: string): void {
99
- // Tool IDs are globally unique, so a simple clear-on-stream-finish
100
- // is enough — they won't collide across sessions.
101
- // For long-running apps, periodically trim to avoid unbounded growth.
102
- if (this.notifiedToolUseIds.size > 500) {
103
- this.notifiedToolUseIds.clear();
104
- }
105
- }
106
-
107
- /**
108
- * Clear state (for cleanup/testing)
109
- */
110
- clear(): void {
111
- this.notifiedToolUseIds.clear();
112
- debug.log('notification', 'GlobalStreamMonitor: Clearing state');
113
- }
114
- }
115
-
116
- // Export singleton instance
117
- export const globalStreamMonitor = new GlobalStreamMonitor();
1
+ /**
2
+ * Global Stream Monitor Service
3
+ *
4
+ * Single source of truth for chat stream notifications (sound + push).
5
+ *
6
+ * Listens for backend events and triggers notifications for ALL projects —
7
+ * both active and non-active:
8
+ * - chat:stream-finished → stream completed/errored/cancelled
9
+ * - chat:waiting-input → AskUserQuestion requires user input
10
+ *
11
+ * The backend uses ws.emit.projectMembers() so notifications reach users
12
+ * even when they are on a different project or session.
13
+ */
14
+
15
+ import { soundNotification, pushNotification } from '$frontend/services/notification';
16
+ import { projectState } from '$frontend/stores/core/projects.svelte';
17
+ import { debug } from '$shared/utils/logger';
18
+ import ws from '$frontend/utils/ws';
19
+
20
+ class GlobalStreamMonitor {
21
+ private initialized = false;
22
+
23
+ /** Track notified AskUserQuestion tool_use IDs to ensure once-only notification */
24
+ private notifiedToolUseIds = new Set<string>();
25
+
26
+ /**
27
+ * Initialize the monitor - subscribes to WS events.
28
+ * Safe to call multiple times (idempotent).
29
+ */
30
+ initialize(): void {
31
+ if (this.initialized) return;
32
+ this.initialized = true;
33
+
34
+ debug.log('notification', 'GlobalStreamMonitor: Initializing WS listeners');
35
+
36
+ // Stream finished — notify on completion
37
+ ws.on('chat:stream-finished', async (data) => {
38
+ const { projectId, status, chatSessionId } = data;
39
+
40
+ debug.log('notification', 'GlobalStreamMonitor: Stream finished', { projectId, status });
41
+
42
+ // Clean up notified IDs for this session (stream is done)
43
+ this.clearSessionNotifications(chatSessionId);
44
+
45
+ // Play sound notification
46
+ try {
47
+ await soundNotification.play();
48
+ } catch (error) {
49
+ debug.error('notification', 'Error playing sound notification:', error);
50
+ }
51
+
52
+ // Send push notification with project context
53
+ try {
54
+ const projectName = projectState.projects.find(p => p.id === projectId)?.name || 'Unknown';
55
+
56
+ if (status === 'completed') {
57
+ await pushNotification.sendChatComplete(`Chat response ready in "${projectName}"`);
58
+ } else if (status === 'error') {
59
+ await pushNotification.sendChatError(`Chat error in "${projectName}"`);
60
+ } else if (status === 'cancelled') {
61
+ await pushNotification.sendChatComplete(`Chat interrupted in "${projectName}"`);
62
+ }
63
+ } catch (error) {
64
+ debug.error('notification', 'Error sending push notification:', error);
65
+ }
66
+ });
67
+
68
+ // Waiting for input — notify once per AskUserQuestion
69
+ ws.on('chat:waiting-input', async (data) => {
70
+ const { projectId, chatSessionId, toolUseId } = data;
71
+
72
+ // Deduplicate: only notify once per tool_use ID
73
+ if (this.notifiedToolUseIds.has(toolUseId)) return;
74
+ this.notifiedToolUseIds.add(toolUseId);
75
+
76
+ debug.log('notification', 'GlobalStreamMonitor: Waiting for input', { projectId, chatSessionId, toolUseId });
77
+
78
+ // Play sound notification
79
+ try {
80
+ await soundNotification.play();
81
+ } catch (error) {
82
+ debug.error('notification', 'Error playing sound notification:', error);
83
+ }
84
+
85
+ // Send push notification
86
+ try {
87
+ const projectName = projectState.projects.find(p => p.id === projectId)?.name || 'Unknown';
88
+ await pushNotification.sendChatComplete(`Waiting for your input in "${projectName}"`);
89
+ } catch (error) {
90
+ debug.error('notification', 'Error sending push notification:', error);
91
+ }
92
+ });
93
+ }
94
+
95
+ /**
96
+ * Remove tracked tool_use IDs for a finished session
97
+ */
98
+ private clearSessionNotifications(chatSessionId: string): void {
99
+ // Tool IDs are globally unique, so a simple clear-on-stream-finish
100
+ // is enough — they won't collide across sessions.
101
+ // For long-running apps, periodically trim to avoid unbounded growth.
102
+ if (this.notifiedToolUseIds.size > 500) {
103
+ this.notifiedToolUseIds.clear();
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Clear state (for cleanup/testing)
109
+ */
110
+ clear(): void {
111
+ this.notifiedToolUseIds.clear();
112
+ debug.log('notification', 'GlobalStreamMonitor: Clearing state');
113
+ }
114
+ }
115
+
116
+ // Export singleton instance
117
+ export const globalStreamMonitor = new GlobalStreamMonitor();
@@ -4,7 +4,7 @@
4
4
  * Handles native browser push notifications for chat responses
5
5
  */
6
6
 
7
- import { settings } from '$frontend/lib/stores/features/settings.svelte';
7
+ import { settings } from '$frontend/stores/features/settings.svelte';
8
8
 
9
9
  import { debug } from '$shared/utils/logger';
10
10
  // Check if browser supports notifications
@@ -4,7 +4,7 @@
4
4
  * Handles single audio notification for chat responses using local notification.ogg file
5
5
  */
6
6
 
7
- import { settings } from '$frontend/lib/stores/features/settings.svelte';
7
+ import { settings } from '$frontend/stores/features/settings.svelte';
8
8
 
9
9
  import { debug } from '$shared/utils/logger';
10
10
  // Cache for audio element
@@ -1,5 +1,5 @@
1
1
  import { debug } from '$shared/utils/logger';
2
- import ws from '$frontend/lib/utils/ws';
2
+ import ws from '$frontend/utils/ws';
3
3
 
4
4
  export interface ConsoleMessage {
5
5
  id: string;
@@ -14,7 +14,7 @@
14
14
  * 7. Render video to canvas, play audio
15
15
  */
16
16
 
17
- import ws from '$frontend/lib/utils/ws';
17
+ import ws from '$frontend/utils/ws';
18
18
  import { debug } from '$shared/utils/logger';
19
19
 
20
20
  export interface BrowserWebCodecsStreamStats {
@@ -5,8 +5,8 @@
5
5
  * opens the preview panel to display the session visually.
6
6
  */
7
7
 
8
- import ws from '$frontend/lib/utils/ws';
9
- import { showPanel } from '$frontend/lib/stores/ui/workspace.svelte';
8
+ import ws from '$frontend/utils/ws';
9
+ import { showPanel } from '$frontend/stores/ui/workspace.svelte';
10
10
  import { debug } from '$shared/utils/logger';
11
11
 
12
12
  export interface MCPLaunchRequest {
@@ -1,160 +1,160 @@
1
- /**
2
- * Project Status Service
3
- * Tracks active streams and user presence for projects via WebSocket
4
- * Fully realtime - no cache, no polling
5
- *
6
- * Single event: `projects:presence-updated` contains full state
7
- */
8
-
9
- import { getOrCreateAnonymousUser, type AnonymousUser } from '$shared/utils/anonymous-user';
10
- import ws from '$frontend/lib/utils/ws';
11
- import { debug } from '$shared/utils/logger';
12
-
13
- export interface ProjectStatus {
14
- projectId: string;
15
- hasActiveStreams: boolean;
16
- activeStreamCount: number;
17
- activeUsers: { userId: string; userName: string }[];
18
- streams: {
19
- streamId: string;
20
- chatSessionId: string;
21
- status: string;
22
- startedAt: string;
23
- messagesCount: number;
24
- isWaitingInput?: boolean;
25
- }[];
26
- /** Per-chat-session user presence: { chatSessionId → users[] } */
27
- chatSessionUsers?: Record<string, { userId: string; userName: string }[]>;
28
- }
29
-
30
- class ProjectStatusService {
31
- private currentUser: AnonymousUser | null = null;
32
- private currentProjectId: string | null = null;
33
- private initialized = false;
34
- private statusUpdateCallbacks: Set<(statuses: ProjectStatus[]) => void> = new Set();
35
- private unsubscribe: (() => void) | null = null;
36
-
37
- /**
38
- * Initialize the service - sets up WS listener
39
- * Called automatically on first use
40
- */
41
- async initialize(): Promise<void> {
42
- if (typeof window === 'undefined' || this.initialized) return;
43
-
44
- this.currentUser = await getOrCreateAnonymousUser();
45
- debug.log('project', 'Initialized with user:', this.currentUser?.name);
46
-
47
- this.unsubscribe = ws.on('projects:presence-updated', (data) => {
48
- try {
49
- if (data.type === 'presence-updated' && data.data) {
50
- const statuses = Array.isArray(data.data) ? data.data : [data.data];
51
- this.statusUpdateCallbacks.forEach(callback => {
52
- try {
53
- callback(statuses);
54
- } catch (error) {
55
- debug.error('project', 'Error in status callback:', error);
56
- }
57
- });
58
- }
59
- } catch (error) {
60
- debug.error('project', 'Error handling presence update:', error);
61
- }
62
- });
63
-
64
- this.initialized = true;
65
- }
66
-
67
- private async ensureInitialized(): Promise<void> {
68
- if (!this.initialized) {
69
- await this.initialize();
70
- }
71
- }
72
-
73
- /**
74
- * Subscribe to real-time presence updates
75
- * Auto-initializes WS listener if not done yet
76
- */
77
- onStatusUpdate(callback: (statuses: ProjectStatus[]) => void): () => void {
78
- this.statusUpdateCallbacks.add(callback);
79
- this.ensureInitialized();
80
-
81
- return () => {
82
- this.statusUpdateCallbacks.delete(callback);
83
- };
84
- }
85
-
86
- /**
87
- * Join a project - start presence tracking
88
- */
89
- async startTracking(projectId: string): Promise<void> {
90
- if (typeof window === 'undefined') return;
91
-
92
- await this.ensureInitialized();
93
-
94
- if (this.currentProjectId && this.currentProjectId !== projectId) {
95
- await this.stopTracking();
96
- }
97
-
98
- this.currentProjectId = projectId;
99
-
100
- if (this.currentUser) {
101
- ws.emit('projects:join', {
102
- userName: this.currentUser.name
103
- });
104
- }
105
-
106
- document.addEventListener('visibilitychange', this.handleVisibilityChange);
107
- window.addEventListener('beforeunload', this.handleBeforeUnload);
108
- }
109
-
110
- /**
111
- * Leave a project - stop presence tracking
112
- */
113
- async stopTracking(): Promise<void> {
114
- if (this.currentProjectId && this.currentUser) {
115
- // Send projectId explicitly because ws.setProject() may have already changed context
116
- ws.emit('projects:leave', {
117
- projectId: this.currentProjectId
118
- });
119
- }
120
-
121
- if (typeof window !== 'undefined') {
122
- document.removeEventListener('visibilitychange', this.handleVisibilityChange);
123
- window.removeEventListener('beforeunload', this.handleBeforeUnload);
124
- }
125
-
126
- this.currentProjectId = null;
127
- }
128
-
129
- cleanup(): void {
130
- if (this.unsubscribe) {
131
- this.unsubscribe();
132
- this.unsubscribe = null;
133
- }
134
- this.statusUpdateCallbacks.clear();
135
- this.initialized = false;
136
- }
137
-
138
- private handleVisibilityChange = () => {
139
- if (!document.hidden && this.currentProjectId && this.currentUser) {
140
- ws.http('projects:update-presence', {
141
- userName: this.currentUser.name,
142
- action: 'update'
143
- }).catch(() => {});
144
- }
145
- };
146
-
147
- private handleBeforeUnload = () => {
148
- if (this.currentProjectId && this.currentUser) {
149
- ws.emit('projects:leave', {
150
- projectId: this.currentProjectId
151
- });
152
- }
153
- };
154
-
155
- getCurrentUser(): AnonymousUser | null {
156
- return this.currentUser;
157
- }
158
- }
159
-
160
- export const projectStatusService = new ProjectStatusService();
1
+ /**
2
+ * Project Status Service
3
+ * Tracks active streams and user presence for projects via WebSocket
4
+ * Fully realtime - no cache, no polling
5
+ *
6
+ * Single event: `projects:presence-updated` contains full state
7
+ */
8
+
9
+ import { getOrCreateAnonymousUser, type AnonymousUser } from '$shared/utils/anonymous-user';
10
+ import ws from '$frontend/utils/ws';
11
+ import { debug } from '$shared/utils/logger';
12
+
13
+ export interface ProjectStatus {
14
+ projectId: string;
15
+ hasActiveStreams: boolean;
16
+ activeStreamCount: number;
17
+ activeUsers: { userId: string; userName: string }[];
18
+ streams: {
19
+ streamId: string;
20
+ chatSessionId: string;
21
+ status: string;
22
+ startedAt: string;
23
+ messagesCount: number;
24
+ isWaitingInput?: boolean;
25
+ }[];
26
+ /** Per-chat-session user presence: { chatSessionId → users[] } */
27
+ chatSessionUsers?: Record<string, { userId: string; userName: string }[]>;
28
+ }
29
+
30
+ class ProjectStatusService {
31
+ private currentUser: AnonymousUser | null = null;
32
+ private currentProjectId: string | null = null;
33
+ private initialized = false;
34
+ private statusUpdateCallbacks: Set<(statuses: ProjectStatus[]) => void> = new Set();
35
+ private unsubscribe: (() => void) | null = null;
36
+
37
+ /**
38
+ * Initialize the service - sets up WS listener
39
+ * Called automatically on first use
40
+ */
41
+ async initialize(): Promise<void> {
42
+ if (typeof window === 'undefined' || this.initialized) return;
43
+
44
+ this.currentUser = await getOrCreateAnonymousUser();
45
+ debug.log('project', 'Initialized with user:', this.currentUser?.name);
46
+
47
+ this.unsubscribe = ws.on('projects:presence-updated', (data) => {
48
+ try {
49
+ if (data.type === 'presence-updated' && data.data) {
50
+ const statuses = Array.isArray(data.data) ? data.data : [data.data];
51
+ this.statusUpdateCallbacks.forEach(callback => {
52
+ try {
53
+ callback(statuses);
54
+ } catch (error) {
55
+ debug.error('project', 'Error in status callback:', error);
56
+ }
57
+ });
58
+ }
59
+ } catch (error) {
60
+ debug.error('project', 'Error handling presence update:', error);
61
+ }
62
+ });
63
+
64
+ this.initialized = true;
65
+ }
66
+
67
+ private async ensureInitialized(): Promise<void> {
68
+ if (!this.initialized) {
69
+ await this.initialize();
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Subscribe to real-time presence updates
75
+ * Auto-initializes WS listener if not done yet
76
+ */
77
+ onStatusUpdate(callback: (statuses: ProjectStatus[]) => void): () => void {
78
+ this.statusUpdateCallbacks.add(callback);
79
+ this.ensureInitialized();
80
+
81
+ return () => {
82
+ this.statusUpdateCallbacks.delete(callback);
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Join a project - start presence tracking
88
+ */
89
+ async startTracking(projectId: string): Promise<void> {
90
+ if (typeof window === 'undefined') return;
91
+
92
+ await this.ensureInitialized();
93
+
94
+ if (this.currentProjectId && this.currentProjectId !== projectId) {
95
+ await this.stopTracking();
96
+ }
97
+
98
+ this.currentProjectId = projectId;
99
+
100
+ if (this.currentUser) {
101
+ ws.emit('projects:join', {
102
+ userName: this.currentUser.name
103
+ });
104
+ }
105
+
106
+ document.addEventListener('visibilitychange', this.handleVisibilityChange);
107
+ window.addEventListener('beforeunload', this.handleBeforeUnload);
108
+ }
109
+
110
+ /**
111
+ * Leave a project - stop presence tracking
112
+ */
113
+ async stopTracking(): Promise<void> {
114
+ if (this.currentProjectId && this.currentUser) {
115
+ // Send projectId explicitly because ws.setProject() may have already changed context
116
+ ws.emit('projects:leave', {
117
+ projectId: this.currentProjectId
118
+ });
119
+ }
120
+
121
+ if (typeof window !== 'undefined') {
122
+ document.removeEventListener('visibilitychange', this.handleVisibilityChange);
123
+ window.removeEventListener('beforeunload', this.handleBeforeUnload);
124
+ }
125
+
126
+ this.currentProjectId = null;
127
+ }
128
+
129
+ cleanup(): void {
130
+ if (this.unsubscribe) {
131
+ this.unsubscribe();
132
+ this.unsubscribe = null;
133
+ }
134
+ this.statusUpdateCallbacks.clear();
135
+ this.initialized = false;
136
+ }
137
+
138
+ private handleVisibilityChange = () => {
139
+ if (!document.hidden && this.currentProjectId && this.currentUser) {
140
+ ws.http('projects:update-presence', {
141
+ userName: this.currentUser.name,
142
+ action: 'update'
143
+ }).catch(() => {});
144
+ }
145
+ };
146
+
147
+ private handleBeforeUnload = () => {
148
+ if (this.currentProjectId && this.currentUser) {
149
+ ws.emit('projects:leave', {
150
+ projectId: this.currentProjectId
151
+ });
152
+ }
153
+ };
154
+
155
+ getCurrentUser(): AnonymousUser | null {
156
+ return this.currentUser;
157
+ }
158
+ }
159
+
160
+ export const projectStatusService = new ProjectStatusService();
@@ -5,8 +5,8 @@
5
5
  * v2 adds conflict detection and session-scoped restore.
6
6
  */
7
7
 
8
- import ws from '$frontend/lib/utils/ws';
9
- import type { TimelineResponse } from '$frontend/lib/components/checkpoint/timeline/types';
8
+ import ws from '$frontend/utils/ws';
9
+ import type { TimelineResponse } from '$frontend/components/checkpoint/timeline/types';
10
10
 
11
11
  /**
12
12
  * Conflict information for a single file
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { terminalSessionManager } from '../session.service';
7
7
  import { terminalPersistenceManager } from '../persistence.service';
8
- import { terminalStore } from '$frontend/lib/stores/features/terminal.svelte';
8
+ import { terminalStore } from '$frontend/stores/features/terminal.svelte';
9
9
 
10
10
  // Import modular services
11
11
  import { streamManager } from './stream-manager';
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { terminalSessionManager } from '../session.service';
7
7
  import { terminalPersistenceManager } from '../persistence.service';
8
- import { terminalStore } from '$frontend/lib/stores/features/terminal.svelte';
8
+ import { terminalStore } from '$frontend/stores/features/terminal.svelte';
9
9
 
10
10
  interface SessionToReconnect {
11
11
  sessionId: string;
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { terminalSessionManager } from '../session.service';
7
7
  import { terminalPersistenceManager } from '../persistence.service';
8
- import { terminalStore } from '$frontend/lib/stores/features/terminal.svelte';
8
+ import { terminalStore } from '$frontend/stores/features/terminal.svelte';
9
9
  import type { TerminalLine } from '$shared/types/terminal';
10
10
 
11
11
  export interface StreamInfo {