@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,224 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { describeChatPaneSendBlocker, findChatPaneSendBlocker, resolveChatPaneSelection, } from '../rules.js';
|
|
3
|
+
import { definedProps } from '../../../util/defined-props.js';
|
|
4
|
+
import { useComposer } from '../../../hooks/useComposer.js';
|
|
5
|
+
import { useConversation, } from '../../../hooks/useConversation.js';
|
|
6
|
+
import { useChatPaneWorkingDirectory, } from './useChatPaneWorkingDirectory.hooks.js';
|
|
7
|
+
function createAttachmentBatchId() {
|
|
8
|
+
return globalThis.crypto?.randomUUID?.()
|
|
9
|
+
?? `chat-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
10
|
+
}
|
|
11
|
+
/** Module scope so each branch costs 1 cognitive point instead of 2 (nested one level inside
|
|
12
|
+
* `useChatPane` where it used to live as a ternary chain). */
|
|
13
|
+
function resolveChatPaneActivity(selectedAgent, conversation) {
|
|
14
|
+
if (selectedAgent === undefined)
|
|
15
|
+
return 'unavailable';
|
|
16
|
+
if (conversation.error)
|
|
17
|
+
return 'failed';
|
|
18
|
+
if (conversation.isStreaming)
|
|
19
|
+
return 'streaming';
|
|
20
|
+
return 'ready';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Runs one attachment upload and, unless superseded/unmounted/aborted by the time it resolves,
|
|
24
|
+
* hands the results (or error) to the caller's effects. Concurrent by design — unlike
|
|
25
|
+
* {@link useLatestOperation}'s latest-wins model, several batches may be in flight at once
|
|
26
|
+
* (`addAttachments`'s `activeUploadsRef` is a `Set`, not a single slot) — so this takes an explicit
|
|
27
|
+
* `stillWanted()` check per attempt rather than a shared generation token.
|
|
28
|
+
*/
|
|
29
|
+
async function uploadAttachmentBatch(files, effects) {
|
|
30
|
+
try {
|
|
31
|
+
const uploaded = await effects.upload(files, { signal: effects.signal, batchId: effects.batchId });
|
|
32
|
+
if (!effects.stillWanted())
|
|
33
|
+
return;
|
|
34
|
+
for (const attachment of uploaded)
|
|
35
|
+
effects.onAttachment(attachment);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (!effects.stillWanted())
|
|
39
|
+
return;
|
|
40
|
+
effects.onError(error instanceof Error ? error : new Error(String(error)));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function useChatPane(options) {
|
|
44
|
+
const [activeUploadCount, setActiveUploadCount] = useState(0);
|
|
45
|
+
const [attachmentError, setAttachmentError] = useState(null);
|
|
46
|
+
const mountedRef = useRef(true);
|
|
47
|
+
const attachmentGenerationRef = useRef(0);
|
|
48
|
+
const attachmentBatchIdRef = useRef(createAttachmentBatchId());
|
|
49
|
+
const activeUploadsRef = useRef(new Set());
|
|
50
|
+
const [internalSelection, setInternalSelection] = useState(options.initialSelection ?? { agentId: '' });
|
|
51
|
+
const workingDirectoryState = useChatPaneWorkingDirectory(definedProps({
|
|
52
|
+
workingDirectory: options.workingDirectory,
|
|
53
|
+
initialWorkingDirectory: options.initialWorkingDirectory,
|
|
54
|
+
onChangeWorkingDirectory: options.onChangeWorkingDirectory,
|
|
55
|
+
workingDirectoryAccess: options.workingDirectoryAccess,
|
|
56
|
+
}));
|
|
57
|
+
const requestedSelection = options.selection ?? internalSelection;
|
|
58
|
+
const selection = useMemo(() => resolveChatPaneSelection(options.agents, requestedSelection), [options.agents, requestedSelection]);
|
|
59
|
+
const selectedAgent = options.agents.find((agent) => agent.id === selection.agentId);
|
|
60
|
+
const composer = useComposer(definedProps({
|
|
61
|
+
initialDraft: options.initialDraft,
|
|
62
|
+
initialAgent: selection,
|
|
63
|
+
conversationId: options.conversationId,
|
|
64
|
+
}));
|
|
65
|
+
const conversation = useConversation(definedProps({
|
|
66
|
+
transport: options.transport,
|
|
67
|
+
initialMessages: options.initialMessages,
|
|
68
|
+
conversationId: options.conversationId,
|
|
69
|
+
// Keys off an empty string, not `undefined` — `selection.agentId` is always a string (never
|
|
70
|
+
// absent), so only the falsy "no agent selected" case should omit the key.
|
|
71
|
+
agentId: selection.agentId || undefined,
|
|
72
|
+
}));
|
|
73
|
+
const activity = resolveChatPaneActivity(selectedAgent, conversation);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
options.onActivityChange?.(activity);
|
|
76
|
+
}, [activity, options.onActivityChange]);
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
options.onMessagesChange?.(conversation.messages);
|
|
79
|
+
}, [conversation.messages, options.onMessagesChange]);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
mountedRef.current = true;
|
|
82
|
+
return () => {
|
|
83
|
+
mountedRef.current = false;
|
|
84
|
+
attachmentGenerationRef.current += 1;
|
|
85
|
+
for (const controller of activeUploadsRef.current)
|
|
86
|
+
controller.abort();
|
|
87
|
+
activeUploadsRef.current.clear();
|
|
88
|
+
};
|
|
89
|
+
}, []);
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (!selection.agentId)
|
|
92
|
+
return;
|
|
93
|
+
if (requestedSelection.agentId === selection.agentId
|
|
94
|
+
&& requestedSelection.model === selection.model
|
|
95
|
+
&& requestedSelection.reasoning === selection.reasoning)
|
|
96
|
+
return;
|
|
97
|
+
if (options.selection === undefined)
|
|
98
|
+
setInternalSelection(selection);
|
|
99
|
+
composer.setAgent(selection);
|
|
100
|
+
options.onSelectionChange?.(selection);
|
|
101
|
+
}, [
|
|
102
|
+
composer,
|
|
103
|
+
options.onSelectionChange,
|
|
104
|
+
options.selection,
|
|
105
|
+
requestedSelection.agentId,
|
|
106
|
+
requestedSelection.model,
|
|
107
|
+
requestedSelection.reasoning,
|
|
108
|
+
selection,
|
|
109
|
+
]);
|
|
110
|
+
const setSelection = useCallback((next) => {
|
|
111
|
+
const validated = resolveChatPaneSelection(options.agents, next);
|
|
112
|
+
setInternalSelection(validated);
|
|
113
|
+
composer.setAgent(validated);
|
|
114
|
+
options.onSelectionChange?.(validated);
|
|
115
|
+
}, [composer, options.agents, options.onSelectionChange]);
|
|
116
|
+
const sendBlocker = findChatPaneSendBlocker({
|
|
117
|
+
selectedAgent,
|
|
118
|
+
isStreaming: conversation.isStreaming,
|
|
119
|
+
activeUploadCount,
|
|
120
|
+
workingDirectoryPending: workingDirectoryState.workingDirectoryPending,
|
|
121
|
+
workingDirectoryInvalid: workingDirectoryState.workingDirectoryInvalid,
|
|
122
|
+
workingDirectoryError: workingDirectoryState.workingDirectoryError,
|
|
123
|
+
});
|
|
124
|
+
const canSend = sendBlocker === null && composer.canSubmit;
|
|
125
|
+
const addAttachments = useCallback(async (files) => {
|
|
126
|
+
if (files.length === 0 || options.uploadAttachments === undefined)
|
|
127
|
+
return;
|
|
128
|
+
const generation = attachmentGenerationRef.current;
|
|
129
|
+
const controller = new AbortController();
|
|
130
|
+
activeUploadsRef.current.add(controller);
|
|
131
|
+
setActiveUploadCount(activeUploadsRef.current.size);
|
|
132
|
+
setAttachmentError(null);
|
|
133
|
+
try {
|
|
134
|
+
await uploadAttachmentBatch(files, {
|
|
135
|
+
upload: options.uploadAttachments,
|
|
136
|
+
signal: controller.signal,
|
|
137
|
+
batchId: attachmentBatchIdRef.current,
|
|
138
|
+
stillWanted: () => mountedRef.current
|
|
139
|
+
&& !controller.signal.aborted
|
|
140
|
+
&& generation === attachmentGenerationRef.current,
|
|
141
|
+
onAttachment: (attachment) => composer.addAttachment(attachment),
|
|
142
|
+
onError: setAttachmentError,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
if (activeUploadsRef.current.delete(controller) && mountedRef.current) {
|
|
147
|
+
setActiveUploadCount(activeUploadsRef.current.size);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}, [composer, options.uploadAttachments]);
|
|
151
|
+
const sendPrompt = useCallback(async (prompt) => {
|
|
152
|
+
const trimmed = prompt.trim();
|
|
153
|
+
if (!trimmed)
|
|
154
|
+
throw new Error('cannot send: the prompt is empty');
|
|
155
|
+
if (sendBlocker !== null) {
|
|
156
|
+
throw new Error(`cannot send: ${describeChatPaneSendBlocker(sendBlocker)}`);
|
|
157
|
+
}
|
|
158
|
+
const attachments = composer.attachments;
|
|
159
|
+
const context = typeof options.runContext === 'function'
|
|
160
|
+
? options.runContext({
|
|
161
|
+
prompt: trimmed,
|
|
162
|
+
selection,
|
|
163
|
+
workingDirectory: workingDirectoryState.workingDirectory,
|
|
164
|
+
})
|
|
165
|
+
: options.runContext;
|
|
166
|
+
composer.reset();
|
|
167
|
+
attachmentGenerationRef.current += 1;
|
|
168
|
+
attachmentBatchIdRef.current = createAttachmentBatchId();
|
|
169
|
+
options.onActivityChange?.('queued');
|
|
170
|
+
await conversation.sendMessage(trimmed, definedProps({
|
|
171
|
+
agentId: selection.agentId,
|
|
172
|
+
// Omitted when the array is EMPTY, not merely absent — an empty `attachments: []` would be a
|
|
173
|
+
// different (valid, present) value to the transport than "no attachments key at all".
|
|
174
|
+
attachments: attachments.length === 0 ? undefined : attachments,
|
|
175
|
+
context,
|
|
176
|
+
}));
|
|
177
|
+
}, [
|
|
178
|
+
composer,
|
|
179
|
+
conversation,
|
|
180
|
+
options.onActivityChange,
|
|
181
|
+
options.runContext,
|
|
182
|
+
selection,
|
|
183
|
+
sendBlocker,
|
|
184
|
+
workingDirectoryState.workingDirectory,
|
|
185
|
+
]);
|
|
186
|
+
const send = useCallback(async () => {
|
|
187
|
+
const prompt = composer.draft.trim()
|
|
188
|
+
|| (composer.attachments.length > 0 ? 'Review the attached file(s).' : '');
|
|
189
|
+
if (!prompt || !canSend)
|
|
190
|
+
return;
|
|
191
|
+
await sendPrompt(prompt);
|
|
192
|
+
}, [canSend, composer, sendPrompt]);
|
|
193
|
+
const reset = useCallback(() => {
|
|
194
|
+
attachmentGenerationRef.current += 1;
|
|
195
|
+
attachmentBatchIdRef.current = createAttachmentBatchId();
|
|
196
|
+
for (const controller of activeUploadsRef.current)
|
|
197
|
+
controller.abort();
|
|
198
|
+
activeUploadsRef.current.clear();
|
|
199
|
+
setActiveUploadCount(0);
|
|
200
|
+
conversation.cancel();
|
|
201
|
+
conversation.setMessages(options.initialMessages ?? []);
|
|
202
|
+
composer.reset();
|
|
203
|
+
setAttachmentError(null);
|
|
204
|
+
}, [composer, conversation, options.initialMessages]);
|
|
205
|
+
return {
|
|
206
|
+
conversation,
|
|
207
|
+
composer,
|
|
208
|
+
selection,
|
|
209
|
+
selectedAgent,
|
|
210
|
+
agents: options.agents,
|
|
211
|
+
activity,
|
|
212
|
+
canSend,
|
|
213
|
+
sendBlocker,
|
|
214
|
+
isUploadingAttachments: activeUploadCount > 0,
|
|
215
|
+
attachmentError,
|
|
216
|
+
...workingDirectoryState,
|
|
217
|
+
setSelection,
|
|
218
|
+
addAttachments,
|
|
219
|
+
send,
|
|
220
|
+
sendPrompt,
|
|
221
|
+
reset,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=useChatPane.hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChatPane.hooks.js","sourceRoot":"","sources":["../../../../../src/react/features/chat-pane/hooks/useChatPane.hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ChatPaneAgentBridgeAccess } from '../types.js';
|
|
2
|
+
import type { UseChatPaneResult } from './useChatPane.hooks.js';
|
|
3
|
+
export interface UseChatPaneAgentControlOptions {
|
|
4
|
+
/** Defaults to `false` — agent control is opt-in. */
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
bridgeAccess?: ChatPaneAgentBridgeAccess;
|
|
7
|
+
/**
|
|
8
|
+
* Register these tools with the in-page WebMCP surface (`document.modelContext`). Defaults to
|
|
9
|
+
* `false`, and that default is a security position rather than caution.
|
|
10
|
+
*
|
|
11
|
+
* The daemon-relayed channel routes every call through `ToolExecutor` — policy, confirmation,
|
|
12
|
+
* timeout, audit. A WebMCP call cannot: it originates inside the page from a browser-native
|
|
13
|
+
* caller, with no run and no principal to authorize against, so there is nothing for the gate to
|
|
14
|
+
* decide on and no run to attribute the action to. Routing it through the daemon would mean
|
|
15
|
+
* inventing both, which is worse than not gating — an invented principal is a gate that says yes.
|
|
16
|
+
*
|
|
17
|
+
* So a host that turns this on is accepting that anything able to reach `document.modelContext`
|
|
18
|
+
* — a browser extension, another script on the page — can drive this pane ungated. That is a
|
|
19
|
+
* legitimate choice for a trusted first-party surface and a bad one for a page hosting untrusted
|
|
20
|
+
* content, which is exactly why it has to be the host's call and not a default.
|
|
21
|
+
*/
|
|
22
|
+
webmcp?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Wires the chat pane's own actions (send/draft/selection/cancel/reset/working-directory/state) up
|
|
26
|
+
* to the outside-caller surfaces the pane supports: a daemon-relayed action channel when
|
|
27
|
+
* `bridgeAccess` is supplied, so an HTTP- or MCP-driven caller can reach this SAME live pane
|
|
28
|
+
* instance, and — only when the host sets `webmcp` — in-page WebMCP tool registration
|
|
29
|
+
* (`document.modelContext.registerTool`, feature-detected). Both dispatch through one identical
|
|
30
|
+
* action map (`runChatPaneAction`, module scope above), so the two callers can never diverge in
|
|
31
|
+
* *behavior*.
|
|
32
|
+
*
|
|
33
|
+
* They do differ in *authorization*, and that difference is the reason WebMCP is off by default.
|
|
34
|
+
* The relayed channel arrives having already passed `ToolExecutor`; a WebMCP call has no run and
|
|
35
|
+
* no principal, so it cannot. See {@link UseChatPaneAgentControlOptions.webmcp}.
|
|
36
|
+
*/
|
|
37
|
+
export declare function useChatPaneAgentControl(pane: UseChatPaneResult, options?: UseChatPaneAgentControlOptions): void;
|
|
38
|
+
//# sourceMappingURL=useChatPaneAgentControl.hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChatPaneAgentControl.hooks.d.ts","sourceRoot":"","sources":["../../../../../src/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,yBAAyB,EAA2B,MAAM,aAAa,CAAC;AAEtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,WAAW,8BAA8B;IAC7C,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,yBAAyB,CAAC;IACzC;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAoOD;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,iBAAiB,EACvB,OAAO,GAAE,8BAAmC,GAC3C,IAAI,CA+DN"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { CHAT_PANE_AGENT_TOOLS } from '../agent-tools.js';
|
|
3
|
+
import { definedProps } from '../../../util/defined-props.js';
|
|
4
|
+
function getModelContext() {
|
|
5
|
+
const doc = globalThis.document;
|
|
6
|
+
if (isModelContext(doc?.modelContext))
|
|
7
|
+
return doc.modelContext;
|
|
8
|
+
const nav = globalThis.navigator;
|
|
9
|
+
if (isModelContext(nav?.modelContext))
|
|
10
|
+
return nav.modelContext;
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
function isModelContext(value) {
|
|
14
|
+
return typeof value === 'object' && value !== null && typeof value.registerTool === 'function';
|
|
15
|
+
}
|
|
16
|
+
function requireStringField(input, key) {
|
|
17
|
+
const value = input[key];
|
|
18
|
+
if (typeof value !== 'string' || value.length === 0)
|
|
19
|
+
throw new Error(`"${key}" is required`);
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
function optionalStringField(input, key) {
|
|
23
|
+
const value = input[key];
|
|
24
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
25
|
+
}
|
|
26
|
+
/** Gate for capabilities whose manifest entry sets `requiresConfirmation`. */
|
|
27
|
+
function requireConfirmation(input, what) {
|
|
28
|
+
if (input['confirm'] !== true) {
|
|
29
|
+
throw new Error(`"confirm" must be true — ${what} is destructive and needs explicit acknowledgement`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function errorMessage(error) {
|
|
33
|
+
return error instanceof Error ? error.message : String(error);
|
|
34
|
+
}
|
|
35
|
+
/** Content read off the page/transcript is untrusted input to whatever model reads it back. */
|
|
36
|
+
const MAX_RETURNED_CONTENT = 2000;
|
|
37
|
+
function summarizeContent(content) {
|
|
38
|
+
return {
|
|
39
|
+
content: content.slice(0, MAX_RETURNED_CONTENT),
|
|
40
|
+
truncated: content.length > MAX_RETURNED_CONTENT,
|
|
41
|
+
originalLength: content.length,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Routes through the pane's own guarded send (`rules.ts`'s blocker set + staged attachments +
|
|
46
|
+
* composer reset + batch rotation + activity notification) rather than calling
|
|
47
|
+
* `conversation.sendMessage` directly, so an agent-driven send cannot bypass what the composer
|
|
48
|
+
* enforces. Throws a describable refusal when blocked.
|
|
49
|
+
*
|
|
50
|
+
* It also does not go the other obvious route — `composer.setDraft(prompt)` followed by `send()`.
|
|
51
|
+
* `setDraft` is a React state update and is therefore asynchronous, so the `send()` immediately
|
|
52
|
+
* after it would race the re-render and read a stale draft. Passing the prompt straight to
|
|
53
|
+
* `sendPrompt` is what makes the agent-driven path deterministic.
|
|
54
|
+
*/
|
|
55
|
+
async function sendMessageAction(pane, input) {
|
|
56
|
+
await pane.sendPrompt(requireStringField(input, 'prompt'));
|
|
57
|
+
return { sent: true };
|
|
58
|
+
}
|
|
59
|
+
async function setDraftAction(pane, input) {
|
|
60
|
+
pane.composer.setDraft(requireStringField(input, 'text'));
|
|
61
|
+
return { ok: true };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Only a runtime this machine actually offers.
|
|
65
|
+
*
|
|
66
|
+
* `setSelection` normalizes an unknown or unavailable agent to the first available one — correct
|
|
67
|
+
* for the picker, which must not break when a runtime disappears mid-session. For a caller that is
|
|
68
|
+
* told `{ok:true}`, that same behavior is a lie with a safety edge: asking for a constrained
|
|
69
|
+
* runtime and silently getting a more capable one is how a prompt intended for a sandboxed agent
|
|
70
|
+
* reaches a full coding agent instead. So this refuses by name rather than substituting.
|
|
71
|
+
*/
|
|
72
|
+
async function selectAgentAction(pane, input) {
|
|
73
|
+
const agentId = requireStringField(input, 'agentId');
|
|
74
|
+
const agent = pane.agents.find((candidate) => candidate.id === agentId);
|
|
75
|
+
if (agent === undefined) {
|
|
76
|
+
const known = pane.agents.map((candidate) => candidate.id).join(', ');
|
|
77
|
+
throw new Error(`unknown agent "${agentId}" — this pane offers: ${known || 'none'}`);
|
|
78
|
+
}
|
|
79
|
+
if (agent.available === false) {
|
|
80
|
+
throw new Error(`agent "${agentId}" is not available on this machine`
|
|
81
|
+
+ `${agent.diagnostic === undefined ? '' : ` (${agent.diagnostic})`}`);
|
|
82
|
+
}
|
|
83
|
+
const model = optionalStringField(input, 'model');
|
|
84
|
+
const reasoning = optionalStringField(input, 'reasoning');
|
|
85
|
+
pane.setSelection(definedProps({ agentId, model, reasoning }));
|
|
86
|
+
return { ok: true };
|
|
87
|
+
}
|
|
88
|
+
async function cancelRunAction(pane) {
|
|
89
|
+
pane.conversation.cancel();
|
|
90
|
+
return { ok: true };
|
|
91
|
+
}
|
|
92
|
+
async function resetConversationAction(pane, input) {
|
|
93
|
+
requireConfirmation(input, 'resetting the conversation');
|
|
94
|
+
pane.reset();
|
|
95
|
+
return { ok: true };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Only a directory the user already approved through the host's native picker. Passing a
|
|
99
|
+
* model-supplied path straight to `selectRecentDirectory` would let the caller choose its own
|
|
100
|
+
* project root, which is the desktop host's human-approval model (`reference-desktop`'s
|
|
101
|
+
* `approvedDirectories`) inverted.
|
|
102
|
+
*/
|
|
103
|
+
async function setWorkingDirectoryAction(pane, input) {
|
|
104
|
+
const path = requireStringField(input, 'path');
|
|
105
|
+
if (!pane.recentDirectories.includes(path)) {
|
|
106
|
+
throw new Error('path must be one of the already-approved recentDirectories from chat.get_state; '
|
|
107
|
+
+ 'a new directory can only be approved by the user through the host picker');
|
|
108
|
+
}
|
|
109
|
+
await pane.selectRecentDirectory(path);
|
|
110
|
+
return { ok: true };
|
|
111
|
+
}
|
|
112
|
+
async function getStateAction(pane) {
|
|
113
|
+
const lastMessage = pane.conversation.messages.at(-1);
|
|
114
|
+
const lastMessageSummary = lastMessage === undefined
|
|
115
|
+
? undefined
|
|
116
|
+
: { role: lastMessage.role, ...summarizeContent(lastMessage.content) };
|
|
117
|
+
return {
|
|
118
|
+
activity: pane.activity,
|
|
119
|
+
selection: pane.selection,
|
|
120
|
+
workingDirectory: pane.workingDirectory,
|
|
121
|
+
recentDirectories: pane.recentDirectories,
|
|
122
|
+
canSend: pane.canSend,
|
|
123
|
+
sendBlocker: pane.sendBlocker,
|
|
124
|
+
messageCount: pane.conversation.messages.length,
|
|
125
|
+
...definedProps({ lastMessage: lastMessageSummary }),
|
|
126
|
+
/**
|
|
127
|
+
* Conversation content is user- and agent-authored text, not instructions from the
|
|
128
|
+
* host. A caller reading it back must treat it as data.
|
|
129
|
+
*/
|
|
130
|
+
untrustedFields: ['lastMessage.content'],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const CHAT_PANE_ACTION_HANDLERS = {
|
|
134
|
+
'chat.send_message': sendMessageAction,
|
|
135
|
+
'chat.set_draft': setDraftAction,
|
|
136
|
+
'chat.select_agent': selectAgentAction,
|
|
137
|
+
'chat.cancel_run': cancelRunAction,
|
|
138
|
+
'chat.reset_conversation': resetConversationAction,
|
|
139
|
+
'chat.set_working_directory': setWorkingDirectoryAction,
|
|
140
|
+
'chat.get_state': getStateAction,
|
|
141
|
+
};
|
|
142
|
+
/** Module-scope so the dispatch itself (one `if`, no branch-per-capability) never pays the
|
|
143
|
+
* per-nested-closure cognitive tax that a `switch` written inline in the effect would; each
|
|
144
|
+
* capability's own logic — and its own explanatory comment — lives in its own top-level
|
|
145
|
+
* function above instead. */
|
|
146
|
+
async function runChatPaneAction(pane, id, input) {
|
|
147
|
+
const handler = CHAT_PANE_ACTION_HANDLERS[id];
|
|
148
|
+
if (!handler)
|
|
149
|
+
throw new Error(`unknown chat capability: ${id}`);
|
|
150
|
+
return handler(pane, input);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Answers one daemon-relayed action on the bridge that delivered it, never on whatever bridge is
|
|
154
|
+
* current: the `invocationId` belongs to that channel, so answering elsewhere would be answering a
|
|
155
|
+
* question nobody asked.
|
|
156
|
+
*
|
|
157
|
+
* Delivery is reported separately from execution: a rejection inside `respondSuccess` is a failure
|
|
158
|
+
* to ANSWER, not a failed action, and must not be re-reported as one. Every delivery attempt is
|
|
159
|
+
* itself guarded so a dead channel cannot surface as an unhandled rejection with the daemon-side
|
|
160
|
+
* invocation left hanging.
|
|
161
|
+
*/
|
|
162
|
+
async function deliverBridgeAction(pane, bridge, action) {
|
|
163
|
+
let output;
|
|
164
|
+
try {
|
|
165
|
+
output = await runChatPaneAction(pane, action.capabilityId, action.input);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
await bridge.respondError(action.invocationId, errorMessage(error)).catch(() => undefined);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
await bridge.respondSuccess(action.invocationId, output);
|
|
173
|
+
}
|
|
174
|
+
catch (deliveryError) {
|
|
175
|
+
await bridge
|
|
176
|
+
.respondError(action.invocationId, `action succeeded but the result could not be delivered: ${errorMessage(deliveryError)}`)
|
|
177
|
+
.catch(() => undefined);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Wires the chat pane's own actions (send/draft/selection/cancel/reset/working-directory/state) up
|
|
182
|
+
* to the outside-caller surfaces the pane supports: a daemon-relayed action channel when
|
|
183
|
+
* `bridgeAccess` is supplied, so an HTTP- or MCP-driven caller can reach this SAME live pane
|
|
184
|
+
* instance, and — only when the host sets `webmcp` — in-page WebMCP tool registration
|
|
185
|
+
* (`document.modelContext.registerTool`, feature-detected). Both dispatch through one identical
|
|
186
|
+
* action map (`runChatPaneAction`, module scope above), so the two callers can never diverge in
|
|
187
|
+
* *behavior*.
|
|
188
|
+
*
|
|
189
|
+
* They do differ in *authorization*, and that difference is the reason WebMCP is off by default.
|
|
190
|
+
* The relayed channel arrives having already passed `ToolExecutor`; a WebMCP call has no run and
|
|
191
|
+
* no principal, so it cannot. See {@link UseChatPaneAgentControlOptions.webmcp}.
|
|
192
|
+
*/
|
|
193
|
+
export function useChatPaneAgentControl(pane, options = {}) {
|
|
194
|
+
const enabled = options.enabled ?? false;
|
|
195
|
+
const paneRef = useRef(pane);
|
|
196
|
+
paneRef.current = pane;
|
|
197
|
+
const bridgeAccessRef = useRef(options.bridgeAccess);
|
|
198
|
+
bridgeAccessRef.current = options.bridgeAccess;
|
|
199
|
+
// Presence, not identity: hosts write `agentControl={{...}}` inline in JSX (as every other prop
|
|
200
|
+
// here is written), so depending on the object itself would tear down and re-register all tools
|
|
201
|
+
// on every render, dropping in-flight actions. See the effect's closing comment for the tradeoff.
|
|
202
|
+
const hasBridgeAccess = options.bridgeAccess !== undefined;
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
if (!enabled)
|
|
205
|
+
return;
|
|
206
|
+
const cleanups = [];
|
|
207
|
+
// Not registered unless the host opted in: see `webmcp`'s own doc for why this path cannot be
|
|
208
|
+
// gated and therefore must not be on by default.
|
|
209
|
+
const modelContext = options.webmcp === true ? getModelContext() : undefined;
|
|
210
|
+
if (modelContext) {
|
|
211
|
+
const controller = new AbortController();
|
|
212
|
+
for (const tool of CHAT_PANE_AGENT_TOOLS) {
|
|
213
|
+
// `registerTool` is async per the draft IDL, and a polyfill may return undefined instead.
|
|
214
|
+
// Normalize both, then swallow: registration is best-effort, and a rejected one must not
|
|
215
|
+
// surface as an unhandled rejection from a React effect.
|
|
216
|
+
const registered = modelContext.registerTool({
|
|
217
|
+
name: tool.id,
|
|
218
|
+
description: tool.description,
|
|
219
|
+
inputSchema: tool.inputSchema,
|
|
220
|
+
execute: (args) => runChatPaneAction(paneRef.current, tool.id, args ?? {}),
|
|
221
|
+
}, { signal: controller.signal });
|
|
222
|
+
void Promise.resolve(registered).catch(() => undefined);
|
|
223
|
+
}
|
|
224
|
+
cleanups.push(() => {
|
|
225
|
+
controller.abort();
|
|
226
|
+
if (modelContext.unregisterTool) {
|
|
227
|
+
for (const tool of CHAT_PANE_AGENT_TOOLS)
|
|
228
|
+
modelContext.unregisterTool(tool.id);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const subscribedBridge = bridgeAccessRef.current;
|
|
233
|
+
if (subscribedBridge) {
|
|
234
|
+
const unsubscribe = subscribedBridge.subscribe((action) => {
|
|
235
|
+
void deliverBridgeAction(paneRef.current, subscribedBridge, action);
|
|
236
|
+
});
|
|
237
|
+
cleanups.push(unsubscribe);
|
|
238
|
+
}
|
|
239
|
+
return () => {
|
|
240
|
+
for (const cleanup of cleanups)
|
|
241
|
+
cleanup();
|
|
242
|
+
};
|
|
243
|
+
// Deps are enablement + bridge PRESENCE, never the bridge object: hosts pass `agentControl`
|
|
244
|
+
// inline, so an identity dep would re-register every tool on every render (see
|
|
245
|
+
// `hasBridgeAccess`). Pane, run context, and bridge are all read through refs at call time.
|
|
246
|
+
// Tradeoff: swapping to a genuinely different bridge instance while enabled does not
|
|
247
|
+
// re-subscribe — responses still route to the current bridge via the ref, but the old
|
|
248
|
+
// subscription stays live. A host needing a true swap should toggle `enabled` or remount.
|
|
249
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
250
|
+
}, [enabled, hasBridgeAccess]);
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=useChatPaneAgentControl.hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChatPaneAgentControl.hooks.js","sourceRoot":"","sources":["../../../../../src/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const CHAT_PANE_CONTROLS_HEIGHT_CSS_VAR = "--jini-chat-controls-height";
|
|
2
|
+
export interface UseChatPaneControlsHeightResult {
|
|
3
|
+
/** Attach to the pane's root element — the nearest ancestor shared by both `.jini-message-list` and `.jini-chat-pane__controls`. */
|
|
4
|
+
rootRef: React.RefObject<HTMLElement | null>;
|
|
5
|
+
/** Attach to `.jini-chat-pane__controls` — the element whose real height is measured. */
|
|
6
|
+
controlsRef: React.RefObject<HTMLDivElement | null>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Keeps {@link CHAT_PANE_CONTROLS_HEIGHT_CSS_VAR} on the pane root in sync with the controls
|
|
10
|
+
* overlay's actual rendered height.
|
|
11
|
+
*
|
|
12
|
+
* @returns Two refs to attach — see {@link UseChatPaneControlsHeightResult}.
|
|
13
|
+
* @complexity O(1) per resize notification.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useChatPaneControlsHeight(): UseChatPaneControlsHeightResult;
|
|
16
|
+
//# sourceMappingURL=useChatPaneControlsHeight.hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChatPaneControlsHeight.hooks.d.ts","sourceRoot":"","sources":["../../../../../src/react/features/chat-pane/hooks/useChatPaneControlsHeight.hooks.ts"],"names":[],"mappings":"AA8BA,eAAO,MAAM,iCAAiC,gCAAgC,CAAC;AAE/E,MAAM,WAAW,+BAA+B;IAC9C,oIAAoI;IACpI,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C,yFAAyF;IACzF,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CACrD;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,IAAI,+BAA+B,CAoB3E"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module useChatPaneControlsHeight
|
|
3
|
+
*
|
|
4
|
+
* `.jini-chat-pane__controls` (composer, suggestions row, status messages) is deliberately an
|
|
5
|
+
* absolutely-positioned overlay rather than a flex sibling that pushes the transcript up — see
|
|
6
|
+
* `styles.ts`'s own comment on that rule for the gradient-fade reasoning. Positioning it out of
|
|
7
|
+
* flow means the browser's layout engine no longer reserves room for it automatically, so
|
|
8
|
+
* `.jini-message-list` has to reserve that space itself via `padding-bottom` — and until this hook,
|
|
9
|
+
* that reservation was a hardcoded guess (240px) that a live render had already outgrown once before
|
|
10
|
+
* (the comment records the prior incident: 170px measured against a 179.75px composer, clipping the
|
|
11
|
+
* last message's tail under the overlay).
|
|
12
|
+
*
|
|
13
|
+
* A hardcoded reservation can only ever be as good as the day someone last measured the composer —
|
|
14
|
+
* an attachment tray, a wrapped multi-line draft, or a taller runtime picker popover each grow
|
|
15
|
+
* `.jini-chat-pane__controls` independently of anything this package's CSS author can predict. This
|
|
16
|
+
* hook removes the guessing: it measures the controls' real rendered height live via
|
|
17
|
+
* `ResizeObserver` and publishes it as a CSS custom property on a shared ancestor, which
|
|
18
|
+
* `.jini-message-list`'s `padding-bottom` reads via `calc(var(--jini-chat-controls-height, 240px) +
|
|
19
|
+
* …)` — the same 240px stays as the *fallback* for environments without `ResizeObserver` (SSR,
|
|
20
|
+
* `McpUiHost.test.tsx`-style environments without the polyfill), so nothing regresses where this
|
|
21
|
+
* hook can't run; live browsers get the exact number instead of a guess that can go stale.
|
|
22
|
+
*
|
|
23
|
+
* The measured value is written to `rootRef`, not `controlsRef` itself — CSS custom properties
|
|
24
|
+
* inherit to descendants only, and `.jini-message-list` is a SIBLING of `.jini-chat-pane__controls`
|
|
25
|
+
* (both children of `.jini-chat-pane__body`), not a descendant of it. The nearest ancestor common to
|
|
26
|
+
* both is the pane's own root `<section>`, so that is where the property has to live for
|
|
27
|
+
* `.jini-message-list` to read it at all.
|
|
28
|
+
*/
|
|
29
|
+
import { useEffect, useRef } from 'react';
|
|
30
|
+
export const CHAT_PANE_CONTROLS_HEIGHT_CSS_VAR = '--jini-chat-controls-height';
|
|
31
|
+
/**
|
|
32
|
+
* Keeps {@link CHAT_PANE_CONTROLS_HEIGHT_CSS_VAR} on the pane root in sync with the controls
|
|
33
|
+
* overlay's actual rendered height.
|
|
34
|
+
*
|
|
35
|
+
* @returns Two refs to attach — see {@link UseChatPaneControlsHeightResult}.
|
|
36
|
+
* @complexity O(1) per resize notification.
|
|
37
|
+
*/
|
|
38
|
+
export function useChatPaneControlsHeight() {
|
|
39
|
+
const rootRef = useRef(null);
|
|
40
|
+
const controlsRef = useRef(null);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const root = rootRef.current;
|
|
43
|
+
const controls = controlsRef.current;
|
|
44
|
+
if (!root || !controls || typeof ResizeObserver !== 'function')
|
|
45
|
+
return;
|
|
46
|
+
const observer = new ResizeObserver((entries) => {
|
|
47
|
+
const entry = entries[0];
|
|
48
|
+
if (!entry)
|
|
49
|
+
return;
|
|
50
|
+
// Rounded up: a fractional px short would let one glyph's descender clip against the
|
|
51
|
+
// gradient's opaque end, which `Math.ceil` never risks understating.
|
|
52
|
+
root.style.setProperty(CHAT_PANE_CONTROLS_HEIGHT_CSS_VAR, `${Math.ceil(entry.contentRect.height)}px`);
|
|
53
|
+
});
|
|
54
|
+
observer.observe(controls);
|
|
55
|
+
return () => observer.disconnect();
|
|
56
|
+
}, []);
|
|
57
|
+
return { rootRef, controlsRef };
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=useChatPaneControlsHeight.hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChatPaneControlsHeight.hooks.js","sourceRoot":"","sources":["../../../../../src/react/features/chat-pane/hooks/useChatPaneControlsHeight.hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE1C,MAAM,CAAC,MAAM,iCAAiC,GAAG,6BAA6B,CAAC;AAS/E;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,OAAO,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IAExD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QAC7B,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC;QACrC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,OAAO,cAAc,KAAK,UAAU;YAAE,OAAO;QACvE,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,CAAC,OAAO,EAAE,EAAE;YAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,qFAAqF;YACrF,qEAAqE;YACrE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,iCAAiC,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxG,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3B,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;AAClC,CAAC"}
|