@seed-ship/mcp-ui-solid 6.19.0 → 6.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +532 -0
- package/README.md +798 -1
- package/dist/adapters/connector.cjs +15 -4
- package/dist/adapters/connector.cjs.map +1 -1
- package/dist/adapters/connector.d.ts +38 -0
- package/dist/adapters/connector.d.ts.map +1 -1
- package/dist/adapters/connector.js +15 -4
- package/dist/adapters/connector.js.map +1 -1
- package/dist/adapters/index.d.ts +4 -3
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/macro-run.cjs +25 -13
- package/dist/adapters/macro-run.cjs.map +1 -1
- package/dist/adapters/macro-run.d.ts +37 -2
- package/dist/adapters/macro-run.d.ts.map +1 -1
- package/dist/adapters/macro-run.js +25 -13
- package/dist/adapters/macro-run.js.map +1 -1
- package/dist/adapters.cjs +2 -0
- package/dist/adapters.cjs.map +1 -1
- package/dist/adapters.js +4 -2
- package/dist/components/ActionGroupRenderer.cjs +3 -1
- package/dist/components/ActionGroupRenderer.cjs.map +1 -1
- package/dist/components/ActionGroupRenderer.d.ts.map +1 -1
- package/dist/components/ActionGroupRenderer.js +3 -1
- package/dist/components/ActionGroupRenderer.js.map +1 -1
- package/dist/components/AgentCard.cjs +11 -8
- package/dist/components/AgentCard.cjs.map +1 -1
- package/dist/components/AgentCard.d.ts.map +1 -1
- package/dist/components/AgentCard.js +11 -8
- package/dist/components/AgentCard.js.map +1 -1
- package/dist/components/AgentHandoff.cjs +6 -1
- package/dist/components/AgentHandoff.cjs.map +1 -1
- package/dist/components/AgentHandoff.d.ts.map +1 -1
- package/dist/components/AgentHandoff.js +6 -1
- package/dist/components/AgentHandoff.js.map +1 -1
- package/dist/components/ArtifactRenderer.cjs +25 -6
- package/dist/components/ArtifactRenderer.cjs.map +1 -1
- package/dist/components/ArtifactRenderer.d.ts.map +1 -1
- package/dist/components/ArtifactRenderer.js +25 -6
- package/dist/components/ArtifactRenderer.js.map +1 -1
- package/dist/components/AutocompleteDropdown.cjs +30 -24
- package/dist/components/AutocompleteDropdown.cjs.map +1 -1
- package/dist/components/AutocompleteDropdown.d.ts.map +1 -1
- package/dist/components/AutocompleteDropdown.js +30 -24
- package/dist/components/AutocompleteDropdown.js.map +1 -1
- package/dist/components/AutocompleteFormField.cjs +3 -1
- package/dist/components/AutocompleteFormField.cjs.map +1 -1
- package/dist/components/AutocompleteFormField.d.ts.map +1 -1
- package/dist/components/AutocompleteFormField.js +4 -2
- package/dist/components/AutocompleteFormField.js.map +1 -1
- package/dist/components/BriefingDiff.cjs +45 -39
- package/dist/components/BriefingDiff.cjs.map +1 -1
- package/dist/components/BriefingDiff.d.ts.map +1 -1
- package/dist/components/BriefingDiff.js +45 -39
- package/dist/components/BriefingDiff.js.map +1 -1
- package/dist/components/CarouselRenderer.cjs +8 -2
- package/dist/components/CarouselRenderer.cjs.map +1 -1
- package/dist/components/CarouselRenderer.d.ts.map +1 -1
- package/dist/components/CarouselRenderer.js +8 -2
- package/dist/components/CarouselRenderer.js.map +1 -1
- package/dist/components/ChartJSRenderer.cjs +60 -36
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +61 -37
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/ChatPrompt.cjs +15 -9
- package/dist/components/ChatPrompt.cjs.map +1 -1
- package/dist/components/ChatPrompt.d.ts.map +1 -1
- package/dist/components/ChatPrompt.js +15 -9
- package/dist/components/ChatPrompt.js.map +1 -1
- package/dist/components/CodeBlockRenderer.cjs +34 -16
- package/dist/components/CodeBlockRenderer.cjs.map +1 -1
- package/dist/components/CodeBlockRenderer.d.ts.map +1 -1
- package/dist/components/CodeBlockRenderer.js +34 -16
- package/dist/components/CodeBlockRenderer.js.map +1 -1
- package/dist/components/DataPreviewSection.cjs +91 -44
- package/dist/components/DataPreviewSection.cjs.map +1 -1
- package/dist/components/DataPreviewSection.d.ts.map +1 -1
- package/dist/components/DataPreviewSection.js +92 -45
- package/dist/components/DataPreviewSection.js.map +1 -1
- package/dist/components/DegradedFallback.cjs +20 -16
- package/dist/components/DegradedFallback.cjs.map +1 -1
- package/dist/components/DegradedFallback.d.ts.map +1 -1
- package/dist/components/DegradedFallback.js +20 -16
- package/dist/components/DegradedFallback.js.map +1 -1
- package/dist/components/FeedbackInline.cjs +19 -3
- package/dist/components/FeedbackInline.cjs.map +1 -1
- package/dist/components/FeedbackInline.js +19 -3
- package/dist/components/FeedbackInline.js.map +1 -1
- package/dist/components/FooterRenderer.cjs +21 -17
- package/dist/components/FooterRenderer.cjs.map +1 -1
- package/dist/components/FooterRenderer.d.ts.map +1 -1
- package/dist/components/FooterRenderer.js +21 -17
- package/dist/components/FooterRenderer.js.map +1 -1
- package/dist/components/FormFieldRenderer.cjs +116 -93
- package/dist/components/FormFieldRenderer.cjs.map +1 -1
- package/dist/components/FormFieldRenderer.d.ts.map +1 -1
- package/dist/components/FormFieldRenderer.js +116 -93
- package/dist/components/FormFieldRenderer.js.map +1 -1
- package/dist/components/FormRenderer.cjs +55 -31
- package/dist/components/FormRenderer.cjs.map +1 -1
- package/dist/components/FormRenderer.d.ts.map +1 -1
- package/dist/components/FormRenderer.js +55 -31
- package/dist/components/FormRenderer.js.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.cjs +20 -15
- package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.d.ts.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.js +20 -15
- package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
- package/dist/components/GraphRenderer.cjs +56 -33
- package/dist/components/GraphRenderer.cjs.map +1 -1
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js +56 -33
- package/dist/components/GraphRenderer.js.map +1 -1
- package/dist/components/ImageGalleryRenderer.cjs +13 -4
- package/dist/components/ImageGalleryRenderer.cjs.map +1 -1
- package/dist/components/ImageGalleryRenderer.d.ts.map +1 -1
- package/dist/components/ImageGalleryRenderer.js +13 -4
- package/dist/components/ImageGalleryRenderer.js.map +1 -1
- package/dist/components/LightboxOverlay.cjs +16 -8
- package/dist/components/LightboxOverlay.cjs.map +1 -1
- package/dist/components/LightboxOverlay.d.ts.map +1 -1
- package/dist/components/LightboxOverlay.js +17 -9
- package/dist/components/LightboxOverlay.js.map +1 -1
- package/dist/components/MapRenderer.cjs +59 -29
- package/dist/components/MapRenderer.cjs.map +1 -1
- package/dist/components/MapRenderer.d.ts +10 -2
- package/dist/components/MapRenderer.d.ts.map +1 -1
- package/dist/components/MapRenderer.js +60 -30
- package/dist/components/MapRenderer.js.map +1 -1
- package/dist/components/ModalRenderer.cjs +4 -1
- package/dist/components/ModalRenderer.cjs.map +1 -1
- package/dist/components/ModalRenderer.d.ts.map +1 -1
- package/dist/components/ModalRenderer.js +5 -2
- package/dist/components/ModalRenderer.js.map +1 -1
- package/dist/components/ScratchpadPanel.cjs +578 -535
- package/dist/components/ScratchpadPanel.cjs.map +1 -1
- package/dist/components/ScratchpadPanel.d.ts.map +1 -1
- package/dist/components/ScratchpadPanel.js +578 -535
- package/dist/components/ScratchpadPanel.js.map +1 -1
- package/dist/components/StreamingUIRenderer.cjs +92 -28
- package/dist/components/StreamingUIRenderer.cjs.map +1 -1
- package/dist/components/StreamingUIRenderer.d.ts.map +1 -1
- package/dist/components/StreamingUIRenderer.js +92 -28
- package/dist/components/StreamingUIRenderer.js.map +1 -1
- package/dist/components/UIResourceRenderer.cjs +456 -363
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts +21 -0
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +458 -365
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/VerifiedText.cjs +39 -20
- package/dist/components/VerifiedText.cjs.map +1 -1
- package/dist/components/VerifiedText.d.ts +2 -1
- package/dist/components/VerifiedText.d.ts.map +1 -1
- package/dist/components/VerifiedText.js +39 -20
- package/dist/components/VerifiedText.js.map +1 -1
- package/dist/components/VideoRenderer.cjs +10 -5
- package/dist/components/VideoRenderer.cjs.map +1 -1
- package/dist/components/VideoRenderer.d.ts.map +1 -1
- package/dist/components/VideoRenderer.js +10 -5
- package/dist/components/VideoRenderer.js.map +1 -1
- package/dist/components/chart-data-table.cjs +38 -17
- package/dist/components/chart-data-table.cjs.map +1 -1
- package/dist/components/chart-data-table.d.ts +30 -1
- package/dist/components/chart-data-table.d.ts.map +1 -1
- package/dist/components/chart-data-table.js +38 -17
- package/dist/components/chart-data-table.js.map +1 -1
- package/dist/context/MCPActionContext.cjs +3 -1
- package/dist/context/MCPActionContext.cjs.map +1 -1
- package/dist/context/MCPActionContext.d.ts.map +1 -1
- package/dist/context/MCPActionContext.js +3 -1
- package/dist/context/MCPActionContext.js.map +1 -1
- package/dist/context/MCPUIStringsContext.cjs +285 -2
- package/dist/context/MCPUIStringsContext.cjs.map +1 -1
- package/dist/context/MCPUIStringsContext.d.ts +600 -3
- package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
- package/dist/context/MCPUIStringsContext.js +285 -2
- package/dist/context/MCPUIStringsContext.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useStreamingUI.cjs +28 -10
- package/dist/hooks/useStreamingUI.cjs.map +1 -1
- package/dist/hooks/useStreamingUI.d.ts +37 -0
- package/dist/hooks/useStreamingUI.d.ts.map +1 -1
- package/dist/hooks/useStreamingUI.js +28 -10
- package/dist/hooks/useStreamingUI.js.map +1 -1
- package/dist/hooks.cjs +1 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.js +2 -1
- package/dist/index.cjs +23 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -3
- package/dist/index.js.map +1 -1
- package/dist/services/validation.cjs +41 -16
- package/dist/services/validation.cjs.map +1 -1
- package/dist/services/validation.d.ts +47 -2
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/services/validation.js +41 -16
- package/dist/services/validation.js.map +1 -1
- package/dist/utils/degraded-projections.cjs +37 -12
- package/dist/utils/degraded-projections.cjs.map +1 -1
- package/dist/utils/degraded-projections.d.ts +39 -3
- package/dist/utils/degraded-projections.d.ts.map +1 -1
- package/dist/utils/degraded-projections.js +37 -12
- package/dist/utils/degraded-projections.js.map +1 -1
- package/dist/utils/format-string.cjs +10 -0
- package/dist/utils/format-string.cjs.map +1 -0
- package/dist/utils/format-string.d.ts +26 -0
- package/dist/utils/format-string.d.ts.map +1 -0
- package/dist/utils/format-string.js +10 -0
- package/dist/utils/format-string.js.map +1 -0
- package/dist/validation.cjs +3 -0
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.d.cts +2 -1
- package/dist/validation.d.ts +2 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +4 -1
- package/package.json +1 -1
- package/src/adapters/connector.ts +58 -4
- package/src/adapters/index.ts +12 -2
- package/src/adapters/macro-run.ts +71 -11
- package/src/components/ActionGroupRenderer.tsx +3 -1
- package/src/components/AgentCard.tsx +27 -9
- package/src/components/AgentHandoff.tsx +4 -1
- package/src/components/ArtifactRenderer.tsx +17 -5
- package/src/components/AutocompleteDropdown.tsx +8 -6
- package/src/components/AutocompleteFormField.tsx +5 -1
- package/src/components/BriefingDiff.tsx +11 -3
- package/src/components/CarouselRenderer.tsx +4 -2
- package/src/components/ChartJSRenderer.tsx +18 -9
- package/src/components/ChatPrompt.tsx +13 -8
- package/src/components/CodeBlockRenderer.tsx +12 -10
- package/src/components/DataPreviewSection.tsx +92 -26
- package/src/components/DegradedFallback.tsx +4 -2
- package/src/components/FeedbackInline.tsx +2 -2
- package/src/components/FooterRenderer.tsx +3 -1
- package/src/components/FormFieldRenderer.tsx +34 -19
- package/src/components/FormRenderer.tsx +38 -10
- package/src/components/GenerativeUIErrorBoundary.tsx +8 -3
- package/src/components/GraphRenderer.tsx +31 -16
- package/src/components/ImageGalleryRenderer.tsx +8 -4
- package/src/components/LightboxOverlay.tsx +6 -4
- package/src/components/MapRenderer.tsx +57 -20
- package/src/components/ModalRenderer.tsx +3 -1
- package/src/components/ScratchpadPanel.tsx +95 -44
- package/src/components/StreamingUIRenderer.tsx +41 -11
- package/src/components/UIResourceRenderer.tsx +145 -63
- package/src/components/VerifiedText.tsx +19 -9
- package/src/components/VideoRenderer.tsx +6 -4
- package/src/components/chart-data-table.ts +68 -14
- package/src/context/MCPActionContext.tsx +4 -1
- package/src/context/MCPUIStringsContext.tsx +1004 -1
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useStreamingUI.ts +64 -10
- package/src/index.ts +23 -0
- package/src/services/validation.ts +93 -16
- package/src/utils/degraded-projections.ts +75 -12
- package/src/utils/format-string.ts +33 -0
- package/src/validation.ts +5 -0
|
@@ -17,6 +17,7 @@ import { AgentCard, AgentStatusBadge } from './AgentCard'
|
|
|
17
17
|
import { SplitStepper } from './SplitStepper'
|
|
18
18
|
import { AgentHandoff } from './AgentHandoff'
|
|
19
19
|
import { BriefingDiff } from './BriefingDiff'
|
|
20
|
+
import { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'
|
|
20
21
|
|
|
21
22
|
export interface ScratchpadPanelProps {
|
|
22
23
|
state: ScratchpadState
|
|
@@ -44,16 +45,35 @@ export interface ScratchpadPanelProps {
|
|
|
44
45
|
maxHeight?: string
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Status badges. The record stays module-level (it is static styling), but
|
|
50
|
+
* it carries a `labelKey` instead of English: the label is resolved from
|
|
51
|
+
* `useMCPUIStrings()` at render time, so a host provider localizes it.
|
|
52
|
+
* Same technique as `SOURCE_BADGES` in `FormFieldRenderer`.
|
|
53
|
+
*/
|
|
54
|
+
type StatusLabelKey =
|
|
55
|
+
| 'statusLoading'
|
|
56
|
+
| 'statusActionAvailable'
|
|
57
|
+
| 'statusYourTurn'
|
|
58
|
+
| 'statusProcessing'
|
|
59
|
+
| 'statusComplete'
|
|
60
|
+
| 'scratchpadError'
|
|
61
|
+
|
|
62
|
+
const STATUS_BADGES: Record<
|
|
63
|
+
ScratchpadState['status'],
|
|
64
|
+
{ labelKey: StatusLabelKey; class: string }
|
|
65
|
+
> = {
|
|
66
|
+
loading: { labelKey: 'statusLoading', class: 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400' },
|
|
67
|
+
ready: { labelKey: 'statusActionAvailable', class: 'bg-cyan-100 text-cyan-700 dark:bg-cyan-900/30 dark:text-cyan-400' },
|
|
68
|
+
waiting_human: { labelKey: 'statusYourTurn', class: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400 animate-pulse' },
|
|
69
|
+
processing: { labelKey: 'statusProcessing', class: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400' },
|
|
70
|
+
complete: { labelKey: 'statusComplete', class: 'bg-green-100 text-green-600 dark:bg-green-900/30 dark:text-green-400' },
|
|
71
|
+
// The error badge reuses the existing `scratchpadError` key ('Error').
|
|
72
|
+
error: { labelKey: 'scratchpadError', class: 'bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400' },
|
|
54
73
|
}
|
|
55
74
|
|
|
56
75
|
export const ScratchpadPanel: Component<ScratchpadPanelProps> = (props) => {
|
|
76
|
+
const strings = useMCPUIStrings()
|
|
57
77
|
const [collapsed, setCollapsed] = createSignal(false)
|
|
58
78
|
const [localPreview, setLocalPreview] = createSignal<ScratchpadState['preview']>(undefined)
|
|
59
79
|
const [loadingAction, setLoadingAction] = createSignal<string | null>(null)
|
|
@@ -198,9 +218,9 @@ export const ScratchpadPanel: Component<ScratchpadPanelProps> = (props) => {
|
|
|
198
218
|
</Show>
|
|
199
219
|
</div>
|
|
200
220
|
<div class="flex items-center gap-2">
|
|
201
|
-
<span class={`px-2 py-0.5 text-xs font-medium rounded-full ${badge().class}`}>{badge().
|
|
221
|
+
<span class={`px-2 py-0.5 text-xs font-medium rounded-full ${badge().class}`}>{strings[badge().labelKey]}</span>
|
|
202
222
|
<Show when={isClosable() && props.onClose}>
|
|
203
|
-
<button onClick={(e) => { e.stopPropagation(); props.onClose?.() }} class="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors" aria-label=
|
|
223
|
+
<button onClick={(e) => { e.stopPropagation(); props.onClose?.() }} class="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors" aria-label={strings.scratchpadClose}>
|
|
204
224
|
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /></svg>
|
|
205
225
|
</button>
|
|
206
226
|
</Show>
|
|
@@ -275,8 +295,8 @@ export const ScratchpadPanel: Component<ScratchpadPanelProps> = (props) => {
|
|
|
275
295
|
<Show when={preview()!.count === 0} fallback={
|
|
276
296
|
<>
|
|
277
297
|
<div class="flex items-center gap-2 mb-2">
|
|
278
|
-
<span class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide">
|
|
279
|
-
<span class="px-1.5 py-0.5 text-xs font-bold bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded">{preview()!.count.toLocaleString()}</span>
|
|
298
|
+
<span class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide">{strings.scratchpadPreview}</span>
|
|
299
|
+
<span class="px-1.5 py-0.5 text-xs font-bold bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded">{preview()!.count.toLocaleString(strings.locale)}</span>
|
|
280
300
|
</div>
|
|
281
301
|
<p class="text-sm text-gray-700 dark:text-gray-300">{preview()!.summary}</p>
|
|
282
302
|
<Show when={preview()!.rows && preview()!.rows!.length > 0}>
|
|
@@ -291,8 +311,8 @@ export const ScratchpadPanel: Component<ScratchpadPanelProps> = (props) => {
|
|
|
291
311
|
}>
|
|
292
312
|
<div class="flex flex-col items-center gap-2 py-4 text-center">
|
|
293
313
|
<span class="text-2xl">🔍</span>
|
|
294
|
-
<p class="text-sm text-gray-500 dark:text-gray-400">
|
|
295
|
-
<button type="button" onClick={() => props.onAction?.('refine_filters')} class="px-3 py-1.5 text-xs font-medium text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded-lg transition-colors">
|
|
314
|
+
<p class="text-sm text-gray-500 dark:text-gray-400">{strings.scratchpadNoResults}</p>
|
|
315
|
+
<button type="button" onClick={() => props.onAction?.('refine_filters')} class="px-3 py-1.5 text-xs font-medium text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded-lg transition-colors">{strings.scratchpadModifyFilters}</button>
|
|
296
316
|
</div>
|
|
297
317
|
</Show>
|
|
298
318
|
</div>
|
|
@@ -306,7 +326,9 @@ export const ScratchpadPanel: Component<ScratchpadPanelProps> = (props) => {
|
|
|
306
326
|
<div class="flex-1">
|
|
307
327
|
<p class="font-medium">{props.state.error!.message}</p>
|
|
308
328
|
<Show when={props.state.error!.code}>
|
|
309
|
-
<p class="text-xs text-red-500 dark:text-red-500 mt-0.5">
|
|
329
|
+
<p class="text-xs text-red-500 dark:text-red-500 mt-0.5">
|
|
330
|
+
{formatMCPUIString(strings.scratchpadErrorCode, { code: props.state.error!.code! })}
|
|
331
|
+
</p>
|
|
310
332
|
</Show>
|
|
311
333
|
</div>
|
|
312
334
|
</div>
|
|
@@ -314,13 +336,13 @@ export const ScratchpadPanel: Component<ScratchpadPanelProps> = (props) => {
|
|
|
314
336
|
<Show when={props.state.error!.retryable !== false}>
|
|
315
337
|
<button type="button" onClick={() => props.onRetry?.()}
|
|
316
338
|
class="px-3 py-1.5 text-sm font-medium rounded-lg bg-red-600 text-white hover:bg-red-700 transition-colors flex items-center gap-1">
|
|
317
|
-
🔄
|
|
339
|
+
🔄 {strings.retry}
|
|
318
340
|
</button>
|
|
319
341
|
</Show>
|
|
320
342
|
<Show when={props.onClose}>
|
|
321
343
|
<button type="button" onClick={() => props.onClose?.()}
|
|
322
344
|
class="px-3 py-1.5 text-sm font-medium rounded-lg border border-gray-200 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors">
|
|
323
|
-
|
|
345
|
+
{strings.scratchpadClose}
|
|
324
346
|
</button>
|
|
325
347
|
</Show>
|
|
326
348
|
</div>
|
|
@@ -336,7 +358,7 @@ export const ScratchpadPanel: Component<ScratchpadPanelProps> = (props) => {
|
|
|
336
358
|
class="w-full px-4 py-2.5 text-sm font-semibold rounded-lg text-white bg-blue-600 hover:bg-blue-700 transition-colors flex items-center justify-center gap-2"
|
|
337
359
|
>
|
|
338
360
|
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>
|
|
339
|
-
|
|
361
|
+
{strings.scratchpadSearch}
|
|
340
362
|
</button>
|
|
341
363
|
</div>
|
|
342
364
|
</Show>
|
|
@@ -427,6 +449,7 @@ const InteractiveFilterSection: Component<{
|
|
|
427
449
|
filters: Record<string, string | string[]>
|
|
428
450
|
onFilterChange?: (filters: Record<string, string | string[]>) => void
|
|
429
451
|
}> = (props) => {
|
|
452
|
+
const strings = useMCPUIStrings()
|
|
430
453
|
const [editingKey, setEditingKey] = createSignal<string | null>(null)
|
|
431
454
|
const [editValue, setEditValue] = createSignal('')
|
|
432
455
|
|
|
@@ -477,7 +500,7 @@ const InteractiveFilterSection: Component<{
|
|
|
477
500
|
<span class="text-blue-500 dark:text-blue-400">{def()?.label || key}:</span> {Array.isArray(value()) ? (value() as string[]).join(', ') : String(value())}
|
|
478
501
|
</button>
|
|
479
502
|
<Show when={props.onFilterChange}>
|
|
480
|
-
<button type="button" onClick={() => removeFilter(key)} class="ml-0.5 hover:text-blue-900 dark:hover:text-blue-100" aria-label={
|
|
503
|
+
<button type="button" onClick={() => removeFilter(key)} class="ml-0.5 hover:text-blue-900 dark:hover:text-blue-100" aria-label={formatMCPUIString(strings.removeItem, { name: key })}>×</button>
|
|
481
504
|
</Show>
|
|
482
505
|
</span>
|
|
483
506
|
</Show>
|
|
@@ -489,8 +512,8 @@ const InteractiveFilterSection: Component<{
|
|
|
489
512
|
<form onSubmit={(e) => { e.preventDefault(); setFilter(key, editValue()) }} class="flex gap-1">
|
|
490
513
|
<input type="text" value={editValue()} onInput={(e) => setEditValue(e.currentTarget.value)} placeholder={def()?.placeholder || key} autofocus
|
|
491
514
|
class="flex-1 px-2 py-1 text-sm border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:border-blue-400 outline-none" />
|
|
492
|
-
<button type="submit" class="px-2 py-1 text-xs bg-blue-600 text-white rounded hover:bg-blue-700">
|
|
493
|
-
<button type="button" onClick={() => setEditingKey(null)} class="px-2 py-1 text-xs text-gray-500 hover:text-gray-700">
|
|
515
|
+
<button type="submit" class="px-2 py-1 text-xs bg-blue-600 text-white rounded hover:bg-blue-700">{strings.ok}</button>
|
|
516
|
+
<button type="button" onClick={() => setEditingKey(null)} class="px-2 py-1 text-xs text-gray-500 hover:text-gray-700">{strings.cancel}</button>
|
|
494
517
|
</form>
|
|
495
518
|
}>
|
|
496
519
|
<div class="max-h-48 overflow-y-auto">
|
|
@@ -506,7 +529,7 @@ const InteractiveFilterSection: Component<{
|
|
|
506
529
|
)}
|
|
507
530
|
</For>
|
|
508
531
|
</div>
|
|
509
|
-
<button type="button" onClick={() => setEditingKey(null)} class="mt-1 w-full px-2 py-1 text-xs text-gray-500 hover:text-gray-700 text-center">
|
|
532
|
+
<button type="button" onClick={() => setEditingKey(null)} class="mt-1 w-full px-2 py-1 text-xs text-gray-500 hover:text-gray-700 text-center">{strings.cancel}</button>
|
|
510
533
|
</Show>
|
|
511
534
|
</div>
|
|
512
535
|
</Show>
|
|
@@ -515,7 +538,7 @@ const InteractiveFilterSection: Component<{
|
|
|
515
538
|
}}
|
|
516
539
|
</For>
|
|
517
540
|
<Show when={allKeys().length === 0}>
|
|
518
|
-
<p class="text-xs text-gray-400 italic">
|
|
541
|
+
<p class="text-xs text-gray-400 italic">{strings.scratchpadNoFilters}</p>
|
|
519
542
|
</Show>
|
|
520
543
|
</div>
|
|
521
544
|
)
|
|
@@ -530,13 +553,14 @@ const EmbeddedFormSection: Component<{
|
|
|
530
553
|
onSubmit?: (sectionId: string, values: Record<string, unknown>) => void
|
|
531
554
|
debugTrace?: boolean
|
|
532
555
|
}> = (props) => {
|
|
556
|
+
const strings = useMCPUIStrings()
|
|
533
557
|
const [dynamicOptions, setDynamicOptions] = createSignal<Record<string, Array<{ label: string; value: string }>>>({})
|
|
534
558
|
|
|
535
559
|
const config = () => {
|
|
536
560
|
const c = props.content as any
|
|
537
561
|
return {
|
|
538
562
|
fields: c?.fields || [],
|
|
539
|
-
submitLabel: c?.submitLabel ||
|
|
563
|
+
submitLabel: c?.submitLabel || strings.submit,
|
|
540
564
|
autoSubmitDelay: c?.autoSubmitDelay as number | undefined,
|
|
541
565
|
}
|
|
542
566
|
}
|
|
@@ -689,7 +713,7 @@ const EmbeddedFormSection: Component<{
|
|
|
689
713
|
</span>
|
|
690
714
|
<span class="text-blue-600 dark:text-blue-300">{countdown()}s...</span>
|
|
691
715
|
<button type="button" onClick={() => { setExpanded(true); cancelCountdown(); setUserInteracted(true) }}
|
|
692
|
-
class="text-blue-600 dark:text-blue-400 underline text-xs">
|
|
716
|
+
class="text-blue-600 dark:text-blue-400 underline text-xs">{strings.scratchpadEdit}</button>
|
|
693
717
|
<button type="button" onClick={() => { cancelCountdown(); setUserInteracted(true) }}
|
|
694
718
|
class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">×</button>
|
|
695
719
|
</div>
|
|
@@ -698,7 +722,10 @@ const EmbeddedFormSection: Component<{
|
|
|
698
722
|
{/* Proposal 3: prefill summary */}
|
|
699
723
|
<Show when={prefillSummary().prefilled > 0}>
|
|
700
724
|
<p class="text-xs text-gray-500 dark:text-gray-400">
|
|
701
|
-
{
|
|
725
|
+
{formatMCPUIString(
|
|
726
|
+
prefillSummary().prefilled === 1 ? strings.formPrefilledOne : strings.formPrefilledMany,
|
|
727
|
+
{ count: prefillSummary().prefilled, total: prefillSummary().total }
|
|
728
|
+
)}
|
|
702
729
|
</p>
|
|
703
730
|
</Show>
|
|
704
731
|
<For each={config().fields}>
|
|
@@ -714,14 +741,17 @@ const EmbeddedFormSection: Component<{
|
|
|
714
741
|
<Show when={countdown() != null}>
|
|
715
742
|
<div class="flex items-center gap-3 p-2 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-md text-sm">
|
|
716
743
|
<span class="text-blue-700 dark:text-blue-300">
|
|
717
|
-
{
|
|
744
|
+
{formatMCPUIString(strings.formSubmitCountdown, {
|
|
745
|
+
label: config().submitLabel,
|
|
746
|
+
seconds: countdown()!,
|
|
747
|
+
})}
|
|
718
748
|
</span>
|
|
719
749
|
<button
|
|
720
750
|
type="button"
|
|
721
751
|
onClick={() => { cancelCountdown(); setUserInteracted(true) }}
|
|
722
752
|
class="text-blue-600 dark:text-blue-400 underline hover:text-blue-800 dark:hover:text-blue-200"
|
|
723
753
|
>
|
|
724
|
-
|
|
754
|
+
{strings.cancel}
|
|
725
755
|
</button>
|
|
726
756
|
</div>
|
|
727
757
|
</Show>
|
|
@@ -758,6 +788,7 @@ const FormDebugTrace: Component<{
|
|
|
758
788
|
userInteracted: boolean
|
|
759
789
|
rawContent: unknown
|
|
760
790
|
}> = (props) => {
|
|
791
|
+
const strings = useMCPUIStrings()
|
|
761
792
|
const [open, setOpen] = createSignal(false)
|
|
762
793
|
const [showRaw, setShowRaw] = createSignal(false)
|
|
763
794
|
|
|
@@ -848,7 +879,7 @@ const FormDebugTrace: Component<{
|
|
|
848
879
|
|
|
849
880
|
<div class="pt-1 border-t border-gray-200 dark:border-gray-600">
|
|
850
881
|
<button type="button" onClick={() => setShowRaw(!showRaw())} class="text-blue-500 hover:text-blue-700 underline">
|
|
851
|
-
{showRaw() ?
|
|
882
|
+
{showRaw() ? strings.scratchpadHideRaw : strings.scratchpadShowRaw}
|
|
852
883
|
</button>
|
|
853
884
|
<Show when={showRaw()}>
|
|
854
885
|
<pre class="mt-1 p-2 bg-gray-50 dark:bg-gray-900 rounded max-h-48 overflow-auto text-[10px]">
|
|
@@ -869,6 +900,7 @@ const EnrichedStepsSection: Component<{
|
|
|
869
900
|
onAction?: (action: string, data?: unknown) => void
|
|
870
901
|
onFilterChange?: (filters: Record<string, string | string[]>) => void
|
|
871
902
|
}> = (props) => {
|
|
903
|
+
const strings = useMCPUIStrings()
|
|
872
904
|
const stepsData = () => {
|
|
873
905
|
const c = props.content as any
|
|
874
906
|
return { steps: c?.steps || [], currentStep: c?.currentStep ?? 0 }
|
|
@@ -911,7 +943,7 @@ const EnrichedStepsSection: Component<{
|
|
|
911
943
|
<div class="flex justify-end">
|
|
912
944
|
<button type="button" onClick={() => props.onAction?.('next_step', { step: stepsData().currentStep })}
|
|
913
945
|
class="px-3 py-1.5 text-sm font-medium text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded-lg transition-colors flex items-center gap-1">
|
|
914
|
-
|
|
946
|
+
{strings.scratchpadNextStep} <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /></svg>
|
|
915
947
|
</button>
|
|
916
948
|
</div>
|
|
917
949
|
</Show>
|
|
@@ -925,6 +957,7 @@ const ActionSection: Component<{
|
|
|
925
957
|
content: unknown
|
|
926
958
|
onAction?: (action: string, data?: unknown) => void
|
|
927
959
|
}> = (props) => {
|
|
960
|
+
const strings = useMCPUIStrings()
|
|
928
961
|
const data = () => {
|
|
929
962
|
const c = props.content as any
|
|
930
963
|
if (Array.isArray(c)) return { actions: c, title: undefined, preview: undefined, validation: undefined }
|
|
@@ -942,7 +975,7 @@ const ActionSection: Component<{
|
|
|
942
975
|
{(preview) => (
|
|
943
976
|
<div class="mb-2 p-2 rounded bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 text-xs text-gray-600 dark:text-gray-400">
|
|
944
977
|
<Show when={preview().count != null}>
|
|
945
|
-
<span class="font-medium text-gray-800 dark:text-gray-200">{preview().count}</span>
|
|
978
|
+
<span class="font-medium text-gray-800 dark:text-gray-200">{preview().count}</span> {strings.scratchpadItems}
|
|
946
979
|
</Show>
|
|
947
980
|
<Show when={preview().summary}>
|
|
948
981
|
<span class="ml-1">— {preview().summary}</span>
|
|
@@ -957,10 +990,16 @@ const ActionSection: Component<{
|
|
|
957
990
|
'text-amber-600 dark:text-amber-400': data().validation.confidence >= 0.5 && data().validation.confidence < 0.8,
|
|
958
991
|
'text-red-600 dark:text-red-400': data().validation.confidence < 0.5,
|
|
959
992
|
}}>
|
|
960
|
-
{
|
|
993
|
+
{formatMCPUIString(strings.verifiedConfidence, {
|
|
994
|
+
pct: Math.round(data().validation.confidence * 100),
|
|
995
|
+
})}
|
|
961
996
|
</span>
|
|
962
997
|
<Show when={data().validation.hallucinated?.length > 0}>
|
|
963
|
-
<span class="text-amber-600">
|
|
998
|
+
<span class="text-amber-600">
|
|
999
|
+
{formatMCPUIString(strings.verifiedUnverifiedCount, {
|
|
1000
|
+
count: data().validation.hallucinated.length,
|
|
1001
|
+
})}
|
|
1002
|
+
</span>
|
|
964
1003
|
</Show>
|
|
965
1004
|
</div>
|
|
966
1005
|
</Show>
|
|
@@ -1039,20 +1078,24 @@ const FeedbackSection: Component<{
|
|
|
1039
1078
|
content: unknown
|
|
1040
1079
|
onAction?: (action: string, data?: unknown) => void
|
|
1041
1080
|
}> = (props) => {
|
|
1081
|
+
const strings = useMCPUIStrings()
|
|
1042
1082
|
const [comment, setComment] = createSignal('')
|
|
1043
1083
|
const [showComment, setShowComment] = createSignal(false)
|
|
1044
1084
|
const [submitted, setSubmitted] = createSignal<string | null>(null)
|
|
1085
|
+
// The badge shows the chosen option's LABEL (payload or localized default),
|
|
1086
|
+
// never its machine value ('approve' / 'reject' / 'comment').
|
|
1087
|
+
const [submittedLabel, setSubmittedLabel] = createSignal('')
|
|
1045
1088
|
const data = () => {
|
|
1046
1089
|
const c = props.content as any
|
|
1047
1090
|
const options = c?.options || [
|
|
1048
|
-
{ value: c?.approve?.value || 'approve', label: c?.approve?.label ||
|
|
1049
|
-
{ value: c?.reject?.value || 'reject', label: c?.reject?.label ||
|
|
1091
|
+
{ value: c?.approve?.value || 'approve', label: c?.approve?.label || strings.yes, icon: '\uD83D\uDC4D', variant: 'primary' },
|
|
1092
|
+
{ value: c?.reject?.value || 'reject', label: c?.reject?.label || strings.no, icon: '\uD83D\uDC4E' },
|
|
1050
1093
|
]
|
|
1051
1094
|
return {
|
|
1052
1095
|
question: c?.question || '',
|
|
1053
1096
|
options: options as Array<{ value: string; label: string; icon?: string; variant?: string; needsComment?: boolean }>,
|
|
1054
1097
|
allowFreeText: c?.allowFreeText ?? c?.allowComment ?? false,
|
|
1055
|
-
placeholder: c?.placeholder || c?.commentPlaceholder ||
|
|
1098
|
+
placeholder: c?.placeholder || c?.commentPlaceholder || strings.scratchpadCommentPlaceholder,
|
|
1056
1099
|
// v4.1.0: per-step feedback
|
|
1057
1100
|
agentId: c?.agentId as string | undefined,
|
|
1058
1101
|
stepId: c?.stepId as string | undefined,
|
|
@@ -1065,6 +1108,7 @@ const FeedbackSection: Component<{
|
|
|
1065
1108
|
return
|
|
1066
1109
|
}
|
|
1067
1110
|
setSubmitted(option.value)
|
|
1111
|
+
setSubmittedLabel(option.label ?? '')
|
|
1068
1112
|
const payload = {
|
|
1069
1113
|
option: option.value,
|
|
1070
1114
|
comment: comment(),
|
|
@@ -1089,7 +1133,7 @@ const FeedbackSection: Component<{
|
|
|
1089
1133
|
'text-red-600': submitted() === 'reject',
|
|
1090
1134
|
'text-blue-600': submitted() !== 'approve' && submitted() !== 'reject',
|
|
1091
1135
|
}}>
|
|
1092
|
-
{submitted() === 'approve' ? '\u2705' : submitted() === 'reject' ? '\u274C' : '\uD83D\uDCAC'} {
|
|
1136
|
+
{submitted() === 'approve' ? '\u2705' : submitted() === 'reject' ? '\u274C' : '\uD83D\uDCAC'} {submittedLabel()}
|
|
1093
1137
|
</span>
|
|
1094
1138
|
<Show when={comment()}>
|
|
1095
1139
|
<span class="italic">— {comment()}</span>
|
|
@@ -1119,8 +1163,8 @@ const FeedbackSection: Component<{
|
|
|
1119
1163
|
<input type="text" value={comment()} onInput={(e) => setComment(e.currentTarget.value)}
|
|
1120
1164
|
placeholder={data().placeholder} autofocus={showComment()}
|
|
1121
1165
|
class="flex-1 px-3 py-2 text-sm border border-gray-200 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:border-blue-400 outline-none" />
|
|
1122
|
-
<button type="button" on:click={() => { setSubmitted('comment'); props.onAction?.('feedback', { option: 'comment', comment: comment(), agentId: data().agentId, stepId: data().stepId }) }}
|
|
1123
|
-
class="px-3 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700">
|
|
1166
|
+
<button type="button" on:click={() => { setSubmitted('comment'); setSubmittedLabel(''); props.onAction?.('feedback', { option: 'comment', comment: comment(), agentId: data().agentId, stepId: data().stepId }) }}
|
|
1167
|
+
class="px-3 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700">{strings.scratchpadSend}</button>
|
|
1124
1168
|
</div>
|
|
1125
1169
|
</Show>
|
|
1126
1170
|
</Show>
|
|
@@ -1134,6 +1178,7 @@ const PromptSection: Component<{
|
|
|
1134
1178
|
content: unknown
|
|
1135
1179
|
onAction?: (action: string, data?: unknown) => void
|
|
1136
1180
|
}> = (props) => {
|
|
1181
|
+
const strings = useMCPUIStrings()
|
|
1137
1182
|
const data = () => {
|
|
1138
1183
|
const c = props.content as any
|
|
1139
1184
|
return {
|
|
@@ -1162,13 +1207,13 @@ const PromptSection: Component<{
|
|
|
1162
1207
|
</div>
|
|
1163
1208
|
<Show when={data().plan}>
|
|
1164
1209
|
<div class="mt-2 px-3 py-2 bg-blue-50 dark:bg-blue-900/10 rounded-lg text-sm text-blue-700 dark:text-blue-300">
|
|
1165
|
-
<span class="font-medium">
|
|
1210
|
+
<span class="font-medium">{strings.scratchpadPlan}</span> {data().plan}
|
|
1166
1211
|
</div>
|
|
1167
1212
|
</Show>
|
|
1168
1213
|
<Show when={data().editable}>
|
|
1169
1214
|
<button type="button" onClick={() => props.onAction?.('edit_prompt', data())}
|
|
1170
1215
|
class="text-xs text-blue-600 dark:text-blue-400 hover:underline flex items-center gap-1">
|
|
1171
|
-
✎
|
|
1216
|
+
✎ {strings.scratchpadModify}
|
|
1172
1217
|
</button>
|
|
1173
1218
|
</Show>
|
|
1174
1219
|
</div>
|
|
@@ -1251,10 +1296,11 @@ const ErrorSectionRenderer: Component<{
|
|
|
1251
1296
|
content: unknown
|
|
1252
1297
|
onAction?: (action: string, data?: unknown) => void
|
|
1253
1298
|
}> = (props) => {
|
|
1299
|
+
const strings = useMCPUIStrings()
|
|
1254
1300
|
const [showDetails, setShowDetails] = createSignal(false)
|
|
1255
1301
|
const data = () => {
|
|
1256
1302
|
const c = props.content as any
|
|
1257
|
-
const d = { message: c?.message ||
|
|
1303
|
+
const d = { message: c?.message || strings.scratchpadError, severity: c?.severity || 'error', retryAction: c?.retryAction, retryLabel: c?.retryLabel || strings.retry, details: c?.details, timestamp: c?.timestamp }
|
|
1258
1304
|
// DX1 Etape 8
|
|
1259
1305
|
console.info(`%c[MCP-UI] Error section rendered%c severity=${d.severity} retry=${!!d.retryAction}`, 'color: #ef4444; font-weight: bold', 'color: inherit')
|
|
1260
1306
|
return d
|
|
@@ -1272,7 +1318,7 @@ const ErrorSectionRenderer: Component<{
|
|
|
1272
1318
|
<button type="button" onClick={() => props.onAction?.(data().retryAction!)} class={`px-2 py-1 text-xs font-medium rounded ${isWarning() ? 'bg-amber-600 text-white hover:bg-amber-700' : 'bg-red-600 text-white hover:bg-red-700'} transition-colors`}>🔄 {data().retryLabel}</button>
|
|
1273
1319
|
</Show>
|
|
1274
1320
|
<Show when={data().details}>
|
|
1275
|
-
<button type="button" onClick={() => setShowDetails(!showDetails())} class="px-2 py-1 text-xs opacity-70 hover:opacity-100">▶
|
|
1321
|
+
<button type="button" onClick={() => setShowDetails(!showDetails())} class="px-2 py-1 text-xs opacity-70 hover:opacity-100">▶ {strings.scratchpadDetails}</button>
|
|
1276
1322
|
</Show>
|
|
1277
1323
|
</div>
|
|
1278
1324
|
<Show when={showDetails() && data().details}>
|
|
@@ -1287,9 +1333,10 @@ const ErrorSectionRenderer: Component<{
|
|
|
1287
1333
|
// ─── Source Card Section (F9) ────────────────────────────────
|
|
1288
1334
|
|
|
1289
1335
|
const SourceCardSection: Component<{ content: unknown }> = (props) => {
|
|
1336
|
+
const strings = useMCPUIStrings()
|
|
1290
1337
|
const data = () => {
|
|
1291
1338
|
const c = props.content as any
|
|
1292
|
-
return { name: c?.name ||
|
|
1339
|
+
return { name: c?.name || strings.scratchpadSource, status: c?.status || 'available', capabilities: c?.capabilities || [], latency_ms: c?.latency_ms, freshness: c?.freshness, row_count: c?.row_count }
|
|
1293
1340
|
}
|
|
1294
1341
|
const statusIcon = () => ({ queried: '✅', available: '📦', error: '❌' } as Record<string, string>)[data().status] || '📦'
|
|
1295
1342
|
|
|
@@ -1298,7 +1345,11 @@ const SourceCardSection: Component<{ content: unknown }> = (props) => {
|
|
|
1298
1345
|
<div class="flex items-center justify-between mb-1.5">
|
|
1299
1346
|
<span class="text-sm font-medium text-gray-900 dark:text-white">{statusIcon()} {data().name}</span>
|
|
1300
1347
|
<Show when={data().row_count !== undefined}>
|
|
1301
|
-
<span class="text-xs font-bold text-blue-600 dark:text-blue-400">
|
|
1348
|
+
<span class="text-xs font-bold text-blue-600 dark:text-blue-400">
|
|
1349
|
+
{formatMCPUIString(strings.scratchpadResultCount, {
|
|
1350
|
+
count: data().row_count?.toLocaleString(strings.locale) ?? '',
|
|
1351
|
+
})}
|
|
1352
|
+
</span>
|
|
1302
1353
|
</Show>
|
|
1303
1354
|
</div>
|
|
1304
1355
|
<div class="flex flex-wrap gap-1.5 mb-1">
|
|
@@ -36,7 +36,11 @@
|
|
|
36
36
|
*/
|
|
37
37
|
|
|
38
38
|
import { Show, For, createSignal, onMount } from 'solid-js'
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
useStreamingUI,
|
|
41
|
+
type StreamingUIMessages,
|
|
42
|
+
type UseStreamingUIOptions,
|
|
43
|
+
} from '../hooks/useStreamingUI'
|
|
40
44
|
import type { UIComponent, RendererError } from '../types'
|
|
41
45
|
import { UIResourceRenderer, type ValidationErrorMode } from './UIResourceRenderer'
|
|
42
46
|
import { useMCPUIStrings } from '../context/MCPUIStringsContext'
|
|
@@ -73,6 +77,21 @@ function asFullWidth(component: UIComponent): UIComponent {
|
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
export function StreamingUIRenderer(props: StreamingUIRendererProps) {
|
|
80
|
+
const strings = useMCPUIStrings()
|
|
81
|
+
// Getters: each message is read from the context when the hook produces it.
|
|
82
|
+
// An explicit `props.messages` entry wins over the context.
|
|
83
|
+
const messages: StreamingUIMessages = {
|
|
84
|
+
get initializing() { return props.messages?.initializing ?? strings.streamInitializing },
|
|
85
|
+
get connecting() { return props.messages?.connecting ?? strings.streamConnecting },
|
|
86
|
+
get loadingComponent() { return props.messages?.loadingComponent ?? strings.streamLoadingComponent },
|
|
87
|
+
get dashboardLoaded() { return props.messages?.dashboardLoaded ?? strings.streamDashboardLoaded },
|
|
88
|
+
get errorProgress() { return props.messages?.errorProgress ?? strings.streamErrorProgress },
|
|
89
|
+
get connectionFailed() { return props.messages?.connectionFailed ?? strings.streamConnectionFailed },
|
|
90
|
+
get requestFailed() { return props.messages?.requestFailed ?? strings.streamRequestFailed },
|
|
91
|
+
get emptyResponse() { return props.messages?.emptyResponse ?? strings.streamEmptyResponse },
|
|
92
|
+
get serverSide() { return props.messages?.serverSide ?? strings.streamServerSide },
|
|
93
|
+
get unknownError() { return props.messages?.unknownError ?? strings.streamUnknownError },
|
|
94
|
+
}
|
|
76
95
|
const { components, isLoading, isStreaming, error, progress, metadata, startStreaming } =
|
|
77
96
|
useStreamingUI({
|
|
78
97
|
query: props.query,
|
|
@@ -82,9 +101,9 @@ export function StreamingUIRenderer(props: StreamingUIRendererProps) {
|
|
|
82
101
|
onComplete: props.onComplete,
|
|
83
102
|
onError: props.onError,
|
|
84
103
|
onComponentReceived: props.onComponentReceived,
|
|
104
|
+
messages,
|
|
85
105
|
})
|
|
86
106
|
|
|
87
|
-
const strings = useMCPUIStrings()
|
|
88
107
|
const [animatingComponents, setAnimatingComponents] = createSignal<Set<string>>(new Set())
|
|
89
108
|
|
|
90
109
|
// Track new components for animation
|
|
@@ -156,7 +175,9 @@ export function StreamingUIRenderer(props: StreamingUIRendererProps) {
|
|
|
156
175
|
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
157
176
|
/>
|
|
158
177
|
</svg>
|
|
159
|
-
<span class="font-medium text-error-primary">
|
|
178
|
+
<span class="font-medium text-error-primary">
|
|
179
|
+
{error()?.error === 'ssr' ? strings.streamServerSideTitle : error()?.error}
|
|
180
|
+
</span>
|
|
160
181
|
</div>
|
|
161
182
|
<p class="text-sm text-text-secondary">{error()?.message}</p>
|
|
162
183
|
|
|
@@ -217,31 +238,40 @@ export function StreamingUIRenderer(props: StreamingUIRendererProps) {
|
|
|
217
238
|
<div class="mt-6 rounded-lg border border-border-subtle bg-surface-secondary p-4 text-sm text-text-secondary">
|
|
218
239
|
<div class="grid grid-cols-2 gap-4 md:grid-cols-4">
|
|
219
240
|
<div>
|
|
220
|
-
<div class="font-medium text-text-primary">
|
|
241
|
+
<div class="font-medium text-text-primary">{strings.metaProvider}</div>
|
|
221
242
|
<div>{metadata()?.provider}</div>
|
|
222
243
|
</div>
|
|
223
244
|
<div>
|
|
224
|
-
<div class="font-medium text-text-primary">
|
|
245
|
+
<div class="font-medium text-text-primary">{strings.metaModel}</div>
|
|
225
246
|
<div>{metadata()?.model}</div>
|
|
226
247
|
</div>
|
|
227
248
|
<div>
|
|
228
|
-
<div class="font-medium text-text-primary">
|
|
249
|
+
<div class="font-medium text-text-primary">{strings.metaExecutionTime}</div>
|
|
229
250
|
<div>{metadata()?.executionTimeMs}ms</div>
|
|
230
251
|
</div>
|
|
231
252
|
<Show when={metadata()?.costUSD !== undefined}>
|
|
232
253
|
<div>
|
|
233
|
-
<div class="font-medium text-text-primary">
|
|
234
|
-
<div
|
|
254
|
+
<div class="font-medium text-text-primary">{strings.metaCost}</div>
|
|
255
|
+
<div>
|
|
256
|
+
{new Intl.NumberFormat(strings.locale, {
|
|
257
|
+
style: 'currency',
|
|
258
|
+
currency: 'USD',
|
|
259
|
+
currencyDisplay: 'narrowSymbol',
|
|
260
|
+
minimumFractionDigits: 4,
|
|
261
|
+
maximumFractionDigits: 4,
|
|
262
|
+
useGrouping: false,
|
|
263
|
+
}).format(metadata()?.costUSD ?? 0)}
|
|
264
|
+
</div>
|
|
235
265
|
</div>
|
|
236
266
|
</Show>
|
|
237
267
|
<div>
|
|
238
|
-
<div class="font-medium text-text-primary">
|
|
268
|
+
<div class="font-medium text-text-primary">{strings.metaTtfb}</div>
|
|
239
269
|
<div>{metadata()?.firstTokenMs}ms</div>
|
|
240
270
|
</div>
|
|
241
271
|
<Show when={metadata()?.cached}>
|
|
242
272
|
<div>
|
|
243
|
-
<div class="font-medium text-text-primary">
|
|
244
|
-
<div class="text-success-primary">
|
|
273
|
+
<div class="font-medium text-text-primary">{strings.metaCached}</div>
|
|
274
|
+
<div class="text-success-primary">{strings.yes}</div>
|
|
245
275
|
</div>
|
|
246
276
|
</Show>
|
|
247
277
|
</div>
|