mulmoclaude 0.5.2 → 0.6.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 (486) hide show
  1. package/Dockerfile.sandbox +100 -0
  2. package/README.md +17 -4
  3. package/bin/mulmoclaude.js +46 -15
  4. package/bin/prepare-dist.js +18 -2
  5. package/client/assets/chunk-CernVdwh.js +1 -0
  6. package/client/assets/chunk-D8eiyYIV-C1eAZMzz.js +1 -0
  7. package/client/assets/html2canvas-CDGcmOD3-BbPeutDg.js +5 -0
  8. package/client/assets/index-BbgSjFQ8.js +4968 -0
  9. package/client/assets/index-ECD0lgIv.css +2 -0
  10. package/client/assets/{index.es-D4YyL_Dg-BgT6a3Nd.js → index.es-DqtpmBm8-DJdTPdnc.js} +5 -5
  11. package/client/assets/material-symbols-outlined-BLDfUw-_.woff2 +0 -0
  12. package/client/assets/runtime-protocol-vue-6WYa8hAs.js +1 -0
  13. package/client/assets/runtime-vue-BVUzgYGA.js +1 -0
  14. package/client/assets/typeof-DBp4T-Ny-C2xoZtcz.js +1 -0
  15. package/client/assets/vue-1e_vz2LW.js +1 -0
  16. package/client/assets/vue.runtime.esm-bundler-DQ8Kjjui.js +4 -0
  17. package/client/index.html +33 -2
  18. package/package.json +20 -18
  19. package/sandbox-entrypoint.sh +106 -0
  20. package/server/accounting/accountNormalize.ts +32 -0
  21. package/server/accounting/defaultAccounts.ts +87 -0
  22. package/server/accounting/eventPublisher.ts +51 -0
  23. package/server/accounting/journal.ts +252 -0
  24. package/server/accounting/openingBalances.ts +114 -0
  25. package/server/accounting/report.ts +237 -0
  26. package/server/accounting/service.ts +718 -0
  27. package/server/accounting/snapshotCache.ts +333 -0
  28. package/server/accounting/timeSeries.ts +265 -0
  29. package/server/accounting/types.ts +148 -0
  30. package/server/agent/activeTools.ts +128 -0
  31. package/server/agent/attachmentConverter.ts +10 -5
  32. package/server/agent/backend/claude-code.ts +8 -2
  33. package/server/agent/backend/types.ts +1 -1
  34. package/server/agent/config.ts +101 -31
  35. package/server/agent/index.ts +45 -33
  36. package/server/agent/mcp-server.ts +146 -69
  37. package/server/agent/mcp-tools/index.ts +1 -5
  38. package/server/agent/mcp-tools/notify.ts +2 -22
  39. package/server/agent/mcp-tools/x.ts +0 -4
  40. package/server/agent/mcpHealth.ts +168 -0
  41. package/server/agent/plugin-names.ts +20 -77
  42. package/server/agent/prompt.ts +259 -51
  43. package/server/agent/resumeFailover.ts +1 -1
  44. package/server/agent/stream.ts +0 -1
  45. package/server/api/auth/bearerAuth.ts +5 -5
  46. package/server/api/csrfGuard.ts +1 -1
  47. package/server/api/routes/accounting.ts +366 -0
  48. package/server/api/routes/agent.ts +509 -46
  49. package/server/api/routes/attachment.ts +104 -0
  50. package/server/api/routes/chart.ts +2 -1
  51. package/server/api/routes/config.ts +12 -12
  52. package/server/api/routes/files.ts +105 -48
  53. package/server/api/routes/image.ts +70 -25
  54. package/server/api/routes/journal.ts +35 -0
  55. package/server/api/routes/mulmo-script.ts +358 -118
  56. package/server/api/routes/mulmoScriptValidate.ts +1 -1
  57. package/server/api/routes/news.ts +1 -1
  58. package/server/api/routes/notifications.ts +92 -22
  59. package/server/api/routes/notifier.ts +98 -0
  60. package/server/api/routes/pdf.ts +188 -48
  61. package/server/api/routes/plugins.ts +34 -14
  62. package/server/api/routes/presentHtml.ts +58 -3
  63. package/server/api/routes/roles.ts +1 -8
  64. package/server/api/routes/runtime-plugin.ts +224 -0
  65. package/server/api/routes/scheduler.ts +7 -5
  66. package/server/api/routes/schedulerHandlers.ts +1 -1
  67. package/server/api/routes/schedulerTasks.ts +8 -7
  68. package/server/api/routes/sessions.ts +234 -121
  69. package/server/api/routes/skills.ts +56 -51
  70. package/server/api/routes/sources.ts +52 -45
  71. package/server/api/routes/translation.ts +44 -0
  72. package/server/api/routes/wiki/frontmatter.ts +13 -65
  73. package/server/api/routes/wiki/history.ts +261 -0
  74. package/server/api/routes/wiki/pageIndex.ts +1 -1
  75. package/server/api/routes/wiki.ts +50 -26
  76. package/server/events/file-change.ts +83 -0
  77. package/server/events/notifications.ts +247 -91
  78. package/server/events/pub-sub/index.ts +1 -1
  79. package/server/events/relay-client.ts +5 -5
  80. package/server/events/scheduler-adapter.ts +2 -2
  81. package/server/events/session-store/index.ts +110 -22
  82. package/server/events/task-manager/index.ts +10 -9
  83. package/server/index.ts +509 -33
  84. package/server/notifier/engine.ts +419 -0
  85. package/server/notifier/legacy-adapters.ts +76 -0
  86. package/server/notifier/runtime-api.ts +74 -0
  87. package/server/notifier/store.ts +70 -0
  88. package/server/notifier/types.ts +121 -0
  89. package/server/plugins/dev-loader.ts +171 -0
  90. package/server/plugins/dev-watcher.ts +150 -0
  91. package/server/plugins/diagnostics.ts +188 -0
  92. package/server/plugins/preset-list.ts +52 -0
  93. package/server/plugins/preset-loader.ts +112 -0
  94. package/server/plugins/runtime-chat-api.ts +38 -0
  95. package/server/plugins/runtime-loader.ts +430 -0
  96. package/server/plugins/runtime-registry.ts +112 -0
  97. package/server/plugins/runtime-tasks-api.ts +50 -0
  98. package/server/plugins/runtime.ts +378 -0
  99. package/server/services/translation/cache.ts +72 -0
  100. package/server/services/translation/index.ts +106 -0
  101. package/server/services/translation/llm.ts +140 -0
  102. package/server/services/translation/types.ts +35 -0
  103. package/server/system/credentials.ts +13 -2
  104. package/server/system/env.ts +6 -1
  105. package/server/system/logger/formatters.ts +46 -4
  106. package/server/system/logger/index.ts +4 -4
  107. package/server/system/logger/sinks.ts +26 -5
  108. package/server/system/logger/types.ts +2 -2
  109. package/server/utils/dev-plugin-args.d.mts +11 -0
  110. package/server/utils/dev-plugin-args.mjs +43 -0
  111. package/server/utils/errors.ts +13 -4
  112. package/server/utils/files/accounting-io.ts +295 -0
  113. package/server/utils/files/atomic.ts +17 -49
  114. package/server/utils/files/attachment-store.ts +182 -0
  115. package/server/utils/files/html-io.ts +1 -7
  116. package/server/utils/files/html-store.ts +19 -0
  117. package/server/utils/files/image-store.ts +20 -22
  118. package/server/utils/files/index.ts +5 -15
  119. package/server/utils/files/journal-io.ts +7 -35
  120. package/server/utils/files/json.ts +2 -29
  121. package/server/utils/files/markdown-image-fill.ts +6 -37
  122. package/server/utils/files/markdown-store.ts +6 -21
  123. package/server/utils/files/naming.ts +3 -39
  124. package/server/utils/files/plugins-io.ts +100 -0
  125. package/server/utils/files/reference-dirs-io.ts +1 -9
  126. package/server/utils/files/roles-io.ts +2 -10
  127. package/server/utils/files/safe.ts +17 -19
  128. package/server/utils/files/scheduler-io.ts +1 -7
  129. package/server/utils/files/scheduler-overrides-io.ts +3 -12
  130. package/server/utils/files/session-io.ts +21 -30
  131. package/server/utils/files/spreadsheet-store.ts +9 -22
  132. package/server/utils/files/translation-io.ts +46 -0
  133. package/server/utils/files/user-tasks-io.ts +1 -7
  134. package/server/utils/files/workspace-io.ts +3 -79
  135. package/server/utils/gemini.ts +33 -11
  136. package/server/utils/html/htmlArtifactSplicer.ts +41 -0
  137. package/server/utils/markdown/frontmatter.ts +112 -0
  138. package/server/utils/regex.ts +56 -0
  139. package/server/utils/router.ts +41 -0
  140. package/server/utils/slug.ts +5 -3
  141. package/server/utils/time.ts +12 -0
  142. package/server/workspace/chat-index/indexer.ts +15 -2
  143. package/server/workspace/chat-index/summarizer.ts +1 -1
  144. package/server/workspace/custom-dirs.ts +1 -1
  145. package/server/workspace/helps/gemini.md +1 -1
  146. package/server/workspace/helps/guide.md +61 -0
  147. package/server/workspace/helps/index.md +4 -0
  148. package/server/workspace/helps/presenthtml.md +80 -0
  149. package/server/workspace/helps/sandbox.md +7 -0
  150. package/server/workspace/helps/storyteller.md +101 -0
  151. package/server/workspace/helps/telegram.md +1 -0
  152. package/server/workspace/helps/wiki.md +9 -7
  153. package/server/workspace/journal/archivist-cli.ts +7 -33
  154. package/server/workspace/journal/archivist-schemas.ts +5 -43
  155. package/server/workspace/journal/dailyPass.ts +34 -187
  156. package/server/workspace/journal/diff.ts +3 -28
  157. package/server/workspace/journal/index.ts +10 -81
  158. package/server/workspace/journal/indexFile.ts +3 -24
  159. package/server/workspace/journal/latestDaily.ts +51 -0
  160. package/server/workspace/journal/memoryExtractor.ts +4 -20
  161. package/server/workspace/journal/optimizationPass.ts +4 -21
  162. package/server/workspace/journal/paths.ts +4 -23
  163. package/server/workspace/journal/state.ts +6 -29
  164. package/server/workspace/memory/io.ts +213 -0
  165. package/server/workspace/memory/llm-classifier.ts +158 -0
  166. package/server/workspace/memory/migrate.ts +263 -0
  167. package/server/workspace/memory/run.ts +84 -0
  168. package/server/workspace/memory/topic-cluster.ts +218 -0
  169. package/server/workspace/memory/topic-detect.ts +67 -0
  170. package/server/workspace/memory/topic-index-hook.ts +128 -0
  171. package/server/workspace/memory/topic-io.ts +180 -0
  172. package/server/workspace/memory/topic-migrate.ts +248 -0
  173. package/server/workspace/memory/topic-run.ts +172 -0
  174. package/server/workspace/memory/topic-swap.ts +135 -0
  175. package/server/workspace/memory/topic-types.ts +142 -0
  176. package/server/workspace/memory/types.ts +83 -0
  177. package/server/workspace/news/reader.ts +4 -5
  178. package/server/workspace/paths.ts +124 -47
  179. package/server/workspace/roles.ts +2 -11
  180. package/server/workspace/skills/parser.ts +38 -55
  181. package/server/workspace/skills/user-tasks.ts +1 -2
  182. package/server/workspace/skills-preset/mc-library/SKILL.md +188 -0
  183. package/server/workspace/skills-preset.ts +196 -0
  184. package/server/workspace/sources/fetchers/githubIssues.ts +13 -11
  185. package/server/workspace/sources/fetchers/index.ts +1 -1
  186. package/server/workspace/sources/fetchers/rssParser.ts +1 -1
  187. package/server/workspace/sources/pipeline/index.ts +2 -2
  188. package/server/workspace/sources/pipeline/notify.ts +3 -3
  189. package/server/workspace/sources/pipeline/write.ts +2 -2
  190. package/server/workspace/sources/registry.ts +39 -61
  191. package/server/workspace/sources/robots.ts +1 -1
  192. package/server/workspace/tool-trace/classify.ts +2 -1
  193. package/server/workspace/tool-trace/index.ts +1 -1
  194. package/server/workspace/tool-trace/writeSearch.ts +6 -1
  195. package/server/workspace/wiki-backlinks/index.ts +19 -7
  196. package/server/workspace/wiki-backlinks/sessionBacklinks.ts +1 -0
  197. package/server/workspace/wiki-history/hook/snapshot.mjs +98 -0
  198. package/server/workspace/wiki-history/hook/snapshot.ts +135 -0
  199. package/server/workspace/wiki-history/provision.ts +181 -0
  200. package/server/workspace/wiki-pages/io.ts +217 -0
  201. package/server/workspace/wiki-pages/snapshot.ts +380 -0
  202. package/server/workspace/workspace.ts +75 -13
  203. package/src/App.vue +115 -40
  204. package/src/_runtime/protocol-vue.ts +21 -0
  205. package/src/_runtime/vue.ts +22 -0
  206. package/src/components/ChatInput.vue +14 -10
  207. package/src/components/CopyChatButton.vue +76 -0
  208. package/src/components/FileContentRenderer.vue +67 -14
  209. package/src/components/FileTree.vue +2 -2
  210. package/src/components/FilesView.vue +17 -1
  211. package/src/components/NewsView.vue +16 -2
  212. package/src/components/NotificationBell.vue +320 -93
  213. package/src/components/PageChatComposer.vue +5 -4
  214. package/src/components/PluginLauncher.vue +42 -6
  215. package/src/components/PluginScopedRoot.vue +87 -0
  216. package/src/components/RoleSelector.vue +12 -1
  217. package/src/components/RolesView.vue +562 -0
  218. package/src/components/SentAttachmentChip.vue +102 -0
  219. package/src/components/SessionHistoryPanel.vue +109 -20
  220. package/src/components/SessionRoleIcon.vue +7 -4
  221. package/src/components/SessionSidebar.vue +20 -7
  222. package/src/components/SessionTabBar.vue +1 -1
  223. package/src/components/SettingsMcpTab.vue +4 -4
  224. package/src/components/SettingsModal.vue +2 -0
  225. package/src/components/SidebarHeader.vue +16 -5
  226. package/src/components/SourcesManager.vue +23 -9
  227. package/src/components/SourcesView.vue +1 -1
  228. package/src/components/StackView.vue +102 -6
  229. package/src/components/SuggestionsPanel.vue +105 -16
  230. package/src/components/SystemFileBanner.vue +1 -1
  231. package/src/components/TodoExplorer.vue +4 -5
  232. package/src/components/todo/TodoAddDialog.vue +2 -3
  233. package/src/components/todo/TodoEditDialog.vue +1 -2
  234. package/src/components/todo/TodoEditPanel.vue +2 -3
  235. package/src/components/todo/TodoKanbanView.vue +8 -5
  236. package/src/components/todo/TodoListView.vue +3 -5
  237. package/src/components/todo/TodoTableView.vue +7 -5
  238. package/src/composables/useAccountingChannel.ts +58 -0
  239. package/src/composables/useActiveSession.ts +4 -25
  240. package/src/composables/useAppApi.ts +6 -44
  241. package/src/composables/useClipboardCopy.ts +3 -20
  242. package/src/composables/useContentDisplay.ts +33 -2
  243. package/src/composables/useDevPluginReload.ts +23 -0
  244. package/src/composables/useDynamicFavicon.ts +5 -31
  245. package/src/composables/useEventListeners.ts +0 -20
  246. package/src/composables/useExpandedDirs.ts +4 -15
  247. package/src/composables/useFaviconState.ts +12 -46
  248. package/src/composables/useFileChange.ts +53 -0
  249. package/src/composables/useFreshPluginData.ts +6 -43
  250. package/src/composables/useHealth.ts +14 -43
  251. package/src/composables/useImageErrorRepair.ts +104 -0
  252. package/src/composables/useLatestDaily.ts +40 -0
  253. package/src/composables/useMarkdownDoc.ts +39 -0
  254. package/src/composables/useMarkdownLinkHandler.ts +1 -1
  255. package/src/composables/useMcpTools.ts +3 -16
  256. package/src/composables/useNotifications.ts +138 -112
  257. package/src/composables/usePdfDownload.ts +17 -3
  258. package/src/composables/usePendingCalls.ts +8 -26
  259. package/src/composables/usePluginErrorBoundary.ts +68 -0
  260. package/src/composables/usePubSub.ts +9 -17
  261. package/src/composables/useRunElapsed.ts +5 -22
  262. package/src/composables/useSandboxStatus.ts +4 -20
  263. package/src/composables/useSessionDerived.ts +7 -15
  264. package/src/composables/useSessionHistory.ts +70 -29
  265. package/src/composables/useSessionSync.ts +25 -3
  266. package/src/composables/useSkillsList.ts +59 -0
  267. package/src/composables/useTranslatedQueries.ts +109 -0
  268. package/src/config/apiRoutes.ts +181 -80
  269. package/src/config/historyFilters.ts +5 -3
  270. package/src/config/hostEvents.ts +17 -0
  271. package/src/config/mcpCatalog.ts +277 -5
  272. package/src/config/pubsubChannels.ts +134 -12
  273. package/src/config/roles.ts +212 -147
  274. package/src/config/systemFileDescriptors.ts +5 -5
  275. package/src/config/toolNames.ts +52 -30
  276. package/src/config/workspacePaths.ts +26 -2
  277. package/src/lang/de.ts +483 -27
  278. package/src/lang/en.ts +448 -27
  279. package/src/lang/es.ts +474 -27
  280. package/src/lang/fr.ts +476 -27
  281. package/src/lang/ja.ts +465 -27
  282. package/src/lang/ko.ts +466 -27
  283. package/src/lang/pt-BR.ts +473 -27
  284. package/src/lang/zh.ts +463 -27
  285. package/src/lib/vue-i18n.ts +1 -1
  286. package/src/lib/wiki-page/slug.ts +66 -0
  287. package/src/main.ts +85 -0
  288. package/src/plugins/_extras.ts +58 -0
  289. package/src/plugins/_generated/metas.ts +42 -0
  290. package/src/plugins/_generated/registrations.ts +44 -0
  291. package/src/plugins/_generated/server-bindings.ts +47 -0
  292. package/src/plugins/accounting/Preview.vue +106 -0
  293. package/src/plugins/accounting/View.vue +632 -0
  294. package/src/plugins/accounting/actions.ts +34 -0
  295. package/src/plugins/accounting/api.ts +301 -0
  296. package/src/plugins/accounting/components/AccountEditor.vue +250 -0
  297. package/src/plugins/accounting/components/AccountRow.vue +50 -0
  298. package/src/plugins/accounting/components/AccountsList.vue +102 -0
  299. package/src/plugins/accounting/components/AccountsModal.vue +300 -0
  300. package/src/plugins/accounting/components/BalanceSheet.vue +186 -0
  301. package/src/plugins/accounting/components/BookSettings.vue +284 -0
  302. package/src/plugins/accounting/components/BookSwitcher.vue +78 -0
  303. package/src/plugins/accounting/components/DateRangePicker.vue +140 -0
  304. package/src/plugins/accounting/components/JournalEntryForm.vue +504 -0
  305. package/src/plugins/accounting/components/JournalList.vue +553 -0
  306. package/src/plugins/accounting/components/Ledger.vue +206 -0
  307. package/src/plugins/accounting/components/NewBookForm.vue +211 -0
  308. package/src/plugins/accounting/components/OpeningBalancesForm.vue +271 -0
  309. package/src/plugins/accounting/components/ProfitLoss.vue +160 -0
  310. package/src/plugins/accounting/components/accountDraft.ts +13 -0
  311. package/src/plugins/accounting/components/accountNumbering.ts +103 -0
  312. package/src/plugins/accounting/components/accountValidation.ts +75 -0
  313. package/src/plugins/accounting/components/useLatestRequest.ts +44 -0
  314. package/src/plugins/accounting/countries.ts +158 -0
  315. package/src/plugins/accounting/currencies.ts +64 -0
  316. package/src/plugins/accounting/dates.ts +51 -0
  317. package/src/plugins/accounting/definition.ts +199 -0
  318. package/src/plugins/accounting/fiscalYear.ts +136 -0
  319. package/src/plugins/accounting/index.ts +49 -0
  320. package/src/plugins/accounting/meta.ts +91 -0
  321. package/src/plugins/accounting/timeSeriesEnums.ts +16 -0
  322. package/src/plugins/api.ts +125 -0
  323. package/src/plugins/canvas/View.vue +38 -28
  324. package/src/plugins/canvas/definition.ts +10 -8
  325. package/src/plugins/canvas/index.ts +15 -8
  326. package/src/plugins/canvas/meta.ts +12 -0
  327. package/src/plugins/chart/Preview.vue +1 -1
  328. package/src/plugins/chart/View.vue +2 -2
  329. package/src/plugins/chart/definition.ts +12 -2
  330. package/src/plugins/chart/index.ts +15 -7
  331. package/src/plugins/chart/meta.ts +18 -0
  332. package/src/plugins/editImages/definition.ts +44 -0
  333. package/src/plugins/editImages/index.ts +43 -0
  334. package/src/plugins/editImages/meta.ts +5 -0
  335. package/src/plugins/generateImage/View.vue +3 -1
  336. package/src/plugins/generateImage/definition.ts +2 -0
  337. package/src/plugins/generateImage/index.ts +13 -5
  338. package/src/plugins/generateImage/meta.ts +5 -0
  339. package/src/plugins/index.ts +35 -0
  340. package/src/plugins/manageRoles/Preview.vue +7 -4
  341. package/src/plugins/manageRoles/View.vue +12 -8
  342. package/src/plugins/manageRoles/definition.ts +6 -0
  343. package/src/plugins/manageRoles/index.ts +7 -6
  344. package/src/plugins/manageSkills/View.vue +11 -7
  345. package/src/plugins/manageSkills/definition.ts +4 -1
  346. package/src/plugins/manageSkills/index.ts +14 -7
  347. package/src/plugins/manageSkills/meta.ts +21 -0
  348. package/src/plugins/manageSource/definition.ts +4 -1
  349. package/src/plugins/manageSource/index.ts +15 -7
  350. package/src/plugins/manageSource/meta.ts +21 -0
  351. package/src/plugins/markdown/Preview.vue +10 -8
  352. package/src/plugins/markdown/View.vue +84 -17
  353. package/src/plugins/markdown/definition.ts +7 -1
  354. package/src/plugins/markdown/index.ts +15 -8
  355. package/src/plugins/markdown/meta.ts +16 -0
  356. package/src/plugins/meta-types.ts +97 -0
  357. package/src/plugins/metas.ts +224 -0
  358. package/src/plugins/presentForm/Preview.vue +4 -15
  359. package/src/plugins/presentForm/View.vue +35 -78
  360. package/src/plugins/presentForm/definition.ts +7 -6
  361. package/src/plugins/presentForm/index.ts +12 -5
  362. package/src/plugins/presentForm/meta.ts +11 -0
  363. package/src/plugins/presentForm/plugin.ts +8 -9
  364. package/src/plugins/presentForm/types.ts +0 -24
  365. package/src/plugins/presentHtml/Preview.vue +1 -8
  366. package/src/plugins/presentHtml/View.vue +401 -30
  367. package/src/plugins/presentHtml/definition.ts +8 -5
  368. package/src/plugins/presentHtml/index.ts +15 -8
  369. package/src/plugins/presentHtml/meta.ts +14 -0
  370. package/src/plugins/presentMulmoScript/View.vue +327 -107
  371. package/src/plugins/presentMulmoScript/definition.ts +34 -7
  372. package/src/plugins/presentMulmoScript/helpers.ts +4 -5
  373. package/src/plugins/presentMulmoScript/index.ts +20 -7
  374. package/src/plugins/presentMulmoScript/meta.ts +52 -0
  375. package/src/plugins/scheduler/AutomationsPreview.vue +2 -8
  376. package/src/plugins/scheduler/Preview.vue +5 -2
  377. package/src/plugins/scheduler/TasksTab.vue +16 -36
  378. package/src/plugins/scheduler/View.vue +22 -54
  379. package/src/plugins/scheduler/automationsDefinition.ts +14 -9
  380. package/src/plugins/scheduler/automationsMeta.ts +5 -0
  381. package/src/plugins/scheduler/calendarDefinition.ts +4 -7
  382. package/src/plugins/scheduler/calendarMeta.ts +28 -0
  383. package/src/plugins/scheduler/formatSchedule.ts +6 -24
  384. package/src/plugins/scheduler/index.ts +26 -52
  385. package/src/plugins/scope.ts +57 -0
  386. package/src/plugins/server-bindings-types.ts +38 -0
  387. package/src/plugins/server.ts +32 -0
  388. package/src/plugins/skill/Preview.vue +25 -0
  389. package/src/plugins/skill/View.vue +125 -0
  390. package/src/plugins/skill/definition.ts +23 -0
  391. package/src/plugins/skill/index.ts +36 -0
  392. package/src/plugins/skill/plugin.ts +31 -0
  393. package/src/plugins/skill/types.ts +21 -0
  394. package/src/plugins/spreadsheet/Preview.vue +1 -3
  395. package/src/plugins/spreadsheet/View.vue +29 -49
  396. package/src/plugins/spreadsheet/cellHighlights.ts +2 -3
  397. package/src/plugins/spreadsheet/definition.ts +5 -2
  398. package/src/plugins/spreadsheet/index.ts +15 -8
  399. package/src/plugins/spreadsheet/keyboardNav.ts +38 -0
  400. package/src/plugins/spreadsheet/meta.ts +14 -0
  401. package/src/plugins/textResponse/Preview.vue +9 -1
  402. package/src/plugins/textResponse/View.vue +59 -8
  403. package/src/plugins/textResponse/index.ts +11 -3
  404. package/src/plugins/textResponse/plugin.ts +8 -10
  405. package/src/plugins/textResponse/types.ts +28 -0
  406. package/src/plugins/wiki/Preview.vue +6 -4
  407. package/src/plugins/wiki/View.vue +463 -254
  408. package/src/plugins/wiki/components/WikiPageBody.vue +159 -0
  409. package/src/plugins/wiki/helpers.ts +17 -0
  410. package/src/plugins/wiki/history/HistoryDetail.vue +325 -0
  411. package/src/plugins/wiki/history/HistoryTab.vue +167 -0
  412. package/src/plugins/wiki/history/RestoreConfirm.vue +63 -0
  413. package/src/plugins/wiki/history/api.ts +52 -0
  414. package/src/plugins/wiki/history/diff.ts +145 -0
  415. package/src/plugins/wiki/index.ts +42 -32
  416. package/src/plugins/wiki/meta.ts +10 -0
  417. package/src/plugins/wiki/pageEditLoader.ts +53 -0
  418. package/src/plugins/wiki/route.ts +8 -0
  419. package/src/router/guards.ts +2 -1
  420. package/src/router/index.ts +19 -0
  421. package/src/router/pageRoutes.ts +1 -0
  422. package/src/tools/index.ts +50 -51
  423. package/src/tools/runtimeLoader.ts +141 -0
  424. package/src/tools/types.ts +44 -1
  425. package/src/types/notification.ts +23 -0
  426. package/src/types/pastedFile.ts +10 -0
  427. package/src/types/session.ts +61 -3
  428. package/src/types/sse.ts +21 -6
  429. package/src/utils/agent/eventDispatch.ts +12 -9
  430. package/src/utils/agent/pastedAttachment.ts +35 -0
  431. package/src/utils/agent/request.ts +32 -3
  432. package/src/utils/agent/toolCalls.ts +7 -1
  433. package/src/utils/api.ts +1 -1
  434. package/src/utils/chat/exportMarkdown.ts +243 -0
  435. package/src/utils/errors.ts +10 -2
  436. package/src/utils/files/expandedDirs.ts +1 -1
  437. package/src/utils/filesPreview/todoPreview.ts +13 -2
  438. package/src/utils/format/date.ts +1 -3
  439. package/src/utils/format/jsonSyntax.ts +5 -0
  440. package/src/utils/html/iframeHeightReporterScript.ts +62 -0
  441. package/src/utils/html/previewCsp.ts +29 -2
  442. package/src/utils/image/htmlSrcAttrs.ts +122 -0
  443. package/src/utils/image/imageRepairInlineScript.ts +115 -0
  444. package/src/utils/image/resolve.ts +17 -3
  445. package/src/utils/image/rewriteMarkdownImageRefs.ts +62 -9
  446. package/src/utils/markdown/frontmatter.ts +125 -0
  447. package/src/utils/markdown/taskList.ts +7 -2
  448. package/src/utils/plugin/runtime.ts +132 -0
  449. package/src/utils/session/mergeSessions.ts +40 -37
  450. package/src/utils/session/sessionEntries.ts +74 -18
  451. package/src/utils/session/sessionHelpers.ts +54 -10
  452. package/src/utils/tools/result.ts +76 -14
  453. package/src/vite-env.d.ts +6 -0
  454. package/client/assets/html2canvas-Cx501zZr-Bug0qRNv.js +0 -5
  455. package/client/assets/index-CY-WpQUm.css +0 -2
  456. package/client/assets/index-DbTz2Mfs.js +0 -4911
  457. package/client/assets/material-symbols-outlined-NzYEeyps.woff2 +0 -0
  458. package/server/api/routes/html.ts +0 -114
  459. package/server/api/routes/todos.ts +0 -293
  460. package/server/api/routes/todosColumnsHandlers.ts +0 -333
  461. package/server/api/routes/todosHandlers.ts +0 -274
  462. package/server/api/routes/todosItemsHandlers.ts +0 -386
  463. package/server/utils/files/todos-io.ts +0 -29
  464. package/src/components/NotificationToast.vue +0 -75
  465. package/src/plugins/editImage/definition.ts +0 -27
  466. package/src/plugins/editImage/index.ts +0 -37
  467. package/src/plugins/presentHtml/helpers.ts +0 -72
  468. package/src/plugins/scheduler/LegacySchedulerView.vue +0 -32
  469. package/src/plugins/scheduler/legacyShape.ts +0 -34
  470. package/src/plugins/todo/Preview.vue +0 -68
  471. package/src/plugins/todo/View.vue +0 -378
  472. package/src/plugins/todo/composables/useTodos.ts +0 -179
  473. package/src/plugins/todo/definition.ts +0 -45
  474. package/src/plugins/todo/index.ts +0 -62
  475. package/src/plugins/todo/labels.ts +0 -163
  476. package/src/plugins/todo/priority.ts +0 -98
  477. package/src/plugins/todo/viewModes.ts +0 -19
  478. package/src/plugins/wiki/definition.ts +0 -25
  479. package/src/tools/legacyPluginNames.ts +0 -13
  480. package/src/utils/format/frontmatter.ts +0 -80
  481. package/src/utils/image/rewriteHtmlImageRefs.ts +0 -50
  482. package/src/utils/notification/dispatch.ts +0 -58
  483. /package/client/assets/{purify.es-Fx1Nqyry-BwJECkqS.js → purify.es-Fx1Nqyry-BSVNht6S.js} +0 -0
  484. /package/src/plugins/{editImage → editImages}/Preview.vue +0 -0
  485. /package/src/plugins/{editImage → editImages}/View.vue +0 -0
  486. /package/src/{config/schedulerActions.ts → plugins/scheduler/actions.ts} +0 -0
@@ -0,0 +1,91 @@
1
+ // Central-registry-facing metadata that the accounting plugin owns.
2
+ // Imported by host aggregators (`src/config/*` and
3
+ // `server/workspace/paths.ts`) which iterate over every plugin's
4
+ // META and merge automatically. Host code holds zero
5
+ // plugin-specific literals — when a constant is "produced by the
6
+ // plugin", the plugin is the source of truth.
7
+ //
8
+ // Browser-safe: no Vue imports, no server-only imports. Both server
9
+ // and frontend code can import this file.
10
+
11
+ import { definePluginMeta } from "../meta-types";
12
+
13
+ /** Single object the host aggregators iterate over. `definePluginMeta`
14
+ * type-checks the shape (typo / missing field surfaces at compile
15
+ * time) AND preserves nested literal types via TS 5.0+'s `const`
16
+ * type parameter. Helper functions / types specific to this plugin
17
+ * (e.g. `bookChannel(bookId)`, `BookChannelPayload`) live below as
18
+ * separate named exports — the META object only carries the static
19
+ * values that aggregate generically. */
20
+ export const META = definePluginMeta({
21
+ toolName: "manageAccounting",
22
+ apiNamespace: "accounting",
23
+ apiRoutes: {
24
+ /** POST /api/accounting — single dispatch with action discriminator. */
25
+ dispatch: { method: "POST", path: "" },
26
+ },
27
+ mcpDispatch: "dispatch",
28
+ // Flat keys merged into the central `WORKSPACE_DIRS`. Created
29
+ // lazily on first `createBook` so default workspaces don't get a
30
+ // stub `accounting/` they never use.
31
+ workspaceDirs: {
32
+ accounting: "data/accounting",
33
+ // `accounting/books/<bookId>/{accounts.json, journal/YYYY-MM.jsonl,
34
+ // snapshots/YYYY-MM.json}` — multi-book layout (#1078).
35
+ accountingBooks: "data/accounting/books",
36
+ },
37
+ // Static pubsub channel names merged into the central
38
+ // `PUBSUB_CHANNELS`. Per-book data changes ride
39
+ // `bookChannel(bookId)` (helper below); book-list-level events
40
+ // (a new book was created, an existing one was deleted) ride
41
+ // `accountingBooks` so a `JournalList.vue` viewing book A doesn't
42
+ // repaint when the user creates book B from another window.
43
+ staticChannels: {
44
+ accountingBooks: "accounting:books",
45
+ },
46
+ });
47
+
48
+ /** Channel factory for per-book event streams. Subscribers:
49
+ * `useAccountingChannel(bookId)`. Publisher:
50
+ * `server/accounting/eventPublisher.ts`. */
51
+ export function bookChannel(bookId: string): string {
52
+ return `accounting:${bookId}`;
53
+ }
54
+
55
+ /** Event kinds that ride `bookChannel(bookId)`. Single source of
56
+ * truth for both publishers (server/accounting) and subscribers
57
+ * (the View) — anyone branching on event kind imports from here
58
+ * and the type system catches drift on either side.
59
+ *
60
+ * - `journal` — addEntry / voidEntry hit the books at `period`.
61
+ * Refetch the journal list and (if the View is
62
+ * showing balances at or after `period`) the
63
+ * relevant report.
64
+ * - `opening` — setOpeningBalances. Affects every period from
65
+ * the opening date forward; refetch everything.
66
+ * - `accounts` — chart-of-accounts mutation that may affect
67
+ * aggregation (account type changed). Refetch
68
+ * accounts and the active report.
69
+ * - `snapshotsRebuilding` / `snapshotsReady` — purely informational;
70
+ * the View can show a "calculating" spinner
71
+ * during rebuild, but the lazy-rebuild safety
72
+ * net means a refetch always returns the right
73
+ * answer regardless. */
74
+ export const BOOK_EVENT_KINDS = {
75
+ journal: "journal",
76
+ opening: "opening",
77
+ accounts: "accounts",
78
+ snapshotsRebuilding: "snapshots-rebuilding",
79
+ snapshotsReady: "snapshots-ready",
80
+ } as const;
81
+
82
+ export type BookEventKind = (typeof BOOK_EVENT_KINDS)[keyof typeof BOOK_EVENT_KINDS];
83
+
84
+ /** Payload published on `bookChannel(bookId)`. */
85
+ export interface BookChannelPayload {
86
+ kind: BookEventKind;
87
+ /** YYYY-MM. Present for `journal` (entry month) and the snapshot
88
+ * events (the earliest invalidated month). Absent for `opening`
89
+ * (which invalidates everything) and `accounts`. */
90
+ period?: string;
91
+ }
@@ -0,0 +1,16 @@
1
+ // Single source of truth for the `getTimeSeries` action's enum
2
+ // surfaces — kept outside the server module so the frontend tool
3
+ // definition (`definition.ts`) and the server validator
4
+ // (`server/accounting/timeSeries.ts`) can both import without
5
+ // crossing the src ↔ server boundary in the wrong direction.
6
+ //
7
+ // Adding a new metric / granularity: extend the array here, then
8
+ // extend the corresponding switch / aggregation in
9
+ // `server/accounting/timeSeries.ts`. The LLM tool schema picks up
10
+ // the new value automatically via `definition.ts`'s `enum` field.
11
+
12
+ export const TIME_SERIES_METRICS = ["revenue", "expense", "netIncome", "accountBalance"] as const;
13
+ export type TimeSeriesMetric = (typeof TIME_SERIES_METRICS)[number];
14
+
15
+ export const TIME_SERIES_GRANULARITIES = ["month", "quarter", "year"] as const;
16
+ export type TimeSeriesGranularity = (typeof TIME_SERIES_GRANULARITIES)[number];
@@ -0,0 +1,125 @@
1
+ // Plugin-side DI container.
2
+ //
3
+ // Plugins must NOT import from `src/config/*` (the host's URL /
4
+ // constants registry) — the host owns those values and decides
5
+ // when / how to provide them. This file is the indirection: plugins
6
+ // call the getters here; the host wires the actual values once at
7
+ // boot via `installHostContext`.
8
+ //
9
+ // Loose coupling means:
10
+ //
11
+ // - This file references zero `src/config/*` modules. The
12
+ // `HostContext` interface declares only the contract — the
13
+ // host is free to swap in test doubles, runtime overrides, or
14
+ // a future server-driven config without touching any plugin.
15
+ // - Plugins import `pluginEndpoints` / `pluginPageRoute` / etc.
16
+ // from `../api`; they never see `API_ROUTES`, `PAGE_ROUTES`,
17
+ // `BUILTIN_ROLE_IDS`, or `getAllPluginNames` directly.
18
+ // - Tests install their own `HostContext` via the same
19
+ // `installHostContext` entry point (see
20
+ // `test/helpers/installHostContext.ts`).
21
+ //
22
+ // Adding a new injected capability: add a typed field to
23
+ // `HostContext`, a corresponding getter helper here, and update
24
+ // the host's install call in `src/main.ts`.
25
+
26
+ import type { ResolvedRoute } from "./meta-types";
27
+
28
+ /** A flat group of plugin-owned routes (`{ create: { method, url } }`).
29
+ * Each plugin scope maps to one of these. The host registry hands
30
+ * back resolved-URL records — the plugin author wrote `{ method,
31
+ * path }` in `meta.ts`, the host composed `/api/<namespace><path>`. */
32
+ export type EndpointGroup = Readonly<Record<string, ResolvedRoute>>;
33
+
34
+ /** Host-shared groups (`files`, `imageStore`, `mcpTools`, `wiki`,
35
+ * `roles`, `image`) that carry plain string URLs rather than the
36
+ * plugin `{ method, url }` shape. Kept around so the same registry
37
+ * can host both plugin-owned routes and the cross-cutting host
38
+ * endpoints plugins reach for. */
39
+ export type HostEndpointGroup = Readonly<Record<string, string>>;
40
+
41
+ /** The full registry of plugin endpoint groups, keyed by scope
42
+ * name (`"todos"`, `"wiki"`, `"mulmoScript"`, …). Values are either
43
+ * plugin-owned `EndpointGroup` records or host-owned
44
+ * `HostEndpointGroup` records — `pluginEndpoints<E>` narrows to the
45
+ * caller-declared shape. */
46
+ export type EndpointRegistry = Readonly<Record<string, EndpointGroup | HostEndpointGroup>>;
47
+
48
+ /** Everything the host hands to plugins at boot. Each field is
49
+ * read-only — plugins consume, never mutate. */
50
+ export interface HostContext {
51
+ /** URL maps for each plugin's API namespace. */
52
+ readonly endpoints: EndpointRegistry;
53
+ /** Built-in role IDs (e.g. `general`, `engineer`). Used by
54
+ * plugins that start a chat with a specific role. */
55
+ readonly builtinRoleIds: Readonly<Record<string, string>>;
56
+ /** Vue-router page-name constants. Used by plugins that need to
57
+ * branch on the current page or push a navigation. */
58
+ readonly pageRoutes: Readonly<Record<string, string>>;
59
+ /** Snapshot of every registered plugin's tool name. Used by
60
+ * manageRoles to populate the role-editor's plugin picker. */
61
+ readonly getAllPluginNames: () => readonly string[];
62
+ }
63
+
64
+ let installedContext: HostContext | null = null;
65
+
66
+ /** Host calls this once at boot (`src/main.ts`) BEFORE component
67
+ * setup runs. Calling it twice replaces the prior context — useful
68
+ * for tests; production should install exactly once. */
69
+ export function installHostContext(context: HostContext): void {
70
+ installedContext = context;
71
+ }
72
+
73
+ /** Strict reader — throws if the host hasn't installed yet. The
74
+ * intent is fail-fast: a plugin invoked before install is a wiring
75
+ * bug, not a state we want to silently paper over. */
76
+ function requireContext(): HostContext {
77
+ if (installedContext === null) {
78
+ throw new Error("Plugin host context not installed. Call installHostContext(...) at app boot before mounting any plugin component.");
79
+ }
80
+ return installedContext;
81
+ }
82
+
83
+ /** Returns the URL group for a plugin's scope. The generic `E` lets
84
+ * the caller declare the expected shape — plugins typically pass
85
+ * their own typed interface so member access is type-checked
86
+ * (`pluginEndpoints<TodoEndpoints>("todos").create.url`).
87
+ *
88
+ * Constraint is `object` (not `EndpointGroup` /
89
+ * `HostEndpointGroup`) so plugin-owned `Record<string, ResolvedRoute>`
90
+ * shapes AND host-shared `Record<string, string>` shapes both
91
+ * satisfy it — `pluginEndpoints` is the indirection that lets a
92
+ * caller assert the contract it expects. */
93
+ export function pluginEndpoints<E extends object = EndpointGroup>(scope: string): E {
94
+ const group = requireContext().endpoints[scope];
95
+ if (!group) {
96
+ throw new Error(`Unknown plugin endpoint scope: "${scope}"`);
97
+ }
98
+ return group as E;
99
+ }
100
+
101
+ /** Built-in role IDs (e.g. `pluginBuiltinRoleIds().general`). */
102
+ export function pluginBuiltinRoleIds(): Readonly<Record<string, string>> {
103
+ return requireContext().builtinRoleIds;
104
+ }
105
+
106
+ /** A specific Vue-router page-name constant
107
+ * (`pluginPageRoute("wiki")`). Throws on unknown name. */
108
+ export function pluginPageRoute(name: string): string {
109
+ const route = requireContext().pageRoutes[name];
110
+ if (!route) {
111
+ throw new Error(`Unknown page route: "${name}"`);
112
+ }
113
+ return route;
114
+ }
115
+
116
+ /** Snapshot of every registered plugin's tool name. */
117
+ export function pluginAllPluginNames(): readonly string[] {
118
+ return requireContext().getAllPluginNames();
119
+ }
120
+
121
+ /** Test-only: drop the installed context so the next `installHostContext`
122
+ * starts from a clean slate. Production code should not call this. */
123
+ export function resetHostContextForTest(): void {
124
+ installedContext = null;
125
+ }
@@ -15,7 +15,7 @@
15
15
  @click="brushSize = size"
16
16
  >
17
17
  <div
18
- :class="'bg-gray-800 rounded-full mx-auto'"
18
+ class="bg-gray-800 rounded-full mx-auto"
19
19
  :style="{
20
20
  width: Math.max(2, size * 1) + 'px',
21
21
  height: Math.max(2, size * 1) + 'px',
@@ -63,14 +63,14 @@
63
63
  :key="`${selectedResult?.uuid || 'default'}-${canvasRenderKey}`"
64
64
  :width="canvasWidth"
65
65
  :height="canvasHeight"
66
- :stroke-type="'dash'"
67
- :line-cap="'round'"
68
- :line-join="'round'"
66
+ stroke-type="dash"
67
+ line-cap="round"
68
+ line-join="round"
69
69
  :fill-shape="false"
70
70
  :eraser="false"
71
71
  :line-width="brushSize"
72
72
  :color="brushColor"
73
- :background-color="'#FFFFFF'"
73
+ background-color="#FFFFFF"
74
74
  :background-image="backgroundImage"
75
75
  :watermark="undefined"
76
76
  save-as="png"
@@ -104,10 +104,12 @@ import VueDrawingCanvas from "vue-drawing-canvas";
104
104
  import type { ToolResult } from "gui-chat-protocol/vue";
105
105
  import type { ImageToolData } from "./definition";
106
106
  import { apiPut } from "../../utils/api";
107
- import { API_ROUTES } from "../../config/apiRoutes";
107
+ import { pluginEndpoints } from "../api";
108
108
  import { resolveImageSrc } from "../../utils/image/resolve";
109
109
  import { bumpImage } from "../../utils/image/cacheBust";
110
110
 
111
+ const imageStoreEndpoints = pluginEndpoints<{ update: string }>("imageStore");
112
+
111
113
  const { t } = useI18n();
112
114
 
113
115
  const props = defineProps<{
@@ -130,10 +132,6 @@ const artStyles = [
130
132
  { id: "pixelart", label: "Pixel Art" },
131
133
  ];
132
134
 
133
- const applyStyle = (style: { id: string; label: string }) => {
134
- props.sendTextMessage?.(`Turn my drawing on the canvas into a ${style.label} style image.`);
135
- };
136
-
137
135
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
136
  const canvasRef = ref<any>(null);
139
137
  const containerRef = ref<HTMLDivElement | null>(null);
@@ -158,6 +156,16 @@ const imagePath = computed(() => {
158
156
  return stored;
159
157
  });
160
158
 
159
+ const applyStyle = (style: { id: string; label: string }) => {
160
+ // Embed the canvas image's workspace path directly so the LLM has
161
+ // it in plain text and can quote it back as `imagePaths` to the
162
+ // editImages tool. Falls back to the path-less phrasing only when
163
+ // openCanvas hasn't been linked to a saved file yet.
164
+ const path = imagePath.value;
165
+ const text = path ? t("pluginCanvas.stylePromptWithPath", { path, style: style.label }) : t("pluginCanvas.stylePromptNoPath", { style: style.label });
166
+ props.sendTextMessage?.(text);
167
+ };
168
+
161
169
  // Per-mount cache buster for the VueDrawingCanvas child. The URL
162
170
  // must be stable for the lifetime of one canvas instance — if it
163
171
  // changes while the child is alive (e.g. from a post-save bump),
@@ -177,25 +185,12 @@ const backgroundImage = computed(() => {
177
185
  let uploadInFlight = false;
178
186
  let pendingSave = false;
179
187
 
180
- // Undo/redo kick off the library's async redraw; give it a tick to
181
- // composite before we snapshot-and-upload.
182
- const undo = () => {
183
- canvasRef.value?.undo();
184
- setTimeout(saveDrawing, 50);
185
- };
186
- const redo = () => {
187
- canvasRef.value?.redo();
188
- setTimeout(saveDrawing, 50);
189
- };
190
- const clear = () => {
191
- canvasRef.value?.reset();
192
- saveDrawing();
193
- };
194
-
195
188
  // Snapshot the current bitmap and PUT it back to the pre-allocated
196
189
  // file. No result mutation — the path is fixed from canvas creation,
197
- // so nothing upstream needs to know about saves.
198
- const saveDrawing = async (): Promise<void> => {
190
+ // so nothing upstream needs to know about saves. `function` (not
191
+ // `const`) so the undo/redo/clear handlers below can reference it
192
+ // without TDZ ordering problems.
193
+ async function saveDrawing(): Promise<void> {
199
194
  if (!canvasRef.value || !imagePath.value) return;
200
195
  if (uploadInFlight) {
201
196
  pendingSave = true;
@@ -204,7 +199,7 @@ const saveDrawing = async (): Promise<void> => {
204
199
  uploadInFlight = true;
205
200
  try {
206
201
  const imageDataUri: string = await canvasRef.value.save();
207
- const result = await apiPut<{ path: string }>(API_ROUTES.image.update, {
202
+ const result = await apiPut<{ path: string }>(imageStoreEndpoints.update, {
208
203
  relativePath: imagePath.value,
209
204
  imageData: imageDataUri,
210
205
  });
@@ -219,6 +214,21 @@ const saveDrawing = async (): Promise<void> => {
219
214
  void saveDrawing();
220
215
  }
221
216
  }
217
+ }
218
+
219
+ // Undo/redo kick off the library's async redraw; give it a tick to
220
+ // composite before we snapshot-and-upload.
221
+ const undo = () => {
222
+ canvasRef.value?.undo();
223
+ setTimeout(saveDrawing, 50);
224
+ };
225
+ const redo = () => {
226
+ canvasRef.value?.redo();
227
+ setTimeout(saveDrawing, 50);
228
+ };
229
+ const clear = () => {
230
+ canvasRef.value?.reset();
231
+ saveDrawing();
222
232
  };
223
233
 
224
234
  const updateCanvasSize = () => {
@@ -1,6 +1,9 @@
1
1
  import type { ToolDefinition } from "gui-chat-protocol";
2
+ import { META } from "./meta";
3
+ import type { ResolvedRoute } from "../meta-types";
2
4
 
3
- export const TOOL_NAME = "openCanvas";
5
+ export const TOOL_NAME = META.toolName;
6
+ export type CanvasEndpoints = { readonly [K in keyof typeof META.apiRoutes]: ResolvedRoute };
4
7
 
5
8
  export interface ImageToolData {
6
9
  imageData: string;
@@ -21,10 +24,9 @@ const toolDefinition: ToolDefinition = {
21
24
 
22
25
  export default toolDefinition;
23
26
 
24
- export const executeOpenCanvas = async () => {
25
- return {
26
- message: "Drawing canvas opened",
27
- instructions: "Tell the user that you are able to turn the drawing into a photographic image, a manga or any other art style.",
28
- title: "Drawing Canvas",
29
- };
30
- };
27
+ export const executeOpenCanvas = async (imagePath: string) => ({
28
+ message: `Drawing canvas opened. The drawing will be saved to: ${imagePath}`,
29
+ instructions:
30
+ "The drawing canvas is now displayed and the user is about to draw on it. Tell them you can turn their drawing into a photographic image, manga, or any other art style once they're done.",
31
+ title: "Drawing Canvas",
32
+ });
@@ -1,18 +1,20 @@
1
- import type { ToolPlugin } from "../../tools/types";
1
+ import type { PluginRegistration, ToolPlugin } from "../../tools/types";
2
2
  import type { ToolResult } from "gui-chat-protocol";
3
- import toolDefinition, { TOOL_NAME } from "./definition";
4
- import type { ImageToolData } from "./definition";
3
+ import toolDefinition, { TOOL_NAME, type CanvasEndpoints, type ImageToolData } from "./definition";
4
+ import { pluginEndpoints } from "../api";
5
+ import { wrapWithScope } from "../scope";
5
6
  import View from "./View.vue";
6
7
  import Preview from "./Preview.vue";
7
- import { apiPost } from "../../utils/api";
8
- import { API_ROUTES } from "../../config/apiRoutes";
8
+ import { apiCall } from "../../utils/api";
9
9
  import { makeUuid } from "../../utils/id";
10
10
 
11
11
  const canvasPlugin: ToolPlugin<ImageToolData> = {
12
12
  toolDefinition,
13
13
 
14
14
  async execute(_context, args) {
15
- const result = await apiPost<ToolResult<ImageToolData>>(API_ROUTES.plugins.canvas, args);
15
+ const endpoints = pluginEndpoints<CanvasEndpoints>("canvas");
16
+ const { method, url } = endpoints.dispatch;
17
+ const result = await apiCall<ToolResult<ImageToolData>>(url, { method, body: args });
16
18
  if (!result.ok) {
17
19
  return {
18
20
  toolName: TOOL_NAME,
@@ -29,9 +31,14 @@ const canvasPlugin: ToolPlugin<ImageToolData> = {
29
31
 
30
32
  isEnabled: () => true,
31
33
  generatingMessage: "Opening drawing canvas...",
32
- viewComponent: View,
33
- previewComponent: Preview,
34
+ viewComponent: wrapWithScope("canvas", View),
35
+ previewComponent: wrapWithScope("canvas", Preview),
34
36
  };
35
37
 
36
38
  export default canvasPlugin;
37
39
  export { TOOL_NAME };
40
+
41
+ export const REGISTRATION: PluginRegistration = {
42
+ toolName: TOOL_NAME,
43
+ entry: canvasPlugin,
44
+ };
@@ -0,0 +1,12 @@
1
+ import { definePluginMeta } from "../meta-types";
2
+
3
+ export const META = definePluginMeta({
4
+ toolName: "openCanvas",
5
+ apiNamespace: "canvas",
6
+ apiRoutes: {
7
+ /** POST /api/canvas — open a drawing canvas the user can sketch
8
+ * on. Result carries the workspace-relative image path. */
9
+ dispatch: { method: "POST", path: "" },
10
+ },
11
+ mcpDispatch: "dispatch",
12
+ });
@@ -36,7 +36,7 @@ const hint = computed(() => {
36
36
  });
37
37
 
38
38
  function inferTypeFromOption(option: Record<string, unknown>): string | null {
39
- const series = option.series;
39
+ const { series } = option;
40
40
  if (Array.isArray(series) && series.length > 0) {
41
41
  const first = series[0] as { type?: unknown };
42
42
  if (typeof first.type === "string") return first.type;
@@ -52,7 +52,7 @@ const data = computed(() => props.selectedResult.data);
52
52
  const charts = computed<ChartEntry[]>(() => data.value?.document?.charts ?? []);
53
53
  const title = computed(() => data.value?.title ?? data.value?.document?.title);
54
54
 
55
- const containers = ref<Array<HTMLDivElement | null>>([]);
55
+ const containers = ref<(HTMLDivElement | null)[]>([]);
56
56
  // Kept as a plain array (not `ref`): ECharts instances are managed
57
57
  // imperatively and should not trigger Vue re-renders on mutation.
58
58
  const instances: echarts.ECharts[] = [];
@@ -74,7 +74,7 @@ function disposeAll(): void {
74
74
  // (zoomOnMouseWheel=true), which traps the scroll over the canvas.
75
75
  // Toolbox/slider/drag zoom still work — only the wheel is disabled.
76
76
  function disableWheelZoom(option: Record<string, unknown>): Record<string, unknown> {
77
- const dataZoom = option.dataZoom;
77
+ const { dataZoom } = option;
78
78
  if (dataZoom === undefined || dataZoom === null) return option;
79
79
  const normalise = (entry: unknown): unknown => {
80
80
  if (!isRecord(entry)) return entry;
@@ -1,10 +1,20 @@
1
1
  import type { ToolDefinition } from "gui-chat-protocol";
2
+ import { META } from "./meta";
3
+ import type { ResolvedRoute } from "../meta-types";
2
4
 
3
- export const TOOL_NAME = "presentChart";
5
+ // Re-export so existing `import { TOOL_NAME } from "./definition"`
6
+ // callers (server/agent/plugin-names.ts ledger, scope wrapper, …)
7
+ // keep compiling — META.toolName is the source of truth.
8
+ export const TOOL_NAME = META.toolName;
9
+
10
+ /** Resolved-URL view of the chart plugin's routes. Plugin code reads
11
+ * `endpoints.create.{method, url}` to drive `apiCall`. Auto-derived
12
+ * from META so adding a route in `meta.ts` is the only edit. */
13
+ export type ChartEndpoints = { readonly [K in keyof typeof META.apiRoutes]: ResolvedRoute };
4
14
 
5
15
  const toolDefinition: ToolDefinition = {
6
16
  type: "function",
7
- name: TOOL_NAME,
17
+ name: META.toolName,
8
18
  description:
9
19
  "Save and present one or more Apache ECharts visualizations as a single document. Use this for line, bar, area, scatter, pie, candlestick, heatmap, sankey, or graph/network charts — anything ECharts supports. Pass ECharts option object(s) directly; the plugin calls setOption on each one. Use `charts: []` array form even for a single chart so multi-chart dashboards share the same slug.",
10
20
  parameters: {
@@ -1,10 +1,11 @@
1
- import type { ToolPlugin } from "../../tools/types";
1
+ import type { PluginRegistration, ToolPlugin } from "../../tools/types";
2
2
  import type { ToolResult } from "gui-chat-protocol";
3
- import toolDefinition, { TOOL_NAME } from "./definition";
3
+ import toolDefinition, { TOOL_NAME, type ChartEndpoints } from "./definition";
4
+ import { pluginEndpoints } from "../api";
5
+ import { wrapWithScope } from "../scope";
4
6
  import View from "./View.vue";
5
7
  import Preview from "./Preview.vue";
6
- import { apiPost } from "../../utils/api";
7
- import { API_ROUTES } from "../../config/apiRoutes";
8
+ import { apiCall } from "../../utils/api";
8
9
  import { makeUuid } from "../../utils/id";
9
10
 
10
11
  export interface ChartEntry {
@@ -28,7 +29,9 @@ const presentChartPlugin: ToolPlugin<PresentChartData> = {
28
29
  toolDefinition,
29
30
 
30
31
  async execute(_context, args) {
31
- const result = await apiPost<ToolResult<PresentChartData>>(API_ROUTES.chart.present, args);
32
+ const endpoints = pluginEndpoints<ChartEndpoints>("chart");
33
+ const { method, url } = endpoints.create;
34
+ const result = await apiCall<ToolResult<PresentChartData>>(url, { method, body: args });
32
35
  if (!result.ok) {
33
36
  return {
34
37
  toolName: TOOL_NAME,
@@ -45,9 +48,14 @@ const presentChartPlugin: ToolPlugin<PresentChartData> = {
45
48
 
46
49
  isEnabled: () => true,
47
50
  generatingMessage: "Rendering chart…",
48
- viewComponent: View,
49
- previewComponent: Preview,
51
+ viewComponent: wrapWithScope("chart", View),
52
+ previewComponent: wrapWithScope("chart", Preview),
50
53
  };
51
54
 
52
55
  export default presentChartPlugin;
53
56
  export { TOOL_NAME };
57
+
58
+ export const REGISTRATION: PluginRegistration = {
59
+ toolName: TOOL_NAME,
60
+ entry: presentChartPlugin,
61
+ };
@@ -0,0 +1,18 @@
1
+ // Central-registry-facing metadata for the chart plugin. Imported by
2
+ // host aggregators (`src/plugins/metas.ts`) which iterate every
3
+ // plugin's META and merge per-dimension records — host code holds
4
+ // zero plugin-specific literals.
5
+ //
6
+ // Browser-safe: no Vue / no Node-only imports.
7
+
8
+ import { definePluginMeta } from "../meta-types";
9
+
10
+ export const META = definePluginMeta({
11
+ toolName: "presentChart",
12
+ apiNamespace: "chart",
13
+ apiRoutes: {
14
+ /** POST /api/chart — render and save a chart document. */
15
+ create: { method: "POST", path: "" },
16
+ },
17
+ mcpDispatch: "create",
18
+ });
@@ -0,0 +1,44 @@
1
+ import type { ToolDefinition } from "gui-chat-protocol";
2
+
3
+ export const TOOL_NAME = "editImages";
4
+
5
+ /** Endpoint contract — both `editImages` and `generateImage` plugins
6
+ * share the host's `image` scope (the host's `API_ROUTES.image.*`).
7
+ * Each picks the URL it needs (`edit` / `generate` / `update`). */
8
+ export interface ImageEndpoints {
9
+ [key: string]: string;
10
+ generate: string;
11
+ edit: string;
12
+ upload: string;
13
+ update: string;
14
+ }
15
+
16
+ export interface ImageToolData {
17
+ imageData: string;
18
+ prompt: string;
19
+ }
20
+
21
+ const toolDefinition: ToolDefinition = {
22
+ type: "function",
23
+ name: TOOL_NAME,
24
+ description: "Edit one or more existing images based on a text prompt. Returns a single new image.",
25
+ prompt: `When the user asks to transform or restyle an existing image (e.g. "turn this into a Ghibli-style image", "combine these two photos"), call ${TOOL_NAME} with the workspace-relative paths of the source images in \`imagePaths\` and the edit instructions in \`prompt\`. Use a single-element array for one image; pass two or more paths to combine multiple images.`,
26
+ parameters: {
27
+ type: "object",
28
+ properties: {
29
+ prompt: {
30
+ type: "string",
31
+ description: "Description of the edits to be made to the image(s) in English",
32
+ },
33
+ imagePaths: {
34
+ type: "array",
35
+ items: { type: "string" },
36
+ description:
37
+ 'Workspace-relative paths of the source images to edit (e.g. ["artifacts/images/2026/04/abc.png"]). Pass at least one path. Multiple paths are combined into a single result image.',
38
+ },
39
+ },
40
+ required: ["prompt", "imagePaths"],
41
+ },
42
+ };
43
+
44
+ export default toolDefinition;
@@ -0,0 +1,43 @@
1
+ import type { PluginRegistration, ToolPlugin } from "../../tools/types";
2
+ import type { ToolResult } from "gui-chat-protocol";
3
+ import toolDefinition, { TOOL_NAME, type ImageEndpoints, type ImageToolData } from "./definition";
4
+ import { pluginEndpoints } from "../api";
5
+ import { wrapWithScope } from "../scope";
6
+ import View from "./View.vue";
7
+ import Preview from "./Preview.vue";
8
+ import { apiPost } from "../../utils/api";
9
+ import { makeUuid } from "../../utils/id";
10
+
11
+ const editImagesPlugin: ToolPlugin<ImageToolData> = {
12
+ toolDefinition,
13
+
14
+ async execute(_context, args) {
15
+ const endpoints = pluginEndpoints<ImageEndpoints>("image");
16
+ const result = await apiPost<ToolResult<ImageToolData>>(endpoints.edit, args);
17
+ if (!result.ok) {
18
+ return {
19
+ toolName: TOOL_NAME,
20
+ uuid: makeUuid(),
21
+ message: result.error,
22
+ };
23
+ }
24
+ return {
25
+ ...result.data,
26
+ toolName: TOOL_NAME,
27
+ uuid: makeUuid(),
28
+ };
29
+ },
30
+
31
+ isEnabled: () => true,
32
+ generatingMessage: "Editing images...",
33
+ viewComponent: wrapWithScope("image", View),
34
+ previewComponent: wrapWithScope("image", Preview),
35
+ };
36
+
37
+ export default editImagesPlugin;
38
+ export { TOOL_NAME };
39
+
40
+ export const REGISTRATION: PluginRegistration = {
41
+ toolName: TOOL_NAME,
42
+ entry: editImagesPlugin,
43
+ };
@@ -0,0 +1,5 @@
1
+ import { definePluginMeta } from "../meta-types";
2
+
3
+ export const META = definePluginMeta({
4
+ toolName: "editImages",
5
+ });