feat(ui): support prefersBorder option for MCP Apps (#6465)
This commit is contained in:
@@ -32,6 +32,12 @@ interface McpAppRendererProps {
|
|||||||
append?: (text: string) => void;
|
append?: (text: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ResourceData {
|
||||||
|
html: string | null;
|
||||||
|
csp: CspMetadata | null;
|
||||||
|
prefersBorder: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export default function McpAppRenderer({
|
export default function McpAppRenderer({
|
||||||
resourceUri,
|
resourceUri,
|
||||||
extensionName,
|
extensionName,
|
||||||
@@ -42,8 +48,11 @@ export default function McpAppRenderer({
|
|||||||
toolCancelled,
|
toolCancelled,
|
||||||
append,
|
append,
|
||||||
}: McpAppRendererProps) {
|
}: McpAppRendererProps) {
|
||||||
const [resourceHtml, setResourceHtml] = useState<string | null>(null);
|
const [resource, setResource] = useState<ResourceData>({
|
||||||
const [resourceCsp, setResourceCsp] = useState<CspMetadata | null>(null);
|
html: null,
|
||||||
|
csp: null,
|
||||||
|
prefersBorder: true,
|
||||||
|
});
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [iframeHeight, setIframeHeight] = useState(DEFAULT_IFRAME_HEIGHT);
|
const [iframeHeight, setIframeHeight] = useState(DEFAULT_IFRAME_HEIGHT);
|
||||||
|
|
||||||
@@ -60,11 +69,15 @@ export default function McpAppRenderer({
|
|||||||
|
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
const content = response.data;
|
const content = response.data;
|
||||||
|
const meta = content._meta as
|
||||||
|
| { ui?: { csp?: CspMetadata; prefersBorder?: boolean } }
|
||||||
|
| undefined;
|
||||||
|
|
||||||
setResourceHtml(content.text);
|
setResource({
|
||||||
|
html: content.text,
|
||||||
const meta = content._meta as { ui?: { csp?: CspMetadata } } | undefined;
|
csp: meta?.ui?.csp || null,
|
||||||
setResourceCsp(meta?.ui?.csp || null);
|
prefersBorder: meta?.ui?.prefersBorder ?? true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err instanceof Error ? err.message : 'Failed to load resource');
|
setError(err instanceof Error ? err.message : 'Failed to load resource');
|
||||||
@@ -161,8 +174,8 @@ export default function McpAppRenderer({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { iframeRef, proxyUrl } = useSandboxBridge({
|
const { iframeRef, proxyUrl } = useSandboxBridge({
|
||||||
resourceHtml: resourceHtml || '',
|
resourceHtml: resource.html || '',
|
||||||
resourceCsp,
|
resourceCsp: resource.csp,
|
||||||
resourceUri,
|
resourceUri,
|
||||||
toolInput,
|
toolInput,
|
||||||
toolInputPartial,
|
toolInputPartial,
|
||||||
@@ -174,25 +187,20 @@ export default function McpAppRenderer({
|
|||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<div className="mt-3 p-4 border border-red-500 rounded-lg bg-red-50 dark:bg-red-900/20">
|
<div className="p-4 border border-red-500 rounded-lg bg-red-50 dark:bg-red-900/20">
|
||||||
<div className="text-red-700 dark:text-red-300">Failed to load MCP app: {error}</div>
|
<div className="text-red-700 dark:text-red-300">Failed to load MCP app: {error}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resourceHtml) {
|
|
||||||
return (
|
|
||||||
<div className="mt-3 p-4 border border-borderSubtle rounded-lg bg-bgApp">
|
|
||||||
<div className="flex items-center justify-center" style={{ minHeight: '200px' }}>
|
|
||||||
Loading MCP app...
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn('mt-3 bg-bgApp', 'border border-borderSubtle rounded-lg overflow-hidden')}>
|
<div
|
||||||
{proxyUrl ? (
|
className={cn(
|
||||||
|
'bg-bgApp overflow-hidden',
|
||||||
|
resource.prefersBorder ? 'border border-borderSubtle rounded-lg' : 'my-6'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{resource.html && proxyUrl ? (
|
||||||
<iframe
|
<iframe
|
||||||
ref={iframeRef}
|
ref={iframeRef}
|
||||||
src={proxyUrl}
|
src={proxyUrl}
|
||||||
@@ -205,16 +213,8 @@ export default function McpAppRenderer({
|
|||||||
sandbox="allow-scripts allow-same-origin"
|
sandbox="allow-scripts allow-same-origin"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div className="flex items-center justify-center p-4" style={{ minHeight: '200px' }}>
|
||||||
style={{
|
Loading MCP app...
|
||||||
width: '100%',
|
|
||||||
minHeight: '200px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Loading...
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user