@flanksource/clicky-ui 0.2.21 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/comments/CommentAuthor.cjs +58 -0
- package/dist/comments/CommentAuthor.cjs.map +1 -0
- package/dist/comments/CommentAuthor.d.ts +17 -0
- package/dist/comments/CommentAuthor.d.ts.map +1 -0
- package/dist/comments/CommentAuthor.js +58 -0
- package/dist/comments/CommentAuthor.js.map +1 -0
- package/dist/comments/CommentCard.cjs +343 -0
- package/dist/comments/CommentCard.cjs.map +1 -0
- package/dist/comments/CommentCard.d.ts +27 -0
- package/dist/comments/CommentCard.d.ts.map +1 -0
- package/dist/comments/CommentCard.js +343 -0
- package/dist/comments/CommentCard.js.map +1 -0
- package/dist/comments/CommentComposer.cjs +207 -0
- package/dist/comments/CommentComposer.cjs.map +1 -0
- package/dist/comments/CommentComposer.d.ts +23 -0
- package/dist/comments/CommentComposer.d.ts.map +1 -0
- package/dist/comments/CommentComposer.js +207 -0
- package/dist/comments/CommentComposer.js.map +1 -0
- package/dist/comments/CommentFilterBar.cjs +145 -0
- package/dist/comments/CommentFilterBar.cjs.map +1 -0
- package/dist/comments/CommentFilterBar.d.ts +15 -0
- package/dist/comments/CommentFilterBar.d.ts.map +1 -0
- package/dist/comments/CommentFilterBar.js +145 -0
- package/dist/comments/CommentFilterBar.js.map +1 -0
- package/dist/comments/CommentMarkdown.cjs +156 -0
- package/dist/comments/CommentMarkdown.cjs.map +1 -0
- package/dist/comments/CommentMarkdown.d.ts +13 -0
- package/dist/comments/CommentMarkdown.d.ts.map +1 -0
- package/dist/comments/CommentMarkdown.js +156 -0
- package/dist/comments/CommentMarkdown.js.map +1 -0
- package/dist/comments/CommentProgress.cjs +86 -0
- package/dist/comments/CommentProgress.cjs.map +1 -0
- package/dist/comments/CommentProgress.d.ts +16 -0
- package/dist/comments/CommentProgress.d.ts.map +1 -0
- package/dist/comments/CommentProgress.js +86 -0
- package/dist/comments/CommentProgress.js.map +1 -0
- package/dist/comments/CommentProvider.cjs +99 -0
- package/dist/comments/CommentProvider.cjs.map +1 -0
- package/dist/comments/CommentProvider.d.ts +19 -0
- package/dist/comments/CommentProvider.d.ts.map +1 -0
- package/dist/comments/CommentProvider.js +99 -0
- package/dist/comments/CommentProvider.js.map +1 -0
- package/dist/comments/CommentSidePanel.cjs +219 -0
- package/dist/comments/CommentSidePanel.cjs.map +1 -0
- package/dist/comments/CommentSidePanel.d.ts +16 -0
- package/dist/comments/CommentSidePanel.d.ts.map +1 -0
- package/dist/comments/CommentSidePanel.js +219 -0
- package/dist/comments/CommentSidePanel.js.map +1 -0
- package/dist/comments/CommentThread.cjs +57 -0
- package/dist/comments/CommentThread.cjs.map +1 -0
- package/dist/comments/CommentThread.d.ts +24 -0
- package/dist/comments/CommentThread.d.ts.map +1 -0
- package/dist/comments/CommentThread.js +57 -0
- package/dist/comments/CommentThread.js.map +1 -0
- package/dist/comments/CommentThreadList.cjs +124 -0
- package/dist/comments/CommentThreadList.cjs.map +1 -0
- package/dist/comments/CommentThreadList.d.ts +25 -0
- package/dist/comments/CommentThreadList.d.ts.map +1 -0
- package/dist/comments/CommentThreadList.js +124 -0
- package/dist/comments/CommentThreadList.js.map +1 -0
- package/dist/comments/GroupedComments.cjs +74 -0
- package/dist/comments/GroupedComments.cjs.map +1 -0
- package/dist/comments/GroupedComments.d.ts +18 -0
- package/dist/comments/GroupedComments.d.ts.map +1 -0
- package/dist/comments/GroupedComments.js +74 -0
- package/dist/comments/GroupedComments.js.map +1 -0
- package/dist/comments/MentionTextarea.cjs +253 -0
- package/dist/comments/MentionTextarea.cjs.map +1 -0
- package/dist/comments/MentionTextarea.d.ts +28 -0
- package/dist/comments/MentionTextarea.d.ts.map +1 -0
- package/dist/comments/MentionTextarea.js +253 -0
- package/dist/comments/MentionTextarea.js.map +1 -0
- package/dist/comments/comment-context.cjs +33 -0
- package/dist/comments/comment-context.cjs.map +1 -0
- package/dist/comments/comment-context.d.ts +32 -0
- package/dist/comments/comment-context.d.ts.map +1 -0
- package/dist/comments/comment-context.js +33 -0
- package/dist/comments/comment-context.js.map +1 -0
- package/dist/comments/comment-fixtures.d.ts +11 -0
- package/dist/comments/comment-fixtures.d.ts.map +1 -0
- package/dist/comments/comment-types.cjs +19 -0
- package/dist/comments/comment-types.cjs.map +1 -0
- package/dist/comments/comment-types.d.ts +170 -0
- package/dist/comments/comment-types.d.ts.map +1 -0
- package/dist/comments/comment-types.js +19 -0
- package/dist/comments/comment-types.js.map +1 -0
- package/dist/comments/comment-utils.cjs +216 -0
- package/dist/comments/comment-utils.cjs.map +1 -0
- package/dist/comments/comment-utils.d.ts +59 -0
- package/dist/comments/comment-utils.d.ts.map +1 -0
- package/dist/comments/comment-utils.js +216 -0
- package/dist/comments/comment-utils.js.map +1 -0
- package/dist/comments.cjs +57 -0
- package/dist/comments.cjs.map +1 -0
- package/dist/comments.d.ts +16 -0
- package/dist/comments.d.ts.map +1 -0
- package/dist/comments.js +57 -0
- package/dist/comments.js.map +1 -0
- package/dist/components/Combobox.cjs +5 -2
- package/dist/components/Combobox.cjs.map +1 -1
- package/dist/components/Combobox.d.ts.map +1 -1
- package/dist/components/Combobox.js +5 -2
- package/dist/components/Combobox.js.map +1 -1
- package/dist/components/FilterBar.cjs +293 -256
- package/dist/components/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +293 -256
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/JsonSchemaForm.cjs +22 -6
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.d.ts +1 -1
- package/dist/components/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm.js +25 -9
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/MultiSelect.cjs +29 -32
- package/dist/components/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect.d.ts.map +1 -1
- package/dist/components/MultiSelect.js +30 -33
- package/dist/components/MultiSelect.js.map +1 -1
- package/dist/components/NamespacePicker.cjs +52 -0
- package/dist/components/NamespacePicker.cjs.map +1 -0
- package/dist/components/NamespacePicker.d.ts +17 -0
- package/dist/components/NamespacePicker.d.ts.map +1 -0
- package/dist/components/NamespacePicker.js +52 -0
- package/dist/components/NamespacePicker.js.map +1 -0
- package/dist/components/TimeRange.cjs +29 -37
- package/dist/components/TimeRange.cjs.map +1 -1
- package/dist/components/TimeRange.d.ts.map +1 -1
- package/dist/components/TimeRange.js +30 -38
- package/dist/components/TimeRange.js.map +1 -1
- package/dist/components/TreePickerField.cjs +6 -3
- package/dist/components/TreePickerField.cjs.map +1 -1
- package/dist/components/TreePickerField.d.ts.map +1 -1
- package/dist/components/TreePickerField.js +6 -3
- package/dist/components/TreePickerField.js.map +1 -1
- package/dist/components/form-lookup-context.cjs +36 -0
- package/dist/components/form-lookup-context.cjs.map +1 -0
- package/dist/components/form-lookup-context.d.ts +9 -0
- package/dist/components/form-lookup-context.d.ts.map +1 -0
- package/dist/components/form-lookup-context.js +36 -0
- package/dist/components/form-lookup-context.js.map +1 -0
- package/dist/components/icon-menu-picker.cjs +9 -3
- package/dist/components/icon-menu-picker.cjs.map +1 -1
- package/dist/components/icon-menu-picker.d.ts.map +1 -1
- package/dist/components/icon-menu-picker.js +9 -3
- package/dist/components/icon-menu-picker.js.map +1 -1
- package/dist/components/json-schema-form-discriminator.cjs +67 -0
- package/dist/components/json-schema-form-discriminator.cjs.map +1 -0
- package/dist/components/json-schema-form-discriminator.d.ts +10 -0
- package/dist/components/json-schema-form-discriminator.d.ts.map +1 -0
- package/dist/components/json-schema-form-discriminator.js +67 -0
- package/dist/components/json-schema-form-discriminator.js.map +1 -0
- package/dist/components/json-schema-form-fields.cjs +146 -3
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts +22 -0
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +147 -4
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-grid.cjs +92 -0
- package/dist/components/json-schema-form-grid.cjs.map +1 -0
- package/dist/components/json-schema-form-grid.d.ts +9 -0
- package/dist/components/json-schema-form-grid.d.ts.map +1 -0
- package/dist/components/json-schema-form-grid.js +92 -0
- package/dist/components/json-schema-form-grid.js.map +1 -0
- package/dist/components/json-schema-form-refs.cjs +60 -0
- package/dist/components/json-schema-form-refs.cjs.map +1 -0
- package/dist/components/json-schema-form-refs.d.ts +3 -0
- package/dist/components/json-schema-form-refs.d.ts.map +1 -0
- package/dist/components/json-schema-form-refs.js +60 -0
- package/dist/components/json-schema-form-refs.js.map +1 -0
- package/dist/components/json-schema-form-render.cjs +34 -5
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +36 -7
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +29 -2
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
- package/dist/components/json-schema-form-resolve.js +29 -2
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components/json-schema-form-template-menu.cjs +83 -0
- package/dist/components/json-schema-form-template-menu.cjs.map +1 -0
- package/dist/components/json-schema-form-template-menu.d.ts +15 -0
- package/dist/components/json-schema-form-template-menu.d.ts.map +1 -0
- package/dist/components/json-schema-form-template-menu.js +83 -0
- package/dist/components/json-schema-form-template-menu.js.map +1 -0
- package/dist/components/json-schema-form-template.cjs +18 -0
- package/dist/components/json-schema-form-template.cjs.map +1 -0
- package/dist/components/json-schema-form-template.d.ts +13 -0
- package/dist/components/json-schema-form-template.d.ts.map +1 -0
- package/dist/components/json-schema-form-template.js +18 -0
- package/dist/components/json-schema-form-template.js.map +1 -0
- package/dist/components/json-schema-form-types.d.ts +41 -2
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-utils.cjs +8 -0
- package/dist/components/json-schema-form-utils.cjs.map +1 -1
- package/dist/components/json-schema-form-utils.d.ts +1 -0
- package/dist/components/json-schema-form-utils.d.ts.map +1 -1
- package/dist/components/json-schema-form-utils.js +8 -0
- package/dist/components/json-schema-form-utils.js.map +1 -1
- package/dist/components/workload-picker-utils.cjs.map +1 -1
- package/dist/components/workload-picker-utils.d.ts +11 -1
- package/dist/components/workload-picker-utils.d.ts.map +1 -1
- package/dist/components/workload-picker-utils.js.map +1 -1
- package/dist/components.cjs +10 -0
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +7 -2
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +10 -0
- package/dist/components.js.map +1 -1
- package/dist/data/Clicky.cjs +231 -69
- package/dist/data/Clicky.cjs.map +1 -1
- package/dist/data/Clicky.d.ts +7 -1
- package/dist/data/Clicky.d.ts.map +1 -1
- package/dist/data/Clicky.fixtures.d.ts +3 -1
- package/dist/data/Clicky.fixtures.d.ts.map +1 -1
- package/dist/data/Clicky.js +232 -70
- package/dist/data/Clicky.js.map +1 -1
- package/dist/data/DataTable.cjs +23 -17
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +7 -1
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.js +24 -18
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/ExecutionTree.cjs +68 -0
- package/dist/data/ExecutionTree.cjs.map +1 -0
- package/dist/data/ExecutionTree.d.ts +40 -0
- package/dist/data/ExecutionTree.d.ts.map +1 -0
- package/dist/data/ExecutionTree.js +68 -0
- package/dist/data/ExecutionTree.js.map +1 -0
- package/dist/data/Gauge.cjs +37 -4
- package/dist/data/Gauge.cjs.map +1 -1
- package/dist/data/Gauge.d.ts +6 -1
- package/dist/data/Gauge.d.ts.map +1 -1
- package/dist/data/Gauge.js +37 -4
- package/dist/data/Gauge.js.map +1 -1
- package/dist/data/GaugeHoverCard.cjs +35 -0
- package/dist/data/GaugeHoverCard.cjs.map +1 -0
- package/dist/data/GaugeHoverCard.d.ts +25 -0
- package/dist/data/GaugeHoverCard.d.ts.map +1 -0
- package/dist/data/GaugeHoverCard.js +35 -0
- package/dist/data/GaugeHoverCard.js.map +1 -0
- package/dist/data/MarkdownEditor.cjs +616 -0
- package/dist/data/MarkdownEditor.cjs.map +1 -0
- package/dist/data/MarkdownEditor.d.ts +61 -0
- package/dist/data/MarkdownEditor.d.ts.map +1 -0
- package/dist/data/MarkdownEditor.js +616 -0
- package/dist/data/MarkdownEditor.js.map +1 -0
- package/dist/data/MarkdownEditor.model.cjs +27 -0
- package/dist/data/MarkdownEditor.model.cjs.map +1 -0
- package/dist/data/MarkdownEditor.model.d.ts +38 -0
- package/dist/data/MarkdownEditor.model.d.ts.map +1 -0
- package/dist/data/MarkdownEditor.model.js +27 -0
- package/dist/data/MarkdownEditor.model.js.map +1 -0
- package/dist/data/ObjectGraph.cjs +44 -0
- package/dist/data/ObjectGraph.cjs.map +1 -0
- package/dist/data/ObjectGraph.d.ts +39 -0
- package/dist/data/ObjectGraph.d.ts.map +1 -0
- package/dist/data/ObjectGraph.js +44 -0
- package/dist/data/ObjectGraph.js.map +1 -0
- package/dist/data/SchemaViewer.cjs +152 -0
- package/dist/data/SchemaViewer.cjs.map +1 -0
- package/dist/data/SchemaViewer.d.ts +27 -0
- package/dist/data/SchemaViewer.d.ts.map +1 -0
- package/dist/data/SchemaViewer.js +152 -0
- package/dist/data/SchemaViewer.js.map +1 -0
- package/dist/data/TimeseriesCoreBars.cjs +169 -32
- package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts +42 -5
- package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.js +170 -33
- package/dist/data/TimeseriesCoreBars.js.map +1 -1
- package/dist/data/TimeseriesCoreBars.model.cjs +5 -5
- package/dist/data/TimeseriesCoreBars.model.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.model.d.ts +4 -4
- package/dist/data/TimeseriesCoreBars.model.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.model.js +5 -5
- package/dist/data/TimeseriesCoreBars.model.js.map +1 -1
- package/dist/data/TimeseriesGauge.cjs +132 -36
- package/dist/data/TimeseriesGauge.cjs.map +1 -1
- package/dist/data/TimeseriesGauge.d.ts +15 -1
- package/dist/data/TimeseriesGauge.d.ts.map +1 -1
- package/dist/data/TimeseriesGauge.js +133 -37
- package/dist/data/TimeseriesGauge.js.map +1 -1
- package/dist/data/WorkloadCard.cjs +371 -0
- package/dist/data/WorkloadCard.cjs.map +1 -0
- package/dist/data/WorkloadCard.d.ts +25 -0
- package/dist/data/WorkloadCard.d.ts.map +1 -0
- package/dist/data/WorkloadCard.js +371 -0
- package/dist/data/WorkloadCard.js.map +1 -0
- package/dist/data/WorkloadCard.model.cjs +51 -0
- package/dist/data/WorkloadCard.model.cjs.map +1 -0
- package/dist/data/WorkloadCard.model.d.ts +53 -0
- package/dist/data/WorkloadCard.model.d.ts.map +1 -0
- package/dist/data/WorkloadCard.model.js +51 -0
- package/dist/data/WorkloadCard.model.js.map +1 -0
- package/dist/data/ai/ChatFab.cjs +3 -1
- package/dist/data/ai/ChatFab.cjs.map +1 -1
- package/dist/data/ai/ChatFab.d.ts.map +1 -1
- package/dist/data/ai/ChatFab.js +3 -1
- package/dist/data/ai/ChatFab.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +19 -9
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts +4 -2
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.js +19 -9
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/ChatWindowRequestBody.cjs +20 -0
- package/dist/data/ai/ChatWindowRequestBody.cjs.map +1 -0
- package/dist/data/ai/ChatWindowRequestBody.d.ts +9 -0
- package/dist/data/ai/ChatWindowRequestBody.d.ts.map +1 -0
- package/dist/data/ai/ChatWindowRequestBody.js +20 -0
- package/dist/data/ai/ChatWindowRequestBody.js.map +1 -0
- package/dist/data/ai/chat-window-context.cjs +2 -1
- package/dist/data/ai/chat-window-context.cjs.map +1 -1
- package/dist/data/ai/chat-window-context.d.ts +1 -1
- package/dist/data/ai/chat-window-context.d.ts.map +1 -1
- package/dist/data/ai/chat-window-context.js +2 -1
- package/dist/data/ai/chat-window-context.js.map +1 -1
- package/dist/data/ai/context.cjs.map +1 -1
- package/dist/data/ai/context.d.ts +3 -0
- package/dist/data/ai/context.d.ts.map +1 -1
- package/dist/data/ai/context.js.map +1 -1
- package/dist/data/chat/Chat.cjs +21 -1
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.d.ts +11 -2
- package/dist/data/chat/Chat.d.ts.map +1 -1
- package/dist/data/chat/Chat.js +22 -2
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/Message.cjs +13 -4
- package/dist/data/chat/Message.cjs.map +1 -1
- package/dist/data/chat/Message.d.ts +4 -2
- package/dist/data/chat/Message.d.ts.map +1 -1
- package/dist/data/chat/Message.js +13 -4
- package/dist/data/chat/Message.js.map +1 -1
- package/dist/data/chat/ToolCall.cjs +9 -4
- package/dist/data/chat/ToolCall.cjs.map +1 -1
- package/dist/data/chat/ToolCall.d.ts +3 -2
- package/dist/data/chat/ToolCall.d.ts.map +1 -1
- package/dist/data/chat/ToolCall.js +9 -4
- package/dist/data/chat/ToolCall.js.map +1 -1
- package/dist/data/chat/index.d.ts +1 -1
- package/dist/data/chat/index.d.ts.map +1 -1
- package/dist/data/chat/types.cjs.map +1 -1
- package/dist/data/chat/types.d.ts +7 -0
- package/dist/data/chat/types.d.ts.map +1 -1
- package/dist/data/chat/types.js.map +1 -1
- package/dist/data/gauge-stats.cjs +19 -0
- package/dist/data/gauge-stats.cjs.map +1 -0
- package/dist/data/gauge-stats.d.ts +15 -0
- package/dist/data/gauge-stats.d.ts.map +1 -0
- package/dist/data/gauge-stats.js +19 -0
- package/dist/data/gauge-stats.js.map +1 -0
- package/dist/data/schema-viewer-model.cjs +436 -0
- package/dist/data/schema-viewer-model.cjs.map +1 -0
- package/dist/data/schema-viewer-model.d.ts +64 -0
- package/dist/data/schema-viewer-model.d.ts.map +1 -0
- package/dist/data/schema-viewer-model.js +436 -0
- package/dist/data/schema-viewer-model.js.map +1 -0
- package/dist/data/version-info.cjs +2 -2
- package/dist/data/version-info.js +2 -2
- package/dist/data.cjs +30 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +14 -4
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +31 -1
- package/dist/data.js.map +1 -1
- package/dist/hooks/use-sort.cjs +19 -10
- package/dist/hooks/use-sort.cjs.map +1 -1
- package/dist/hooks/use-sort.d.ts +3 -0
- package/dist/hooks/use-sort.d.ts.map +1 -1
- package/dist/hooks/use-sort.js +19 -10
- package/dist/hooks/use-sort.js.map +1 -1
- package/dist/index.cjs +98 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -2
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.cjs +6 -10
- package/dist/layout/AppShell.cjs.map +1 -1
- package/dist/layout/AppShell.d.ts +2 -0
- package/dist/layout/AppShell.d.ts.map +1 -1
- package/dist/layout/AppShell.js +6 -10
- package/dist/layout/AppShell.js.map +1 -1
- package/dist/overlay/DropdownMenu.cjs +50 -38
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.d.ts +5 -1
- package/dist/overlay/DropdownMenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenu.js +50 -38
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/overlay/HoverCard.cjs +7 -2
- package/dist/overlay/HoverCard.cjs.map +1 -1
- package/dist/overlay/HoverCard.d.ts.map +1 -1
- package/dist/overlay/HoverCard.js +7 -2
- package/dist/overlay/HoverCard.js.map +1 -1
- package/dist/overlay/Modal.cjs +20 -17
- package/dist/overlay/Modal.cjs.map +1 -1
- package/dist/overlay/Modal.d.ts.map +1 -1
- package/dist/overlay/Modal.js +21 -18
- package/dist/overlay/Modal.js.map +1 -1
- package/dist/overlay/Toast.cjs +9 -1
- package/dist/overlay/Toast.cjs.map +1 -1
- package/dist/overlay/Toast.d.ts.map +1 -1
- package/dist/overlay/Toast.js +9 -1
- package/dist/overlay/Toast.js.map +1 -1
- package/dist/overlay/modalStack.cjs +53 -1
- package/dist/overlay/modalStack.cjs.map +1 -1
- package/dist/overlay/modalStack.d.ts +12 -0
- package/dist/overlay/modalStack.d.ts.map +1 -1
- package/dist/overlay/modalStack.js +54 -2
- package/dist/overlay/modalStack.js.map +1 -1
- package/dist/overlay/zIndex.cjs +20 -0
- package/dist/overlay/zIndex.cjs.map +1 -0
- package/dist/overlay/zIndex.d.ts +39 -0
- package/dist/overlay/zIndex.d.ts.map +1 -0
- package/dist/overlay/zIndex.js +20 -0
- package/dist/overlay/zIndex.js.map +1 -0
- package/dist/rpc/EntityExplorerApp.cjs +102 -143
- package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
- package/dist/rpc/EntityExplorerApp.d.ts +34 -1
- package/dist/rpc/EntityExplorerApp.d.ts.map +1 -1
- package/dist/rpc/EntityExplorerApp.js +105 -146
- package/dist/rpc/EntityExplorerApp.js.map +1 -1
- package/dist/rpc/OperationActionBar.cjs +135 -0
- package/dist/rpc/OperationActionBar.cjs.map +1 -0
- package/dist/rpc/OperationActionBar.d.ts +20 -0
- package/dist/rpc/OperationActionBar.d.ts.map +1 -0
- package/dist/rpc/OperationActionBar.js +135 -0
- package/dist/rpc/OperationActionBar.js.map +1 -0
- package/dist/rpc/OperationCatalog.cjs +79 -116
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts +8 -1
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +80 -117
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/OperationCommandPage.cjs +134 -223
- package/dist/rpc/OperationCommandPage.cjs.map +1 -1
- package/dist/rpc/OperationCommandPage.d.ts +1 -1
- package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
- package/dist/rpc/OperationCommandPage.js +135 -224
- package/dist/rpc/OperationCommandPage.js.map +1 -1
- package/dist/rpc/OperationEntityPage.cjs +49 -100
- package/dist/rpc/OperationEntityPage.cjs.map +1 -1
- package/dist/rpc/OperationEntityPage.d.ts +6 -1
- package/dist/rpc/OperationEntityPage.d.ts.map +1 -1
- package/dist/rpc/OperationEntityPage.js +50 -101
- package/dist/rpc/OperationEntityPage.js.map +1 -1
- package/dist/rpc/OperationResultView.cjs +43 -0
- package/dist/rpc/OperationResultView.cjs.map +1 -0
- package/dist/rpc/OperationResultView.d.ts +30 -0
- package/dist/rpc/OperationResultView.d.ts.map +1 -0
- package/dist/rpc/OperationResultView.js +43 -0
- package/dist/rpc/OperationResultView.js.map +1 -0
- package/dist/rpc/SchemaActionForm.cjs +102 -0
- package/dist/rpc/SchemaActionForm.cjs.map +1 -0
- package/dist/rpc/SchemaActionForm.d.ts +23 -0
- package/dist/rpc/SchemaActionForm.d.ts.map +1 -0
- package/dist/rpc/SchemaActionForm.js +102 -0
- package/dist/rpc/SchemaActionForm.js.map +1 -0
- package/dist/rpc/accept-options.cjs.map +1 -1
- package/dist/rpc/accept-options.d.ts +0 -1
- package/dist/rpc/accept-options.d.ts.map +1 -1
- package/dist/rpc/accept-options.js.map +1 -1
- package/dist/rpc/apiClient.cjs +34 -2
- package/dist/rpc/apiClient.cjs.map +1 -1
- package/dist/rpc/apiClient.d.ts +4 -1
- package/dist/rpc/apiClient.d.ts.map +1 -1
- package/dist/rpc/apiClient.js +34 -2
- package/dist/rpc/apiClient.js.map +1 -1
- package/dist/rpc/clickyMetadata.cjs +4 -4
- package/dist/rpc/clickyMetadata.cjs.map +1 -1
- package/dist/rpc/clickyMetadata.d.ts +0 -1
- package/dist/rpc/clickyMetadata.d.ts.map +1 -1
- package/dist/rpc/clickyMetadata.js +4 -4
- package/dist/rpc/clickyMetadata.js.map +1 -1
- package/dist/rpc/formMetadata.cjs +1 -0
- package/dist/rpc/formMetadata.cjs.map +1 -1
- package/dist/rpc/formMetadata.d.ts +6 -1
- package/dist/rpc/formMetadata.d.ts.map +1 -1
- package/dist/rpc/formMetadata.js +1 -0
- package/dist/rpc/formMetadata.js.map +1 -1
- package/dist/rpc/rowNavigation.cjs +86 -0
- package/dist/rpc/rowNavigation.cjs.map +1 -0
- package/dist/rpc/rowNavigation.d.ts +14 -0
- package/dist/rpc/rowNavigation.d.ts.map +1 -0
- package/dist/rpc/rowNavigation.js +86 -0
- package/dist/rpc/rowNavigation.js.map +1 -0
- package/dist/rpc/schemaActionPath.cjs +22 -0
- package/dist/rpc/schemaActionPath.cjs.map +1 -0
- package/dist/rpc/schemaActionPath.d.ts +4 -0
- package/dist/rpc/schemaActionPath.d.ts.map +1 -0
- package/dist/rpc/schemaActionPath.js +22 -0
- package/dist/rpc/schemaActionPath.js.map +1 -0
- package/dist/rpc/surfaceIconMap.cjs +35 -0
- package/dist/rpc/surfaceIconMap.cjs.map +1 -0
- package/dist/rpc/surfaceIconMap.d.ts +3 -0
- package/dist/rpc/surfaceIconMap.d.ts.map +1 -0
- package/dist/rpc/surfaceIconMap.js +35 -0
- package/dist/rpc/surfaceIconMap.js.map +1 -0
- package/dist/rpc/types.cjs.map +1 -1
- package/dist/rpc/types.d.ts +2 -0
- package/dist/rpc/types.d.ts.map +1 -1
- package/dist/rpc/types.js.map +1 -1
- package/dist/rpc/useOperations.cjs.map +1 -1
- package/dist/rpc/useOperations.d.ts +4 -1
- package/dist/rpc/useOperations.d.ts.map +1 -1
- package/dist/rpc/useOperations.js.map +1 -1
- package/dist/rpc.cjs +4 -2
- package/dist/rpc.cjs.map +1 -1
- package/dist/rpc.d.ts +7 -6
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +4 -2
- package/dist/rpc.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +6 -1
- package/dist/rpc/AcceptPicker.cjs +0 -135
- package/dist/rpc/AcceptPicker.cjs.map +0 -1
- package/dist/rpc/AcceptPicker.d.ts +0 -12
- package/dist/rpc/AcceptPicker.d.ts.map +0 -1
- package/dist/rpc/AcceptPicker.js +0 -135
- package/dist/rpc/AcceptPicker.js.map +0 -1
package/dist/data/ai/ChatFab.js
CHANGED
|
@@ -2,6 +2,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { cn } from "../../lib/utils.js";
|
|
3
3
|
import { Icon } from "../Icon.js";
|
|
4
4
|
import { useChatWindowManager } from "./chat-window-context.js";
|
|
5
|
+
import { zIndex } from "../../overlay/zIndex.js";
|
|
5
6
|
import { UiComment } from "../../icons/components/UiComment.js";
|
|
6
7
|
function ChatFab({ icon = UiComment, label = "Open chat", className }) {
|
|
7
8
|
const { panels, openPanel } = useChatWindowManager();
|
|
@@ -14,8 +15,9 @@ function ChatFab({ icon = UiComment, label = "Open chat", className }) {
|
|
|
14
15
|
title: label,
|
|
15
16
|
"aria-label": label,
|
|
16
17
|
onClick: () => openPanel(),
|
|
18
|
+
style: { zIndex: zIndex.chatFab },
|
|
17
19
|
className: cn(
|
|
18
|
-
"fixed bottom-4 right-4
|
|
20
|
+
"fixed bottom-4 right-4 flex h-12 w-12 items-center justify-center",
|
|
19
21
|
"rounded-full bg-primary text-primary-foreground shadow-lg transition-colors hover:bg-primary/90",
|
|
20
22
|
className
|
|
21
23
|
),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatFab.js","sources":["../../../src/data/ai/ChatFab.tsx"],"sourcesContent":["import { cn } from \"../../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"../Icon\";\nimport { UiComment } from \"../../icons\";\nimport { useChatWindowManager } from \"./chat-window-context\";\n\nexport type ChatFabProps = {\n /** Iconify name or imported icon component shown in the button. */\n icon?: string | StaticIconComponent;\n /** Accessible label / tooltip. */\n label?: string;\n className?: string;\n};\n\n/** A fixed bottom-right launch button that opens the first chat window. It\n * hides itself once any window is open (the windows carry their own controls). */\nexport function ChatFab({ icon = UiComment, label = \"Open chat\", className }: ChatFabProps) {\n const { panels, openPanel } = useChatWindowManager();\n if (panels.length > 0) return null;\n\n return (\n <button\n type=\"button\"\n data-testid=\"chat-fab\"\n title={label}\n aria-label={label}\n onClick={() => openPanel()}\n className={cn(\n \"fixed bottom-4 right-4
|
|
1
|
+
{"version":3,"file":"ChatFab.js","sources":["../../../src/data/ai/ChatFab.tsx"],"sourcesContent":["import { cn } from \"../../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"../Icon\";\nimport { UiComment } from \"../../icons\";\nimport { useChatWindowManager } from \"./chat-window-context\";\nimport { zIndex } from \"../../overlay/zIndex\";\n\nexport type ChatFabProps = {\n /** Iconify name or imported icon component shown in the button. */\n icon?: string | StaticIconComponent;\n /** Accessible label / tooltip. */\n label?: string;\n className?: string;\n};\n\n/** A fixed bottom-right launch button that opens the first chat window. It\n * hides itself once any window is open (the windows carry their own controls). */\nexport function ChatFab({ icon = UiComment, label = \"Open chat\", className }: ChatFabProps) {\n const { panels, openPanel } = useChatWindowManager();\n if (panels.length > 0) return null;\n\n return (\n <button\n type=\"button\"\n data-testid=\"chat-fab\"\n title={label}\n aria-label={label}\n onClick={() => openPanel()}\n style={{ zIndex: zIndex.chatFab }}\n className={cn(\n \"fixed bottom-4 right-4 flex h-12 w-12 items-center justify-center\",\n \"rounded-full bg-primary text-primary-foreground shadow-lg transition-colors hover:bg-primary/90\",\n className,\n )}\n >\n <Icon {...(typeof icon === \"string\" ? { name: icon } : { icon })} className=\"size-5\" />\n </button>\n );\n}\n"],"names":[],"mappings":";;;;;;AAgBO,SAAS,QAAQ,EAAE,OAAO,WAAW,QAAQ,aAAa,aAA2B;AAC1F,QAAM,EAAE,QAAQ,UAAA,IAAc,qBAAA;AAC9B,MAAI,OAAO,SAAS,EAAG,QAAO;AAE9B,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,eAAY;AAAA,MACZ,OAAO;AAAA,MACP,cAAY;AAAA,MACZ,SAAS,MAAM,UAAA;AAAA,MACf,OAAO,EAAE,QAAQ,OAAO,QAAA;AAAA,MACxB,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAGF,UAAA,oBAAC,MAAA,EAAM,GAAI,OAAO,SAAS,WAAW,EAAE,MAAM,KAAA,IAAS,EAAE,KAAA,GAAS,WAAU,SAAA,CAAS;AAAA,IAAA;AAAA,EAAA;AAG3F;"}
|
|
@@ -32,7 +32,7 @@ const chatWindowContext = require("./chat-window-context.cjs");
|
|
|
32
32
|
const ThreadPicker = require("./ThreadPicker.cjs");
|
|
33
33
|
const ContextBadges = require("./ContextBadges.cjs");
|
|
34
34
|
const ToolPreferences = require("./ToolPreferences.cjs");
|
|
35
|
-
const
|
|
35
|
+
const ChatWindowRequestBody = require("./ChatWindowRequestBody.cjs");
|
|
36
36
|
const UiAdd = require("../../icons/components/UiAdd.cjs");
|
|
37
37
|
const UiFullscreen = require("../../icons/components/UiFullscreen.cjs");
|
|
38
38
|
const UiClose = require("../../icons/components/UiClose.cjs");
|
|
@@ -52,6 +52,7 @@ function ChatWindow({
|
|
|
52
52
|
threadsSource,
|
|
53
53
|
contextTypeConfig,
|
|
54
54
|
tools,
|
|
55
|
+
defaultToolMode = "ask",
|
|
55
56
|
headerExtras
|
|
56
57
|
}) {
|
|
57
58
|
const { updatePanel, closePanel, bringToFront, maximizePanel, openPanel } = chatWindowContext.useChatWindowManager();
|
|
@@ -64,13 +65,13 @@ function ChatWindow({
|
|
|
64
65
|
let changed = false;
|
|
65
66
|
for (const t of tools) {
|
|
66
67
|
if (next[t.name] === void 0) {
|
|
67
|
-
next[t.name] =
|
|
68
|
+
next[t.name] = defaultToolMode;
|
|
68
69
|
changed = true;
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
return changed ? next : prev;
|
|
72
73
|
});
|
|
73
|
-
}, [tools]);
|
|
74
|
+
}, [defaultToolMode, tools]);
|
|
74
75
|
react.useEffect(() => {
|
|
75
76
|
let active = true;
|
|
76
77
|
import("react-rnd").then((m) => {
|
|
@@ -84,11 +85,18 @@ function ChatWindow({
|
|
|
84
85
|
(id) => updatePanel(panel.id, { contextItems: panel.contextItems.filter((c) => c.id !== id) }),
|
|
85
86
|
[updatePanel, panel.id, panel.contextItems]
|
|
86
87
|
);
|
|
87
|
-
const mergedBody = {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
const mergedBody = ChatWindowRequestBody.chatWindowRequestBody({
|
|
89
|
+
base: chat == null ? void 0 : chat.body,
|
|
90
|
+
contextItems: panel.contextItems,
|
|
91
|
+
tools,
|
|
92
|
+
toolPrefs
|
|
93
|
+
});
|
|
94
|
+
const initialPrompt = panel.initialPrompt ?? (chat == null ? void 0 : chat.initialPrompt) ?? null;
|
|
95
|
+
const handleInitialPromptSent = react.useCallback(() => {
|
|
96
|
+
var _a;
|
|
97
|
+
if (panel.initialPrompt) updatePanel(panel.id, { initialPrompt: null });
|
|
98
|
+
(_a = chat == null ? void 0 : chat.onInitialPromptSent) == null ? void 0 : _a.call(chat);
|
|
99
|
+
}, [chat, panel.id, panel.initialPrompt, updatePanel]);
|
|
92
100
|
const header = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "chat-drag-handle flex cursor-move items-center gap-1 border-b border-border bg-muted/40 px-2 py-1.5", children: [
|
|
93
101
|
threadsSource != null || threadsApi !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
94
102
|
ThreadPicker.ThreadPicker,
|
|
@@ -130,7 +138,9 @@ function ChatWindow({
|
|
|
130
138
|
{
|
|
131
139
|
...chat,
|
|
132
140
|
...panel.threadId ? { threadId: panel.threadId } : {},
|
|
133
|
-
body: mergedBody
|
|
141
|
+
body: mergedBody,
|
|
142
|
+
initialPrompt,
|
|
143
|
+
onInitialPromptSent: handleInitialPromptSent
|
|
134
144
|
}
|
|
135
145
|
) })
|
|
136
146
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatWindow.cjs","sources":["../../../src/data/ai/ChatWindow.tsx"],"sourcesContent":["import { useCallback, useEffect, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../../components/button\";\nimport { Icon } from \"../Icon\";\nimport { UiAdd, UiClose, UiFullscreen } from \"../../icons\";\nimport { Chat, type ChatProps } from \"../chat/Chat\";\nimport { useChatWindowManager, type ChatWindowState } from \"./chat-window-context\";\nimport { ThreadPicker, type ThreadSource } from \"./ThreadPicker\";\nimport { ContextBadges } from \"./ContextBadges\";\nimport { ToolPreferences, type ToolMeta, type ToolMode } from \"./ToolPreferences\";\nimport { serializeContext, type ContextTypeConfig } from \"./context\";\n\nexport type ChatWindowProps = {\n panel: ChatWindowState;\n /** Props forwarded to the inner <Chat>. The window manages `threadId` and\n * merges attached context / tool preferences into `body` on top of these. */\n chat?: Partial<ChatProps>;\n /** Header title shown when the thread picker is disabled. */\n title?: ReactNode;\n /** Thread switcher endpoint, or null to hide the picker. Defaults to\n * \"/api/chat/threads\". Ignored when `threadsSource` is set. */\n threadsApi?: string | null;\n /** Inject the thread list/delete directly instead of fetching `threadsApi`\n * (e.g. an app that loads conversations via its own client). Shows the\n * picker regardless of `threadsApi`. */\n threadsSource?: ThreadSource;\n /** Maps context item `type` to an icon/colour for the badge row. */\n contextTypeConfig?: ContextTypeConfig;\n /** When provided, a tool-preferences popover is shown and forwarded as\n * `body.toolPreferences`. Tools default to \"ask\" (approval required); the\n * user can switch any tool to Auto/Off from the popover. */\n tools?: ToolMeta[];\n /** Extra controls rendered in the header, e.g. a <ContextUsage/> gauge. */\n headerExtras?: ReactNode;\n};\n\nconst MAXIMIZE_CSS = `\n.chat-maximized .react-draggable {\n transform: none !important;\n width: auto !important;\n height: auto !important;\n inset: 0 !important;\n position: absolute !important;\n}`;\n\n/** A draggable, resizable floating chat window. It lazy-loads `react-rnd` (an\n * optional dependency, so consumers of just the inner <Chat> never pull it)\n * and renders the existing <Chat> beneath a drag-handle header with thread\n * switching, a context-badge row and optional tool preferences. */\nexport function ChatWindow({\n panel,\n chat,\n title = \"Assistant\",\n threadsApi = \"/api/chat/threads\",\n threadsSource,\n contextTypeConfig,\n tools,\n headerExtras,\n}: ChatWindowProps) {\n const { updatePanel, closePanel, bringToFront, maximizePanel, openPanel } = useChatWindowManager();\n const [Rnd, setRnd] = useState<typeof import(\"react-rnd\").Rnd | null>(null);\n const [toolPrefs, setToolPrefs] = useState<Record<string, ToolMode>>({});\n\n // Tools default to \"ask\" (human-in-the-loop approval) on chat windows. Seed\n // any tool the user hasn't configured yet; existing choices are preserved.\n // Handles tools that load asynchronously after mount.\n useEffect(() => {\n if (!tools?.length) return;\n setToolPrefs((prev) => {\n const next = { ...prev };\n let changed = false;\n for (const t of tools) {\n if (next[t.name] === undefined) {\n next[t.name] = \"ask\";\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [tools]);\n\n useEffect(() => {\n let active = true;\n import(\"react-rnd\").then((m) => {\n if (active) setRnd(() => m.Rnd);\n });\n return () => {\n active = false;\n };\n }, []);\n\n const removeContext = useCallback(\n (id: string) =>\n updatePanel(panel.id, { contextItems: panel.contextItems.filter((c) => c.id !== id) }),\n [updatePanel, panel.id, panel.contextItems],\n );\n\n const mergedBody: Record<string, unknown> = {\n ...chat?.body,\n ...(panel.contextItems.length ? { context: serializeContext(panel.contextItems) } : {}),\n ...(tools ? { toolPreferences: toolPrefs } : {}),\n };\n\n const header = (\n <div className=\"chat-drag-handle flex cursor-move items-center gap-1 border-b border-border bg-muted/40 px-2 py-1.5\">\n {threadsSource != null || threadsApi !== null ? (\n <ThreadPicker\n threadId={panel.threadId}\n onSelect={(tid) => updatePanel(panel.id, { threadId: tid })}\n onNew={() => updatePanel(panel.id, { threadId: null })}\n {...(threadsSource\n ? { source: threadsSource }\n : threadsApi !== null\n ? { api: threadsApi }\n : {})}\n />\n ) : (\n <span className=\"px-1 text-sm font-medium\">{title}</span>\n )}\n <div className=\"flex-1\" />\n {headerExtras}\n {tools && <ToolPreferences tools={tools} value={toolPrefs} onChange={setToolPrefs} />}\n <Button variant=\"ghost\" size=\"icon\" title=\"New window\" onClick={() => openPanel()}>\n <Icon icon={UiAdd} className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title={panel.maximized ? \"Restore\" : \"Maximize\"}\n onClick={() => maximizePanel(panel.id)}\n >\n <Icon icon={UiFullscreen} className=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon\" title=\"Close\" onClick={() => closePanel(panel.id)}>\n <Icon icon={UiClose} className=\"size-4\" />\n </Button>\n </div>\n );\n\n const frame = (\n <div className=\"flex h-full flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl\">\n {header}\n <ContextBadges\n items={panel.contextItems}\n onRemove={removeContext}\n {...(contextTypeConfig ? { typeConfig: contextTypeConfig } : {})}\n />\n <div className=\"min-h-0 flex-1\">\n <Chat\n {...chat}\n {...(panel.threadId ? { threadId: panel.threadId } : {})}\n body={mergedBody}\n />\n </div>\n </div>\n );\n\n const outerClass = cn(\n \"fixed pointer-events-none\",\n panel.maximized ? \"inset-4 chat-maximized\" : \"inset-0\",\n );\n\n // Until react-rnd loads (and as a graceful fallback if it never does) the\n // window is statically positioned — still usable, just not draggable.\n if (!Rnd) {\n return (\n <div className={outerClass} style={{ zIndex: panel.zIndex }}>\n <div\n className=\"pointer-events-auto h-full\"\n style={\n panel.maximized\n ? { position: \"relative\", width: \"100%\", height: \"100%\" }\n : { position: \"absolute\", left: panel.x, top: panel.y, width: panel.width, height: panel.height }\n }\n >\n {frame}\n </div>\n </div>\n );\n }\n\n return (\n <div className={outerClass} style={{ zIndex: panel.zIndex }}>\n <style>{MAXIMIZE_CSS}</style>\n <Rnd\n default={{ x: panel.x, y: panel.y, width: panel.width, height: panel.height }}\n style={{ pointerEvents: \"auto\" }}\n minWidth={360}\n minHeight={400}\n bounds=\"parent\"\n dragHandleClassName=\"chat-drag-handle\"\n disableDragging={panel.maximized}\n enableResizing={!panel.maximized}\n onDragStart={() => bringToFront(panel.id)}\n onDragStop={(_e, d) => updatePanel(panel.id, { x: d.x, y: d.y })}\n onResizeStop={(_e, _dir, ref, _delta, pos) =>\n updatePanel(panel.id, { width: ref.offsetWidth, height: ref.offsetHeight, x: pos.x, y: pos.y })\n }\n >\n {frame}\n </Rnd>\n </div>\n );\n}\n\n/** Renders every open window for the current {@link useChatWindowManager}.\n * Drop one of these near the root alongside a <ChatFab/>. */\nexport function ChatWindowLayer(props: Omit<ChatWindowProps, \"panel\">) {\n const { panels } = useChatWindowManager();\n return (\n <>\n {panels.map((panel) => (\n <ChatWindow key={panel.id} panel={panel} {...props} />\n ))}\n </>\n );\n}\n"],"names":["useChatWindowManager","useState","useEffect","useCallback","serializeContext","jsxs","jsx","ThreadPicker","ToolPreferences","Button","Icon","UiAdd","UiFullscreen","UiClose","ContextBadges","Chat","cn","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChatWindow.cjs","sources":["../../../src/data/ai/ChatWindow.tsx"],"sourcesContent":["import { useCallback, useEffect, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../../components/button\";\nimport { Icon } from \"../Icon\";\nimport { UiAdd, UiClose, UiFullscreen } from \"../../icons\";\nimport { Chat, type ChatProps } from \"../chat/Chat\";\nimport { useChatWindowManager, type ChatWindowState } from \"./chat-window-context\";\nimport { ThreadPicker, type ThreadSource } from \"./ThreadPicker\";\nimport { ContextBadges } from \"./ContextBadges\";\nimport { ToolPreferences, type ToolMeta, type ToolMode } from \"./ToolPreferences\";\nimport type { ContextTypeConfig } from \"./context\";\nimport { chatWindowRequestBody } from \"./ChatWindowRequestBody\";\n\nexport type ChatWindowProps = {\n panel: ChatWindowState;\n /** Props forwarded to the inner <Chat>. The window manages `threadId` and\n * merges attached context / tool preferences into `body` on top of these. */\n chat?: Partial<ChatProps>;\n /** Header title shown when the thread picker is disabled. */\n title?: ReactNode;\n /** Thread switcher endpoint, or null to hide the picker. Defaults to\n * \"/api/chat/threads\". Ignored when `threadsSource` is set. */\n threadsApi?: string | null;\n /** Inject the thread list/delete directly instead of fetching `threadsApi`\n * (e.g. an app that loads conversations via its own client). Shows the\n * picker regardless of `threadsApi`. */\n threadsSource?: ThreadSource;\n /** Maps context item `type` to an icon/colour for the badge row. */\n contextTypeConfig?: ContextTypeConfig;\n /** When provided, a tool-preferences popover is shown and forwarded as\n * `body.toolPreferences`. Tools default to \"ask\" (approval required); the\n * user can switch any tool to Auto/Off from the popover. */\n tools?: ToolMeta[];\n /** Initial mode assigned to tools when they first load. Defaults to \"ask\". */\n defaultToolMode?: ToolMode;\n /** Extra controls rendered in the header, e.g. a <ContextUsage/> gauge. */\n headerExtras?: ReactNode;\n};\n\nconst MAXIMIZE_CSS = `\n.chat-maximized .react-draggable {\n transform: none !important;\n width: auto !important;\n height: auto !important;\n inset: 0 !important;\n position: absolute !important;\n}`;\n\n/** A draggable, resizable floating chat window. It lazy-loads `react-rnd` (an\n * optional dependency, so consumers of just the inner <Chat> never pull it)\n * and renders the existing <Chat> beneath a drag-handle header with thread\n * switching, a context-badge row and optional tool preferences. */\nexport function ChatWindow({\n panel,\n chat,\n title = \"Assistant\",\n threadsApi = \"/api/chat/threads\",\n threadsSource,\n contextTypeConfig,\n tools,\n defaultToolMode = \"ask\",\n headerExtras,\n}: ChatWindowProps) {\n const { updatePanel, closePanel, bringToFront, maximizePanel, openPanel } = useChatWindowManager();\n const [Rnd, setRnd] = useState<typeof import(\"react-rnd\").Rnd | null>(null);\n const [toolPrefs, setToolPrefs] = useState<Record<string, ToolMode>>({});\n\n // Tools default to \"ask\" (human-in-the-loop approval) on chat windows. Seed\n // any tool the user hasn't configured yet; existing choices are preserved.\n // Handles tools that load asynchronously after mount.\n useEffect(() => {\n if (!tools?.length) return;\n setToolPrefs((prev) => {\n const next = { ...prev };\n let changed = false;\n for (const t of tools) {\n if (next[t.name] === undefined) {\n next[t.name] = defaultToolMode;\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [defaultToolMode, tools]);\n\n useEffect(() => {\n let active = true;\n import(\"react-rnd\").then((m) => {\n if (active) setRnd(() => m.Rnd);\n });\n return () => {\n active = false;\n };\n }, []);\n\n const removeContext = useCallback(\n (id: string) =>\n updatePanel(panel.id, { contextItems: panel.contextItems.filter((c) => c.id !== id) }),\n [updatePanel, panel.id, panel.contextItems],\n );\n\n const mergedBody = chatWindowRequestBody({\n base: chat?.body,\n contextItems: panel.contextItems,\n tools,\n toolPrefs,\n });\n\n const initialPrompt = panel.initialPrompt ?? chat?.initialPrompt ?? null;\n const handleInitialPromptSent = useCallback(() => {\n if (panel.initialPrompt) updatePanel(panel.id, { initialPrompt: null });\n chat?.onInitialPromptSent?.();\n }, [chat, panel.id, panel.initialPrompt, updatePanel]);\n\n const header = (\n <div className=\"chat-drag-handle flex cursor-move items-center gap-1 border-b border-border bg-muted/40 px-2 py-1.5\">\n {threadsSource != null || threadsApi !== null ? (\n <ThreadPicker\n threadId={panel.threadId}\n onSelect={(tid) => updatePanel(panel.id, { threadId: tid })}\n onNew={() => updatePanel(panel.id, { threadId: null })}\n {...(threadsSource\n ? { source: threadsSource }\n : threadsApi !== null\n ? { api: threadsApi }\n : {})}\n />\n ) : (\n <span className=\"px-1 text-sm font-medium\">{title}</span>\n )}\n <div className=\"flex-1\" />\n {headerExtras}\n {tools && <ToolPreferences tools={tools} value={toolPrefs} onChange={setToolPrefs} />}\n <Button variant=\"ghost\" size=\"icon\" title=\"New window\" onClick={() => openPanel()}>\n <Icon icon={UiAdd} className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title={panel.maximized ? \"Restore\" : \"Maximize\"}\n onClick={() => maximizePanel(panel.id)}\n >\n <Icon icon={UiFullscreen} className=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon\" title=\"Close\" onClick={() => closePanel(panel.id)}>\n <Icon icon={UiClose} className=\"size-4\" />\n </Button>\n </div>\n );\n\n const frame = (\n <div className=\"flex h-full flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl\">\n {header}\n <ContextBadges\n items={panel.contextItems}\n onRemove={removeContext}\n {...(contextTypeConfig ? { typeConfig: contextTypeConfig } : {})}\n />\n <div className=\"min-h-0 flex-1\">\n <Chat\n {...chat}\n {...(panel.threadId ? { threadId: panel.threadId } : {})}\n body={mergedBody}\n initialPrompt={initialPrompt}\n onInitialPromptSent={handleInitialPromptSent}\n />\n </div>\n </div>\n );\n\n const outerClass = cn(\n \"fixed pointer-events-none\",\n panel.maximized ? \"inset-4 chat-maximized\" : \"inset-0\",\n );\n\n // Until react-rnd loads (and as a graceful fallback if it never does) the\n // window is statically positioned — still usable, just not draggable.\n if (!Rnd) {\n return (\n <div className={outerClass} style={{ zIndex: panel.zIndex }}>\n <div\n className=\"pointer-events-auto h-full\"\n style={\n panel.maximized\n ? { position: \"relative\", width: \"100%\", height: \"100%\" }\n : { position: \"absolute\", left: panel.x, top: panel.y, width: panel.width, height: panel.height }\n }\n >\n {frame}\n </div>\n </div>\n );\n }\n\n return (\n <div className={outerClass} style={{ zIndex: panel.zIndex }}>\n <style>{MAXIMIZE_CSS}</style>\n <Rnd\n default={{ x: panel.x, y: panel.y, width: panel.width, height: panel.height }}\n style={{ pointerEvents: \"auto\" }}\n minWidth={360}\n minHeight={400}\n bounds=\"parent\"\n dragHandleClassName=\"chat-drag-handle\"\n disableDragging={panel.maximized}\n enableResizing={!panel.maximized}\n onDragStart={() => bringToFront(panel.id)}\n onDragStop={(_e, d) => updatePanel(panel.id, { x: d.x, y: d.y })}\n onResizeStop={(_e, _dir, ref, _delta, pos) =>\n updatePanel(panel.id, { width: ref.offsetWidth, height: ref.offsetHeight, x: pos.x, y: pos.y })\n }\n >\n {frame}\n </Rnd>\n </div>\n );\n}\n\n/** Renders every open window for the current {@link useChatWindowManager}.\n * Drop one of these near the root alongside a <ChatFab/>. */\nexport function ChatWindowLayer(props: Omit<ChatWindowProps, \"panel\">) {\n const { panels } = useChatWindowManager();\n return (\n <>\n {panels.map((panel) => (\n <ChatWindow key={panel.id} panel={panel} {...props} />\n ))}\n </>\n );\n}\n"],"names":["useChatWindowManager","useState","useEffect","useCallback","chatWindowRequestBody","jsxs","jsx","ThreadPicker","ToolPreferences","Button","Icon","UiAdd","UiFullscreen","UiClose","ContextBadges","Chat","cn","Fragment"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAad,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB;AACF,GAAoB;AAClB,QAAM,EAAE,aAAa,YAAY,cAAc,eAAe,UAAA,IAAcA,uCAAA;AAC5E,QAAM,CAAC,KAAK,MAAM,IAAIC,MAAAA,SAAgD,IAAI;AAC1E,QAAM,CAAC,WAAW,YAAY,IAAIA,MAAAA,SAAmC,CAAA,CAAE;AAKvEC,QAAAA,UAAU,MAAM;AACd,QAAI,EAAC,+BAAO,QAAQ;AACpB,iBAAa,CAAC,SAAS;AACrB,YAAM,OAAO,EAAE,GAAG,KAAA;AAClB,UAAI,UAAU;AACd,iBAAW,KAAK,OAAO;AACrB,YAAI,KAAK,EAAE,IAAI,MAAM,QAAW;AAC9B,eAAK,EAAE,IAAI,IAAI;AACf,oBAAU;AAAA,QACZ;AAAA,MACF;AACA,aAAO,UAAU,OAAO;AAAA,IAC1B,CAAC;AAAA,EACH,GAAG,CAAC,iBAAiB,KAAK,CAAC;AAE3BA,QAAAA,UAAU,MAAM;AACd,QAAI,SAAS;AACb,WAAO,WAAW,EAAE,KAAK,CAAC,MAAM;AAC9B,UAAI,OAAQ,QAAO,MAAM,EAAE,GAAG;AAAA,IAChC,CAAC;AACD,WAAO,MAAM;AACX,eAAS;AAAA,IACX;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,gBAAgBC,MAAAA;AAAAA,IACpB,CAAC,OACC,YAAY,MAAM,IAAI,EAAE,cAAc,MAAM,aAAa,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG;AAAA,IACvF,CAAC,aAAa,MAAM,IAAI,MAAM,YAAY;AAAA,EAAA;AAG5C,QAAM,aAAaC,sBAAAA,sBAAsB;AAAA,IACvC,MAAM,6BAAM;AAAA,IACZ,cAAc,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,EAAA,CACD;AAED,QAAM,gBAAgB,MAAM,kBAAiB,6BAAM,kBAAiB;AACpE,QAAM,0BAA0BD,MAAAA,YAAY,MAAM;;AAChD,QAAI,MAAM,cAAe,aAAY,MAAM,IAAI,EAAE,eAAe,MAAM;AACtE,uCAAM,wBAAN;AAAA,EACF,GAAG,CAAC,MAAM,MAAM,IAAI,MAAM,eAAe,WAAW,CAAC;AAErD,QAAM,SACJE,2BAAAA,KAAC,OAAA,EAAI,WAAU,uGACZ,UAAA;AAAA,IAAA,iBAAiB,QAAQ,eAAe,OACvCC,2BAAAA;AAAAA,MAACC,aAAAA;AAAAA,MAAA;AAAA,QACC,UAAU,MAAM;AAAA,QAChB,UAAU,CAAC,QAAQ,YAAY,MAAM,IAAI,EAAE,UAAU,KAAK;AAAA,QAC1D,OAAO,MAAM,YAAY,MAAM,IAAI,EAAE,UAAU,MAAM;AAAA,QACpD,GAAI,gBACD,EAAE,QAAQ,cAAA,IACV,eAAe,OACb,EAAE,KAAK,eACP,CAAA;AAAA,MAAC;AAAA,IAAA,IAGTD,2BAAAA,IAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,OAAM;AAAA,IAEpDA,2BAAAA,IAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,IACvB;AAAA,IACA,SAASA,2BAAAA,IAACE,gBAAAA,iBAAA,EAAgB,OAAc,OAAO,WAAW,UAAU,cAAc;AAAA,mCAClFC,OAAAA,QAAA,EAAO,SAAQ,SAAQ,MAAK,QAAO,OAAM,cAAa,SAAS,MAAM,UAAA,GACpE,UAAAH,+BAACI,KAAAA,MAAA,EAAK,MAAMC,MAAAA,OAAO,WAAU,UAAS,GACxC;AAAA,IACAL,2BAAAA;AAAAA,MAACG,OAAAA;AAAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,OAAO,MAAM,YAAY,YAAY;AAAA,QACrC,SAAS,MAAM,cAAc,MAAM,EAAE;AAAA,QAErC,UAAAH,2BAAAA,IAACI,WAAA,EAAK,MAAME,aAAAA,cAAc,WAAU,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAAA,IAE/CN,+BAACG,OAAAA,UAAO,SAAQ,SAAQ,MAAK,QAAO,OAAM,SAAQ,SAAS,MAAM,WAAW,MAAM,EAAE,GAClF,UAAAH,2BAAAA,IAACI,KAAAA,MAAA,EAAK,MAAMG,iBAAS,WAAU,UAAS,EAAA,CAC1C;AAAA,EAAA,GACF;AAGF,QAAM,QACJR,2BAAAA,KAAC,OAAA,EAAI,WAAU,gGACZ,UAAA;AAAA,IAAA;AAAA,IACDC,2BAAAA;AAAAA,MAACQ,cAAAA;AAAAA,MAAA;AAAA,QACC,OAAO,MAAM;AAAA,QACb,UAAU;AAAA,QACT,GAAI,oBAAoB,EAAE,YAAY,sBAAsB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,IAEhER,2BAAAA,IAAC,OAAA,EAAI,WAAU,kBACb,UAAAA,2BAAAA;AAAAA,MAACS,KAAAA;AAAAA,MAAA;AAAA,QACE,GAAG;AAAA,QACH,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAA,IAAa,CAAA;AAAA,QACrD,MAAM;AAAA,QACN;AAAA,QACA,qBAAqB;AAAA,MAAA;AAAA,IAAA,EACvB,CACF;AAAA,EAAA,GACF;AAGF,QAAM,aAAaC,MAAAA;AAAAA,IACjB;AAAA,IACA,MAAM,YAAY,2BAA2B;AAAA,EAAA;AAK/C,MAAI,CAAC,KAAK;AACR,WACEV,+BAAC,SAAI,WAAW,YAAY,OAAO,EAAE,QAAQ,MAAM,OAAA,GACjD,UAAAA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,OACE,MAAM,YACF,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,OAAA,IAC/C,EAAE,UAAU,YAAY,MAAM,MAAM,GAAG,KAAK,MAAM,GAAG,OAAO,MAAM,OAAO,QAAQ,MAAM,OAAA;AAAA,QAG5F,UAAA;AAAA,MAAA;AAAA,IAAA,GAEL;AAAA,EAEJ;AAEA,SACED,gCAAC,SAAI,WAAW,YAAY,OAAO,EAAE,QAAQ,MAAM,OAAA,GACjD,UAAA;AAAA,IAAAC,2BAAAA,IAAC,WAAO,UAAA,aAAA,CAAa;AAAA,IACrBA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAS,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,OAAO,MAAM,OAAO,QAAQ,MAAM,OAAA;AAAA,QACrE,OAAO,EAAE,eAAe,OAAA;AAAA,QACxB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,QAAO;AAAA,QACP,qBAAoB;AAAA,QACpB,iBAAiB,MAAM;AAAA,QACvB,gBAAgB,CAAC,MAAM;AAAA,QACvB,aAAa,MAAM,aAAa,MAAM,EAAE;AAAA,QACxC,YAAY,CAAC,IAAI,MAAM,YAAY,MAAM,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG;AAAA,QAC/D,cAAc,CAAC,IAAI,MAAM,KAAK,QAAQ,QACpC,YAAY,MAAM,IAAI,EAAE,OAAO,IAAI,aAAa,QAAQ,IAAI,cAAc,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG;AAAA,QAG/F,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ;AAIO,SAAS,gBAAgB,OAAuC;AACrE,QAAM,EAAE,OAAA,IAAWN,uCAAA;AACnB,SACEM,2BAAAA,IAAAW,WAAAA,UAAA,EACG,UAAA,OAAO,IAAI,CAAC,UACXX,2BAAAA,IAAC,YAAA,EAA0B,OAAe,GAAG,MAAA,GAA5B,MAAM,EAA6B,CACrD,GACH;AAEJ;;;"}
|
|
@@ -2,7 +2,7 @@ import { ReactNode } from 'react';
|
|
|
2
2
|
import { ChatProps } from '../chat/Chat';
|
|
3
3
|
import { ChatWindowState } from './chat-window-context';
|
|
4
4
|
import { ThreadSource } from './ThreadPicker';
|
|
5
|
-
import { ToolMeta } from './ToolPreferences';
|
|
5
|
+
import { ToolMeta, ToolMode } from './ToolPreferences';
|
|
6
6
|
import { ContextTypeConfig } from './context';
|
|
7
7
|
export type ChatWindowProps = {
|
|
8
8
|
panel: ChatWindowState;
|
|
@@ -24,6 +24,8 @@ export type ChatWindowProps = {
|
|
|
24
24
|
* `body.toolPreferences`. Tools default to "ask" (approval required); the
|
|
25
25
|
* user can switch any tool to Auto/Off from the popover. */
|
|
26
26
|
tools?: ToolMeta[];
|
|
27
|
+
/** Initial mode assigned to tools when they first load. Defaults to "ask". */
|
|
28
|
+
defaultToolMode?: ToolMode;
|
|
27
29
|
/** Extra controls rendered in the header, e.g. a <ContextUsage/> gauge. */
|
|
28
30
|
headerExtras?: ReactNode;
|
|
29
31
|
};
|
|
@@ -31,7 +33,7 @@ export type ChatWindowProps = {
|
|
|
31
33
|
* optional dependency, so consumers of just the inner <Chat> never pull it)
|
|
32
34
|
* and renders the existing <Chat> beneath a drag-handle header with thread
|
|
33
35
|
* switching, a context-badge row and optional tool preferences. */
|
|
34
|
-
export declare function ChatWindow({ panel, chat, title, threadsApi, threadsSource, contextTypeConfig, tools, headerExtras, }: ChatWindowProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
export declare function ChatWindow({ panel, chat, title, threadsApi, threadsSource, contextTypeConfig, tools, defaultToolMode, headerExtras, }: ChatWindowProps): import("react/jsx-runtime").JSX.Element;
|
|
35
37
|
/** Renders every open window for the current {@link useChatWindowManager}.
|
|
36
38
|
* Drop one of these near the root alongside a <ChatFab/>. */
|
|
37
39
|
export declare function ChatWindowLayer(props: Omit<ChatWindowProps, "panel">): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatWindow.d.ts","sourceRoot":"","sources":["../../../src/data/ai/ChatWindow.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKzE,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAmB,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"ChatWindow.d.ts","sourceRoot":"","sources":["../../../src/data/ai/ChatWindow.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKzE,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAmB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGnD,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,eAAe,CAAC;IACvB;kFAC8E;IAC9E,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC1B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;oEACgE;IAChE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;6CAEyC;IACzC,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,oEAAoE;IACpE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;iEAE6D;IAC7D,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,QAAQ,CAAC;IAC3B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,SAAS,CAAC;CAC1B,CAAC;AAWF;;;oEAGoE;AACpE,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,IAAI,EACJ,KAAmB,EACnB,UAAgC,EAChC,aAAa,EACb,iBAAiB,EACjB,KAAK,EACL,eAAuB,EACvB,YAAY,GACb,EAAE,eAAe,2CA0JjB;AAED;8DAC8D;AAC9D,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,2CASpE"}
|
|
@@ -8,7 +8,7 @@ import { useChatWindowManager } from "./chat-window-context.js";
|
|
|
8
8
|
import { ThreadPicker } from "./ThreadPicker.js";
|
|
9
9
|
import { ContextBadges } from "./ContextBadges.js";
|
|
10
10
|
import { ToolPreferences } from "./ToolPreferences.js";
|
|
11
|
-
import {
|
|
11
|
+
import { chatWindowRequestBody } from "./ChatWindowRequestBody.js";
|
|
12
12
|
import { UiAdd } from "../../icons/components/UiAdd.js";
|
|
13
13
|
import { UiFullscreen } from "../../icons/components/UiFullscreen.js";
|
|
14
14
|
import { UiClose } from "../../icons/components/UiClose.js";
|
|
@@ -28,6 +28,7 @@ function ChatWindow({
|
|
|
28
28
|
threadsSource,
|
|
29
29
|
contextTypeConfig,
|
|
30
30
|
tools,
|
|
31
|
+
defaultToolMode = "ask",
|
|
31
32
|
headerExtras
|
|
32
33
|
}) {
|
|
33
34
|
const { updatePanel, closePanel, bringToFront, maximizePanel, openPanel } = useChatWindowManager();
|
|
@@ -40,13 +41,13 @@ function ChatWindow({
|
|
|
40
41
|
let changed = false;
|
|
41
42
|
for (const t of tools) {
|
|
42
43
|
if (next[t.name] === void 0) {
|
|
43
|
-
next[t.name] =
|
|
44
|
+
next[t.name] = defaultToolMode;
|
|
44
45
|
changed = true;
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
return changed ? next : prev;
|
|
48
49
|
});
|
|
49
|
-
}, [tools]);
|
|
50
|
+
}, [defaultToolMode, tools]);
|
|
50
51
|
useEffect(() => {
|
|
51
52
|
let active = true;
|
|
52
53
|
import("react-rnd").then((m) => {
|
|
@@ -60,11 +61,18 @@ function ChatWindow({
|
|
|
60
61
|
(id) => updatePanel(panel.id, { contextItems: panel.contextItems.filter((c) => c.id !== id) }),
|
|
61
62
|
[updatePanel, panel.id, panel.contextItems]
|
|
62
63
|
);
|
|
63
|
-
const mergedBody = {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
const mergedBody = chatWindowRequestBody({
|
|
65
|
+
base: chat == null ? void 0 : chat.body,
|
|
66
|
+
contextItems: panel.contextItems,
|
|
67
|
+
tools,
|
|
68
|
+
toolPrefs
|
|
69
|
+
});
|
|
70
|
+
const initialPrompt = panel.initialPrompt ?? (chat == null ? void 0 : chat.initialPrompt) ?? null;
|
|
71
|
+
const handleInitialPromptSent = useCallback(() => {
|
|
72
|
+
var _a;
|
|
73
|
+
if (panel.initialPrompt) updatePanel(panel.id, { initialPrompt: null });
|
|
74
|
+
(_a = chat == null ? void 0 : chat.onInitialPromptSent) == null ? void 0 : _a.call(chat);
|
|
75
|
+
}, [chat, panel.id, panel.initialPrompt, updatePanel]);
|
|
68
76
|
const header = /* @__PURE__ */ jsxs("div", { className: "chat-drag-handle flex cursor-move items-center gap-1 border-b border-border bg-muted/40 px-2 py-1.5", children: [
|
|
69
77
|
threadsSource != null || threadsApi !== null ? /* @__PURE__ */ jsx(
|
|
70
78
|
ThreadPicker,
|
|
@@ -106,7 +114,9 @@ function ChatWindow({
|
|
|
106
114
|
{
|
|
107
115
|
...chat,
|
|
108
116
|
...panel.threadId ? { threadId: panel.threadId } : {},
|
|
109
|
-
body: mergedBody
|
|
117
|
+
body: mergedBody,
|
|
118
|
+
initialPrompt,
|
|
119
|
+
onInitialPromptSent: handleInitialPromptSent
|
|
110
120
|
}
|
|
111
121
|
) })
|
|
112
122
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatWindow.js","sources":["../../../src/data/ai/ChatWindow.tsx"],"sourcesContent":["import { useCallback, useEffect, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../../components/button\";\nimport { Icon } from \"../Icon\";\nimport { UiAdd, UiClose, UiFullscreen } from \"../../icons\";\nimport { Chat, type ChatProps } from \"../chat/Chat\";\nimport { useChatWindowManager, type ChatWindowState } from \"./chat-window-context\";\nimport { ThreadPicker, type ThreadSource } from \"./ThreadPicker\";\nimport { ContextBadges } from \"./ContextBadges\";\nimport { ToolPreferences, type ToolMeta, type ToolMode } from \"./ToolPreferences\";\nimport { serializeContext, type ContextTypeConfig } from \"./context\";\n\nexport type ChatWindowProps = {\n panel: ChatWindowState;\n /** Props forwarded to the inner <Chat>. The window manages `threadId` and\n * merges attached context / tool preferences into `body` on top of these. */\n chat?: Partial<ChatProps>;\n /** Header title shown when the thread picker is disabled. */\n title?: ReactNode;\n /** Thread switcher endpoint, or null to hide the picker. Defaults to\n * \"/api/chat/threads\". Ignored when `threadsSource` is set. */\n threadsApi?: string | null;\n /** Inject the thread list/delete directly instead of fetching `threadsApi`\n * (e.g. an app that loads conversations via its own client). Shows the\n * picker regardless of `threadsApi`. */\n threadsSource?: ThreadSource;\n /** Maps context item `type` to an icon/colour for the badge row. */\n contextTypeConfig?: ContextTypeConfig;\n /** When provided, a tool-preferences popover is shown and forwarded as\n * `body.toolPreferences`. Tools default to \"ask\" (approval required); the\n * user can switch any tool to Auto/Off from the popover. */\n tools?: ToolMeta[];\n /** Extra controls rendered in the header, e.g. a <ContextUsage/> gauge. */\n headerExtras?: ReactNode;\n};\n\nconst MAXIMIZE_CSS = `\n.chat-maximized .react-draggable {\n transform: none !important;\n width: auto !important;\n height: auto !important;\n inset: 0 !important;\n position: absolute !important;\n}`;\n\n/** A draggable, resizable floating chat window. It lazy-loads `react-rnd` (an\n * optional dependency, so consumers of just the inner <Chat> never pull it)\n * and renders the existing <Chat> beneath a drag-handle header with thread\n * switching, a context-badge row and optional tool preferences. */\nexport function ChatWindow({\n panel,\n chat,\n title = \"Assistant\",\n threadsApi = \"/api/chat/threads\",\n threadsSource,\n contextTypeConfig,\n tools,\n headerExtras,\n}: ChatWindowProps) {\n const { updatePanel, closePanel, bringToFront, maximizePanel, openPanel } = useChatWindowManager();\n const [Rnd, setRnd] = useState<typeof import(\"react-rnd\").Rnd | null>(null);\n const [toolPrefs, setToolPrefs] = useState<Record<string, ToolMode>>({});\n\n // Tools default to \"ask\" (human-in-the-loop approval) on chat windows. Seed\n // any tool the user hasn't configured yet; existing choices are preserved.\n // Handles tools that load asynchronously after mount.\n useEffect(() => {\n if (!tools?.length) return;\n setToolPrefs((prev) => {\n const next = { ...prev };\n let changed = false;\n for (const t of tools) {\n if (next[t.name] === undefined) {\n next[t.name] = \"ask\";\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [tools]);\n\n useEffect(() => {\n let active = true;\n import(\"react-rnd\").then((m) => {\n if (active) setRnd(() => m.Rnd);\n });\n return () => {\n active = false;\n };\n }, []);\n\n const removeContext = useCallback(\n (id: string) =>\n updatePanel(panel.id, { contextItems: panel.contextItems.filter((c) => c.id !== id) }),\n [updatePanel, panel.id, panel.contextItems],\n );\n\n const mergedBody: Record<string, unknown> = {\n ...chat?.body,\n ...(panel.contextItems.length ? { context: serializeContext(panel.contextItems) } : {}),\n ...(tools ? { toolPreferences: toolPrefs } : {}),\n };\n\n const header = (\n <div className=\"chat-drag-handle flex cursor-move items-center gap-1 border-b border-border bg-muted/40 px-2 py-1.5\">\n {threadsSource != null || threadsApi !== null ? (\n <ThreadPicker\n threadId={panel.threadId}\n onSelect={(tid) => updatePanel(panel.id, { threadId: tid })}\n onNew={() => updatePanel(panel.id, { threadId: null })}\n {...(threadsSource\n ? { source: threadsSource }\n : threadsApi !== null\n ? { api: threadsApi }\n : {})}\n />\n ) : (\n <span className=\"px-1 text-sm font-medium\">{title}</span>\n )}\n <div className=\"flex-1\" />\n {headerExtras}\n {tools && <ToolPreferences tools={tools} value={toolPrefs} onChange={setToolPrefs} />}\n <Button variant=\"ghost\" size=\"icon\" title=\"New window\" onClick={() => openPanel()}>\n <Icon icon={UiAdd} className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title={panel.maximized ? \"Restore\" : \"Maximize\"}\n onClick={() => maximizePanel(panel.id)}\n >\n <Icon icon={UiFullscreen} className=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon\" title=\"Close\" onClick={() => closePanel(panel.id)}>\n <Icon icon={UiClose} className=\"size-4\" />\n </Button>\n </div>\n );\n\n const frame = (\n <div className=\"flex h-full flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl\">\n {header}\n <ContextBadges\n items={panel.contextItems}\n onRemove={removeContext}\n {...(contextTypeConfig ? { typeConfig: contextTypeConfig } : {})}\n />\n <div className=\"min-h-0 flex-1\">\n <Chat\n {...chat}\n {...(panel.threadId ? { threadId: panel.threadId } : {})}\n body={mergedBody}\n />\n </div>\n </div>\n );\n\n const outerClass = cn(\n \"fixed pointer-events-none\",\n panel.maximized ? \"inset-4 chat-maximized\" : \"inset-0\",\n );\n\n // Until react-rnd loads (and as a graceful fallback if it never does) the\n // window is statically positioned — still usable, just not draggable.\n if (!Rnd) {\n return (\n <div className={outerClass} style={{ zIndex: panel.zIndex }}>\n <div\n className=\"pointer-events-auto h-full\"\n style={\n panel.maximized\n ? { position: \"relative\", width: \"100%\", height: \"100%\" }\n : { position: \"absolute\", left: panel.x, top: panel.y, width: panel.width, height: panel.height }\n }\n >\n {frame}\n </div>\n </div>\n );\n }\n\n return (\n <div className={outerClass} style={{ zIndex: panel.zIndex }}>\n <style>{MAXIMIZE_CSS}</style>\n <Rnd\n default={{ x: panel.x, y: panel.y, width: panel.width, height: panel.height }}\n style={{ pointerEvents: \"auto\" }}\n minWidth={360}\n minHeight={400}\n bounds=\"parent\"\n dragHandleClassName=\"chat-drag-handle\"\n disableDragging={panel.maximized}\n enableResizing={!panel.maximized}\n onDragStart={() => bringToFront(panel.id)}\n onDragStop={(_e, d) => updatePanel(panel.id, { x: d.x, y: d.y })}\n onResizeStop={(_e, _dir, ref, _delta, pos) =>\n updatePanel(panel.id, { width: ref.offsetWidth, height: ref.offsetHeight, x: pos.x, y: pos.y })\n }\n >\n {frame}\n </Rnd>\n </div>\n );\n}\n\n/** Renders every open window for the current {@link useChatWindowManager}.\n * Drop one of these near the root alongside a <ChatFab/>. */\nexport function ChatWindowLayer(props: Omit<ChatWindowProps, \"panel\">) {\n const { panels } = useChatWindowManager();\n return (\n <>\n {panels.map((panel) => (\n <ChatWindow key={panel.id} panel={panel} {...props} />\n ))}\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAoCA,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAad,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,EAAE,aAAa,YAAY,cAAc,eAAe,UAAA,IAAc,qBAAA;AAC5E,QAAM,CAAC,KAAK,MAAM,IAAI,SAAgD,IAAI;AAC1E,QAAM,CAAC,WAAW,YAAY,IAAI,SAAmC,CAAA,CAAE;AAKvE,YAAU,MAAM;AACd,QAAI,EAAC,+BAAO,QAAQ;AACpB,iBAAa,CAAC,SAAS;AACrB,YAAM,OAAO,EAAE,GAAG,KAAA;AAClB,UAAI,UAAU;AACd,iBAAW,KAAK,OAAO;AACrB,YAAI,KAAK,EAAE,IAAI,MAAM,QAAW;AAC9B,eAAK,EAAE,IAAI,IAAI;AACf,oBAAU;AAAA,QACZ;AAAA,MACF;AACA,aAAO,UAAU,OAAO;AAAA,IAC1B,CAAC;AAAA,EACH,GAAG,CAAC,KAAK,CAAC;AAEV,YAAU,MAAM;AACd,QAAI,SAAS;AACb,WAAO,WAAW,EAAE,KAAK,CAAC,MAAM;AAC9B,UAAI,OAAQ,QAAO,MAAM,EAAE,GAAG;AAAA,IAChC,CAAC;AACD,WAAO,MAAM;AACX,eAAS;AAAA,IACX;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,gBAAgB;AAAA,IACpB,CAAC,OACC,YAAY,MAAM,IAAI,EAAE,cAAc,MAAM,aAAa,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG;AAAA,IACvF,CAAC,aAAa,MAAM,IAAI,MAAM,YAAY;AAAA,EAAA;AAG5C,QAAM,aAAsC;AAAA,IAC1C,GAAG,6BAAM;AAAA,IACT,GAAI,MAAM,aAAa,SAAS,EAAE,SAAS,iBAAiB,MAAM,YAAY,EAAA,IAAM,CAAA;AAAA,IACpF,GAAI,QAAQ,EAAE,iBAAiB,cAAc,CAAA;AAAA,EAAC;AAGhD,QAAM,SACJ,qBAAC,OAAA,EAAI,WAAU,uGACZ,UAAA;AAAA,IAAA,iBAAiB,QAAQ,eAAe,OACvC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,UAAU,MAAM;AAAA,QAChB,UAAU,CAAC,QAAQ,YAAY,MAAM,IAAI,EAAE,UAAU,KAAK;AAAA,QAC1D,OAAO,MAAM,YAAY,MAAM,IAAI,EAAE,UAAU,MAAM;AAAA,QACpD,GAAI,gBACD,EAAE,QAAQ,cAAA,IACV,eAAe,OACb,EAAE,KAAK,eACP,CAAA;AAAA,MAAC;AAAA,IAAA,IAGT,oBAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,OAAM;AAAA,IAEpD,oBAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,IACvB;AAAA,IACA,SAAS,oBAAC,iBAAA,EAAgB,OAAc,OAAO,WAAW,UAAU,cAAc;AAAA,wBAClF,QAAA,EAAO,SAAQ,SAAQ,MAAK,QAAO,OAAM,cAAa,SAAS,MAAM,UAAA,GACpE,UAAA,oBAAC,MAAA,EAAK,MAAM,OAAO,WAAU,UAAS,GACxC;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,OAAO,MAAM,YAAY,YAAY;AAAA,QACrC,SAAS,MAAM,cAAc,MAAM,EAAE;AAAA,QAErC,UAAA,oBAAC,MAAA,EAAK,MAAM,cAAc,WAAU,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAAA,IAE/C,oBAAC,UAAO,SAAQ,SAAQ,MAAK,QAAO,OAAM,SAAQ,SAAS,MAAM,WAAW,MAAM,EAAE,GAClF,UAAA,oBAAC,MAAA,EAAK,MAAM,SAAS,WAAU,UAAS,EAAA,CAC1C;AAAA,EAAA,GACF;AAGF,QAAM,QACJ,qBAAC,OAAA,EAAI,WAAU,gGACZ,UAAA;AAAA,IAAA;AAAA,IACD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO,MAAM;AAAA,QACb,UAAU;AAAA,QACT,GAAI,oBAAoB,EAAE,YAAY,sBAAsB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,IAEhE,oBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACE,GAAG;AAAA,QACH,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAA,IAAa,CAAA;AAAA,QACrD,MAAM;AAAA,MAAA;AAAA,IAAA,EACR,CACF;AAAA,EAAA,GACF;AAGF,QAAM,aAAa;AAAA,IACjB;AAAA,IACA,MAAM,YAAY,2BAA2B;AAAA,EAAA;AAK/C,MAAI,CAAC,KAAK;AACR,WACE,oBAAC,SAAI,WAAW,YAAY,OAAO,EAAE,QAAQ,MAAM,OAAA,GACjD,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,OACE,MAAM,YACF,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,OAAA,IAC/C,EAAE,UAAU,YAAY,MAAM,MAAM,GAAG,KAAK,MAAM,GAAG,OAAO,MAAM,OAAO,QAAQ,MAAM,OAAA;AAAA,QAG5F,UAAA;AAAA,MAAA;AAAA,IAAA,GAEL;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAW,YAAY,OAAO,EAAE,QAAQ,MAAM,OAAA,GACjD,UAAA;AAAA,IAAA,oBAAC,WAAO,UAAA,aAAA,CAAa;AAAA,IACrB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAS,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,OAAO,MAAM,OAAO,QAAQ,MAAM,OAAA;AAAA,QACrE,OAAO,EAAE,eAAe,OAAA;AAAA,QACxB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,QAAO;AAAA,QACP,qBAAoB;AAAA,QACpB,iBAAiB,MAAM;AAAA,QACvB,gBAAgB,CAAC,MAAM;AAAA,QACvB,aAAa,MAAM,aAAa,MAAM,EAAE;AAAA,QACxC,YAAY,CAAC,IAAI,MAAM,YAAY,MAAM,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG;AAAA,QAC/D,cAAc,CAAC,IAAI,MAAM,KAAK,QAAQ,QACpC,YAAY,MAAM,IAAI,EAAE,OAAO,IAAI,aAAa,QAAQ,IAAI,cAAc,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG;AAAA,QAG/F,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ;AAIO,SAAS,gBAAgB,OAAuC;AACrE,QAAM,EAAE,OAAA,IAAW,qBAAA;AACnB,SACE,oBAAA,UAAA,EACG,UAAA,OAAO,IAAI,CAAC,UACX,oBAAC,YAAA,EAA0B,OAAe,GAAG,MAAA,GAA5B,MAAM,EAA6B,CACrD,GACH;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"ChatWindow.js","sources":["../../../src/data/ai/ChatWindow.tsx"],"sourcesContent":["import { useCallback, useEffect, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../../components/button\";\nimport { Icon } from \"../Icon\";\nimport { UiAdd, UiClose, UiFullscreen } from \"../../icons\";\nimport { Chat, type ChatProps } from \"../chat/Chat\";\nimport { useChatWindowManager, type ChatWindowState } from \"./chat-window-context\";\nimport { ThreadPicker, type ThreadSource } from \"./ThreadPicker\";\nimport { ContextBadges } from \"./ContextBadges\";\nimport { ToolPreferences, type ToolMeta, type ToolMode } from \"./ToolPreferences\";\nimport type { ContextTypeConfig } from \"./context\";\nimport { chatWindowRequestBody } from \"./ChatWindowRequestBody\";\n\nexport type ChatWindowProps = {\n panel: ChatWindowState;\n /** Props forwarded to the inner <Chat>. The window manages `threadId` and\n * merges attached context / tool preferences into `body` on top of these. */\n chat?: Partial<ChatProps>;\n /** Header title shown when the thread picker is disabled. */\n title?: ReactNode;\n /** Thread switcher endpoint, or null to hide the picker. Defaults to\n * \"/api/chat/threads\". Ignored when `threadsSource` is set. */\n threadsApi?: string | null;\n /** Inject the thread list/delete directly instead of fetching `threadsApi`\n * (e.g. an app that loads conversations via its own client). Shows the\n * picker regardless of `threadsApi`. */\n threadsSource?: ThreadSource;\n /** Maps context item `type` to an icon/colour for the badge row. */\n contextTypeConfig?: ContextTypeConfig;\n /** When provided, a tool-preferences popover is shown and forwarded as\n * `body.toolPreferences`. Tools default to \"ask\" (approval required); the\n * user can switch any tool to Auto/Off from the popover. */\n tools?: ToolMeta[];\n /** Initial mode assigned to tools when they first load. Defaults to \"ask\". */\n defaultToolMode?: ToolMode;\n /** Extra controls rendered in the header, e.g. a <ContextUsage/> gauge. */\n headerExtras?: ReactNode;\n};\n\nconst MAXIMIZE_CSS = `\n.chat-maximized .react-draggable {\n transform: none !important;\n width: auto !important;\n height: auto !important;\n inset: 0 !important;\n position: absolute !important;\n}`;\n\n/** A draggable, resizable floating chat window. It lazy-loads `react-rnd` (an\n * optional dependency, so consumers of just the inner <Chat> never pull it)\n * and renders the existing <Chat> beneath a drag-handle header with thread\n * switching, a context-badge row and optional tool preferences. */\nexport function ChatWindow({\n panel,\n chat,\n title = \"Assistant\",\n threadsApi = \"/api/chat/threads\",\n threadsSource,\n contextTypeConfig,\n tools,\n defaultToolMode = \"ask\",\n headerExtras,\n}: ChatWindowProps) {\n const { updatePanel, closePanel, bringToFront, maximizePanel, openPanel } = useChatWindowManager();\n const [Rnd, setRnd] = useState<typeof import(\"react-rnd\").Rnd | null>(null);\n const [toolPrefs, setToolPrefs] = useState<Record<string, ToolMode>>({});\n\n // Tools default to \"ask\" (human-in-the-loop approval) on chat windows. Seed\n // any tool the user hasn't configured yet; existing choices are preserved.\n // Handles tools that load asynchronously after mount.\n useEffect(() => {\n if (!tools?.length) return;\n setToolPrefs((prev) => {\n const next = { ...prev };\n let changed = false;\n for (const t of tools) {\n if (next[t.name] === undefined) {\n next[t.name] = defaultToolMode;\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n }, [defaultToolMode, tools]);\n\n useEffect(() => {\n let active = true;\n import(\"react-rnd\").then((m) => {\n if (active) setRnd(() => m.Rnd);\n });\n return () => {\n active = false;\n };\n }, []);\n\n const removeContext = useCallback(\n (id: string) =>\n updatePanel(panel.id, { contextItems: panel.contextItems.filter((c) => c.id !== id) }),\n [updatePanel, panel.id, panel.contextItems],\n );\n\n const mergedBody = chatWindowRequestBody({\n base: chat?.body,\n contextItems: panel.contextItems,\n tools,\n toolPrefs,\n });\n\n const initialPrompt = panel.initialPrompt ?? chat?.initialPrompt ?? null;\n const handleInitialPromptSent = useCallback(() => {\n if (panel.initialPrompt) updatePanel(panel.id, { initialPrompt: null });\n chat?.onInitialPromptSent?.();\n }, [chat, panel.id, panel.initialPrompt, updatePanel]);\n\n const header = (\n <div className=\"chat-drag-handle flex cursor-move items-center gap-1 border-b border-border bg-muted/40 px-2 py-1.5\">\n {threadsSource != null || threadsApi !== null ? (\n <ThreadPicker\n threadId={panel.threadId}\n onSelect={(tid) => updatePanel(panel.id, { threadId: tid })}\n onNew={() => updatePanel(panel.id, { threadId: null })}\n {...(threadsSource\n ? { source: threadsSource }\n : threadsApi !== null\n ? { api: threadsApi }\n : {})}\n />\n ) : (\n <span className=\"px-1 text-sm font-medium\">{title}</span>\n )}\n <div className=\"flex-1\" />\n {headerExtras}\n {tools && <ToolPreferences tools={tools} value={toolPrefs} onChange={setToolPrefs} />}\n <Button variant=\"ghost\" size=\"icon\" title=\"New window\" onClick={() => openPanel()}>\n <Icon icon={UiAdd} className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title={panel.maximized ? \"Restore\" : \"Maximize\"}\n onClick={() => maximizePanel(panel.id)}\n >\n <Icon icon={UiFullscreen} className=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon\" title=\"Close\" onClick={() => closePanel(panel.id)}>\n <Icon icon={UiClose} className=\"size-4\" />\n </Button>\n </div>\n );\n\n const frame = (\n <div className=\"flex h-full flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl\">\n {header}\n <ContextBadges\n items={panel.contextItems}\n onRemove={removeContext}\n {...(contextTypeConfig ? { typeConfig: contextTypeConfig } : {})}\n />\n <div className=\"min-h-0 flex-1\">\n <Chat\n {...chat}\n {...(panel.threadId ? { threadId: panel.threadId } : {})}\n body={mergedBody}\n initialPrompt={initialPrompt}\n onInitialPromptSent={handleInitialPromptSent}\n />\n </div>\n </div>\n );\n\n const outerClass = cn(\n \"fixed pointer-events-none\",\n panel.maximized ? \"inset-4 chat-maximized\" : \"inset-0\",\n );\n\n // Until react-rnd loads (and as a graceful fallback if it never does) the\n // window is statically positioned — still usable, just not draggable.\n if (!Rnd) {\n return (\n <div className={outerClass} style={{ zIndex: panel.zIndex }}>\n <div\n className=\"pointer-events-auto h-full\"\n style={\n panel.maximized\n ? { position: \"relative\", width: \"100%\", height: \"100%\" }\n : { position: \"absolute\", left: panel.x, top: panel.y, width: panel.width, height: panel.height }\n }\n >\n {frame}\n </div>\n </div>\n );\n }\n\n return (\n <div className={outerClass} style={{ zIndex: panel.zIndex }}>\n <style>{MAXIMIZE_CSS}</style>\n <Rnd\n default={{ x: panel.x, y: panel.y, width: panel.width, height: panel.height }}\n style={{ pointerEvents: \"auto\" }}\n minWidth={360}\n minHeight={400}\n bounds=\"parent\"\n dragHandleClassName=\"chat-drag-handle\"\n disableDragging={panel.maximized}\n enableResizing={!panel.maximized}\n onDragStart={() => bringToFront(panel.id)}\n onDragStop={(_e, d) => updatePanel(panel.id, { x: d.x, y: d.y })}\n onResizeStop={(_e, _dir, ref, _delta, pos) =>\n updatePanel(panel.id, { width: ref.offsetWidth, height: ref.offsetHeight, x: pos.x, y: pos.y })\n }\n >\n {frame}\n </Rnd>\n </div>\n );\n}\n\n/** Renders every open window for the current {@link useChatWindowManager}.\n * Drop one of these near the root alongside a <ChatFab/>. */\nexport function ChatWindowLayer(props: Omit<ChatWindowProps, \"panel\">) {\n const { panels } = useChatWindowManager();\n return (\n <>\n {panels.map((panel) => (\n <ChatWindow key={panel.id} panel={panel} {...props} />\n ))}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const context = require("./context.cjs");
|
|
4
|
+
function chatWindowRequestBody({
|
|
5
|
+
base,
|
|
6
|
+
contextItems,
|
|
7
|
+
tools,
|
|
8
|
+
toolPrefs
|
|
9
|
+
}) {
|
|
10
|
+
return {
|
|
11
|
+
...base,
|
|
12
|
+
...contextItems.length ? {
|
|
13
|
+
context: context.serializeContext(contextItems),
|
|
14
|
+
contextItems
|
|
15
|
+
} : {},
|
|
16
|
+
...tools ? { toolPreferences: toolPrefs ?? {} } : {}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
exports.chatWindowRequestBody = chatWindowRequestBody;
|
|
20
|
+
//# sourceMappingURL=ChatWindowRequestBody.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatWindowRequestBody.cjs","sources":["../../../src/data/ai/ChatWindowRequestBody.ts"],"sourcesContent":["import { serializeContext, type ChatContextItem } from \"./context\";\nimport type { ToolMeta, ToolMode } from \"./ToolPreferences\";\n\nexport function chatWindowRequestBody({\n base,\n contextItems,\n tools,\n toolPrefs,\n}: {\n base?: Record<string, unknown> | undefined;\n contextItems: ChatContextItem[];\n tools?: ToolMeta[] | undefined;\n toolPrefs?: Record<string, ToolMode> | undefined;\n}): Record<string, unknown> {\n return {\n ...base,\n ...(contextItems.length ? {\n context: serializeContext(contextItems),\n contextItems,\n } : {}),\n ...(tools ? { toolPreferences: toolPrefs ?? {} } : {}),\n };\n}\n"],"names":["serializeContext"],"mappings":";;;AAGO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAK4B;AAC1B,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,aAAa,SAAS;AAAA,MACxB,SAASA,QAAAA,iBAAiB,YAAY;AAAA,MACtC;AAAA,IAAA,IACE,CAAA;AAAA,IACJ,GAAI,QAAQ,EAAE,iBAAiB,aAAa,CAAA,EAAC,IAAM,CAAA;AAAA,EAAC;AAExD;;"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ChatContextItem } from './context';
|
|
2
|
+
import { ToolMeta, ToolMode } from './ToolPreferences';
|
|
3
|
+
export declare function chatWindowRequestBody({ base, contextItems, tools, toolPrefs, }: {
|
|
4
|
+
base?: Record<string, unknown> | undefined;
|
|
5
|
+
contextItems: ChatContextItem[];
|
|
6
|
+
tools?: ToolMeta[] | undefined;
|
|
7
|
+
toolPrefs?: Record<string, ToolMode> | undefined;
|
|
8
|
+
}): Record<string, unknown>;
|
|
9
|
+
//# sourceMappingURL=ChatWindowRequestBody.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatWindowRequestBody.d.ts","sourceRoot":"","sources":["../../../src/data/ai/ChatWindowRequestBody.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE5D,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,KAAK,EACL,SAAS,GACV,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC3C,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;CAClD,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAS1B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { serializeContext } from "./context.js";
|
|
2
|
+
function chatWindowRequestBody({
|
|
3
|
+
base,
|
|
4
|
+
contextItems,
|
|
5
|
+
tools,
|
|
6
|
+
toolPrefs
|
|
7
|
+
}) {
|
|
8
|
+
return {
|
|
9
|
+
...base,
|
|
10
|
+
...contextItems.length ? {
|
|
11
|
+
context: serializeContext(contextItems),
|
|
12
|
+
contextItems
|
|
13
|
+
} : {},
|
|
14
|
+
...tools ? { toolPreferences: toolPrefs ?? {} } : {}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
chatWindowRequestBody
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=ChatWindowRequestBody.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatWindowRequestBody.js","sources":["../../../src/data/ai/ChatWindowRequestBody.ts"],"sourcesContent":["import { serializeContext, type ChatContextItem } from \"./context\";\nimport type { ToolMeta, ToolMode } from \"./ToolPreferences\";\n\nexport function chatWindowRequestBody({\n base,\n contextItems,\n tools,\n toolPrefs,\n}: {\n base?: Record<string, unknown> | undefined;\n contextItems: ChatContextItem[];\n tools?: ToolMeta[] | undefined;\n toolPrefs?: Record<string, ToolMode> | undefined;\n}): Record<string, unknown> {\n return {\n ...base,\n ...(contextItems.length ? {\n context: serializeContext(contextItems),\n contextItems,\n } : {}),\n ...(tools ? { toolPreferences: toolPrefs ?? {} } : {}),\n };\n}\n"],"names":[],"mappings":";AAGO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAK4B;AAC1B,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,aAAa,SAAS;AAAA,MACxB,SAAS,iBAAiB,YAAY;AAAA,MACtC;AAAA,IAAA,IACE,CAAA;AAAA,IACJ,GAAI,QAAQ,EAAE,iBAAiB,aAAa,CAAA,EAAC,IAAM,CAAA;AAAA,EAAC;AAExD;"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const react = require("react");
|
|
4
|
+
const zIndex = require("../../overlay/zIndex.cjs");
|
|
4
5
|
const ChatWindowManagerContext = react.createContext(null);
|
|
5
6
|
function useChatWindowManager() {
|
|
6
7
|
const ctx = react.useContext(ChatWindowManagerContext);
|
|
@@ -11,7 +12,7 @@ const MAX_PANELS = 6;
|
|
|
11
12
|
const DEFAULT_WIDTH = 520;
|
|
12
13
|
const DEFAULT_HEIGHT = 700;
|
|
13
14
|
const CASCADE_OFFSET = 30;
|
|
14
|
-
const Z_BASE =
|
|
15
|
+
const Z_BASE = zIndex.zIndex.chatWindow;
|
|
15
16
|
function storageKey(storageId) {
|
|
16
17
|
return `chat-panels:${storageId}`;
|
|
17
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-window-context.cjs","sources":["../../../src/data/ai/chat-window-context.ts"],"sourcesContent":["// Non-component half of the chat window manager: the context object, the hook,\n// id helpers, persistence and layout maths. Split from the Provider (a .tsx\n// component) so this file stays JSX-free — matching the repo idiom of keeping\n// context/hooks in a .ts (see hooks/use-theme.ts, data/test-runner/context.ts)\n// and keeping React-Fast-Refresh happy.\nimport { createContext, useContext } from \"react\";\nimport type { ChatContextItem } from \"./context\";\n\n/** Live state of one floating chat window. Position/size/maximized are\n * persisted to localStorage; the rest is session-only. */\nexport interface ChatWindowState {\n id: string;\n threadId: string | null;\n initialModel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n maximized: boolean;\n /** A prompt to auto-send when the window mounts (the `id` lets the window\n * detect a fresh request even if the text repeats). */\n initialPrompt: { id: number; text: string } | null;\n contextItems: ChatContextItem[];\n}\n\nexport interface OpenPanelOpts {\n threadId?: string | null;\n initialModel?: string | null;\n initialPrompt?: { id: number; text: string } | null;\n contextItems?: ChatContextItem[];\n}\n\nexport interface ChatWindowManagerValue {\n panels: ChatWindowState[];\n openPanel: (opts?: OpenPanelOpts) => string;\n closePanel: (id: string) => void;\n updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;\n bringToFront: (id: string) => void;\n maximizePanel: (id: string) => void;\n /** Reuses the front-most existing window (merging in any new prompt/context)\n * or opens a fresh one when none exist. */\n findOrCreatePanel: (opts?: OpenPanelOpts) => string;\n}\n\nexport const ChatWindowManagerContext = createContext<ChatWindowManagerValue | null>(null);\n\nexport function useChatWindowManager(): ChatWindowManagerValue {\n const ctx = useContext(ChatWindowManagerContext);\n if (!ctx) throw new Error(\"useChatWindowManager must be used within <ChatWindowManagerProvider>\");\n return ctx;\n}\n\nexport const MAX_PANELS = 6;\nexport const DEFAULT_WIDTH = 520;\nexport const DEFAULT_HEIGHT = 700;\nexport const CASCADE_OFFSET = 30;\nexport const Z_BASE =
|
|
1
|
+
{"version":3,"file":"chat-window-context.cjs","sources":["../../../src/data/ai/chat-window-context.ts"],"sourcesContent":["// Non-component half of the chat window manager: the context object, the hook,\n// id helpers, persistence and layout maths. Split from the Provider (a .tsx\n// component) so this file stays JSX-free — matching the repo idiom of keeping\n// context/hooks in a .ts (see hooks/use-theme.ts, data/test-runner/context.ts)\n// and keeping React-Fast-Refresh happy.\nimport { createContext, useContext } from \"react\";\nimport type { ChatContextItem } from \"./context\";\nimport { zIndex } from \"../../overlay/zIndex\";\n\n/** Live state of one floating chat window. Position/size/maximized are\n * persisted to localStorage; the rest is session-only. */\nexport interface ChatWindowState {\n id: string;\n threadId: string | null;\n initialModel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n maximized: boolean;\n /** A prompt to auto-send when the window mounts (the `id` lets the window\n * detect a fresh request even if the text repeats). */\n initialPrompt: { id: number; text: string } | null;\n contextItems: ChatContextItem[];\n}\n\nexport interface OpenPanelOpts {\n threadId?: string | null;\n initialModel?: string | null;\n initialPrompt?: { id: number; text: string } | null;\n contextItems?: ChatContextItem[];\n}\n\nexport interface ChatWindowManagerValue {\n panels: ChatWindowState[];\n openPanel: (opts?: OpenPanelOpts) => string;\n closePanel: (id: string) => void;\n updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;\n bringToFront: (id: string) => void;\n maximizePanel: (id: string) => void;\n /** Reuses the front-most existing window (merging in any new prompt/context)\n * or opens a fresh one when none exist. */\n findOrCreatePanel: (opts?: OpenPanelOpts) => string;\n}\n\nexport const ChatWindowManagerContext = createContext<ChatWindowManagerValue | null>(null);\n\nexport function useChatWindowManager(): ChatWindowManagerValue {\n const ctx = useContext(ChatWindowManagerContext);\n if (!ctx) throw new Error(\"useChatWindowManager must be used within <ChatWindowManagerProvider>\");\n return ctx;\n}\n\nexport const MAX_PANELS = 6;\nexport const DEFAULT_WIDTH = 520;\nexport const DEFAULT_HEIGHT = 700;\nexport const CASCADE_OFFSET = 30;\nexport const Z_BASE = zIndex.chatWindow;\n\nfunction storageKey(storageId: string) {\n return `chat-panels:${storageId}`;\n}\n\ninterface PersistedPanel {\n id: string;\n threadId: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n maximized: boolean;\n}\n\nexport function loadPanels(storageId: string): ChatWindowState[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = localStorage.getItem(storageKey(storageId));\n if (!raw) return [];\n const persisted: PersistedPanel[] = JSON.parse(raw);\n return persisted.map((p, i) => ({\n ...p,\n initialModel: null,\n zIndex: Z_BASE + i,\n initialPrompt: null,\n contextItems: [],\n }));\n } catch {\n return [];\n }\n}\n\nexport function savePanels(storageId: string, panels: ChatWindowState[]) {\n const persisted: PersistedPanel[] = panels.map((p) => ({\n id: p.id,\n threadId: p.threadId,\n x: p.x,\n y: p.y,\n width: p.width,\n height: p.height,\n maximized: p.maximized,\n }));\n localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));\n}\n\nlet _panelId = 0;\nexport function nextPanelId(): string {\n return `panel-${++_panelId}-${Date.now()}`;\n}\n\nlet _promptId = 0;\n/** A monotonic id stamped onto an `initialPrompt` so a window re-sends even when\n * the same text is requested twice. */\nexport function nextPromptId(): number {\n return ++_promptId;\n}\n\n/** Re-indexes z so values stay compact (61, 62, …) with `frontId` on top. */\nexport function reindex(panels: ChatWindowState[], frontId?: string): ChatWindowState[] {\n const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);\n if (frontId) {\n const idx = sorted.findIndex((p) => p.id === frontId);\n if (idx >= 0) {\n const [item] = sorted.splice(idx, 1);\n if (item) sorted.push(item);\n }\n }\n return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));\n}\n"],"names":["createContext","useContext","zIndex"],"mappings":";;;;AA8CO,MAAM,2BAA2BA,MAAAA,cAA6C,IAAI;AAElF,SAAS,uBAA+C;AAC7D,QAAM,MAAMC,MAAAA,WAAW,wBAAwB;AAC/C,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sEAAsE;AAChG,SAAO;AACT;AAEO,MAAM,aAAa;AACnB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,SAASC,OAAAA,OAAO;AAE7B,SAAS,WAAW,WAAmB;AACrC,SAAO,eAAe,SAAS;AACjC;AAYO,SAAS,WAAW,WAAsC;AAC/D,MAAI,OAAO,WAAW,YAAa,QAAO,CAAA;AAC1C,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,WAAW,SAAS,CAAC;AACtD,QAAI,CAAC,IAAK,QAAO,CAAA;AACjB,UAAM,YAA8B,KAAK,MAAM,GAAG;AAClD,WAAO,UAAU,IAAI,CAAC,GAAG,OAAO;AAAA,MAC9B,GAAG;AAAA,MACH,cAAc;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB,eAAe;AAAA,MACf,cAAc,CAAA;AAAA,IAAC,EACf;AAAA,EACJ,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AAEO,SAAS,WAAW,WAAmB,QAA2B;AACvE,QAAM,YAA8B,OAAO,IAAI,CAAC,OAAO;AAAA,IACrD,IAAI,EAAE;AAAA,IACN,UAAU,EAAE;AAAA,IACZ,GAAG,EAAE;AAAA,IACL,GAAG,EAAE;AAAA,IACL,OAAO,EAAE;AAAA,IACT,QAAQ,EAAE;AAAA,IACV,WAAW,EAAE;AAAA,EAAA,EACb;AACF,eAAa,QAAQ,WAAW,SAAS,GAAG,KAAK,UAAU,SAAS,CAAC;AACvE;AAEA,IAAI,WAAW;AACR,SAAS,cAAsB;AACpC,SAAO,SAAS,EAAE,QAAQ,IAAI,KAAK,KAAK;AAC1C;AAEA,IAAI,YAAY;AAGT,SAAS,eAAuB;AACrC,SAAO,EAAE;AACX;AAGO,SAAS,QAAQ,QAA2B,SAAqC;AACtF,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC7D,MAAI,SAAS;AACX,UAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AACpD,QAAI,OAAO,GAAG;AACZ,YAAM,CAAC,IAAI,IAAI,OAAO,OAAO,KAAK,CAAC;AACnC,UAAI,KAAM,QAAO,KAAK,IAAI;AAAA,IAC5B;AAAA,EACF;AACA,SAAO,OAAO,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,QAAQ,SAAS,EAAA,EAAI;AAC5D;;;;;;;;;;;;;"}
|
|
@@ -45,7 +45,7 @@ export declare const MAX_PANELS = 6;
|
|
|
45
45
|
export declare const DEFAULT_WIDTH = 520;
|
|
46
46
|
export declare const DEFAULT_HEIGHT = 700;
|
|
47
47
|
export declare const CASCADE_OFFSET = 30;
|
|
48
|
-
export declare const Z_BASE
|
|
48
|
+
export declare const Z_BASE: 61;
|
|
49
49
|
export declare function loadPanels(storageId: string): ChatWindowState[];
|
|
50
50
|
export declare function savePanels(storageId: string, panels: ChatWindowState[]): void;
|
|
51
51
|
export declare function nextPanelId(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-window-context.d.ts","sourceRoot":"","sources":["../../../src/data/ai/chat-window-context.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"chat-window-context.d.ts","sourceRoot":"","sources":["../../../src/data/ai/chat-window-context.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD;2DAC2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB;4DACwD;IACxD,aAAa,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD,YAAY,EAAE,eAAe,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,aAAa,KAAK,MAAM,CAAC;IAC5C,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IACrE,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC;gDAC4C;IAC5C,iBAAiB,EAAE,CAAC,IAAI,CAAC,EAAE,aAAa,KAAK,MAAM,CAAC;CACrD;AAED,eAAO,MAAM,wBAAwB,wDAAqD,CAAC;AAE3F,wBAAgB,oBAAoB,IAAI,sBAAsB,CAI7D;AAED,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,MAAM,IAAoB,CAAC;AAgBxC,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAgB/D;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,QAWtE;AAGD,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAGD;wCACwC;AACxC,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE,CAUtF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useContext, createContext } from "react";
|
|
2
|
+
import { zIndex } from "../../overlay/zIndex.js";
|
|
2
3
|
const ChatWindowManagerContext = createContext(null);
|
|
3
4
|
function useChatWindowManager() {
|
|
4
5
|
const ctx = useContext(ChatWindowManagerContext);
|
|
@@ -9,7 +10,7 @@ const MAX_PANELS = 6;
|
|
|
9
10
|
const DEFAULT_WIDTH = 520;
|
|
10
11
|
const DEFAULT_HEIGHT = 700;
|
|
11
12
|
const CASCADE_OFFSET = 30;
|
|
12
|
-
const Z_BASE =
|
|
13
|
+
const Z_BASE = zIndex.chatWindow;
|
|
13
14
|
function storageKey(storageId) {
|
|
14
15
|
return `chat-panels:${storageId}`;
|
|
15
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-window-context.js","sources":["../../../src/data/ai/chat-window-context.ts"],"sourcesContent":["// Non-component half of the chat window manager: the context object, the hook,\n// id helpers, persistence and layout maths. Split from the Provider (a .tsx\n// component) so this file stays JSX-free — matching the repo idiom of keeping\n// context/hooks in a .ts (see hooks/use-theme.ts, data/test-runner/context.ts)\n// and keeping React-Fast-Refresh happy.\nimport { createContext, useContext } from \"react\";\nimport type { ChatContextItem } from \"./context\";\n\n/** Live state of one floating chat window. Position/size/maximized are\n * persisted to localStorage; the rest is session-only. */\nexport interface ChatWindowState {\n id: string;\n threadId: string | null;\n initialModel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n maximized: boolean;\n /** A prompt to auto-send when the window mounts (the `id` lets the window\n * detect a fresh request even if the text repeats). */\n initialPrompt: { id: number; text: string } | null;\n contextItems: ChatContextItem[];\n}\n\nexport interface OpenPanelOpts {\n threadId?: string | null;\n initialModel?: string | null;\n initialPrompt?: { id: number; text: string } | null;\n contextItems?: ChatContextItem[];\n}\n\nexport interface ChatWindowManagerValue {\n panels: ChatWindowState[];\n openPanel: (opts?: OpenPanelOpts) => string;\n closePanel: (id: string) => void;\n updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;\n bringToFront: (id: string) => void;\n maximizePanel: (id: string) => void;\n /** Reuses the front-most existing window (merging in any new prompt/context)\n * or opens a fresh one when none exist. */\n findOrCreatePanel: (opts?: OpenPanelOpts) => string;\n}\n\nexport const ChatWindowManagerContext = createContext<ChatWindowManagerValue | null>(null);\n\nexport function useChatWindowManager(): ChatWindowManagerValue {\n const ctx = useContext(ChatWindowManagerContext);\n if (!ctx) throw new Error(\"useChatWindowManager must be used within <ChatWindowManagerProvider>\");\n return ctx;\n}\n\nexport const MAX_PANELS = 6;\nexport const DEFAULT_WIDTH = 520;\nexport const DEFAULT_HEIGHT = 700;\nexport const CASCADE_OFFSET = 30;\nexport const Z_BASE =
|
|
1
|
+
{"version":3,"file":"chat-window-context.js","sources":["../../../src/data/ai/chat-window-context.ts"],"sourcesContent":["// Non-component half of the chat window manager: the context object, the hook,\n// id helpers, persistence and layout maths. Split from the Provider (a .tsx\n// component) so this file stays JSX-free — matching the repo idiom of keeping\n// context/hooks in a .ts (see hooks/use-theme.ts, data/test-runner/context.ts)\n// and keeping React-Fast-Refresh happy.\nimport { createContext, useContext } from \"react\";\nimport type { ChatContextItem } from \"./context\";\nimport { zIndex } from \"../../overlay/zIndex\";\n\n/** Live state of one floating chat window. Position/size/maximized are\n * persisted to localStorage; the rest is session-only. */\nexport interface ChatWindowState {\n id: string;\n threadId: string | null;\n initialModel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n maximized: boolean;\n /** A prompt to auto-send when the window mounts (the `id` lets the window\n * detect a fresh request even if the text repeats). */\n initialPrompt: { id: number; text: string } | null;\n contextItems: ChatContextItem[];\n}\n\nexport interface OpenPanelOpts {\n threadId?: string | null;\n initialModel?: string | null;\n initialPrompt?: { id: number; text: string } | null;\n contextItems?: ChatContextItem[];\n}\n\nexport interface ChatWindowManagerValue {\n panels: ChatWindowState[];\n openPanel: (opts?: OpenPanelOpts) => string;\n closePanel: (id: string) => void;\n updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;\n bringToFront: (id: string) => void;\n maximizePanel: (id: string) => void;\n /** Reuses the front-most existing window (merging in any new prompt/context)\n * or opens a fresh one when none exist. */\n findOrCreatePanel: (opts?: OpenPanelOpts) => string;\n}\n\nexport const ChatWindowManagerContext = createContext<ChatWindowManagerValue | null>(null);\n\nexport function useChatWindowManager(): ChatWindowManagerValue {\n const ctx = useContext(ChatWindowManagerContext);\n if (!ctx) throw new Error(\"useChatWindowManager must be used within <ChatWindowManagerProvider>\");\n return ctx;\n}\n\nexport const MAX_PANELS = 6;\nexport const DEFAULT_WIDTH = 520;\nexport const DEFAULT_HEIGHT = 700;\nexport const CASCADE_OFFSET = 30;\nexport const Z_BASE = zIndex.chatWindow;\n\nfunction storageKey(storageId: string) {\n return `chat-panels:${storageId}`;\n}\n\ninterface PersistedPanel {\n id: string;\n threadId: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n maximized: boolean;\n}\n\nexport function loadPanels(storageId: string): ChatWindowState[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = localStorage.getItem(storageKey(storageId));\n if (!raw) return [];\n const persisted: PersistedPanel[] = JSON.parse(raw);\n return persisted.map((p, i) => ({\n ...p,\n initialModel: null,\n zIndex: Z_BASE + i,\n initialPrompt: null,\n contextItems: [],\n }));\n } catch {\n return [];\n }\n}\n\nexport function savePanels(storageId: string, panels: ChatWindowState[]) {\n const persisted: PersistedPanel[] = panels.map((p) => ({\n id: p.id,\n threadId: p.threadId,\n x: p.x,\n y: p.y,\n width: p.width,\n height: p.height,\n maximized: p.maximized,\n }));\n localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));\n}\n\nlet _panelId = 0;\nexport function nextPanelId(): string {\n return `panel-${++_panelId}-${Date.now()}`;\n}\n\nlet _promptId = 0;\n/** A monotonic id stamped onto an `initialPrompt` so a window re-sends even when\n * the same text is requested twice. */\nexport function nextPromptId(): number {\n return ++_promptId;\n}\n\n/** Re-indexes z so values stay compact (61, 62, …) with `frontId` on top. */\nexport function reindex(panels: ChatWindowState[], frontId?: string): ChatWindowState[] {\n const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);\n if (frontId) {\n const idx = sorted.findIndex((p) => p.id === frontId);\n if (idx >= 0) {\n const [item] = sorted.splice(idx, 1);\n if (item) sorted.push(item);\n }\n }\n return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));\n}\n"],"names":[],"mappings":";;AA8CO,MAAM,2BAA2B,cAA6C,IAAI;AAElF,SAAS,uBAA+C;AAC7D,QAAM,MAAM,WAAW,wBAAwB;AAC/C,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sEAAsE;AAChG,SAAO;AACT;AAEO,MAAM,aAAa;AACnB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,SAAS,OAAO;AAE7B,SAAS,WAAW,WAAmB;AACrC,SAAO,eAAe,SAAS;AACjC;AAYO,SAAS,WAAW,WAAsC;AAC/D,MAAI,OAAO,WAAW,YAAa,QAAO,CAAA;AAC1C,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,WAAW,SAAS,CAAC;AACtD,QAAI,CAAC,IAAK,QAAO,CAAA;AACjB,UAAM,YAA8B,KAAK,MAAM,GAAG;AAClD,WAAO,UAAU,IAAI,CAAC,GAAG,OAAO;AAAA,MAC9B,GAAG;AAAA,MACH,cAAc;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB,eAAe;AAAA,MACf,cAAc,CAAA;AAAA,IAAC,EACf;AAAA,EACJ,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AAEO,SAAS,WAAW,WAAmB,QAA2B;AACvE,QAAM,YAA8B,OAAO,IAAI,CAAC,OAAO;AAAA,IACrD,IAAI,EAAE;AAAA,IACN,UAAU,EAAE;AAAA,IACZ,GAAG,EAAE;AAAA,IACL,GAAG,EAAE;AAAA,IACL,OAAO,EAAE;AAAA,IACT,QAAQ,EAAE;AAAA,IACV,WAAW,EAAE;AAAA,EAAA,EACb;AACF,eAAa,QAAQ,WAAW,SAAS,GAAG,KAAK,UAAU,SAAS,CAAC;AACvE;AAEA,IAAI,WAAW;AACR,SAAS,cAAsB;AACpC,SAAO,SAAS,EAAE,QAAQ,IAAI,KAAK,KAAK;AAC1C;AAEA,IAAI,YAAY;AAGT,SAAS,eAAuB;AACrC,SAAO,EAAE;AACX;AAGO,SAAS,QAAQ,QAA2B,SAAqC;AACtF,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC7D,MAAI,SAAS;AACX,UAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AACpD,QAAI,OAAO,GAAG;AACZ,YAAM,CAAC,IAAI,IAAI,OAAO,OAAO,KAAK,CAAC;AACnC,UAAI,KAAM,QAAO,KAAK,IAAI;AAAA,IAC5B;AAAA,EACF;AACA,SAAO,OAAO,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,QAAQ,SAAS,EAAA,EAAI;AAC5D;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.cjs","sources":["../../../src/data/ai/context.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\n\n/** A piece of context the user has attached to a chat (a record, a selection,\n * a document…). The `type` is an arbitrary caller-defined string; a\n * {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`\n * are flat key/value details serialized into the prompt and rendered as a\n * compact suffix on the badge. */\nexport interface ChatContextItem {\n id: string;\n type: string;\n label: string;\n fields?: Record<string, string>;\n}\n\n/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */\nexport interface ContextTypeStyle {\n /** Iconify name or an imported icon component. */\n icon?: string | StaticIconComponent;\n /** Tailwind classes for the badge (text + background colour). */\n className?: string;\n}\n\nexport type ContextTypeConfig = Record<string, ContextTypeStyle>;\n\n/** Serializes attached context into a `Context:` block the backend can prepend\n * to (or read alongside) the user's message. Mirrors the format parsed by\n * {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns \"\" when\n * there is nothing attached. */\nexport function serializeContext(items: ChatContextItem[]): string {\n if (items.length === 0) return \"\";\n const lines = items.map((item) => {\n const entries = Object.entries(item.fields ?? {})\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;\n });\n return `Context:\\n${lines.join(\"\\n\")}\\n\\n`;\n}\n\nconst CONTEXT_LINE_RE = /^\\[([^\\]]+)\\]\\s+(.+?)(?:\\s+\\((.+)\\))?$/;\n\n/** Splits a message produced with a {@link serializeContext} prefix back into\n * its attached items and the bare question. When no prefix is present the\n * whole text is returned as the question with no items. */\nexport function parseContextPrefix(text: string): { items: ChatContextItem[]; question: string } {\n if (!text.startsWith(\"Context:\\n\")) return { items: [], question: text };\n const blockEnd = text.indexOf(\"\\n\\n\");\n if (blockEnd === -1) return { items: [], question: text };\n const block = text.slice(\"Context:\\n\".length, blockEnd);\n const question = text.slice(blockEnd + 2);\n const items: ChatContextItem[] = [];\n for (const line of block.split(\"\\n\")) {\n const m = line.match(CONTEXT_LINE_RE);\n if (!m) continue;\n const fields: Record<string, string> = {};\n if (m[3]) {\n for (const pair of m[3].split(/,\\s*(?=[A-Za-z0-9_]+:)/)) {\n const idx = pair.indexOf(\":\");\n if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n }\n }\n items.push({ id: `parsed-${items.length}`, type: m[1]!, label: m[2]!, fields });\n }\n return { items, question };\n}\n\nlet nextId = 0;\n/** A process-unique id for a newly attached context item. */\nexport function makeContextId(): string {\n return `ctx-${++nextId}-${Date.now()}`;\n}\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"context.cjs","sources":["../../../src/data/ai/context.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\n\n/** A piece of context the user has attached to a chat (a record, a selection,\n * a document…). The `type` is an arbitrary caller-defined string; a\n * {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`\n * are flat key/value details serialized into the prompt and rendered as a\n * compact suffix on the badge. */\nexport interface ChatContextItem {\n id: string;\n type: string;\n label: string;\n fields?: Record<string, string>;\n /** Rich caller-owned data forwarded to the chat backend alongside the\n * serialized context summary. It is intentionally not rendered in badges. */\n payload?: unknown;\n}\n\n/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */\nexport interface ContextTypeStyle {\n /** Iconify name or an imported icon component. */\n icon?: string | StaticIconComponent;\n /** Tailwind classes for the badge (text + background colour). */\n className?: string;\n}\n\nexport type ContextTypeConfig = Record<string, ContextTypeStyle>;\n\n/** Serializes attached context into a `Context:` block the backend can prepend\n * to (or read alongside) the user's message. Mirrors the format parsed by\n * {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns \"\" when\n * there is nothing attached. */\nexport function serializeContext(items: ChatContextItem[]): string {\n if (items.length === 0) return \"\";\n const lines = items.map((item) => {\n const entries = Object.entries(item.fields ?? {})\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;\n });\n return `Context:\\n${lines.join(\"\\n\")}\\n\\n`;\n}\n\nconst CONTEXT_LINE_RE = /^\\[([^\\]]+)\\]\\s+(.+?)(?:\\s+\\((.+)\\))?$/;\n\n/** Splits a message produced with a {@link serializeContext} prefix back into\n * its attached items and the bare question. When no prefix is present the\n * whole text is returned as the question with no items. */\nexport function parseContextPrefix(text: string): { items: ChatContextItem[]; question: string } {\n if (!text.startsWith(\"Context:\\n\")) return { items: [], question: text };\n const blockEnd = text.indexOf(\"\\n\\n\");\n if (blockEnd === -1) return { items: [], question: text };\n const block = text.slice(\"Context:\\n\".length, blockEnd);\n const question = text.slice(blockEnd + 2);\n const items: ChatContextItem[] = [];\n for (const line of block.split(\"\\n\")) {\n const m = line.match(CONTEXT_LINE_RE);\n if (!m) continue;\n const fields: Record<string, string> = {};\n if (m[3]) {\n for (const pair of m[3].split(/,\\s*(?=[A-Za-z0-9_]+:)/)) {\n const idx = pair.indexOf(\":\");\n if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n }\n }\n items.push({ id: `parsed-${items.length}`, type: m[1]!, label: m[2]!, fields });\n }\n return { items, question };\n}\n\nlet nextId = 0;\n/** A process-unique id for a newly attached context item. */\nexport function makeContextId(): string {\n return `ctx-${++nextId}-${Date.now()}`;\n}\n"],"names":[],"mappings":";;AA+BO,SAAS,iBAAiB,OAAkC;AACjE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAQ,MAAM,IAAI,CAAC,SAAS;AAChC,UAAM,UAAU,OAAO,QAAQ,KAAK,UAAU,CAAA,CAAE,EAC7C,OAAO,CAAC,CAAA,EAAG,CAAC,MAAM,KAAK,QAAQ,MAAM,EAAE,EACvC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,EAC5B,KAAK,IAAI;AACZ,WAAO,UAAU,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,OAAO,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,EAC7F,CAAC;AACD,SAAO;AAAA,EAAa,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA;AACtC;AAEA,MAAM,kBAAkB;AAKjB,SAAS,mBAAmB,MAA8D;AAC/F,MAAI,CAAC,KAAK,WAAW,YAAY,EAAG,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AAClE,QAAM,WAAW,KAAK,QAAQ,MAAM;AACpC,MAAI,aAAa,GAAI,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AACnD,QAAM,QAAQ,KAAK,MAAM,aAAa,QAAQ,QAAQ;AACtD,QAAM,WAAW,KAAK,MAAM,WAAW,CAAC;AACxC,QAAM,QAA2B,CAAA;AACjC,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,UAAM,IAAI,KAAK,MAAM,eAAe;AACpC,QAAI,CAAC,EAAG;AACR,UAAM,SAAiC,CAAA;AACvC,QAAI,EAAE,CAAC,GAAG;AACR,iBAAW,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,GAAG;AACvD,cAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,YAAI,MAAM,EAAG,QAAO,KAAK,MAAM,GAAG,GAAG,EAAE,KAAA,CAAM,IAAI,KAAK,MAAM,MAAM,CAAC,EAAE,KAAA;AAAA,MACvE;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAI,UAAU,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC,GAAI,OAAO,EAAE,CAAC,GAAI,QAAQ;AAAA,EAChF;AACA,SAAO,EAAE,OAAO,SAAA;AAClB;AAEA,IAAI,SAAS;AAEN,SAAS,gBAAwB;AACtC,SAAO,OAAO,EAAE,MAAM,IAAI,KAAK,KAAK;AACtC;;;;"}
|
|
@@ -9,6 +9,9 @@ export interface ChatContextItem {
|
|
|
9
9
|
type: string;
|
|
10
10
|
label: string;
|
|
11
11
|
fields?: Record<string, string>;
|
|
12
|
+
/** Rich caller-owned data forwarded to the chat backend alongside the
|
|
13
|
+
* serialized context summary. It is intentionally not rendered in badges. */
|
|
14
|
+
payload?: unknown;
|
|
12
15
|
}
|
|
13
16
|
/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */
|
|
14
17
|
export interface ContextTypeStyle {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/data/ai/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;mCAImC;AACnC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/data/ai/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;mCAImC;AACnC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;kFAC8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAEjE;;;iCAGiC;AACjC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,CAUjE;AAID;;4DAE4D;AAC5D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAoB/F;AAGD,6DAA6D;AAC7D,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sources":["../../../src/data/ai/context.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\n\n/** A piece of context the user has attached to a chat (a record, a selection,\n * a document…). The `type` is an arbitrary caller-defined string; a\n * {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`\n * are flat key/value details serialized into the prompt and rendered as a\n * compact suffix on the badge. */\nexport interface ChatContextItem {\n id: string;\n type: string;\n label: string;\n fields?: Record<string, string>;\n}\n\n/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */\nexport interface ContextTypeStyle {\n /** Iconify name or an imported icon component. */\n icon?: string | StaticIconComponent;\n /** Tailwind classes for the badge (text + background colour). */\n className?: string;\n}\n\nexport type ContextTypeConfig = Record<string, ContextTypeStyle>;\n\n/** Serializes attached context into a `Context:` block the backend can prepend\n * to (or read alongside) the user's message. Mirrors the format parsed by\n * {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns \"\" when\n * there is nothing attached. */\nexport function serializeContext(items: ChatContextItem[]): string {\n if (items.length === 0) return \"\";\n const lines = items.map((item) => {\n const entries = Object.entries(item.fields ?? {})\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;\n });\n return `Context:\\n${lines.join(\"\\n\")}\\n\\n`;\n}\n\nconst CONTEXT_LINE_RE = /^\\[([^\\]]+)\\]\\s+(.+?)(?:\\s+\\((.+)\\))?$/;\n\n/** Splits a message produced with a {@link serializeContext} prefix back into\n * its attached items and the bare question. When no prefix is present the\n * whole text is returned as the question with no items. */\nexport function parseContextPrefix(text: string): { items: ChatContextItem[]; question: string } {\n if (!text.startsWith(\"Context:\\n\")) return { items: [], question: text };\n const blockEnd = text.indexOf(\"\\n\\n\");\n if (blockEnd === -1) return { items: [], question: text };\n const block = text.slice(\"Context:\\n\".length, blockEnd);\n const question = text.slice(blockEnd + 2);\n const items: ChatContextItem[] = [];\n for (const line of block.split(\"\\n\")) {\n const m = line.match(CONTEXT_LINE_RE);\n if (!m) continue;\n const fields: Record<string, string> = {};\n if (m[3]) {\n for (const pair of m[3].split(/,\\s*(?=[A-Za-z0-9_]+:)/)) {\n const idx = pair.indexOf(\":\");\n if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n }\n }\n items.push({ id: `parsed-${items.length}`, type: m[1]!, label: m[2]!, fields });\n }\n return { items, question };\n}\n\nlet nextId = 0;\n/** A process-unique id for a newly attached context item. */\nexport function makeContextId(): string {\n return `ctx-${++nextId}-${Date.now()}`;\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.js","sources":["../../../src/data/ai/context.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\n\n/** A piece of context the user has attached to a chat (a record, a selection,\n * a document…). The `type` is an arbitrary caller-defined string; a\n * {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`\n * are flat key/value details serialized into the prompt and rendered as a\n * compact suffix on the badge. */\nexport interface ChatContextItem {\n id: string;\n type: string;\n label: string;\n fields?: Record<string, string>;\n /** Rich caller-owned data forwarded to the chat backend alongside the\n * serialized context summary. It is intentionally not rendered in badges. */\n payload?: unknown;\n}\n\n/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */\nexport interface ContextTypeStyle {\n /** Iconify name or an imported icon component. */\n icon?: string | StaticIconComponent;\n /** Tailwind classes for the badge (text + background colour). */\n className?: string;\n}\n\nexport type ContextTypeConfig = Record<string, ContextTypeStyle>;\n\n/** Serializes attached context into a `Context:` block the backend can prepend\n * to (or read alongside) the user's message. Mirrors the format parsed by\n * {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns \"\" when\n * there is nothing attached. */\nexport function serializeContext(items: ChatContextItem[]): string {\n if (items.length === 0) return \"\";\n const lines = items.map((item) => {\n const entries = Object.entries(item.fields ?? {})\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;\n });\n return `Context:\\n${lines.join(\"\\n\")}\\n\\n`;\n}\n\nconst CONTEXT_LINE_RE = /^\\[([^\\]]+)\\]\\s+(.+?)(?:\\s+\\((.+)\\))?$/;\n\n/** Splits a message produced with a {@link serializeContext} prefix back into\n * its attached items and the bare question. When no prefix is present the\n * whole text is returned as the question with no items. */\nexport function parseContextPrefix(text: string): { items: ChatContextItem[]; question: string } {\n if (!text.startsWith(\"Context:\\n\")) return { items: [], question: text };\n const blockEnd = text.indexOf(\"\\n\\n\");\n if (blockEnd === -1) return { items: [], question: text };\n const block = text.slice(\"Context:\\n\".length, blockEnd);\n const question = text.slice(blockEnd + 2);\n const items: ChatContextItem[] = [];\n for (const line of block.split(\"\\n\")) {\n const m = line.match(CONTEXT_LINE_RE);\n if (!m) continue;\n const fields: Record<string, string> = {};\n if (m[3]) {\n for (const pair of m[3].split(/,\\s*(?=[A-Za-z0-9_]+:)/)) {\n const idx = pair.indexOf(\":\");\n if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n }\n }\n items.push({ id: `parsed-${items.length}`, type: m[1]!, label: m[2]!, fields });\n }\n return { items, question };\n}\n\nlet nextId = 0;\n/** A process-unique id for a newly attached context item. */\nexport function makeContextId(): string {\n return `ctx-${++nextId}-${Date.now()}`;\n}\n"],"names":[],"mappings":"AA+BO,SAAS,iBAAiB,OAAkC;AACjE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAQ,MAAM,IAAI,CAAC,SAAS;AAChC,UAAM,UAAU,OAAO,QAAQ,KAAK,UAAU,CAAA,CAAE,EAC7C,OAAO,CAAC,CAAA,EAAG,CAAC,MAAM,KAAK,QAAQ,MAAM,EAAE,EACvC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,EAC5B,KAAK,IAAI;AACZ,WAAO,UAAU,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,OAAO,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,EAC7F,CAAC;AACD,SAAO;AAAA,EAAa,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA;AACtC;AAEA,MAAM,kBAAkB;AAKjB,SAAS,mBAAmB,MAA8D;AAC/F,MAAI,CAAC,KAAK,WAAW,YAAY,EAAG,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AAClE,QAAM,WAAW,KAAK,QAAQ,MAAM;AACpC,MAAI,aAAa,GAAI,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AACnD,QAAM,QAAQ,KAAK,MAAM,aAAa,QAAQ,QAAQ;AACtD,QAAM,WAAW,KAAK,MAAM,WAAW,CAAC;AACxC,QAAM,QAA2B,CAAA;AACjC,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,UAAM,IAAI,KAAK,MAAM,eAAe;AACpC,QAAI,CAAC,EAAG;AACR,UAAM,SAAiC,CAAA;AACvC,QAAI,EAAE,CAAC,GAAG;AACR,iBAAW,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,GAAG;AACvD,cAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,YAAI,MAAM,EAAG,QAAO,KAAK,MAAM,GAAG,GAAG,EAAE,KAAA,CAAM,IAAI,KAAK,MAAM,MAAM,CAAC,EAAE,KAAA;AAAA,MACvE;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAI,UAAU,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC,GAAI,OAAO,EAAE,CAAC,GAAI,QAAQ;AAAA,EAChF;AACA,SAAO,EAAE,OAAO,SAAA;AAClB;AAEA,IAAI,SAAS;AAEN,SAAS,gBAAwB;AACtC,SAAO,OAAO,EAAE,MAAM,IAAI,KAAK,KAAK;AACtC;"}
|