@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,73 @@
1
+ /**
2
+ * Frontend Native UI Types
3
+ * For dialog, select dropdown, and context menu overlays
4
+ */
5
+
6
+ // Dialog types
7
+ export interface BrowserDialogEvent {
8
+ sessionId: string;
9
+ dialogId: string;
10
+ type: 'alert' | 'confirm' | 'prompt' | 'beforeunload';
11
+ message: string;
12
+ defaultValue?: string;
13
+ timestamp: number;
14
+ }
15
+
16
+ export interface BrowserPrintEvent {
17
+ sessionId: string;
18
+ timestamp: number;
19
+ }
20
+
21
+ // Select dropdown types
22
+ export interface BrowserSelectOption {
23
+ index: number;
24
+ value: string;
25
+ text: string;
26
+ selected: boolean;
27
+ disabled?: boolean;
28
+ }
29
+
30
+ export interface BrowserSelectInfo {
31
+ sessionId: string;
32
+ selectId: string;
33
+ x: number;
34
+ y: number;
35
+ boundingBox: {
36
+ x: number;
37
+ y: number;
38
+ width: number;
39
+ height: number;
40
+ };
41
+ options: BrowserSelectOption[];
42
+ selectedIndex: number;
43
+ timestamp: number;
44
+ }
45
+
46
+ // Context menu types
47
+ export interface BrowserContextMenuItem {
48
+ id: string;
49
+ label: string;
50
+ enabled: boolean;
51
+ type?: 'normal' | 'separator' | 'submenu';
52
+ icon?: string;
53
+ submenu?: BrowserContextMenuItem[];
54
+ }
55
+
56
+ export interface BrowserContextMenuInfo {
57
+ sessionId: string;
58
+ menuId: string;
59
+ x: number;
60
+ y: number;
61
+ items: BrowserContextMenuItem[];
62
+ elementInfo: {
63
+ tagName: string;
64
+ isLink: boolean;
65
+ isImage: boolean;
66
+ isInput: boolean;
67
+ isTextSelected: boolean;
68
+ linkUrl?: string;
69
+ imageUrl?: string;
70
+ inputType?: string;
71
+ };
72
+ timestamp: number;
73
+ }
@@ -0,0 +1,39 @@
1
+ import type { SDKMessageFormatter } from '$shared/types/database/schema';
2
+
3
+ // Interface for date separator items
4
+ export interface DateSeparatorItem {
5
+ type: 'message' | 'date';
6
+ data: any;
7
+ key: string;
8
+ }
9
+
10
+ // Add date separators to messages
11
+ // startIndex: global offset for stable keys when using windowed slices
12
+ export function addDateSeparators(messages: SDKMessageFormatter[], startIndex: number = 0): DateSeparatorItem[] {
13
+ const result: DateSeparatorItem[] = [];
14
+ let lastDate: string | null = null;
15
+
16
+ messages.forEach((message, index) => {
17
+ const createdAt = message.metadata?.created_at || new Date().toISOString();
18
+ const messageDate = new Date(createdAt).toDateString();
19
+
20
+ // Add date separator if date has changed
21
+ if (messageDate !== lastDate) {
22
+ result.push({
23
+ type: 'date',
24
+ data: createdAt,
25
+ key: `date-${messageDate}`
26
+ });
27
+ lastDate = messageDate;
28
+ }
29
+
30
+ // Use global index for stable keys across window shifts
31
+ result.push({
32
+ type: 'message',
33
+ data: message,
34
+ key: `message-${startIndex + index}`
35
+ });
36
+ });
37
+
38
+ return result;
39
+ }
@@ -0,0 +1,219 @@
1
+ import type { SDKMessageFormatter } from '$shared/types/database/schema';
2
+ import {
3
+ shouldFilterMessage,
4
+ extractToolUses,
5
+ extractToolResults
6
+ } from './message-processor';
7
+ import { processToolMessage } from './tool-handler';
8
+
9
+ // Tool group for mapping tool_use with tool_result
10
+ export interface ToolGroup {
11
+ toolUseMessage: SDKMessageFormatter;
12
+ toolResultMessage: SDKMessageFormatter | null;
13
+ }
14
+
15
+ // Background bash session data
16
+ export interface BackgroundBashData {
17
+ bashToolId: string;
18
+ bashOutputs: any[];
19
+ }
20
+
21
+ // Processed message type
22
+ export type ProcessedMessage = SDKMessageFormatter;
23
+
24
+ // Group tool_use and tool_result messages together
25
+ export function groupMessages(messages: SDKMessageFormatter[]): {
26
+ groups: ProcessedMessage[],
27
+ toolUseMap: Map<string, ToolGroup>
28
+ } {
29
+ const groups: ProcessedMessage[] = [];
30
+ const toolUseMap = new Map<string, ToolGroup>();
31
+
32
+ messages.forEach(message => {
33
+ // Skip messages that should be filtered
34
+ if (shouldFilterMessage(message)) {
35
+ return;
36
+ }
37
+
38
+ // Handle assistant messages with tool_use
39
+ if (message.type === 'assistant' && 'message' in message && message.message?.content) {
40
+ const toolUses = extractToolUses(message.message.content);
41
+
42
+ if (toolUses.length > 0) {
43
+ // Store tool_use messages for grouping
44
+ toolUses.forEach((toolUse: any) => {
45
+ if (toolUse.id) {
46
+ toolUseMap.set(toolUse.id, {
47
+ toolUseMessage: message,
48
+ toolResultMessage: null
49
+ });
50
+ }
51
+ });
52
+ groups.push(message as ProcessedMessage);
53
+ } else {
54
+ groups.push(message as ProcessedMessage);
55
+ }
56
+ }
57
+ // Handle user messages with tool_result
58
+ else if (message.type === 'user' && 'message' in message && message.message?.content) {
59
+ const toolResults = extractToolResults(message.message.content);
60
+
61
+ if (toolResults.length > 0) {
62
+ // Group tool_result with corresponding tool_use
63
+ toolResults.forEach((toolResult: any) => {
64
+ if (toolResult.tool_use_id && toolUseMap.has(toolResult.tool_use_id)) {
65
+ const group = toolUseMap.get(toolResult.tool_use_id);
66
+ if (group) {
67
+ group.toolResultMessage = message;
68
+ }
69
+ }
70
+ });
71
+ // Don't add tool_result messages separately
72
+ } else {
73
+ // Regular user message
74
+ groups.push(message as ProcessedMessage);
75
+ }
76
+ }
77
+ // Include stream_event and other messages
78
+ else {
79
+ groups.push(message as ProcessedMessage);
80
+ }
81
+ });
82
+
83
+ return { groups, toolUseMap };
84
+ }
85
+
86
+ // Add tool results to messages
87
+ export function embedToolResults(
88
+ groups: ProcessedMessage[],
89
+ toolUseMap: Map<string, ToolGroup>
90
+ ): ProcessedMessage[] {
91
+ // Track background bash sessions
92
+ const backgroundBashMap = trackBackgroundBashSessions(groups, toolUseMap);
93
+
94
+ // Create combined messages with tool_use including $result property
95
+ return groups.map(message => {
96
+ if (message.type === 'assistant' && 'message' in message && message.message?.content) {
97
+ const toolUses = extractToolUses(message.message.content);
98
+
99
+ if (toolUses.length > 0) {
100
+ const processedMessage = processToolMessage(
101
+ message,
102
+ toolUseMap,
103
+ backgroundBashMap
104
+ );
105
+ return processedMessage;
106
+ }
107
+ }
108
+
109
+ return message;
110
+ });
111
+ }
112
+
113
+ // Track background bash sessions and their outputs
114
+ function trackBackgroundBashSessions(
115
+ groups: ProcessedMessage[],
116
+ toolUseMap: Map<string, ToolGroup>
117
+ ): Map<string, BackgroundBashData> {
118
+ const backgroundBashMap = new Map<string, BackgroundBashData>();
119
+
120
+ groups.forEach(message => {
121
+ if (message.type === 'assistant' && 'message' in message && message.message?.content) {
122
+ const contentArray = Array.isArray(message.message.content)
123
+ ? message.message.content
124
+ : [message.message.content];
125
+
126
+ contentArray.forEach((item) => {
127
+ if (typeof item === 'object' && item && 'type' in item && item.type === 'tool_use') {
128
+ const toolUse = item as any;
129
+ // Check for Bash with run_in_background
130
+ if (toolUse.name === 'Bash' && toolUse.input &&
131
+ typeof toolUse.input === 'object' &&
132
+ 'run_in_background' in toolUse.input &&
133
+ toolUse.input.run_in_background) {
134
+ trackBackgroundBash(toolUse, toolUseMap, backgroundBashMap);
135
+ }
136
+ // Collect all BashOutput results
137
+ else if (toolUse.name === 'BashOutput' && toolUse.input &&
138
+ typeof toolUse.input === 'object' &&
139
+ 'bash_id' in toolUse.input) {
140
+ trackBashOutput(toolUse, toolUseMap, backgroundBashMap);
141
+ }
142
+ }
143
+ });
144
+ }
145
+ });
146
+
147
+ return backgroundBashMap;
148
+ }
149
+
150
+ function trackBackgroundBash(
151
+ item: any,
152
+ toolUseMap: Map<string, ToolGroup>,
153
+ backgroundBashMap: Map<string, BackgroundBashData>
154
+ ): void {
155
+ const toolId = item.id;
156
+ if (!toolId || !toolUseMap.has(toolId)) return;
157
+
158
+ const group = toolUseMap.get(toolId);
159
+ if (!group?.toolResultMessage) return;
160
+
161
+ const resultMessage = group.toolResultMessage as any;
162
+ const resultContent = resultMessage.message ?
163
+ (Array.isArray(resultMessage.message.content) ? resultMessage.message.content : [resultMessage.message.content]) : [];
164
+
165
+ const toolResult = resultContent.find((resultItem: any) =>
166
+ typeof resultItem === 'object' &&
167
+ resultItem &&
168
+ 'type' in resultItem &&
169
+ resultItem.type === 'tool_result' &&
170
+ 'tool_use_id' in resultItem &&
171
+ resultItem.tool_use_id === toolId
172
+ ) as any | undefined;
173
+
174
+ if (toolResult?.content && typeof toolResult.content === 'string') {
175
+ // Extract bash ID from "Command running in background with ID: xxxxx"
176
+ const idMatch = toolResult.content.match(/Command running in background with ID:\s*(\w+)/);
177
+ if (idMatch) {
178
+ const bashId = idMatch[1];
179
+ backgroundBashMap.set(bashId, {
180
+ bashToolId: toolId,
181
+ bashOutputs: []
182
+ });
183
+ }
184
+ }
185
+ }
186
+
187
+ function trackBashOutput(
188
+ item: any,
189
+ toolUseMap: Map<string, ToolGroup>,
190
+ backgroundBashMap: Map<string, BackgroundBashData>
191
+ ): void {
192
+ const bashId = (item.input as any).bash_id as string;
193
+ const toolId = item.id;
194
+
195
+ if (!toolId || !toolUseMap.has(toolId)) return;
196
+
197
+ const group = toolUseMap.get(toolId);
198
+ if (!group?.toolResultMessage) return;
199
+
200
+ const resultMessage = group.toolResultMessage as any;
201
+ const resultContent = resultMessage.message ?
202
+ (Array.isArray(resultMessage.message.content) ? resultMessage.message.content : [resultMessage.message.content]) : [];
203
+
204
+ const toolResult = resultContent.find((resultItem: any) =>
205
+ typeof resultItem === 'object' &&
206
+ resultItem &&
207
+ 'type' in resultItem &&
208
+ resultItem.type === 'tool_result' &&
209
+ 'tool_use_id' in resultItem &&
210
+ resultItem.tool_use_id === toolId
211
+ ) as any | undefined;
212
+
213
+ if (toolResult && backgroundBashMap.has(bashId)) {
214
+ const bashData = backgroundBashMap.get(bashId);
215
+ if (bashData) {
216
+ bashData.bashOutputs.push(toolResult);
217
+ }
218
+ }
219
+ }
@@ -0,0 +1,135 @@
1
+ import type { SDKMessageFormatter } from '$shared/types/database/schema';
2
+ import type { ToolInput } from '$shared/types/messaging';
3
+
4
+ // Content that can be either single or array
5
+ export type MessageContentArray = any[] | any | string;
6
+
7
+ // Helper type guards
8
+ export function isToolUseBlock(item: unknown): boolean {
9
+ return (
10
+ typeof item === 'object' &&
11
+ item !== null &&
12
+ 'type' in item &&
13
+ (item as any).type === 'tool_use'
14
+ );
15
+ }
16
+
17
+ export function isToolResultBlock(item: unknown): boolean {
18
+ return (
19
+ typeof item === 'object' &&
20
+ item !== null &&
21
+ 'type' in item &&
22
+ (item as any).type === 'tool_result'
23
+ );
24
+ }
25
+
26
+ // Ensure content is always an array
27
+ export function normalizeContent(content: MessageContentArray): any[] {
28
+ if (Array.isArray(content)) {
29
+ return content;
30
+ }
31
+ if (typeof content === 'string') {
32
+ return [{ type: 'text', text: content }];
33
+ }
34
+ return [content];
35
+ }
36
+
37
+ // List of tool names that should include tool_result in content
38
+ export const TOOLS_WITH_RESULTS: ToolInput['name'][] = [
39
+ 'Bash',
40
+ 'TaskOutput',
41
+ 'Edit',
42
+ 'ExitPlanMode',
43
+ 'Glob',
44
+ 'Grep',
45
+ 'KillShell',
46
+ 'ListMcpResources',
47
+ 'NotebookEdit',
48
+ 'ReadMcpResource',
49
+ 'Read',
50
+ 'Task',
51
+ 'TodoWrite',
52
+ 'WebFetch',
53
+ 'WebSearch',
54
+ 'Write'
55
+ ];
56
+
57
+ // Tools that should be hidden from display
58
+ export const HIDDEN_TOOLS: ToolInput['name'][] = [
59
+ 'TaskOutput',
60
+ 'TodoWrite'
61
+ ];
62
+
63
+ // Check if a message should be filtered out
64
+ export function shouldFilterMessage(message: SDKMessageFormatter): boolean {
65
+ // Skip system and result type messages
66
+ if (message.type === 'system' || message.type === 'result') {
67
+ return true;
68
+ }
69
+
70
+ // Filter out stream_event messages with no partial text
71
+ if (message.type === 'stream_event') {
72
+ if (!('partialText' in message) || !message.partialText) {
73
+ return true;
74
+ }
75
+ }
76
+
77
+ // Filter out assistant messages with no visible content
78
+ if (message.type === 'assistant') {
79
+ // No message property at all
80
+ if (!('message' in message) || !message.message) {
81
+ return true;
82
+ }
83
+
84
+ const content = message.message.content;
85
+
86
+ // No content or falsy content
87
+ if (!content) {
88
+ return true;
89
+ }
90
+
91
+ if (Array.isArray(content)) {
92
+ // Empty content array
93
+ if (content.length === 0) {
94
+ return true;
95
+ }
96
+ // Check if there's any meaningful visible content
97
+ const hasNonEmptyText = content.some((item: any) =>
98
+ item.type === 'text' && item.text && item.text.trim().length > 0
99
+ );
100
+ const hasToolUse = content.some((item: any) => item.type === 'tool_use');
101
+ // Filter if no meaningful text and no tool_use blocks
102
+ if (!hasNonEmptyText && !hasToolUse) {
103
+ return true;
104
+ }
105
+ }
106
+ }
107
+
108
+ return false;
109
+ }
110
+
111
+ // Extract tool uses from message content
112
+ export function extractToolUses(content: MessageContentArray): any[] {
113
+ const contentArray = normalizeContent(content);
114
+ return contentArray.filter(isToolUseBlock);
115
+ }
116
+
117
+ // Extract tool results from message content
118
+ export function extractToolResults(content: MessageContentArray): any[] {
119
+ const contentArray = normalizeContent(content);
120
+ return contentArray.filter(isToolResultBlock);
121
+ }
122
+
123
+ // Check if a tool should have its result embedded
124
+ export function shouldEmbedResult(toolName: string): boolean {
125
+ // Custom MCP tools always embed results (they start with 'mcp__')
126
+ if (toolName.startsWith('mcp__')) {
127
+ return true;
128
+ }
129
+ return TOOLS_WITH_RESULTS.includes(toolName as ToolInput['name']);
130
+ }
131
+
132
+ // Check if a tool should be hidden
133
+ export function shouldHideTool(toolName: string): boolean {
134
+ return HIDDEN_TOOLS.includes(toolName as ToolInput['name']);
135
+ }
@@ -0,0 +1,161 @@
1
+ import {
2
+ shouldEmbedResult,
3
+ shouldHideTool
4
+ } from './message-processor';
5
+ import type {
6
+ ProcessedMessage,
7
+ ToolGroup,
8
+ BackgroundBashData
9
+ } from './message-grouper';
10
+
11
+ // Extended ToolUse with embedded result
12
+ export interface ToolUseWithResult {
13
+ type: 'tool_use';
14
+ id: string;
15
+ name: string;
16
+ input: any;
17
+ $result?: any;
18
+ }
19
+
20
+ // Process a tool message with embedded results
21
+ export function processToolMessage(
22
+ message: ProcessedMessage,
23
+ toolUseMap: Map<string, ToolGroup>,
24
+ backgroundBashMap: Map<string, BackgroundBashData>
25
+ ): ProcessedMessage {
26
+ const messageAny = message as any;
27
+ const content = messageAny.message?.content ?
28
+ (Array.isArray(messageAny.message.content) ? messageAny.message.content : [messageAny.message.content]) : [];
29
+
30
+ // Create modified content with embedded tool_result in tool_use objects
31
+ const modifiedContent = content
32
+ .map((item: any): any => {
33
+ if (typeof item === 'object' && item && 'type' in item && item.type === 'tool_use') {
34
+ return processToolUse(item, toolUseMap, backgroundBashMap);
35
+ }
36
+ return item;
37
+ })
38
+ .filter((item: any) => item !== null); // Remove null items (hidden tools)
39
+
40
+ // Return modified message with embedded tool_results
41
+ return {
42
+ ...message,
43
+ message: {
44
+ ...messageAny.message,
45
+ content: modifiedContent
46
+ }
47
+ } as ProcessedMessage;
48
+ }
49
+
50
+ // Process individual tool_use item
51
+ function processToolUse(
52
+ item: any,
53
+ toolUseMap: Map<string, ToolGroup>,
54
+ backgroundBashMap: Map<string, BackgroundBashData>
55
+ ): ToolUseWithResult | null {
56
+ // Hide certain tools completely
57
+ if (shouldHideTool(item.name)) {
58
+ return null;
59
+ }
60
+
61
+ // Special handling for Bash with run_in_background
62
+ if (item.name === 'Bash' && item.input &&
63
+ typeof item.input === 'object' &&
64
+ 'run_in_background' in item.input &&
65
+ item.input.run_in_background && item.id) {
66
+ return handleBackgroundBash(item, toolUseMap, backgroundBashMap);
67
+ }
68
+
69
+ // Regular tool handling
70
+ if (item.id && item.name && shouldEmbedResult(item.name) && toolUseMap.has(item.id)) {
71
+ return handleRegularTool(item, toolUseMap);
72
+ }
73
+
74
+ return item;
75
+ }
76
+
77
+ // Handle background bash commands
78
+ function handleBackgroundBash(
79
+ item: any,
80
+ toolUseMap: Map<string, ToolGroup>,
81
+ backgroundBashMap: Map<string, BackgroundBashData>
82
+ ): ToolUseWithResult {
83
+ const group = toolUseMap.get(item.id);
84
+ if (!group?.toolResultMessage) return item;
85
+
86
+ const resultMessage = group.toolResultMessage as any;
87
+ const resultContent = resultMessage.message ?
88
+ (Array.isArray(resultMessage.message.content) ? resultMessage.message.content : [resultMessage.message.content]) : [];
89
+
90
+ const toolResult = findToolResult(resultContent, item.id);
91
+
92
+ if (!toolResult?.content || typeof toolResult.content !== 'string') return item;
93
+
94
+ // Extract bash ID and check for BashOutput
95
+ const idMatch = toolResult.content.match(/Command running in background with ID:\s*(\w+)/);
96
+ if (!idMatch) return item;
97
+
98
+ const bashId = idMatch[1];
99
+ const bashData = backgroundBashMap.get(bashId);
100
+
101
+ if (bashData && bashData.bashOutputs.length > 0) {
102
+ // Use the last BashOutput result
103
+ const lastOutput = bashData.bashOutputs[bashData.bashOutputs.length - 1];
104
+ return {
105
+ ...item,
106
+ $result: {
107
+ ...toolResult,
108
+ content: lastOutput.content || ""
109
+ }
110
+ } as ToolUseWithResult;
111
+ } else {
112
+ // No BashOutput found, clear the content
113
+ return {
114
+ ...item,
115
+ $result: {
116
+ ...toolResult,
117
+ content: ""
118
+ }
119
+ } as ToolUseWithResult;
120
+ }
121
+ }
122
+
123
+ // Handle regular tools
124
+ function handleRegularTool(
125
+ item: any,
126
+ toolUseMap: Map<string, ToolGroup>
127
+ ): ToolUseWithResult {
128
+ const group = toolUseMap.get(item.id);
129
+ if (!group || !group.toolResultMessage) return item;
130
+
131
+ const resultMessage = group.toolResultMessage as any;
132
+ const resultContent = resultMessage.message ?
133
+ (Array.isArray(resultMessage.message.content) ? resultMessage.message.content : [resultMessage.message.content]) : [];
134
+
135
+ const toolResult = findToolResult(resultContent, item.id);
136
+
137
+ if (toolResult) {
138
+ // Embed tool_result as $result property in tool_use object
139
+ return {
140
+ ...item,
141
+ $result: toolResult
142
+ } as ToolUseWithResult;
143
+ }
144
+
145
+ return item;
146
+ }
147
+
148
+ // Helper to find tool result by id
149
+ function findToolResult(
150
+ content: any[],
151
+ toolUseId: string
152
+ ): any {
153
+ return content.find((resultItem: any) =>
154
+ typeof resultItem === 'object' &&
155
+ resultItem !== null &&
156
+ 'type' in resultItem &&
157
+ resultItem.type === 'tool_result' &&
158
+ 'tool_use_id' in resultItem &&
159
+ resultItem.tool_use_id === toolUseId
160
+ );
161
+ }