mulmoclaude 0.1.0

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 (408) hide show
  1. package/README.md +44 -0
  2. package/bin/mulmoclaude.js +202 -0
  3. package/bin/prepare-dist.js +93 -0
  4. package/client/assets/chunk-vKJrgz-R-C_I3GbVV.js +1 -0
  5. package/client/assets/html2canvas-Cx501zZr-BF5dYYkY.js +5 -0
  6. package/client/assets/index-D8rhwXLq.js +4906 -0
  7. package/client/assets/index-KNLBjwuh.css +1 -0
  8. package/client/assets/index.es-D4YyL_Dg-BfRHLTZV.js +5 -0
  9. package/client/assets/material-icons-Dr0goTwe.woff +0 -0
  10. package/client/assets/material-icons-kAwBdRge.woff2 +0 -0
  11. package/client/assets/material-icons-outlined-BpWbwl2n.woff +0 -0
  12. package/client/assets/material-icons-outlined-DZhiGvEA.woff2 +0 -0
  13. package/client/assets/material-icons-round-BDlwx-sv.woff +0 -0
  14. package/client/assets/material-icons-round-DrirKXBx.woff2 +0 -0
  15. package/client/assets/material-icons-sharp-CH1KkVu7.woff +0 -0
  16. package/client/assets/material-icons-sharp-gidztirS.woff2 +0 -0
  17. package/client/assets/material-icons-two-tone-B7wz7mED.woff +0 -0
  18. package/client/assets/material-icons-two-tone-DuNIpaEj.woff2 +0 -0
  19. package/client/assets/mulmo_bw-ERmkSv0a.png +0 -0
  20. package/client/assets/purify.es-Fx1Nqyry-PeS5RUhs.js +2 -0
  21. package/client/assets/typeof-DBp4T-Ny-BC0P-2DM.js +1 -0
  22. package/client/index.html +28 -0
  23. package/package.json +66 -0
  24. package/server/agent/attachmentConverter.ts +270 -0
  25. package/server/agent/config.ts +414 -0
  26. package/server/agent/index.ts +260 -0
  27. package/server/agent/mcp-server.ts +412 -0
  28. package/server/agent/mcp-tools/index.ts +63 -0
  29. package/server/agent/mcp-tools/x.ts +188 -0
  30. package/server/agent/plugin-names.ts +75 -0
  31. package/server/agent/prompt.ts +349 -0
  32. package/server/agent/resumeFailover.ts +129 -0
  33. package/server/agent/sandboxMounts.ts +329 -0
  34. package/server/agent/stream.ts +194 -0
  35. package/server/api/auth/bearerAuth.ts +61 -0
  36. package/server/api/auth/token.ts +98 -0
  37. package/server/api/csrfGuard.ts +85 -0
  38. package/server/api/routes/agent.ts +478 -0
  39. package/server/api/routes/chart.ts +98 -0
  40. package/server/api/routes/chat-index.ts +46 -0
  41. package/server/api/routes/config.ts +258 -0
  42. package/server/api/routes/dispatchResponse.ts +79 -0
  43. package/server/api/routes/files.ts +812 -0
  44. package/server/api/routes/html.ts +101 -0
  45. package/server/api/routes/image.ts +169 -0
  46. package/server/api/routes/mulmo-script.ts +712 -0
  47. package/server/api/routes/mulmoScriptValidate.ts +101 -0
  48. package/server/api/routes/notifications.ts +69 -0
  49. package/server/api/routes/pdf.ts +163 -0
  50. package/server/api/routes/plugins.ts +276 -0
  51. package/server/api/routes/presentHtml.ts +48 -0
  52. package/server/api/routes/roles.ts +125 -0
  53. package/server/api/routes/scheduler.ts +153 -0
  54. package/server/api/routes/schedulerHandlers.ts +151 -0
  55. package/server/api/routes/schedulerTasks.ts +163 -0
  56. package/server/api/routes/sessions.ts +294 -0
  57. package/server/api/routes/sessionsCursor.ts +59 -0
  58. package/server/api/routes/skills.ts +195 -0
  59. package/server/api/routes/sources.ts +540 -0
  60. package/server/api/routes/todos.ts +263 -0
  61. package/server/api/routes/todosColumnsHandlers.ts +347 -0
  62. package/server/api/routes/todosHandlers.ts +274 -0
  63. package/server/api/routes/todosItemsHandlers.ts +386 -0
  64. package/server/api/routes/wiki/pageIndex.ts +53 -0
  65. package/server/api/routes/wiki.ts +363 -0
  66. package/server/api/sandboxStatus.ts +64 -0
  67. package/server/events/notifications.ts +160 -0
  68. package/server/events/pub-sub/index.ts +45 -0
  69. package/server/events/relay-client.ts +288 -0
  70. package/server/events/scheduler-adapter.ts +302 -0
  71. package/server/events/session-store/index.ts +492 -0
  72. package/server/events/task-manager/index.ts +181 -0
  73. package/server/index.ts +572 -0
  74. package/server/system/config.ts +243 -0
  75. package/server/system/credentials.ts +220 -0
  76. package/server/system/docker.ts +97 -0
  77. package/server/system/env.ts +109 -0
  78. package/server/system/logger/config.ts +112 -0
  79. package/server/system/logger/formatters.ts +40 -0
  80. package/server/system/logger/index.ts +53 -0
  81. package/server/system/logger/rotation.ts +37 -0
  82. package/server/system/logger/sinks.ts +101 -0
  83. package/server/system/logger/types.ts +29 -0
  84. package/server/utils/date.ts +57 -0
  85. package/server/utils/errors.ts +7 -0
  86. package/server/utils/fetch.ts +27 -0
  87. package/server/utils/files/atomic.ts +125 -0
  88. package/server/utils/files/html-io.ts +20 -0
  89. package/server/utils/files/image-store.ts +66 -0
  90. package/server/utils/files/index.ts +45 -0
  91. package/server/utils/files/journal-io.ts +213 -0
  92. package/server/utils/files/json.ts +69 -0
  93. package/server/utils/files/markdown-store.ts +33 -0
  94. package/server/utils/files/naming.ts +50 -0
  95. package/server/utils/files/reference-dirs-io.ts +45 -0
  96. package/server/utils/files/roles-io.ts +45 -0
  97. package/server/utils/files/safe.ts +106 -0
  98. package/server/utils/files/scheduler-io.ts +20 -0
  99. package/server/utils/files/scheduler-overrides-io.ts +64 -0
  100. package/server/utils/files/session-io.ts +136 -0
  101. package/server/utils/files/spreadsheet-store.ts +63 -0
  102. package/server/utils/files/todos-io.ts +29 -0
  103. package/server/utils/files/user-tasks-io.ts +25 -0
  104. package/server/utils/files/workspace-io.ts +221 -0
  105. package/server/utils/gemini.ts +59 -0
  106. package/server/utils/gitignore.ts +69 -0
  107. package/server/utils/http.ts +15 -0
  108. package/server/utils/httpError.ts +61 -0
  109. package/server/utils/id.ts +16 -0
  110. package/server/utils/json.ts +83 -0
  111. package/server/utils/logBackgroundError.ts +22 -0
  112. package/server/utils/markdown.ts +82 -0
  113. package/server/utils/request.ts +29 -0
  114. package/server/utils/slug.ts +50 -0
  115. package/server/utils/spawn.ts +62 -0
  116. package/server/utils/time.ts +34 -0
  117. package/server/utils/types.ts +47 -0
  118. package/server/workspace/chat-index/index.ts +153 -0
  119. package/server/workspace/chat-index/indexer.ts +209 -0
  120. package/server/workspace/chat-index/paths.ts +34 -0
  121. package/server/workspace/chat-index/summarizer.ts +247 -0
  122. package/server/workspace/chat-index/types.ts +38 -0
  123. package/server/workspace/custom-dirs.ts +220 -0
  124. package/server/workspace/helps/business.md +104 -0
  125. package/server/workspace/helps/github.md +23 -0
  126. package/server/workspace/helps/index.md +60 -0
  127. package/server/workspace/helps/mulmoscript.md +249 -0
  128. package/server/workspace/helps/sandbox.md +90 -0
  129. package/server/workspace/helps/spreadsheet.md +43 -0
  130. package/server/workspace/helps/telegram.md +135 -0
  131. package/server/workspace/helps/wiki.md +131 -0
  132. package/server/workspace/journal/archivist.ts +386 -0
  133. package/server/workspace/journal/dailyPass.ts +743 -0
  134. package/server/workspace/journal/diff.ts +71 -0
  135. package/server/workspace/journal/index.ts +185 -0
  136. package/server/workspace/journal/indexFile.ts +136 -0
  137. package/server/workspace/journal/linkRewrite.ts +4 -0
  138. package/server/workspace/journal/memoryExtractor.ts +130 -0
  139. package/server/workspace/journal/optimizationPass.ts +160 -0
  140. package/server/workspace/journal/paths.ts +76 -0
  141. package/server/workspace/journal/state.ts +125 -0
  142. package/server/workspace/paths.ts +158 -0
  143. package/server/workspace/reference-dirs.ts +252 -0
  144. package/server/workspace/roles.ts +37 -0
  145. package/server/workspace/skills/discovery.ts +125 -0
  146. package/server/workspace/skills/index.ts +10 -0
  147. package/server/workspace/skills/parser.ts +144 -0
  148. package/server/workspace/skills/paths.ts +41 -0
  149. package/server/workspace/skills/scheduler.ts +149 -0
  150. package/server/workspace/skills/types.ts +30 -0
  151. package/server/workspace/skills/user-tasks.ts +257 -0
  152. package/server/workspace/skills/writer.ts +189 -0
  153. package/server/workspace/sources/arxivDiscovery.ts +182 -0
  154. package/server/workspace/sources/classifier.ts +268 -0
  155. package/server/workspace/sources/fetchers/arxiv.ts +170 -0
  156. package/server/workspace/sources/fetchers/github.ts +106 -0
  157. package/server/workspace/sources/fetchers/githubIssues.ts +208 -0
  158. package/server/workspace/sources/fetchers/githubReleases.ts +186 -0
  159. package/server/workspace/sources/fetchers/index.ts +71 -0
  160. package/server/workspace/sources/fetchers/registerAll.ts +15 -0
  161. package/server/workspace/sources/fetchers/rss.ts +141 -0
  162. package/server/workspace/sources/fetchers/rssParser.ts +295 -0
  163. package/server/workspace/sources/httpFetcher.ts +230 -0
  164. package/server/workspace/sources/interests.ts +120 -0
  165. package/server/workspace/sources/paths.ts +110 -0
  166. package/server/workspace/sources/pipeline/dedup.ts +60 -0
  167. package/server/workspace/sources/pipeline/fetch.ts +136 -0
  168. package/server/workspace/sources/pipeline/index.ts +249 -0
  169. package/server/workspace/sources/pipeline/notify.ts +72 -0
  170. package/server/workspace/sources/pipeline/plan.ts +66 -0
  171. package/server/workspace/sources/pipeline/summarize.ts +189 -0
  172. package/server/workspace/sources/pipeline/write.ts +185 -0
  173. package/server/workspace/sources/rateLimiter.ts +148 -0
  174. package/server/workspace/sources/registry.ts +326 -0
  175. package/server/workspace/sources/robots.ts +271 -0
  176. package/server/workspace/sources/sourceState.ts +135 -0
  177. package/server/workspace/sources/taxonomy.ts +74 -0
  178. package/server/workspace/sources/types.ts +144 -0
  179. package/server/workspace/sources/urls.ts +112 -0
  180. package/server/workspace/tool-trace/classify.ts +114 -0
  181. package/server/workspace/tool-trace/index.ts +250 -0
  182. package/server/workspace/tool-trace/writeSearch.ts +98 -0
  183. package/server/workspace/wiki-backlinks/index.ts +107 -0
  184. package/server/workspace/wiki-backlinks/sessionBacklinks.ts +144 -0
  185. package/server/workspace/workspace.ts +66 -0
  186. package/src/App.vue +720 -0
  187. package/src/assets/mulmo_bw.png +0 -0
  188. package/src/components/CanvasViewToggle.vue +27 -0
  189. package/src/components/ChatAttachmentPreview.vue +45 -0
  190. package/src/components/ChatImagePreview.vue +17 -0
  191. package/src/components/ChatInput.vue +208 -0
  192. package/src/components/FileContentHeader.vue +49 -0
  193. package/src/components/FileContentRenderer.vue +162 -0
  194. package/src/components/FileTree.vue +115 -0
  195. package/src/components/FileTreePane.vue +85 -0
  196. package/src/components/FilesView.vue +206 -0
  197. package/src/components/LockStatusPopup.vue +111 -0
  198. package/src/components/NotificationBell.vue +131 -0
  199. package/src/components/NotificationToast.vue +72 -0
  200. package/src/components/PluginLauncher.vue +138 -0
  201. package/src/components/RightSidebar.vue +113 -0
  202. package/src/components/RoleSelector.vue +64 -0
  203. package/src/components/SessionHistoryPanel.vue +176 -0
  204. package/src/components/SessionTabBar.vue +81 -0
  205. package/src/components/SettingsMcpTab.vue +350 -0
  206. package/src/components/SettingsModal.vue +275 -0
  207. package/src/components/SettingsReferenceDirsTab.vue +173 -0
  208. package/src/components/SettingsWorkspaceDirsTab.vue +174 -0
  209. package/src/components/SidebarHeader.vue +69 -0
  210. package/src/components/StackView.vue +360 -0
  211. package/src/components/SuggestionsPanel.vue +65 -0
  212. package/src/components/TodoExplorer.vue +358 -0
  213. package/src/components/ToolResultsPanel.vue +77 -0
  214. package/src/components/todo/TodoAddDialog.vue +131 -0
  215. package/src/components/todo/TodoEditDialog.vue +47 -0
  216. package/src/components/todo/TodoEditPanel.vue +113 -0
  217. package/src/components/todo/TodoKanbanView.vue +249 -0
  218. package/src/components/todo/TodoListView.vue +79 -0
  219. package/src/components/todo/TodoTableView.vue +177 -0
  220. package/src/composables/useActiveSession.ts +40 -0
  221. package/src/composables/useAppApi.ts +45 -0
  222. package/src/composables/useCanvasViewMode.ts +121 -0
  223. package/src/composables/useChatScroll.ts +47 -0
  224. package/src/composables/useClickOutside.ts +26 -0
  225. package/src/composables/useClipboardCopy.ts +44 -0
  226. package/src/composables/useContentDisplay.ts +52 -0
  227. package/src/composables/useDebugBeat.ts +23 -0
  228. package/src/composables/useDynamicFavicon.ts +115 -0
  229. package/src/composables/useEventListeners.ts +42 -0
  230. package/src/composables/useExpandedDirs.ts +64 -0
  231. package/src/composables/useFaviconState.ts +30 -0
  232. package/src/composables/useFileSelection.ts +115 -0
  233. package/src/composables/useFileSortMode.ts +24 -0
  234. package/src/composables/useFileTree.ts +85 -0
  235. package/src/composables/useFreshPluginData.ts +89 -0
  236. package/src/composables/useHealth.ts +38 -0
  237. package/src/composables/useImeAwareEnter.ts +57 -0
  238. package/src/composables/useKeyNavigation.ts +60 -0
  239. package/src/composables/useMarkdownLinkHandler.ts +46 -0
  240. package/src/composables/useMarkdownMode.ts +17 -0
  241. package/src/composables/useMcpTools.ts +71 -0
  242. package/src/composables/useMergedSessions.ts +27 -0
  243. package/src/composables/useNotifications.ts +90 -0
  244. package/src/composables/usePdfDownload.ts +60 -0
  245. package/src/composables/usePendingCalls.ts +77 -0
  246. package/src/composables/usePubSub.ts +85 -0
  247. package/src/composables/useRightSidebar.ts +23 -0
  248. package/src/composables/useRoles.ts +34 -0
  249. package/src/composables/useSandboxStatus.ts +67 -0
  250. package/src/composables/useSelectedResult.ts +49 -0
  251. package/src/composables/useSessionDerived.ts +51 -0
  252. package/src/composables/useSessionHistory.ts +81 -0
  253. package/src/composables/useSessionSync.ts +57 -0
  254. package/src/composables/useViewLayout.ts +55 -0
  255. package/src/config/apiRoutes.ts +173 -0
  256. package/src/config/pubsubChannels.ts +45 -0
  257. package/src/config/roles.ts +335 -0
  258. package/src/config/schedulerActions.ts +25 -0
  259. package/src/config/toolNames.ts +71 -0
  260. package/src/config/workspacePaths.ts +24 -0
  261. package/src/index.css +107 -0
  262. package/src/main.ts +25 -0
  263. package/src/plugins/canvas/Preview.vue +13 -0
  264. package/src/plugins/canvas/View.vue +333 -0
  265. package/src/plugins/canvas/definition.ts +38 -0
  266. package/src/plugins/canvas/index.ts +36 -0
  267. package/src/plugins/chart/Preview.vue +49 -0
  268. package/src/plugins/chart/View.vue +143 -0
  269. package/src/plugins/chart/definition.ts +58 -0
  270. package/src/plugins/chart/index.ts +52 -0
  271. package/src/plugins/editImage/Preview.vue +13 -0
  272. package/src/plugins/editImage/View.vue +13 -0
  273. package/src/plugins/editImage/definition.ts +27 -0
  274. package/src/plugins/editImage/index.ts +36 -0
  275. package/src/plugins/generateImage/Preview.vue +13 -0
  276. package/src/plugins/generateImage/View.vue +33 -0
  277. package/src/plugins/generateImage/definition.ts +32 -0
  278. package/src/plugins/generateImage/index.ts +56 -0
  279. package/src/plugins/manageRoles/Preview.vue +49 -0
  280. package/src/plugins/manageRoles/View.vue +525 -0
  281. package/src/plugins/manageRoles/definition.ts +43 -0
  282. package/src/plugins/manageRoles/index.ts +47 -0
  283. package/src/plugins/manageSkills/Preview.vue +21 -0
  284. package/src/plugins/manageSkills/View.vue +321 -0
  285. package/src/plugins/manageSkills/definition.ts +49 -0
  286. package/src/plugins/manageSkills/index.ts +49 -0
  287. package/src/plugins/manageSource/Preview.vue +33 -0
  288. package/src/plugins/manageSource/View.vue +697 -0
  289. package/src/plugins/manageSource/definition.ts +63 -0
  290. package/src/plugins/manageSource/index.ts +66 -0
  291. package/src/plugins/markdown/Preview.vue +77 -0
  292. package/src/plugins/markdown/View.vue +476 -0
  293. package/src/plugins/markdown/definition.ts +50 -0
  294. package/src/plugins/markdown/index.ts +36 -0
  295. package/src/plugins/presentHtml/Preview.vue +25 -0
  296. package/src/plugins/presentHtml/View.vue +52 -0
  297. package/src/plugins/presentHtml/definition.ts +27 -0
  298. package/src/plugins/presentHtml/helpers.ts +72 -0
  299. package/src/plugins/presentHtml/index.ts +41 -0
  300. package/src/plugins/presentMulmoScript/Preview.vue +23 -0
  301. package/src/plugins/presentMulmoScript/View.vue +1166 -0
  302. package/src/plugins/presentMulmoScript/definition.ts +95 -0
  303. package/src/plugins/presentMulmoScript/helpers.ts +162 -0
  304. package/src/plugins/presentMulmoScript/index.ts +40 -0
  305. package/src/plugins/scheduler/Preview.vue +67 -0
  306. package/src/plugins/scheduler/TasksTab.vue +205 -0
  307. package/src/plugins/scheduler/View.vue +565 -0
  308. package/src/plugins/scheduler/definition.ts +57 -0
  309. package/src/plugins/scheduler/index.ts +45 -0
  310. package/src/plugins/scheduler/viewModes.ts +26 -0
  311. package/src/plugins/spreadsheet/Preview.vue +29 -0
  312. package/src/plugins/spreadsheet/View.vue +997 -0
  313. package/src/plugins/spreadsheet/cellHighlights.ts +79 -0
  314. package/src/plugins/spreadsheet/definition.ts +121 -0
  315. package/src/plugins/spreadsheet/engine/calculator.ts +459 -0
  316. package/src/plugins/spreadsheet/engine/cellBuilder.ts +81 -0
  317. package/src/plugins/spreadsheet/engine/date-parser.ts +220 -0
  318. package/src/plugins/spreadsheet/engine/date-utils.ts +56 -0
  319. package/src/plugins/spreadsheet/engine/engine.ts +176 -0
  320. package/src/plugins/spreadsheet/engine/evaluator.ts +390 -0
  321. package/src/plugins/spreadsheet/engine/formatter.ts +172 -0
  322. package/src/plugins/spreadsheet/engine/formulaRefs.ts +101 -0
  323. package/src/plugins/spreadsheet/engine/functions/date.ts +299 -0
  324. package/src/plugins/spreadsheet/engine/functions/financial.ts +387 -0
  325. package/src/plugins/spreadsheet/engine/functions/index.ts +16 -0
  326. package/src/plugins/spreadsheet/engine/functions/logical.ts +262 -0
  327. package/src/plugins/spreadsheet/engine/functions/lookup.ts +400 -0
  328. package/src/plugins/spreadsheet/engine/functions/mathematical.ts +297 -0
  329. package/src/plugins/spreadsheet/engine/functions/statistical.ts +338 -0
  330. package/src/plugins/spreadsheet/engine/functions/text.ts +389 -0
  331. package/src/plugins/spreadsheet/engine/index.ts +27 -0
  332. package/src/plugins/spreadsheet/engine/jsonCellLocator.ts +111 -0
  333. package/src/plugins/spreadsheet/engine/parser.ts +143 -0
  334. package/src/plugins/spreadsheet/engine/registry.ts +150 -0
  335. package/src/plugins/spreadsheet/engine/responseDecoder.ts +67 -0
  336. package/src/plugins/spreadsheet/engine/types.ts +64 -0
  337. package/src/plugins/spreadsheet/index.ts +36 -0
  338. package/src/plugins/textResponse/Preview.vue +94 -0
  339. package/src/plugins/textResponse/View.vue +503 -0
  340. package/src/plugins/textResponse/definition.ts +34 -0
  341. package/src/plugins/textResponse/index.ts +27 -0
  342. package/src/plugins/textResponse/plugin.ts +29 -0
  343. package/src/plugins/textResponse/samples.ts +97 -0
  344. package/src/plugins/textResponse/types.ts +11 -0
  345. package/src/plugins/todo/Preview.vue +63 -0
  346. package/src/plugins/todo/View.vue +364 -0
  347. package/src/plugins/todo/composables/useTodos.ts +177 -0
  348. package/src/plugins/todo/definition.ts +45 -0
  349. package/src/plugins/todo/index.ts +61 -0
  350. package/src/plugins/todo/labels.ts +163 -0
  351. package/src/plugins/todo/priority.ts +98 -0
  352. package/src/plugins/todo/viewModes.ts +19 -0
  353. package/src/plugins/ui-image/ImagePreview.vue +23 -0
  354. package/src/plugins/ui-image/ImageView.vue +34 -0
  355. package/src/plugins/ui-image/index.ts +3 -0
  356. package/src/plugins/ui-image/types.ts +4 -0
  357. package/src/plugins/wiki/Preview.vue +65 -0
  358. package/src/plugins/wiki/View.vue +342 -0
  359. package/src/plugins/wiki/definition.ts +25 -0
  360. package/src/plugins/wiki/helpers.ts +59 -0
  361. package/src/plugins/wiki/index.ts +52 -0
  362. package/src/router/guards.ts +61 -0
  363. package/src/router/index.ts +50 -0
  364. package/src/tools/index.ts +52 -0
  365. package/src/tools/types.ts +27 -0
  366. package/src/types/events.ts +16 -0
  367. package/src/types/fileTree.ts +13 -0
  368. package/src/types/notification.ts +67 -0
  369. package/src/types/session.ts +116 -0
  370. package/src/types/sse.ts +90 -0
  371. package/src/types/toolCallHistory.ts +13 -0
  372. package/src/utils/agent/eventDispatch.ts +74 -0
  373. package/src/utils/agent/request.ts +55 -0
  374. package/src/utils/agent/toolCalls.ts +62 -0
  375. package/src/utils/api.ts +218 -0
  376. package/src/utils/canvas/viewMode.ts +46 -0
  377. package/src/utils/dom/authTokenMeta.ts +20 -0
  378. package/src/utils/dom/clickOutside.ts +11 -0
  379. package/src/utils/dom/externalLink.ts +57 -0
  380. package/src/utils/dom/scrollable.ts +24 -0
  381. package/src/utils/errors.ts +11 -0
  382. package/src/utils/files/expandedDirs.ts +25 -0
  383. package/src/utils/files/filename.ts +12 -0
  384. package/src/utils/files/sortChildren.ts +20 -0
  385. package/src/utils/filesPreview/schedulerPreview.ts +38 -0
  386. package/src/utils/filesPreview/todoPreview.ts +40 -0
  387. package/src/utils/format/date.ts +85 -0
  388. package/src/utils/format/frontmatter.ts +80 -0
  389. package/src/utils/format/jsonSyntax.ts +109 -0
  390. package/src/utils/html/previewCsp.ts +65 -0
  391. package/src/utils/image/resolve.ts +8 -0
  392. package/src/utils/image/rewriteMarkdownImageRefs.ts +182 -0
  393. package/src/utils/markdown/extractFirstH1.ts +39 -0
  394. package/src/utils/notification/dispatch.ts +22 -0
  395. package/src/utils/path/relativeLink.ts +130 -0
  396. package/src/utils/role/icon.ts +20 -0
  397. package/src/utils/role/merge.ts +10 -0
  398. package/src/utils/role/plugins.ts +12 -0
  399. package/src/utils/session/mergeSessions.ts +103 -0
  400. package/src/utils/session/seedRoleDefault.ts +35 -0
  401. package/src/utils/session/sessionEntries.ts +121 -0
  402. package/src/utils/session/sessionFactory.ts +22 -0
  403. package/src/utils/session/sessionHelpers.ts +99 -0
  404. package/src/utils/tools/dedup.ts +17 -0
  405. package/src/utils/tools/mcp.ts +33 -0
  406. package/src/utils/tools/pendingCalls.ts +16 -0
  407. package/src/utils/tools/result.ts +40 -0
  408. package/src/utils/types.ts +44 -0
@@ -0,0 +1,16 @@
1
+ // Single source of truth: @mulmobridge/protocol.
2
+ //
3
+ // This file re-exports so that ~30 server/frontend files that import
4
+ // from "../../src/types/events.js" keep working without a mass rename.
5
+ // New code should import directly from "@mulmobridge/protocol" when
6
+ // it's in a package-eligible module (chat-service, bridges).
7
+
8
+ export {
9
+ EVENT_TYPES,
10
+ type EventType,
11
+ GENERATION_KINDS,
12
+ type GenerationKind,
13
+ type GenerationEvent,
14
+ type PendingGeneration,
15
+ generationKey,
16
+ } from "@mulmobridge/protocol";
@@ -0,0 +1,13 @@
1
+ // TreeNode type — shared between FileTree.vue, FilesView.vue,
2
+ // and composables (useFileTree, useFileSelection).
3
+ // Extracted from FileTree.vue so .ts files can import it without
4
+ // depending on a .vue module (which tsc can't resolve).
5
+
6
+ export interface TreeNode {
7
+ name: string;
8
+ path: string;
9
+ type: "file" | "dir";
10
+ size?: number;
11
+ modifiedMs?: number;
12
+ children?: TreeNode[];
13
+ }
@@ -0,0 +1,67 @@
1
+ // Notification payload — shared by server (publish) and frontend (subscribe).
2
+
3
+ export const NOTIFICATION_KINDS = {
4
+ todo: "todo",
5
+ scheduler: "scheduler",
6
+ agent: "agent",
7
+ journal: "journal",
8
+ push: "push",
9
+ bridge: "bridge",
10
+ } as const;
11
+
12
+ export type NotificationKind = (typeof NOTIFICATION_KINDS)[keyof typeof NOTIFICATION_KINDS];
13
+
14
+ export const NOTIFICATION_ICONS: Record<NotificationKind, string> = {
15
+ todo: "check_circle",
16
+ scheduler: "event",
17
+ agent: "smart_toy",
18
+ journal: "auto_stories",
19
+ push: "notifications",
20
+ bridge: "chat",
21
+ };
22
+
23
+ export const NOTIFICATION_ACTION_TYPES = {
24
+ navigate: "navigate",
25
+ none: "none",
26
+ } as const;
27
+
28
+ export type NotificationActionType = (typeof NOTIFICATION_ACTION_TYPES)[keyof typeof NOTIFICATION_ACTION_TYPES];
29
+
30
+ export const NOTIFICATION_VIEWS = {
31
+ todos: "todos",
32
+ scheduler: "scheduler",
33
+ files: "files",
34
+ chat: "chat",
35
+ } as const;
36
+
37
+ export type NotificationView = (typeof NOTIFICATION_VIEWS)[keyof typeof NOTIFICATION_VIEWS];
38
+
39
+ export const NOTIFICATION_PRIORITIES = {
40
+ normal: "normal",
41
+ high: "high",
42
+ } as const;
43
+
44
+ export type NotificationPriority = (typeof NOTIFICATION_PRIORITIES)[keyof typeof NOTIFICATION_PRIORITIES];
45
+
46
+ export type NotificationAction =
47
+ | {
48
+ type: typeof NOTIFICATION_ACTION_TYPES.navigate;
49
+ view: NotificationView;
50
+ path?: string;
51
+ sessionId?: string;
52
+ itemId?: string;
53
+ }
54
+ | { type: typeof NOTIFICATION_ACTION_TYPES.none };
55
+
56
+ export interface NotificationPayload {
57
+ id: string;
58
+ kind: NotificationKind;
59
+ title: string;
60
+ body?: string;
61
+ icon?: string;
62
+ action: NotificationAction;
63
+ firedAt: string;
64
+ priority: NotificationPriority;
65
+ sessionId?: string;
66
+ transportId?: string;
67
+ }
@@ -0,0 +1,116 @@
1
+ // Per-session client-side state and the on-disk envelope shapes
2
+ // returned by the server's session routes.
3
+
4
+ import type { ToolResultComplete } from "gui-chat-protocol/vue";
5
+ import { EVENT_TYPES, type PendingGeneration } from "./events";
6
+ import type { ToolCallHistoryItem } from "./toolCallHistory";
7
+
8
+ // ── Session origin (#486) ───────────────────────────────────
9
+
10
+ export const SESSION_ORIGINS = {
11
+ human: "human",
12
+ scheduler: "scheduler",
13
+ skill: "skill",
14
+ bridge: "bridge",
15
+ } as const;
16
+
17
+ export type SessionOrigin = (typeof SESSION_ORIGINS)[keyof typeof SESSION_ORIGINS];
18
+
19
+ const VALID_ORIGINS: ReadonlySet<string> = new Set(Object.values(SESSION_ORIGINS));
20
+
21
+ export function isSessionOrigin(value: unknown): value is SessionOrigin {
22
+ return typeof value === "string" && VALID_ORIGINS.has(value);
23
+ }
24
+
25
+ // Server `/api/sessions` summary. Optional `summary` and `keywords`
26
+ // are populated by the chat indexer (#123) when present.
27
+ //
28
+ // `updatedAt` is the most recent activity timestamp — taken from the
29
+ // jsonl file's mtime on the server side and bumped whenever the
30
+ // client appends a message in-memory. Used for the "most recently
31
+ // touched" sort order in the session history sidebar (users expect
32
+ // active sessions to float to the top, not to stay pinned in
33
+ // creation order).
34
+ export interface SessionSummary {
35
+ id: string;
36
+ roleId: string;
37
+ startedAt: string;
38
+ updatedAt: string;
39
+ preview: string;
40
+ summary?: string;
41
+ keywords?: string[];
42
+ /** Where this session originated. Missing = "human" (backward compat). */
43
+ origin?: SessionOrigin;
44
+ // Live state from the server session store (present when the
45
+ // session has an active in-memory entry on the server).
46
+ isRunning?: boolean;
47
+ hasUnread?: boolean;
48
+ statusMessage?: string;
49
+ }
50
+
51
+ // One line of a session jsonl as returned by `/api/sessions/:id`.
52
+ // Generic envelope; concrete narrowed shapes below.
53
+ export interface SessionEntry {
54
+ type?: string;
55
+ source?: string;
56
+ roleId?: string;
57
+ message?: string;
58
+ result?: ToolResultComplete;
59
+ }
60
+
61
+ export interface TextEntry extends SessionEntry {
62
+ source: "user" | "assistant";
63
+ type: typeof EVENT_TYPES.text;
64
+ message: string;
65
+ }
66
+
67
+ export interface ToolResultEntry extends SessionEntry {
68
+ source: "tool";
69
+ type: typeof EVENT_TYPES.toolResult;
70
+ result: ToolResultComplete;
71
+ }
72
+
73
+ export const isTextEntry = (e: SessionEntry): e is TextEntry =>
74
+ (e.source === "user" || e.source === "assistant") && e.type === EVENT_TYPES.text && typeof e.message === "string";
75
+
76
+ export const isToolResultEntry = (e: SessionEntry): e is ToolResultEntry => e.source === "tool" && e.type === EVENT_TYPES.toolResult && e.result !== undefined;
77
+
78
+ // In-memory session held in `sessionMap`. PR #88 introduced this so
79
+ // multiple chats can run concurrently — `id` matches the `chatSessionId`
80
+ // the server uses for the on-disk jsonl.
81
+ export interface ActiveSession {
82
+ id: string;
83
+ roleId: string;
84
+ toolResults: ToolResultComplete[];
85
+ /** UUID → epoch ms. Recorded when each result is added to the
86
+ * session — either from a real-time pubsub event or from
87
+ * loading a saved session. For saved sessions, the session's
88
+ * `startedAt` is used as a baseline (individual per-entry
89
+ * timestamps aren't persisted in the JSONL yet). */
90
+ resultTimestamps: Map<string, number>;
91
+ isRunning: boolean;
92
+ statusMessage: string;
93
+ toolCallHistory: ToolCallHistoryItem[];
94
+ selectedResultUuid: string | null;
95
+ hasUnread: boolean;
96
+ startedAt: string;
97
+ // Bumped whenever the user sends a new message in this session.
98
+ // Used by `mergedSessions` to sort the sidebar history list by
99
+ // "most recently touched" rather than "created first".
100
+ updatedAt: string;
101
+ // Index into `toolResults` at which the current run's outputs begin.
102
+ // Rewritten on every user turn by `beginUserTurn`; consumed by
103
+ // `shouldSelectAssistantText` to decide whether a trailing text
104
+ // reply should become the selected canvas result. Lives on the
105
+ // session (not on the subscription closure) so updates on turn N+1
106
+ // are visible to the reused subscription callback.
107
+ runStartIndex: number;
108
+ /**
109
+ * In-flight background generations triggered by a plugin view (e.g.
110
+ * MulmoScript image/audio/movie renders). Keyed by
111
+ * `generationKey(kind, filePath, key)` (opaque identity, not parsed
112
+ * back); the value carries the decomposed (kind, filePath, key) so
113
+ * views read those fields directly. Empty map = no background work.
114
+ */
115
+ pendingGenerations: Record<string, PendingGeneration>;
116
+ }
@@ -0,0 +1,90 @@
1
+ // Server-sent events delivered by `POST /api/agent`. The frontend
2
+ // reads these off the SSE stream and dispatches into the active
3
+ // session's state.
4
+
5
+ import type { ToolResultComplete } from "gui-chat-protocol/vue";
6
+ import { EVENT_TYPES, type GenerationKind } from "./events";
7
+
8
+ export interface SseToolCall {
9
+ type: typeof EVENT_TYPES.toolCall;
10
+ toolUseId: string;
11
+ toolName: string;
12
+ args: unknown;
13
+ }
14
+
15
+ export interface SseToolCallResult {
16
+ type: typeof EVENT_TYPES.toolCallResult;
17
+ toolUseId: string;
18
+ content: string;
19
+ }
20
+
21
+ export interface SseStatus {
22
+ type: typeof EVENT_TYPES.status;
23
+ message: string;
24
+ }
25
+
26
+ export interface SseSwitchRole {
27
+ type: typeof EVENT_TYPES.switchRole;
28
+ roleId: string;
29
+ }
30
+
31
+ export interface SseText {
32
+ type: typeof EVENT_TYPES.text;
33
+ message: string;
34
+ source?: "user" | "assistant";
35
+ }
36
+
37
+ export interface SseToolResult {
38
+ type: typeof EVENT_TYPES.toolResult;
39
+ result: ToolResultComplete;
40
+ }
41
+
42
+ export interface SseRolesUpdated {
43
+ type: typeof EVENT_TYPES.rolesUpdated;
44
+ }
45
+
46
+ export interface SseError {
47
+ type: typeof EVENT_TYPES.error;
48
+ message: string;
49
+ }
50
+
51
+ /** Sent on the session channel when the agent run finishes. */
52
+ export interface SseSessionFinished {
53
+ type: typeof EVENT_TYPES.sessionFinished;
54
+ }
55
+
56
+ /**
57
+ * Plugin-initiated background work (e.g. MulmoScript image / audio /
58
+ * movie render) started. The client records this in
59
+ * `session.pendingGenerations` so the sidebar busy indicator stays
60
+ * lit even when the originating view isn't mounted.
61
+ */
62
+ export interface SseGenerationStarted {
63
+ type: typeof EVENT_TYPES.generationStarted;
64
+ kind: GenerationKind;
65
+ filePath: string;
66
+ key: string;
67
+ }
68
+
69
+ /** Companion event to `SseGenerationStarted` — the work completed
70
+ * (or failed; `error` populated). */
71
+ export interface SseGenerationFinished {
72
+ type: typeof EVENT_TYPES.generationFinished;
73
+ kind: GenerationKind;
74
+ filePath: string;
75
+ key: string;
76
+ error?: string;
77
+ }
78
+
79
+ export type SseEvent =
80
+ | SseToolCall
81
+ | SseToolCallResult
82
+ | SseStatus
83
+ | SseSwitchRole
84
+ | SseText
85
+ | SseToolResult
86
+ | SseRolesUpdated
87
+ | SseError
88
+ | SseSessionFinished
89
+ | SseGenerationStarted
90
+ | SseGenerationFinished;
@@ -0,0 +1,13 @@
1
+ // One row of the right-side tool-call history pane. Lifted out of
2
+ // `src/components/RightSidebar.vue` so non-component code (the
3
+ // session domain types, the pending-calls helper, etc.) can refer
4
+ // to it without depending on a Vue file.
5
+
6
+ export interface ToolCallHistoryItem {
7
+ toolUseId: string;
8
+ toolName: string;
9
+ args: unknown;
10
+ timestamp: number;
11
+ result?: string;
12
+ error?: string;
13
+ }
@@ -0,0 +1,74 @@
1
+ // Pure dispatcher: maps an SseEvent into mutations on an ActiveSession
2
+ // via the AgentEventContext adapter. No Vue refs, no component scope.
3
+
4
+ import type { ActiveSession } from "../../types/session";
5
+ import type { SseEvent } from "../../types/sse";
6
+ import { EVENT_TYPES, generationKey } from "../../types/events";
7
+ import { findPendingToolCall, toToolCallEntry } from "./toolCalls";
8
+ import { pushErrorMessage, applyTextEvent, applyToolResultToSession } from "../session/sessionHelpers";
9
+
10
+ export interface AgentEventContext {
11
+ session: ActiveSession;
12
+ setCurrentRoleId: (roleId: string) => void;
13
+ onRoleChange: () => void;
14
+ refreshRoles: () => Promise<void>;
15
+ scrollSidebarToBottom: () => void;
16
+ onGenerationsDrained: () => void;
17
+ }
18
+
19
+ export async function applyAgentEvent(event: SseEvent, ctx: AgentEventContext): Promise<void> {
20
+ const { session } = ctx;
21
+ switch (event.type) {
22
+ case EVENT_TYPES.toolCall:
23
+ session.toolCallHistory.push(toToolCallEntry(event));
24
+ ctx.scrollSidebarToBottom();
25
+ return;
26
+ case EVENT_TYPES.toolCallResult: {
27
+ const entry = findPendingToolCall(session.toolCallHistory, event.toolUseId);
28
+ if (entry) entry.result = event.content;
29
+ ctx.scrollSidebarToBottom();
30
+ return;
31
+ }
32
+ case EVENT_TYPES.status:
33
+ session.statusMessage = event.message;
34
+ return;
35
+ case EVENT_TYPES.switchRole:
36
+ setTimeout(() => {
37
+ ctx.setCurrentRoleId(event.roleId);
38
+ ctx.onRoleChange();
39
+ }, 0);
40
+ return;
41
+ case EVENT_TYPES.rolesUpdated:
42
+ await ctx.refreshRoles();
43
+ return;
44
+ case EVENT_TYPES.text:
45
+ applyTextEvent(session, event.message, event.source ?? "assistant");
46
+ return;
47
+ case EVENT_TYPES.toolResult:
48
+ applyToolResultToSession(session, event.result);
49
+ return;
50
+ case EVENT_TYPES.error:
51
+ console.error("[agent] error event:", event.message);
52
+ pushErrorMessage(session, event.message);
53
+ return;
54
+ case EVENT_TYPES.sessionFinished:
55
+ return;
56
+ case EVENT_TYPES.generationStarted: {
57
+ const mapKey = generationKey(event.kind, event.filePath, event.key);
58
+ session.pendingGenerations[mapKey] = {
59
+ kind: event.kind,
60
+ filePath: event.filePath,
61
+ key: event.key,
62
+ };
63
+ return;
64
+ }
65
+ case EVENT_TYPES.generationFinished: {
66
+ const mapKey = generationKey(event.kind, event.filePath, event.key);
67
+ delete session.pendingGenerations[mapKey];
68
+ if (Object.keys(session.pendingGenerations).length === 0) {
69
+ ctx.onGenerationsDrained();
70
+ }
71
+ return;
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,55 @@
1
+ // Request-body construction and dispatch for `POST /api/agent`.
2
+
3
+ import type { Role } from "../../config/roles";
4
+ import { API_ROUTES } from "../../config/apiRoutes";
5
+ import { apiFetchRaw } from "../api";
6
+
7
+ export interface AgentRequestBodyParams {
8
+ message: string;
9
+ role: Role;
10
+ chatSessionId: string;
11
+ selectedImageData?: string;
12
+ }
13
+
14
+ export interface AgentRequestBody {
15
+ message: string;
16
+ roleId: string;
17
+ chatSessionId: string;
18
+ selectedImageData: string | undefined;
19
+ }
20
+
21
+ export function buildAgentRequestBody(params: AgentRequestBodyParams): AgentRequestBody {
22
+ return {
23
+ message: params.message,
24
+ roleId: params.role.id,
25
+ chatSessionId: params.chatSessionId,
26
+ selectedImageData: params.selectedImageData,
27
+ };
28
+ }
29
+
30
+ /** POST the agent request body and return the response.
31
+ * On network or HTTP error, returns a descriptive error string
32
+ * instead. The caller decides how to surface it. */
33
+ export async function postAgentRun(body: AgentRequestBody): Promise<{ ok: true } | { ok: false; error: string }> {
34
+ try {
35
+ const response = await apiFetchRaw(API_ROUTES.agent.run, {
36
+ method: "POST",
37
+ body: JSON.stringify(body),
38
+ headers: { "Content-Type": "application/json" },
39
+ });
40
+ if (!response.ok) {
41
+ const errBody = await response.text().catch(() => "");
42
+ return {
43
+ ok: false,
44
+ error: `Server error ${response.status}: ${errBody.slice(0, 200)}`,
45
+ };
46
+ }
47
+ return { ok: true };
48
+ } catch (e) {
49
+ console.error("[agent] fetch error:", e);
50
+ return {
51
+ ok: false,
52
+ error: e instanceof Error ? e.message : "Connection error.",
53
+ };
54
+ }
55
+ }
@@ -0,0 +1,62 @@
1
+ // Pure helpers for the agent's tool-call history manipulation
2
+ // pulled out of `src/App.vue#sendMessage`. Each function is
3
+ // single-purpose, testable in isolation, and side-effect-free.
4
+ //
5
+ // Extracted as part of the cognitive-complexity refactor tracked
6
+ // in #175.
7
+
8
+ import type { ToolCallHistoryItem } from "../../types/toolCallHistory";
9
+ import type { SseToolCall } from "../../types/sse";
10
+ import type { ToolResultComplete } from "gui-chat-protocol/vue";
11
+
12
+ // Convert an SSE tool_call event into a ToolCallHistoryItem ready
13
+ // to push onto a session's toolCallHistory. Pure.
14
+ export function toToolCallEntry(event: SseToolCall): ToolCallHistoryItem {
15
+ return {
16
+ toolUseId: event.toolUseId,
17
+ toolName: event.toolName,
18
+ args: event.args,
19
+ timestamp: Date.now(),
20
+ };
21
+ }
22
+
23
+ // When an SSE `tool_call_result` event arrives, the server tells
24
+ // us which tool call it belongs to via `toolUseId`. Find the most
25
+ // recent matching history entry that's still **pending** (no
26
+ // result, no error) and return it so the caller can attach the
27
+ // payload.
28
+ //
29
+ // Newest-first: scanning in reverse is intentional — two calls to
30
+ // the same tool within one run would otherwise attach the new
31
+ // result to the earlier entry. Reverse scan always picks the
32
+ // freshest pending entry, matching the server's LIFO ordering.
33
+ //
34
+ // Returns `undefined` when no pending call matches (race / retry /
35
+ // late-arriving event). Pure.
36
+ export function findPendingToolCall(history: readonly ToolCallHistoryItem[], toolUseId: string): ToolCallHistoryItem | undefined {
37
+ for (let i = history.length - 1; i >= 0; i--) {
38
+ const entry = history[i];
39
+ if (entry.toolUseId === toolUseId && entry.result === undefined && entry.error === undefined) {
40
+ return entry;
41
+ }
42
+ }
43
+ return undefined;
44
+ }
45
+
46
+ // Decide whether a newly-arrived assistant text message should
47
+ // become the selected canvas result. Rule: yes, iff no plugin
48
+ // tool result has landed during this run. A plugin result — e.g.
49
+ // an image, a todo list update — is visually richer than a bare
50
+ // text response and should stay selected once emitted.
51
+ //
52
+ // `runStartIndex` is the index into `toolResults` at which the
53
+ // current run's outputs begin. Results before that index belong
54
+ // to previous turns and don't count.
55
+ //
56
+ // Pure — returns a boolean for the caller to act on.
57
+ export function shouldSelectAssistantText(toolResults: readonly ToolResultComplete[], runStartIndex: number): boolean {
58
+ for (let i = runStartIndex; i < toolResults.length; i++) {
59
+ if (toolResults[i].toolName !== "text-response") return false;
60
+ }
61
+ return true;
62
+ }