@dxos/plugin-assistant 0.8.4-main.9be5663bfe → 0.8.4-main.abd8ff62ef
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/dist/lib/browser/AssistantSettings-GG52BLKS.mjs +40 -0
- package/dist/lib/browser/AssistantSettings-GG52BLKS.mjs.map +7 -0
- package/dist/lib/browser/blueprints/index.mjs +26 -3
- package/dist/lib/browser/blueprints/index.mjs.map +4 -4
- package/dist/lib/browser/{chunk-ATHYBVGN.mjs → chunk-DVOOFAWU.mjs} +4 -5
- package/dist/lib/browser/chunk-DVOOFAWU.mjs.map +7 -0
- package/dist/lib/browser/chunk-M55MBYG7.mjs +932 -0
- package/dist/lib/browser/chunk-M55MBYG7.mjs.map +7 -0
- package/dist/lib/browser/{chunk-RUV2WOQH.mjs → chunk-SEMCG4ZK.mjs} +58 -17
- package/dist/lib/browser/chunk-SEMCG4ZK.mjs.map +7 -0
- package/dist/lib/browser/chunk-VK53MITK.mjs +2300 -0
- package/dist/lib/browser/chunk-VK53MITK.mjs.map +7 -0
- package/dist/lib/browser/cli/index.mjs +73 -0
- package/dist/lib/browser/cli/index.mjs.map +7 -0
- package/dist/lib/browser/components/index.mjs +20 -0
- package/dist/lib/browser/components/index.mjs.map +7 -0
- package/dist/lib/browser/{create-chat-LBZHGVSN.mjs → create-chat-E2ZLVTLP.mjs} +4 -13
- package/dist/lib/browser/create-chat-E2ZLVTLP.mjs.map +7 -0
- package/dist/lib/browser/{ensure-companion-chat-FR4AWZ2P.mjs → ensure-companion-chat-7GDMXSQW.mjs} +4 -4
- package/dist/lib/browser/ensure-companion-chat-7GDMXSQW.mjs.map +7 -0
- package/dist/lib/browser/hooks/index.mjs +39 -0
- package/dist/lib/browser/hooks/index.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +43 -3233
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{on-create-space-54RNX5JI.mjs → on-create-space-4J3KTNAJ.mjs} +3 -3
- package/dist/lib/browser/{on-create-space-54RNX5JI.mjs.map → on-create-space-4J3KTNAJ.mjs.map} +1 -1
- package/dist/lib/browser/operations/index.mjs +3 -3
- package/dist/lib/browser/operations/index.mjs.map +3 -3
- package/dist/lib/browser/{resolve-navigation-targets-NZOD66NY.mjs → resolve-navigation-targets-3ZPQE6SZ.mjs} +3 -3
- package/dist/lib/browser/{resolve-navigation-targets-NZOD66NY.mjs.map → resolve-navigation-targets-3ZPQE6SZ.mjs.map} +1 -1
- package/dist/lib/browser/{run-prompt-in-new-chat-4YQ37XIS.mjs → run-prompt-in-new-chat-AA3KPBDN.mjs} +9 -39
- package/dist/lib/browser/run-prompt-in-new-chat-AA3KPBDN.mjs.map +7 -0
- package/dist/lib/browser/{set-current-chat-WJI3WAVM.mjs → set-current-chat-P4VHI3YF.mjs} +4 -4
- package/dist/lib/browser/set-current-chat-P4VHI3YF.mjs.map +7 -0
- package/dist/lib/browser/translations.mjs +172 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +1 -3
- package/dist/lib/browser/{update-chat-name-3Y36KFAS.mjs → update-chat-name-VWKNUON7.mjs} +7 -22
- package/dist/lib/browser/update-chat-name-VWKNUON7.mjs.map +7 -0
- package/dist/lib/node-esm/AssistantSettings-23A5IMHS.mjs +41 -0
- package/dist/lib/node-esm/AssistantSettings-23A5IMHS.mjs.map +7 -0
- package/dist/lib/node-esm/blueprints/index.mjs +26 -3
- package/dist/lib/node-esm/blueprints/index.mjs.map +4 -4
- package/dist/lib/node-esm/chunk-FWC3ZGPH.mjs +933 -0
- package/dist/lib/node-esm/chunk-FWC3ZGPH.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-JKEB3NFZ.mjs +2302 -0
- package/dist/lib/node-esm/chunk-JKEB3NFZ.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-PXAJSTGZ.mjs → chunk-MBDVPB4V.mjs} +4 -5
- package/dist/lib/node-esm/chunk-MBDVPB4V.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-PY4X6FJT.mjs → chunk-XAFVSEUJ.mjs} +58 -17
- package/dist/lib/node-esm/chunk-XAFVSEUJ.mjs.map +7 -0
- package/dist/lib/node-esm/cli/index.mjs +74 -0
- package/dist/lib/node-esm/cli/index.mjs.map +7 -0
- package/dist/lib/node-esm/components/index.mjs +21 -0
- package/dist/lib/node-esm/components/index.mjs.map +7 -0
- package/dist/lib/node-esm/{create-chat-3BEG4R6J.mjs → create-chat-UQQ3542N.mjs} +4 -13
- package/dist/lib/node-esm/create-chat-UQQ3542N.mjs.map +7 -0
- package/dist/lib/node-esm/{ensure-companion-chat-BLP7NT32.mjs → ensure-companion-chat-LVCPD4DJ.mjs} +4 -4
- package/dist/lib/node-esm/ensure-companion-chat-LVCPD4DJ.mjs.map +7 -0
- package/dist/lib/node-esm/hooks/index.mjs +40 -0
- package/dist/lib/node-esm/hooks/index.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +43 -3233
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{on-create-space-YRPZ6HZY.mjs → on-create-space-M63UBTTT.mjs} +3 -3
- package/dist/lib/node-esm/{on-create-space-YRPZ6HZY.mjs.map → on-create-space-M63UBTTT.mjs.map} +1 -1
- package/dist/lib/node-esm/operations/index.mjs +3 -3
- package/dist/lib/node-esm/operations/index.mjs.map +3 -3
- package/dist/lib/node-esm/{resolve-navigation-targets-3PPK7XLH.mjs → resolve-navigation-targets-HO77CAFT.mjs} +3 -3
- package/dist/lib/node-esm/{resolve-navigation-targets-3PPK7XLH.mjs.map → resolve-navigation-targets-HO77CAFT.mjs.map} +1 -1
- package/dist/lib/node-esm/{run-prompt-in-new-chat-2IJBSDTM.mjs → run-prompt-in-new-chat-RIRYYYPK.mjs} +9 -39
- package/dist/lib/node-esm/run-prompt-in-new-chat-RIRYYYPK.mjs.map +7 -0
- package/dist/lib/node-esm/{set-current-chat-KBMMZULR.mjs → set-current-chat-Z7GJ52VX.mjs} +4 -4
- package/dist/lib/node-esm/set-current-chat-Z7GJ52VX.mjs.map +7 -0
- package/dist/lib/node-esm/translations.mjs +173 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +1 -3
- package/dist/lib/node-esm/{update-chat-name-HM2P4NSI.mjs → update-chat-name-GV4HX32Z.mjs} +7 -22
- package/dist/lib/node-esm/update-chat-name-GV4HX32Z.mjs.map +7 -0
- package/dist/types/src/AssistantPlugin.d.ts +1 -0
- package/dist/types/src/AssistantPlugin.d.ts.map +1 -1
- package/dist/types/src/AssistantPlugin.node.d.ts +4 -0
- package/dist/types/src/AssistantPlugin.node.d.ts.map +1 -0
- package/dist/types/src/AssistantPlugin.test.d.ts +2 -0
- package/dist/types/src/AssistantPlugin.test.d.ts.map +1 -0
- package/dist/types/src/blueprints/assistant/blueprint.d.ts +2 -2
- package/dist/types/src/blueprints/assistant/blueprint.d.ts.map +1 -1
- package/dist/types/src/capabilities/ai-service.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/companion-chat-provisioner.d.ts.map +1 -1
- package/dist/types/src/capabilities/edge-model-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +5 -17
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/local-model-resolver.d.ts +6 -3
- package/dist/types/src/capabilities/local-model-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/markdown.d.ts +1 -1
- package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
- package/dist/types/src/capabilities/migrations.d.ts +1 -1
- package/dist/types/src/capabilities/migrations.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/settings.d.ts +1 -13
- package/dist/types/src/capabilities/settings.d.ts.map +1 -1
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/capabilities/toolkit.d.ts.map +1 -1
- package/dist/types/src/cli/index.d.ts +2 -0
- package/dist/types/src/cli/index.d.ts.map +1 -0
- package/dist/types/src/cli/plugin.d.ts +10 -0
- package/dist/types/src/cli/plugin.d.ts.map +1 -0
- package/dist/types/src/components/AssistantSettings/AssistantSettings.d.ts +1 -1
- package/dist/types/src/components/AssistantSettings/AssistantSettings.d.ts.map +1 -1
- package/dist/types/src/components/AssistantSettings/AssistantSettings.stories.d.ts +1 -539
- package/dist/types/src/components/AssistantSettings/AssistantSettings.stories.d.ts.map +1 -1
- package/dist/types/src/components/Chat/Chat.d.ts +32 -42
- package/dist/types/src/components/Chat/Chat.d.ts.map +1 -1
- package/dist/types/src/components/Chat/context.d.ts +29 -0
- package/dist/types/src/components/Chat/context.d.ts.map +1 -0
- package/dist/types/src/components/ChatPrompt/ChatActions.d.ts.map +1 -1
- package/dist/types/src/components/ChatPrompt/ChatMcpErrors.d.ts +12 -0
- package/dist/types/src/components/ChatPrompt/ChatMcpErrors.d.ts.map +1 -0
- package/dist/types/src/components/ChatPrompt/ChatOptions.d.ts +6 -2
- package/dist/types/src/components/ChatPrompt/ChatOptions.d.ts.map +1 -1
- package/dist/types/src/components/ChatPrompt/ChatOptions.stories.d.ts +19 -0
- package/dist/types/src/components/ChatPrompt/ChatOptions.stories.d.ts.map +1 -0
- package/dist/types/src/components/ChatPrompt/ChatPresets.d.ts.map +1 -1
- package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts +28 -0
- package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts.map +1 -0
- package/dist/types/src/components/ChatPrompt/ChatReferences.d.ts.map +1 -1
- package/dist/types/src/components/ChatPrompt/ChatStatus.d.ts +20 -0
- package/dist/types/src/components/ChatPrompt/ChatStatus.d.ts.map +1 -0
- package/dist/types/src/components/ChatPrompt/ChatStatusIndicator.d.ts.map +1 -1
- package/dist/types/src/components/ChatPrompt/index.d.ts +3 -0
- package/dist/types/src/components/ChatPrompt/index.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/Anchor.stories.d.ts +14 -0
- package/dist/types/src/components/ChatThread/Anchor.stories.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/ChatThread.d.ts +6 -3
- package/dist/types/src/components/ChatThread/ChatThread.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/ChatThread.stories.d.ts +4 -541
- package/dist/types/src/components/ChatThread/ChatThread.stories.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/Link.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/MarkdownStream.stories.d.ts +9 -540
- package/dist/types/src/components/ChatThread/MarkdownStream.stories.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/registry.d.ts +18 -0
- package/dist/types/src/components/ChatThread/registry.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/sync.d.ts +40 -14
- package/dist/types/src/components/ChatThread/sync.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/tool-widget-state.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/FallbackWidget.d.ts +4 -4
- package/dist/types/src/components/ChatThread/widgets/FallbackWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/ReasoningWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/ReasoningWidget.stories.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/ReferenceWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/SelectWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/StatsWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/StatusWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/SuggestionWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/SummaryWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/ToolWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/ToolWidget.stories.d.ts +1 -539
- package/dist/types/src/components/ChatThread/widgets/ToolWidget.stories.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/defaults.d.ts +5 -0
- package/dist/types/src/components/ChatThread/widgets/defaults.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/widgets/index.d.ts +1 -2
- package/dist/types/src/components/ChatThread/widgets/index.d.ts.map +1 -1
- package/dist/types/src/components/ProcessTree/ProcessTree.d.ts +2 -1
- package/dist/types/src/components/ProcessTree/ProcessTree.d.ts.map +1 -1
- package/dist/types/src/components/ProcessTree/ProcessTree.stories.d.ts +0 -1
- package/dist/types/src/components/ProcessTree/ProcessTree.stories.d.ts.map +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts +2 -2
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts.map +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts +1 -539
- package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts +3 -3
- package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts.map +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts +1 -539
- package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts.map +1 -1
- package/dist/types/src/components/TemplateEditor/extensions/handlebars-extension.d.ts.map +1 -1
- package/dist/types/src/components/TemplateEditor/extensions/xml-extension.d.ts.map +1 -1
- package/dist/types/src/components/ToolBlock/ToolBlock.d.ts +4 -4
- package/dist/types/src/components/ToolBlock/ToolBlock.d.ts.map +1 -1
- package/dist/types/src/components/Toolbox/Toolbox.d.ts +3 -3
- package/dist/types/src/components/Toolbox/Toolbox.d.ts.map +1 -1
- package/dist/types/src/components/Toolbox/Toolbox.stories.d.ts +1 -539
- package/dist/types/src/components/Toolbox/Toolbox.stories.d.ts.map +1 -1
- package/dist/types/src/containers/AgentArticle/AgentArticle.d.ts +2 -2
- package/dist/types/src/containers/AgentArticle/AgentArticle.d.ts.map +1 -1
- package/dist/types/src/containers/AgentArticle/AgentArticle.stories.d.ts +7 -540
- package/dist/types/src/containers/AgentArticle/AgentArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/AgentProperties/AgentProperties.d.ts +1 -1
- package/dist/types/src/containers/AgentProperties/AgentProperties.d.ts.map +1 -1
- package/dist/types/src/containers/AgentProperties/AgentProperties.stories.d.ts +1 -539
- package/dist/types/src/containers/AgentProperties/AgentProperties.stories.d.ts.map +1 -1
- package/dist/types/src/containers/BlueprintArticle/BlueprintArticle.d.ts +1 -1
- package/dist/types/src/containers/BlueprintArticle/BlueprintArticle.d.ts.map +1 -1
- package/dist/types/src/containers/ChatCompanion/ChatCompanion.d.ts +1 -1
- package/dist/types/src/containers/ChatContainer/ChatContainer.d.ts.map +1 -1
- package/dist/types/src/containers/ChatDialog/ChatDialog.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts +6 -0
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineArticle/index.d.ts +2 -0
- package/dist/types/src/containers/RoutineArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineList/RoutineList.d.ts +6 -0
- package/dist/types/src/containers/RoutineList/RoutineList.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineList/RoutineList.stories.d.ts +21 -0
- package/dist/types/src/containers/RoutineList/RoutineList.stories.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineList/index.d.ts +2 -0
- package/dist/types/src/containers/RoutineList/index.d.ts.map +1 -0
- package/dist/types/src/containers/TracePanel/TracePanel.d.ts +6 -4
- package/dist/types/src/containers/TracePanel/TracePanel.d.ts.map +1 -1
- package/dist/types/src/containers/TracePanel/TracePanel.stories.d.ts +13 -0
- package/dist/types/src/containers/TracePanel/TracePanel.stories.d.ts.map +1 -0
- package/dist/types/src/containers/TracePanel/dxn-extractor.d.ts +1 -1
- package/dist/types/src/containers/TracePanel/dxn-extractor.d.ts.map +1 -1
- package/dist/types/src/containers/TracePanel/execution-graph.d.ts +97 -0
- package/dist/types/src/containers/TracePanel/execution-graph.d.ts.map +1 -0
- package/dist/types/src/containers/TracePanel/execution-graph.test.d.ts +2 -0
- package/dist/types/src/containers/TracePanel/execution-graph.test.d.ts.map +1 -0
- package/dist/types/src/containers/TracePanel/index.d.ts.map +1 -1
- package/dist/types/src/containers/TracePanel/testing/index.d.ts +3 -0
- package/dist/types/src/containers/TracePanel/testing/index.d.ts.map +1 -0
- package/dist/types/src/containers/TracePanel/testing/simulated-agent.d.ts +14 -0
- package/dist/types/src/containers/TracePanel/testing/simulated-agent.d.ts.map +1 -0
- package/dist/types/src/containers/TracePanel/testing/snapshot-playback.d.ts +12 -0
- package/dist/types/src/containers/TracePanel/testing/snapshot-playback.d.ts.map +1 -0
- package/dist/types/src/containers/TriggerStatus/TriggerStatus.d.ts +3 -2
- package/dist/types/src/containers/TriggerStatus/TriggerStatus.d.ts.map +1 -1
- package/dist/types/src/containers/TriggerStatus/index.d.ts +1 -1
- package/dist/types/src/containers/TriggerStatus/index.d.ts.map +1 -1
- package/dist/types/src/containers/index.d.ts +2 -2
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/extensions/prompt-extension.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useBlueprintRegistry.d.ts +1 -1
- package/dist/types/src/hooks/useBlueprintRegistry.d.ts.map +1 -1
- package/dist/types/src/hooks/useChatKeymap.d.ts +12 -0
- package/dist/types/src/hooks/useChatKeymap.d.ts.map +1 -0
- package/dist/types/src/hooks/useChatProcessor.d.ts +1 -1
- package/dist/types/src/hooks/useChatProcessor.d.ts.map +1 -1
- package/dist/types/src/hooks/useChatServices.d.ts.map +1 -1
- package/dist/types/src/hooks/useChatToolbarActions.d.ts.map +1 -1
- package/dist/types/src/hooks/useContextBinder.d.ts.map +1 -1
- package/dist/types/src/hooks/useContextObjects.d.ts.map +1 -1
- package/dist/types/src/hooks/useDebug.d.ts +10 -0
- package/dist/types/src/hooks/useDebug.d.ts.map +1 -0
- package/dist/types/src/hooks/useFilteredTypes.d.ts.map +1 -1
- package/dist/types/src/hooks/useFlush.d.ts +1 -1
- package/dist/types/src/hooks/useFlush.d.ts.map +1 -1
- package/dist/types/src/hooks/usePresets.d.ts.map +1 -1
- package/dist/types/src/hooks/useReferencesProvider.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -5
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/operations/create-chat.d.ts +1 -1
- package/dist/types/src/operations/create-chat.d.ts.map +1 -1
- package/dist/types/src/operations/definitions.d.ts +24 -19
- package/dist/types/src/operations/definitions.d.ts.map +1 -1
- package/dist/types/src/operations/ensure-companion-chat.d.ts +1 -1
- package/dist/types/src/operations/ensure-companion-chat.d.ts.map +1 -1
- package/dist/types/src/operations/index.d.ts +1 -1
- package/dist/types/src/operations/index.d.ts.map +1 -1
- package/dist/types/src/operations/on-create-space.d.ts +1 -1
- package/dist/types/src/operations/on-create-space.d.ts.map +1 -1
- package/dist/types/src/operations/prompt.test.d.ts +2 -0
- package/dist/types/src/operations/prompt.test.d.ts.map +1 -0
- package/dist/types/src/operations/resolve-navigation-targets.d.ts +1 -1
- package/dist/types/src/operations/resolve-navigation-targets.d.ts.map +1 -1
- package/dist/types/src/operations/run-prompt-in-new-chat.d.ts +1 -1
- package/dist/types/src/operations/run-prompt-in-new-chat.d.ts.map +1 -1
- package/dist/types/src/operations/set-current-chat.d.ts +1 -1
- package/dist/types/src/operations/set-current-chat.d.ts.map +1 -1
- package/dist/types/src/operations/update-chat-name.d.ts +1 -1
- package/dist/types/src/operations/update-chat-name.d.ts.map +1 -1
- package/dist/types/src/processor/presets.d.ts +1 -1
- package/dist/types/src/processor/presets.d.ts.map +1 -1
- package/dist/types/src/processor/processor.d.ts +25 -7
- package/dist/types/src/processor/processor.d.ts.map +1 -1
- package/dist/types/src/queue-logger.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-generator.d.ts.map +1 -1
- package/dist/types/src/testing/test-generator.test.d.ts +2 -0
- package/dist/types/src/testing/test-generator.test.d.ts.map +1 -0
- package/dist/types/src/testing/test-services.d.ts.map +1 -1
- package/dist/types/src/testing/test-trace.d.ts +5 -0
- package/dist/types/src/testing/test-trace.d.ts.map +1 -0
- package/dist/types/src/testing/trace-timeline.test.d.ts +2 -0
- package/dist/types/src/testing/trace-timeline.test.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +2 -539
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Assistant.d.ts +22 -6
- package/dist/types/src/types/Assistant.d.ts.map +1 -1
- package/dist/types/src/types/Settings.d.ts +22 -6
- package/dist/types/src/types/Settings.d.ts.map +1 -1
- package/dist/types/src/types/capabilities.d.ts +1 -13
- package/dist/types/src/types/capabilities.d.ts.map +1 -1
- package/dist/types/src/types/events.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +0 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/service.d.ts +1 -1
- package/dist/types/src/types/service.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +113 -99
- package/src/AssistantPlugin.node.ts +125 -0
- package/src/AssistantPlugin.test.ts +35 -0
- package/src/AssistantPlugin.tsx +22 -16
- package/src/blueprints/assistant/blueprint.test.ts +3 -3
- package/src/blueprints/assistant/blueprint.ts +3 -3
- package/src/capabilities/app-graph-builder.ts +5 -61
- package/src/capabilities/blueprint-definition.ts +2 -4
- package/src/capabilities/index.ts +2 -1
- package/src/capabilities/local-model-resolver.ts +14 -4
- package/src/capabilities/markdown.ts +1 -1
- package/src/capabilities/migrations.ts +1 -7
- package/src/capabilities/operation-handler.ts +1 -1
- package/src/capabilities/react-surface.tsx +38 -28
- package/src/capabilities/toolkit.ts +2 -2
- package/src/{components/Typewriter → cli}/index.ts +1 -1
- package/src/cli/plugin.ts +83 -0
- package/src/components/AssistantSettings/AssistantSettings.stories.tsx +3 -2
- package/src/components/AssistantSettings/AssistantSettings.tsx +22 -111
- package/src/components/Chat/Chat.tsx +82 -286
- package/src/components/Chat/context.ts +39 -0
- package/src/components/ChatPrompt/ChatActions.tsx +10 -10
- package/src/components/ChatPrompt/ChatMcpErrors.tsx +50 -0
- package/src/components/ChatPrompt/ChatOptions.stories.tsx +136 -0
- package/src/components/ChatPrompt/ChatOptions.tsx +229 -37
- package/src/components/ChatPrompt/ChatPrompt.tsx +182 -0
- package/src/components/ChatPrompt/ChatReferences.tsx +1 -1
- package/src/components/ChatPrompt/ChatStatus.tsx +123 -0
- package/src/components/ChatPrompt/index.ts +3 -0
- package/src/components/ChatThread/Anchor.stories.tsx +95 -0
- package/src/components/ChatThread/ChatThread.stories.tsx +39 -29
- package/src/components/ChatThread/ChatThread.tsx +36 -21
- package/src/components/ChatThread/DEBUG.md +41 -0
- package/src/components/ChatThread/MarkdownStream.stories.tsx +43 -5
- package/src/components/ChatThread/registry.tsx +72 -24
- package/src/components/ChatThread/sync.test.ts +175 -15
- package/src/components/ChatThread/sync.ts +87 -102
- package/src/components/ChatThread/testing/reasoning.md +25 -0
- package/src/components/ChatThread/widgets/FallbackWidget.tsx +2 -2
- package/src/components/ChatThread/widgets/ReasoningWidget.stories.tsx +1 -1
- package/src/components/ChatThread/widgets/ReasoningWidget.ts +6 -6
- package/src/components/ChatThread/widgets/ReferenceWidget.ts +3 -1
- package/src/components/ChatThread/widgets/SelectWidget.ts +3 -1
- package/src/components/ChatThread/widgets/StatsWidget.ts +3 -1
- package/src/components/ChatThread/widgets/StatusWidget.ts +3 -3
- package/src/components/ChatThread/widgets/SuggestionWidget.ts +1 -1
- package/src/components/ChatThread/widgets/SummaryWidget.tsx +3 -2
- package/src/components/ChatThread/widgets/ToolWidget.stories.tsx +3 -2
- package/src/components/ChatThread/widgets/ToolWidget.tsx +2 -2
- package/src/components/ChatThread/widgets/defaults.ts +8 -0
- package/src/components/ChatThread/widgets/index.ts +1 -2
- package/src/components/ProcessTree/ProcessTree.stories.tsx +12 -38
- package/src/components/ProcessTree/ProcessTree.tsx +70 -37
- package/src/components/TemplateEditor/TemplateEditor.stories.tsx +3 -2
- package/src/components/TemplateEditor/TemplateEditor.tsx +5 -5
- package/src/components/TemplateEditor/TemplateForm.stories.tsx +4 -3
- package/src/components/TemplateEditor/TemplateForm.tsx +3 -3
- package/src/components/TemplateEditor/extensions/handlebars-extension.ts +1 -1
- package/src/components/ToolBlock/ToolBlock.tsx +2 -2
- package/src/components/Toolbox/Toolbox.stories.tsx +2 -1
- package/src/components/Toolbox/Toolbox.tsx +2 -2
- package/src/containers/AgentArticle/AgentArticle.stories.tsx +40 -25
- package/src/containers/AgentArticle/AgentArticle.tsx +96 -53
- package/src/containers/AgentProperties/AgentProperties.stories.tsx +14 -4
- package/src/containers/AgentProperties/AgentProperties.tsx +46 -88
- package/src/containers/BlueprintArticle/BlueprintArticle.tsx +1 -1
- package/src/containers/ChatCompanion/ChatCompanion.tsx +1 -1
- package/src/containers/ChatContainer/ChatContainer.tsx +16 -6
- package/src/containers/ChatDialog/ChatDialog.tsx +3 -9
- package/src/containers/{PromptArticle/PromptArticle.tsx → RoutineArticle/RoutineArticle.tsx} +4 -4
- package/src/containers/RoutineArticle/index.ts +5 -0
- package/src/containers/{PromptList/PromptList.stories.tsx → RoutineList/RoutineList.stories.tsx} +11 -10
- package/src/containers/{PromptList/PromptList.tsx → RoutineList/RoutineList.tsx} +6 -5
- package/src/containers/RoutineList/index.ts +5 -0
- package/src/containers/TracePanel/TracePanel.stories.tsx +278 -0
- package/src/containers/TracePanel/TracePanel.tsx +95 -318
- package/src/containers/TracePanel/dxn-extractor.test.ts +7 -7
- package/src/containers/TracePanel/dxn-extractor.ts +4 -4
- package/src/containers/TracePanel/execution-graph.test.ts +382 -0
- package/src/containers/TracePanel/execution-graph.ts +579 -0
- package/src/containers/TracePanel/testing/index.ts +6 -0
- package/src/containers/TracePanel/testing/simulated-agent.ts +114 -0
- package/src/containers/TracePanel/testing/snapshot-playback.ts +45 -0
- package/src/containers/TriggerStatus/TriggerStatus.tsx +19 -34
- package/src/containers/TriggerStatus/index.ts +1 -1
- package/src/containers/index.ts +2 -2
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useBlueprintRegistry.ts +1 -1
- package/src/hooks/useChatKeymap.ts +52 -0
- package/src/hooks/useChatProcessor.ts +11 -11
- package/src/hooks/useDebug.ts +38 -0
- package/src/index.ts +8 -6
- package/src/operations/create-chat.ts +1 -2
- package/src/operations/definitions.ts +3 -4
- package/src/operations/ensure-companion-chat.ts +1 -1
- package/src/operations/index.ts +1 -1
- package/src/operations/on-create-space.ts +1 -1
- package/src/operations/prompt.test.ts +77 -0
- package/src/operations/resolve-navigation-targets.ts +1 -1
- package/src/operations/run-prompt-in-new-chat.ts +2 -3
- package/src/operations/set-current-chat.ts +1 -1
- package/src/operations/update-chat-name.ts +2 -2
- package/src/processor/presets.ts +9 -1
- package/src/processor/processor.test.ts +4 -4
- package/src/processor/processor.ts +43 -27
- package/src/queue-logger.ts +19 -8
- package/src/testing/data/trace-timeline.dx.json +4657 -0
- package/src/testing/index.ts +1 -0
- package/src/testing/test-generator.test.ts +81 -0
- package/src/testing/test-generator.ts +46 -40
- package/src/testing/test-trace.ts +20 -0
- package/src/testing/trace-timeline.conversations.json +1 -0
- package/src/testing/trace-timeline.test.ts +249 -0
- package/src/translations.ts +49 -34
- package/src/types/Assistant.ts +11 -0
- package/src/types/Settings.ts +63 -8
- package/src/types/index.ts +0 -1
- package/src/types/service.ts +1 -1
- package/dist/lib/browser/AssistantSettings-7QMO3LGF.mjs +0 -97
- package/dist/lib/browser/AssistantSettings-7QMO3LGF.mjs.map +0 -7
- package/dist/lib/browser/chunk-ATHYBVGN.mjs.map +0 -7
- package/dist/lib/browser/chunk-EZRS3J25.mjs +0 -30
- package/dist/lib/browser/chunk-EZRS3J25.mjs.map +0 -7
- package/dist/lib/browser/chunk-RUV2WOQH.mjs.map +0 -7
- package/dist/lib/browser/create-chat-LBZHGVSN.mjs.map +0 -7
- package/dist/lib/browser/ensure-companion-chat-FR4AWZ2P.mjs.map +0 -7
- package/dist/lib/browser/run-prompt-in-new-chat-4YQ37XIS.mjs.map +0 -7
- package/dist/lib/browser/set-current-chat-WJI3WAVM.mjs.map +0 -7
- package/dist/lib/browser/update-chat-name-3Y36KFAS.mjs.map +0 -7
- package/dist/lib/node-esm/AssistantSettings-UVUTKO7E.mjs +0 -98
- package/dist/lib/node-esm/AssistantSettings-UVUTKO7E.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NZIKC7AN.mjs +0 -32
- package/dist/lib/node-esm/chunk-NZIKC7AN.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-PXAJSTGZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-PY4X6FJT.mjs.map +0 -7
- package/dist/lib/node-esm/create-chat-3BEG4R6J.mjs.map +0 -7
- package/dist/lib/node-esm/ensure-companion-chat-BLP7NT32.mjs.map +0 -7
- package/dist/lib/node-esm/run-prompt-in-new-chat-2IJBSDTM.mjs.map +0 -7
- package/dist/lib/node-esm/set-current-chat-KBMMZULR.mjs.map +0 -7
- package/dist/lib/node-esm/update-chat-name-HM2P4NSI.mjs.map +0 -7
- package/dist/types/src/components/ChatProgress/ChatProgress.d.ts +0 -10
- package/dist/types/src/components/ChatProgress/ChatProgress.d.ts.map +0 -1
- package/dist/types/src/components/ChatProgress/index.d.ts +0 -2
- package/dist/types/src/components/ChatProgress/index.d.ts.map +0 -1
- package/dist/types/src/components/ChatThread/widgets/PromptWidget.d.ts +0 -14
- package/dist/types/src/components/ChatThread/widgets/PromptWidget.d.ts.map +0 -1
- package/dist/types/src/components/Typewriter/AssistantToolbar.d.ts +0 -12
- package/dist/types/src/components/Typewriter/AssistantToolbar.d.ts.map +0 -1
- package/dist/types/src/components/Typewriter/Typewriter.d.ts +0 -11
- package/dist/types/src/components/Typewriter/Typewriter.d.ts.map +0 -1
- package/dist/types/src/components/Typewriter/Typewriter.stories.d.ts +0 -7
- package/dist/types/src/components/Typewriter/Typewriter.stories.d.ts.map +0 -1
- package/dist/types/src/components/Typewriter/assistant-extension.d.ts +0 -5
- package/dist/types/src/components/Typewriter/assistant-extension.d.ts.map +0 -1
- package/dist/types/src/components/Typewriter/index.d.ts +0 -2
- package/dist/types/src/components/Typewriter/index.d.ts.map +0 -1
- package/dist/types/src/containers/PromptArticle/PromptArticle.d.ts +0 -6
- package/dist/types/src/containers/PromptArticle/PromptArticle.d.ts.map +0 -1
- package/dist/types/src/containers/PromptArticle/index.d.ts +0 -2
- package/dist/types/src/containers/PromptArticle/index.d.ts.map +0 -1
- package/dist/types/src/containers/PromptList/PromptList.d.ts +0 -6
- package/dist/types/src/containers/PromptList/PromptList.d.ts.map +0 -1
- package/dist/types/src/containers/PromptList/PromptList.stories.d.ts +0 -559
- package/dist/types/src/containers/PromptList/PromptList.stories.d.ts.map +0 -1
- package/dist/types/src/containers/PromptList/index.d.ts +0 -2
- package/dist/types/src/containers/PromptList/index.d.ts.map +0 -1
- package/dist/types/src/types/defs.d.ts +0 -2
- package/dist/types/src/types/defs.d.ts.map +0 -1
- package/src/blueprints/assistant/blueprint.conversations.json +0 -1
- package/src/components/ChatProgress/ChatProgress.tsx +0 -56
- package/src/components/ChatProgress/index.ts +0 -5
- package/src/components/ChatThread/widgets/PromptWidget.ts +0 -28
- package/src/components/Typewriter/AssistantToolbar.tsx +0 -161
- package/src/components/Typewriter/Typewriter.stories.tsx +0 -86
- package/src/components/Typewriter/Typewriter.tsx +0 -50
- package/src/components/Typewriter/assistant-extension.tsx +0 -141
- package/src/containers/PromptArticle/index.ts +0 -5
- package/src/containers/PromptList/index.ts +0 -5
- package/src/types/defs.ts +0 -5
|
@@ -8,11 +8,11 @@ import { log } from '@dxos/log';
|
|
|
8
8
|
import { ContentBlock, type Message } from '@dxos/types';
|
|
9
9
|
import { type XmlWidgetRegistry, getXmlTextChild } from '@dxos/ui-editor';
|
|
10
10
|
|
|
11
|
+
import { type Assistant } from '../../types';
|
|
11
12
|
import { type BlockRenderer, type MessageThreadContext } from './sync';
|
|
12
13
|
import { applyToolBlockToWidgetState } from './tool-widget-state';
|
|
13
14
|
import {
|
|
14
15
|
FallbackWidget,
|
|
15
|
-
PromptWidget,
|
|
16
16
|
ReasoningWidget,
|
|
17
17
|
ReferenceWidget,
|
|
18
18
|
SelectWidget,
|
|
@@ -25,17 +25,36 @@ import {
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Custom XML tags registry.
|
|
28
|
+
*
|
|
29
|
+
* NOTE: `<prompt>` has no widget — it is rendered via mark + line decorations
|
|
30
|
+
* (`xmlBlockDecoration`) in MarkdownStream so the prompt text remains part of the document
|
|
31
|
+
* and can be highlighted by `xmlFormatting`. It is still listed here so the markdown block
|
|
32
|
+
* parser (`xmlBlockParsers`) knows to keep `<prompt>...</prompt>` as a single HTMLBlock
|
|
33
|
+
* — otherwise an unregistered prompt opens a Paragraph that lazy-continues into the
|
|
34
|
+
* following lines and breaks parsing of subsequent multi-line tags (e.g. a `<reasoning>`
|
|
35
|
+
* block whose content contains an ordered list).
|
|
28
36
|
*/
|
|
29
37
|
export const componentRegistry: XmlWidgetRegistry = {
|
|
30
38
|
//
|
|
31
|
-
//
|
|
39
|
+
// Block-only (no widget — see note above).
|
|
32
40
|
//
|
|
33
41
|
|
|
34
42
|
prompt: {
|
|
35
43
|
block: true,
|
|
36
|
-
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
//
|
|
47
|
+
// DOM Widgets
|
|
48
|
+
//
|
|
49
|
+
|
|
50
|
+
synthetic: {
|
|
51
|
+
block: true,
|
|
52
|
+
factory: ({ children, range }) => {
|
|
37
53
|
const text = getXmlTextChild(children);
|
|
38
|
-
|
|
54
|
+
// TODO(dmaretskyi): Synthetic blocks are "user"-turn messages generated by the system, i.e. and event from a trigger, an email-encoded to JSON, etc.
|
|
55
|
+
// They are meant to start agent, to process the event without looking like user-authored prompt.
|
|
56
|
+
// Create a new widget type for them.
|
|
57
|
+
return text ? new ReasoningWidget(text, range.from) : null;
|
|
39
58
|
},
|
|
40
59
|
},
|
|
41
60
|
reasoning: {
|
|
@@ -123,17 +142,47 @@ export const componentRegistry: XmlWidgetRegistry = {
|
|
|
123
142
|
/**
|
|
124
143
|
* Convert block to markdown.
|
|
125
144
|
*/
|
|
126
|
-
export const blockToMarkdown: BlockRenderer = (
|
|
127
|
-
|
|
145
|
+
export const blockToMarkdown: BlockRenderer = createBlockRenderer('normal');
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Create a {@link BlockRenderer} that filters blocks based on the chat view type.
|
|
149
|
+
*
|
|
150
|
+
* - `summary`: only user prompts.
|
|
151
|
+
* - `normal`: user prompts + assistant text + tool calls + summary/select/suggestion/reference + status. Hides reasoning.
|
|
152
|
+
* - `thinking`: same as normal plus reasoning.
|
|
153
|
+
* - `debug`: renders every block (raw fallbacks visible).
|
|
154
|
+
*/
|
|
155
|
+
export function createBlockRenderer(viewType: Assistant.ChatView | undefined): BlockRenderer {
|
|
156
|
+
return (context, message, block) => {
|
|
157
|
+
if (!isBlockVisible(viewType, message, block)) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
let str = blockToMarkdownImpl(context, message, block);
|
|
161
|
+
if (str && !block.pending) {
|
|
162
|
+
return (str += '\n');
|
|
163
|
+
}
|
|
164
|
+
return str;
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const isBlockVisible = (
|
|
169
|
+
viewType: Assistant.ChatView | undefined,
|
|
128
170
|
message: Message.Message,
|
|
129
171
|
block: ContentBlock.Any,
|
|
130
|
-
) => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
172
|
+
): boolean => {
|
|
173
|
+
switch (viewType) {
|
|
174
|
+
case 'debug':
|
|
175
|
+
return true;
|
|
176
|
+
case 'normal':
|
|
177
|
+
return block._tag !== 'reasoning';
|
|
178
|
+
case 'summary':
|
|
179
|
+
// Show only conversational text (user prompts + assistant replies); hide reasoning,
|
|
180
|
+
// tool calls, status, stats, and synthetic system messages.
|
|
181
|
+
return block._tag === 'text' && (block as ContentBlock.Text).disposition !== 'synthetic';
|
|
182
|
+
case 'thinking':
|
|
183
|
+
default:
|
|
184
|
+
return true;
|
|
134
185
|
}
|
|
135
|
-
|
|
136
|
-
return str;
|
|
137
186
|
};
|
|
138
187
|
|
|
139
188
|
const blockToMarkdownImpl = (context: MessageThreadContext, message: Message.Message, block: ContentBlock.Any) => {
|
|
@@ -141,7 +190,11 @@ const blockToMarkdownImpl = (context: MessageThreadContext, message: Message.Mes
|
|
|
141
190
|
switch (block._tag) {
|
|
142
191
|
case 'text': {
|
|
143
192
|
if (message.sender.role === 'user') {
|
|
144
|
-
|
|
193
|
+
if (block.disposition === 'synthetic') {
|
|
194
|
+
return renderXMLBlock('synthetic', { content: block.text, pending: block.pending });
|
|
195
|
+
} else {
|
|
196
|
+
return `<prompt>${block.text}</prompt>`;
|
|
197
|
+
}
|
|
145
198
|
} else {
|
|
146
199
|
const text = block.text.trim();
|
|
147
200
|
if (text.length > 0) {
|
|
@@ -217,18 +270,13 @@ const blockToMarkdownImpl = (context: MessageThreadContext, message: Message.Mes
|
|
|
217
270
|
const escapeXmlTextContent = (raw: string): string =>
|
|
218
271
|
raw.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
219
272
|
|
|
220
|
-
/**
|
|
221
|
-
* Strip actual list-marker prefixes without removing meaningful leading content.
|
|
222
|
-
*/
|
|
223
|
-
const stripBulletLikeLinePrefixes = (raw: string): string =>
|
|
224
|
-
raw
|
|
225
|
-
.split(/\r?\n/)
|
|
226
|
-
.map((line) => line.replace(/^\s*(?:[-*+•]|\d+[.)]\s)/, ''))
|
|
227
|
-
.join('\n');
|
|
228
|
-
|
|
229
273
|
const renderXMLBlock = (tag: string, opts: { content?: string; pending?: boolean; attributes?: string }) => {
|
|
230
|
-
// Replace paragraph breaks so that markdown parser does not split the content into multiple paragraphs.
|
|
231
|
-
|
|
274
|
+
// Replace paragraph breaks so that the markdown parser does not split the content into multiple paragraphs.
|
|
275
|
+
// NOTE: do not strip leading list-marker prefixes (`-`, `*`, `1. `, ...) per line — the streaming
|
|
276
|
+
// tag's range is replaced atomically by the XML widget so the inner markdown is never user-visible,
|
|
277
|
+
// and stripping can collapse a line to empty mid-stream (e.g. when only `1. ` has arrived), breaking
|
|
278
|
+
// the prefix-extension contract that `MessageSyncer` relies on for incremental appends.
|
|
279
|
+
const content = escapeXmlTextContent((opts.content ?? '').replace(/\n\n/g, ' ').trim());
|
|
232
280
|
|
|
233
281
|
if (opts.pending) {
|
|
234
282
|
return `<${tag}${opts.attributes ? ` ${opts.attributes}` : ''}>${content}`;
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
|
|
3
1
|
//
|
|
4
2
|
// Copyright 2025 DXOS.org
|
|
5
3
|
//
|
|
6
4
|
|
|
5
|
+
// @vitest-environment jsdom
|
|
6
|
+
|
|
7
7
|
import { EditorView } from '@codemirror/view';
|
|
8
8
|
import { describe, it } from '@effect/vitest';
|
|
9
9
|
import * as Effect from 'effect/Effect';
|
|
10
10
|
|
|
11
11
|
import { Obj } from '@dxos/echo';
|
|
12
12
|
import { type Mutable } from '@dxos/echo/internal';
|
|
13
|
-
import { type ContentBlock } from '@dxos/types';
|
|
13
|
+
import { type ContentBlock, type Message } from '@dxos/types';
|
|
14
14
|
|
|
15
15
|
import { createMessage } from '#testing';
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
import { MessageSyncer, type TextModel } from './sync';
|
|
17
|
+
import { createBlockRenderer } from './registry';
|
|
18
|
+
import { type BlockRenderer, MessageSyncer, type MessageThreadContext, type TextModel } from './sync';
|
|
19
19
|
|
|
20
20
|
class TestDocument implements TextModel {
|
|
21
21
|
private readonly _view = new EditorView({ extensions: [] });
|
|
@@ -48,20 +48,20 @@ describe('reducers', () => {
|
|
|
48
48
|
'basic sync',
|
|
49
49
|
Effect.fn(function* ({ expect }) {
|
|
50
50
|
const doc = new TestDocument();
|
|
51
|
-
const syncer = new MessageSyncer(doc,
|
|
51
|
+
const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
|
|
52
52
|
|
|
53
53
|
const messages = [
|
|
54
54
|
createMessage('user', [{ _tag: 'text', text: 'Hello' }]),
|
|
55
55
|
createMessage('assistant', [{ _tag: 'text', text: 'Hi there!' }]),
|
|
56
56
|
];
|
|
57
57
|
|
|
58
|
-
syncer.
|
|
58
|
+
syncer.update(messages);
|
|
59
59
|
expect(doc.content).toEqual(['<prompt>Hello</prompt>', 'Hi there!', ''].join('\n'));
|
|
60
60
|
|
|
61
|
-
Obj.
|
|
61
|
+
Obj.update(messages[1], (obj) => {
|
|
62
62
|
obj.blocks.push({ _tag: 'text', text: 'How can I help?' });
|
|
63
63
|
});
|
|
64
|
-
syncer.
|
|
64
|
+
syncer.update(messages);
|
|
65
65
|
expect(doc.content).toEqual(['<prompt>Hello</prompt>', 'Hi there!', 'How can I help?', ''].join('\n'));
|
|
66
66
|
}),
|
|
67
67
|
);
|
|
@@ -70,30 +70,190 @@ describe('reducers', () => {
|
|
|
70
70
|
'sync with partial updates',
|
|
71
71
|
Effect.fn(function* ({ expect }) {
|
|
72
72
|
const doc = new TestDocument();
|
|
73
|
-
const syncer = new MessageSyncer(doc,
|
|
73
|
+
const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
|
|
74
74
|
|
|
75
75
|
const messages = [
|
|
76
76
|
createMessage('user', [{ _tag: 'text', text: 'Hello' }]),
|
|
77
77
|
createMessage('assistant', [{ _tag: 'text', text: 'Hi there!', pending: true }]),
|
|
78
78
|
];
|
|
79
79
|
|
|
80
|
-
syncer.
|
|
80
|
+
syncer.update(messages);
|
|
81
81
|
expect(doc.content).toEqual(['<prompt>Hello</prompt>', 'Hi there!'].join('\n'));
|
|
82
82
|
|
|
83
|
-
Obj.
|
|
83
|
+
Obj.update(messages[1], (obj) => {
|
|
84
84
|
const block = obj.blocks[0] as Mutable<ContentBlock.Text>;
|
|
85
85
|
block.text = 'Hi there! How are you?';
|
|
86
86
|
block.pending = false;
|
|
87
87
|
});
|
|
88
|
-
syncer.
|
|
88
|
+
syncer.update(messages);
|
|
89
89
|
|
|
90
|
-
Obj.
|
|
90
|
+
Obj.update(messages[1], (obj) => {
|
|
91
91
|
obj.blocks.push({ _tag: 'text', text: 'How can I help?' });
|
|
92
92
|
});
|
|
93
|
-
syncer.
|
|
93
|
+
syncer.update(messages);
|
|
94
94
|
expect(doc.content).toEqual(
|
|
95
95
|
['<prompt>Hello</prompt>', 'Hi there! How are you?', 'How can I help?', ''].join('\n'),
|
|
96
96
|
);
|
|
97
97
|
}),
|
|
98
98
|
);
|
|
99
|
+
|
|
100
|
+
// Regression: streaming reasoning text that passes through a bare list-marker state
|
|
101
|
+
// (e.g. `"…\n1. "`) used to make `stripBulletLikeLinePrefixes` collapse the line to empty,
|
|
102
|
+
// breaking the prefix-diff invariant in `MessageSyncer` and producing a duplicate `<reasoning>`
|
|
103
|
+
// opening tag in the document.
|
|
104
|
+
it.effect(
|
|
105
|
+
'streaming reasoning with list-marker transitions does not duplicate opening tag',
|
|
106
|
+
Effect.fn(function* ({ expect }) {
|
|
107
|
+
const doc = new TestDocument();
|
|
108
|
+
const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
|
|
109
|
+
|
|
110
|
+
const setReasoning = (message: Message.Message, text: string, pending: boolean) => {
|
|
111
|
+
Obj.update(message, (message) => {
|
|
112
|
+
const block = message.blocks[0] as Mutable<ContentBlock.Reasoning>;
|
|
113
|
+
block.reasoningText = text;
|
|
114
|
+
block.pending = pending;
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const messages = [createMessage('assistant', [{ _tag: 'reasoning', reasoningText: 'abc\n1', pending: true }])];
|
|
119
|
+
|
|
120
|
+
// Tick 1: `"abc\n1"` — `\d+[.)]\s` regex does not match (no dot/space yet).
|
|
121
|
+
syncer.update(messages);
|
|
122
|
+
|
|
123
|
+
// Tick 2: `"abc\n1."` — still no match (no trailing whitespace).
|
|
124
|
+
setReasoning(messages[0], 'abc\n1.', true);
|
|
125
|
+
syncer.update(messages);
|
|
126
|
+
|
|
127
|
+
// Tick 3: `"abc\n1. "` — line `"1. "` matches and is stripped to empty.
|
|
128
|
+
setReasoning(messages[0], 'abc\n1. ', true);
|
|
129
|
+
syncer.update(messages);
|
|
130
|
+
|
|
131
|
+
// Tick 4: `"abc\n1. foo"` — list item with content.
|
|
132
|
+
setReasoning(messages[0], 'abc\n1. foo', true);
|
|
133
|
+
syncer.update(messages);
|
|
134
|
+
|
|
135
|
+
// Tick 5: finalize.
|
|
136
|
+
setReasoning(messages[0], 'abc\n1. foo', false);
|
|
137
|
+
syncer.update(messages);
|
|
138
|
+
|
|
139
|
+
const openTagCount = (doc.content.match(/<reasoning>/g) ?? []).length;
|
|
140
|
+
const closeTagCount = (doc.content.match(/<\/reasoning>/g) ?? []).length;
|
|
141
|
+
expect(openTagCount).toBe(1);
|
|
142
|
+
expect(closeTagCount).toBe(1);
|
|
143
|
+
}),
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// Regression: prompt "respond with your name inside an xml tag" produces a streamed
|
|
147
|
+
// reasoning block followed by a text block containing a non-registered XML tag
|
|
148
|
+
// (`<name>Claude</name>`). The text block must appear in the document AFTER the
|
|
149
|
+
// closed reasoning block — the bug symptom is the reasoning tag rendering with no
|
|
150
|
+
// follow-up response visible.
|
|
151
|
+
it.effect(
|
|
152
|
+
'reasoning block followed by text containing a non-registered xml tag',
|
|
153
|
+
Effect.fn(function* ({ expect }) {
|
|
154
|
+
const doc = new TestDocument();
|
|
155
|
+
const syncer = new MessageSyncer(doc, createBlockRenderer('thinking'));
|
|
156
|
+
|
|
157
|
+
const setReasoning = (message: Message.Message, text: string, pending: boolean) => {
|
|
158
|
+
Obj.update(message, (message) => {
|
|
159
|
+
const block = message.blocks[0] as Mutable<ContentBlock.Reasoning>;
|
|
160
|
+
block.reasoningText = text;
|
|
161
|
+
block.pending = pending;
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const setText = (message: Message.Message, text: string, pending: boolean) => {
|
|
166
|
+
Obj.update(message, (message) => {
|
|
167
|
+
const block = message.blocks[1] as Mutable<ContentBlock.Text>;
|
|
168
|
+
block.text = text;
|
|
169
|
+
block.pending = pending;
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Tick 1: reasoning starts streaming.
|
|
174
|
+
const messages = [createMessage('assistant', [{ _tag: 'reasoning', reasoningText: 'Thinking', pending: true }])];
|
|
175
|
+
syncer.update(messages);
|
|
176
|
+
|
|
177
|
+
// Tick 2: reasoning grows.
|
|
178
|
+
setReasoning(messages[0], 'Thinking about the answer', true);
|
|
179
|
+
syncer.update(messages);
|
|
180
|
+
|
|
181
|
+
// Tick 3: reasoning closes.
|
|
182
|
+
setReasoning(messages[0], 'Thinking about the answer', false);
|
|
183
|
+
syncer.update(messages);
|
|
184
|
+
|
|
185
|
+
// Tick 4: text block appears, pending and empty (model has started emitting but text is still '').
|
|
186
|
+
Obj.update(messages[0], (message) => {
|
|
187
|
+
message.blocks.push({ _tag: 'text', text: '', pending: true });
|
|
188
|
+
});
|
|
189
|
+
syncer.update(messages);
|
|
190
|
+
|
|
191
|
+
// Tick 5: partial text — opening tag only.
|
|
192
|
+
setText(messages[0], '<name>', true);
|
|
193
|
+
syncer.update(messages);
|
|
194
|
+
|
|
195
|
+
// Tick 6: full text streamed.
|
|
196
|
+
setText(messages[0], '<name>Claude</name>', true);
|
|
197
|
+
syncer.update(messages);
|
|
198
|
+
|
|
199
|
+
// Tick 7: text finalised.
|
|
200
|
+
setText(messages[0], '<name>Claude</name>', false);
|
|
201
|
+
syncer.update(messages);
|
|
202
|
+
|
|
203
|
+
// Both the closed reasoning tag and the response text must be present.
|
|
204
|
+
expect(doc.content).toContain('<reasoning>Thinking about the answer</reasoning>');
|
|
205
|
+
expect(doc.content).toContain('<name>Claude</name>');
|
|
206
|
+
|
|
207
|
+
const openReasoning = (doc.content.match(/<reasoning>/g) ?? []).length;
|
|
208
|
+
const closeReasoning = (doc.content.match(/<\/reasoning>/g) ?? []).length;
|
|
209
|
+
expect(openReasoning).toBe(1);
|
|
210
|
+
expect(closeReasoning).toBe(1);
|
|
211
|
+
}),
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// Direct test of `MessageSyncer`'s tolerance for non-monotonic renderer output —
|
|
215
|
+
// any renderer that produces a shorter string for the same streaming block (e.g., due
|
|
216
|
+
// to whitespace normalisation or future transforms) must not produce duplicate output.
|
|
217
|
+
it.effect(
|
|
218
|
+
'non-monotonic renderer output does not duplicate previously-emitted content',
|
|
219
|
+
Effect.fn(function* ({ expect }) {
|
|
220
|
+
const doc = new TestDocument();
|
|
221
|
+
|
|
222
|
+
const renderer: BlockRenderer = (_ctx: MessageThreadContext, _msg: Message.Message, block: ContentBlock.Any) => {
|
|
223
|
+
if (block._tag !== 'reasoning') {
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
const text = block.reasoningText ?? '';
|
|
227
|
+
// Simulate a non-monotonic transform: collapse a line that is a sole digit+dot+space.
|
|
228
|
+
const normalised = text
|
|
229
|
+
.split(/\r?\n/)
|
|
230
|
+
.map((line) => line.replace(/^\s*\d+[.)]\s$/, ''))
|
|
231
|
+
.join('\n')
|
|
232
|
+
.trim();
|
|
233
|
+
return block.pending ? `<reasoning>${normalised}` : `<reasoning>${normalised}</reasoning>\n`;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const syncer = new MessageSyncer(doc, renderer);
|
|
237
|
+
|
|
238
|
+
const messages = [createMessage('assistant', [{ _tag: 'reasoning', reasoningText: 'abc\n1.', pending: true }])];
|
|
239
|
+
|
|
240
|
+
syncer.update(messages);
|
|
241
|
+
Obj.update(messages[0], (obj) => {
|
|
242
|
+
const block = obj.blocks[0] as Mutable<ContentBlock.Reasoning>;
|
|
243
|
+
block.reasoningText = 'abc\n1. ';
|
|
244
|
+
});
|
|
245
|
+
syncer.update(messages);
|
|
246
|
+
Obj.update(messages[0], (obj) => {
|
|
247
|
+
const block = obj.blocks[0] as Mutable<ContentBlock.Reasoning>;
|
|
248
|
+
block.reasoningText = 'abc\n1. tail';
|
|
249
|
+
block.pending = false;
|
|
250
|
+
});
|
|
251
|
+
syncer.update(messages);
|
|
252
|
+
|
|
253
|
+
const openTagCount = (doc.content.match(/<reasoning>/g) ?? []).length;
|
|
254
|
+
const closeTagCount = (doc.content.match(/<\/reasoning>/g) ?? []).length;
|
|
255
|
+
expect(openTagCount).toBe(1);
|
|
256
|
+
expect(closeTagCount).toBe(1);
|
|
257
|
+
}),
|
|
258
|
+
);
|
|
99
259
|
});
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type DXN } from '@dxos/echo';
|
|
6
|
-
import {
|
|
7
|
-
import { type MarkdownStreamController } from '@dxos/react-ui-components';
|
|
6
|
+
import { type MarkdownStreamController } from '@dxos/react-ui-markdown';
|
|
8
7
|
import { type ContentBlock, type Message } from '@dxos/types';
|
|
9
8
|
import { type StateDispatch, type XmlWidgetStateManager } from '@dxos/ui-editor';
|
|
10
9
|
|
|
@@ -15,6 +14,21 @@ import { rehydrateToolWidgetsFromMessages } from './tool-widget-state';
|
|
|
15
14
|
*/
|
|
16
15
|
export type TextModel = Pick<MarkdownStreamController, 'length' | 'setContent' | 'append' | 'updateWidget'>;
|
|
17
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Renders a block to markdown.
|
|
19
|
+
*
|
|
20
|
+
* Contract: for any block whose lifetime spans multiple invocations (i.e. a streaming block
|
|
21
|
+
* with `pending: true` whose content grows over time, transitioning to `pending: false`), the
|
|
22
|
+
* sequence of returned strings must be monotonically extending — each subsequent value must be
|
|
23
|
+
* a string-extension of the previous. The {@link MessageSyncer} relies on this invariant to
|
|
24
|
+
* compute appendable deltas without diffing.
|
|
25
|
+
*/
|
|
26
|
+
export type BlockRenderer = (
|
|
27
|
+
context: MessageThreadContext,
|
|
28
|
+
message: Message.Message,
|
|
29
|
+
block: ContentBlock.Any,
|
|
30
|
+
) => string | undefined;
|
|
31
|
+
|
|
18
32
|
/**
|
|
19
33
|
* Thread context passed to renderer.
|
|
20
34
|
*/
|
|
@@ -25,30 +39,30 @@ export class MessageThreadContext implements Pick<MarkdownStreamController, 'upd
|
|
|
25
39
|
this._widgetState?.updateWidget(id, value);
|
|
26
40
|
}
|
|
27
41
|
|
|
28
|
-
// TODO(burdon): Resolve from hypergraph.
|
|
42
|
+
// TODO(burdon): Resolve name from hypergraph.
|
|
29
43
|
getObjectLabel(_id: DXN) {
|
|
30
44
|
return 'Object';
|
|
31
45
|
}
|
|
32
46
|
}
|
|
33
47
|
|
|
34
|
-
/**
|
|
35
|
-
* Renders a block to markdown.
|
|
36
|
-
*/
|
|
37
|
-
export type BlockRenderer = (
|
|
38
|
-
context: MessageThreadContext,
|
|
39
|
-
message: Message.Message,
|
|
40
|
-
block: ContentBlock.Any,
|
|
41
|
-
) => string | undefined;
|
|
42
|
-
|
|
43
48
|
/**
|
|
44
49
|
* Syncs messages with the editor.
|
|
50
|
+
*
|
|
51
|
+
* Reflects the AI streaming contract:
|
|
52
|
+
* - Messages and their blocks are appended in order.
|
|
53
|
+
* - Only the last block in `messages` may be `pending`; all earlier blocks are finalized.
|
|
54
|
+
* - The renderer's output for a streaming block grows monotonically (see {@link BlockRenderer}).
|
|
55
|
+
* - The document is read-only outside this syncer.
|
|
56
|
+
*
|
|
57
|
+
* Under those rules the syncer needs only:
|
|
58
|
+
* - `_completed`: the flat-block index past which everything has been fully appended.
|
|
59
|
+
* - `_trailing`: chars of the in-flight block (at index `_completed`) already appended.
|
|
60
|
+
* - `_threadId`: identity sentinel; if `messages[0]?.id` changes, the document is replaced.
|
|
45
61
|
*/
|
|
46
62
|
export class MessageSyncer {
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
private
|
|
50
|
-
private _currentBlockIndex = 0;
|
|
51
|
-
private _currentBlockContent?: string;
|
|
63
|
+
private _threadId?: string;
|
|
64
|
+
private _completed = 0;
|
|
65
|
+
private _trailing = 0;
|
|
52
66
|
|
|
53
67
|
private readonly _context: MessageThreadContext;
|
|
54
68
|
|
|
@@ -63,103 +77,74 @@ export class MessageSyncer {
|
|
|
63
77
|
return this._context;
|
|
64
78
|
}
|
|
65
79
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
73
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Replace the document with the rendering of `messages`. Use on mount, on thread switch,
|
|
82
|
+
* and from {@link update} when it detects an identity change in `messages[0]`.
|
|
83
|
+
*/
|
|
84
|
+
reset(messages: Message.Message[] = []): void {
|
|
85
|
+
this._threadId = messages[0]?.id;
|
|
86
|
+
this._completed = 0;
|
|
87
|
+
this._trailing = 0;
|
|
88
|
+
const buffer = this._walk(messages);
|
|
89
|
+
// Match the pre-rewrite behaviour: rendering from a steady state (initial mount with
|
|
90
|
+
// non-empty messages, or thread switch) lands the entire content via `setContent` — which
|
|
91
|
+
// uses `wireBypass`, so the editor jumps straight to the final text and `update()` returns
|
|
92
|
+
// `true` so the caller can scroll to the bottom. Live streaming partials that arrive
|
|
93
|
+
// *after* this initial render flow through `update()`'s incremental path → `_document.append`
|
|
94
|
+
// → wire's drip filter, preserving the char-by-char typewriter for incoming text.
|
|
95
|
+
void this._document.setContent(buffer).then(() => {
|
|
96
|
+
rehydrateToolWidgetsFromMessages(this._context, messages);
|
|
97
|
+
});
|
|
74
98
|
}
|
|
75
99
|
|
|
76
100
|
/**
|
|
77
|
-
*
|
|
101
|
+
* Stream the suffix of the rendered messages into the document.
|
|
102
|
+
* Returns `true` if the document was replaced (initial mount or thread switch), `false`
|
|
103
|
+
* if the call was a streaming append (or a no-op).
|
|
78
104
|
*/
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// ...message,
|
|
83
|
-
// blocks: message.blocks.filter((block) => !block.pending || block._tag === 'text'),
|
|
84
|
-
// }));
|
|
85
|
-
|
|
86
|
-
// Check if new set of messages.
|
|
87
|
-
if (this._initialMessageId !== messages[0]?.id) {
|
|
88
|
-
this.reset();
|
|
89
|
-
this._initialMessageId = messages[0]?.id;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (this._document.length === 0 && flush) {
|
|
93
|
-
const buffer: string[] = [];
|
|
94
|
-
this.processBlocks(messages, (content) => buffer.push(content));
|
|
95
|
-
const content = buffer.join('');
|
|
96
|
-
// `setContent` dispatches `xmlTagResetEffect`, which clears widget props accumulated during
|
|
97
|
-
// `processBlocks`; re-apply tool state after the document is replaced.
|
|
98
|
-
const epoch = this.#syncEpoch;
|
|
99
|
-
void this._document
|
|
100
|
-
.setContent(content)
|
|
101
|
-
.then(() => {
|
|
102
|
-
if (epoch !== this.#syncEpoch) {
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
rehydrateToolWidgetsFromMessages(this._context, messages);
|
|
106
|
-
})
|
|
107
|
-
.catch((error) => {
|
|
108
|
-
log.warn('failed to replace thread content before widget rehydration', { error });
|
|
109
|
-
});
|
|
110
|
-
|
|
105
|
+
update(messages: Message.Message[]): boolean {
|
|
106
|
+
if (messages[0]?.id !== this._threadId) {
|
|
107
|
+
this.reset(messages);
|
|
111
108
|
return true;
|
|
112
|
-
} else {
|
|
113
|
-
this.processBlocks(messages, (content) => {
|
|
114
|
-
void this._document.append(content);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
return false;
|
|
118
109
|
}
|
|
110
|
+
const buffer = this._walk(messages);
|
|
111
|
+
if (buffer.length > 0) {
|
|
112
|
+
void this._document.append(buffer);
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
119
115
|
}
|
|
120
116
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
for (const block of message.blocks.slice(this._currentBlockIndex)) {
|
|
139
|
-
this._currentBlockIndex = j;
|
|
140
|
-
const currentBlockContent = this._renderer(this._context, message, block);
|
|
141
|
-
if (currentBlockContent) {
|
|
142
|
-
let content: string = '';
|
|
143
|
-
if (this._currentBlockContent && currentBlockContent.startsWith(this._currentBlockContent)) {
|
|
144
|
-
content = currentBlockContent.slice(this._currentBlockContent.length);
|
|
145
|
-
} else {
|
|
146
|
-
content = currentBlockContent;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// console.log('append', { message: i, block: j, content });
|
|
150
|
-
this._currentBlockContent = currentBlockContent;
|
|
151
|
-
append(content);
|
|
117
|
+
/**
|
|
118
|
+
* Walk flat blocks starting at `_completed`, advancing the cursors and returning the chars
|
|
119
|
+
* to append. Blocks before `_completed` are skipped — their renderer is never re-invoked,
|
|
120
|
+
* which preserves single-shot side effects (e.g. tool widget state mutation).
|
|
121
|
+
*/
|
|
122
|
+
_walk(messages: Message.Message[]): string {
|
|
123
|
+
let buffer = '';
|
|
124
|
+
let index = 0;
|
|
125
|
+
outer: for (const message of messages) {
|
|
126
|
+
for (const block of message.blocks) {
|
|
127
|
+
if (index < this._completed) {
|
|
128
|
+
index++;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const rendered = this._renderer(this._context, message, block) ?? '';
|
|
132
|
+
if (rendered.length > this._trailing) {
|
|
133
|
+
buffer += rendered.slice(this._trailing);
|
|
152
134
|
}
|
|
153
|
-
|
|
154
135
|
if (block.pending) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
this.
|
|
158
|
-
|
|
136
|
+
// Stay on this block; record how far we've appended so the next call can resume.
|
|
137
|
+
// `Math.max`-style guard against a non-monotonic renderer output without shrinking the doc.
|
|
138
|
+
if (rendered.length > this._trailing) {
|
|
139
|
+
this._trailing = rendered.length;
|
|
140
|
+
}
|
|
141
|
+
break outer;
|
|
159
142
|
}
|
|
160
|
-
|
|
143
|
+
this._completed = index + 1;
|
|
144
|
+
this._trailing = 0;
|
|
145
|
+
index++;
|
|
161
146
|
}
|
|
162
|
-
i++;
|
|
163
147
|
}
|
|
148
|
+
return buffer;
|
|
164
149
|
}
|
|
165
150
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<prompt>How should I structure a CLI tool with subcommands?</prompt>
|
|
2
|
+
|
|
3
|
+
<reasoning>
|
|
4
|
+
The user is asking about CLI subcommand structure. Let me think through what they likely care about:
|
|
5
|
+
|
|
6
|
+
1. Discoverability — every subcommand needs help text and a flat top-level listing.
|
|
7
|
+
2. Composability — subcommands should be invokable individually for scripting.
|
|
8
|
+
3. Shared concerns — auth, config, logging should not be duplicated per command.
|
|
9
|
+
|
|
10
|
+
A few patterns worth considering:
|
|
11
|
+
|
|
12
|
+
- A single binary that dispatches to subcommand handlers (like `git`, `kubectl`).
|
|
13
|
+
- A plugin model where subcommands live in separate binaries on the PATH (like `git-foo`).
|
|
14
|
+
- A library that each subcommand wraps as a thin executable.
|
|
15
|
+
|
|
16
|
+
The plugin model wins for very large surfaces but adds packaging cost. For a tool with under ~30 subcommands the dispatcher pattern stays clearer.
|
|
17
|
+
</reasoning>
|
|
18
|
+
|
|
19
|
+
For a CLI with a moderate set of subcommands, the dispatcher pattern is usually the right default:
|
|
20
|
+
|
|
21
|
+
1. One binary, one entry point.
|
|
22
|
+
2. Subcommands registered as handlers off a shared root.
|
|
23
|
+
3. Cross-cutting concerns (auth, config, logging) wired in at the root and inherited.
|
|
24
|
+
|
|
25
|
+
If you grow past ~30 subcommands or want third-party extensions, switch to a plugin model where binaries named `<tool>-<subcommand>` are discovered on the `PATH`.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
7
|
import { TogglePanel } from '@dxos/react-ui-components';
|
|
8
|
-
import {
|
|
8
|
+
import { JsonHighlighter } from '@dxos/react-ui-syntax-highlighter';
|
|
9
9
|
import { type XmlWidgetProps } from '@dxos/ui-editor';
|
|
10
10
|
|
|
11
11
|
import { type MessageThreadContext } from '../sync';
|
|
@@ -16,7 +16,7 @@ export const FallbackWidget = ({ _tag, ...props }: XmlWidgetProps<MessageThreadC
|
|
|
16
16
|
<TogglePanel.Header classNames='bg-group-surface'>{_tag}</TogglePanel.Header>
|
|
17
17
|
<TogglePanel.Content classNames='bg-modal-surface'>
|
|
18
18
|
<TogglePanel.Viewport>
|
|
19
|
-
<
|
|
19
|
+
<JsonHighlighter classNames='p-2! text-sm' data={props} />
|
|
20
20
|
</TogglePanel.Viewport>
|
|
21
21
|
</TogglePanel.Content>
|
|
22
22
|
</TogglePanel.Root>
|