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