@seed-ship/mcp-ui-solid 6.19.1 → 6.21.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 +663 -0
- package/README.md +911 -4
- 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/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/IframeFallbackLink.cjs +37 -0
- package/dist/components/IframeFallbackLink.cjs.map +1 -0
- package/dist/components/IframeFallbackLink.d.ts +23 -0
- package/dist/components/IframeFallbackLink.d.ts.map +1 -0
- package/dist/components/IframeFallbackLink.js +37 -0
- package/dist/components/IframeFallbackLink.js.map +1 -0
- 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 +481 -365
- 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 +484 -368
- 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 +51 -20
- package/dist/components/VideoRenderer.cjs.map +1 -1
- package/dist/components/VideoRenderer.d.ts.map +1 -1
- package/dist/components/VideoRenderer.js +51 -20
- 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/MCPUIConfigContext.cjs +29 -0
- package/dist/context/MCPUIConfigContext.cjs.map +1 -0
- package/dist/context/MCPUIConfigContext.d.ts +124 -0
- package/dist/context/MCPUIConfigContext.d.ts.map +1 -0
- package/dist/context/MCPUIConfigContext.js +29 -0
- package/dist/context/MCPUIConfigContext.js.map +1 -0
- package/dist/context/MCPUIStringsContext.cjs +287 -2
- package/dist/context/MCPUIStringsContext.cjs.map +1 -1
- package/dist/context/MCPUIStringsContext.d.ts +607 -3
- package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
- package/dist/context/MCPUIStringsContext.js +287 -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 +29 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -4
- package/dist/index.d.ts +12 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -3
- package/dist/index.js.map +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/validation.cjs +52 -26
- package/dist/services/validation.cjs.map +1 -1
- package/dist/services/validation.d.ts +67 -2
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/services/validation.js +52 -26
- 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/utils/iframe-coep.cjs +30 -0
- package/dist/utils/iframe-coep.cjs.map +1 -0
- package/dist/utils/iframe-coep.d.ts +46 -0
- package/dist/utils/iframe-coep.d.ts.map +1 -0
- package/dist/utils/iframe-coep.js +30 -0
- package/dist/utils/iframe-coep.js.map +1 -0
- package/dist/validation.cjs +5 -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 +6 -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/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/IframeFallbackLink.tsx +57 -0
- 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 +176 -67
- package/src/components/VerifiedText.tsx +19 -9
- package/src/components/VideoRenderer.tsx +26 -4
- package/src/components/chart-data-table.ts +68 -14
- package/src/context/MCPActionContext.tsx +4 -1
- package/src/context/MCPUIConfigContext.tsx +151 -0
- package/src/context/MCPUIStringsContext.tsx +1014 -1
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useStreamingUI.ts +64 -10
- package/src/index.ts +38 -0
- package/src/services/index.ts +1 -0
- package/src/services/validation.ts +131 -32
- package/src/solid-jsx-attrs.d.ts +24 -0
- package/src/utils/degraded-projections.ts +75 -12
- package/src/utils/format-string.ts +33 -0
- package/src/utils/iframe-coep.ts +74 -0
- package/src/validation.ts +9 -0
|
@@ -6,12 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Modes:
|
|
8
8
|
* - highlight: ✅/⚠️ badges next to numbers (default)
|
|
9
|
-
* - strip: replaces hallucinated numbers with
|
|
9
|
+
* - strip: replaces hallucinated numbers with the `verifiedStripLabel`
|
|
10
|
+
* chrome string ('[unverified]' by default)
|
|
10
11
|
* - annotate: tooltip on hover with closest source number
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
import { createMemo, For } from 'solid-js'
|
|
14
15
|
import type { DataValidation, HallucinatedNumber } from '../types/chat-bus'
|
|
16
|
+
import { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'
|
|
15
17
|
|
|
16
18
|
export interface VerifiedTextProps {
|
|
17
19
|
text: string
|
|
@@ -94,6 +96,7 @@ function buildAnnotatedSegments(text: string, validation: DataValidation): TextS
|
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
export function VerifiedText(props: VerifiedTextProps) {
|
|
99
|
+
const strings = useMCPUIStrings()
|
|
97
100
|
const mode = () => props.mode || 'highlight'
|
|
98
101
|
|
|
99
102
|
const segments = createMemo<TextSegment[]>(() => {
|
|
@@ -115,10 +118,10 @@ export function VerifiedText(props: VerifiedTextProps) {
|
|
|
115
118
|
return (
|
|
116
119
|
<span
|
|
117
120
|
class="inline-flex items-center gap-0.5 px-0.5 rounded bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-300"
|
|
118
|
-
title=
|
|
121
|
+
title={strings.verifiedTitle}
|
|
119
122
|
>
|
|
120
123
|
{seg.content}
|
|
121
|
-
<span class="text-xs opacity-70" aria-label=
|
|
124
|
+
<span class="text-xs opacity-70" aria-label={strings.verifiedAria}>✅</span>
|
|
122
125
|
</span>
|
|
123
126
|
)
|
|
124
127
|
}
|
|
@@ -127,9 +130,12 @@ export function VerifiedText(props: VerifiedTextProps) {
|
|
|
127
130
|
const h = seg.item!
|
|
128
131
|
const tooltipText = () => {
|
|
129
132
|
if (h.closest != null && h.distance != null) {
|
|
130
|
-
return
|
|
133
|
+
return formatMCPUIString(strings.verifiedNotFoundClosest, {
|
|
134
|
+
closest: h.closest,
|
|
135
|
+
pct: Math.round(h.distance * 100),
|
|
136
|
+
})
|
|
131
137
|
}
|
|
132
|
-
return
|
|
138
|
+
return strings.verifiedNotFound
|
|
133
139
|
}
|
|
134
140
|
|
|
135
141
|
if (mode() === 'strip') {
|
|
@@ -138,7 +144,7 @@ export function VerifiedText(props: VerifiedTextProps) {
|
|
|
138
144
|
class="inline-flex items-center px-1 rounded bg-amber-50 dark:bg-amber-900/20 text-amber-700 dark:text-amber-300 italic text-xs"
|
|
139
145
|
title={tooltipText()}
|
|
140
146
|
>
|
|
141
|
-
|
|
147
|
+
{strings.verifiedStripLabel}
|
|
142
148
|
</span>
|
|
143
149
|
)
|
|
144
150
|
}
|
|
@@ -151,7 +157,7 @@ export function VerifiedText(props: VerifiedTextProps) {
|
|
|
151
157
|
role={props.onHallucinationClick ? 'button' : undefined}
|
|
152
158
|
>
|
|
153
159
|
{seg.content}
|
|
154
|
-
<span class="text-xs" aria-label=
|
|
160
|
+
<span class="text-xs" aria-label={strings.unverifiedAria}>⚠️</span>
|
|
155
161
|
</span>
|
|
156
162
|
)
|
|
157
163
|
}}
|
|
@@ -172,8 +178,12 @@ export function VerifiedText(props: VerifiedTextProps) {
|
|
|
172
178
|
/>
|
|
173
179
|
</div>
|
|
174
180
|
<span>
|
|
175
|
-
{
|
|
176
|
-
|
|
181
|
+
{formatMCPUIString(strings.verifiedConfidence, {
|
|
182
|
+
pct: Math.round(props.validation.confidence * 100),
|
|
183
|
+
})}{' '}
|
|
184
|
+
{formatMCPUIString(strings.verifiedUnverifiedCount, {
|
|
185
|
+
count: props.validation.hallucinated.length,
|
|
186
|
+
})}
|
|
177
187
|
</span>
|
|
178
188
|
</div>
|
|
179
189
|
)}
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
import { Component, createMemo, Show } from 'solid-js'
|
|
9
9
|
import type { UIComponent, VideoComponentParams } from '../types'
|
|
10
10
|
import { ExpandableWrapper, useExpanded } from './ExpandableWrapper'
|
|
11
|
+
import { useMCPUIStrings } from '../context/MCPUIStringsContext'
|
|
12
|
+
import { useMCPUIConfig } from '../context/MCPUIConfigContext'
|
|
13
|
+
import { shouldSetCredentialless } from '../utils/iframe-coep'
|
|
14
|
+
import { IframeFallbackLink } from './IframeFallbackLink'
|
|
11
15
|
|
|
12
16
|
export interface VideoRendererProps {
|
|
13
17
|
/**
|
|
@@ -74,6 +78,8 @@ function parseVideoUrl(url: string): VideoInfo {
|
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
export const VideoRenderer: Component<VideoRendererProps> = (props) => {
|
|
81
|
+
const strings = useMCPUIStrings()
|
|
82
|
+
const config = useMCPUIConfig()
|
|
77
83
|
const params = () => props.params || (props.component?.params as VideoComponentParams)
|
|
78
84
|
const isExpanded = useExpanded()
|
|
79
85
|
|
|
@@ -135,9 +141,9 @@ export const VideoRenderer: Component<VideoRendererProps> = (props) => {
|
|
|
135
141
|
|
|
136
142
|
return (
|
|
137
143
|
<ExpandableWrapper
|
|
138
|
-
title={params()?.title ||
|
|
144
|
+
title={params()?.title || strings.videoTitle}
|
|
139
145
|
copyData={params()?.url || ''}
|
|
140
|
-
copyLabel=
|
|
146
|
+
copyLabel={strings.videoCopy}
|
|
141
147
|
toolbarVariant={props.toolbarVariant}
|
|
142
148
|
>
|
|
143
149
|
<div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${
|
|
@@ -168,22 +174,38 @@ export const VideoRenderer: Component<VideoRendererProps> = (props) => {
|
|
|
168
174
|
onError={handleVideoError}
|
|
169
175
|
>
|
|
170
176
|
<track kind="captions" />
|
|
171
|
-
|
|
177
|
+
{strings.videoUnsupported}
|
|
172
178
|
</video>
|
|
173
179
|
}
|
|
174
180
|
>
|
|
175
181
|
{/* YouTube/Vimeo embed */}
|
|
176
182
|
<iframe
|
|
177
183
|
src={embedUrl()!}
|
|
178
|
-
title={params()?.title ||
|
|
184
|
+
title={params()?.title || strings.videoTitle}
|
|
179
185
|
class="absolute inset-0 w-full h-full"
|
|
180
186
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
181
187
|
allowfullscreen
|
|
188
|
+
// v6.21.0 — youtube-nocookie / player.vimeo are not trusted hosts,
|
|
189
|
+
// so under COEP `credentialless` is what lets them load at all.
|
|
190
|
+
// `attr:` + `true | undefined` — see the note in `IframeRenderer`.
|
|
191
|
+
attr:credentialless={
|
|
192
|
+
// No sandbox here: a YouTube/Vimeo embed keeps its provider
|
|
193
|
+
// cookies, so `'auto'` leaves it alone and a COEP host opts in
|
|
194
|
+
// with `iframeCredentialless: 'always'`.
|
|
195
|
+
shouldSetCredentialless(embedUrl()!, config, {
|
|
196
|
+
sandboxedWithoutSameOrigin: false,
|
|
197
|
+
}) || undefined
|
|
198
|
+
}
|
|
182
199
|
loading="lazy"
|
|
183
200
|
/>
|
|
184
201
|
</Show>
|
|
185
202
|
</div>
|
|
186
203
|
|
|
204
|
+
{/* v6.21.0 — a COEP-blocked embed is silent; this link is the way out. */}
|
|
205
|
+
<Show when={embedUrl()}>
|
|
206
|
+
<IframeFallbackLink url={params()?.url || ''} />
|
|
207
|
+
</Show>
|
|
208
|
+
|
|
187
209
|
{/* Caption */}
|
|
188
210
|
<Show when={params()?.caption}>
|
|
189
211
|
<div class="px-4 py-3 border-t border-gray-200 dark:border-gray-700 flex-shrink-0">
|
|
@@ -1,3 +1,44 @@
|
|
|
1
|
+
import { formatMCPUIString } from '../utils/format-string';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Column headers and series names of the accessible chart data table.
|
|
5
|
+
*
|
|
6
|
+
* `chartToDataTable` is a pure helper with no access to `MCPUIStrings`, so
|
|
7
|
+
* the wording is injected: it takes an optional trailing `labels` partial,
|
|
8
|
+
* which `ChartJSRenderer` feeds from `useMCPUIStrings()`. Left out, the
|
|
9
|
+
* English defaults below apply — the pre-v6.20.0 behaviour.
|
|
10
|
+
*
|
|
11
|
+
* `x` / `y` / `r` stay untranslated on purpose: they are the Chart.js point
|
|
12
|
+
* property NAMES the cells mirror, not prose.
|
|
13
|
+
*
|
|
14
|
+
* @since v6.20.0
|
|
15
|
+
*/
|
|
16
|
+
export interface ChartDataTableLabels {
|
|
17
|
+
/** Series column of the per-point table. */
|
|
18
|
+
series: string;
|
|
19
|
+
/** Point-index column of the per-point table. */
|
|
20
|
+
point: string;
|
|
21
|
+
/** Label column (categorical table, and per-point table when labelled). */
|
|
22
|
+
label: string;
|
|
23
|
+
/** Fallback dataset name. Template — `{n}`. */
|
|
24
|
+
seriesName: string;
|
|
25
|
+
/** Chart.js point property names — machine tokens, rarely overridden. */
|
|
26
|
+
x: string;
|
|
27
|
+
y: string;
|
|
28
|
+
r: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** English defaults for {@link ChartDataTableLabels}. */
|
|
32
|
+
export const CHART_DATA_TABLE_LABELS: ChartDataTableLabels = {
|
|
33
|
+
series: 'Series',
|
|
34
|
+
point: 'Point',
|
|
35
|
+
label: 'Label',
|
|
36
|
+
seriesName: 'Series {n}',
|
|
37
|
+
x: 'x',
|
|
38
|
+
y: 'y',
|
|
39
|
+
r: 'r',
|
|
40
|
+
};
|
|
41
|
+
|
|
1
42
|
export interface ChartDataTable {
|
|
2
43
|
columns: string[];
|
|
3
44
|
rows: Array<Array<string | number>>;
|
|
@@ -41,37 +82,41 @@ function isPoint(value: unknown): value is Record<string, unknown> {
|
|
|
41
82
|
* coordinates. Categorical charts use a compact wide table; scatter, bubble,
|
|
42
83
|
* and object-valued line charts use one row per point so x/y/r remain distinct.
|
|
43
84
|
*/
|
|
44
|
-
export function chartToDataTable(
|
|
85
|
+
export function chartToDataTable(
|
|
86
|
+
params: ChartDataLike,
|
|
87
|
+
labels?: Partial<ChartDataTableLabels>
|
|
88
|
+
): ChartDataTable {
|
|
89
|
+
const l: ChartDataTableLabels = { ...CHART_DATA_TABLE_LABELS, ...labels };
|
|
45
90
|
const datasets = params.data?.datasets ?? [];
|
|
46
|
-
const
|
|
91
|
+
const dataLabels = params.data?.labels ?? [];
|
|
47
92
|
const pointData =
|
|
48
93
|
params.type === 'scatter' ||
|
|
49
94
|
params.type === 'bubble' ||
|
|
50
95
|
datasets.some((dataset) => dataset.data?.some(isPoint));
|
|
51
96
|
|
|
52
97
|
if (pointData) {
|
|
53
|
-
const hasLabels =
|
|
98
|
+
const hasLabels = dataLabels.length > 0;
|
|
54
99
|
const hasRadius =
|
|
55
100
|
params.type === 'bubble' ||
|
|
56
101
|
datasets.some((dataset) => dataset.data?.some((value) => isPoint(value) && 'r' in value));
|
|
57
102
|
const columns = [
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
...(hasLabels ? [
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
...(hasRadius ? [
|
|
103
|
+
l.series,
|
|
104
|
+
l.point,
|
|
105
|
+
...(hasLabels ? [l.label] : []),
|
|
106
|
+
l.x,
|
|
107
|
+
l.y,
|
|
108
|
+
...(hasRadius ? [l.r] : []),
|
|
64
109
|
];
|
|
65
110
|
const rows: Array<Array<string | number>> = [];
|
|
66
111
|
|
|
67
112
|
datasets.forEach((dataset, datasetIndex) => {
|
|
68
|
-
const series = dataset.label ||
|
|
113
|
+
const series = dataset.label || formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });
|
|
69
114
|
(dataset.data ?? []).forEach((value, pointIndex) => {
|
|
70
115
|
const point = isPoint(value) ? value : { y: value };
|
|
71
116
|
rows.push([
|
|
72
117
|
series,
|
|
73
118
|
pointIndex + 1,
|
|
74
|
-
...(hasLabels ? [tableCell(
|
|
119
|
+
...(hasLabels ? [tableCell(dataLabels[pointIndex])] : []),
|
|
75
120
|
tableCell(point.x),
|
|
76
121
|
tableCell(point.y),
|
|
77
122
|
...(hasRadius ? [tableCell(point.r)] : []),
|
|
@@ -82,13 +127,22 @@ export function chartToDataTable(params: ChartDataLike): ChartDataTable {
|
|
|
82
127
|
return { columns, rows };
|
|
83
128
|
}
|
|
84
129
|
|
|
85
|
-
const rowCount = Math.max(
|
|
86
|
-
|
|
130
|
+
const rowCount = Math.max(
|
|
131
|
+
dataLabels.length,
|
|
132
|
+
...datasets.map((dataset) => dataset.data?.length ?? 0),
|
|
133
|
+
0
|
|
134
|
+
);
|
|
135
|
+
const columns = [
|
|
136
|
+
l.label,
|
|
137
|
+
...datasets.map(
|
|
138
|
+
(dataset, index) => dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 })
|
|
139
|
+
),
|
|
140
|
+
];
|
|
87
141
|
const rows: Array<Array<string | number>> = [];
|
|
88
142
|
|
|
89
143
|
for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
|
|
90
144
|
rows.push([
|
|
91
|
-
tableCell(
|
|
145
|
+
tableCell(dataLabels[rowIndex] ?? rowIndex + 1),
|
|
92
146
|
...datasets.map((dataset) => tableCell(dataset.data?.[rowIndex])),
|
|
93
147
|
]);
|
|
94
148
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { createContext, createSignal, useContext, ParentComponent, Accessor } from 'solid-js'
|
|
7
|
+
import { useMCPUIStrings } from './MCPUIStringsContext'
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Action request payload
|
|
@@ -223,6 +224,8 @@ const defaultExecutor = async (request: ActionRequest): Promise<ActionResult> =>
|
|
|
223
224
|
* ```
|
|
224
225
|
*/
|
|
225
226
|
export const MCPActionProvider: ParentComponent<MCPActionProviderProps> = (props) => {
|
|
227
|
+
// The error of a failed action can be rendered by FormRenderer.
|
|
228
|
+
const strings = useMCPUIStrings()
|
|
226
229
|
const [isExecuting, setIsExecuting] = createSignal(false)
|
|
227
230
|
const [lastResult, setLastResult] = createSignal<ActionResult>()
|
|
228
231
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -270,7 +273,7 @@ export const MCPActionProvider: ParentComponent<MCPActionProviderProps> = (props
|
|
|
270
273
|
} catch (error) {
|
|
271
274
|
const errorResult: ActionResult = {
|
|
272
275
|
success: false,
|
|
273
|
-
error: error instanceof Error ? error.message :
|
|
276
|
+
error: error instanceof Error ? error.message : strings.errorUnknown,
|
|
274
277
|
timestamp: new Date().toISOString(),
|
|
275
278
|
toolName: request.toolName,
|
|
276
279
|
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPUIConfigContext — host-level rendering policy for the library's iframes.
|
|
3
|
+
*
|
|
4
|
+
* @since v6.21.0
|
|
5
|
+
*
|
|
6
|
+
* ## Why
|
|
7
|
+
*
|
|
8
|
+
* A host that serves `Cross-Origin-Embedder-Policy: credentialless` makes the
|
|
9
|
+
* browser refuse every cross-origin iframe whose own document does not send a
|
|
10
|
+
* COEP header — which is YouTube, Vimeo, Google Docs, Notion and nearly all of
|
|
11
|
+
* `DEFAULT_IFRAME_DOMAINS`. The escape hatch is the boolean HTML attribute
|
|
12
|
+
* `credentialless` on the `<iframe>` itself: the document then loads, but
|
|
13
|
+
* without access to the cookies and storage of its own origin.
|
|
14
|
+
*
|
|
15
|
+
* That trade-off is free for a public video or chart and fatal for an
|
|
16
|
+
* authenticated embed, so the library keys it on the distinction it already
|
|
17
|
+
* makes: `TRUSTED_IFRAME_DOMAINS` (the hosts that receive `allow-same-origin`
|
|
18
|
+
* because they need their own cookies) do NOT get the attribute; everything
|
|
19
|
+
* else does. This context lets a host override that, add its own trusted
|
|
20
|
+
* hosts, and control the "open in a new tab" fallback link.
|
|
21
|
+
*
|
|
22
|
+
* ## Scope — policy only, NOT strings
|
|
23
|
+
*
|
|
24
|
+
* Text lives in `MCPUIStrings` (`MCPUIStringsContext`). This context carries
|
|
25
|
+
* only behavioural switches, and like the strings context every renderer works
|
|
26
|
+
* standalone: with no provider mounted, `DEFAULT_MCPUI_CONFIG` applies.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* import { MCPUIConfigProvider } from '@seed-ship/mcp-ui-solid'
|
|
31
|
+
*
|
|
32
|
+
* <MCPUIConfigProvider config={{ customTrustedIframeDomains: ['embed.acme.com'] }}>
|
|
33
|
+
* <App />
|
|
34
|
+
* </MCPUIConfigProvider>
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { createContext, mergeProps, useContext, type JSX } from 'solid-js'
|
|
39
|
+
import type { IframePolicy } from '../types'
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Host-level rendering policy. Every field has a default — a provider passes
|
|
43
|
+
* a partial override.
|
|
44
|
+
*/
|
|
45
|
+
export interface MCPUIConfig {
|
|
46
|
+
/**
|
|
47
|
+
* When the library puts the boolean `credentialless` attribute on an
|
|
48
|
+
* `<iframe>` it renders.
|
|
49
|
+
*
|
|
50
|
+
* - `'auto'` (default) — on every iframe whose host is NOT in
|
|
51
|
+
* `TRUSTED_IFRAME_DOMAINS` (plus `customTrustedIframeDomains`). Those
|
|
52
|
+
* hosts already ran without cookies, since their sandbox has no
|
|
53
|
+
* `allow-same-origin`; the attribute is what unblocks them under COEP.
|
|
54
|
+
* - `'always'` — on every iframe, trusted hosts included. An authenticated
|
|
55
|
+
* embed will then render its login screen.
|
|
56
|
+
* - `'never'` — never. The right value for a host that sends no COEP header
|
|
57
|
+
* and does not want its embeds to lose their cookies.
|
|
58
|
+
*
|
|
59
|
+
* Chrome/Edge 110+ honour the attribute; Firefox ignores it (iframes stay
|
|
60
|
+
* blocked while the host sends COEP); Safari ignores the COEP value itself,
|
|
61
|
+
* so nothing is blocked there in the first place.
|
|
62
|
+
*/
|
|
63
|
+
iframeCredentialless: 'auto' | 'always' | 'never'
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Extra hosts treated as trusted, on top of `TRUSTED_IFRAME_DOMAINS`:
|
|
67
|
+
* no `credentialless` attribute, and `allow-same-origin` in the sandbox.
|
|
68
|
+
* A subdomain of a listed host matches too.
|
|
69
|
+
*
|
|
70
|
+
* This only RECLASSIFIES a host the allow-list already accepts. To render an
|
|
71
|
+
* iframe whose host is outside `DEFAULT_IFRAME_DOMAINS`, add it to
|
|
72
|
+
* {@link MCPUIConfig.customIframeDomains} with `iframePolicy: 'extend'`.
|
|
73
|
+
*/
|
|
74
|
+
customTrustedIframeDomains: string[]
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* How `UIResourceRenderer` validates an `iframe` component's host:
|
|
78
|
+
* `'strict'` (default) accepts `DEFAULT_IFRAME_DOMAINS` only, `'extend'`
|
|
79
|
+
* also accepts {@link MCPUIConfig.customIframeDomains}.
|
|
80
|
+
*/
|
|
81
|
+
iframePolicy: IframePolicy
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Extra hosts the allow-list accepts when `iframePolicy` is `'extend'`.
|
|
85
|
+
* Without this, a component pointing at an unlisted host is replaced by the
|
|
86
|
+
* validation card before any renderer runs.
|
|
87
|
+
*/
|
|
88
|
+
customIframeDomains: string[]
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* When the library renders an "open in a new tab" link under an embed
|
|
92
|
+
* (`strings.iframeOpenInNewTab`).
|
|
93
|
+
*
|
|
94
|
+
* A COEP-blocked iframe fires no event the parent page can observe, so
|
|
95
|
+
* without this the user sees an unexplained blank frame.
|
|
96
|
+
*
|
|
97
|
+
* - `'auto'` (default) — only when the page is cross-origin isolated
|
|
98
|
+
* (`window.crossOriginIsolated`). That flag needs COOP `same-origin` AND
|
|
99
|
+
* COEP, so a host that sends COEP alone still blocks embeds while the
|
|
100
|
+
* flag is false: set `'always'` there. Read after mount, never during
|
|
101
|
+
* render, so SSR markup and hydration agree.
|
|
102
|
+
* - `'always'` / `'never'` — unconditional.
|
|
103
|
+
*/
|
|
104
|
+
iframeFallbackLink: 'auto' | 'always' | 'never'
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Defaults. Chosen so a host that sends no COEP header sees no change from
|
|
109
|
+
* 6.20.0 apart from the fallback link, which `'auto'` keeps hidden there.
|
|
110
|
+
*/
|
|
111
|
+
export const DEFAULT_MCPUI_CONFIG: MCPUIConfig = {
|
|
112
|
+
iframeCredentialless: 'auto',
|
|
113
|
+
customTrustedIframeDomains: [],
|
|
114
|
+
iframePolicy: 'strict',
|
|
115
|
+
customIframeDomains: [],
|
|
116
|
+
iframeFallbackLink: 'auto',
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const MCPUIConfigContext = createContext<MCPUIConfig>(DEFAULT_MCPUI_CONFIG)
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Reads the active host config. Returns `DEFAULT_MCPUI_CONFIG` when no
|
|
123
|
+
* `<MCPUIConfigProvider>` is mounted above.
|
|
124
|
+
*/
|
|
125
|
+
export function useMCPUIConfig(): MCPUIConfig {
|
|
126
|
+
return mergeProps(DEFAULT_MCPUI_CONFIG, useContext(MCPUIConfigContext))
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface MCPUIConfigProviderProps {
|
|
130
|
+
/**
|
|
131
|
+
* Partial override of the host config. Any key left unset falls back to
|
|
132
|
+
* `DEFAULT_MCPUI_CONFIG`.
|
|
133
|
+
*/
|
|
134
|
+
config?: Partial<MCPUIConfig>
|
|
135
|
+
children: JSX.Element
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Provides the host config to every MCP-UI renderer below it.
|
|
140
|
+
* Merges the partial `config` override over the defaults.
|
|
141
|
+
*/
|
|
142
|
+
export function MCPUIConfigProvider(props: MCPUIConfigProviderProps): JSX.Element {
|
|
143
|
+
// The function source keeps replacement `config` objects reactive while
|
|
144
|
+
// mergeProps fills any omitted key without taking a one-time snapshot.
|
|
145
|
+
const value = mergeProps(DEFAULT_MCPUI_CONFIG, () => props.config)
|
|
146
|
+
return (
|
|
147
|
+
<MCPUIConfigContext.Provider value={value}>
|
|
148
|
+
{props.children}
|
|
149
|
+
</MCPUIConfigContext.Provider>
|
|
150
|
+
)
|
|
151
|
+
}
|