@myrialabs/clopen 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (456) hide show
  1. package/.env.example +6 -0
  2. package/.github/workflows/release.yml +60 -0
  3. package/.github/workflows/test.yml +40 -0
  4. package/CONTRIBUTING.md +499 -0
  5. package/LICENSE +21 -0
  6. package/README.md +209 -0
  7. package/backend/index.ts +156 -0
  8. package/backend/lib/chat/helpers.ts +42 -0
  9. package/backend/lib/chat/index.ts +2 -0
  10. package/backend/lib/chat/stream-manager.ts +1126 -0
  11. package/backend/lib/database/README.md +77 -0
  12. package/backend/lib/database/index.ts +119 -0
  13. package/backend/lib/database/migrations/001_create_projects_table.ts +31 -0
  14. package/backend/lib/database/migrations/002_create_chat_sessions_table.ts +33 -0
  15. package/backend/lib/database/migrations/003_create_messages_table.ts +32 -0
  16. package/backend/lib/database/migrations/004_create_prompt_templates_table.ts +34 -0
  17. package/backend/lib/database/migrations/005_create_settings_table.ts +24 -0
  18. package/backend/lib/database/migrations/006_add_user_to_messages.ts +58 -0
  19. package/backend/lib/database/migrations/007_create_stream_states_table.ts +41 -0
  20. package/backend/lib/database/migrations/008_create_message_snapshots_table.ts +62 -0
  21. package/backend/lib/database/migrations/009_add_delta_snapshot_fields.ts +41 -0
  22. package/backend/lib/database/migrations/010_add_soft_delete_and_branch_support.ts +70 -0
  23. package/backend/lib/database/migrations/011_git_like_commit_graph.ts +156 -0
  24. package/backend/lib/database/migrations/012_add_file_change_statistics.ts +41 -0
  25. package/backend/lib/database/migrations/013_checkpoint_tree_state.ts +118 -0
  26. package/backend/lib/database/migrations/014_add_engine_to_sessions.ts +18 -0
  27. package/backend/lib/database/migrations/015_add_model_to_sessions.ts +18 -0
  28. package/backend/lib/database/migrations/016_create_user_projects_table.ts +34 -0
  29. package/backend/lib/database/migrations/017_add_current_session_to_user_projects.ts +32 -0
  30. package/backend/lib/database/migrations/018_create_claude_accounts_table.ts +24 -0
  31. package/backend/lib/database/migrations/019_add_claude_account_to_sessions.ts +18 -0
  32. package/backend/lib/database/migrations/020_add_snapshot_tree_hash.ts +32 -0
  33. package/backend/lib/database/migrations/021_drop_prompt_templates_table.ts +33 -0
  34. package/backend/lib/database/migrations/index.ts +154 -0
  35. package/backend/lib/database/queries/checkpoint-queries.ts +87 -0
  36. package/backend/lib/database/queries/engine-queries.ts +75 -0
  37. package/backend/lib/database/queries/index.ts +9 -0
  38. package/backend/lib/database/queries/message-queries.ts +472 -0
  39. package/backend/lib/database/queries/project-queries.ts +117 -0
  40. package/backend/lib/database/queries/session-queries.ts +271 -0
  41. package/backend/lib/database/queries/settings-queries.ts +34 -0
  42. package/backend/lib/database/queries/snapshot-queries.ts +326 -0
  43. package/backend/lib/database/queries/utils-queries.ts +59 -0
  44. package/backend/lib/database/seeders/index.ts +13 -0
  45. package/backend/lib/database/seeders/settings_seeder.ts +84 -0
  46. package/backend/lib/database/utils/connection.ts +174 -0
  47. package/backend/lib/database/utils/index.ts +4 -0
  48. package/backend/lib/database/utils/migration-runner.ts +118 -0
  49. package/backend/lib/database/utils/seeder-runner.ts +121 -0
  50. package/backend/lib/engine/adapters/claude/environment.ts +164 -0
  51. package/backend/lib/engine/adapters/claude/error-handler.ts +60 -0
  52. package/backend/lib/engine/adapters/claude/index.ts +1 -0
  53. package/backend/lib/engine/adapters/claude/path-utils.ts +38 -0
  54. package/backend/lib/engine/adapters/claude/stream.ts +177 -0
  55. package/backend/lib/engine/adapters/opencode/index.ts +2 -0
  56. package/backend/lib/engine/adapters/opencode/message-converter.ts +862 -0
  57. package/backend/lib/engine/adapters/opencode/server.ts +104 -0
  58. package/backend/lib/engine/adapters/opencode/stream.ts +755 -0
  59. package/backend/lib/engine/index.ts +196 -0
  60. package/backend/lib/engine/types.ts +58 -0
  61. package/backend/lib/files/file-operations.ts +478 -0
  62. package/backend/lib/files/file-reading.ts +308 -0
  63. package/backend/lib/files/file-watcher.ts +383 -0
  64. package/backend/lib/files/path-browsing.ts +382 -0
  65. package/backend/lib/git/git-executor.ts +88 -0
  66. package/backend/lib/git/git-parser.ts +411 -0
  67. package/backend/lib/git/git-service.ts +505 -0
  68. package/backend/lib/mcp/README.md +1144 -0
  69. package/backend/lib/mcp/config.ts +316 -0
  70. package/backend/lib/mcp/index.ts +35 -0
  71. package/backend/lib/mcp/project-context.ts +236 -0
  72. package/backend/lib/mcp/servers/browser-automation/actions.ts +156 -0
  73. package/backend/lib/mcp/servers/browser-automation/browser.ts +419 -0
  74. package/backend/lib/mcp/servers/browser-automation/index.ts +791 -0
  75. package/backend/lib/mcp/servers/browser-automation/inspection.ts +501 -0
  76. package/backend/lib/mcp/servers/helper.ts +143 -0
  77. package/backend/lib/mcp/servers/index.ts +45 -0
  78. package/backend/lib/mcp/servers/weather/get-temperature.ts +56 -0
  79. package/backend/lib/mcp/servers/weather/index.ts +31 -0
  80. package/backend/lib/mcp/stdio-server.ts +103 -0
  81. package/backend/lib/mcp/types.ts +65 -0
  82. package/backend/lib/preview/browser/browser-audio-capture.ts +86 -0
  83. package/backend/lib/preview/browser/browser-console-manager.ts +263 -0
  84. package/backend/lib/preview/browser/browser-dialog-handler.ts +222 -0
  85. package/backend/lib/preview/browser/browser-interaction-handler.ts +421 -0
  86. package/backend/lib/preview/browser/browser-mcp-control.ts +415 -0
  87. package/backend/lib/preview/browser/browser-native-ui-handler.ts +512 -0
  88. package/backend/lib/preview/browser/browser-navigation-tracker.ts +104 -0
  89. package/backend/lib/preview/browser/browser-pool.ts +357 -0
  90. package/backend/lib/preview/browser/browser-preview-service.ts +882 -0
  91. package/backend/lib/preview/browser/browser-tab-manager.ts +935 -0
  92. package/backend/lib/preview/browser/browser-video-capture.ts +695 -0
  93. package/backend/lib/preview/browser/scripts/audio-stream.ts +292 -0
  94. package/backend/lib/preview/browser/scripts/cursor-tracking.ts +85 -0
  95. package/backend/lib/preview/browser/scripts/video-stream.ts +438 -0
  96. package/backend/lib/preview/browser/types.ts +359 -0
  97. package/backend/lib/preview/index.ts +24 -0
  98. package/backend/lib/project/index.ts +2 -0
  99. package/backend/lib/project/status-manager.ts +182 -0
  100. package/backend/lib/shared/index.ts +2 -0
  101. package/backend/lib/shared/port-utils.ts +25 -0
  102. package/backend/lib/shared/process-manager.ts +281 -0
  103. package/backend/lib/snapshot/blob-store.ts +227 -0
  104. package/backend/lib/snapshot/gitignore.ts +307 -0
  105. package/backend/lib/snapshot/helpers.ts +397 -0
  106. package/backend/lib/snapshot/snapshot-service.ts +483 -0
  107. package/backend/lib/terminal/helpers.ts +14 -0
  108. package/backend/lib/terminal/index.ts +8 -0
  109. package/backend/lib/terminal/pty-manager.ts +4 -0
  110. package/backend/lib/terminal/pty-session-manager.ts +387 -0
  111. package/backend/lib/terminal/shell-utils.ts +313 -0
  112. package/backend/lib/terminal/stream-manager.ts +293 -0
  113. package/backend/lib/tunnel/global-tunnel-manager.ts +243 -0
  114. package/backend/lib/tunnel/project-tunnel-manager.ts +311 -0
  115. package/backend/lib/user/helpers.ts +87 -0
  116. package/backend/lib/utils/ws.ts +944 -0
  117. package/backend/lib/vite-dev.ts +353 -0
  118. package/backend/middleware/cors.ts +15 -0
  119. package/backend/middleware/error-handler.ts +49 -0
  120. package/backend/middleware/logger.ts +9 -0
  121. package/backend/types/api.ts +24 -0
  122. package/backend/ws/README.md +1505 -0
  123. package/backend/ws/chat/background.ts +198 -0
  124. package/backend/ws/chat/index.ts +21 -0
  125. package/backend/ws/chat/stream.ts +707 -0
  126. package/backend/ws/engine/claude/accounts.ts +401 -0
  127. package/backend/ws/engine/claude/index.ts +13 -0
  128. package/backend/ws/engine/claude/status.ts +43 -0
  129. package/backend/ws/engine/index.ts +14 -0
  130. package/backend/ws/engine/opencode/index.ts +11 -0
  131. package/backend/ws/engine/opencode/status.ts +30 -0
  132. package/backend/ws/engine/utils.ts +36 -0
  133. package/backend/ws/files/index.ts +30 -0
  134. package/backend/ws/files/read.ts +189 -0
  135. package/backend/ws/files/search.ts +453 -0
  136. package/backend/ws/files/watch.ts +124 -0
  137. package/backend/ws/files/write.ts +143 -0
  138. package/backend/ws/git/branch.ts +106 -0
  139. package/backend/ws/git/commit.ts +39 -0
  140. package/backend/ws/git/conflict.ts +68 -0
  141. package/backend/ws/git/diff.ts +69 -0
  142. package/backend/ws/git/index.ts +24 -0
  143. package/backend/ws/git/log.ts +41 -0
  144. package/backend/ws/git/remote.ts +214 -0
  145. package/backend/ws/git/staging.ts +84 -0
  146. package/backend/ws/git/status.ts +90 -0
  147. package/backend/ws/index.ts +69 -0
  148. package/backend/ws/mcp/index.ts +61 -0
  149. package/backend/ws/messages/crud.ts +74 -0
  150. package/backend/ws/messages/index.ts +14 -0
  151. package/backend/ws/preview/browser/cleanup.ts +129 -0
  152. package/backend/ws/preview/browser/console.ts +114 -0
  153. package/backend/ws/preview/browser/interact.ts +513 -0
  154. package/backend/ws/preview/browser/mcp.ts +129 -0
  155. package/backend/ws/preview/browser/native-ui.ts +235 -0
  156. package/backend/ws/preview/browser/stats.ts +55 -0
  157. package/backend/ws/preview/browser/tab-info.ts +126 -0
  158. package/backend/ws/preview/browser/tab.ts +166 -0
  159. package/backend/ws/preview/browser/webcodecs.ts +293 -0
  160. package/backend/ws/preview/index.ts +146 -0
  161. package/backend/ws/projects/crud.ts +113 -0
  162. package/backend/ws/projects/index.ts +25 -0
  163. package/backend/ws/projects/presence.ts +46 -0
  164. package/backend/ws/projects/status.ts +116 -0
  165. package/backend/ws/sessions/crud.ts +327 -0
  166. package/backend/ws/sessions/index.ts +33 -0
  167. package/backend/ws/settings/crud.ts +112 -0
  168. package/backend/ws/settings/index.ts +14 -0
  169. package/backend/ws/snapshot/index.ts +17 -0
  170. package/backend/ws/snapshot/restore.ts +173 -0
  171. package/backend/ws/snapshot/timeline.ts +141 -0
  172. package/backend/ws/system/index.ts +14 -0
  173. package/backend/ws/system/operations.ts +49 -0
  174. package/backend/ws/terminal/index.ts +40 -0
  175. package/backend/ws/terminal/persistence.ts +153 -0
  176. package/backend/ws/terminal/session.ts +382 -0
  177. package/backend/ws/terminal/stream.ts +79 -0
  178. package/backend/ws/tunnel/index.ts +14 -0
  179. package/backend/ws/tunnel/operations.ts +91 -0
  180. package/backend/ws/types.ts +20 -0
  181. package/backend/ws/user/crud.ts +156 -0
  182. package/backend/ws/user/index.ts +14 -0
  183. package/bin/clopen.ts +307 -0
  184. package/bun.lock +1352 -0
  185. package/frontend/App.svelte +34 -0
  186. package/frontend/app.css +313 -0
  187. package/frontend/lib/app-environment.ts +10 -0
  188. package/frontend/lib/components/chat/ChatInterface.svelte +407 -0
  189. package/frontend/lib/components/chat/formatters/ErrorMessage.svelte +57 -0
  190. package/frontend/lib/components/chat/formatters/MessageFormatter.svelte +224 -0
  191. package/frontend/lib/components/chat/formatters/TextMessage.svelte +395 -0
  192. package/frontend/lib/components/chat/formatters/Tools.svelte +70 -0
  193. package/frontend/lib/components/chat/formatters/index.ts +3 -0
  194. package/frontend/lib/components/chat/input/ChatInput.svelte +421 -0
  195. package/frontend/lib/components/chat/input/components/ChatInputActions.svelte +78 -0
  196. package/frontend/lib/components/chat/input/components/DragDropOverlay.svelte +30 -0
  197. package/frontend/lib/components/chat/input/components/EditModeIndicator.svelte +33 -0
  198. package/frontend/lib/components/chat/input/components/EngineModelPicker.svelte +619 -0
  199. package/frontend/lib/components/chat/input/components/FileAttachmentPreview.svelte +48 -0
  200. package/frontend/lib/components/chat/input/components/LoadingIndicator.svelte +31 -0
  201. package/frontend/lib/components/chat/input/composables/use-animations.svelte.ts +201 -0
  202. package/frontend/lib/components/chat/input/composables/use-chat-actions.svelte.ts +148 -0
  203. package/frontend/lib/components/chat/input/composables/use-file-handling.svelte.ts +216 -0
  204. package/frontend/lib/components/chat/input/composables/use-input-state.svelte.ts +357 -0
  205. package/frontend/lib/components/chat/input/composables/use-textarea-resize.svelte.ts +57 -0
  206. package/frontend/lib/components/chat/message/ChatMessage.svelte +478 -0
  207. package/frontend/lib/components/chat/message/ChatMessages.svelte +541 -0
  208. package/frontend/lib/components/chat/message/DateSeparator.svelte +86 -0
  209. package/frontend/lib/components/chat/message/MessageBubble.svelte +86 -0
  210. package/frontend/lib/components/chat/message/MessageHeader.svelte +157 -0
  211. package/frontend/lib/components/chat/modal/DebugModal.svelte +59 -0
  212. package/frontend/lib/components/chat/modal/TokenUsageModal.svelte +124 -0
  213. package/frontend/lib/components/chat/shared/index.ts +2 -0
  214. package/frontend/lib/components/chat/shared/utils.ts +116 -0
  215. package/frontend/lib/components/chat/tools/BashOutputTool.svelte +35 -0
  216. package/frontend/lib/components/chat/tools/BashTool.svelte +46 -0
  217. package/frontend/lib/components/chat/tools/CustomMcpTool.svelte +139 -0
  218. package/frontend/lib/components/chat/tools/EditTool.svelte +48 -0
  219. package/frontend/lib/components/chat/tools/ExitPlanModeTool.svelte +32 -0
  220. package/frontend/lib/components/chat/tools/GlobTool.svelte +51 -0
  221. package/frontend/lib/components/chat/tools/GrepTool.svelte +90 -0
  222. package/frontend/lib/components/chat/tools/KillShellTool.svelte +26 -0
  223. package/frontend/lib/components/chat/tools/ListMcpResourcesTool.svelte +31 -0
  224. package/frontend/lib/components/chat/tools/NotebookEditTool.svelte +38 -0
  225. package/frontend/lib/components/chat/tools/ReadMcpResourceTool.svelte +34 -0
  226. package/frontend/lib/components/chat/tools/ReadTool.svelte +41 -0
  227. package/frontend/lib/components/chat/tools/TaskTool.svelte +64 -0
  228. package/frontend/lib/components/chat/tools/TodoWriteTool.svelte +75 -0
  229. package/frontend/lib/components/chat/tools/WebFetchTool.svelte +35 -0
  230. package/frontend/lib/components/chat/tools/WebSearchTool.svelte +84 -0
  231. package/frontend/lib/components/chat/tools/WriteTool.svelte +33 -0
  232. package/frontend/lib/components/chat/tools/components/CodeBlock.svelte +79 -0
  233. package/frontend/lib/components/chat/tools/components/DiffBlock.svelte +408 -0
  234. package/frontend/lib/components/chat/tools/components/FileHeader.svelte +45 -0
  235. package/frontend/lib/components/chat/tools/components/InfoLine.svelte +19 -0
  236. package/frontend/lib/components/chat/tools/components/StatsBadges.svelte +27 -0
  237. package/frontend/lib/components/chat/tools/components/TerminalCommand.svelte +54 -0
  238. package/frontend/lib/components/chat/tools/components/index.ts +7 -0
  239. package/frontend/lib/components/chat/tools/index.ts +26 -0
  240. package/frontend/lib/components/chat/widgets/FloatingTodoList.svelte +249 -0
  241. package/frontend/lib/components/chat/widgets/TokenUsage.svelte +78 -0
  242. package/frontend/lib/components/checkpoint/TimelineModal.svelte +391 -0
  243. package/frontend/lib/components/checkpoint/timeline/TimelineEdge.svelte +26 -0
  244. package/frontend/lib/components/checkpoint/timeline/TimelineGraph.svelte +87 -0
  245. package/frontend/lib/components/checkpoint/timeline/TimelineNode.svelte +108 -0
  246. package/frontend/lib/components/checkpoint/timeline/TimelineVersionGroup.svelte +59 -0
  247. package/frontend/lib/components/checkpoint/timeline/animation.ts +168 -0
  248. package/frontend/lib/components/checkpoint/timeline/config.ts +44 -0
  249. package/frontend/lib/components/checkpoint/timeline/graph-builder.ts +304 -0
  250. package/frontend/lib/components/checkpoint/timeline/types.ts +65 -0
  251. package/frontend/lib/components/checkpoint/timeline/utils.ts +53 -0
  252. package/frontend/lib/components/common/Alert.svelte +139 -0
  253. package/frontend/lib/components/common/AvatarBubble.svelte +56 -0
  254. package/frontend/lib/components/common/Button.svelte +71 -0
  255. package/frontend/lib/components/common/Card.svelte +102 -0
  256. package/frontend/lib/components/common/Checkbox.svelte +48 -0
  257. package/frontend/lib/components/common/Dialog.svelte +249 -0
  258. package/frontend/lib/components/common/FolderBrowser.svelte +843 -0
  259. package/frontend/lib/components/common/Icon.svelte +58 -0
  260. package/frontend/lib/components/common/Input.svelte +72 -0
  261. package/frontend/lib/components/common/Lightbox.svelte +233 -0
  262. package/frontend/lib/components/common/LoadingScreen.svelte +52 -0
  263. package/frontend/lib/components/common/LoadingSpinner.svelte +48 -0
  264. package/frontend/lib/components/common/Modal.svelte +177 -0
  265. package/frontend/lib/components/common/ModalProvider.svelte +28 -0
  266. package/frontend/lib/components/common/ModelSelector.svelte +110 -0
  267. package/frontend/lib/components/common/MonacoEditor.svelte +569 -0
  268. package/frontend/lib/components/common/NotificationToast.svelte +113 -0
  269. package/frontend/lib/components/common/PageTemplate.svelte +76 -0
  270. package/frontend/lib/components/common/ProjectUserAvatars.svelte +79 -0
  271. package/frontend/lib/components/common/Select.svelte +98 -0
  272. package/frontend/lib/components/common/Textarea.svelte +80 -0
  273. package/frontend/lib/components/common/ThemeToggle.svelte +44 -0
  274. package/frontend/lib/components/common/lucide-icons.ts +1642 -0
  275. package/frontend/lib/components/common/material-icons.ts +1082 -0
  276. package/frontend/lib/components/common/xterm/XTerm.svelte +796 -0
  277. package/frontend/lib/components/common/xterm/index.ts +16 -0
  278. package/frontend/lib/components/common/xterm/terminal-config.ts +68 -0
  279. package/frontend/lib/components/common/xterm/types.ts +31 -0
  280. package/frontend/lib/components/common/xterm/xterm-service.ts +353 -0
  281. package/frontend/lib/components/files/FileNode.svelte +384 -0
  282. package/frontend/lib/components/files/FileTree.svelte +681 -0
  283. package/frontend/lib/components/files/FileViewer.svelte +728 -0
  284. package/frontend/lib/components/files/SearchResults.svelte +303 -0
  285. package/frontend/lib/components/git/BranchManager.svelte +458 -0
  286. package/frontend/lib/components/git/ChangesSection.svelte +107 -0
  287. package/frontend/lib/components/git/CommitForm.svelte +76 -0
  288. package/frontend/lib/components/git/ConflictResolver.svelte +158 -0
  289. package/frontend/lib/components/git/DiffViewer.svelte +364 -0
  290. package/frontend/lib/components/git/FileChangeItem.svelte +97 -0
  291. package/frontend/lib/components/git/GitButton.svelte +33 -0
  292. package/frontend/lib/components/git/GitLog.svelte +361 -0
  293. package/frontend/lib/components/git/GitModal.svelte +80 -0
  294. package/frontend/lib/components/history/HistoryModal.svelte +563 -0
  295. package/frontend/lib/components/history/HistoryView.svelte +615 -0
  296. package/frontend/lib/components/index.ts +34 -0
  297. package/frontend/lib/components/preview/browser/BrowserPreview.svelte +549 -0
  298. package/frontend/lib/components/preview/browser/components/Canvas.svelte +1058 -0
  299. package/frontend/lib/components/preview/browser/components/ConsolePanel.svelte +757 -0
  300. package/frontend/lib/components/preview/browser/components/Container.svelte +450 -0
  301. package/frontend/lib/components/preview/browser/components/ContextMenu.svelte +236 -0
  302. package/frontend/lib/components/preview/browser/components/SelectDropdown.svelte +224 -0
  303. package/frontend/lib/components/preview/browser/components/Toolbar.svelte +339 -0
  304. package/frontend/lib/components/preview/browser/components/VirtualCursor.svelte +36 -0
  305. package/frontend/lib/components/preview/browser/core/cleanup.svelte.ts +155 -0
  306. package/frontend/lib/components/preview/browser/core/coordinator.svelte.ts +837 -0
  307. package/frontend/lib/components/preview/browser/core/interactions.svelte.ts +113 -0
  308. package/frontend/lib/components/preview/browser/core/mcp-handlers.svelte.ts +296 -0
  309. package/frontend/lib/components/preview/browser/core/native-ui-handlers.svelte.ts +391 -0
  310. package/frontend/lib/components/preview/browser/core/stream-handler.svelte.ts +231 -0
  311. package/frontend/lib/components/preview/browser/core/tab-manager.svelte.ts +210 -0
  312. package/frontend/lib/components/preview/browser/core/tab-operations.svelte.ts +239 -0
  313. package/frontend/lib/components/preview/index.ts +2 -0
  314. package/frontend/lib/components/settings/SettingsModal.svelte +235 -0
  315. package/frontend/lib/components/settings/SettingsView.svelte +36 -0
  316. package/frontend/lib/components/settings/appearance/AppearanceSettings.svelte +51 -0
  317. package/frontend/lib/components/settings/appearance/LayoutPresetSettings.svelte +160 -0
  318. package/frontend/lib/components/settings/appearance/LayoutPreview.svelte +76 -0
  319. package/frontend/lib/components/settings/engines/AIEnginesSettings.svelte +917 -0
  320. package/frontend/lib/components/settings/general/AdvancedSettings.svelte +187 -0
  321. package/frontend/lib/components/settings/general/DataManagementSettings.svelte +203 -0
  322. package/frontend/lib/components/settings/general/GeneralSettings.svelte +10 -0
  323. package/frontend/lib/components/settings/model/ModelSettings.svelte +357 -0
  324. package/frontend/lib/components/settings/notifications/NotificationSettings.svelte +205 -0
  325. package/frontend/lib/components/settings/user/UserSettings.svelte +197 -0
  326. package/frontend/lib/components/terminal/Terminal.svelte +368 -0
  327. package/frontend/lib/components/terminal/TerminalTabs.svelte +87 -0
  328. package/frontend/lib/components/terminal/TerminalView.svelte +55 -0
  329. package/frontend/lib/components/tunnel/TunnelActive.svelte +142 -0
  330. package/frontend/lib/components/tunnel/TunnelButton.svelte +54 -0
  331. package/frontend/lib/components/tunnel/TunnelInactive.svelte +284 -0
  332. package/frontend/lib/components/tunnel/TunnelModal.svelte +47 -0
  333. package/frontend/lib/components/tunnel/TunnelQRCode.svelte +49 -0
  334. package/frontend/lib/components/workspace/DesktopNavigator.svelte +382 -0
  335. package/frontend/lib/components/workspace/MobileNavigator.svelte +403 -0
  336. package/frontend/lib/components/workspace/PanelContainer.svelte +100 -0
  337. package/frontend/lib/components/workspace/PanelHeader.svelte +505 -0
  338. package/frontend/lib/components/workspace/ViewMenu.svelte +162 -0
  339. package/frontend/lib/components/workspace/WorkspaceLayout.svelte +169 -0
  340. package/frontend/lib/components/workspace/layout/DesktopLayout.svelte +15 -0
  341. package/frontend/lib/components/workspace/layout/MobileLayout.svelte +17 -0
  342. package/frontend/lib/components/workspace/layout/split-pane/Container.svelte +42 -0
  343. package/frontend/lib/components/workspace/layout/split-pane/Handle.svelte +85 -0
  344. package/frontend/lib/components/workspace/layout/split-pane/Layout.svelte +37 -0
  345. package/frontend/lib/components/workspace/panels/ChatPanel.svelte +274 -0
  346. package/frontend/lib/components/workspace/panels/FilesPanel.svelte +1261 -0
  347. package/frontend/lib/components/workspace/panels/GitPanel.svelte +1560 -0
  348. package/frontend/lib/components/workspace/panels/PreviewPanel.svelte +150 -0
  349. package/frontend/lib/components/workspace/panels/TerminalPanel.svelte +73 -0
  350. package/frontend/lib/constants/preview.ts +45 -0
  351. package/frontend/lib/services/chat/chat.service.ts +704 -0
  352. package/frontend/lib/services/chat/index.ts +7 -0
  353. package/frontend/lib/services/notification/global-stream-monitor.ts +86 -0
  354. package/frontend/lib/services/notification/index.ts +8 -0
  355. package/frontend/lib/services/notification/push.service.ts +144 -0
  356. package/frontend/lib/services/notification/sound.service.ts +127 -0
  357. package/frontend/lib/services/preview/browser/browser-console.service.ts +61 -0
  358. package/frontend/lib/services/preview/browser/browser-webcodecs.service.ts +1499 -0
  359. package/frontend/lib/services/preview/browser/mcp-integration.svelte.ts +67 -0
  360. package/frontend/lib/services/preview/index.ts +23 -0
  361. package/frontend/lib/services/project/index.ts +8 -0
  362. package/frontend/lib/services/project/status.service.ts +159 -0
  363. package/frontend/lib/services/snapshot/snapshot.service.ts +47 -0
  364. package/frontend/lib/services/terminal/background/index.ts +130 -0
  365. package/frontend/lib/services/terminal/background/session-restore.ts +274 -0
  366. package/frontend/lib/services/terminal/background/stream-manager.ts +286 -0
  367. package/frontend/lib/services/terminal/index.ts +14 -0
  368. package/frontend/lib/services/terminal/persistence.service.ts +260 -0
  369. package/frontend/lib/services/terminal/project.service.ts +953 -0
  370. package/frontend/lib/services/terminal/session.service.ts +364 -0
  371. package/frontend/lib/services/terminal/terminal.service.ts +369 -0
  372. package/frontend/lib/stores/core/app.svelte.ts +117 -0
  373. package/frontend/lib/stores/core/files.svelte.ts +73 -0
  374. package/frontend/lib/stores/core/presence.svelte.ts +48 -0
  375. package/frontend/lib/stores/core/projects.svelte.ts +317 -0
  376. package/frontend/lib/stores/core/sessions.svelte.ts +383 -0
  377. package/frontend/lib/stores/features/claude-accounts.svelte.ts +58 -0
  378. package/frontend/lib/stores/features/models.svelte.ts +89 -0
  379. package/frontend/lib/stores/features/settings.svelte.ts +87 -0
  380. package/frontend/lib/stores/features/terminal.svelte.ts +701 -0
  381. package/frontend/lib/stores/features/tunnel.svelte.ts +161 -0
  382. package/frontend/lib/stores/features/user.svelte.ts +96 -0
  383. package/frontend/lib/stores/ui/chat-input.svelte.ts +57 -0
  384. package/frontend/lib/stores/ui/chat-model.svelte.ts +61 -0
  385. package/frontend/lib/stores/ui/dialog.svelte.ts +59 -0
  386. package/frontend/lib/stores/ui/edit-mode.svelte.ts +214 -0
  387. package/frontend/lib/stores/ui/notification.svelte.ts +166 -0
  388. package/frontend/lib/stores/ui/settings-modal.svelte.ts +88 -0
  389. package/frontend/lib/stores/ui/theme.svelte.ts +179 -0
  390. package/frontend/lib/stores/ui/workspace.svelte.ts +754 -0
  391. package/frontend/lib/types/native-ui.ts +73 -0
  392. package/frontend/lib/utils/chat/date-separator.ts +39 -0
  393. package/frontend/lib/utils/chat/message-grouper.ts +219 -0
  394. package/frontend/lib/utils/chat/message-processor.ts +135 -0
  395. package/frontend/lib/utils/chat/tool-handler.ts +161 -0
  396. package/frontend/lib/utils/chat/virtual-scroll.svelte.ts +142 -0
  397. package/frontend/lib/utils/click-outside.ts +20 -0
  398. package/frontend/lib/utils/context-manager.ts +257 -0
  399. package/frontend/lib/utils/file-icon-mappings.ts +769 -0
  400. package/frontend/lib/utils/folder-icon-mappings.ts +1030 -0
  401. package/frontend/lib/utils/git-status.ts +68 -0
  402. package/frontend/lib/utils/platform.ts +113 -0
  403. package/frontend/lib/utils/port-check.ts +65 -0
  404. package/frontend/lib/utils/terminalFormatter.ts +207 -0
  405. package/frontend/lib/utils/theme.ts +6 -0
  406. package/frontend/lib/utils/tree-visualizer.ts +320 -0
  407. package/frontend/lib/utils/ws.ts +44 -0
  408. package/frontend/main.ts +13 -0
  409. package/index.html +70 -0
  410. package/package.json +111 -0
  411. package/scripts/generate-icons.ts +87 -0
  412. package/scripts/pre-publish-check.sh +142 -0
  413. package/scripts/setup-hooks.sh +134 -0
  414. package/scripts/validate-branch-name.sh +47 -0
  415. package/scripts/validate-commit-msg.sh +42 -0
  416. package/shared/constants/engines.ts +134 -0
  417. package/shared/types/database/connection.ts +16 -0
  418. package/shared/types/database/index.ts +6 -0
  419. package/shared/types/database/schema.ts +141 -0
  420. package/shared/types/engine/index.ts +45 -0
  421. package/shared/types/filesystem/index.ts +22 -0
  422. package/shared/types/git.ts +171 -0
  423. package/shared/types/messaging/index.ts +239 -0
  424. package/shared/types/messaging/tool.ts +526 -0
  425. package/shared/types/network/api.ts +18 -0
  426. package/shared/types/network/index.ts +5 -0
  427. package/shared/types/stores/app.ts +23 -0
  428. package/shared/types/stores/dialog.ts +21 -0
  429. package/shared/types/stores/index.ts +3 -0
  430. package/shared/types/stores/settings.ts +15 -0
  431. package/shared/types/terminal/index.ts +44 -0
  432. package/shared/types/ui/components.ts +61 -0
  433. package/shared/types/ui/icons.ts +23 -0
  434. package/shared/types/ui/index.ts +22 -0
  435. package/shared/types/ui/notifications.ts +14 -0
  436. package/shared/types/ui/theme.ts +12 -0
  437. package/shared/types/websocket/index.ts +43 -0
  438. package/shared/types/window.d.ts +13 -0
  439. package/shared/utils/anonymous-user.ts +168 -0
  440. package/shared/utils/async.ts +10 -0
  441. package/shared/utils/diff-calculator.ts +184 -0
  442. package/shared/utils/file-type-detection.ts +166 -0
  443. package/shared/utils/logger.ts +158 -0
  444. package/shared/utils/message-formatter.ts +79 -0
  445. package/shared/utils/path.ts +47 -0
  446. package/shared/utils/ws-client.ts +768 -0
  447. package/shared/utils/ws-server.ts +660 -0
  448. package/static/audio/notification.ogg +0 -0
  449. package/static/favicon.svg +8 -0
  450. package/static/fonts/dm-sans/dm-sans-italic-latin-ext.woff2 +0 -0
  451. package/static/fonts/dm-sans/dm-sans-italic-latin.woff2 +0 -0
  452. package/static/fonts/dm-sans/dm-sans-normal-latin-ext.woff2 +0 -0
  453. package/static/fonts/dm-sans/dm-sans-normal-latin.woff2 +0 -0
  454. package/static/fonts/dm-sans.css +96 -0
  455. package/svelte.config.js +20 -0
  456. package/vite.config.ts +33 -0
@@ -0,0 +1,359 @@
1
+ import type { Browser, BrowserContext, Page } from 'puppeteer';
2
+ import type { DeviceSize, Rotation } from '$frontend/lib/constants/preview.js';
3
+
4
+ // Re-export types from preview config
5
+ export type { DeviceSize, Rotation };
6
+
7
+ export interface BrowserConsoleMessage {
8
+ id: string;
9
+ type: 'log' | 'info' | 'warn' | 'error' | 'debug' | 'trace' | 'clear';
10
+ text: string;
11
+ args?: unknown[];
12
+ location?: {
13
+ url: string;
14
+ lineNumber: number;
15
+ columnNumber: number;
16
+ };
17
+ stackTrace?: string;
18
+ timestamp: number;
19
+ }
20
+
21
+ /**
22
+ * Browser Tab Interface
23
+ *
24
+ * Tab-centric architecture where each tab represents a complete browser instance
25
+ * (context + page) from the browser pool. No separate "session" concept.
26
+ */
27
+ export interface BrowserTab {
28
+ // Identity
29
+ id: string;
30
+ url: string;
31
+ title: string;
32
+ favicon?: string;
33
+ isActive: boolean;
34
+
35
+ // Browser instances (from pool)
36
+ browser: Browser; // Shared browser reference
37
+ context: BrowserContext; // Isolated context (cookies, localStorage, etc.)
38
+ page: Page;
39
+
40
+ // Streaming
41
+ isStreaming: boolean;
42
+ quality: 'perfect' | 'good';
43
+ screenshotInterval?: NodeJS.Timeout;
44
+ streamingInterval?: NodeJS.Timeout;
45
+ isCapturing?: boolean;
46
+
47
+ // Device
48
+ deviceSize: DeviceSize;
49
+ rotation: Rotation;
50
+
51
+ // Console
52
+ consoleLogs: BrowserConsoleMessage[];
53
+ consoleEnabled: boolean;
54
+
55
+ // Navigation
56
+ isLoading: boolean;
57
+ canGoBack: boolean;
58
+ canGoForward: boolean;
59
+ lastNavigationTime?: number;
60
+ currentUrl?: string;
61
+
62
+ // Streaming internals
63
+ lastFrameHash?: string;
64
+ duplicateFrameCount?: number;
65
+ lastUniqueFrameTime?: number;
66
+ stableFrameStartTime?: number;
67
+ lastCursorInfo?: { x: number; y: number; cursor: string };
68
+ scale?: number; // Frontend canvas scale factor (for bandwidth optimization)
69
+
70
+ // Interaction tracking
71
+ lastInteractionTime?: number;
72
+ lastInteractionLogTime?: number;
73
+
74
+ // Timestamps
75
+ createdAt: number;
76
+ lastAccessedAt: number;
77
+
78
+ // Internal
79
+ isDestroyed?: boolean;
80
+ }
81
+
82
+ /**
83
+ * Tab Events
84
+ */
85
+ export interface TabCreatedEvent {
86
+ tabId: string;
87
+ url: string;
88
+ title: string;
89
+ isActive: boolean;
90
+ timestamp: number;
91
+ }
92
+
93
+ export interface TabClosedEvent {
94
+ tabId: string;
95
+ newActiveTabId?: string;
96
+ timestamp: number;
97
+ }
98
+
99
+ export interface TabSwitchedEvent {
100
+ previousTabId: string;
101
+ newTabId: string;
102
+ timestamp: number;
103
+ }
104
+
105
+ export interface TabNavigatedEvent {
106
+ tabId: string;
107
+ url: string;
108
+ title: string;
109
+ timestamp: number;
110
+ }
111
+
112
+ export interface BrowserTabInfo {
113
+ id: string;
114
+ url: string;
115
+ title: string;
116
+ quality: 'perfect' | 'good';
117
+ isStreaming: boolean;
118
+ deviceSize: DeviceSize;
119
+ rotation: Rotation;
120
+ isActive: boolean;
121
+ }
122
+
123
+ export interface BrowserAutonomousAction {
124
+ /**
125
+ * Action types (minimal, native-only, no DOM):
126
+ * - 'click': Mouse click at coordinates (x, y)
127
+ * - 'type': Keyboard input - type text OR press single key
128
+ * - 'move': Move mouse to coordinates (x, y)
129
+ * - 'scroll': Scroll by delta amount, optionally at target area (x, y)
130
+ * - 'wait': Wait for specified delay
131
+ * - 'extract_data': Extract data from DOM element using CSS selector
132
+ *
133
+ * All interactions use native browser input (no DOM manipulation except extract_data)
134
+ */
135
+ type: 'click' | 'type' | 'move' | 'scroll' | 'wait' | 'extract_data';
136
+
137
+ // Coordinates for click/move, or target area for scroll
138
+ x?: number;
139
+ y?: number;
140
+
141
+ // For scroll action - scroll delta amounts
142
+ deltaX?: number;
143
+ deltaY?: number;
144
+
145
+ // For click action
146
+ click?: 'left' | 'right' | 'middle'; // Mouse button (default: 'left')
147
+
148
+ // For type action - either text OR key, not both
149
+ text?: string; // Type a string of text
150
+ key?: string; // Press a single key (Enter, Tab, Escape, ArrowUp, etc.)
151
+ clearFirst?: boolean; // Clear existing input before typing (default: true for MCP, false for user)
152
+
153
+ // For extract_data action
154
+ selector?: string; // Element identifier - tool automatically tries all selector patterns and attributes
155
+
156
+ // Timing options
157
+ delay?: number;
158
+ steps?: number; // For mouse movement interpolation
159
+
160
+ // Behavior options
161
+ humanLike?: boolean; // Simulate human-like movement/typing
162
+ smooth?: boolean; // For smooth scrolling
163
+ }
164
+
165
+ export interface BrowserNavigationEvent {
166
+ tabId: string;
167
+ type: 'navigation';
168
+ url: string;
169
+ timestamp: number;
170
+ }
171
+
172
+ export interface BrowserNavigationLoadingEvent {
173
+ tabId: string;
174
+ type: 'navigation-loading';
175
+ url: string;
176
+ timestamp: number;
177
+ }
178
+
179
+ export interface BrowserCursorPosition {
180
+ tabId: string;
181
+ x: number;
182
+ y: number;
183
+ timestamp: number;
184
+ }
185
+
186
+ export interface BrowserConsoleEvent {
187
+ tabId: string;
188
+ message: BrowserConsoleMessage;
189
+ }
190
+
191
+ export interface BrowserScreenshotFrame {
192
+ tabId: string;
193
+ frame: number;
194
+ timestamp: number;
195
+ data: string;
196
+ cursorInfo: any;
197
+ duplicatesSkipped: number;
198
+ }
199
+
200
+ /**
201
+ * Unified Streaming Configuration
202
+ *
203
+ * Central configuration for WebCodecs streaming (video + audio).
204
+ * Used across audio capture, video capture, and session management.
205
+ *
206
+ * Single source of truth for all codec settings.
207
+ */
208
+ export interface StreamingConfig {
209
+ video: {
210
+ codec: string;
211
+ width: number;
212
+ height: number;
213
+ framerate: number;
214
+ bitrate: number;
215
+ keyframeInterval: number;
216
+ screenshotQuality: number;
217
+ hardwareAcceleration: 'no-preference' | 'prefer-hardware' | 'prefer-software';
218
+ latencyMode: 'quality' | 'realtime';
219
+ };
220
+ audio: {
221
+ codec: string
222
+ sampleRate: number;
223
+ bitrate: number;
224
+ numberOfChannels: number;
225
+ bufferSize: number;
226
+ };
227
+ }
228
+
229
+ /**
230
+ * Default streaming configuration
231
+ *
232
+ * Optimized for low-end servers without GPU:
233
+ * - Software encoding only (hardwareAcceleration: 'no-preference')
234
+ * - Lower bitrate for bandwidth efficiency
235
+ * - VP8 for video (good software encoder performance)
236
+ * - Opus for audio (efficient and widely supported)
237
+ */
238
+ export const DEFAULT_STREAMING_CONFIG: StreamingConfig = {
239
+ video: {
240
+ codec: 'vp8',
241
+ width: 0,
242
+ height: 0,
243
+ framerate: 24,
244
+ bitrate: 600_000,
245
+ keyframeInterval: 2,
246
+ screenshotQuality: 35,
247
+ hardwareAcceleration: 'no-preference',
248
+ latencyMode: 'realtime'
249
+ },
250
+ audio: {
251
+ codec: 'opus',
252
+ sampleRate: 48_000,
253
+ bitrate: 128_000,
254
+ numberOfChannels: 2,
255
+ bufferSize: 4096
256
+ }
257
+ };
258
+
259
+ /**
260
+ * Native UI Dialog Types
261
+ * Intercepted from headless browser and re-rendered as native dialogs
262
+ */
263
+ export interface BrowserDialogEvent {
264
+ tabId: string;
265
+ dialogId: string;
266
+ type: 'alert' | 'confirm' | 'prompt' | 'beforeunload';
267
+ message: string;
268
+ defaultValue?: string; // For prompt dialogs
269
+ timestamp: number;
270
+ }
271
+
272
+ export interface BrowserDialogResponse {
273
+ tabId: string;
274
+ dialogId: string;
275
+ accept: boolean; // true = OK/Yes, false = Cancel/No
276
+ promptText?: string; // For prompt dialogs
277
+ }
278
+
279
+ /**
280
+ * Print Request Event
281
+ * Intercepted from window.print() calls
282
+ */
283
+ export interface BrowserPrintEvent {
284
+ tabId: string;
285
+ timestamp: number;
286
+ }
287
+
288
+ /**
289
+ * Select Dropdown Types
290
+ * For rendering native select dropdowns over canvas
291
+ */
292
+ export interface BrowserSelectOption {
293
+ index: number;
294
+ value: string;
295
+ text: string;
296
+ selected: boolean;
297
+ disabled?: boolean;
298
+ }
299
+
300
+ export interface BrowserSelectInfo {
301
+ tabId: string;
302
+ selectId: string;
303
+ x: number; // Click coordinates
304
+ y: number;
305
+ boundingBox: {
306
+ x: number;
307
+ y: number;
308
+ width: number;
309
+ height: number;
310
+ };
311
+ options: BrowserSelectOption[];
312
+ selectedIndex: number;
313
+ timestamp: number;
314
+ }
315
+
316
+ export interface BrowserSelectResponse {
317
+ tabId: string;
318
+ selectId: string;
319
+ selectedIndex: number;
320
+ }
321
+
322
+ /**
323
+ * Context Menu Types
324
+ * For rendering native context menus over canvas
325
+ */
326
+ export interface BrowserContextMenuItem {
327
+ id: string;
328
+ label: string;
329
+ enabled: boolean;
330
+ type?: 'normal' | 'separator' | 'submenu';
331
+ icon?: string;
332
+ submenu?: BrowserContextMenuItem[];
333
+ }
334
+
335
+ export interface BrowserContextMenuInfo {
336
+ tabId: string;
337
+ menuId: string;
338
+ x: number; // Click coordinates
339
+ y: number;
340
+ items: BrowserContextMenuItem[];
341
+ elementInfo: {
342
+ tagName: string;
343
+ isLink: boolean;
344
+ isImage: boolean;
345
+ isInput: boolean;
346
+ isTextSelected: boolean;
347
+ linkUrl?: string;
348
+ imageUrl?: string;
349
+ inputType?: string;
350
+ };
351
+ timestamp: number;
352
+ }
353
+
354
+ export interface BrowserContextMenuResponse {
355
+ tabId: string;
356
+ menuId: string;
357
+ itemId: string; // Selected menu item ID
358
+ }
359
+
@@ -0,0 +1,24 @@
1
+ // Export all browser types (includes StreamingConfig and DEFAULT_STREAMING_CONFIG)
2
+ export * from './browser/types';
3
+
4
+ // Export MCP control types
5
+ export type { McpControlState, McpControlEvent, McpCursorEvent, McpClickEvent } from './browser/browser-mcp-control';
6
+
7
+ // Export the main preview service class and manager
8
+ export {
9
+ BrowserPreviewService,
10
+ browserPreviewServiceManager
11
+ } from './browser/browser-preview-service.js';
12
+
13
+ // Export browser-specific handlers
14
+ export { BrowserTabManager } from './browser/browser-tab-manager.js';
15
+ export { BrowserConsoleManager } from './browser/browser-console-manager.js';
16
+ export { BrowserInteractionHandler } from './browser/browser-interaction-handler.js';
17
+ export { BrowserNavigationTracker } from './browser/browser-navigation-tracker.js';
18
+ export { BrowserAudioCapture } from './browser/browser-audio-capture.js';
19
+ export { BrowserVideoCapture } from './browser/browser-video-capture.js';
20
+ export { BrowserMcpControl, browserMcpControl } from './browser/browser-mcp-control.js';
21
+ export { browserPool } from './browser/browser-pool';
22
+
23
+ // Note: MCP control initialization is now handled per-project
24
+ // Each project's BrowserPreviewService instance should initialize MCP control separately
@@ -0,0 +1,2 @@
1
+ // Export project status manager
2
+ export * from './status-manager.js';
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Project Status Data Service
3
+ * Shared logic for getting project status data
4
+ */
5
+
6
+ import { streamManager } from '../chat/stream-manager.js';
7
+ import { ws } from '../utils/ws.js';
8
+
9
+ // Store active users per project (shared with main endpoint)
10
+ const projectUsers = new Map<string, Set<{ userId: string; userName: string; lastSeen: number }>>();
11
+
12
+ // Cleanup inactive users after 5 minutes
13
+ const USER_TIMEOUT = 5 * 60 * 1000;
14
+
15
+ function cleanupInactiveUsers() {
16
+ const now = Date.now();
17
+ projectUsers.forEach((users, projectId) => {
18
+ const activeUsers = new Set([...users].filter(user => now - user.lastSeen < USER_TIMEOUT));
19
+ if (activeUsers.size === 0) {
20
+ projectUsers.delete(projectId);
21
+ } else {
22
+ projectUsers.set(projectId, activeUsers);
23
+ }
24
+ });
25
+ }
26
+
27
+ // Get project status data
28
+ export async function getProjectStatusData(projectId?: string) {
29
+ cleanupInactiveUsers();
30
+
31
+ if (projectId) {
32
+ // Get status for specific project
33
+ const allProjectStreams = streamManager.getProjectStreams(projectId);
34
+ const users = projectUsers.get(projectId);
35
+
36
+ // Filter to only count active streams
37
+ const activeStreams = allProjectStreams.filter(s => s.status === 'active');
38
+
39
+ // Get per-chat-session user presence from WS rooms
40
+ const chatSessionUsers = ws.getProjectChatSessions(projectId);
41
+
42
+ return {
43
+ projectId,
44
+ hasActiveStreams: activeStreams.length > 0,
45
+ activeStreamCount: activeStreams.length,
46
+ activeUsers: users ? [...users].map(u => ({
47
+ userId: u.userId,
48
+ userName: u.userName
49
+ })) : [],
50
+ streams: allProjectStreams.map(s => ({
51
+ streamId: s.streamId,
52
+ chatSessionId: s.chatSessionId,
53
+ status: s.status,
54
+ startedAt: s.startedAt,
55
+ messagesCount: s.messages.length
56
+ })),
57
+ chatSessionUsers: Object.fromEntries(
58
+ Array.from(chatSessionUsers.entries()).map(([csId, csUsers]) => [
59
+ csId,
60
+ csUsers.map(u => {
61
+ // Resolve userName from projectUsers
62
+ const projectUser = users ? [...users].find(pu => pu.userId === u.userId) : undefined;
63
+ return { userId: u.userId, userName: projectUser?.userName || u.userId };
64
+ })
65
+ ])
66
+ )
67
+ };
68
+ } else {
69
+ // Get status for all projects
70
+ const allProjects = new Map<string, any>();
71
+
72
+ // Get all active streams grouped by project
73
+ const allStreams = streamManager.getAllStreams();
74
+ allStreams.forEach(stream => {
75
+ if (stream.projectId) {
76
+ if (!allProjects.has(stream.projectId)) {
77
+ allProjects.set(stream.projectId, {
78
+ projectId: stream.projectId,
79
+ hasActiveStreams: false,
80
+ activeStreamCount: 0,
81
+ activeUsers: [],
82
+ streams: []
83
+ });
84
+ }
85
+
86
+ const projectData = allProjects.get(stream.projectId);
87
+ if (stream.status === 'active') {
88
+ projectData.hasActiveStreams = true;
89
+ projectData.activeStreamCount++;
90
+ }
91
+ projectData.streams.push({
92
+ streamId: stream.streamId,
93
+ chatSessionId: stream.chatSessionId,
94
+ status: stream.status,
95
+ startedAt: stream.startedAt,
96
+ messagesCount: stream.messages.length
97
+ });
98
+ }
99
+ });
100
+
101
+ // Add active users to each project
102
+ projectUsers.forEach((users, projectId) => {
103
+ if (!allProjects.has(projectId)) {
104
+ allProjects.set(projectId, {
105
+ projectId,
106
+ hasActiveStreams: false,
107
+ activeStreamCount: 0,
108
+ activeUsers: [],
109
+ streams: [],
110
+ chatSessionUsers: {}
111
+ });
112
+ }
113
+
114
+ const projectData = allProjects.get(projectId);
115
+ projectData.activeUsers = [...users].map(u => ({
116
+ userId: u.userId,
117
+ userName: u.userName
118
+ }));
119
+ });
120
+
121
+ // Add per-chat-session user presence to each project
122
+ for (const [projectId, projectData] of allProjects) {
123
+ const chatSessionUsers = ws.getProjectChatSessions(projectId);
124
+ const users = projectUsers.get(projectId);
125
+ projectData.chatSessionUsers = Object.fromEntries(
126
+ Array.from(chatSessionUsers.entries()).map(([csId, csUsers]) => [
127
+ csId,
128
+ csUsers.map(u => {
129
+ const projectUser = users ? [...users].find(pu => pu.userId === u.userId) : undefined;
130
+ return { userId: u.userId, userName: projectUser?.userName || u.userId };
131
+ })
132
+ ])
133
+ );
134
+ }
135
+
136
+ return [...allProjects.values()];
137
+ }
138
+ }
139
+
140
+ // Update user presence
141
+ export function updateUserPresence(projectId: string, userId: string, userName: string, action: string) {
142
+ cleanupInactiveUsers();
143
+
144
+ if (action === 'leave') {
145
+ // Remove user from project
146
+ const users = projectUsers.get(projectId);
147
+ if (users) {
148
+ const updatedUsers = new Set([...users].filter(u => u.userId !== userId));
149
+ if (updatedUsers.size === 0) {
150
+ projectUsers.delete(projectId);
151
+ } else {
152
+ projectUsers.set(projectId, updatedUsers);
153
+ }
154
+ }
155
+ } else {
156
+ // Add or update user presence
157
+ if (!projectUsers.has(projectId)) {
158
+ projectUsers.set(projectId, new Set());
159
+ }
160
+
161
+ const users = projectUsers.get(projectId)!;
162
+ // Remove old entry if exists
163
+ const updatedUsers = new Set([...users].filter(u => u.userId !== userId));
164
+ // Add new entry with updated timestamp
165
+ updatedUsers.add({
166
+ userId,
167
+ userName,
168
+ lastSeen: Date.now()
169
+ });
170
+ projectUsers.set(projectId, updatedUsers);
171
+ }
172
+
173
+ // Return current users for the project
174
+ const currentUsers = projectUsers.get(projectId);
175
+ return {
176
+ projectId,
177
+ activeUsers: currentUsers ? [...currentUsers].map(u => ({
178
+ userId: u.userId,
179
+ userName: u.userName
180
+ })) : []
181
+ };
182
+ }
@@ -0,0 +1,2 @@
1
+ // Export process manager utilities
2
+ export * from './process-manager.js';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Port utilities for checking ports before server start.
3
+ * Bun-optimized: uses Bun.connect for fast cross-platform port check.
4
+ */
5
+
6
+ /** Check if a port is currently in use */
7
+ export async function isPortInUse(port: number): Promise<boolean> {
8
+ try {
9
+ // Bun-native TCP connect — fast cross-platform check
10
+ const socket = await Bun.connect({
11
+ hostname: '127.0.0.1',
12
+ port,
13
+ socket: {
14
+ data() {},
15
+ open(socket) { socket.end(); },
16
+ error() {},
17
+ close() {}
18
+ }
19
+ });
20
+ socket.end();
21
+ return true; // Connection succeeded = port in use
22
+ } catch {
23
+ return false; // Connection refused = port is free
24
+ }
25
+ }