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.
- package/Dockerfile.sandbox +100 -0
- package/README.md +17 -4
- package/bin/mulmoclaude.js +46 -15
- package/bin/prepare-dist.js +18 -2
- package/client/assets/chunk-CernVdwh.js +1 -0
- package/client/assets/chunk-D8eiyYIV-C1eAZMzz.js +1 -0
- package/client/assets/html2canvas-CDGcmOD3-BbPeutDg.js +5 -0
- package/client/assets/index-BbgSjFQ8.js +4968 -0
- package/client/assets/index-ECD0lgIv.css +2 -0
- package/client/assets/{index.es-D4YyL_Dg-BgT6a3Nd.js → index.es-DqtpmBm8-DJdTPdnc.js} +5 -5
- package/client/assets/material-symbols-outlined-BLDfUw-_.woff2 +0 -0
- package/client/assets/runtime-protocol-vue-6WYa8hAs.js +1 -0
- package/client/assets/runtime-vue-BVUzgYGA.js +1 -0
- package/client/assets/typeof-DBp4T-Ny-C2xoZtcz.js +1 -0
- package/client/assets/vue-1e_vz2LW.js +1 -0
- package/client/assets/vue.runtime.esm-bundler-DQ8Kjjui.js +4 -0
- package/client/index.html +33 -2
- package/package.json +20 -18
- package/sandbox-entrypoint.sh +106 -0
- package/server/accounting/accountNormalize.ts +32 -0
- package/server/accounting/defaultAccounts.ts +87 -0
- package/server/accounting/eventPublisher.ts +51 -0
- package/server/accounting/journal.ts +252 -0
- package/server/accounting/openingBalances.ts +114 -0
- package/server/accounting/report.ts +237 -0
- package/server/accounting/service.ts +718 -0
- package/server/accounting/snapshotCache.ts +333 -0
- package/server/accounting/timeSeries.ts +265 -0
- package/server/accounting/types.ts +148 -0
- package/server/agent/activeTools.ts +128 -0
- package/server/agent/attachmentConverter.ts +10 -5
- package/server/agent/backend/claude-code.ts +8 -2
- package/server/agent/backend/types.ts +1 -1
- package/server/agent/config.ts +101 -31
- package/server/agent/index.ts +45 -33
- package/server/agent/mcp-server.ts +146 -69
- package/server/agent/mcp-tools/index.ts +1 -5
- package/server/agent/mcp-tools/notify.ts +2 -22
- package/server/agent/mcp-tools/x.ts +0 -4
- package/server/agent/mcpHealth.ts +168 -0
- package/server/agent/plugin-names.ts +20 -77
- package/server/agent/prompt.ts +259 -51
- package/server/agent/resumeFailover.ts +1 -1
- package/server/agent/stream.ts +0 -1
- package/server/api/auth/bearerAuth.ts +5 -5
- package/server/api/csrfGuard.ts +1 -1
- package/server/api/routes/accounting.ts +366 -0
- package/server/api/routes/agent.ts +509 -46
- package/server/api/routes/attachment.ts +104 -0
- package/server/api/routes/chart.ts +2 -1
- package/server/api/routes/config.ts +12 -12
- package/server/api/routes/files.ts +105 -48
- package/server/api/routes/image.ts +70 -25
- package/server/api/routes/journal.ts +35 -0
- package/server/api/routes/mulmo-script.ts +358 -118
- package/server/api/routes/mulmoScriptValidate.ts +1 -1
- package/server/api/routes/news.ts +1 -1
- package/server/api/routes/notifications.ts +92 -22
- package/server/api/routes/notifier.ts +98 -0
- package/server/api/routes/pdf.ts +188 -48
- package/server/api/routes/plugins.ts +34 -14
- package/server/api/routes/presentHtml.ts +58 -3
- package/server/api/routes/roles.ts +1 -8
- package/server/api/routes/runtime-plugin.ts +224 -0
- package/server/api/routes/scheduler.ts +7 -5
- package/server/api/routes/schedulerHandlers.ts +1 -1
- package/server/api/routes/schedulerTasks.ts +8 -7
- package/server/api/routes/sessions.ts +234 -121
- package/server/api/routes/skills.ts +56 -51
- package/server/api/routes/sources.ts +52 -45
- package/server/api/routes/translation.ts +44 -0
- package/server/api/routes/wiki/frontmatter.ts +13 -65
- package/server/api/routes/wiki/history.ts +261 -0
- package/server/api/routes/wiki/pageIndex.ts +1 -1
- package/server/api/routes/wiki.ts +50 -26
- package/server/events/file-change.ts +83 -0
- package/server/events/notifications.ts +247 -91
- package/server/events/pub-sub/index.ts +1 -1
- package/server/events/relay-client.ts +5 -5
- package/server/events/scheduler-adapter.ts +2 -2
- package/server/events/session-store/index.ts +110 -22
- package/server/events/task-manager/index.ts +10 -9
- package/server/index.ts +509 -33
- package/server/notifier/engine.ts +419 -0
- package/server/notifier/legacy-adapters.ts +76 -0
- package/server/notifier/runtime-api.ts +74 -0
- package/server/notifier/store.ts +70 -0
- package/server/notifier/types.ts +121 -0
- package/server/plugins/dev-loader.ts +171 -0
- package/server/plugins/dev-watcher.ts +150 -0
- package/server/plugins/diagnostics.ts +188 -0
- package/server/plugins/preset-list.ts +52 -0
- package/server/plugins/preset-loader.ts +112 -0
- package/server/plugins/runtime-chat-api.ts +38 -0
- package/server/plugins/runtime-loader.ts +430 -0
- package/server/plugins/runtime-registry.ts +112 -0
- package/server/plugins/runtime-tasks-api.ts +50 -0
- package/server/plugins/runtime.ts +378 -0
- package/server/services/translation/cache.ts +72 -0
- package/server/services/translation/index.ts +106 -0
- package/server/services/translation/llm.ts +140 -0
- package/server/services/translation/types.ts +35 -0
- package/server/system/credentials.ts +13 -2
- package/server/system/env.ts +6 -1
- package/server/system/logger/formatters.ts +46 -4
- package/server/system/logger/index.ts +4 -4
- package/server/system/logger/sinks.ts +26 -5
- package/server/system/logger/types.ts +2 -2
- package/server/utils/dev-plugin-args.d.mts +11 -0
- package/server/utils/dev-plugin-args.mjs +43 -0
- package/server/utils/errors.ts +13 -4
- package/server/utils/files/accounting-io.ts +295 -0
- package/server/utils/files/atomic.ts +17 -49
- package/server/utils/files/attachment-store.ts +182 -0
- package/server/utils/files/html-io.ts +1 -7
- package/server/utils/files/html-store.ts +19 -0
- package/server/utils/files/image-store.ts +20 -22
- package/server/utils/files/index.ts +5 -15
- package/server/utils/files/journal-io.ts +7 -35
- package/server/utils/files/json.ts +2 -29
- package/server/utils/files/markdown-image-fill.ts +6 -37
- package/server/utils/files/markdown-store.ts +6 -21
- package/server/utils/files/naming.ts +3 -39
- package/server/utils/files/plugins-io.ts +100 -0
- package/server/utils/files/reference-dirs-io.ts +1 -9
- package/server/utils/files/roles-io.ts +2 -10
- package/server/utils/files/safe.ts +17 -19
- package/server/utils/files/scheduler-io.ts +1 -7
- package/server/utils/files/scheduler-overrides-io.ts +3 -12
- package/server/utils/files/session-io.ts +21 -30
- package/server/utils/files/spreadsheet-store.ts +9 -22
- package/server/utils/files/translation-io.ts +46 -0
- package/server/utils/files/user-tasks-io.ts +1 -7
- package/server/utils/files/workspace-io.ts +3 -79
- package/server/utils/gemini.ts +33 -11
- package/server/utils/html/htmlArtifactSplicer.ts +41 -0
- package/server/utils/markdown/frontmatter.ts +112 -0
- package/server/utils/regex.ts +56 -0
- package/server/utils/router.ts +41 -0
- package/server/utils/slug.ts +5 -3
- package/server/utils/time.ts +12 -0
- package/server/workspace/chat-index/indexer.ts +15 -2
- package/server/workspace/chat-index/summarizer.ts +1 -1
- package/server/workspace/custom-dirs.ts +1 -1
- package/server/workspace/helps/gemini.md +1 -1
- package/server/workspace/helps/guide.md +61 -0
- package/server/workspace/helps/index.md +4 -0
- package/server/workspace/helps/presenthtml.md +80 -0
- package/server/workspace/helps/sandbox.md +7 -0
- package/server/workspace/helps/storyteller.md +101 -0
- package/server/workspace/helps/telegram.md +1 -0
- package/server/workspace/helps/wiki.md +9 -7
- package/server/workspace/journal/archivist-cli.ts +7 -33
- package/server/workspace/journal/archivist-schemas.ts +5 -43
- package/server/workspace/journal/dailyPass.ts +34 -187
- package/server/workspace/journal/diff.ts +3 -28
- package/server/workspace/journal/index.ts +10 -81
- package/server/workspace/journal/indexFile.ts +3 -24
- package/server/workspace/journal/latestDaily.ts +51 -0
- package/server/workspace/journal/memoryExtractor.ts +4 -20
- package/server/workspace/journal/optimizationPass.ts +4 -21
- package/server/workspace/journal/paths.ts +4 -23
- package/server/workspace/journal/state.ts +6 -29
- package/server/workspace/memory/io.ts +213 -0
- package/server/workspace/memory/llm-classifier.ts +158 -0
- package/server/workspace/memory/migrate.ts +263 -0
- package/server/workspace/memory/run.ts +84 -0
- package/server/workspace/memory/topic-cluster.ts +218 -0
- package/server/workspace/memory/topic-detect.ts +67 -0
- package/server/workspace/memory/topic-index-hook.ts +128 -0
- package/server/workspace/memory/topic-io.ts +180 -0
- package/server/workspace/memory/topic-migrate.ts +248 -0
- package/server/workspace/memory/topic-run.ts +172 -0
- package/server/workspace/memory/topic-swap.ts +135 -0
- package/server/workspace/memory/topic-types.ts +142 -0
- package/server/workspace/memory/types.ts +83 -0
- package/server/workspace/news/reader.ts +4 -5
- package/server/workspace/paths.ts +124 -47
- package/server/workspace/roles.ts +2 -11
- package/server/workspace/skills/parser.ts +38 -55
- package/server/workspace/skills/user-tasks.ts +1 -2
- package/server/workspace/skills-preset/mc-library/SKILL.md +188 -0
- package/server/workspace/skills-preset.ts +196 -0
- package/server/workspace/sources/fetchers/githubIssues.ts +13 -11
- package/server/workspace/sources/fetchers/index.ts +1 -1
- package/server/workspace/sources/fetchers/rssParser.ts +1 -1
- package/server/workspace/sources/pipeline/index.ts +2 -2
- package/server/workspace/sources/pipeline/notify.ts +3 -3
- package/server/workspace/sources/pipeline/write.ts +2 -2
- package/server/workspace/sources/registry.ts +39 -61
- package/server/workspace/sources/robots.ts +1 -1
- package/server/workspace/tool-trace/classify.ts +2 -1
- package/server/workspace/tool-trace/index.ts +1 -1
- package/server/workspace/tool-trace/writeSearch.ts +6 -1
- package/server/workspace/wiki-backlinks/index.ts +19 -7
- package/server/workspace/wiki-backlinks/sessionBacklinks.ts +1 -0
- package/server/workspace/wiki-history/hook/snapshot.mjs +98 -0
- package/server/workspace/wiki-history/hook/snapshot.ts +135 -0
- package/server/workspace/wiki-history/provision.ts +181 -0
- package/server/workspace/wiki-pages/io.ts +217 -0
- package/server/workspace/wiki-pages/snapshot.ts +380 -0
- package/server/workspace/workspace.ts +75 -13
- package/src/App.vue +115 -40
- package/src/_runtime/protocol-vue.ts +21 -0
- package/src/_runtime/vue.ts +22 -0
- package/src/components/ChatInput.vue +14 -10
- package/src/components/CopyChatButton.vue +76 -0
- package/src/components/FileContentRenderer.vue +67 -14
- package/src/components/FileTree.vue +2 -2
- package/src/components/FilesView.vue +17 -1
- package/src/components/NewsView.vue +16 -2
- package/src/components/NotificationBell.vue +320 -93
- package/src/components/PageChatComposer.vue +5 -4
- package/src/components/PluginLauncher.vue +42 -6
- package/src/components/PluginScopedRoot.vue +87 -0
- package/src/components/RoleSelector.vue +12 -1
- package/src/components/RolesView.vue +562 -0
- package/src/components/SentAttachmentChip.vue +102 -0
- package/src/components/SessionHistoryPanel.vue +109 -20
- package/src/components/SessionRoleIcon.vue +7 -4
- package/src/components/SessionSidebar.vue +20 -7
- package/src/components/SessionTabBar.vue +1 -1
- package/src/components/SettingsMcpTab.vue +4 -4
- package/src/components/SettingsModal.vue +2 -0
- package/src/components/SidebarHeader.vue +16 -5
- package/src/components/SourcesManager.vue +23 -9
- package/src/components/SourcesView.vue +1 -1
- package/src/components/StackView.vue +102 -6
- package/src/components/SuggestionsPanel.vue +105 -16
- package/src/components/SystemFileBanner.vue +1 -1
- package/src/components/TodoExplorer.vue +4 -5
- package/src/components/todo/TodoAddDialog.vue +2 -3
- package/src/components/todo/TodoEditDialog.vue +1 -2
- package/src/components/todo/TodoEditPanel.vue +2 -3
- package/src/components/todo/TodoKanbanView.vue +8 -5
- package/src/components/todo/TodoListView.vue +3 -5
- package/src/components/todo/TodoTableView.vue +7 -5
- package/src/composables/useAccountingChannel.ts +58 -0
- package/src/composables/useActiveSession.ts +4 -25
- package/src/composables/useAppApi.ts +6 -44
- package/src/composables/useClipboardCopy.ts +3 -20
- package/src/composables/useContentDisplay.ts +33 -2
- package/src/composables/useDevPluginReload.ts +23 -0
- package/src/composables/useDynamicFavicon.ts +5 -31
- package/src/composables/useEventListeners.ts +0 -20
- package/src/composables/useExpandedDirs.ts +4 -15
- package/src/composables/useFaviconState.ts +12 -46
- package/src/composables/useFileChange.ts +53 -0
- package/src/composables/useFreshPluginData.ts +6 -43
- package/src/composables/useHealth.ts +14 -43
- package/src/composables/useImageErrorRepair.ts +104 -0
- package/src/composables/useLatestDaily.ts +40 -0
- package/src/composables/useMarkdownDoc.ts +39 -0
- package/src/composables/useMarkdownLinkHandler.ts +1 -1
- package/src/composables/useMcpTools.ts +3 -16
- package/src/composables/useNotifications.ts +138 -112
- package/src/composables/usePdfDownload.ts +17 -3
- package/src/composables/usePendingCalls.ts +8 -26
- package/src/composables/usePluginErrorBoundary.ts +68 -0
- package/src/composables/usePubSub.ts +9 -17
- package/src/composables/useRunElapsed.ts +5 -22
- package/src/composables/useSandboxStatus.ts +4 -20
- package/src/composables/useSessionDerived.ts +7 -15
- package/src/composables/useSessionHistory.ts +70 -29
- package/src/composables/useSessionSync.ts +25 -3
- package/src/composables/useSkillsList.ts +59 -0
- package/src/composables/useTranslatedQueries.ts +109 -0
- package/src/config/apiRoutes.ts +181 -80
- package/src/config/historyFilters.ts +5 -3
- package/src/config/hostEvents.ts +17 -0
- package/src/config/mcpCatalog.ts +277 -5
- package/src/config/pubsubChannels.ts +134 -12
- package/src/config/roles.ts +212 -147
- package/src/config/systemFileDescriptors.ts +5 -5
- package/src/config/toolNames.ts +52 -30
- package/src/config/workspacePaths.ts +26 -2
- package/src/lang/de.ts +483 -27
- package/src/lang/en.ts +448 -27
- package/src/lang/es.ts +474 -27
- package/src/lang/fr.ts +476 -27
- package/src/lang/ja.ts +465 -27
- package/src/lang/ko.ts +466 -27
- package/src/lang/pt-BR.ts +473 -27
- package/src/lang/zh.ts +463 -27
- package/src/lib/vue-i18n.ts +1 -1
- package/src/lib/wiki-page/slug.ts +66 -0
- package/src/main.ts +85 -0
- package/src/plugins/_extras.ts +58 -0
- package/src/plugins/_generated/metas.ts +42 -0
- package/src/plugins/_generated/registrations.ts +44 -0
- package/src/plugins/_generated/server-bindings.ts +47 -0
- package/src/plugins/accounting/Preview.vue +106 -0
- package/src/plugins/accounting/View.vue +632 -0
- package/src/plugins/accounting/actions.ts +34 -0
- package/src/plugins/accounting/api.ts +301 -0
- package/src/plugins/accounting/components/AccountEditor.vue +250 -0
- package/src/plugins/accounting/components/AccountRow.vue +50 -0
- package/src/plugins/accounting/components/AccountsList.vue +102 -0
- package/src/plugins/accounting/components/AccountsModal.vue +300 -0
- package/src/plugins/accounting/components/BalanceSheet.vue +186 -0
- package/src/plugins/accounting/components/BookSettings.vue +284 -0
- package/src/plugins/accounting/components/BookSwitcher.vue +78 -0
- package/src/plugins/accounting/components/DateRangePicker.vue +140 -0
- package/src/plugins/accounting/components/JournalEntryForm.vue +504 -0
- package/src/plugins/accounting/components/JournalList.vue +553 -0
- package/src/plugins/accounting/components/Ledger.vue +206 -0
- package/src/plugins/accounting/components/NewBookForm.vue +211 -0
- package/src/plugins/accounting/components/OpeningBalancesForm.vue +271 -0
- package/src/plugins/accounting/components/ProfitLoss.vue +160 -0
- package/src/plugins/accounting/components/accountDraft.ts +13 -0
- package/src/plugins/accounting/components/accountNumbering.ts +103 -0
- package/src/plugins/accounting/components/accountValidation.ts +75 -0
- package/src/plugins/accounting/components/useLatestRequest.ts +44 -0
- package/src/plugins/accounting/countries.ts +158 -0
- package/src/plugins/accounting/currencies.ts +64 -0
- package/src/plugins/accounting/dates.ts +51 -0
- package/src/plugins/accounting/definition.ts +199 -0
- package/src/plugins/accounting/fiscalYear.ts +136 -0
- package/src/plugins/accounting/index.ts +49 -0
- package/src/plugins/accounting/meta.ts +91 -0
- package/src/plugins/accounting/timeSeriesEnums.ts +16 -0
- package/src/plugins/api.ts +125 -0
- package/src/plugins/canvas/View.vue +38 -28
- package/src/plugins/canvas/definition.ts +10 -8
- package/src/plugins/canvas/index.ts +15 -8
- package/src/plugins/canvas/meta.ts +12 -0
- package/src/plugins/chart/Preview.vue +1 -1
- package/src/plugins/chart/View.vue +2 -2
- package/src/plugins/chart/definition.ts +12 -2
- package/src/plugins/chart/index.ts +15 -7
- package/src/plugins/chart/meta.ts +18 -0
- package/src/plugins/editImages/definition.ts +44 -0
- package/src/plugins/editImages/index.ts +43 -0
- package/src/plugins/editImages/meta.ts +5 -0
- package/src/plugins/generateImage/View.vue +3 -1
- package/src/plugins/generateImage/definition.ts +2 -0
- package/src/plugins/generateImage/index.ts +13 -5
- package/src/plugins/generateImage/meta.ts +5 -0
- package/src/plugins/index.ts +35 -0
- package/src/plugins/manageRoles/Preview.vue +7 -4
- package/src/plugins/manageRoles/View.vue +12 -8
- package/src/plugins/manageRoles/definition.ts +6 -0
- package/src/plugins/manageRoles/index.ts +7 -6
- package/src/plugins/manageSkills/View.vue +11 -7
- package/src/plugins/manageSkills/definition.ts +4 -1
- package/src/plugins/manageSkills/index.ts +14 -7
- package/src/plugins/manageSkills/meta.ts +21 -0
- package/src/plugins/manageSource/definition.ts +4 -1
- package/src/plugins/manageSource/index.ts +15 -7
- package/src/plugins/manageSource/meta.ts +21 -0
- package/src/plugins/markdown/Preview.vue +10 -8
- package/src/plugins/markdown/View.vue +84 -17
- package/src/plugins/markdown/definition.ts +7 -1
- package/src/plugins/markdown/index.ts +15 -8
- package/src/plugins/markdown/meta.ts +16 -0
- package/src/plugins/meta-types.ts +97 -0
- package/src/plugins/metas.ts +224 -0
- package/src/plugins/presentForm/Preview.vue +4 -15
- package/src/plugins/presentForm/View.vue +35 -78
- package/src/plugins/presentForm/definition.ts +7 -6
- package/src/plugins/presentForm/index.ts +12 -5
- package/src/plugins/presentForm/meta.ts +11 -0
- package/src/plugins/presentForm/plugin.ts +8 -9
- package/src/plugins/presentForm/types.ts +0 -24
- package/src/plugins/presentHtml/Preview.vue +1 -8
- package/src/plugins/presentHtml/View.vue +401 -30
- package/src/plugins/presentHtml/definition.ts +8 -5
- package/src/plugins/presentHtml/index.ts +15 -8
- package/src/plugins/presentHtml/meta.ts +14 -0
- package/src/plugins/presentMulmoScript/View.vue +327 -107
- package/src/plugins/presentMulmoScript/definition.ts +34 -7
- package/src/plugins/presentMulmoScript/helpers.ts +4 -5
- package/src/plugins/presentMulmoScript/index.ts +20 -7
- package/src/plugins/presentMulmoScript/meta.ts +52 -0
- package/src/plugins/scheduler/AutomationsPreview.vue +2 -8
- package/src/plugins/scheduler/Preview.vue +5 -2
- package/src/plugins/scheduler/TasksTab.vue +16 -36
- package/src/plugins/scheduler/View.vue +22 -54
- package/src/plugins/scheduler/automationsDefinition.ts +14 -9
- package/src/plugins/scheduler/automationsMeta.ts +5 -0
- package/src/plugins/scheduler/calendarDefinition.ts +4 -7
- package/src/plugins/scheduler/calendarMeta.ts +28 -0
- package/src/plugins/scheduler/formatSchedule.ts +6 -24
- package/src/plugins/scheduler/index.ts +26 -52
- package/src/plugins/scope.ts +57 -0
- package/src/plugins/server-bindings-types.ts +38 -0
- package/src/plugins/server.ts +32 -0
- package/src/plugins/skill/Preview.vue +25 -0
- package/src/plugins/skill/View.vue +125 -0
- package/src/plugins/skill/definition.ts +23 -0
- package/src/plugins/skill/index.ts +36 -0
- package/src/plugins/skill/plugin.ts +31 -0
- package/src/plugins/skill/types.ts +21 -0
- package/src/plugins/spreadsheet/Preview.vue +1 -3
- package/src/plugins/spreadsheet/View.vue +29 -49
- package/src/plugins/spreadsheet/cellHighlights.ts +2 -3
- package/src/plugins/spreadsheet/definition.ts +5 -2
- package/src/plugins/spreadsheet/index.ts +15 -8
- package/src/plugins/spreadsheet/keyboardNav.ts +38 -0
- package/src/plugins/spreadsheet/meta.ts +14 -0
- package/src/plugins/textResponse/Preview.vue +9 -1
- package/src/plugins/textResponse/View.vue +59 -8
- package/src/plugins/textResponse/index.ts +11 -3
- package/src/plugins/textResponse/plugin.ts +8 -10
- package/src/plugins/textResponse/types.ts +28 -0
- package/src/plugins/wiki/Preview.vue +6 -4
- package/src/plugins/wiki/View.vue +463 -254
- package/src/plugins/wiki/components/WikiPageBody.vue +159 -0
- package/src/plugins/wiki/helpers.ts +17 -0
- package/src/plugins/wiki/history/HistoryDetail.vue +325 -0
- package/src/plugins/wiki/history/HistoryTab.vue +167 -0
- package/src/plugins/wiki/history/RestoreConfirm.vue +63 -0
- package/src/plugins/wiki/history/api.ts +52 -0
- package/src/plugins/wiki/history/diff.ts +145 -0
- package/src/plugins/wiki/index.ts +42 -32
- package/src/plugins/wiki/meta.ts +10 -0
- package/src/plugins/wiki/pageEditLoader.ts +53 -0
- package/src/plugins/wiki/route.ts +8 -0
- package/src/router/guards.ts +2 -1
- package/src/router/index.ts +19 -0
- package/src/router/pageRoutes.ts +1 -0
- package/src/tools/index.ts +50 -51
- package/src/tools/runtimeLoader.ts +141 -0
- package/src/tools/types.ts +44 -1
- package/src/types/notification.ts +23 -0
- package/src/types/pastedFile.ts +10 -0
- package/src/types/session.ts +61 -3
- package/src/types/sse.ts +21 -6
- package/src/utils/agent/eventDispatch.ts +12 -9
- package/src/utils/agent/pastedAttachment.ts +35 -0
- package/src/utils/agent/request.ts +32 -3
- package/src/utils/agent/toolCalls.ts +7 -1
- package/src/utils/api.ts +1 -1
- package/src/utils/chat/exportMarkdown.ts +243 -0
- package/src/utils/errors.ts +10 -2
- package/src/utils/files/expandedDirs.ts +1 -1
- package/src/utils/filesPreview/todoPreview.ts +13 -2
- package/src/utils/format/date.ts +1 -3
- package/src/utils/format/jsonSyntax.ts +5 -0
- package/src/utils/html/iframeHeightReporterScript.ts +62 -0
- package/src/utils/html/previewCsp.ts +29 -2
- package/src/utils/image/htmlSrcAttrs.ts +122 -0
- package/src/utils/image/imageRepairInlineScript.ts +115 -0
- package/src/utils/image/resolve.ts +17 -3
- package/src/utils/image/rewriteMarkdownImageRefs.ts +62 -9
- package/src/utils/markdown/frontmatter.ts +125 -0
- package/src/utils/markdown/taskList.ts +7 -2
- package/src/utils/plugin/runtime.ts +132 -0
- package/src/utils/session/mergeSessions.ts +40 -37
- package/src/utils/session/sessionEntries.ts +74 -18
- package/src/utils/session/sessionHelpers.ts +54 -10
- package/src/utils/tools/result.ts +76 -14
- package/src/vite-env.d.ts +6 -0
- package/client/assets/html2canvas-Cx501zZr-Bug0qRNv.js +0 -5
- package/client/assets/index-CY-WpQUm.css +0 -2
- package/client/assets/index-DbTz2Mfs.js +0 -4911
- package/client/assets/material-symbols-outlined-NzYEeyps.woff2 +0 -0
- package/server/api/routes/html.ts +0 -114
- package/server/api/routes/todos.ts +0 -293
- package/server/api/routes/todosColumnsHandlers.ts +0 -333
- package/server/api/routes/todosHandlers.ts +0 -274
- package/server/api/routes/todosItemsHandlers.ts +0 -386
- package/server/utils/files/todos-io.ts +0 -29
- package/src/components/NotificationToast.vue +0 -75
- package/src/plugins/editImage/definition.ts +0 -27
- package/src/plugins/editImage/index.ts +0 -37
- package/src/plugins/presentHtml/helpers.ts +0 -72
- package/src/plugins/scheduler/LegacySchedulerView.vue +0 -32
- package/src/plugins/scheduler/legacyShape.ts +0 -34
- package/src/plugins/todo/Preview.vue +0 -68
- package/src/plugins/todo/View.vue +0 -378
- package/src/plugins/todo/composables/useTodos.ts +0 -179
- package/src/plugins/todo/definition.ts +0 -45
- package/src/plugins/todo/index.ts +0 -62
- package/src/plugins/todo/labels.ts +0 -163
- package/src/plugins/todo/priority.ts +0 -98
- package/src/plugins/todo/viewModes.ts +0 -19
- package/src/plugins/wiki/definition.ts +0 -25
- package/src/tools/legacyPluginNames.ts +0 -13
- package/src/utils/format/frontmatter.ts +0 -80
- package/src/utils/image/rewriteHtmlImageRefs.ts +0 -50
- package/src/utils/notification/dispatch.ts +0 -58
- /package/client/assets/{purify.es-Fx1Nqyry-BwJECkqS.js → purify.es-Fx1Nqyry-BSVNht6S.js} +0 -0
- /package/src/plugins/{editImage → editImages}/Preview.vue +0 -0
- /package/src/plugins/{editImage → editImages}/View.vue +0 -0
- /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
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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 }>(
|
|
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 =
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
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<
|
|
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
|
|
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
|
|
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:
|
|
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 {
|
|
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
|
|
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
|
+
};
|