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,46 @@
1
+ // Debug trigger endpoint for the chat indexer. The normal path is
2
+ // the agent `finally` hook in server/routes/agent.ts — one session
3
+ // at a time, with a 15-minute freshness throttle. This endpoint
4
+ // exists so the user can force-rebuild every session's summary on
5
+ // demand without restarting the server, which is useful for
6
+ // testing the feature against an existing workspace full of
7
+ // never-indexed sessions.
8
+ //
9
+ // Usage:
10
+ // curl -X POST http://localhost:3000/api/chat-index/rebuild
11
+
12
+ import { Router, Request, Response } from "express";
13
+ import { backfillAllSessions } from "../../workspace/chat-index/index.js";
14
+ import { log } from "../../system/logger/index.js";
15
+ import { serverError } from "../../utils/httpError.js";
16
+ import { API_ROUTES } from "../../../src/config/apiRoutes.js";
17
+
18
+ interface RebuildResponse {
19
+ total: number;
20
+ indexed: number;
21
+ skipped: number;
22
+ }
23
+
24
+ interface RebuildErrorResponse {
25
+ error: string;
26
+ }
27
+
28
+ const router = Router();
29
+
30
+ router.post(API_ROUTES.chatIndex.rebuild, async (_req: Request, res: Response<RebuildResponse | RebuildErrorResponse>) => {
31
+ try {
32
+ log.info("chat-index", "manual rebuild triggered");
33
+ const result = await backfillAllSessions();
34
+ log.info("chat-index", "rebuild complete", {
35
+ indexed: result.indexed,
36
+ total: result.total,
37
+ skipped: result.skipped,
38
+ });
39
+ res.json(result);
40
+ } catch (err) {
41
+ log.warn("chat-index", "rebuild failed", { error: String(err) });
42
+ serverError(res, err instanceof Error ? err.message : "unknown error");
43
+ }
44
+ });
45
+
46
+ export default router;
@@ -0,0 +1,258 @@
1
+ import { Router, type Request, type Response } from "express";
2
+ import {
3
+ fromMcpEntries,
4
+ isAppSettings,
5
+ loadMcpConfig,
6
+ loadSettings,
7
+ saveMcpConfig,
8
+ saveSettings,
9
+ toMcpEntries,
10
+ type AppSettings,
11
+ type McpConfigFile,
12
+ type McpServerEntry,
13
+ } from "../../system/config.js";
14
+ import { badRequest, serverError } from "../../utils/httpError.js";
15
+ import { isRecord } from "../../utils/types.js";
16
+ import { API_ROUTES } from "../../../src/config/apiRoutes.js";
17
+ import { loadCustomDirs, saveCustomDirs, ensureCustomDirs, validateCustomDirs, type CustomDirEntry } from "../../workspace/custom-dirs.js";
18
+ import { loadReferenceDirs, saveReferenceDirs, validateReferenceDirs, type ReferenceDirEntry } from "../../workspace/reference-dirs.js";
19
+
20
+ // Public surface of /api/config. GET returns the full config tree so
21
+ // the client can render every section in one request. PUT surfaces are
22
+ // per-section to keep payloads small and validation obvious.
23
+ export interface ConfigResponse {
24
+ settings: AppSettings;
25
+ mcp: { servers: McpServerEntry[] };
26
+ }
27
+
28
+ export interface ConfigErrorResponse {
29
+ error: string;
30
+ }
31
+
32
+ type ConfigRes = Response<ConfigResponse | ConfigErrorResponse>;
33
+
34
+ function buildFullResponse(): ConfigResponse {
35
+ return {
36
+ settings: loadSettings(),
37
+ mcp: { servers: toMcpEntries(loadMcpConfig()) },
38
+ };
39
+ }
40
+
41
+ function isMcpPutBody(value: unknown): value is { servers: McpServerEntry[] } {
42
+ if (!isRecord(value)) return false;
43
+ if (!Array.isArray(value.servers)) return false;
44
+ // Full shape validation happens inside fromMcpEntries (throws on
45
+ // anything malformed). Here we just confirm the envelope.
46
+ return value.servers.every((e) => isRecord(e) && "id" in e && "spec" in e);
47
+ }
48
+
49
+ // Parse an MCP payload through `fromMcpEntries` (which does the full
50
+ // shape validation and throws on anything malformed). On failure,
51
+ // respond 400 and return null so the caller can early-return.
52
+ function parseMcpPayloadOrFail(res: ConfigRes, servers: McpServerEntry[]): McpConfigFile | null {
53
+ try {
54
+ return fromMcpEntries(servers);
55
+ } catch (err) {
56
+ badRequest(res, err instanceof Error ? err.message : "invalid mcp entries");
57
+ return null;
58
+ }
59
+ }
60
+
61
+ // Run a filesystem save. On failure, respond 500 with the error's
62
+ // message and return false so the caller can early-return. Returns
63
+ // true on success.
64
+ function runSaveOrFail(res: ConfigRes, save: () => void, fallback: string): boolean {
65
+ try {
66
+ save();
67
+ return true;
68
+ } catch (err) {
69
+ serverError(res, err instanceof Error ? err.message : fallback);
70
+ return false;
71
+ }
72
+ }
73
+
74
+ const router = Router();
75
+
76
+ router.get(API_ROUTES.config.base, (_req: Request, res: Response<ConfigResponse>) => {
77
+ res.json(buildFullResponse());
78
+ });
79
+
80
+ // Atomic save for both settings and MCP. Validates both payloads first
81
+ // (no writes happen until every input is known-good), then writes
82
+ // settings and captures the previous state so a subsequent saveMcpConfig
83
+ // failure can roll back. This is the endpoint the Settings modal should
84
+ // use; the per-section PUTs below remain for targeted updates.
85
+ interface PutConfigBody {
86
+ settings: AppSettings;
87
+ mcp: { servers: McpServerEntry[] };
88
+ }
89
+
90
+ function isPutConfigBody(value: unknown): value is PutConfigBody {
91
+ if (!isRecord(value)) return false;
92
+ return isAppSettings(value.settings) && isMcpPutBody(value.mcp);
93
+ }
94
+
95
+ router.put(API_ROUTES.config.base, (req: Request<unknown, unknown, PutConfigBody>, res: ConfigRes) => {
96
+ const body = req.body;
97
+ if (!isPutConfigBody(body)) {
98
+ badRequest(res, "Invalid config payload");
99
+ return;
100
+ }
101
+ const mcpCfg = parseMcpPayloadOrFail(res, body.mcp.servers);
102
+ if (!mcpCfg) return;
103
+
104
+ // Snapshot previous settings so we can roll back if the second
105
+ // write fails — a cross-file atomic write isn't possible, but
106
+ // rollback keeps the pair consistent from the user's perspective.
107
+ const previousSettings = loadSettings();
108
+ if (!runSaveOrFail(res, () => saveSettings(body.settings), "saveSettings failed")) {
109
+ return;
110
+ }
111
+ if (!runSaveOrFail(res, () => saveMcpConfig(mcpCfg), "saveMcpConfig failed")) {
112
+ // Best-effort rollback; if it fails too, the original mcp error
113
+ // is already on the wire.
114
+ try {
115
+ saveSettings(previousSettings);
116
+ } catch {
117
+ /* swallow — original error already sent */
118
+ }
119
+ return;
120
+ }
121
+ res.json(buildFullResponse());
122
+ });
123
+
124
+ router.put(API_ROUTES.config.settings, (req: Request<unknown, unknown, AppSettings>, res: ConfigRes) => {
125
+ const body = req.body;
126
+ if (!isAppSettings(body)) {
127
+ badRequest(res, "Invalid AppSettings payload");
128
+ return;
129
+ }
130
+ if (!runSaveOrFail(res, () => saveSettings(body), "saveSettings failed")) {
131
+ return;
132
+ }
133
+ res.json(buildFullResponse());
134
+ });
135
+
136
+ router.put(API_ROUTES.config.mcp, (req: Request<unknown, unknown, { servers: McpServerEntry[] }>, res: ConfigRes) => {
137
+ const body = req.body;
138
+ if (!isMcpPutBody(body)) {
139
+ badRequest(res, "Invalid mcp payload envelope");
140
+ return;
141
+ }
142
+ // fromMcpEntries rejects malformed client input (400). saveMcpConfig
143
+ // can fail for server-side reasons like disk/permission errors (500).
144
+ const cfg = parseMcpPayloadOrFail(res, body.servers);
145
+ if (!cfg) return;
146
+ if (!runSaveOrFail(res, () => saveMcpConfig(cfg), "saveMcpConfig failed")) {
147
+ return;
148
+ }
149
+ res.json(buildFullResponse());
150
+ });
151
+
152
+ // ── Workspace custom directories (#239) ──────────────────────────
153
+
154
+ router.get(API_ROUTES.config.workspaceDirs, (_req: Request, res: Response<{ dirs: CustomDirEntry[] }>) => {
155
+ res.json({ dirs: loadCustomDirs() });
156
+ });
157
+
158
+ router.put(
159
+ API_ROUTES.config.workspaceDirs,
160
+ (req: Request<unknown, unknown, { dirs: unknown }>, res: Response<{ dirs: CustomDirEntry[] } | ConfigErrorResponse>) => {
161
+ const body = req.body;
162
+ if (!isRecord(body) || !("dirs" in body)) {
163
+ badRequest(res, "expected { dirs: [...] }");
164
+ return;
165
+ }
166
+ const result = validateCustomDirs(body.dirs);
167
+ if ("error" in result) {
168
+ badRequest(res, result.error);
169
+ return;
170
+ }
171
+ try {
172
+ saveCustomDirs(result.entries);
173
+ ensureCustomDirs(result.entries);
174
+ res.json({ dirs: result.entries });
175
+ } catch (err) {
176
+ serverError(res, err instanceof Error ? err.message : "save failed");
177
+ }
178
+ },
179
+ );
180
+
181
+ // ── Reference directories (#455) ────────────────────────────────
182
+
183
+ router.get(API_ROUTES.config.referenceDirs, (_req: Request, res: Response<{ dirs: ReferenceDirEntry[] }>) => {
184
+ res.json({ dirs: loadReferenceDirs() });
185
+ });
186
+
187
+ router.put(
188
+ API_ROUTES.config.referenceDirs,
189
+ (req: Request<unknown, unknown, { dirs: unknown }>, res: Response<{ dirs: ReferenceDirEntry[] } | ConfigErrorResponse>) => {
190
+ const body = req.body;
191
+ if (!isRecord(body) || !("dirs" in body)) {
192
+ badRequest(res, "expected { dirs: [...] }");
193
+ return;
194
+ }
195
+ const result = validateReferenceDirs(body.dirs);
196
+ if ("error" in result) {
197
+ badRequest(res, result.error);
198
+ return;
199
+ }
200
+ try {
201
+ saveReferenceDirs(result.entries);
202
+ res.json({ dirs: result.entries });
203
+ } catch (err) {
204
+ serverError(res, err instanceof Error ? err.message : "save failed");
205
+ }
206
+ },
207
+ );
208
+
209
+ // ── Scheduler overrides (#493) ──────────────────────────────────
210
+
211
+ import { loadSchedulerOverrides, saveSchedulerOverrides, UTC_HH_MM_RE, type ScheduleOverrides } from "../../utils/files/scheduler-overrides-io.js";
212
+ import { applyScheduleOverride } from "../../events/scheduler-adapter.js";
213
+ import { SCHEDULE_TYPES } from "@receptron/task-scheduler";
214
+
215
+ router.get(API_ROUTES.config.schedulerOverrides, (_req: Request, res: Response<{ overrides: ScheduleOverrides }>) => {
216
+ res.json({ overrides: loadSchedulerOverrides() });
217
+ });
218
+
219
+ router.put(
220
+ API_ROUTES.config.schedulerOverrides,
221
+ async (req: Request<unknown, unknown, { overrides: unknown }>, res: Response<{ overrides: ScheduleOverrides } | ConfigErrorResponse>) => {
222
+ const body = req.body;
223
+ if (!isRecord(body) || !("overrides" in body)) {
224
+ badRequest(res, "expected { overrides: { ... } }");
225
+ return;
226
+ }
227
+ const raw = body.overrides;
228
+ if (!isRecord(raw)) {
229
+ badRequest(res, "overrides must be an object");
230
+ return;
231
+ }
232
+ const overrides = raw as ScheduleOverrides;
233
+ try {
234
+ saveSchedulerOverrides(overrides);
235
+
236
+ // Apply to running task-manager immediately
237
+ for (const [taskId, ovr] of Object.entries(overrides)) {
238
+ if (typeof ovr.intervalMs === "number" && ovr.intervalMs > 0) {
239
+ await applyScheduleOverride(taskId, {
240
+ type: SCHEDULE_TYPES.interval,
241
+ intervalMs: ovr.intervalMs,
242
+ });
243
+ } else if (typeof ovr.time === "string" && UTC_HH_MM_RE.test(ovr.time)) {
244
+ await applyScheduleOverride(taskId, {
245
+ type: SCHEDULE_TYPES.daily,
246
+ time: ovr.time,
247
+ });
248
+ }
249
+ }
250
+
251
+ res.json({ overrides: loadSchedulerOverrides() });
252
+ } catch (err) {
253
+ serverError(res, err instanceof Error ? err.message : "save failed");
254
+ }
255
+ },
256
+ );
257
+
258
+ export default router;
@@ -0,0 +1,79 @@
1
+ // Shared HTTP response plumbing for dispatcher-style POST routes
2
+ // (currently todos and scheduler). Both routes follow the same
3
+ // pattern: load items, run a pure dispatch function that returns a
4
+ // discriminated `{ kind: "error" | "success" }` result, persist on
5
+ // success when applicable, and translate to JSON. This module owns
6
+ // the translation step so each route handler stays a few lines.
7
+
8
+ import type { Response } from "express";
9
+ import { errorMessage } from "../../utils/errors.js";
10
+ import { sendError, serverError } from "../../utils/httpError.js";
11
+
12
+ export type DispatchResult<T> =
13
+ | { kind: "error"; status: number; error: string }
14
+ | {
15
+ kind: "success";
16
+ items: T[];
17
+ message: string;
18
+ jsonData: Record<string, unknown>;
19
+ };
20
+
21
+ export interface DispatchSuccessResponse<T> {
22
+ data: { items: T[] };
23
+ message: string;
24
+ jsonData: Record<string, unknown>;
25
+ instructions: string;
26
+ updating: boolean;
27
+ }
28
+
29
+ export interface DispatchErrorResponse {
30
+ error: string;
31
+ }
32
+
33
+ export interface RespondOptions<T> {
34
+ // Whether to call the persist callback before responding. Different
35
+ // routes have different read-only action rules (e.g. todos has a
36
+ // READ_ONLY_ACTIONS set, scheduler exempts only "show"), so the
37
+ // caller decides per-request.
38
+ shouldPersist: boolean;
39
+ // Per-route instructions string baked into the response.
40
+ instructions: string;
41
+ // Persistence callback. Called with the post-dispatch items only
42
+ // when shouldPersist is true.
43
+ persist: (items: T[]) => void;
44
+ }
45
+
46
+ // Translate a DispatchResult into the JSON response shape used by
47
+ // dispatcher-style routes. Side-effects: calls `options.persist` on
48
+ // success when `options.shouldPersist` is true; writes the response.
49
+ //
50
+ // Persistence failures are caught and translated into a structured
51
+ // 500 JSON error so the route's response contract stays consistent —
52
+ // otherwise an fs.writeFileSync throw would bubble out and trigger
53
+ // Express's default HTML error page instead of the JSON shape that
54
+ // clients expect.
55
+ export function respondWithDispatchResult<T>(
56
+ res: Response<DispatchSuccessResponse<T> | DispatchErrorResponse>,
57
+ result: DispatchResult<T>,
58
+ options: RespondOptions<T>,
59
+ ): void {
60
+ if (result.kind === "error") {
61
+ sendError(res, result.status, result.error);
62
+ return;
63
+ }
64
+ if (options.shouldPersist) {
65
+ try {
66
+ options.persist(result.items);
67
+ } catch (err) {
68
+ serverError(res, `Failed to persist changes: ${errorMessage(err)}`);
69
+ return;
70
+ }
71
+ }
72
+ res.json({
73
+ data: { items: result.items },
74
+ message: result.message,
75
+ jsonData: result.jsonData,
76
+ instructions: options.instructions,
77
+ updating: true,
78
+ });
79
+ }