@jini-ai/chat 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +109 -0
- package/dist/core/agentic/chat-capabilities.d.ts +19 -0
- package/dist/core/agentic/chat-capabilities.d.ts.map +1 -0
- package/dist/core/agentic/chat-capabilities.js +106 -0
- package/dist/core/agentic/chat-capabilities.js.map +1 -0
- package/dist/core/agentic/index.d.ts +22 -0
- package/dist/core/agentic/index.d.ts.map +1 -0
- package/dist/core/agentic/index.js +21 -0
- package/dist/core/agentic/index.js.map +1 -0
- package/dist/core/events.d.ts +84 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +14 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/index.d.ts +40 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +40 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/messages.d.ts +53 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +16 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/partial-json.d.ts +36 -0
- package/dist/core/partial-json.d.ts.map +1 -0
- package/dist/core/partial-json.js +119 -0
- package/dist/core/partial-json.js.map +1 -0
- package/dist/core/persistence/index.d.ts +11 -0
- package/dist/core/persistence/index.d.ts.map +1 -0
- package/dist/core/persistence/index.js +11 -0
- package/dist/core/persistence/index.js.map +1 -0
- package/dist/core/persistence/ports.d.ts +124 -0
- package/dist/core/persistence/ports.d.ts.map +1 -0
- package/dist/core/persistence/ports.js +2 -0
- package/dist/core/persistence/ports.js.map +1 -0
- package/dist/core/persistence/title.d.ts +35 -0
- package/dist/core/persistence/title.d.ts.map +1 -0
- package/dist/core/persistence/title.js +137 -0
- package/dist/core/persistence/title.js.map +1 -0
- package/dist/core/question-form/format.d.ts +27 -0
- package/dist/core/question-form/format.d.ts.map +1 -0
- package/dist/core/question-form/format.js +45 -0
- package/dist/core/question-form/format.js.map +1 -0
- package/dist/core/question-form/normalize.d.ts +30 -0
- package/dist/core/question-form/normalize.d.ts.map +1 -0
- package/dist/core/question-form/normalize.js +192 -0
- package/dist/core/question-form/normalize.js.map +1 -0
- package/dist/core/question-form/scan.d.ts +50 -0
- package/dist/core/question-form/scan.d.ts.map +1 -0
- package/dist/core/question-form/scan.js +404 -0
- package/dist/core/question-form/scan.js.map +1 -0
- package/dist/core/question-form/types.d.ts +83 -0
- package/dist/core/question-form/types.d.ts.map +1 -0
- package/dist/core/question-form/types.js +11 -0
- package/dist/core/question-form/types.js.map +1 -0
- package/dist/core/question-form.d.ts +39 -0
- package/dist/core/question-form.d.ts.map +1 -0
- package/dist/core/question-form.js +4 -0
- package/dist/core/question-form.js.map +1 -0
- package/dist/core/todos.d.ts +70 -0
- package/dist/core/todos.d.ts.map +1 -0
- package/dist/core/todos.js +175 -0
- package/dist/core/todos.js.map +1 -0
- package/dist/core/tool-events.d.ts +18 -0
- package/dist/core/tool-events.d.ts.map +1 -0
- package/dist/core/tool-events.js +36 -0
- package/dist/core/tool-events.js.map +1 -0
- package/dist/core/tools.d.ts +51 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +41 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/transcript.d.ts +81 -0
- package/dist/core/transcript.d.ts.map +1 -0
- package/dist/core/transcript.js +133 -0
- package/dist/core/transcript.js.map +1 -0
- package/dist/core/transport.d.ts +109 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/core/transport.js +2 -0
- package/dist/core/transport.js.map +1 -0
- package/dist/core/util/index.d.ts +16 -0
- package/dist/core/util/index.d.ts.map +1 -0
- package/dist/core/util/index.js +16 -0
- package/dist/core/util/index.js.map +1 -0
- package/dist/core/util/manifest.d.ts +39 -0
- package/dist/core/util/manifest.d.ts.map +1 -0
- package/dist/core/util/manifest.js +173 -0
- package/dist/core/util/manifest.js.map +1 -0
- package/dist/core/util/markdown-context.d.ts +47 -0
- package/dist/core/util/markdown-context.d.ts.map +1 -0
- package/dist/core/util/markdown-context.js +125 -0
- package/dist/core/util/markdown-context.js.map +1 -0
- package/dist/core/util/markup-attributes.d.ts +20 -0
- package/dist/core/util/markup-attributes.d.ts.map +1 -0
- package/dist/core/util/markup-attributes.js +33 -0
- package/dist/core/util/markup-attributes.js.map +1 -0
- package/dist/core/util/parser.d.ts +42 -0
- package/dist/core/util/parser.d.ts.map +1 -0
- package/dist/core/util/parser.js +238 -0
- package/dist/core/util/parser.js.map +1 -0
- package/dist/core/util/pointer.d.ts +28 -0
- package/dist/core/util/pointer.d.ts.map +1 -0
- package/dist/core/util/pointer.js +75 -0
- package/dist/core/util/pointer.js.map +1 -0
- package/dist/core/util/recover.d.ts +40 -0
- package/dist/core/util/recover.d.ts.map +1 -0
- package/dist/core/util/recover.js +117 -0
- package/dist/core/util/recover.js.map +1 -0
- package/dist/core/util/strip.d.ts +112 -0
- package/dist/core/util/strip.d.ts.map +1 -0
- package/dist/core/util/strip.js +333 -0
- package/dist/core/util/strip.js.map +1 -0
- package/dist/core/util/types.d.ts +31 -0
- package/dist/core/util/types.d.ts.map +1 -0
- package/dist/core/util/types.js +2 -0
- package/dist/core/util/types.js.map +1 -0
- package/dist/core/util/validate.d.ts +50 -0
- package/dist/core/util/validate.d.ts.map +1 -0
- package/dist/core/util/validate.js +202 -0
- package/dist/core/util/validate.js.map +1 -0
- package/dist/react/agent-bridge/frontend-session-bridge.d.ts +45 -0
- package/dist/react/agent-bridge/frontend-session-bridge.d.ts.map +1 -0
- package/dist/react/agent-bridge/frontend-session-bridge.js +214 -0
- package/dist/react/agent-bridge/frontend-session-bridge.js.map +1 -0
- package/dist/react/artifact-types.d.ts +61 -0
- package/dist/react/artifact-types.d.ts.map +1 -0
- package/dist/react/artifact-types.js +33 -0
- package/dist/react/artifact-types.js.map +1 -0
- package/dist/react/chat-pane.d.ts +21 -0
- package/dist/react/chat-pane.d.ts.map +1 -0
- package/dist/react/chat-pane.js +20 -0
- package/dist/react/chat-pane.js.map +1 -0
- package/dist/react/components/A2uiSurfaceCard.d.ts +35 -0
- package/dist/react/components/A2uiSurfaceCard.d.ts.map +1 -0
- package/dist/react/components/A2uiSurfaceCard.js +272 -0
- package/dist/react/components/A2uiSurfaceCard.js.map +1 -0
- package/dist/react/components/AttachmentTray.d.ts +6 -0
- package/dist/react/components/AttachmentTray.d.ts.map +1 -0
- package/dist/react/components/AttachmentTray.js +30 -0
- package/dist/react/components/AttachmentTray.js.map +1 -0
- package/dist/react/components/ChatFab.d.ts +8 -0
- package/dist/react/components/ChatFab.d.ts.map +1 -0
- package/dist/react/components/ChatFab.js +24 -0
- package/dist/react/components/ChatFab.js.map +1 -0
- package/dist/react/components/Composer.d.ts +34 -0
- package/dist/react/components/Composer.d.ts.map +1 -0
- package/dist/react/components/Composer.js +300 -0
- package/dist/react/components/Composer.js.map +1 -0
- package/dist/react/components/ComposerDiscovery.d.ts +46 -0
- package/dist/react/components/ComposerDiscovery.d.ts.map +1 -0
- package/dist/react/components/ComposerDiscovery.js +38 -0
- package/dist/react/components/ComposerDiscovery.js.map +1 -0
- package/dist/react/components/ConversationList.d.ts +31 -0
- package/dist/react/components/ConversationList.d.ts.map +1 -0
- package/dist/react/components/ConversationList.js +221 -0
- package/dist/react/components/ConversationList.js.map +1 -0
- package/dist/react/components/ExtEventErrorBoundary.d.ts +35 -0
- package/dist/react/components/ExtEventErrorBoundary.d.ts.map +1 -0
- package/dist/react/components/ExtEventErrorBoundary.js +38 -0
- package/dist/react/components/ExtEventErrorBoundary.js.map +1 -0
- package/dist/react/components/Icon.d.ts +17 -0
- package/dist/react/components/Icon.d.ts.map +1 -0
- package/dist/react/components/Icon.js +46 -0
- package/dist/react/components/Icon.js.map +1 -0
- package/dist/react/components/JiniChatProvider.d.ts +45 -0
- package/dist/react/components/JiniChatProvider.d.ts.map +1 -0
- package/dist/react/components/JiniChatProvider.js +44 -0
- package/dist/react/components/JiniChatProvider.js.map +1 -0
- package/dist/react/components/Markdown.d.ts +5 -0
- package/dist/react/components/Markdown.d.ts.map +1 -0
- package/dist/react/components/Markdown.js +390 -0
- package/dist/react/components/Markdown.js.map +1 -0
- package/dist/react/components/McpUiSurfaceCard.d.ts +51 -0
- package/dist/react/components/McpUiSurfaceCard.d.ts.map +1 -0
- package/dist/react/components/McpUiSurfaceCard.js +159 -0
- package/dist/react/components/McpUiSurfaceCard.js.map +1 -0
- package/dist/react/components/MessageList.d.ts +15 -0
- package/dist/react/components/MessageList.d.ts.map +1 -0
- package/dist/react/components/MessageList.js +81 -0
- package/dist/react/components/MessageList.js.map +1 -0
- package/dist/react/components/MessageRow.d.ts +60 -0
- package/dist/react/components/MessageRow.d.ts.map +1 -0
- package/dist/react/components/MessageRow.js +156 -0
- package/dist/react/components/MessageRow.js.map +1 -0
- package/dist/react/components/NextStepActions.d.ts +34 -0
- package/dist/react/components/NextStepActions.d.ts.map +1 -0
- package/dist/react/components/NextStepActions.js +9 -0
- package/dist/react/components/NextStepActions.js.map +1 -0
- package/dist/react/components/QuestionForm.d.ts +26 -0
- package/dist/react/components/QuestionForm.d.ts.map +1 -0
- package/dist/react/components/QuestionForm.js +238 -0
- package/dist/react/components/QuestionForm.js.map +1 -0
- package/dist/react/components/QuestionsPanel.d.ts +13 -0
- package/dist/react/components/QuestionsPanel.d.ts.map +1 -0
- package/dist/react/components/QuestionsPanel.js +33 -0
- package/dist/react/components/QuestionsPanel.js.map +1 -0
- package/dist/react/components/TodoCard.d.ts +8 -0
- package/dist/react/components/TodoCard.d.ts.map +1 -0
- package/dist/react/components/TodoCard.js +29 -0
- package/dist/react/components/TodoCard.js.map +1 -0
- package/dist/react/components/ToolCard.d.ts +22 -0
- package/dist/react/components/ToolCard.d.ts.map +1 -0
- package/dist/react/components/ToolCard.js +298 -0
- package/dist/react/components/ToolCard.js.map +1 -0
- package/dist/react/components/composer-discovery.d.ts +107 -0
- package/dist/react/components/composer-discovery.d.ts.map +1 -0
- package/dist/react/components/composer-discovery.js +176 -0
- package/dist/react/components/composer-discovery.js.map +1 -0
- package/dist/react/ext-event-renderer-registry.d.ts +51 -0
- package/dist/react/ext-event-renderer-registry.d.ts.map +1 -0
- package/dist/react/ext-event-renderer-registry.js +20 -0
- package/dist/react/ext-event-renderer-registry.js.map +1 -0
- package/dist/react/features/chat-pane/agent-tools.d.ts +14 -0
- package/dist/react/features/chat-pane/agent-tools.d.ts.map +1 -0
- package/dist/react/features/chat-pane/agent-tools.js +22 -0
- package/dist/react/features/chat-pane/agent-tools.js.map +1 -0
- package/dist/react/features/chat-pane/components/AgentRuntimePicker.d.ts +12 -0
- package/dist/react/features/chat-pane/components/AgentRuntimePicker.d.ts.map +1 -0
- package/dist/react/features/chat-pane/components/AgentRuntimePicker.js +106 -0
- package/dist/react/features/chat-pane/components/AgentRuntimePicker.js.map +1 -0
- package/dist/react/features/chat-pane/components/ChatPane.d.ts +10 -0
- package/dist/react/features/chat-pane/components/ChatPane.d.ts.map +1 -0
- package/dist/react/features/chat-pane/components/ChatPane.js +169 -0
- package/dist/react/features/chat-pane/components/ChatPane.js.map +1 -0
- package/dist/react/features/chat-pane/create-daemon-attachment-uploader.d.ts +21 -0
- package/dist/react/features/chat-pane/create-daemon-attachment-uploader.d.ts.map +1 -0
- package/dist/react/features/chat-pane/create-daemon-attachment-uploader.js +213 -0
- package/dist/react/features/chat-pane/create-daemon-attachment-uploader.js.map +1 -0
- package/dist/react/features/chat-pane/create-mcp-ui-tool-caller.d.ts +70 -0
- package/dist/react/features/chat-pane/create-mcp-ui-tool-caller.d.ts.map +1 -0
- package/dist/react/features/chat-pane/create-mcp-ui-tool-caller.js +76 -0
- package/dist/react/features/chat-pane/create-mcp-ui-tool-caller.js.map +1 -0
- package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.d.ts +133 -0
- package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.js +258 -0
- package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPane.hooks.d.ts +66 -0
- package/dist/react/features/chat-pane/hooks/useChatPane.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPane.hooks.js +224 -0
- package/dist/react/features/chat-pane/hooks/useChatPane.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.d.ts +38 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.js +252 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneControlsHeight.hooks.d.ts +16 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneControlsHeight.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneControlsHeight.hooks.js +59 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneControlsHeight.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneFileDrop.hooks.d.ts +26 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneFileDrop.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneFileDrop.hooks.js +74 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneFileDrop.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.d.ts +25 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.js +88 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneWorkingDirectory.hooks.d.ts +38 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneWorkingDirectory.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneWorkingDirectory.hooks.js +184 -0
- package/dist/react/features/chat-pane/hooks/useChatPaneWorkingDirectory.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/index.d.ts +12 -0
- package/dist/react/features/chat-pane/index.d.ts.map +1 -0
- package/dist/react/features/chat-pane/index.js +11 -0
- package/dist/react/features/chat-pane/index.js.map +1 -0
- package/dist/react/features/chat-pane/react/components/AgentRuntimePicker.d.ts +12 -0
- package/dist/react/features/chat-pane/react/components/AgentRuntimePicker.d.ts.map +1 -0
- package/dist/react/features/chat-pane/react/components/AgentRuntimePicker.js +102 -0
- package/dist/react/features/chat-pane/react/components/AgentRuntimePicker.js.map +1 -0
- package/dist/react/features/chat-pane/react/components/ChatPane.d.ts +10 -0
- package/dist/react/features/chat-pane/react/components/ChatPane.d.ts.map +1 -0
- package/dist/react/features/chat-pane/react/components/ChatPane.js +137 -0
- package/dist/react/features/chat-pane/react/components/ChatPane.js.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useAgentRuntimePicker.hooks.d.ts +133 -0
- package/dist/react/features/chat-pane/react/hooks/useAgentRuntimePicker.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useAgentRuntimePicker.hooks.js +258 -0
- package/dist/react/features/chat-pane/react/hooks/useAgentRuntimePicker.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPane.hooks.d.ts +66 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPane.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPane.hooks.js +223 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPane.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneAgentControl.hooks.d.ts +38 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneAgentControl.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneAgentControl.hooks.js +252 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneAgentControl.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneFileDrop.hooks.d.ts +26 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneFileDrop.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneFileDrop.hooks.js +60 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneFileDrop.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneRuntimeInventory.hooks.d.ts +25 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneRuntimeInventory.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneRuntimeInventory.hooks.js +83 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneRuntimeInventory.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneWorkingDirectory.hooks.d.ts +38 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneWorkingDirectory.hooks.d.ts.map +1 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneWorkingDirectory.hooks.js +184 -0
- package/dist/react/features/chat-pane/react/hooks/useChatPaneWorkingDirectory.hooks.js.map +1 -0
- package/dist/react/features/chat-pane/react/styles.d.ts +2 -0
- package/dist/react/features/chat-pane/react/styles.d.ts.map +1 -0
- package/dist/react/features/chat-pane/react/styles.js +863 -0
- package/dist/react/features/chat-pane/react/styles.js.map +1 -0
- package/dist/react/features/chat-pane/rules.d.ts +31 -0
- package/dist/react/features/chat-pane/rules.d.ts.map +1 -0
- package/dist/react/features/chat-pane/rules.js +81 -0
- package/dist/react/features/chat-pane/rules.js.map +1 -0
- package/dist/react/features/chat-pane/styles.d.ts +2 -0
- package/dist/react/features/chat-pane/styles.d.ts.map +1 -0
- package/dist/react/features/chat-pane/styles.js +1327 -0
- package/dist/react/features/chat-pane/styles.js.map +1 -0
- package/dist/react/features/chat-pane/types.d.ts +248 -0
- package/dist/react/features/chat-pane/types.d.ts.map +1 -0
- package/dist/react/features/chat-pane/types.js +2 -0
- package/dist/react/features/chat-pane/types.js.map +1 -0
- package/dist/react/features/model-picker/components/CredentialStatusBadge.d.ts +7 -0
- package/dist/react/features/model-picker/components/CredentialStatusBadge.d.ts.map +1 -0
- package/dist/react/features/model-picker/components/CredentialStatusBadge.js +20 -0
- package/dist/react/features/model-picker/components/CredentialStatusBadge.js.map +1 -0
- package/dist/react/features/model-picker/components/ModelPicker.d.ts +9 -0
- package/dist/react/features/model-picker/components/ModelPicker.d.ts.map +1 -0
- package/dist/react/features/model-picker/components/ModelPicker.js +34 -0
- package/dist/react/features/model-picker/components/ModelPicker.js.map +1 -0
- package/dist/react/features/model-picker/constants.d.ts +6 -0
- package/dist/react/features/model-picker/constants.d.ts.map +1 -0
- package/dist/react/features/model-picker/constants.js +9 -0
- package/dist/react/features/model-picker/constants.js.map +1 -0
- package/dist/react/features/model-picker/dependencies.d.ts +11 -0
- package/dist/react/features/model-picker/dependencies.d.ts.map +1 -0
- package/dist/react/features/model-picker/dependencies.js +10 -0
- package/dist/react/features/model-picker/dependencies.js.map +1 -0
- package/dist/react/features/model-picker/hooks/useModelPicker.hooks.d.ts +27 -0
- package/dist/react/features/model-picker/hooks/useModelPicker.hooks.d.ts.map +1 -0
- package/dist/react/features/model-picker/hooks/useModelPicker.hooks.js +62 -0
- package/dist/react/features/model-picker/hooks/useModelPicker.hooks.js.map +1 -0
- package/dist/react/features/model-picker/index.d.ts +32 -0
- package/dist/react/features/model-picker/index.d.ts.map +1 -0
- package/dist/react/features/model-picker/index.js +29 -0
- package/dist/react/features/model-picker/index.js.map +1 -0
- package/dist/react/features/model-picker/ports.d.ts +11 -0
- package/dist/react/features/model-picker/ports.d.ts.map +1 -0
- package/dist/react/features/model-picker/ports.js +2 -0
- package/dist/react/features/model-picker/ports.js.map +1 -0
- package/dist/react/features/model-picker/react/components/CredentialStatusBadge.d.ts +7 -0
- package/dist/react/features/model-picker/react/components/CredentialStatusBadge.d.ts.map +1 -0
- package/dist/react/features/model-picker/react/components/CredentialStatusBadge.js +20 -0
- package/dist/react/features/model-picker/react/components/CredentialStatusBadge.js.map +1 -0
- package/dist/react/features/model-picker/react/components/ModelPicker.d.ts +9 -0
- package/dist/react/features/model-picker/react/components/ModelPicker.d.ts.map +1 -0
- package/dist/react/features/model-picker/react/components/ModelPicker.js +34 -0
- package/dist/react/features/model-picker/react/components/ModelPicker.js.map +1 -0
- package/dist/react/features/model-picker/react/hooks/useModelPicker.hooks.d.ts +27 -0
- package/dist/react/features/model-picker/react/hooks/useModelPicker.hooks.d.ts.map +1 -0
- package/dist/react/features/model-picker/react/hooks/useModelPicker.hooks.js +62 -0
- package/dist/react/features/model-picker/react/hooks/useModelPicker.hooks.js.map +1 -0
- package/dist/react/features/model-picker/rules.d.ts +26 -0
- package/dist/react/features/model-picker/rules.d.ts.map +1 -0
- package/dist/react/features/model-picker/rules.js +84 -0
- package/dist/react/features/model-picker/rules.js.map +1 -0
- package/dist/react/features/model-picker/types.d.ts +38 -0
- package/dist/react/features/model-picker/types.d.ts.map +1 -0
- package/dist/react/features/model-picker/types.js +2 -0
- package/dist/react/features/model-picker/types.js.map +1 -0
- package/dist/react/hooks/composer-draft-cache.d.ts +65 -0
- package/dist/react/hooks/composer-draft-cache.d.ts.map +1 -0
- package/dist/react/hooks/composer-draft-cache.js +89 -0
- package/dist/react/hooks/composer-draft-cache.js.map +1 -0
- package/dist/react/hooks/context.d.ts +18 -0
- package/dist/react/hooks/context.d.ts.map +1 -0
- package/dist/react/hooks/context.js +60 -0
- package/dist/react/hooks/context.js.map +1 -0
- package/dist/react/hooks/testing/fake-transport.d.ts +34 -0
- package/dist/react/hooks/testing/fake-transport.d.ts.map +1 -0
- package/dist/react/hooks/testing/fake-transport.js +46 -0
- package/dist/react/hooks/testing/fake-transport.js.map +1 -0
- package/dist/react/hooks/useArtifactStream.d.ts +18 -0
- package/dist/react/hooks/useArtifactStream.d.ts.map +1 -0
- package/dist/react/hooks/useArtifactStream.js +55 -0
- package/dist/react/hooks/useArtifactStream.js.map +1 -0
- package/dist/react/hooks/useChatFabDrag.d.ts +25 -0
- package/dist/react/hooks/useChatFabDrag.d.ts.map +1 -0
- package/dist/react/hooks/useChatFabDrag.js +88 -0
- package/dist/react/hooks/useChatFabDrag.js.map +1 -0
- package/dist/react/hooks/useComposer.d.ts +48 -0
- package/dist/react/hooks/useComposer.d.ts.map +1 -0
- package/dist/react/hooks/useComposer.js +121 -0
- package/dist/react/hooks/useComposer.js.map +1 -0
- package/dist/react/hooks/useConversation.d.ts +34 -0
- package/dist/react/hooks/useConversation.d.ts.map +1 -0
- package/dist/react/hooks/useConversation.js +163 -0
- package/dist/react/hooks/useConversation.js.map +1 -0
- package/dist/react/hooks/useCopyToClipboard.d.ts +14 -0
- package/dist/react/hooks/useCopyToClipboard.d.ts.map +1 -0
- package/dist/react/hooks/useCopyToClipboard.js +98 -0
- package/dist/react/hooks/useCopyToClipboard.js.map +1 -0
- package/dist/react/hooks/useExtEventGroups.d.ts +7 -0
- package/dist/react/hooks/useExtEventGroups.d.ts.map +1 -0
- package/dist/react/hooks/useExtEventGroups.js +32 -0
- package/dist/react/hooks/useExtEventGroups.js.map +1 -0
- package/dist/react/hooks/useLatestOperation.d.ts +31 -0
- package/dist/react/hooks/useLatestOperation.d.ts.map +1 -0
- package/dist/react/hooks/useLatestOperation.js +74 -0
- package/dist/react/hooks/useLatestOperation.js.map +1 -0
- package/dist/react/hooks/usePinnedTodos.d.ts +15 -0
- package/dist/react/hooks/usePinnedTodos.d.ts.map +1 -0
- package/dist/react/hooks/usePinnedTodos.js +43 -0
- package/dist/react/hooks/usePinnedTodos.js.map +1 -0
- package/dist/react/hooks/useQuestionForms.d.ts +28 -0
- package/dist/react/hooks/useQuestionForms.d.ts.map +1 -0
- package/dist/react/hooks/useQuestionForms.js +113 -0
- package/dist/react/hooks/useQuestionForms.js.map +1 -0
- package/dist/react/hooks/useRunStream.d.ts +27 -0
- package/dist/react/hooks/useRunStream.d.ts.map +1 -0
- package/dist/react/hooks/useRunStream.js +180 -0
- package/dist/react/hooks/useRunStream.js.map +1 -0
- package/dist/react/hooks/useToolTimeline.d.ts +33 -0
- package/dist/react/hooks/useToolTimeline.d.ts.map +1 -0
- package/dist/react/hooks/useToolTimeline.js +47 -0
- package/dist/react/hooks/useToolTimeline.js.map +1 -0
- package/dist/react/index.d.ts +158 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +118 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/message-blocks.d.ts +86 -0
- package/dist/react/message-blocks.d.ts.map +1 -0
- package/dist/react/message-blocks.js +78 -0
- package/dist/react/message-blocks.js.map +1 -0
- package/dist/react/poc-mcp-ui-official/PocMcpUiCard.d.ts +9 -0
- package/dist/react/poc-mcp-ui-official/PocMcpUiCard.d.ts.map +1 -0
- package/dist/react/poc-mcp-ui-official/PocMcpUiCard.js +29 -0
- package/dist/react/poc-mcp-ui-official/PocMcpUiCard.js.map +1 -0
- package/dist/react/poc-mcp-ui-official/create-poc-resource.d.ts +30 -0
- package/dist/react/poc-mcp-ui-official/create-poc-resource.d.ts.map +1 -0
- package/dist/react/poc-mcp-ui-official/create-poc-resource.js +44 -0
- package/dist/react/poc-mcp-ui-official/create-poc-resource.js.map +1 -0
- package/dist/react/slots.d.ts +215 -0
- package/dist/react/slots.d.ts.map +1 -0
- package/dist/react/slots.js +2 -0
- package/dist/react/slots.js.map +1 -0
- package/dist/react/styles/reference.css +298 -0
- package/dist/react/tool-renderer-registry.d.ts +41 -0
- package/dist/react/tool-renderer-registry.d.ts.map +1 -0
- package/dist/react/tool-renderer-registry.js +22 -0
- package/dist/react/tool-renderer-registry.js.map +1 -0
- package/dist/react/util/defined-props.d.ts +31 -0
- package/dist/react/util/defined-props.d.ts.map +1 -0
- package/dist/react/util/defined-props.js +28 -0
- package/dist/react/util/defined-props.js.map +1 -0
- package/package.json +99 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module useConversation
|
|
3
|
+
*
|
|
4
|
+
* Owns the message array, an optimistic user-message append, a scroll-intent
|
|
5
|
+
* flag, and the active conversation id. Reconciles `useRunStream`'s live
|
|
6
|
+
* `AgentEvent[]` into the streaming assistant message's `events`/`content`
|
|
7
|
+
* as they arrive, and finalizes it once the run reaches a terminal status.
|
|
8
|
+
* Per `ADS-memory/reports/jini-port/recon/r4b-webui-design.md` §4.
|
|
9
|
+
*
|
|
10
|
+
* Mutations reach the transport only through the composed `useRunStream` —
|
|
11
|
+
* this hook never imports `fetch`/`EventSource` itself.
|
|
12
|
+
*/
|
|
13
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
14
|
+
import { isTerminalRunStatus } from '../../core/index.js';
|
|
15
|
+
import { useRunStream } from './useRunStream.js';
|
|
16
|
+
let fallbackIdCounter = 0;
|
|
17
|
+
function defaultCreateMessageId() {
|
|
18
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function')
|
|
19
|
+
return crypto.randomUUID();
|
|
20
|
+
fallbackIdCounter += 1;
|
|
21
|
+
return `msg-${Date.now()}-${fallbackIdCounter}`;
|
|
22
|
+
}
|
|
23
|
+
function assistantContentFromEvents(events) {
|
|
24
|
+
let out = '';
|
|
25
|
+
for (const ev of events) {
|
|
26
|
+
if (ev.kind === 'text')
|
|
27
|
+
out += ev.text;
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
export function useConversation(options) {
|
|
32
|
+
const { transport, conversationId = null, agentId, createMessageId = defaultCreateMessageId } = options;
|
|
33
|
+
const [messages, setMessagesState] = useState(options.initialMessages ?? []);
|
|
34
|
+
const [scrollIntent, setScrollIntent] = useState(false);
|
|
35
|
+
const run = useRunStream(transport);
|
|
36
|
+
// The assistant message id the currently-active run is writing into.
|
|
37
|
+
const activeAssistantIdRef = useRef(null);
|
|
38
|
+
const messagesRef = useRef(messages);
|
|
39
|
+
messagesRef.current = messages;
|
|
40
|
+
const setMessages = useCallback((updater) => {
|
|
41
|
+
setMessagesState((prev) => (typeof updater === 'function' ? updater(prev) : updater));
|
|
42
|
+
}, []);
|
|
43
|
+
const applyRunToAssistantMessage = useCallback(() => {
|
|
44
|
+
const assistantId = activeAssistantIdRef.current;
|
|
45
|
+
if (!assistantId)
|
|
46
|
+
return;
|
|
47
|
+
setMessagesState((prev) => prev.map((m) => {
|
|
48
|
+
if (m.id !== assistantId)
|
|
49
|
+
return m;
|
|
50
|
+
// A plain if/else chain (not a nested ternary) — deliberately, so
|
|
51
|
+
// each of the four mapped statuses is its own independently
|
|
52
|
+
// trackable branch under coverage instrumentation. The initial
|
|
53
|
+
// value is asserted non-null: this reconciliation effect only ever
|
|
54
|
+
// runs after `sendMessage`/`retry` has called `run.start()`/
|
|
55
|
+
// `reattach` (both set the message's `runStatus: 'queued'` via
|
|
56
|
+
// `activeAssistantIdRef` first), so `m.runStatus` is always defined
|
|
57
|
+
// and `run.status` is never `'idle'` by the time this callback
|
|
58
|
+
// fires — one of the four branches below always reassigns it.
|
|
59
|
+
let runStatus = m.runStatus;
|
|
60
|
+
if (run.status === 'streaming')
|
|
61
|
+
runStatus = 'running';
|
|
62
|
+
else if (run.status === 'done')
|
|
63
|
+
runStatus = 'succeeded';
|
|
64
|
+
else if (run.status === 'error')
|
|
65
|
+
runStatus = 'failed';
|
|
66
|
+
else if (run.status === 'canceled')
|
|
67
|
+
runStatus = 'canceled';
|
|
68
|
+
const nextRunId = run.runId ?? m.runId;
|
|
69
|
+
return {
|
|
70
|
+
...m,
|
|
71
|
+
...(nextRunId !== undefined ? { runId: nextRunId } : {}),
|
|
72
|
+
events: run.events,
|
|
73
|
+
content: assistantContentFromEvents(run.events),
|
|
74
|
+
runStatus,
|
|
75
|
+
...(isTerminalRunStatus(runStatus) ? { endedAt: Date.now() } : {}),
|
|
76
|
+
};
|
|
77
|
+
}));
|
|
78
|
+
setScrollIntent(true);
|
|
79
|
+
}, [run.events, run.runId, run.status]);
|
|
80
|
+
// Reconcile the live run's events onto the streaming assistant message
|
|
81
|
+
// whenever any of them changes identity. `run.runId` must be included:
|
|
82
|
+
// an event can arrive (and get reconciled) before `start()`'s promise
|
|
83
|
+
// resolves with the real id, and if the id then resolves with no further
|
|
84
|
+
// event/status change, omitting it here would leave the message's runId
|
|
85
|
+
// permanently unset.
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
applyRunToAssistantMessage();
|
|
88
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89
|
+
}, [run.events, run.status, run.runId]);
|
|
90
|
+
const sendMessage = useCallback(async (content, sendOptions = {}) => {
|
|
91
|
+
const userMessage = {
|
|
92
|
+
id: createMessageId(),
|
|
93
|
+
role: 'user',
|
|
94
|
+
content,
|
|
95
|
+
createdAt: Date.now(),
|
|
96
|
+
...(sendOptions.attachments ? { attachments: sendOptions.attachments } : {}),
|
|
97
|
+
};
|
|
98
|
+
const resolvedAgentId = sendOptions.agentId ?? agentId;
|
|
99
|
+
const assistantMessage = {
|
|
100
|
+
id: createMessageId(),
|
|
101
|
+
role: 'assistant',
|
|
102
|
+
content: '',
|
|
103
|
+
...(resolvedAgentId !== undefined ? { agentId: resolvedAgentId } : {}),
|
|
104
|
+
runStatus: 'queued',
|
|
105
|
+
createdAt: Date.now(),
|
|
106
|
+
startedAt: Date.now(),
|
|
107
|
+
};
|
|
108
|
+
activeAssistantIdRef.current = assistantMessage.id;
|
|
109
|
+
const history = [...messagesRef.current, userMessage];
|
|
110
|
+
setMessagesState([...history, assistantMessage]);
|
|
111
|
+
setScrollIntent(true);
|
|
112
|
+
await run.start({
|
|
113
|
+
history,
|
|
114
|
+
...(resolvedAgentId !== undefined ? { agentId: resolvedAgentId } : {}),
|
|
115
|
+
conversationId,
|
|
116
|
+
...(sendOptions.attachments !== undefined ? { attachments: sendOptions.attachments } : {}),
|
|
117
|
+
...(sendOptions.context !== undefined ? { context: sendOptions.context } : {}),
|
|
118
|
+
});
|
|
119
|
+
}, [agentId, conversationId, createMessageId, run]);
|
|
120
|
+
const retry = useCallback(async (assistantMessageId) => {
|
|
121
|
+
const idx = messagesRef.current.findIndex((m) => m.id === assistantMessageId);
|
|
122
|
+
if (idx <= 0)
|
|
123
|
+
return;
|
|
124
|
+
const priorUser = messagesRef.current[idx - 1];
|
|
125
|
+
if (!priorUser || priorUser.role !== 'user')
|
|
126
|
+
return;
|
|
127
|
+
const history = messagesRef.current.slice(0, idx);
|
|
128
|
+
const resetAssistant = { ...messagesRef.current[idx], content: '', events: [], runStatus: 'queued' };
|
|
129
|
+
activeAssistantIdRef.current = resetAssistant.id;
|
|
130
|
+
setMessagesState([...history, resetAssistant]);
|
|
131
|
+
setScrollIntent(true);
|
|
132
|
+
const resolvedAgentId = resetAssistant.agentId ?? agentId;
|
|
133
|
+
// `priorUser`'s attachments go back out with the retry. They were located above and then
|
|
134
|
+
// dropped: `sendMessage` forwards `attachments` to `run.start`, this path did not, so
|
|
135
|
+
// retrying an image or file prompt re-sent the TEXT alone. The model then answered a question
|
|
136
|
+
// about a picture it could no longer see — and because the transcript still renders the
|
|
137
|
+
// attachment beside the user turn, the failure reads as the model ignoring it rather than as
|
|
138
|
+
// the client never having sent it.
|
|
139
|
+
await run.start({
|
|
140
|
+
history,
|
|
141
|
+
...(resolvedAgentId !== undefined ? { agentId: resolvedAgentId } : {}),
|
|
142
|
+
conversationId,
|
|
143
|
+
...(priorUser.attachments !== undefined ? { attachments: priorUser.attachments } : {}),
|
|
144
|
+
});
|
|
145
|
+
}, [agentId, conversationId, run]);
|
|
146
|
+
const cancel = useCallback(() => run.cancel(), [run]);
|
|
147
|
+
const acknowledgeScroll = useCallback(() => setScrollIntent(false), []);
|
|
148
|
+
const suppressScroll = useCallback(() => setScrollIntent(false), []);
|
|
149
|
+
return useMemo(() => ({
|
|
150
|
+
messages,
|
|
151
|
+
conversationId,
|
|
152
|
+
isStreaming: run.isStreaming,
|
|
153
|
+
error: run.error,
|
|
154
|
+
scrollIntent,
|
|
155
|
+
sendMessage,
|
|
156
|
+
cancel,
|
|
157
|
+
retry,
|
|
158
|
+
setMessages,
|
|
159
|
+
acknowledgeScroll,
|
|
160
|
+
suppressScroll,
|
|
161
|
+
}), [messages, conversationId, run.isStreaming, run.error, scrollIntent, sendMessage, cancel, retry, setMessages, acknowledgeScroll, suppressScroll]);
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=useConversation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useConversation.js","sourceRoot":"","sources":["../../../src/react/hooks/useConversation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface UseCopyToClipboardResult {
|
|
2
|
+
/** `true` for `COPIED_RESET_MS` after a successful `copy()` call, then reverts to `false` on its own. */
|
|
3
|
+
copied: boolean;
|
|
4
|
+
/** Copies `text` verbatim. Resolves to whether the copy actually succeeded. */
|
|
5
|
+
copy: (text: string) => Promise<boolean>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* React hook wrapping the copy-to-clipboard logic above with the transient
|
|
9
|
+
* `copied` UI flag callers use to drive an icon swap or status announcement.
|
|
10
|
+
* @returns The current `copied` flag and a `copy` function to invoke it.
|
|
11
|
+
* @complexity O(1) per `copy()` call (excluding the clipboard API's own cost).
|
|
12
|
+
*/
|
|
13
|
+
export declare function useCopyToClipboard(): UseCopyToClipboardResult;
|
|
14
|
+
//# sourceMappingURL=useCopyToClipboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCopyToClipboard.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useCopyToClipboard.ts"],"names":[],"mappings":"AA8DA,MAAM,WAAW,wBAAwB;IACvC,yGAAyG;IACzG,MAAM,EAAE,OAAO,CAAC;IAChB,+EAA+E;IAC/E,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,wBAAwB,CA8B7D"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module useCopyToClipboard
|
|
3
|
+
*
|
|
4
|
+
* Copies a string to the system clipboard and exposes a transient `copied`
|
|
5
|
+
* flag a UI affordance can key off of (icon swap, status text, ...). This is
|
|
6
|
+
* the shared primitive behind the per-message copy button in `MessageRow.tsx`
|
|
7
|
+
* -- kept here, not inlined there, so the per-block copy button
|
|
8
|
+
* `Markdown.tsx` still has as a TODO can reuse the same copy/fallback logic
|
|
9
|
+
* once it's built, without duplicating the secure-context handling below.
|
|
10
|
+
*
|
|
11
|
+
* Two copy paths, tried in order:
|
|
12
|
+
* 1. `navigator.clipboard.writeText` -- the modern async Clipboard API.
|
|
13
|
+
* Requires a secure context (HTTPS, or `localhost`); rejects everywhere
|
|
14
|
+
* else, and can also reject in a secure context that denies clipboard
|
|
15
|
+
* permission.
|
|
16
|
+
* 2. A hidden, focused, selected `<textarea>` + `document.execCommand('copy')`
|
|
17
|
+
* -- deprecated, but still the only synchronous copy path browsers expose
|
|
18
|
+
* outside a secure context. This package ships to hosts beyond localhost,
|
|
19
|
+
* so the secure-context requirement above can't be assumed.
|
|
20
|
+
*
|
|
21
|
+
* Both paths report their own success back to the caller (rather than being
|
|
22
|
+
* assumed to have worked) so a caller can decide how to react to a copy that
|
|
23
|
+
* silently failed instead of showing a false "Copied" state.
|
|
24
|
+
*/
|
|
25
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
26
|
+
/** How long the `copied` flag stays true after a successful copy before it reverts on its own. */
|
|
27
|
+
const COPIED_RESET_MS = 1500;
|
|
28
|
+
/**
|
|
29
|
+
* Synchronous fallback copy path for non-secure contexts: a hidden textarea
|
|
30
|
+
* gets the text, is selected, and `execCommand('copy')` is invoked against
|
|
31
|
+
* that selection. Returns whether the browser reports the command as
|
|
32
|
+
* executed -- `execCommand` itself throws in some embedding contexts (e.g. a
|
|
33
|
+
* sandboxed iframe without clipboard-write) rather than just returning
|
|
34
|
+
* `false`, so this also guards with try/catch.
|
|
35
|
+
* @param text - The exact string to place on the clipboard.
|
|
36
|
+
* @returns Whether the copy command executed successfully.
|
|
37
|
+
* @complexity O(1) -- one DOM node created, selected, and removed.
|
|
38
|
+
*/
|
|
39
|
+
function copyViaExecCommand(text) {
|
|
40
|
+
if (typeof document === 'undefined')
|
|
41
|
+
return false;
|
|
42
|
+
const textarea = document.createElement('textarea');
|
|
43
|
+
textarea.value = text;
|
|
44
|
+
// Off-screen but still focusable/selectable: a `display:none` element can't hold a selection.
|
|
45
|
+
textarea.style.position = 'fixed';
|
|
46
|
+
textarea.style.top = '-1000px';
|
|
47
|
+
textarea.style.left = '-1000px';
|
|
48
|
+
textarea.setAttribute('readonly', '');
|
|
49
|
+
document.body.appendChild(textarea);
|
|
50
|
+
textarea.focus();
|
|
51
|
+
textarea.select();
|
|
52
|
+
let ok = false;
|
|
53
|
+
try {
|
|
54
|
+
ok = document.execCommand('copy');
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
ok = false;
|
|
58
|
+
}
|
|
59
|
+
document.body.removeChild(textarea);
|
|
60
|
+
return ok;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* React hook wrapping the copy-to-clipboard logic above with the transient
|
|
64
|
+
* `copied` UI flag callers use to drive an icon swap or status announcement.
|
|
65
|
+
* @returns The current `copied` flag and a `copy` function to invoke it.
|
|
66
|
+
* @complexity O(1) per `copy()` call (excluding the clipboard API's own cost).
|
|
67
|
+
*/
|
|
68
|
+
export function useCopyToClipboard() {
|
|
69
|
+
const [copied, setCopied] = useState(false);
|
|
70
|
+
const resetTimer = useRef(undefined);
|
|
71
|
+
// Clears any pending reset on unmount so a copy just before navigating away never calls
|
|
72
|
+
// setState on an unmounted component.
|
|
73
|
+
useEffect(() => () => clearTimeout(resetTimer.current), []);
|
|
74
|
+
const copy = useCallback(async (text) => {
|
|
75
|
+
let ok = false;
|
|
76
|
+
if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {
|
|
77
|
+
try {
|
|
78
|
+
await navigator.clipboard.writeText(text);
|
|
79
|
+
ok = true;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Denied permission, or a non-secure context where the API exists but rejects every call.
|
|
83
|
+
ok = copyViaExecCommand(text);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
ok = copyViaExecCommand(text);
|
|
88
|
+
}
|
|
89
|
+
if (ok) {
|
|
90
|
+
setCopied(true);
|
|
91
|
+
clearTimeout(resetTimer.current);
|
|
92
|
+
resetTimer.current = setTimeout(() => setCopied(false), COPIED_RESET_MS);
|
|
93
|
+
}
|
|
94
|
+
return ok;
|
|
95
|
+
}, []);
|
|
96
|
+
return { copied, copy };
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=useCopyToClipboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCopyToClipboard.js","sourceRoot":"","sources":["../../../src/react/hooks/useCopyToClipboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjE,kGAAkG;AAClG,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B;;;;;;;;;;GAUG;AACH,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAClD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC;IACtB,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACtC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACjB,QAAQ,CAAC,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,GAAG,KAAK,CAAC;IACf,IAAI,CAAC;QACH,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,EAAE,GAAG,KAAK,CAAC;IACb,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,OAAO,EAAE,CAAC;AACZ,CAAC;AASD;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,MAAM,CAA4C,SAAS,CAAC,CAAC;IAEhF,wFAAwF;IACxF,sCAAsC;IACtC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAE5D,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,IAAY,EAAoB,EAAE;QAChE,IAAI,EAAE,GAAG,KAAK,CAAC;QACf,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC;YACvE,IAAI,CAAC;gBACH,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC1C,EAAE,GAAG,IAAI,CAAC;YACZ,CAAC;YAAC,MAAM,CAAC;gBACP,0FAA0F;gBAC1F,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,EAAE,EAAE,CAAC;YACP,SAAS,CAAC,IAAI,CAAC,CAAC;YAChB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACjC,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AgentEvent } from '../../core/index.js';
|
|
2
|
+
export interface ExtEventGroup {
|
|
3
|
+
name: string;
|
|
4
|
+
events: unknown[];
|
|
5
|
+
}
|
|
6
|
+
export declare function useExtEventGroups(events: AgentEvent[] | undefined): ExtEventGroup[];
|
|
7
|
+
//# sourceMappingURL=useExtEventGroups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useExtEventGroups.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useExtEventGroups.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS,GAAG,aAAa,EAAE,CAgBnF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module useExtEventGroups
|
|
3
|
+
*
|
|
4
|
+
* Groups a message's `kind: 'ext'` events by `name`. Groups are ordered by each name's first
|
|
5
|
+
* occurrence; within a group, events keep arrival order regardless of what's interleaved between
|
|
6
|
+
* them in the raw stream — `a2ui`, `a2ui`, `foo`, `a2ui` yields `[{name:'a2ui', events:[e1,e2,e3]},
|
|
7
|
+
* {name:'foo', events:[e2]}]` (indices illustrative), since `ExtEventRenderer` needs the full
|
|
8
|
+
* ordered sequence for a name, not just a contiguous run of it. Pure over `AgentEvent[]` — zero
|
|
9
|
+
* I/O, no React state, unlike `useToolTimeline` (which also tracks expand/collapse UI state
|
|
10
|
+
* ext-event renderers don't need since `MessageRow` doesn't own any generic collapsed/expanded
|
|
11
|
+
* chrome for them).
|
|
12
|
+
*/
|
|
13
|
+
import { useMemo } from 'react';
|
|
14
|
+
export function useExtEventGroups(events) {
|
|
15
|
+
return useMemo(() => {
|
|
16
|
+
const order = [];
|
|
17
|
+
const byName = new Map();
|
|
18
|
+
for (const ev of events ?? []) {
|
|
19
|
+
if (ev.kind !== 'ext')
|
|
20
|
+
continue;
|
|
21
|
+
let group = byName.get(ev.name);
|
|
22
|
+
if (!group) {
|
|
23
|
+
group = [];
|
|
24
|
+
byName.set(ev.name, group);
|
|
25
|
+
order.push(ev.name);
|
|
26
|
+
}
|
|
27
|
+
group.push(ev.data);
|
|
28
|
+
}
|
|
29
|
+
return order.map((name) => ({ name, events: byName.get(name) }));
|
|
30
|
+
}, [events]);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=useExtEventGroups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useExtEventGroups.js","sourceRoot":"","sources":["../../../src/react/hooks/useExtEventGroups.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAQhC,MAAM,UAAU,iBAAiB,CAAC,MAAgC;IAChE,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;QAC5C,KAAK,MAAM,EAAE,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC;YAC9B,IAAI,EAAE,CAAC,IAAI,KAAK,KAAK;gBAAE,SAAS;YAChC,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,KAAK,GAAG,EAAE,CAAC;gBACX,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAC3B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAE,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface OperationToken {
|
|
2
|
+
/**
|
|
3
|
+
* Abandons the surrounding {@link LatestOperation.run} body unless this is still the newest
|
|
4
|
+
* operation on a mounted component. Call it after each await, in place of a guard clause.
|
|
5
|
+
*/
|
|
6
|
+
ensureCurrent(): void;
|
|
7
|
+
/** Whether this is still the newest operation and the component is still mounted. */
|
|
8
|
+
isCurrent(): boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface LatestOperation {
|
|
11
|
+
/**
|
|
12
|
+
* Runs `body` as the newest operation, superseding any still in flight.
|
|
13
|
+
*
|
|
14
|
+
* `onError` is invoked only for a genuine failure of an operation that is *still* current — a
|
|
15
|
+
* superseded or unmounted one is discarded silently, which is what the hand-written guards did.
|
|
16
|
+
*/
|
|
17
|
+
run(body: (token: OperationToken) => Promise<void>, onError: (error: Error) => void): Promise<void>;
|
|
18
|
+
/** Supersedes whatever is in flight without starting a new operation. */
|
|
19
|
+
supersede(): void;
|
|
20
|
+
}
|
|
21
|
+
/** Preserves native Error objects while normalizing opaque host-bridge rejections. */
|
|
22
|
+
export declare function normalizeOperationError(error: unknown): Error;
|
|
23
|
+
/**
|
|
24
|
+
* Owns the mounted flag and the generation counter that decide which async attempt is allowed to
|
|
25
|
+
* write state. One instance per hook: every operation started through it supersedes the previous
|
|
26
|
+
* one, so a validation still in flight cannot clobber the result of the pick that replaced it.
|
|
27
|
+
*
|
|
28
|
+
* @complexity Time/space: O(1).
|
|
29
|
+
*/
|
|
30
|
+
export declare function useLatestOperation(): LatestOperation;
|
|
31
|
+
//# sourceMappingURL=useLatestOperation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLatestOperation.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useLatestOperation.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,aAAa,IAAI,IAAI,CAAC;IACtB,qFAAqF;IACrF,SAAS,IAAI,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,GAAG,CACD,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,EAC9C,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,yEAAyE;IACzE,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAE7D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAwCpD"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* "Only the newest attempt may write state" — the rule every async hook in this package needs, and
|
|
4
|
+
* the one that produced the worst complexity in the feature.
|
|
5
|
+
*
|
|
6
|
+
* Written by hand it is a `if (!mountedRef.current || generation !== generationRef.current) return;`
|
|
7
|
+
* after *every* await, repeated again inside the `catch`, inside a `useCallback` inside a hook — so
|
|
8
|
+
* each of those guards is scored at nesting level 2 or 3 and costs 3 cognitive points rather than 1.
|
|
9
|
+
* `useChatPaneWorkingDirectory` carried four near-identical copies of the shape.
|
|
10
|
+
*
|
|
11
|
+
* Here the guard throws instead of returning, and {@link LatestOperation.run} swallows it. The body
|
|
12
|
+
* then reads as a straight line of awaits with `token.ensureCurrent()` between them, and the branch
|
|
13
|
+
* exists once — in this file.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Thrown by {@link OperationToken.ensureCurrent} once its operation has been superseded or the
|
|
17
|
+
* component has unmounted. Never escapes {@link LatestOperation.run}, and callers neither construct
|
|
18
|
+
* nor catch it.
|
|
19
|
+
*/
|
|
20
|
+
class SupersededOperation extends Error {
|
|
21
|
+
constructor() {
|
|
22
|
+
super('operation superseded');
|
|
23
|
+
this.name = 'SupersededOperation';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Preserves native Error objects while normalizing opaque host-bridge rejections. */
|
|
27
|
+
export function normalizeOperationError(error) {
|
|
28
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Owns the mounted flag and the generation counter that decide which async attempt is allowed to
|
|
32
|
+
* write state. One instance per hook: every operation started through it supersedes the previous
|
|
33
|
+
* one, so a validation still in flight cannot clobber the result of the pick that replaced it.
|
|
34
|
+
*
|
|
35
|
+
* @complexity Time/space: O(1).
|
|
36
|
+
*/
|
|
37
|
+
export function useLatestOperation() {
|
|
38
|
+
const mountedRef = useRef(true);
|
|
39
|
+
const generationRef = useRef(0);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
mountedRef.current = true;
|
|
42
|
+
return () => {
|
|
43
|
+
mountedRef.current = false;
|
|
44
|
+
generationRef.current += 1;
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
const supersede = useCallback(() => {
|
|
48
|
+
generationRef.current += 1;
|
|
49
|
+
}, []);
|
|
50
|
+
const run = useCallback(async (body, onError) => {
|
|
51
|
+
const generation = ++generationRef.current;
|
|
52
|
+
const isCurrent = () => mountedRef.current && generation === generationRef.current;
|
|
53
|
+
const token = {
|
|
54
|
+
isCurrent,
|
|
55
|
+
ensureCurrent: () => {
|
|
56
|
+
// A generation only ever increases and unmount bumps it, so once stale always stale —
|
|
57
|
+
// which is why `run`'s catch needs no `instanceof` test to tell this apart from a real
|
|
58
|
+
// failure. `isCurrent()` is already false for anything thrown from here.
|
|
59
|
+
if (!isCurrent())
|
|
60
|
+
throw new SupersededOperation();
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
try {
|
|
64
|
+
await body(token);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (!isCurrent())
|
|
68
|
+
return;
|
|
69
|
+
onError(normalizeOperationError(error));
|
|
70
|
+
}
|
|
71
|
+
}, []);
|
|
72
|
+
return useMemo(() => ({ run, supersede }), [run, supersede]);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=useLatestOperation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLatestOperation.js","sourceRoot":"","sources":["../../../src/react/hooks/useLatestOperation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAEhE;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH,MAAM,mBAAoB,SAAQ,KAAK;IACrC;QACE,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AA2BD,sFAAsF;AACtF,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACpD,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAEhC,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC1B,OAAO,GAAG,EAAE;YACV,UAAU,CAAC,OAAO,GAAG,KAAK,CAAC;YAC3B,aAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QAC7B,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,aAAa,CAAC,OAAO,IAAI,CAAC,CAAC;IAC7B,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,EAC3B,IAA8C,EAC9C,OAA+B,EAChB,EAAE;QACjB,MAAM,UAAU,GAAG,EAAE,aAAa,CAAC,OAAO,CAAC;QAC3C,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,IAAI,UAAU,KAAK,aAAa,CAAC,OAAO,CAAC;QACnF,MAAM,KAAK,GAAmB;YAC5B,SAAS;YACT,aAAa,EAAE,GAAG,EAAE;gBAClB,sFAAsF;gBACtF,uFAAuF;gBACvF,yEAAyE;gBACzE,IAAI,CAAC,SAAS,EAAE;oBAAE,MAAM,IAAI,mBAAmB,EAAE,CAAC;YACpD,CAAC;SACF,CAAC;QACF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,SAAS,EAAE;gBAAE,OAAO;YACzB,OAAO,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ChatMessage, TodoItem } from '../../core/index.js';
|
|
2
|
+
export interface UsePinnedTodosResult {
|
|
3
|
+
todos: TodoItem[];
|
|
4
|
+
total: number;
|
|
5
|
+
completed: number;
|
|
6
|
+
inProgress: TodoItem | undefined;
|
|
7
|
+
/** `true` once every todo in the latest plan is `completed`. */
|
|
8
|
+
allComplete: boolean;
|
|
9
|
+
/** `false` when there's no plan yet, or the user dismissed the current (all-complete) plan. */
|
|
10
|
+
visible: boolean;
|
|
11
|
+
/** Dismisses the currently-pinned card. Only meaningful once `allComplete`; re-appears automatically once the plan changes again. */
|
|
12
|
+
dismiss: () => void;
|
|
13
|
+
}
|
|
14
|
+
export declare function usePinnedTodos(messages: ReadonlyArray<ChatMessage> | undefined): UsePinnedTodosResult;
|
|
15
|
+
//# sourceMappingURL=usePinnedTodos.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePinnedTodos.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/usePinnedTodos.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGjE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAC;IACjC,gEAAgE;IAChE,WAAW,EAAE,OAAO,CAAC;IACrB,+FAA+F;IAC/F,OAAO,EAAE,OAAO,CAAC;IACjB,qIAAqI;IACrI,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,SAAS,GAAG,oBAAoB,CAkBrG"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module usePinnedTodos
|
|
3
|
+
*
|
|
4
|
+
* The latest `TodoWrite`-style plan snapshot across a conversation, a
|
|
5
|
+
* dismissed-key so a user's dismissal sticks until the plan actually
|
|
6
|
+
* changes again, and progress counts for a pinned progress-card UI. Pure
|
|
7
|
+
* over `messages` — built on `@jini-ai/chat/core`'s
|
|
8
|
+
* `latestTodoWriteInputForPinnedCard`/`parseTodoWriteInput`. Per
|
|
9
|
+
* `ADS-memory/reports/jini-port/recon/r4b-webui-design.md` §4 (origin: OD's
|
|
10
|
+
* `runtime/todos.ts` pinned-card logic, `components/ToolCard.tsx`'s
|
|
11
|
+
* `TodoCard`'s `onDismiss` convention).
|
|
12
|
+
*/
|
|
13
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
14
|
+
import { latestTodoWriteInputForPinnedCard, parseTodoWriteInput } from '../../core/index.js';
|
|
15
|
+
export function usePinnedTodos(messages) {
|
|
16
|
+
const [dismissedKey, setDismissedKey] = useState(null);
|
|
17
|
+
const rawInput = useMemo(() => latestTodoWriteInputForPinnedCard(messages), [messages]);
|
|
18
|
+
const todos = useMemo(() => parseTodoWriteInput(rawInput), [rawInput]);
|
|
19
|
+
const key = useMemo(() => (rawInput === null ? null : safeStableKey(rawInput)), [rawInput]);
|
|
20
|
+
const total = todos.length;
|
|
21
|
+
const completed = todos.filter((t) => t.status === 'completed').length;
|
|
22
|
+
const allComplete = total > 0 && completed === total;
|
|
23
|
+
const inProgress = todos.find((t) => t.status === 'in_progress');
|
|
24
|
+
const visible = total > 0 && !(allComplete && key !== null && key === dismissedKey);
|
|
25
|
+
const dismiss = useCallback(() => {
|
|
26
|
+
if (key !== null)
|
|
27
|
+
setDismissedKey(key);
|
|
28
|
+
}, [key]);
|
|
29
|
+
return { todos, total, completed, inProgress, allComplete, visible, dismiss };
|
|
30
|
+
}
|
|
31
|
+
// A plan-tool `input` is arbitrary JSON; stringify gives a cheap, stable
|
|
32
|
+
// identity for "has the plan actually changed since dismissal" without
|
|
33
|
+
// depending on object reference equality (a fresh event array on every
|
|
34
|
+
// stream tick would otherwise always look "new").
|
|
35
|
+
function safeStableKey(input) {
|
|
36
|
+
try {
|
|
37
|
+
return JSON.stringify(input);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return String(input);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=usePinnedTodos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePinnedTodos.js","sourceRoot":"","sources":["../../../src/react/hooks/usePinnedTodos.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAE,iCAAiC,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAe7F,MAAM,UAAU,cAAc,CAAC,QAAgD;IAC7E,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAEtE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,iCAAiC,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE5F,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;IACvE,MAAM,WAAW,GAAG,KAAK,GAAG,CAAC,IAAI,SAAS,KAAK,KAAK,CAAC;IACrD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,YAAY,CAAC,CAAC;IAEpF,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;QAC/B,IAAI,GAAG,KAAK,IAAI;YAAE,eAAe,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEV,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAChF,CAAC;AAED,yEAAyE;AACzE,uEAAuE;AACvE,uEAAuE;AACvE,kDAAkD;AAClD,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ChatMessage, QuestionForm } from '../../core/index.js';
|
|
2
|
+
export type QuestionFormAnswers = Record<string, string | string[]>;
|
|
3
|
+
export interface ParsedQuestionForm {
|
|
4
|
+
form: QuestionForm;
|
|
5
|
+
raw: string;
|
|
6
|
+
/** The assistant message this form was found in. */
|
|
7
|
+
messageId: string;
|
|
8
|
+
/** `true` when this is the most recent assistant message with no reply after it yet — i.e. still answerable. */
|
|
9
|
+
interactive: boolean;
|
|
10
|
+
/** Recovered from the next user message's `[form answers — ...]` text, if one exists. */
|
|
11
|
+
submittedAnswers: QuestionFormAnswers | undefined;
|
|
12
|
+
}
|
|
13
|
+
export interface UseQuestionFormsResult {
|
|
14
|
+
/** Every question-form found across the conversation, oldest first. */
|
|
15
|
+
forms: ParsedQuestionForm[];
|
|
16
|
+
/** The most recent form that is still `interactive` (unanswered), or `null`. */
|
|
17
|
+
activeForm: ParsedQuestionForm | null;
|
|
18
|
+
/** Formats `answers` into the prose user-message text the host sends back. */
|
|
19
|
+
buildSubmission: (form: QuestionForm, answers: QuestionFormAnswers) => string;
|
|
20
|
+
}
|
|
21
|
+
export declare function useQuestionForms(messages: ReadonlyArray<ChatMessage> | undefined): UseQuestionFormsResult;
|
|
22
|
+
/**
|
|
23
|
+
* Reverse of `formatFormAnswers` — given the user message that (maybe)
|
|
24
|
+
* answered `form`, recover the answers map so the form can render in its
|
|
25
|
+
* locked "answered" state with the user's picks visible.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseSubmittedAnswers(form: QuestionForm, userMessageContent: string): QuestionFormAnswers | null;
|
|
28
|
+
//# sourceMappingURL=useQuestionForms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useQuestionForms.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useQuestionForms.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAgB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnF,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,YAAY,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,gHAAgH;IAChH,WAAW,EAAE,OAAO,CAAC;IACrB,yFAAyF;IACzF,gBAAgB,EAAE,mBAAmB,GAAG,SAAS,CAAC;CACnD;AAED,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,gFAAgF;IAChF,UAAU,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACtC,8EAA8E;IAC9E,eAAe,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,KAAK,MAAM,CAAC;CAC/E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,SAAS,GAAG,sBAAsB,CA6BzG;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAkChH"}
|