@dxos/plugin-assistant 0.9.1-staging.ee54ba693a → 0.11.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/PLUGIN.mdl +3 -28
- package/dist/lib/AssistantPlugin.mjs +2 -0
- package/dist/lib/AssistantPlugin.node.mjs +55 -0
- package/dist/lib/AssistantPlugin.node.mjs.map +1 -0
- package/dist/lib/AssistantPlugin.workerd.mjs +43 -0
- package/dist/lib/AssistantPlugin.workerd.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +24 -0
- package/dist/lib/capabilities.mjs.map +1 -0
- package/dist/lib/chunk-AgentArticle.mjs +52 -0
- package/dist/lib/chunk-AgentArticle.mjs.map +1 -0
- package/dist/lib/chunk-AgentProperties.mjs +35 -0
- package/dist/lib/chunk-AgentProperties.mjs.map +1 -0
- package/dist/lib/chunk-AssistantPlugin.mjs +88 -0
- package/dist/lib/chunk-AssistantPlugin.mjs.map +1 -0
- package/dist/lib/chunk-AssistantSettings.mjs +285 -0
- package/dist/lib/chunk-AssistantSettings.mjs.map +1 -0
- package/dist/lib/chunk-ChatArticle.mjs +121 -0
- package/dist/lib/chunk-ChatArticle.mjs.map +1 -0
- package/dist/lib/chunk-ChatCompanion.mjs +116 -0
- package/dist/lib/chunk-ChatCompanion.mjs.map +1 -0
- package/dist/lib/chunk-ChatDialog.mjs +73 -0
- package/dist/lib/chunk-ChatDialog.mjs.map +1 -0
- package/dist/lib/chunk-IntegrationPrompt.mjs +73 -0
- package/dist/lib/chunk-IntegrationPrompt.mjs.map +1 -0
- package/dist/lib/chunk-SpaceHomePrompt.mjs +104 -0
- package/dist/lib/chunk-SpaceHomePrompt.mjs.map +1 -0
- package/dist/lib/chunk-SpaceHomeSuggestions.mjs +60 -0
- package/dist/lib/chunk-SpaceHomeSuggestions.mjs.map +1 -0
- package/dist/lib/chunk-TracePanel.mjs +127 -0
- package/dist/lib/chunk-TracePanel.mjs.map +1 -0
- package/dist/lib/chunk-TracePanel2.mjs +7 -0
- package/dist/lib/chunk-TracePanel2.mjs.map +1 -0
- package/dist/lib/chunk-TriggerStatus.mjs +72 -0
- package/dist/lib/chunk-TriggerStatus.mjs.map +1 -0
- package/dist/lib/chunk-agent-hydrator.mjs +22 -0
- package/dist/lib/chunk-agent-hydrator.mjs.map +1 -0
- package/dist/lib/chunk-agent-service.mjs +21 -0
- package/dist/lib/chunk-agent-service.mjs.map +1 -0
- package/dist/lib/{neutral/ai-context-LIKJYMIN.mjs → chunk-ai-context.mjs} +8 -12
- package/dist/lib/chunk-ai-context.mjs.map +1 -0
- package/dist/lib/chunk-ai-service.mjs +27 -0
- package/dist/lib/chunk-ai-service.mjs.map +1 -0
- package/dist/lib/chunk-app-graph-builder.mjs +179 -0
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
- package/dist/lib/chunk-automation-templates.mjs +99 -0
- package/dist/lib/chunk-automation-templates.mjs.map +1 -0
- package/dist/lib/chunk-companion-chat-provisioner.mjs +123 -0
- package/dist/lib/chunk-companion-chat-provisioner.mjs.map +1 -0
- package/dist/lib/chunk-connector.mjs +60 -0
- package/dist/lib/chunk-connector.mjs.map +1 -0
- package/dist/lib/chunk-constants.mjs +9 -0
- package/dist/lib/chunk-constants.mjs.map +1 -0
- package/dist/lib/chunk-context.mjs +7 -0
- package/dist/lib/chunk-context.mjs.map +1 -0
- package/dist/lib/chunk-create-chat.mjs +53 -0
- package/dist/lib/chunk-create-chat.mjs.map +1 -0
- package/dist/lib/chunk-create-object.mjs +70 -0
- package/dist/lib/chunk-create-object.mjs.map +1 -0
- package/dist/lib/chunk-edge-model-resolver.mjs +64 -0
- package/dist/lib/chunk-edge-model-resolver.mjs.map +1 -0
- package/dist/lib/chunk-ensure-companion-chat.mjs +49 -0
- package/dist/lib/chunk-ensure-companion-chat.mjs.map +1 -0
- package/dist/lib/chunk-extensions.mjs +78 -0
- package/dist/lib/chunk-extensions.mjs.map +1 -0
- package/dist/lib/chunk-fork-chat.mjs +83 -0
- package/dist/lib/chunk-fork-chat.mjs.map +1 -0
- package/dist/lib/chunk-generate-home-suggestions.mjs +71 -0
- package/dist/lib/chunk-generate-home-suggestions.mjs.map +1 -0
- package/dist/lib/chunk-local-model-resolver.mjs +25 -0
- package/dist/lib/chunk-local-model-resolver.mjs.map +1 -0
- package/dist/lib/chunk-markdown-extension.mjs +27 -0
- package/dist/lib/chunk-markdown-extension.mjs.map +1 -0
- package/dist/lib/{neutral/chunk-L7AR4VTA.mjs → chunk-meta.mjs} +20 -25
- package/dist/lib/chunk-meta.mjs.map +1 -0
- package/dist/lib/chunk-operation-handler.mjs +13 -0
- package/dist/lib/chunk-operation-handler.mjs.map +1 -0
- package/dist/lib/chunk-paths.mjs +8 -0
- package/dist/lib/chunk-paths.mjs.map +1 -0
- package/dist/lib/chunk-processor.mjs +432 -0
- package/dist/lib/chunk-processor.mjs.map +1 -0
- package/dist/lib/chunk-react-surface.mjs +177 -0
- package/dist/lib/chunk-react-surface.mjs.map +1 -0
- package/dist/lib/chunk-run-prompt-in-new-chat.mjs +96 -0
- package/dist/lib/chunk-run-prompt-in-new-chat.mjs.map +1 -0
- package/dist/lib/chunk-set-current-chat.mjs +43 -0
- package/dist/lib/chunk-set-current-chat.mjs.map +1 -0
- package/dist/lib/chunk-settings.mjs +23 -0
- package/dist/lib/chunk-settings.mjs.map +1 -0
- package/dist/lib/chunk-skill-definition.mjs +42 -0
- package/dist/lib/chunk-skill-definition.mjs.map +1 -0
- package/dist/lib/chunk-skills.mjs +19 -0
- package/dist/lib/chunk-skills.mjs.map +1 -0
- package/dist/lib/chunk-state.mjs +32 -0
- package/dist/lib/chunk-state.mjs.map +1 -0
- package/dist/lib/chunk-toggle-trace-panel-debug.mjs +18 -0
- package/dist/lib/chunk-toggle-trace-panel-debug.mjs.map +1 -0
- package/dist/lib/chunk-toolkit.mjs +12 -0
- package/dist/lib/chunk-toolkit.mjs.map +1 -0
- package/dist/lib/chunk-types.mjs +332 -0
- package/dist/lib/chunk-types.mjs.map +1 -0
- package/dist/lib/chunk-update-chat-name.mjs +63 -0
- package/dist/lib/chunk-update-chat-name.mjs.map +1 -0
- package/dist/lib/components.mjs +2616 -0
- package/dist/lib/components.mjs.map +1 -0
- package/dist/lib/containers.mjs +17 -0
- package/dist/lib/containers.mjs.map +1 -0
- package/dist/lib/execution-graph.mjs +961 -0
- package/dist/lib/execution-graph.mjs.map +1 -0
- package/dist/lib/extensions.mjs +2 -0
- package/dist/lib/hooks.mjs +674 -0
- package/dist/lib/hooks.mjs.map +1 -0
- package/dist/lib/index.mjs +5 -0
- package/dist/lib/meta.mjs +2 -0
- package/dist/lib/operations.mjs +7 -0
- package/dist/lib/operations.mjs.map +1 -0
- package/dist/lib/plugin.mjs +9 -0
- package/dist/lib/plugin.mjs.map +1 -0
- package/dist/lib/plugin.workerd.mjs +2 -0
- package/dist/lib/skills.mjs +2 -0
- package/dist/lib/testing.mjs +2 -0
- package/dist/lib/translations.mjs +207 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/types/src/AssistantPlugin.d.ts.map +1 -1
- package/dist/types/src/AssistantPlugin.node.d.ts.map +1 -1
- package/dist/types/src/AssistantPlugin.workerd.d.ts.map +1 -1
- package/dist/types/src/capabilities/AssistantSurfaces.d.ts +22 -0
- package/dist/types/src/capabilities/AssistantSurfaces.d.ts.map +1 -0
- package/dist/types/src/capabilities/agent-hydrator.d.ts +1 -1
- package/dist/types/src/capabilities/agent-service.d.ts +1 -1
- package/dist/types/src/capabilities/agent-service.d.ts.map +1 -1
- package/dist/types/src/capabilities/ai-context.d.ts +1 -1
- package/dist/types/src/capabilities/ai-service.d.ts +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +12 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/automation-templates.d.ts +1 -1
- package/dist/types/src/capabilities/companion-chat-provisioner.d.ts +1 -1
- package/dist/types/src/capabilities/connector.d.ts +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +1 -1
- package/dist/types/src/capabilities/edge-model-resolver.d.ts +1 -1
- package/dist/types/src/capabilities/edge-model-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +0 -2
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/local-model-resolver.d.ts +1 -1
- package/dist/types/src/capabilities/local-model-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/markdown-extension.d.ts +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/settings.d.ts +1 -1
- package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/standalone-chats-query.test.d.ts +2 -0
- package/dist/types/src/capabilities/standalone-chats-query.test.d.ts.map +1 -0
- package/dist/types/src/capabilities/state.d.ts +1 -1
- package/dist/types/src/capabilities/toolkit.d.ts +1 -1
- package/dist/types/src/components/AgentProperties/AgentProperties.d.ts +4 -1
- package/dist/types/src/components/AgentProperties/AgentProperties.d.ts.map +1 -1
- package/dist/types/src/components/AgentProperties/AgentProperties.stories.d.ts.map +1 -1
- package/dist/types/src/components/Chat/Chat.d.ts +21 -8
- package/dist/types/src/components/Chat/Chat.d.ts.map +1 -1
- package/dist/types/src/components/Chat/{Chat.stories.d.ts → Error.stories.d.ts} +1 -1
- package/dist/types/src/components/Chat/Error.stories.d.ts.map +1 -0
- package/dist/types/src/components/Chat/context.d.ts +8 -0
- package/dist/types/src/components/Chat/context.d.ts.map +1 -1
- package/dist/types/src/components/Chat/events.d.ts +5 -0
- package/dist/types/src/components/Chat/events.d.ts.map +1 -1
- package/dist/types/src/components/Chat/thread.d.ts +42 -0
- package/dist/types/src/components/Chat/thread.d.ts.map +1 -0
- package/dist/types/src/components/Chat/thread.test.d.ts +2 -0
- package/dist/types/src/components/Chat/thread.test.d.ts.map +1 -0
- package/dist/types/src/components/ChatPrompt/ChatActions.d.ts.map +1 -1
- package/dist/types/src/components/ChatPrompt/ChatOptions.stories.d.ts.map +1 -1
- package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts +5 -3
- package/dist/types/src/components/ChatPrompt/ChatPrompt.d.ts.map +1 -1
- package/dist/types/src/components/ChatPrompt/index.d.ts +0 -1
- package/dist/types/src/components/ChatPrompt/index.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/Anchor.stories.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/ChatThread.d.ts +8 -3
- package/dist/types/src/components/ChatThread/ChatThread.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/ChatThread.stories.d.ts +30 -2
- 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/index.d.ts +1 -0
- package/dist/types/src/components/ChatThread/index.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/registry.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/sync/index.d.ts +3 -0
- package/dist/types/src/components/ChatThread/sync/index.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/{sync.d.ts → sync/sync.d.ts} +46 -2
- package/dist/types/src/components/ChatThread/sync/sync.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/sync/sync.test.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/sync/tool-widget-state.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/sync/tool-widget-state.test.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/widgets/BranchWidget.d.ts +15 -0
- package/dist/types/src/components/ChatThread/widgets/BranchWidget.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/widgets/BranchWidget.stories.d.ts +21 -0
- package/dist/types/src/components/ChatThread/widgets/BranchWidget.stories.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/widgets/BranchWidget.test.d.ts +2 -0
- package/dist/types/src/components/ChatThread/widgets/BranchWidget.test.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/widgets/ReferenceWidget.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/ToolWidget.d.ts +1 -2
- package/dist/types/src/components/ChatThread/widgets/ToolWidget.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/defaults.d.ts +6 -0
- package/dist/types/src/components/ChatThread/widgets/defaults.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/format-time.d.ts +2 -0
- package/dist/types/src/components/ChatThread/widgets/format-time.d.ts.map +1 -0
- package/dist/types/src/components/ChatThread/widgets/index.d.ts +4 -1
- package/dist/types/src/components/ChatThread/widgets/index.d.ts.map +1 -1
- package/dist/types/src/components/ChatThread/widgets/is-tool-message.d.ts +3 -0
- package/dist/types/src/components/ChatThread/widgets/is-tool-message.d.ts.map +1 -0
- package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.d.ts +16 -0
- package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.d.ts.map +1 -0
- package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.stories.d.ts +210 -0
- package/dist/types/src/components/ConnectorAuthMenu/ConnectorAuthMenu.stories.d.ts.map +1 -0
- package/dist/types/src/components/ConnectorAuthMenu/index.d.ts +2 -0
- package/dist/types/src/components/ConnectorAuthMenu/index.d.ts.map +1 -0
- package/dist/types/src/components/ProcessTree/ProcessTree.d.ts +1 -1
- package/dist/types/src/components/ProcessTree/ProcessTree.d.ts.map +1 -1
- package/dist/types/src/components/TaskList/TaskList.d.ts +9 -11
- package/dist/types/src/components/TaskList/TaskList.d.ts.map +1 -1
- package/dist/types/src/components/TaskList/TaskList.stories.d.ts +3 -4
- package/dist/types/src/components/TaskList/TaskList.stories.d.ts.map +1 -1
- package/dist/types/src/components/ToolBlock/ToolBlock.d.ts +1 -2
- package/dist/types/src/components/ToolBlock/ToolBlock.d.ts.map +1 -1
- package/dist/types/src/components/ToolBlock/index.d.ts +1 -0
- package/dist/types/src/components/ToolBlock/index.d.ts.map +1 -1
- package/dist/types/src/components/ToolBlock/is-tool-message.d.ts +3 -0
- package/dist/types/src/components/ToolBlock/is-tool-message.d.ts.map +1 -0
- package/dist/types/src/components/Toolbox/Toolbox.d.ts +1 -1
- package/dist/types/src/components/Toolbox/Toolbox.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/AgentArticle/AgentArticle.d.ts +5 -2
- package/dist/types/src/containers/AgentArticle/AgentArticle.d.ts.map +1 -1
- package/dist/types/src/containers/AgentArticle/AgentArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/AgentProperties/AgentProperties.d.ts +4 -1
- package/dist/types/src/containers/AgentProperties/AgentProperties.d.ts.map +1 -1
- package/dist/types/src/containers/AssistantSettings/AssistantSettings.d.ts +4 -1
- package/dist/types/src/containers/AssistantSettings/AssistantSettings.d.ts.map +1 -1
- package/dist/types/src/containers/AssistantSettings/AssistantSettings.stories.d.ts +4 -1
- package/dist/types/src/containers/AssistantSettings/AssistantSettings.stories.d.ts.map +1 -1
- package/dist/types/src/containers/AssistantSettings/OllamaModels.d.ts +4 -6
- package/dist/types/src/containers/AssistantSettings/OllamaModels.d.ts.map +1 -1
- package/dist/types/src/containers/ChatArticle/ChatArticle.d.ts.map +1 -1
- package/dist/types/src/containers/ChatArticle/ChatArticle.stories.d.ts +22 -1
- package/dist/types/src/containers/ChatArticle/ChatArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/ChatCompanion/ChatCompanion.d.ts.map +1 -1
- package/dist/types/src/containers/ChatDialog/ChatDialog.d.ts +4 -1
- package/dist/types/src/containers/ChatDialog/ChatDialog.d.ts.map +1 -1
- package/dist/types/src/containers/IntegrationPrompt/IntegrationPrompt.d.ts +4 -7
- package/dist/types/src/containers/IntegrationPrompt/IntegrationPrompt.d.ts.map +1 -1
- package/dist/types/src/containers/SpaceHomePrompt/SpaceHomePrompt.d.ts +4 -9
- package/dist/types/src/containers/SpaceHomePrompt/SpaceHomePrompt.d.ts.map +1 -1
- package/dist/types/src/containers/SpaceHomeSuggestions/SpaceHomeSuggestions.d.ts +5 -7
- package/dist/types/src/containers/SpaceHomeSuggestions/SpaceHomeSuggestions.d.ts.map +1 -1
- package/dist/types/src/containers/TracePanel/TracePanel.d.ts +1 -1
- package/dist/types/src/containers/TracePanel/TracePanel.d.ts.map +1 -1
- package/dist/types/src/containers/TracePanel/TracePanel.stories.d.ts.map +1 -1
- package/dist/types/src/containers/TriggerStatus/TriggerStatus.d.ts +15 -1
- package/dist/types/src/containers/TriggerStatus/TriggerStatus.d.ts.map +1 -1
- package/dist/types/src/containers/index.d.ts +0 -1
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/execution-graph/execution-graph.d.ts +12 -1
- package/dist/types/src/execution-graph/execution-graph.d.ts.map +1 -1
- package/dist/types/src/execution-graph/index.d.ts +1 -1
- package/dist/types/src/execution-graph/index.d.ts.map +1 -1
- package/dist/types/src/execution-graph/pending-block-status.d.ts.map +1 -1
- package/dist/types/src/execution-graph/span-tree.d.ts +17 -0
- package/dist/types/src/execution-graph/span-tree.d.ts.map +1 -1
- package/dist/types/src/feed-logger.d.ts +1 -1
- package/dist/types/src/feed-logger.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useChatProcessor.d.ts.map +1 -1
- package/dist/types/src/hooks/useChatToolbarActions.d.ts.map +1 -1
- package/dist/types/src/hooks/useContextObjects.d.ts +1 -1
- package/dist/types/src/hooks/useContextObjects.d.ts.map +1 -1
- package/dist/types/src/hooks/useSelectionContext.d.ts +13 -0
- package/dist/types/src/hooks/useSelectionContext.d.ts.map +1 -0
- package/dist/types/src/hooks/useSelectionContext.test.d.ts +2 -0
- package/dist/types/src/hooks/useSelectionContext.test.d.ts.map +1 -0
- package/dist/types/src/hooks/useTraceMessages.d.ts.map +1 -1
- package/dist/types/src/operations/index.d.ts.map +1 -1
- package/dist/types/src/processor/index.d.ts +1 -0
- package/dist/types/src/processor/index.d.ts.map +1 -1
- package/dist/types/src/processor/processor.d.ts +5 -2
- package/dist/types/src/processor/processor.d.ts.map +1 -1
- package/dist/types/src/processor/prompt.d.ts +18 -0
- package/dist/types/src/processor/prompt.d.ts.map +1 -0
- package/dist/types/src/processor/prompt.test.d.ts +2 -0
- package/dist/types/src/processor/prompt.test.d.ts.map +1 -0
- package/dist/types/src/processor/streaming.node.test.d.ts +2 -0
- package/dist/types/src/processor/streaming.node.test.d.ts.map +1 -0
- package/dist/types/src/skills/assistant/skill.d.ts.map +1 -1
- package/dist/types/src/templates/scaffold.d.ts +1 -1
- package/dist/types/src/templates/scaffold.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/AssistantCapabilities.d.ts +1 -1
- package/dist/types/src/types/AssistantCapabilities.d.ts.map +1 -1
- package/dist/types/src/types/AssistantOperation.d.ts +2 -13
- package/dist/types/src/types/AssistantOperation.d.ts.map +1 -1
- package/dist/types/src/types/ChatSurface.d.ts +2 -2
- package/dist/types/src/types/ChatSurface.d.ts.map +1 -1
- package/dist/types/src/types/Ollama.d.ts +1 -1
- package/dist/types/src/types/Ollama.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +1 -0
- package/package.json +106 -105
- package/src/AssistantPlugin.node.ts +1 -2
- package/src/AssistantPlugin.test.ts +60 -62
- package/src/AssistantPlugin.ts +1 -10
- package/src/AssistantPlugin.workerd.ts +1 -2
- package/src/capabilities/AssistantSurfaces.tsx +86 -0
- package/src/capabilities/agent-service.ts +1 -1
- package/src/capabilities/app-graph-builder.ts +31 -17
- package/src/capabilities/companion-chat-provisioner.ts +12 -11
- package/src/capabilities/connector.ts +3 -3
- package/src/capabilities/edge-model-resolver.ts +5 -2
- package/src/capabilities/index.ts +0 -2
- package/src/capabilities/react-surface.ts +135 -0
- package/src/capabilities/skill-definition.ts +4 -0
- package/src/capabilities/standalone-chats-query.test.ts +51 -0
- package/src/capabilities/state.ts +1 -1
- package/src/components/AgentProperties/AgentProperties.stories.tsx +6 -7
- package/src/components/AgentProperties/AgentProperties.tsx +37 -30
- package/src/components/Chat/Chat.tsx +275 -59
- package/src/components/Chat/{Chat.stories.tsx → Error.stories.tsx} +1 -1
- package/src/components/Chat/context.ts +8 -0
- package/src/components/Chat/events.ts +5 -0
- package/src/components/Chat/thread.test.ts +127 -0
- package/src/components/Chat/thread.ts +87 -0
- package/src/components/ChatPrompt/ChatActions.tsx +8 -8
- package/src/components/ChatPrompt/ChatMcpErrors.tsx +2 -2
- package/src/components/ChatPrompt/ChatOptions.stories.tsx +2 -1
- package/src/components/ChatPrompt/ChatOptions.tsx +5 -5
- package/src/components/ChatPrompt/ChatPrompt.tsx +33 -6
- package/src/components/ChatPrompt/index.ts +0 -1
- package/src/components/ChatThread/Anchor.stories.tsx +2 -1
- package/src/components/ChatThread/ChatThread.stories.tsx +99 -4
- package/src/components/ChatThread/ChatThread.tsx +34 -6
- package/src/components/ChatThread/Link.tsx +1 -0
- package/src/components/ChatThread/index.ts +2 -0
- package/src/components/ChatThread/registry.tsx +28 -4
- package/src/components/ChatThread/sync/index.ts +6 -0
- package/src/components/ChatThread/{sync.test.ts → sync/sync.test.ts} +167 -7
- package/src/components/ChatThread/{sync.ts → sync/sync.ts} +97 -3
- package/src/components/ChatThread/{tool-widget-state.ts → sync/tool-widget-state.ts} +1 -3
- package/src/components/ChatThread/widgets/BranchWidget.stories.tsx +83 -0
- package/src/components/ChatThread/widgets/BranchWidget.test.ts +55 -0
- package/src/components/ChatThread/widgets/BranchWidget.tsx +61 -0
- package/src/components/ChatThread/widgets/FallbackWidget.tsx +2 -2
- package/src/components/ChatThread/widgets/ReasoningWidget.ts +1 -1
- package/src/components/ChatThread/widgets/ReferenceWidget.ts +1 -6
- package/src/components/ChatThread/widgets/SuggestionWidget.ts +12 -3
- package/src/components/ChatThread/widgets/SummaryWidget.tsx +1 -1
- package/src/components/ChatThread/widgets/ToolWidget.tsx +15 -9
- package/src/components/ChatThread/widgets/defaults.ts +7 -1
- package/src/components/ChatThread/widgets/format-time.ts +45 -0
- package/src/components/ChatThread/widgets/index.ts +4 -1
- package/src/components/ChatThread/widgets/is-tool-message.ts +13 -0
- package/src/components/ConnectorAuthMenu/ConnectorAuthMenu.stories.tsx +177 -0
- package/src/components/ConnectorAuthMenu/ConnectorAuthMenu.tsx +82 -0
- package/src/components/ConnectorAuthMenu/index.ts +5 -0
- package/src/components/ProcessTree/ProcessTree.stories.tsx +1 -1
- package/src/components/TaskList/TaskList.stories.tsx +19 -26
- package/src/components/TaskList/TaskList.tsx +32 -104
- package/src/components/ToolBlock/ToolBlock.tsx +1 -5
- package/src/components/ToolBlock/index.ts +1 -0
- package/src/components/ToolBlock/is-tool-message.ts +13 -0
- package/src/components/Toolbox/Toolbox.tsx +1 -1
- package/src/components/index.ts +1 -0
- package/src/containers/AgentArticle/AgentArticle.stories.tsx +18 -11
- package/src/containers/AgentArticle/AgentArticle.tsx +27 -151
- package/src/containers/AgentProperties/AgentProperties.tsx +21 -17
- package/src/containers/AssistantSettings/AssistantSettings.tsx +2 -0
- package/src/containers/AssistantSettings/OllamaModels.tsx +6 -4
- package/src/containers/ChatArticle/ChatArticle.stories.tsx +200 -27
- package/src/containers/ChatArticle/ChatArticle.tsx +25 -5
- package/src/containers/ChatCompanion/ChatCompanion.tsx +45 -10
- package/src/containers/ChatDialog/ChatDialog.tsx +4 -1
- package/src/containers/IntegrationPrompt/IntegrationPrompt.tsx +9 -6
- package/src/containers/SpaceHomePrompt/SpaceHomePrompt.tsx +2 -0
- package/src/containers/SpaceHomeSuggestions/SpaceHomeSuggestions.tsx +40 -39
- package/src/containers/TracePanel/TracePanel.stories.tsx +9 -4
- package/src/containers/TracePanel/TracePanel.tsx +22 -6
- package/src/containers/TriggerStatus/TriggerStatus.tsx +9 -16
- package/src/containers/index.ts +0 -1
- package/src/execution-graph/SPEC.md +60 -2
- package/src/execution-graph/execution-graph.ts +15 -2
- package/src/execution-graph/index.ts +1 -0
- package/src/execution-graph/pending-block-status.ts +3 -2
- package/src/execution-graph/span-tree.test.ts +87 -1
- package/src/execution-graph/span-tree.ts +95 -0
- package/src/feed-logger.ts +6 -6
- package/src/hooks/index.ts +1 -1
- package/src/hooks/useChatProcessor.ts +2 -1
- package/src/hooks/useChatToolbarActions.ts +22 -19
- package/src/hooks/useContextObjects.ts +9 -3
- package/src/hooks/useSelectionContext.test.ts +93 -0
- package/src/hooks/useSelectionContext.ts +72 -0
- package/src/hooks/useSkillRegistry.ts +1 -1
- package/src/hooks/useTraceMessages.ts +5 -3
- package/src/operations/create-chat.ts +2 -2
- package/src/operations/fork-chat.ts +2 -2
- package/src/operations/generate-home-suggestions.test.ts +2 -2
- package/src/operations/index.ts +0 -1
- package/src/operations/prompt.node.test.ts +1 -1
- package/src/paths.ts +3 -3
- package/src/processor/index.ts +1 -0
- package/src/processor/processor.node.test.ts +1 -1
- package/src/processor/processor.ts +33 -5
- package/src/processor/prompt.test.ts +37 -0
- package/src/processor/prompt.ts +42 -0
- package/src/processor/streaming.node.test.ts +196 -0
- package/src/skills/assistant/skill.node.test.ts +2 -2
- package/src/skills/assistant/skill.ts +3 -5
- package/src/templates/routine-templates.test.ts +1 -2
- package/src/templates/scaffold.ts +3 -3
- package/src/testing/data/trace-timeline-multiple.dx.json +1 -1
- package/src/testing/data/trace-timeline-remote.dx.json +1 -1
- package/src/testing/data/trace-timeline.dx.json +1 -2
- package/src/testing/trace-timeline.node.test.ts +3 -3
- package/src/translations.ts +11 -10
- package/src/types/AssistantCapabilities.ts +1 -1
- package/src/types/AssistantOperation.ts +8 -31
- package/src/types/ChatSurface.ts +3 -3
- package/src/types/Ollama.ts +1 -1
- package/dist/lib/neutral/AgentArticle-GV6EEW3I.mjs +0 -161
- package/dist/lib/neutral/AgentArticle-GV6EEW3I.mjs.map +0 -7
- package/dist/lib/neutral/AgentProperties-LFTEYJ54.mjs +0 -40
- package/dist/lib/neutral/AgentProperties-LFTEYJ54.mjs.map +0 -7
- package/dist/lib/neutral/AssistantPlugin.mjs +0 -10
- package/dist/lib/neutral/AssistantPlugin.mjs.map +0 -7
- package/dist/lib/neutral/AssistantPlugin.node.mjs +0 -72
- package/dist/lib/neutral/AssistantPlugin.node.mjs.map +0 -7
- package/dist/lib/neutral/AssistantPlugin.workerd.mjs +0 -13
- package/dist/lib/neutral/AssistantPlugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/AssistantSettings-3N5M5VCN.mjs +0 -302
- package/dist/lib/neutral/AssistantSettings-3N5M5VCN.mjs.map +0 -7
- package/dist/lib/neutral/ChatArticle-OO7GGEFW.mjs +0 -8
- package/dist/lib/neutral/ChatArticle-OO7GGEFW.mjs.map +0 -7
- package/dist/lib/neutral/ChatCompanion-GIFJRY6I.mjs +0 -128
- package/dist/lib/neutral/ChatCompanion-GIFJRY6I.mjs.map +0 -7
- package/dist/lib/neutral/ChatDialog-5MXN4MXS.mjs +0 -74
- package/dist/lib/neutral/ChatDialog-5MXN4MXS.mjs.map +0 -7
- package/dist/lib/neutral/IntegrationPrompt-2HJQFYJE.mjs +0 -72
- package/dist/lib/neutral/IntegrationPrompt-2HJQFYJE.mjs.map +0 -7
- package/dist/lib/neutral/PlanArticle-VPK2IYWU.mjs +0 -34
- package/dist/lib/neutral/PlanArticle-VPK2IYWU.mjs.map +0 -7
- package/dist/lib/neutral/SpaceHomePrompt-ISAB76LD.mjs +0 -114
- package/dist/lib/neutral/SpaceHomePrompt-ISAB76LD.mjs.map +0 -7
- package/dist/lib/neutral/SpaceHomeSuggestions-IDH77QQR.mjs +0 -63
- package/dist/lib/neutral/SpaceHomeSuggestions-IDH77QQR.mjs.map +0 -7
- package/dist/lib/neutral/TracePanel-JKNWADJ4.mjs +0 -12
- package/dist/lib/neutral/TracePanel-JKNWADJ4.mjs.map +0 -7
- package/dist/lib/neutral/TriggerStatus-FURRBHYA.mjs +0 -95
- package/dist/lib/neutral/TriggerStatus-FURRBHYA.mjs.map +0 -7
- package/dist/lib/neutral/agent-hydrator-OBO3RHLO.mjs +0 -23
- package/dist/lib/neutral/agent-hydrator-OBO3RHLO.mjs.map +0 -7
- package/dist/lib/neutral/agent-service-XFJ4VQMT.mjs +0 -32
- package/dist/lib/neutral/agent-service-XFJ4VQMT.mjs.map +0 -7
- package/dist/lib/neutral/ai-context-LIKJYMIN.mjs.map +0 -7
- package/dist/lib/neutral/ai-service-DM6YXWUC.mjs +0 -44
- package/dist/lib/neutral/ai-service-DM6YXWUC.mjs.map +0 -7
- package/dist/lib/neutral/app-graph-builder-OPVOEQY7.mjs +0 -249
- package/dist/lib/neutral/app-graph-builder-OPVOEQY7.mjs.map +0 -7
- package/dist/lib/neutral/automation-templates-MADJLXGJ.mjs +0 -97
- package/dist/lib/neutral/automation-templates-MADJLXGJ.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/index.mjs +0 -47
- package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
- package/dist/lib/neutral/chunk-5IHQ52KJ.mjs +0 -9
- package/dist/lib/neutral/chunk-5IHQ52KJ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-6Q4OBGIK.mjs +0 -420
- package/dist/lib/neutral/chunk-6Q4OBGIK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BXI2R4OO.mjs +0 -410
- package/dist/lib/neutral/chunk-BXI2R4OO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-CMPLPDYE.mjs +0 -30
- package/dist/lib/neutral/chunk-CMPLPDYE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GPHT3HYS.mjs +0 -8
- package/dist/lib/neutral/chunk-GPHT3HYS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-HKLSFB5I.mjs +0 -90
- package/dist/lib/neutral/chunk-HKLSFB5I.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-L7AR4VTA.mjs.map +0 -7
- package/dist/lib/neutral/chunk-LS72HWMM.mjs +0 -42
- package/dist/lib/neutral/chunk-LS72HWMM.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OZWZGIV2.mjs +0 -12
- package/dist/lib/neutral/chunk-OZWZGIV2.mjs.map +0 -7
- package/dist/lib/neutral/chunk-QOKLFHUS.mjs +0 -13
- package/dist/lib/neutral/chunk-QOKLFHUS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SCTHQVIJ.mjs +0 -155
- package/dist/lib/neutral/chunk-SCTHQVIJ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-U4LTLBAX.mjs +0 -56
- package/dist/lib/neutral/chunk-U4LTLBAX.mjs.map +0 -7
- package/dist/lib/neutral/chunk-UPKFUZ6V.mjs +0 -115
- package/dist/lib/neutral/chunk-UPKFUZ6V.mjs.map +0 -7
- package/dist/lib/neutral/chunk-V2Y4XE3O.mjs +0 -12
- package/dist/lib/neutral/chunk-V2Y4XE3O.mjs.map +0 -7
- package/dist/lib/neutral/chunk-VTK5R4H3.mjs +0 -9
- package/dist/lib/neutral/chunk-VTK5R4H3.mjs.map +0 -7
- package/dist/lib/neutral/chunk-XVGEJWJX.mjs +0 -133
- package/dist/lib/neutral/chunk-XVGEJWJX.mjs.map +0 -7
- package/dist/lib/neutral/companion-chat-provisioner-IQV5VIVE.mjs +0 -126
- package/dist/lib/neutral/companion-chat-provisioner-IQV5VIVE.mjs.map +0 -7
- package/dist/lib/neutral/components/index.mjs +0 -2527
- package/dist/lib/neutral/components/index.mjs.map +0 -7
- package/dist/lib/neutral/connector-ITLLTBPZ.mjs +0 -70
- package/dist/lib/neutral/connector-ITLLTBPZ.mjs.map +0 -7
- package/dist/lib/neutral/containers/index.mjs +0 -31
- package/dist/lib/neutral/containers/index.mjs.map +0 -7
- package/dist/lib/neutral/create-chat-YGVZZYGP.mjs +0 -56
- package/dist/lib/neutral/create-chat-YGVZZYGP.mjs.map +0 -7
- package/dist/lib/neutral/create-object-5PAEJ6KM.mjs +0 -76
- package/dist/lib/neutral/create-object-5PAEJ6KM.mjs.map +0 -7
- package/dist/lib/neutral/edge-model-resolver-WDJWDZTT.mjs +0 -55
- package/dist/lib/neutral/edge-model-resolver-WDJWDZTT.mjs.map +0 -7
- package/dist/lib/neutral/ensure-companion-chat-AMOF3C66.mjs +0 -58
- package/dist/lib/neutral/ensure-companion-chat-AMOF3C66.mjs.map +0 -7
- package/dist/lib/neutral/execution-graph/index.mjs +0 -977
- package/dist/lib/neutral/execution-graph/index.mjs.map +0 -7
- package/dist/lib/neutral/extensions/index.mjs +0 -8
- package/dist/lib/neutral/extensions/index.mjs.map +0 -7
- package/dist/lib/neutral/fork-chat-RMAAYYQF.mjs +0 -92
- package/dist/lib/neutral/fork-chat-RMAAYYQF.mjs.map +0 -7
- package/dist/lib/neutral/generate-home-suggestions-6MM2XWPV.mjs +0 -93
- package/dist/lib/neutral/generate-home-suggestions-6MM2XWPV.mjs.map +0 -7
- package/dist/lib/neutral/hooks/index.mjs +0 -877
- package/dist/lib/neutral/hooks/index.mjs.map +0 -7
- package/dist/lib/neutral/index.mjs +0 -42
- package/dist/lib/neutral/index.mjs.map +0 -7
- package/dist/lib/neutral/local-model-resolver-I2BENFFS.mjs +0 -24
- package/dist/lib/neutral/local-model-resolver-I2BENFFS.mjs.map +0 -7
- package/dist/lib/neutral/markdown-extension-R4TKDTIF.mjs +0 -41
- package/dist/lib/neutral/markdown-extension-R4TKDTIF.mjs.map +0 -7
- package/dist/lib/neutral/meta.json +0 -1
- package/dist/lib/neutral/meta.mjs +0 -12
- package/dist/lib/neutral/meta.mjs.map +0 -7
- package/dist/lib/neutral/migrations-7DEMVBOG.mjs +0 -28
- package/dist/lib/neutral/migrations-7DEMVBOG.mjs.map +0 -7
- package/dist/lib/neutral/navigation-resolver-PYGP2DAW.mjs +0 -18
- package/dist/lib/neutral/navigation-resolver-PYGP2DAW.mjs.map +0 -7
- package/dist/lib/neutral/operation-handler-2LEN45GP.mjs +0 -8
- package/dist/lib/neutral/operation-handler-2LEN45GP.mjs.map +0 -7
- package/dist/lib/neutral/operations/index.mjs +0 -8
- package/dist/lib/neutral/operations/index.mjs.map +0 -7
- package/dist/lib/neutral/plugin.mjs +0 -16
- package/dist/lib/neutral/plugin.mjs.map +0 -7
- package/dist/lib/neutral/plugin.workerd.mjs +0 -13
- package/dist/lib/neutral/plugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/react-surface-HEJEK44F.mjs +0 -171
- package/dist/lib/neutral/react-surface-HEJEK44F.mjs.map +0 -7
- package/dist/lib/neutral/resolve-navigation-targets-PBQ3OLUE.mjs +0 -28
- package/dist/lib/neutral/resolve-navigation-targets-PBQ3OLUE.mjs.map +0 -7
- package/dist/lib/neutral/run-prompt-in-new-chat-RNUJE2FM.mjs +0 -102
- package/dist/lib/neutral/run-prompt-in-new-chat-RNUJE2FM.mjs.map +0 -7
- package/dist/lib/neutral/set-current-chat-VWBPSIMZ.mjs +0 -48
- package/dist/lib/neutral/set-current-chat-VWBPSIMZ.mjs.map +0 -7
- package/dist/lib/neutral/settings-7Q3RITIT.mjs +0 -28
- package/dist/lib/neutral/settings-7Q3RITIT.mjs.map +0 -7
- package/dist/lib/neutral/skill-definition-553MQRTR.mjs +0 -8
- package/dist/lib/neutral/skill-definition-553MQRTR.mjs.map +0 -7
- package/dist/lib/neutral/skills/index.mjs +0 -8
- package/dist/lib/neutral/skills/index.mjs.map +0 -7
- package/dist/lib/neutral/state-4LGAKSSD.mjs +0 -34
- package/dist/lib/neutral/state-4LGAKSSD.mjs.map +0 -7
- package/dist/lib/neutral/testing.mjs +0 -8
- package/dist/lib/neutral/testing.mjs.map +0 -7
- package/dist/lib/neutral/toggle-trace-panel-debug-JGTB6KVJ.mjs +0 -21
- package/dist/lib/neutral/toggle-trace-panel-debug-JGTB6KVJ.mjs.map +0 -7
- package/dist/lib/neutral/toolkit-ETWLG5NT.mjs +0 -8
- package/dist/lib/neutral/toolkit-ETWLG5NT.mjs.map +0 -7
- package/dist/lib/neutral/translations.mjs +0 -217
- package/dist/lib/neutral/translations.mjs.map +0 -7
- package/dist/lib/neutral/types/index.mjs +0 -24
- package/dist/lib/neutral/types/index.mjs.map +0 -7
- package/dist/lib/neutral/update-chat-name-IJJELRR6.mjs +0 -61
- package/dist/lib/neutral/update-chat-name-IJJELRR6.mjs.map +0 -7
- package/dist/types/src/capabilities/migrations.d.ts +0 -5
- package/dist/types/src/capabilities/migrations.d.ts.map +0 -1
- package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -5
- package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
- package/dist/types/src/components/Chat/Chat.stories.d.ts.map +0 -1
- package/dist/types/src/components/ChatPrompt/ChatStatusIndicator.d.ts +0 -10
- package/dist/types/src/components/ChatPrompt/ChatStatusIndicator.d.ts.map +0 -1
- package/dist/types/src/components/ChatThread/sync.d.ts.map +0 -1
- package/dist/types/src/components/ChatThread/sync.test.d.ts.map +0 -1
- package/dist/types/src/components/ChatThread/tool-widget-state.d.ts.map +0 -1
- package/dist/types/src/components/ChatThread/tool-widget-state.test.d.ts.map +0 -1
- package/dist/types/src/containers/PlanArticle/PlanArticle.d.ts +0 -6
- package/dist/types/src/containers/PlanArticle/PlanArticle.d.ts.map +0 -1
- package/dist/types/src/containers/PlanArticle/index.d.ts +0 -2
- package/dist/types/src/containers/PlanArticle/index.d.ts.map +0 -1
- package/dist/types/src/hooks/useFlush.d.ts +0 -6
- package/dist/types/src/hooks/useFlush.d.ts.map +0 -1
- package/dist/types/src/operations/resolve-navigation-targets.d.ts +0 -5
- package/dist/types/src/operations/resolve-navigation-targets.d.ts.map +0 -1
- package/src/AssistantPlugin.conversations.json +0 -1
- package/src/capabilities/migrations.ts +0 -28
- package/src/capabilities/navigation-resolver.ts +0 -20
- package/src/capabilities/react-surface.tsx +0 -177
- package/src/components/ChatPrompt/ChatStatusIndicator.tsx +0 -42
- package/src/components/ChatThread/DEBUG.md +0 -64
- package/src/containers/PlanArticle/PlanArticle.tsx +0 -37
- package/src/containers/PlanArticle/index.ts +0 -5
- package/src/hooks/useFlush.ts +0 -35
- package/src/operations/resolve-navigation-targets.ts +0 -44
- /package/dist/types/src/components/ChatThread/{sync.test.d.ts → sync/sync.test.d.ts} +0 -0
- /package/dist/types/src/components/ChatThread/{tool-widget-state.d.ts → sync/tool-widget-state.d.ts} +0 -0
- /package/dist/types/src/components/ChatThread/{tool-widget-state.test.d.ts → sync/tool-widget-state.test.d.ts} +0 -0
- /package/src/components/ChatThread/{tool-widget-state.test.ts → sync/tool-widget-state.test.ts} +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Array from 'effect/Array';
|
|
6
|
+
import { describe, test } from 'vitest';
|
|
7
|
+
|
|
8
|
+
import { Feed, Obj } from '@dxos/echo';
|
|
9
|
+
import { Message } from '@dxos/types';
|
|
10
|
+
|
|
11
|
+
import { byAppendOrder, projectThread, resolveRewind } from './thread';
|
|
12
|
+
|
|
13
|
+
describe('byAppendOrder', () => {
|
|
14
|
+
test('orders by feed position when it discriminates', ({ expect }) => {
|
|
15
|
+
const a = positioned(message('a'), 2);
|
|
16
|
+
const b = positioned(message('b'), 1);
|
|
17
|
+
expect(sortText([a, b])).toEqual(['b', 'a']);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Positions are assigned by the server: with no position authority every block reports `+Infinity`,
|
|
21
|
+
// and a query returns an unordered set, so position alone leaves them arbitrary.
|
|
22
|
+
test('falls back to created when positions are absent', ({ expect }) => {
|
|
23
|
+
const first = message('first');
|
|
24
|
+
const second = message('second');
|
|
25
|
+
expect(sortText([second, first])).toEqual(['first', 'second']);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('an unpositioned message sorts after a positioned one', ({ expect }) => {
|
|
29
|
+
const acknowledged = positioned(message('acknowledged'), 7);
|
|
30
|
+
const local = message('local');
|
|
31
|
+
expect(sortText([local, acknowledged])).toEqual(['acknowledged', 'local']);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('projectThread', () => {
|
|
36
|
+
test('a feed with no lineage projects to itself', ({ expect }) => {
|
|
37
|
+
const messages = [message('one'), message('two'), message('three')];
|
|
38
|
+
expect(text(projectThread({ feedMessages: messages }).messages)).toEqual(['one', 'two', 'three']);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('pending messages are appended and deduped against the feed', ({ expect }) => {
|
|
42
|
+
const persisted = message('persisted');
|
|
43
|
+
const pending = message('pending');
|
|
44
|
+
const { messages } = projectThread({
|
|
45
|
+
feedMessages: [persisted, pending],
|
|
46
|
+
pendingMessages: [pending],
|
|
47
|
+
});
|
|
48
|
+
expect(text(messages)).toEqual(['persisted', 'pending']);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('lineage hides the turns a fork abandoned', ({ expect }) => {
|
|
52
|
+
const first = message('first');
|
|
53
|
+
const answer = message('answer');
|
|
54
|
+
const abandoned = message('abandoned');
|
|
55
|
+
const retry = message('retry');
|
|
56
|
+
Feed.setParent(retry, answer);
|
|
57
|
+
|
|
58
|
+
const { messages } = projectThread({ feedMessages: [first, answer, abandoned, retry] });
|
|
59
|
+
expect(text(messages)).toEqual(['first', 'answer', 'retry']);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Edit-and-resend: rewinding to a prompt discards the prompt and everything after it, so the user can
|
|
63
|
+
// revise the question rather than stare at it unanswered.
|
|
64
|
+
test('a pending rewind truncates to what precedes it', ({ expect }) => {
|
|
65
|
+
const first = message('first');
|
|
66
|
+
const answer = message('answer');
|
|
67
|
+
const asked = message('asked');
|
|
68
|
+
const replied = message('replied');
|
|
69
|
+
|
|
70
|
+
const { messages } = projectThread({
|
|
71
|
+
feedMessages: [first, answer, asked, replied],
|
|
72
|
+
rewindFrom: asked.id,
|
|
73
|
+
});
|
|
74
|
+
expect(text(messages)).toEqual(['first', 'answer']);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('rewinding to the first turn empties the thread', ({ expect }) => {
|
|
78
|
+
const first = message('first');
|
|
79
|
+
const answer = message('answer');
|
|
80
|
+
const { messages } = projectThread({ feedMessages: [first, answer], rewindFrom: first.id });
|
|
81
|
+
expect(messages).toEqual([]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('a stale rewind pointer falls back to the feed lineage', ({ expect }) => {
|
|
85
|
+
const first = message('first');
|
|
86
|
+
const answer = message('answer');
|
|
87
|
+
const { messages } = projectThread({
|
|
88
|
+
feedMessages: [first, answer],
|
|
89
|
+
rewindFrom: message('never replicated').id,
|
|
90
|
+
});
|
|
91
|
+
expect(text(messages)).toEqual(['first', 'answer']);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('an empty feed projects nothing', ({ expect }) => {
|
|
95
|
+
expect(projectThread({ feedMessages: [] }).messages).toEqual([]);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('resolveRewind', () => {
|
|
100
|
+
test('returns the discard point and the prompt text to restore', ({ expect }) => {
|
|
101
|
+
const prompt = message('what is a feed?');
|
|
102
|
+
const resolved = resolveRewind([message('earlier'), prompt], prompt.id);
|
|
103
|
+
expect(resolved).toEqual({ rewindFrom: prompt.id, text: 'what is a feed?' });
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('an absent message resolves to nothing, so a stale click is a no-op', ({ expect }) => {
|
|
107
|
+
expect(resolveRewind([message('only')], message('absent').id)).toBeUndefined();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
let clock = 0;
|
|
112
|
+
|
|
113
|
+
const message = (text: string, sender: 'user' | 'assistant' = 'user') =>
|
|
114
|
+
Message.make({ created: new Date(clock++).toISOString(), sender, blocks: [{ _tag: 'text', text }] });
|
|
115
|
+
|
|
116
|
+
/** Stamps the queue position a position authority would have assigned. */
|
|
117
|
+
const positioned = (message: Message.Message, position: number) => {
|
|
118
|
+
Obj.update(message, (message) => {
|
|
119
|
+
Obj.getMeta(message).keys.push({ source: Feed.POSITION_KEY, id: String(position) });
|
|
120
|
+
});
|
|
121
|
+
return message;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const text = (messages: readonly Message.Message[]) =>
|
|
125
|
+
messages.map((message) => (message.blocks[0] as { text: string }).text);
|
|
126
|
+
|
|
127
|
+
const sortText = (messages: Message.Message[]) => text(Array.sort(messages, byAppendOrder));
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Array from 'effect/Array';
|
|
6
|
+
import * as Order from 'effect/Order';
|
|
7
|
+
|
|
8
|
+
import { Feed } from '@dxos/echo';
|
|
9
|
+
import { Message } from '@dxos/types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Append order for {@link Feed.history}, which walks lineage positionally rather than by time.
|
|
13
|
+
*
|
|
14
|
+
* Position is authoritative but server-assigned: locally-written blocks — and every block until a
|
|
15
|
+
* position authority acknowledges them — report `+Infinity`, and a query returns an unordered set, so
|
|
16
|
+
* position alone leaves them in arbitrary order. `created` breaks those ties: sound locally, where one
|
|
17
|
+
* conversation's messages come off one clock, and consulted only when position cannot decide.
|
|
18
|
+
*/
|
|
19
|
+
export const byAppendOrder: Order.Order<Message.Message> = (a, b) => {
|
|
20
|
+
const positionA = Feed.getPosition(a);
|
|
21
|
+
const positionB = Feed.getPosition(b);
|
|
22
|
+
if (positionA !== positionB) {
|
|
23
|
+
return positionA < positionB ? -1 : 1;
|
|
24
|
+
}
|
|
25
|
+
return a.created < b.created ? -1 : a.created > b.created ? 1 : 0;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type ThreadProjection = {
|
|
29
|
+
/** The turns to render, in append order. */
|
|
30
|
+
messages: Message.Message[];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The turns a thread should render: those reachable from the feed's head, so a rewind's abandoned turns
|
|
35
|
+
* disappear from the view exactly as they disappear from the model's history.
|
|
36
|
+
*
|
|
37
|
+
* A pending `rewindFrom` truncates the view to what precedes it — the rewound-to prompt and everything
|
|
38
|
+
* after it, since the point of rewinding to a prompt is to re-ask it. The pointer is cleared by the next
|
|
39
|
+
* append (which turns the fork into lineage), so a rewind that is never followed through stays visible
|
|
40
|
+
* as a truncated thread with the prompt restored in the composer.
|
|
41
|
+
*/
|
|
42
|
+
export const projectThread = ({
|
|
43
|
+
feedMessages,
|
|
44
|
+
pendingMessages = [],
|
|
45
|
+
rewindFrom,
|
|
46
|
+
}: {
|
|
47
|
+
feedMessages: readonly Message.Message[];
|
|
48
|
+
/** Messages produced by the current turn that are not in the feed yet. */
|
|
49
|
+
pendingMessages?: readonly Message.Message[];
|
|
50
|
+
/** Earliest message a pending rewind discards. */
|
|
51
|
+
rewindFrom?: string;
|
|
52
|
+
}): ThreadProjection => {
|
|
53
|
+
const all = Array.dedupeWith([...feedMessages, ...pendingMessages], ({ id: a }, { id: b }) => a === b);
|
|
54
|
+
const sorted = Array.sort(all, byAppendOrder);
|
|
55
|
+
|
|
56
|
+
if (rewindFrom !== undefined) {
|
|
57
|
+
const index = sorted.findIndex((message) => message.id === rewindFrom);
|
|
58
|
+
if (index === 0) {
|
|
59
|
+
// Rewound to the first turn: nothing precedes it.
|
|
60
|
+
return { messages: [] };
|
|
61
|
+
}
|
|
62
|
+
if (index > 0) {
|
|
63
|
+
return { messages: Feed.history(sorted, { head: sorted[index - 1].id }).items };
|
|
64
|
+
}
|
|
65
|
+
// Not present — a stale pointer (e.g. the message never replicated); fall through to the feed's
|
|
66
|
+
// own lineage rather than blanking the thread.
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return { messages: Feed.history(sorted).items };
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* What a rewind to `messageId` implies: the messages to discard from, and the prompt text to restore so
|
|
74
|
+
* the user can edit and resend it.
|
|
75
|
+
*
|
|
76
|
+
* Returns `undefined` when the message is absent, so a stale click is a no-op rather than a truncation.
|
|
77
|
+
*/
|
|
78
|
+
export const resolveRewind = (
|
|
79
|
+
messages: readonly Message.Message[],
|
|
80
|
+
messageId: string,
|
|
81
|
+
): { rewindFrom: string; text: string } | undefined => {
|
|
82
|
+
const message = messages.find((candidate) => candidate.id === messageId);
|
|
83
|
+
if (!message) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
return { rewindFrom: messageId, text: Message.extractText(message) };
|
|
87
|
+
};
|
|
@@ -13,6 +13,11 @@ import { meta } from '#meta';
|
|
|
13
13
|
|
|
14
14
|
import { type ChatEvent } from '../Chat/events';
|
|
15
15
|
|
|
16
|
+
type AudioInputDevice = {
|
|
17
|
+
deviceId: string;
|
|
18
|
+
label: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
16
21
|
export type ChatActionsProps = ThemedClassName<
|
|
17
22
|
PropsWithChildren<{
|
|
18
23
|
docId?: string;
|
|
@@ -23,11 +28,6 @@ export type ChatActionsProps = ThemedClassName<
|
|
|
23
28
|
}>
|
|
24
29
|
>;
|
|
25
30
|
|
|
26
|
-
type AudioInputDevice = {
|
|
27
|
-
deviceId: string;
|
|
28
|
-
label: string;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
31
|
export const ChatActions = ({
|
|
32
32
|
classNames,
|
|
33
33
|
children,
|
|
@@ -179,7 +179,6 @@ export const ChatActions = ({
|
|
|
179
179
|
))}
|
|
180
180
|
|
|
181
181
|
<DropdownMenu.Separator />
|
|
182
|
-
|
|
183
182
|
<DropdownMenu.CheckboxItem
|
|
184
183
|
checked={entityExtraction}
|
|
185
184
|
onCheckedChange={handleEntityExtractionChange}
|
|
@@ -210,9 +209,10 @@ export const ChatActions = ({
|
|
|
210
209
|
)}
|
|
211
210
|
|
|
212
211
|
<IconButton
|
|
213
|
-
|
|
212
|
+
disabled={!processing} // TODO(dmaretskyi): Set processing state correctly on rehydrated agents.
|
|
214
213
|
variant='ghost'
|
|
215
|
-
|
|
214
|
+
classNames={processing && 'text-error-text'}
|
|
215
|
+
icon={processing ? 'ph--square--duotone' : 'ph--square--regular'}
|
|
216
216
|
iconOnly
|
|
217
217
|
label={t('cancel-processing.button')}
|
|
218
218
|
onClick={() => {
|
|
@@ -34,7 +34,7 @@ export const ChatMcpErrors = ({ classNames, processor }: ChatMcpErrorsProps) =>
|
|
|
34
34
|
return (
|
|
35
35
|
<Message.Root classNames={['m-1', classNames]} valence='warning'>
|
|
36
36
|
<Message.Title onClose={handleDismiss}>{t('mcp-server-error.label')}</Message.Title>
|
|
37
|
-
<Message.
|
|
37
|
+
<Message.Body asChild>
|
|
38
38
|
<ul className='flex flex-col gap-0.5 text-sm'>
|
|
39
39
|
{errors.map((error) => (
|
|
40
40
|
<li key={`${error.url}::${error.protocol}`} className='truncate'>
|
|
@@ -44,7 +44,7 @@ export const ChatMcpErrors = ({ classNames, processor }: ChatMcpErrorsProps) =>
|
|
|
44
44
|
</li>
|
|
45
45
|
))}
|
|
46
46
|
</ul>
|
|
47
|
-
</Message.
|
|
47
|
+
</Message.Body>
|
|
48
48
|
</Message.Root>
|
|
49
49
|
);
|
|
50
50
|
};
|
|
@@ -10,13 +10,14 @@ import { withPluginManager } from '@dxos/app-framework/testing';
|
|
|
10
10
|
import { Chat } from '@dxos/assistant-toolkit';
|
|
11
11
|
import { capabilities } from '@dxos/assistant-toolkit/testing';
|
|
12
12
|
import { Feed, Filter, Ref } from '@dxos/echo';
|
|
13
|
+
import { useQuery } from '@dxos/echo-react';
|
|
13
14
|
import { ChessPlugin } from '@dxos/plugin-chess/testing';
|
|
14
15
|
import { ClientPlugin } from '@dxos/plugin-client/testing';
|
|
15
16
|
import { initializeIdentity } from '@dxos/plugin-client/testing';
|
|
16
17
|
import { MapPlugin } from '@dxos/plugin-map/testing';
|
|
17
18
|
import { TablePlugin } from '@dxos/plugin-table/testing';
|
|
18
19
|
import { corePlugins } from '@dxos/plugin-testing';
|
|
19
|
-
import {
|
|
20
|
+
import { useRegistry, useSpaces } from '@dxos/react-client/echo';
|
|
20
21
|
import { Loading, withTheme } from '@dxos/react-ui/testing';
|
|
21
22
|
import { Organization, Person } from '@dxos/types';
|
|
22
23
|
|
|
@@ -7,7 +7,7 @@ import React, { type JSX, useCallback, useMemo, useState } from 'react';
|
|
|
7
7
|
import { type AiContext } from '@dxos/assistant';
|
|
8
8
|
import { type Chat as ChatModule, McpServer } from '@dxos/assistant-toolkit';
|
|
9
9
|
import { type Database, Filter, Obj, type Registry, Type, URI } from '@dxos/echo';
|
|
10
|
-
import { useObject, useQuery } from '@dxos/react
|
|
10
|
+
import { useObject, useQuery } from '@dxos/echo-react';
|
|
11
11
|
import { IconButton, Input, Popover, Select, useTranslation } from '@dxos/react-ui';
|
|
12
12
|
import { Listbox } from '@dxos/react-ui-list';
|
|
13
13
|
import { SearchList, useSearchListResults } from '@dxos/react-ui-search';
|
|
@@ -79,14 +79,14 @@ export const ChatOptions = ({ chat, db, context, registry, presets, preset, onPr
|
|
|
79
79
|
<ModelsPanel presets={presets} preset={preset} onPresetChange={onPresetChange} />
|
|
80
80
|
</Tabs.Panel>
|
|
81
81
|
<Tabs.Tablist classNames={[styles.toolbar]}>
|
|
82
|
-
<Tabs.
|
|
83
|
-
<Tabs.
|
|
84
|
-
<Tabs.
|
|
82
|
+
<Tabs.IconButton value='view' icon='ph--eye--regular' label={t('chat-view.title')} />
|
|
83
|
+
<Tabs.IconButton value='skills' icon='ph--blueprint--regular' label={t('options.skills.title')} />
|
|
84
|
+
<Tabs.IconButton
|
|
85
85
|
value='mcp-servers'
|
|
86
86
|
icon='ph--plugs-connected--regular'
|
|
87
87
|
label={t('options.mcp.title')}
|
|
88
88
|
/>
|
|
89
|
-
<Tabs.
|
|
89
|
+
<Tabs.IconButton value='model' icon='ph--cpu--regular' label={t('options.chat-model.title')} />
|
|
90
90
|
</Tabs.Tablist>
|
|
91
91
|
</Tabs.Viewport>
|
|
92
92
|
</Tabs.Root>
|
|
@@ -8,9 +8,17 @@ import React, { useCallback, useEffect, useId, useMemo, useRef } from 'react';
|
|
|
8
8
|
|
|
9
9
|
import { type Chat } from '@dxos/assistant-toolkit';
|
|
10
10
|
import { type Event } from '@dxos/async';
|
|
11
|
-
import {
|
|
11
|
+
import { Project } from '@dxos/compute';
|
|
12
|
+
import { type Database, Obj } from '@dxos/echo';
|
|
13
|
+
import { useObject } from '@dxos/echo-react';
|
|
12
14
|
import { Input, type ThemedClassName, useDynamicRef, useTranslation } from '@dxos/react-ui';
|
|
13
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
ChatEditor,
|
|
17
|
+
type ChatEditorController,
|
|
18
|
+
type ChatEditorProps,
|
|
19
|
+
ChatStatusIndicator,
|
|
20
|
+
commands,
|
|
21
|
+
} from '@dxos/react-ui-chat';
|
|
14
22
|
import { pendingText } from '@dxos/ui-editor';
|
|
15
23
|
import { mx } from '@dxos/ui-theme';
|
|
16
24
|
import { type Merge } from '@dxos/util';
|
|
@@ -20,12 +28,11 @@ import { meta } from '#meta';
|
|
|
20
28
|
import { type ChatPresetProps } from '#types';
|
|
21
29
|
|
|
22
30
|
import { type AiChatProcessor } from '../../processor';
|
|
23
|
-
import { type ChatEvent } from '../Chat
|
|
31
|
+
import { type ChatEvent } from '../Chat';
|
|
24
32
|
import { ChatActions, type ChatActionsProps } from './ChatActions';
|
|
25
33
|
import { ChatMcpErrors } from './ChatMcpErrors';
|
|
26
34
|
import { ChatOptions } from './ChatOptions';
|
|
27
35
|
import { ChatReferences } from './ChatReferences';
|
|
28
|
-
import { ChatStatusIndicator } from './ChatStatusIndicator';
|
|
29
36
|
import { useChatVoiceInput } from './useChatVoiceInput';
|
|
30
37
|
|
|
31
38
|
export type ChatPromptProps = Merge<
|
|
@@ -40,6 +47,8 @@ export type ChatPromptProps = Merge<
|
|
|
40
47
|
/** Read-only indicator of whether the configured provider is the remote (online) service. */
|
|
41
48
|
online?: boolean;
|
|
42
49
|
placeholder?: ChatEditorProps['placeholder'];
|
|
50
|
+
/** Object the chat is attached to; its project instructions (if any) supply sentinel-command completion. */
|
|
51
|
+
companionTo?: Obj.Unknown;
|
|
43
52
|
}>,
|
|
44
53
|
ChatPresetProps
|
|
45
54
|
>;
|
|
@@ -57,6 +66,7 @@ export const ChatPrompt = ({
|
|
|
57
66
|
settings = true,
|
|
58
67
|
presets,
|
|
59
68
|
preset,
|
|
69
|
+
companionTo,
|
|
60
70
|
}: ChatPromptProps) => {
|
|
61
71
|
const { t } = useTranslation(meta.profile.key);
|
|
62
72
|
|
|
@@ -80,7 +90,23 @@ export const ChatPrompt = ({
|
|
|
80
90
|
useChatVoiceInput(docId, editorRef);
|
|
81
91
|
|
|
82
92
|
const keymapExtensions = useChatKeymapExtensions({ event });
|
|
83
|
-
|
|
93
|
+
|
|
94
|
+
// Sentinel-command completion is sourced from the bound project's instructions, if any.
|
|
95
|
+
const [companion] = useObject(companionTo);
|
|
96
|
+
const [instructions] = useObject(Obj.instanceOf(Project.Project, companion) ? companion.instructions : undefined);
|
|
97
|
+
const commandsRef = useDynamicRef(instructions?.commands ?? []);
|
|
98
|
+
const commandsExtension = useMemo(
|
|
99
|
+
() =>
|
|
100
|
+
commands({
|
|
101
|
+
getCommands: () => commandsRef.current.map(({ sentinel, description }) => ({ sentinel, description })),
|
|
102
|
+
}),
|
|
103
|
+
[commandsRef],
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const extensions = useMemo(
|
|
107
|
+
() => [keymapExtensions, pendingText(), commandsExtension],
|
|
108
|
+
[keymapExtensions, commandsExtension],
|
|
109
|
+
);
|
|
84
110
|
|
|
85
111
|
const handleSubmit = useCallback<NonNullable<ChatEditorProps['onSubmit']>>(
|
|
86
112
|
(text) => {
|
|
@@ -105,7 +131,7 @@ export const ChatPrompt = ({
|
|
|
105
131
|
className={mx(
|
|
106
132
|
'flex flex-col w-full dx-density-md',
|
|
107
133
|
outline &&
|
|
108
|
-
'
|
|
134
|
+
'dx-group-surface rounded-sm border border-subdued-separator transition transition-border [&:has(.cm-content:focus)]:border-separator',
|
|
109
135
|
classNames,
|
|
110
136
|
)}
|
|
111
137
|
>
|
|
@@ -116,6 +142,7 @@ export const ChatPrompt = ({
|
|
|
116
142
|
<ChatEditor
|
|
117
143
|
ref={editorRef}
|
|
118
144
|
autoFocus
|
|
145
|
+
markdown
|
|
119
146
|
lineWrapping
|
|
120
147
|
classNames='col-span-2 pt-0.5'
|
|
121
148
|
placeholder={placeholder ?? t('prompt.placeholder')}
|
|
@@ -8,12 +8,13 @@ import React from 'react';
|
|
|
8
8
|
|
|
9
9
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
10
10
|
import { Database, Filter, Obj } from '@dxos/echo';
|
|
11
|
+
import { useQuery } from '@dxos/echo-react';
|
|
11
12
|
import { DxAnchor } from '@dxos/lit-ui/react';
|
|
12
13
|
import { ClientPlugin } from '@dxos/plugin-client/testing';
|
|
13
14
|
import { initializeIdentity } from '@dxos/plugin-client/testing';
|
|
14
15
|
import { PreviewPlugin } from '@dxos/plugin-preview/testing';
|
|
15
16
|
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
16
|
-
import {
|
|
17
|
+
import { useSpaces } from '@dxos/react-client/echo';
|
|
17
18
|
import { Loading, withLayout } from '@dxos/react-ui/testing';
|
|
18
19
|
import { Organization } from '@dxos/types';
|
|
19
20
|
|
|
@@ -7,15 +7,18 @@ import * as Effect from 'effect/Effect';
|
|
|
7
7
|
import * as Fiber from 'effect/Fiber';
|
|
8
8
|
import * as Layer from 'effect/Layer';
|
|
9
9
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
10
|
+
import { expect, userEvent, waitFor, within } from 'storybook/test';
|
|
10
11
|
|
|
11
12
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
12
13
|
import { Database, Feed, Filter, Query } from '@dxos/echo';
|
|
14
|
+
import { useQuery } from '@dxos/echo-react';
|
|
13
15
|
import { EffectEx } from '@dxos/effect';
|
|
14
16
|
import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
|
|
15
17
|
import { PreviewPlugin } from '@dxos/plugin-preview/testing';
|
|
16
18
|
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
17
19
|
import { random } from '@dxos/random';
|
|
18
|
-
import {
|
|
20
|
+
import { useSpaces } from '@dxos/react-client/echo';
|
|
21
|
+
import { Button } from '@dxos/react-ui';
|
|
19
22
|
import { EditorPreviewProvider } from '@dxos/react-ui-editor';
|
|
20
23
|
import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
21
24
|
import { Message, Organization, Person } from '@dxos/types';
|
|
@@ -29,9 +32,15 @@ random.seed(1);
|
|
|
29
32
|
|
|
30
33
|
type MessageGenerator = Effect.Effect<void, never, Database.Service | Feed.ContextFeedService>;
|
|
31
34
|
|
|
32
|
-
type StoryArgs = {
|
|
35
|
+
type StoryArgs = {
|
|
36
|
+
generator?: MessageGenerator[];
|
|
37
|
+
delay?: number;
|
|
38
|
+
wait?: boolean;
|
|
39
|
+
/** Render a toggle that unmounts and remounts the thread, reproducing navigating away and back. */
|
|
40
|
+
remountable?: boolean;
|
|
41
|
+
} & ChatThreadProps;
|
|
33
42
|
|
|
34
|
-
const DefaultStory = ({ generator = [], delay = 0, wait, ...props }: StoryArgs) => {
|
|
43
|
+
const DefaultStory = ({ generator = [], delay = 0, wait, remountable, ...props }: StoryArgs) => {
|
|
35
44
|
const [space] = useSpaces();
|
|
36
45
|
const feed = useMemo<Feed.Feed | undefined>(
|
|
37
46
|
() => (space ? space.db.add(Feed.make({ name: 'chat' })) : undefined),
|
|
@@ -73,11 +82,32 @@ const DefaultStory = ({ generator = [], delay = 0, wait, ...props }: StoryArgs)
|
|
|
73
82
|
|
|
74
83
|
return (
|
|
75
84
|
<EditorPreviewProvider onLookup={async ({ dxn, label }) => ({ label, text: dxn })}>
|
|
76
|
-
|
|
85
|
+
{remountable ? (
|
|
86
|
+
<RemountableThread {...props} messages={messages} />
|
|
87
|
+
) : (
|
|
88
|
+
<ChatThread {...props} messages={messages} />
|
|
89
|
+
)}
|
|
77
90
|
</EditorPreviewProvider>
|
|
78
91
|
);
|
|
79
92
|
};
|
|
80
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Unmount/remount harness. Returning to a chat remounts the thread, which re-walks the messages and
|
|
96
|
+
* replaces the document — and a full replace clears accumulated widget props, so tool rows depend on
|
|
97
|
+
* the rehydration that follows it. Mounting fresh never exercises that path.
|
|
98
|
+
*/
|
|
99
|
+
const RemountableThread = (props: ChatThreadProps) => {
|
|
100
|
+
const [mounted, setMounted] = useState(true);
|
|
101
|
+
return (
|
|
102
|
+
<div className='flex flex-col h-full'>
|
|
103
|
+
<Button data-testid='story.toggleMount' onClick={() => setMounted((value) => !value)}>
|
|
104
|
+
{mounted ? 'Unmount' : 'Mount'}
|
|
105
|
+
</Button>
|
|
106
|
+
{mounted && <ChatThread {...props} />}
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
81
111
|
const meta = {
|
|
82
112
|
title: 'plugins/plugin-assistant/components/ChatThread',
|
|
83
113
|
component: ChatThread,
|
|
@@ -117,6 +147,35 @@ export const Default: Story = {
|
|
|
117
147
|
},
|
|
118
148
|
};
|
|
119
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Every user prompt carries a rewind toolbar. It is emitted as its own markdown block after the
|
|
152
|
+
* `<prompt>` tag; a single newline between them would let CommonMark absorb the toolbar into the
|
|
153
|
+
* prompt's HTML block, so this asserts the tag actually parses into a widget.
|
|
154
|
+
*/
|
|
155
|
+
export const Rewind: Story = {
|
|
156
|
+
args: {
|
|
157
|
+
generator: createMessageGenerator(),
|
|
158
|
+
wait: true,
|
|
159
|
+
},
|
|
160
|
+
play: async ({ canvasElement }) => {
|
|
161
|
+
const canvas = within(canvasElement);
|
|
162
|
+
const buttons = await waitFor(
|
|
163
|
+
async () => {
|
|
164
|
+
const found = canvas.queryAllByTestId('chat.rewind');
|
|
165
|
+
await expect(found.length).toBeGreaterThan(0);
|
|
166
|
+
return found;
|
|
167
|
+
},
|
|
168
|
+
{ timeout: 10_000 },
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// One toolbar per user prompt.
|
|
172
|
+
const prompts = canvasElement.querySelectorAll('.cm-prompt, [data-prompt]');
|
|
173
|
+
if (prompts.length > 0) {
|
|
174
|
+
await expect(buttons.length).toBe(prompts.length);
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
120
179
|
export const Delayed: Story = {
|
|
121
180
|
args: {
|
|
122
181
|
generator: createMessageGenerator(),
|
|
@@ -128,3 +187,39 @@ export const Delayed: Story = {
|
|
|
128
187
|
},
|
|
129
188
|
},
|
|
130
189
|
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Tool rows must survive navigating away and back.
|
|
193
|
+
*
|
|
194
|
+
* They render from out-of-band widget state, not from the document: `blockToMarkdown` emits a
|
|
195
|
+
* `<toolCall id/>` placeholder and pushes the blocks via `updateWidget`; an empty state renders an
|
|
196
|
+
* empty row. On remount `MessageSyncer.reset` replaces the document, which fires `xmlTagResetEffect`
|
|
197
|
+
* and clears that state, then rehydrates it — and that rehydration used to be dropped, because the
|
|
198
|
+
* rebuild it triggers replaces the widget instances the editor was routing updates through
|
|
199
|
+
* (`xml-tags.test.ts`, "state reaches a mounted widget after a rebuild replaced its decoration
|
|
200
|
+
* instance").
|
|
201
|
+
*/
|
|
202
|
+
export const Remount: Story = {
|
|
203
|
+
args: {
|
|
204
|
+
generator: createMessageGenerator(),
|
|
205
|
+
wait: true,
|
|
206
|
+
remountable: true,
|
|
207
|
+
},
|
|
208
|
+
play: async ({ canvasElement }) => {
|
|
209
|
+
const canvas = within(canvasElement);
|
|
210
|
+
|
|
211
|
+
// Streaming path: the tool rows render as the messages land.
|
|
212
|
+
await expect(canvas.findByText(/Calling search/, undefined, { timeout: 10_000 })).resolves.toBeTruthy();
|
|
213
|
+
await expect(canvas.findByText(/Calling create/, undefined, { timeout: 10_000 })).resolves.toBeTruthy();
|
|
214
|
+
|
|
215
|
+
// Away and back.
|
|
216
|
+
const toggle = await canvas.findByTestId('story.toggleMount');
|
|
217
|
+
await userEvent.click(toggle);
|
|
218
|
+
await waitFor(() => expect(canvas.queryByText(/Calling search/)).toBeNull());
|
|
219
|
+
await userEvent.click(toggle);
|
|
220
|
+
|
|
221
|
+
// Replay path: same rows, rebuilt from the messages rather than from streaming updates.
|
|
222
|
+
await expect(canvas.findByText(/Calling search/, undefined, { timeout: 10_000 })).resolves.toBeTruthy();
|
|
223
|
+
await expect(canvas.findByText(/Calling create/, undefined, { timeout: 10_000 })).resolves.toBeTruthy();
|
|
224
|
+
},
|
|
225
|
+
};
|