@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,56 @@
1
+ /**
2
+ * Get Temperature Handler
3
+ */
4
+
5
+ export async function getTemperatureHandler(args: { latitude: number; longitude: number }) {
6
+ try {
7
+ // Call Open-Meteo API (no API key required)
8
+ const url = `https://api.open-meteo.com/v1/forecast?latitude=${args.latitude}&longitude=${args.longitude}&current=temperature_2m&temperature_unit=fahrenheit`;
9
+
10
+ const response = await fetch(url);
11
+
12
+ if (!response.ok) {
13
+ return {
14
+ content: [{
15
+ type: "text" as const,
16
+ text: `Failed to fetch weather data: ${response.status} ${response.statusText}`
17
+ }],
18
+ isError: true
19
+ };
20
+ }
21
+
22
+ const data = await response.json();
23
+
24
+ // Check if temperature data is available
25
+ if (!data.current || data.current.temperature_2m === undefined) {
26
+ return {
27
+ content: [{
28
+ type: "text" as const,
29
+ text: "Temperature data not available for this location."
30
+ }],
31
+ isError: true
32
+ };
33
+ }
34
+
35
+ const temperature = data.current.temperature_2m;
36
+ const unit = data.current_units?.temperature_2m || "°F";
37
+
38
+ return {
39
+ content: [{
40
+ type: "text" as const,
41
+ text: `Temperature: ${temperature}${unit}`
42
+ }]
43
+ };
44
+
45
+ } catch (error) {
46
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
47
+
48
+ return {
49
+ content: [{
50
+ type: "text" as const,
51
+ text: `Error fetching temperature: ${errorMessage}`
52
+ }],
53
+ isError: true
54
+ };
55
+ }
56
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Weather Service - Custom MCP Server
3
+ *
4
+ * Provides weather-related tools using the Open-Meteo API.
5
+ * No API key required.
6
+ */
7
+
8
+ import { z } from "zod";
9
+ import { defineServer } from "../helper";
10
+ import { getTemperatureHandler } from "./get-temperature";
11
+
12
+ export default defineServer({
13
+ name: "weather-service",
14
+ version: "1.0.0",
15
+ tools: {
16
+ "get_temperature": {
17
+ description: "Get current temperature for a location using coordinates. Returns temperature in Fahrenheit.",
18
+ schema: {
19
+ latitude: z.number()
20
+ .min(-90)
21
+ .max(90)
22
+ .describe("Latitude coordinate (-90 to 90)"),
23
+ longitude: z.number()
24
+ .min(-180)
25
+ .max(180)
26
+ .describe("Longitude coordinate (-180 to 180)")
27
+ },
28
+ handler: getTemperatureHandler
29
+ }
30
+ }
31
+ });
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * MCP Stdio Server for Open Code
4
+ *
5
+ * Standalone subprocess that exposes our custom MCP tools via stdio transport.
6
+ * Open Code spawns this process and communicates over stdin/stdout (JSON-RPC 2.0).
7
+ *
8
+ * Tool definitions (schema, description) are loaded from the SAME source as
9
+ * Claude Code — the `serverMetadata` registry in `./servers/index.ts`.
10
+ *
11
+ * ALL tool calls are proxied to the main Clopen server via WSClient bridge,
12
+ * because handlers need in-process access to browser instances, project context, etc.
13
+ */
14
+
15
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
16
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
17
+ import { WSClient } from '$shared/utils/ws-client';
18
+ import { serverMetadata } from './servers/index';
19
+ import { mcpServers } from './config';
20
+
21
+ // ============================================================================
22
+ // WebSocket Bridge — proxies tool calls to the main Clopen server via WSClient
23
+ // ============================================================================
24
+
25
+ const BRIDGE_PORT = process.env.CLOPEN_PORT || '9141';
26
+ const WS_URL = `ws://localhost:${BRIDGE_PORT}/ws`;
27
+
28
+ /**
29
+ * WSClient instance for communicating with the main Clopen server.
30
+ * Uses the same protocol as the frontend (JSON messages with action/payload).
31
+ */
32
+ const wsClient = new WSClient<any>(WS_URL, {
33
+ autoReconnect: true,
34
+ maxReconnectAttempts: 10,
35
+ reconnectDelay: 1000,
36
+ maxReconnectDelay: 10000,
37
+ });
38
+
39
+ /**
40
+ * Call a tool handler on the main Clopen server via the WS bridge.
41
+ * Uses WSClient.http() which follows the standard request-response pattern.
42
+ */
43
+ async function callBridge(
44
+ serverName: string,
45
+ toolName: string,
46
+ args: Record<string, unknown>
47
+ ): Promise<{ content: Array<{ type: string; text?: string; data?: string; mimeType?: string }>; isError?: boolean }> {
48
+ try {
49
+ return await wsClient.http('mcp:execute' as any, {
50
+ server: serverName,
51
+ tool: toolName,
52
+ args,
53
+ } as any, 30000);
54
+ } catch (error) {
55
+ const msg = error instanceof Error ? error.message : String(error);
56
+ return {
57
+ content: [{ type: 'text', text: `Bridge connection failed: ${msg}` }],
58
+ isError: true,
59
+ };
60
+ }
61
+ }
62
+
63
+ // ============================================================================
64
+ // Build MCP server from existing server metadata (single source of truth)
65
+ // ============================================================================
66
+
67
+ const server = new McpServer({
68
+ name: 'clopen-mcp',
69
+ version: '1.0.0',
70
+ });
71
+
72
+ // Iterate over all configured servers and register their enabled tools
73
+ for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
74
+ if (!serverConfig.enabled) continue;
75
+
76
+ // Get tool definitions from the metadata registry
77
+ const meta = (serverMetadata as Record<string, { toolDefs: Record<string, { description: string; schema: Record<string, any> }> }>)[serverName];
78
+ if (!meta) continue;
79
+
80
+ for (const toolName of serverConfig.tools) {
81
+ const toolDef = meta.toolDefs[toolName];
82
+ if (!toolDef) continue;
83
+
84
+ // Register tool with the same schema/description, but handler goes through bridge
85
+ server.registerTool(
86
+ toolName,
87
+ {
88
+ description: toolDef.description,
89
+ inputSchema: toolDef.schema,
90
+ },
91
+ async (args: Record<string, unknown>) => {
92
+ return await callBridge(serverName, toolName, args) as any;
93
+ }
94
+ );
95
+ }
96
+ }
97
+
98
+ // ============================================================================
99
+ // Connect via stdio transport
100
+ // ============================================================================
101
+
102
+ const transport = new StdioServerTransport();
103
+ await server.connect(transport);
@@ -0,0 +1,65 @@
1
+ /**
2
+ * MCP (Model Context Protocol) Custom Tools - Type Definitions
3
+ *
4
+ * This file contains all TypeScript types and interfaces used across
5
+ * the custom MCP tools system.
6
+ */
7
+
8
+ import type { serverMetadata } from './servers';
9
+ import type { McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-agent-sdk';
10
+
11
+ /**
12
+ * Extract server names from metadata registry
13
+ */
14
+ export type ServerName = keyof typeof serverMetadata;
15
+
16
+ /**
17
+ * Extract tool names from a specific server
18
+ * Automatically inferred from server metadata
19
+ */
20
+ export type ToolsForServer<S extends ServerName> = (typeof serverMetadata)[S]['tools'][number];
21
+
22
+ /**
23
+ * Configuration for an MCP server (user-defined)
24
+ */
25
+ export type ServerConfig<S extends ServerName = ServerName> = {
26
+ /** Whether this server is enabled */
27
+ enabled: boolean;
28
+ /** List of enabled tool names for this server */
29
+ tools: readonly ToolsForServer<S>[];
30
+ };
31
+
32
+ /**
33
+ * Complete server configuration with instance (internal use)
34
+ */
35
+ export type McpServerConfigWithInstance<S extends ServerName = ServerName> = ServerConfig<S> & {
36
+ instance: McpSdkServerConfigWithInstance;
37
+ };
38
+
39
+ /**
40
+ * Parsed MCP tool name
41
+ * Format: mcp__server-name__tool-name
42
+ */
43
+ export interface ParsedMcpToolName {
44
+ /** Server name (e.g., "weather-service") */
45
+ server: string;
46
+ /** Tool name (e.g., "get_temperature") */
47
+ tool: string;
48
+ /** Full tool name (e.g., "mcp__weather-service__get_temperature") */
49
+ fullName: string;
50
+ }
51
+
52
+ /**
53
+ * MCP server status from SDK
54
+ */
55
+ export interface McpServerStatus {
56
+ /** Server name */
57
+ name: string;
58
+ /** Connection status */
59
+ status: 'connected' | 'failed' | 'needs-auth' | 'pending';
60
+ /** Server information if connected */
61
+ serverInfo?: {
62
+ name: string;
63
+ version: string;
64
+ };
65
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Browser Audio Capture Handler
3
+ *
4
+ * Handles audio capture setup and management for headless browser sessions.
5
+ * Audio is captured via AudioContext interception and encoded with AudioEncoder (Opus).
6
+ */
7
+
8
+ import type { Page } from 'puppeteer';
9
+ import type { StreamingConfig } from './types';
10
+ import { audioCaptureScript } from './scripts/audio-stream';
11
+
12
+ export class BrowserAudioCapture {
13
+ /**
14
+ * Setup audio capture for a page
15
+ * Injects audio capture script that intercepts AudioContext before page loads
16
+ */
17
+ async setupAudioCapture(page: Page, config: StreamingConfig['audio']): Promise<void> {
18
+ // Inject audio capture script BEFORE page loads to intercept AudioContext
19
+ await page.evaluateOnNewDocument(audioCaptureScript, config);
20
+ }
21
+
22
+ /**
23
+ * Check if audio encoder is supported in the page
24
+ */
25
+ async isAudioSupported(page: Page): Promise<boolean> {
26
+ try {
27
+ return await page.evaluate(() => {
28
+ return typeof (window as any).__audioEncoder?.isSupported === 'function'
29
+ && (window as any).__audioEncoder.isSupported();
30
+ });
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Initialize and start audio capture
38
+ */
39
+ async startAudioCapture(page: Page): Promise<boolean> {
40
+ try {
41
+ const initialized = await page.evaluate(async () => {
42
+ const encoder = (window as any).__audioEncoder;
43
+ if (!encoder) return false;
44
+
45
+ const initiated = await encoder.init();
46
+ if (initiated) {
47
+ return encoder.start();
48
+ }
49
+ return false;
50
+ });
51
+
52
+ return initialized;
53
+ } catch (error) {
54
+ return false;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Stop audio capture
60
+ */
61
+ async stopAudioCapture(page: Page): Promise<void> {
62
+ try {
63
+ await page.evaluate(() => {
64
+ const encoder = (window as any).__audioEncoder;
65
+ if (encoder) {
66
+ encoder.stop();
67
+ }
68
+ });
69
+ } catch {
70
+ // Ignore errors during cleanup
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Check if audio is currently being captured
76
+ */
77
+ async isCapturing(page: Page): Promise<boolean> {
78
+ try {
79
+ return await page.evaluate(() => {
80
+ return (window as any).__audioEncoder?.isCapturing() || false;
81
+ });
82
+ } catch {
83
+ return false;
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,263 @@
1
+ import { EventEmitter } from 'events';
2
+ import type { Page, ConsoleMessage as PuppeteerConsoleMessage, HTTPResponse } from 'puppeteer';
3
+ import type { BrowserConsoleMessage, BrowserTab } from './types';
4
+
5
+ import { debug } from '$shared/utils/logger';
6
+ export class BrowserConsoleManager extends EventEmitter {
7
+ constructor() {
8
+ super();
9
+ }
10
+
11
+ async setupConsoleLogging(sessionId: string, page: Page, session: BrowserTab) {
12
+
13
+ // Clear any existing console logs for this session
14
+ session.consoleLogs = [];
15
+
16
+ // Listen to ALL console events from the page
17
+ page.on('console', async (consoleMessage: PuppeteerConsoleMessage) => {
18
+ // Always log to server console for debugging
19
+ if (!session.consoleEnabled) {
20
+ return;
21
+ }
22
+
23
+ try {
24
+ const messageId = `console-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
25
+ const text = consoleMessage.text();
26
+ const type = consoleMessage.type() as BrowserConsoleMessage['type'];
27
+
28
+ // Get location information (Puppeteer uses location() method)
29
+ const location = consoleMessage.location();
30
+ const messageLocation = location ? {
31
+ url: location.url || '',
32
+ lineNumber: location.lineNumber || 0,
33
+ columnNumber: location.columnNumber || 0
34
+ } : undefined;
35
+
36
+ // Extract arguments with improved error handling
37
+ let args: any[] = [];
38
+ try {
39
+ const messageArgs = consoleMessage.args();
40
+ if (messageArgs && messageArgs.length > 0) {
41
+ args = await Promise.all(
42
+ messageArgs.map(async (arg) => {
43
+ try {
44
+ // Try to get JSON value first
45
+ const jsonValue = await arg.jsonValue();
46
+ return jsonValue;
47
+ } catch {
48
+ try {
49
+ // Fallback to string representation
50
+ return arg.toString();
51
+ } catch {
52
+ // Final fallback
53
+ return '[Unable to serialize]';
54
+ }
55
+ }
56
+ })
57
+ );
58
+ }
59
+ } catch (error) {
60
+ debug.warn('preview', 'Could not extract console message args:', error);
61
+ args = [];
62
+ }
63
+
64
+ const consoleLog: BrowserConsoleMessage = {
65
+ id: messageId,
66
+ type,
67
+ text,
68
+ args,
69
+ location: messageLocation,
70
+ timestamp: Date.now()
71
+ };
72
+
73
+ // Add to session logs (with limit to prevent memory issues)
74
+ session.consoleLogs.push(consoleLog);
75
+ if (session.consoleLogs.length > 1000) {
76
+ session.consoleLogs = session.consoleLogs.slice(-500); // Keep last 500 logs
77
+ }
78
+
79
+ // Emit console message event for real-time streaming
80
+ this.emit('console-message', {
81
+ sessionId: session.id,
82
+ message: consoleLog
83
+ });
84
+
85
+
86
+ } catch (error) {
87
+ debug.error('preview', '❌ Error processing console message:', error);
88
+ }
89
+ });
90
+
91
+ // Listen to page errors (uncaught JavaScript errors)
92
+ page.on('pageerror', (err) => {
93
+ if (!session.consoleEnabled) {
94
+ return;
95
+ }
96
+
97
+ try {
98
+ const error = err as Error;
99
+ const messageId = `error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
100
+ const consoleLog: BrowserConsoleMessage = {
101
+ id: messageId,
102
+ type: 'error',
103
+ text: `Uncaught ${error.message || String(err)}`,
104
+ stackTrace: error.stack,
105
+ timestamp: Date.now()
106
+ };
107
+
108
+ session.consoleLogs.push(consoleLog);
109
+ if (session.consoleLogs.length > 1000) {
110
+ session.consoleLogs = session.consoleLogs.slice(-500);
111
+ }
112
+
113
+ this.emit('console-message', {
114
+ sessionId: session.id,
115
+ message: consoleLog
116
+ });
117
+
118
+
119
+ } catch (err) {
120
+ debug.error('preview', '❌ Error processing page error:', err);
121
+ }
122
+ });
123
+
124
+ // Listen to response failures (network errors)
125
+ page.on('response', (response: HTTPResponse) => {
126
+ if (!session.consoleEnabled) return;
127
+
128
+ if (!response.ok() && response.status() >= 400) {
129
+
130
+
131
+ try {
132
+ const messageId = `network-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
133
+ const consoleLog: BrowserConsoleMessage = {
134
+ id: messageId,
135
+ type: 'error',
136
+ text: `Network error: ${response.status()} ${response.statusText()} - ${response.url()}`,
137
+ location: {
138
+ url: response.url(),
139
+ lineNumber: 0,
140
+ columnNumber: 0
141
+ },
142
+ timestamp: Date.now()
143
+ };
144
+
145
+ session.consoleLogs.push(consoleLog);
146
+ if (session.consoleLogs.length > 1000) {
147
+ session.consoleLogs = session.consoleLogs.slice(-500);
148
+ }
149
+
150
+ this.emit('console-message', {
151
+ sessionId: session.id,
152
+ message: consoleLog
153
+ });
154
+
155
+
156
+ } catch (err) {
157
+ debug.error('preview', '❌ Error processing network error:', err);
158
+ }
159
+ }
160
+ });
161
+
162
+ // Console monitoring is handled automatically by Puppeteer's console event listener
163
+ // No additional injection needed
164
+
165
+
166
+ }
167
+
168
+ getConsoleLogs(session: BrowserTab): BrowserConsoleMessage[] {
169
+ return session ? session.consoleLogs : [];
170
+ }
171
+
172
+ clearConsoleLogs(session: BrowserTab): boolean {
173
+ if (!session) return false;
174
+
175
+ session.consoleLogs = [];
176
+
177
+ // Add a clear message to console logs
178
+ const clearMessage: BrowserConsoleMessage = {
179
+ id: `clear-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
180
+ type: 'clear',
181
+ text: 'Console was cleared',
182
+ timestamp: Date.now()
183
+ };
184
+
185
+ session.consoleLogs.push(clearMessage);
186
+
187
+ // Emit clear event
188
+ this.emit('console-clear', {
189
+ sessionId: session.id,
190
+ timestamp: Date.now()
191
+ });
192
+
193
+
194
+ return true;
195
+ }
196
+
197
+ toggleConsoleLogging(session: BrowserTab, enabled: boolean): boolean {
198
+ if (!session) return false;
199
+
200
+ session.consoleEnabled = enabled;
201
+
202
+ return true;
203
+ }
204
+
205
+ async executeConsoleCommand(session: BrowserTab, command: string): Promise<any> {
206
+ if (!session) throw new Error('Session not found');
207
+
208
+ try {
209
+
210
+
211
+ // Execute the command in the browser context
212
+ const result = await session.page.evaluate((cmd: string) => {
213
+ // Create a safe evaluation context
214
+ try {
215
+ // Use Function constructor for safer evaluation than eval
216
+ const func = new Function('return ' + cmd);
217
+ return func();
218
+ } catch (error) {
219
+ return { error: error instanceof Error ? error.message : String(error) };
220
+ }
221
+ }, command);
222
+
223
+ // Log the command execution as a console message
224
+ const commandMessage: BrowserConsoleMessage = {
225
+ id: `command-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
226
+ type: 'log',
227
+ text: `> ${command}`,
228
+ args: [result],
229
+ timestamp: Date.now()
230
+ };
231
+
232
+ session.consoleLogs.push(commandMessage);
233
+
234
+ // Emit the command result
235
+ this.emit('console-message', {
236
+ sessionId: session.id,
237
+ message: commandMessage
238
+ });
239
+
240
+ return result;
241
+ } catch (error) {
242
+ debug.error('preview', 'Error executing console command:', error);
243
+
244
+ // Log the error as a console message
245
+ const errorMessage: BrowserConsoleMessage = {
246
+ id: `command-error-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
247
+ type: 'error',
248
+ text: `Error executing command: ${command}`,
249
+ args: [error instanceof Error ? error.message : String(error)],
250
+ timestamp: Date.now()
251
+ };
252
+
253
+ session.consoleLogs.push(errorMessage);
254
+
255
+ this.emit('console-message', {
256
+ sessionId: session.id,
257
+ message: errorMessage
258
+ });
259
+
260
+ throw error;
261
+ }
262
+ }
263
+ }