sunpeak 0.18.2 → 0.18.7
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/bin/commands/dev.mjs +6 -2
- package/bin/commands/inspect.mjs +405 -5
- package/bin/commands/new.mjs +5 -0
- package/bin/lib/dev-overlay.mjs +50 -0
- package/bin/lib/live/live-config.d.mts +3 -0
- package/bin/lib/live/live-config.mjs +3 -1
- package/bin/lib/sandbox-server.mjs +11 -1
- package/dist/chatgpt/index.cjs +2 -2
- package/dist/chatgpt/index.js +2 -2
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-request-teardown.d.ts +21 -0
- package/dist/host/chatgpt/index.cjs +1 -1
- package/dist/host/chatgpt/index.js +1 -1
- package/dist/index.cjs +110 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +68 -31
- package/dist/index.js.map +1 -1
- package/dist/inspector/hosts.d.ts +12 -0
- package/dist/inspector/index.cjs +2 -2
- package/dist/inspector/index.js +2 -2
- package/dist/inspector/inspector-url.d.ts +13 -0
- package/dist/inspector/mcp-app-host.d.ts +3 -0
- package/dist/inspector/simple-sidebar.d.ts +1 -1
- package/dist/inspector/use-inspector-state.d.ts +2 -0
- package/dist/inspector/use-mcp-connection.d.ts +9 -1
- package/dist/{inspector-CByJjmPD.cjs → inspector-CKc58UuI.cjs} +557 -136
- package/dist/inspector-CKc58UuI.cjs.map +1 -0
- package/dist/{inspector-ClhpqKLi.js → inspector-DZrN0kej.js} +556 -135
- package/dist/inspector-DZrN0kej.js.map +1 -0
- package/dist/{inspector-url-7qhtJwY6.cjs → inspector-url-C3LTKgXt.cjs} +3 -1
- package/dist/inspector-url-C3LTKgXt.cjs.map +1 -0
- package/dist/{inspector-url-DuEFmxLP.js → inspector-url-CyQcuBI9.js} +3 -1
- package/dist/inspector-url-CyQcuBI9.js.map +1 -0
- package/dist/mcp/index.cjs +119 -40
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +116 -37
- package/dist/mcp/index.js.map +1 -1
- package/dist/style.css +12 -0
- package/dist/{use-app-X7JbGskk.js → use-app-BNbz1uzj.js} +51 -42
- package/dist/use-app-BNbz1uzj.js.map +1 -0
- package/dist/{use-app-D2h-aiyr.cjs → use-app-Dqh20JPP.cjs} +93 -72
- package/dist/use-app-Dqh20JPP.cjs.map +1 -0
- package/package.json +2 -2
- package/template/dist/albums/albums.html +3 -3
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.html +3 -3
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.html +3 -3
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.html +3 -3
- package/template/dist/review/review.json +1 -1
- package/template/node_modules/.vite/deps/_metadata.json +3 -3
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +51 -42
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +56 -50
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +52 -43
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/_metadata.json +22 -22
- package/template/tests/e2e/albums.spec.ts +20 -16
- package/template/tests/e2e/carousel.spec.ts +1 -1
- package/template/tests/e2e/dev-overlay.spec.ts +118 -0
- package/template/tests/e2e/helpers.ts +13 -0
- package/template/tests/e2e/map.spec.ts +1 -1
- package/template/tests/e2e/review.spec.ts +1 -1
- package/template/tests/live/albums.spec.ts +10 -0
- package/template/tests/live/playwright.config.ts +1 -1
- package/dist/inspector-CByJjmPD.cjs.map +0 -1
- package/dist/inspector-ClhpqKLi.js.map +0 -1
- package/dist/inspector-url-7qhtJwY6.cjs.map +0 -1
- package/dist/inspector-url-DuEFmxLP.js.map +0 -1
- package/dist/use-app-D2h-aiyr.cjs.map +0 -1
- package/dist/use-app-X7JbGskk.js.map +0 -1
|
@@ -487,7 +487,9 @@ function ClaudeConversation({ children, screenWidth, displayMode, platform, onRe
|
|
|
487
487
|
style: {
|
|
488
488
|
transform: "translate(0)",
|
|
489
489
|
backgroundColor: "var(--sim-bg-conversation, var(--color-background-primary))",
|
|
490
|
-
color: "var(--color-text-primary)"
|
|
490
|
+
color: "var(--color-text-primary)",
|
|
491
|
+
fontFamily: "var(--font-sans)",
|
|
492
|
+
WebkitFontSmoothing: "antialiased"
|
|
491
493
|
},
|
|
492
494
|
children: [
|
|
493
495
|
isFullscreen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -521,17 +523,20 @@ function ClaudeConversation({ children, screenWidth, displayMode, platform, onRe
|
|
|
521
523
|
style: { backgroundColor: "var(--sim-bg-conversation, var(--color-background-primary))" },
|
|
522
524
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
523
525
|
className: "max-w-[48rem] mx-auto",
|
|
524
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
525
|
-
|
|
526
|
-
name: "userInput",
|
|
527
|
-
disabled: true,
|
|
528
|
-
placeholder: "Reply to sunpeak...",
|
|
529
|
-
className: "w-full rounded-xl px-4 py-2.5 text-sm",
|
|
526
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
527
|
+
className: "relative rounded-[20px] px-4 py-2.5",
|
|
530
528
|
style: {
|
|
531
529
|
backgroundColor: "var(--sim-bg-reply-input, var(--color-background-secondary))",
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
530
|
+
boxShadow: "0 4px 20px rgba(0, 0, 0, 0.035), 0 0 0 0.5px var(--color-border-tertiary)"
|
|
531
|
+
},
|
|
532
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
533
|
+
className: "w-full text-base outline-none opacity-50",
|
|
534
|
+
style: {
|
|
535
|
+
lineHeight: "1.4",
|
|
536
|
+
color: "var(--color-text-tertiary)"
|
|
537
|
+
},
|
|
538
|
+
children: "Reply to sunpeak..."
|
|
539
|
+
})
|
|
535
540
|
})
|
|
536
541
|
})
|
|
537
542
|
})
|
|
@@ -559,8 +564,14 @@ function ClaudeConversation({ children, screenWidth, displayMode, platform, onRe
|
|
|
559
564
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
560
565
|
className: "max-w-[48rem] mx-auto flex justify-end",
|
|
561
566
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
562
|
-
className: "inline-
|
|
563
|
-
style: {
|
|
567
|
+
className: "inline-flex rounded-xl max-w-[85%] break-words",
|
|
568
|
+
style: {
|
|
569
|
+
padding: "10px 16px",
|
|
570
|
+
lineHeight: "22.4px",
|
|
571
|
+
fontSize: "16px",
|
|
572
|
+
fontWeight: 430,
|
|
573
|
+
backgroundColor: "var(--sim-bg-user-bubble, var(--color-background-tertiary))"
|
|
574
|
+
},
|
|
564
575
|
children: userMessage
|
|
565
576
|
})
|
|
566
577
|
})
|
|
@@ -630,17 +641,18 @@ function ClaudeConversation({ children, screenWidth, displayMode, platform, onRe
|
|
|
630
641
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
631
642
|
className: "max-w-[48rem] mx-auto px-4 py-4",
|
|
632
643
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
633
|
-
className: "relative",
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
className: "w-full
|
|
644
|
+
className: "relative rounded-[20px] px-4 py-2.5",
|
|
645
|
+
style: {
|
|
646
|
+
backgroundColor: "var(--sim-bg-reply-input, var(--color-background-secondary))",
|
|
647
|
+
boxShadow: "0 4px 20px rgba(0, 0, 0, 0.035), 0 0 0 0.5px var(--color-border-tertiary)"
|
|
648
|
+
},
|
|
649
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
650
|
+
className: "w-full text-base outline-none opacity-50",
|
|
640
651
|
style: {
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
652
|
+
lineHeight: "1.4",
|
|
653
|
+
color: "var(--color-text-tertiary)"
|
|
654
|
+
},
|
|
655
|
+
children: "Reply to sunpeak..."
|
|
644
656
|
})
|
|
645
657
|
})
|
|
646
658
|
})
|
|
@@ -651,17 +663,32 @@ function ClaudeConversation({ children, screenWidth, displayMode, platform, onRe
|
|
|
651
663
|
}
|
|
652
664
|
//#endregion
|
|
653
665
|
//#region src/claude/claude-host.ts
|
|
666
|
+
/**
|
|
667
|
+
* Claude host version info — matches what Claude reports via the MCP protocol.
|
|
668
|
+
* Verified against production Claude on 2026-03-25.
|
|
669
|
+
*/
|
|
654
670
|
var CLAUDE_HOST_INFO = {
|
|
655
671
|
name: "Claude",
|
|
656
672
|
version: "1.0.0"
|
|
657
673
|
};
|
|
674
|
+
/**
|
|
675
|
+
* Claude host capabilities — matches what Claude reports via the MCP protocol.
|
|
676
|
+
* Verified against production Claude on 2026-03-25.
|
|
677
|
+
*
|
|
678
|
+
* Notable: Claude supports downloadFile, updateModelContext.image, and
|
|
679
|
+
* message.text. serverTools and serverResources both report listChanged.
|
|
680
|
+
* No sandbox.permissions (no microphone etc.). No PiP display mode.
|
|
681
|
+
*/
|
|
658
682
|
var CLAUDE_HOST_CAPABILITIES = {
|
|
659
683
|
openLinks: {},
|
|
660
|
-
serverTools: {},
|
|
661
|
-
serverResources: {},
|
|
662
684
|
downloadFile: {},
|
|
685
|
+
serverTools: { listChanged: true },
|
|
686
|
+
serverResources: { listChanged: true },
|
|
663
687
|
logging: {},
|
|
664
|
-
updateModelContext: {
|
|
688
|
+
updateModelContext: {
|
|
689
|
+
text: {},
|
|
690
|
+
image: {}
|
|
691
|
+
},
|
|
665
692
|
message: { text: {} },
|
|
666
693
|
sandbox: {}
|
|
667
694
|
};
|
|
@@ -680,35 +707,100 @@ registerHostShell({
|
|
|
680
707
|
applyTheme: applyClaudeTheme,
|
|
681
708
|
hostInfo: CLAUDE_HOST_INFO,
|
|
682
709
|
hostCapabilities: CLAUDE_HOST_CAPABILITIES,
|
|
683
|
-
userAgent: "claude",
|
|
684
710
|
styleVariables: {
|
|
685
711
|
...DEFAULT_STYLE_VARIABLES,
|
|
686
|
-
"--color-background-primary": "light-dark(
|
|
687
|
-
"--color-background-secondary": "light-dark(
|
|
688
|
-
"--color-background-tertiary": "light-dark(
|
|
689
|
-
"--color-background-inverse": "light-dark(
|
|
690
|
-
"--color-
|
|
691
|
-
"--color-
|
|
692
|
-
"--color-
|
|
693
|
-
"--color-
|
|
694
|
-
"--color-
|
|
695
|
-
"--color-
|
|
696
|
-
"--color-
|
|
712
|
+
"--color-background-primary": "light-dark(rgba(255, 255, 255, 1), rgba(48, 48, 46, 1))",
|
|
713
|
+
"--color-background-secondary": "light-dark(rgba(245, 244, 237, 1), rgba(38, 38, 36, 1))",
|
|
714
|
+
"--color-background-tertiary": "light-dark(rgba(250, 249, 245, 1), rgba(20, 20, 19, 1))",
|
|
715
|
+
"--color-background-inverse": "light-dark(rgba(20, 20, 19, 1), rgba(250, 249, 245, 1))",
|
|
716
|
+
"--color-background-ghost": "light-dark(rgba(255, 255, 255, 0), rgba(48, 48, 46, 0))",
|
|
717
|
+
"--color-background-info": "light-dark(rgba(214, 228, 246, 1), rgba(37, 62, 95, 1))",
|
|
718
|
+
"--color-background-danger": "light-dark(rgba(247, 236, 236, 1), rgba(96, 42, 40, 1))",
|
|
719
|
+
"--color-background-success": "light-dark(rgba(233, 241, 220, 1), rgba(27, 70, 20, 1))",
|
|
720
|
+
"--color-background-warning": "light-dark(rgba(246, 238, 223, 1), rgba(72, 58, 15, 1))",
|
|
721
|
+
"--color-background-disabled": "light-dark(rgba(255, 255, 255, 0.5), rgba(48, 48, 46, 0.5))",
|
|
722
|
+
"--color-text-primary": "light-dark(rgba(20, 20, 19, 1), rgba(250, 249, 245, 1))",
|
|
723
|
+
"--color-text-secondary": "light-dark(rgba(61, 61, 58, 1), rgba(194, 192, 182, 1))",
|
|
724
|
+
"--color-text-tertiary": "light-dark(rgba(115, 114, 108, 1), rgba(156, 154, 146, 1))",
|
|
725
|
+
"--color-text-inverse": "light-dark(rgba(255, 255, 255, 1), rgba(20, 20, 19, 1))",
|
|
726
|
+
"--color-text-ghost": "light-dark(rgba(115, 114, 108, 0.5), rgba(156, 154, 146, 0.5))",
|
|
727
|
+
"--color-text-info": "light-dark(rgba(50, 102, 173, 1), rgba(128, 170, 221, 1))",
|
|
728
|
+
"--color-text-danger": "light-dark(rgba(127, 44, 40, 1), rgba(238, 136, 132, 1))",
|
|
729
|
+
"--color-text-success": "light-dark(rgba(38, 91, 25, 1), rgba(122, 185, 72, 1))",
|
|
730
|
+
"--color-text-warning": "light-dark(rgba(90, 72, 21, 1), rgba(209, 160, 65, 1))",
|
|
731
|
+
"--color-text-disabled": "light-dark(rgba(20, 20, 19, 0.5), rgba(250, 249, 245, 0.5))",
|
|
732
|
+
"--color-border-primary": "light-dark(rgba(31, 30, 29, 0.4), rgba(222, 220, 209, 0.4))",
|
|
733
|
+
"--color-border-secondary": "light-dark(rgba(31, 30, 29, 0.3), rgba(222, 220, 209, 0.3))",
|
|
734
|
+
"--color-border-tertiary": "light-dark(rgba(31, 30, 29, 0.15), rgba(222, 220, 209, 0.15))",
|
|
735
|
+
"--color-border-inverse": "light-dark(rgba(255, 255, 255, 0.3), rgba(20, 20, 19, 0.15))",
|
|
736
|
+
"--color-border-ghost": "light-dark(rgba(31, 30, 29, 0), rgba(222, 220, 209, 0))",
|
|
737
|
+
"--color-border-info": "light-dark(rgba(70, 130, 213, 1), rgba(70, 130, 213, 1))",
|
|
738
|
+
"--color-border-danger": "light-dark(rgba(167, 61, 57, 1), rgba(205, 92, 88, 1))",
|
|
739
|
+
"--color-border-success": "light-dark(rgba(67, 116, 38, 1), rgba(89, 145, 48, 1))",
|
|
740
|
+
"--color-border-warning": "light-dark(rgba(128, 92, 31, 1), rgba(168, 120, 41, 1))",
|
|
741
|
+
"--color-border-disabled": "light-dark(rgba(31, 30, 29, 0.1), rgba(222, 220, 209, 0.1))",
|
|
742
|
+
"--color-ring-primary": "light-dark(rgba(20, 20, 19, 0.7), rgba(250, 249, 245, 0.7))",
|
|
743
|
+
"--color-ring-secondary": "light-dark(rgba(61, 61, 58, 0.7), rgba(194, 192, 182, 0.7))",
|
|
744
|
+
"--color-ring-inverse": "light-dark(rgba(255, 255, 255, 0.7), rgba(20, 20, 19, 0.7))",
|
|
745
|
+
"--color-ring-info": "light-dark(rgba(50, 102, 173, 0.5), rgba(128, 170, 221, 0.5))",
|
|
746
|
+
"--color-ring-danger": "light-dark(rgba(167, 61, 57, 0.5), rgba(205, 92, 88, 0.5))",
|
|
747
|
+
"--color-ring-success": "light-dark(rgba(67, 116, 38, 0.5), rgba(89, 145, 48, 0.5))",
|
|
748
|
+
"--color-ring-warning": "light-dark(rgba(128, 92, 31, 0.5), rgba(168, 120, 41, 0.5))",
|
|
749
|
+
"--font-sans": "\"Anthropic Sans\", system-ui, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif",
|
|
750
|
+
"--font-mono": "ui-monospace, monospace",
|
|
751
|
+
"--font-text-xs-size": "12px",
|
|
752
|
+
"--font-text-sm-size": "14px",
|
|
753
|
+
"--font-text-md-size": "16px",
|
|
754
|
+
"--font-text-lg-size": "20px",
|
|
755
|
+
"--font-heading-xs-size": "12px",
|
|
756
|
+
"--font-heading-sm-size": "14px",
|
|
757
|
+
"--font-heading-md-size": "16px",
|
|
758
|
+
"--font-heading-lg-size": "20px",
|
|
759
|
+
"--font-heading-xl-size": "24px",
|
|
760
|
+
"--font-heading-2xl-size": "28px",
|
|
761
|
+
"--font-heading-3xl-size": "36px",
|
|
762
|
+
"--font-text-md-line-height": "1.4",
|
|
763
|
+
"--font-text-lg-line-height": "1.25",
|
|
764
|
+
"--font-heading-lg-line-height": "1.25",
|
|
765
|
+
"--font-heading-2xl-line-height": "1.1",
|
|
766
|
+
"--font-heading-3xl-line-height": "1",
|
|
767
|
+
"--border-radius-xs": "4px",
|
|
768
|
+
"--border-radius-sm": "6px",
|
|
769
|
+
"--border-radius-md": "8px",
|
|
770
|
+
"--border-radius-lg": "10px",
|
|
771
|
+
"--border-width-regular": "0.5px"
|
|
697
772
|
},
|
|
698
773
|
pageStyles: {
|
|
699
|
-
"--sim-bg-sidebar": "light-dark(
|
|
700
|
-
"--sim-bg-conversation": "light-dark(
|
|
701
|
-
"--sim-bg-user-bubble": "light-dark(
|
|
702
|
-
"--sim-bg-reply-input": "light-dark(
|
|
703
|
-
}
|
|
774
|
+
"--sim-bg-sidebar": "light-dark(rgb(250, 249, 245), rgb(38, 38, 36))",
|
|
775
|
+
"--sim-bg-conversation": "light-dark(rgb(250, 249, 245), rgb(38, 38, 36))",
|
|
776
|
+
"--sim-bg-user-bubble": "light-dark(rgb(240, 238, 230), rgb(20, 20, 19))",
|
|
777
|
+
"--sim-bg-reply-input": "light-dark(rgb(255, 255, 255), rgb(48, 48, 46))"
|
|
778
|
+
},
|
|
779
|
+
availableDisplayModes: ["inline", "fullscreen"],
|
|
780
|
+
fontCss: `@font-face {
|
|
781
|
+
font-family: "Anthropic Sans";
|
|
782
|
+
src: url("https://assets-proxy.anthropic.com/claude-ai/v2/assets/v1/cc27851ad-CFxw3nG7.woff2") format("woff2");
|
|
783
|
+
font-weight: 300 800;
|
|
784
|
+
font-style: normal;
|
|
785
|
+
font-display: swap;
|
|
786
|
+
font-feature-settings: "dlig" 0;
|
|
787
|
+
}
|
|
788
|
+
@font-face {
|
|
789
|
+
font-family: "Anthropic Sans";
|
|
790
|
+
src: url("https://assets-proxy.anthropic.com/claude-ai/v2/assets/v1/c9d3a3a49-BI1hrwN4.woff2") format("woff2");
|
|
791
|
+
font-weight: 300 800;
|
|
792
|
+
font-style: italic;
|
|
793
|
+
font-display: swap;
|
|
794
|
+
font-feature-settings: "dlig" 0;
|
|
795
|
+
}`
|
|
704
796
|
});
|
|
705
797
|
//#endregion
|
|
706
|
-
//#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.
|
|
707
|
-
var G = "2026-01-26",
|
|
798
|
+
//#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.3.1_@modelcontextprotocol+sdk@1.27.1_zod@4.3.6__react-_cd1fb28fd87e0bddd0a29eba0721855d/node_modules/@modelcontextprotocol/ext-apps/dist/src/app-bridge.js
|
|
799
|
+
var G = "2026-01-26", p = require_protocol.union([require_protocol.literal("light"), require_protocol.literal("dark")]).describe("Color theme preference for the host environment."), D = require_protocol.union([
|
|
708
800
|
require_protocol.literal("inline"),
|
|
709
801
|
require_protocol.literal("fullscreen"),
|
|
710
802
|
require_protocol.literal("pip")
|
|
711
|
-
]).describe("Display mode for UI presentation."),
|
|
803
|
+
]).describe("Display mode for UI presentation."), IQ = require_protocol.union([
|
|
712
804
|
require_protocol.literal("--color-background-primary"),
|
|
713
805
|
require_protocol.literal("--color-background-secondary"),
|
|
714
806
|
require_protocol.literal("--color-background-tertiary"),
|
|
@@ -785,7 +877,7 @@ var G = "2026-01-26", m = require_protocol.union([require_protocol.literal("ligh
|
|
|
785
877
|
require_protocol.literal("--shadow-sm"),
|
|
786
878
|
require_protocol.literal("--shadow-md"),
|
|
787
879
|
require_protocol.literal("--shadow-lg")
|
|
788
|
-
]).describe("CSS variable keys available to MCP apps for theming."),
|
|
880
|
+
]).describe("CSS variable keys available to MCP apps for theming."), AQ = require_protocol.record(IQ.describe(`Style variables for theming MCP apps.
|
|
789
881
|
|
|
790
882
|
Individual style keys are optional - hosts may provide any subset of these values.
|
|
791
883
|
Values are strings containing CSS values (colors, sizes, font stacks, etc.).
|
|
@@ -810,7 +902,7 @@ for compatibility with Zod schema generation. Both are functionally equivalent f
|
|
|
810
902
|
require_protocol.object({ isError: require_protocol.boolean().optional().describe("True if the host failed to open the URL (e.g., due to security policy).") }).passthrough();
|
|
811
903
|
require_protocol.object({ isError: require_protocol.boolean().optional().describe("True if the download failed (e.g., user cancelled or host denied).") }).passthrough();
|
|
812
904
|
require_protocol.object({ isError: require_protocol.boolean().optional().describe("True if the host rejected or failed to deliver the message.") }).passthrough();
|
|
813
|
-
var
|
|
905
|
+
var L = require_protocol.object({
|
|
814
906
|
method: require_protocol.literal("ui/notifications/sandbox-proxy-ready"),
|
|
815
907
|
params: require_protocol.object({})
|
|
816
908
|
}), j = require_protocol.object({
|
|
@@ -845,22 +937,25 @@ require_protocol.object({
|
|
|
845
937
|
method: require_protocol.literal("ui/notifications/tool-cancelled"),
|
|
846
938
|
params: require_protocol.object({ reason: require_protocol.string().optional().describe("Optional reason for the cancellation (e.g., \"user action\", \"timeout\").") })
|
|
847
939
|
});
|
|
848
|
-
var
|
|
849
|
-
variables:
|
|
850
|
-
css:
|
|
940
|
+
var c = require_protocol.object({ fonts: require_protocol.string().optional() }), n = require_protocol.object({
|
|
941
|
+
variables: AQ.optional().describe("CSS variables for theming the app."),
|
|
942
|
+
css: c.optional().describe("CSS blocks that apps can inject.")
|
|
851
943
|
});
|
|
852
944
|
require_protocol.object({
|
|
853
945
|
method: require_protocol.literal("ui/resource-teardown"),
|
|
854
946
|
params: require_protocol.object({})
|
|
855
947
|
});
|
|
856
|
-
var
|
|
948
|
+
var H = require_protocol.record(require_protocol.string(), require_protocol.unknown()), O = require_protocol.object({
|
|
857
949
|
text: require_protocol.object({}).optional().describe("Host supports text content blocks."),
|
|
858
950
|
image: require_protocol.object({}).optional().describe("Host supports image content blocks."),
|
|
859
951
|
audio: require_protocol.object({}).optional().describe("Host supports audio content blocks."),
|
|
860
952
|
resource: require_protocol.object({}).optional().describe("Host supports resource content blocks."),
|
|
861
953
|
resourceLink: require_protocol.object({}).optional().describe("Host supports resource link content blocks."),
|
|
862
954
|
structuredContent: require_protocol.object({}).optional().describe("Host supports structured content.")
|
|
863
|
-
}),
|
|
955
|
+
}), M = require_protocol.object({
|
|
956
|
+
method: require_protocol.literal("ui/notifications/request-teardown"),
|
|
957
|
+
params: require_protocol.object({}).optional()
|
|
958
|
+
}), i = require_protocol.object({
|
|
864
959
|
experimental: require_protocol.object({}).optional().describe("Experimental features (structure TBD)."),
|
|
865
960
|
openLinks: require_protocol.object({}).optional().describe("Host supports opening external URLs."),
|
|
866
961
|
downloadFile: require_protocol.object({}).optional().describe("Host supports file downloads via ui/download-file."),
|
|
@@ -873,11 +968,11 @@ var R = require_protocol.record(require_protocol.string(), require_protocol.unkn
|
|
|
873
968
|
}).optional().describe("Sandbox configuration applied by the host."),
|
|
874
969
|
updateModelContext: O.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),
|
|
875
970
|
message: O.optional().describe("Host supports receiving content messages (ui/message) from the view.")
|
|
876
|
-
}),
|
|
971
|
+
}), l = require_protocol.object({
|
|
877
972
|
experimental: require_protocol.object({}).optional().describe("Experimental features (structure TBD)."),
|
|
878
973
|
tools: require_protocol.object({ listChanged: require_protocol.boolean().optional().describe("App supports tools/list_changed notifications.") }).optional().describe("App exposes MCP-style tools that the host can call."),
|
|
879
974
|
availableDisplayModes: require_protocol.array(D).optional().describe("Display modes the app supports.")
|
|
880
|
-
}),
|
|
975
|
+
}), v = require_protocol.object({
|
|
881
976
|
method: require_protocol.literal("ui/notifications/initialized"),
|
|
882
977
|
params: require_protocol.object({}).optional()
|
|
883
978
|
});
|
|
@@ -906,18 +1001,18 @@ var W = require_protocol.object({
|
|
|
906
1001
|
params: require_protocol.object({ mode: D.describe("The display mode being requested.") })
|
|
907
1002
|
});
|
|
908
1003
|
require_protocol.object({ mode: D.describe("The display mode that was actually set. May differ from requested if not supported.") }).passthrough();
|
|
909
|
-
var
|
|
1004
|
+
var r = require_protocol.union([require_protocol.literal("model"), require_protocol.literal("app")]).describe("Tool visibility scope - who can access the tool.");
|
|
910
1005
|
require_protocol.object({
|
|
911
1006
|
resourceUri: require_protocol.string().optional(),
|
|
912
|
-
visibility: require_protocol.array(
|
|
1007
|
+
visibility: require_protocol.array(r).optional().describe(`Who can access this tool. Default: ["model", "app"]
|
|
913
1008
|
- "model": Tool visible to and callable by the agent
|
|
914
1009
|
- "app": Tool callable by the app from this server only`)
|
|
915
1010
|
});
|
|
916
1011
|
require_protocol.object({ mimeTypes: require_protocol.array(require_protocol.string()).optional().describe("Array of supported MIME types for UI resources.\nMust include `\"text/html;profile=mcp-app\"` for MCP Apps support.") });
|
|
917
|
-
var
|
|
1012
|
+
var C = require_protocol.object({
|
|
918
1013
|
method: require_protocol.literal("ui/download-file"),
|
|
919
1014
|
params: require_protocol.object({ contents: require_protocol.array(require_protocol.union([require_protocol.EmbeddedResourceSchema, require_protocol.ResourceLinkSchema])).describe("Resource contents to download — embedded (inline data) or linked (host fetches). Uses standard MCP resource types.") })
|
|
920
|
-
}),
|
|
1015
|
+
}), S = require_protocol.object({
|
|
921
1016
|
method: require_protocol.literal("ui/message"),
|
|
922
1017
|
params: require_protocol.object({
|
|
923
1018
|
role: require_protocol.literal("user").describe("Message role, currently only \"user\" is supported."),
|
|
@@ -937,13 +1032,13 @@ require_protocol.object({
|
|
|
937
1032
|
method: require_protocol.literal("ui/notifications/tool-result"),
|
|
938
1033
|
params: require_protocol.CallToolResultSchema.describe("Standard MCP tool execution result.")
|
|
939
1034
|
});
|
|
940
|
-
var
|
|
1035
|
+
var y = require_protocol.object({
|
|
941
1036
|
toolInfo: require_protocol.object({
|
|
942
1037
|
id: require_protocol.RequestIdSchema.optional().describe("JSON-RPC id of the tools/call request."),
|
|
943
1038
|
tool: require_protocol.ToolSchema.describe("Tool definition including name, inputSchema, etc.")
|
|
944
1039
|
}).optional().describe("Metadata of the tool call that instantiated this App."),
|
|
945
|
-
theme:
|
|
946
|
-
styles:
|
|
1040
|
+
theme: p.optional().describe("Current color theme preference."),
|
|
1041
|
+
styles: n.optional().describe("Style configuration for theming the app."),
|
|
947
1042
|
displayMode: D.optional().describe("How the UI is currently displayed."),
|
|
948
1043
|
availableDisplayModes: require_protocol.array(D).optional().describe("Display modes the host supports."),
|
|
949
1044
|
containerDimensions: require_protocol.union([require_protocol.object({ height: require_protocol.number().describe("Fixed container height in pixels.") }), require_protocol.object({ maxHeight: require_protocol.union([require_protocol.number(), require_protocol._undefined()]).optional().describe("Maximum container height in pixels.") })]).and(require_protocol.union([require_protocol.object({ width: require_protocol.number().describe("Fixed container width in pixels.") }), require_protocol.object({ maxWidth: require_protocol.union([require_protocol.number(), require_protocol._undefined()]).optional().describe("Maximum container width in pixels.") })])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
|
|
@@ -969,27 +1064,27 @@ container holding the app. Specify either width or maxWidth, and either height o
|
|
|
969
1064
|
}).passthrough();
|
|
970
1065
|
require_protocol.object({
|
|
971
1066
|
method: require_protocol.literal("ui/notifications/host-context-changed"),
|
|
972
|
-
params:
|
|
1067
|
+
params: y.describe("Partial context update containing only changed fields.")
|
|
973
1068
|
});
|
|
974
|
-
var
|
|
1069
|
+
var f = require_protocol.object({
|
|
975
1070
|
method: require_protocol.literal("ui/update-model-context"),
|
|
976
1071
|
params: require_protocol.object({
|
|
977
1072
|
content: require_protocol.array(require_protocol.ContentBlockSchema).optional().describe("Context content blocks (text, image, etc.)."),
|
|
978
1073
|
structuredContent: require_protocol.record(require_protocol.string(), require_protocol.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")
|
|
979
1074
|
})
|
|
980
|
-
}),
|
|
1075
|
+
}), d = require_protocol.object({
|
|
981
1076
|
method: require_protocol.literal("ui/initialize"),
|
|
982
1077
|
params: require_protocol.object({
|
|
983
1078
|
appInfo: require_protocol.ImplementationSchema.describe("App identification (name and version)."),
|
|
984
|
-
appCapabilities:
|
|
1079
|
+
appCapabilities: l.describe("Features and capabilities this app provides."),
|
|
985
1080
|
protocolVersion: require_protocol.string().describe("Protocol version this app supports.")
|
|
986
1081
|
})
|
|
987
1082
|
});
|
|
988
1083
|
require_protocol.object({
|
|
989
1084
|
protocolVersion: require_protocol.string().describe("Negotiated protocol version string (e.g., \"2025-11-21\")."),
|
|
990
1085
|
hostInfo: require_protocol.ImplementationSchema.describe("Host application identification and version."),
|
|
991
|
-
hostCapabilities:
|
|
992
|
-
hostContext:
|
|
1086
|
+
hostCapabilities: i.describe("Features and capabilities provided by the host."),
|
|
1087
|
+
hostContext: y.describe("Rich context about the host environment.")
|
|
993
1088
|
}).passthrough();
|
|
994
1089
|
var N = class {
|
|
995
1090
|
eventTarget;
|
|
@@ -1025,8 +1120,8 @@ var N = class {
|
|
|
1025
1120
|
sessionId;
|
|
1026
1121
|
setProtocolVersion;
|
|
1027
1122
|
};
|
|
1028
|
-
var
|
|
1029
|
-
var
|
|
1123
|
+
var aQ = [G];
|
|
1124
|
+
var tQ = class extends require_protocol.Protocol {
|
|
1030
1125
|
_client;
|
|
1031
1126
|
_hostInfo;
|
|
1032
1127
|
_capabilities;
|
|
@@ -1038,7 +1133,7 @@ var oQ = class extends require_protocol.Protocol {
|
|
|
1038
1133
|
this._client = X;
|
|
1039
1134
|
this._hostInfo = Y;
|
|
1040
1135
|
this._capabilities = Z;
|
|
1041
|
-
this._hostContext = $?.hostContext || {}, this.setRequestHandler(
|
|
1136
|
+
this._hostContext = $?.hostContext || {}, this.setRequestHandler(d, (K) => this._oninitialize(K)), this.setRequestHandler(require_protocol.PingRequestSchema, (K, J) => {
|
|
1042
1137
|
return this.onping?.(K.params, J), {};
|
|
1043
1138
|
}), this.setRequestHandler(W, (K) => {
|
|
1044
1139
|
return { mode: this._hostContext.displayMode ?? "inline" };
|
|
@@ -1055,13 +1150,13 @@ var oQ = class extends require_protocol.Protocol {
|
|
|
1055
1150
|
this.setNotificationHandler(P, (Y) => X(Y.params));
|
|
1056
1151
|
}
|
|
1057
1152
|
set onsandboxready(X) {
|
|
1058
|
-
this.setNotificationHandler(
|
|
1153
|
+
this.setNotificationHandler(L, (Y) => X(Y.params));
|
|
1059
1154
|
}
|
|
1060
1155
|
set oninitialized(X) {
|
|
1061
|
-
this.setNotificationHandler(
|
|
1156
|
+
this.setNotificationHandler(v, (Y) => X(Y.params));
|
|
1062
1157
|
}
|
|
1063
1158
|
set onmessage(X) {
|
|
1064
|
-
this.setRequestHandler(
|
|
1159
|
+
this.setRequestHandler(S, async (Y, Z) => {
|
|
1065
1160
|
return X(Y.params, Z);
|
|
1066
1161
|
});
|
|
1067
1162
|
}
|
|
@@ -1071,10 +1166,13 @@ var oQ = class extends require_protocol.Protocol {
|
|
|
1071
1166
|
});
|
|
1072
1167
|
}
|
|
1073
1168
|
set ondownloadfile(X) {
|
|
1074
|
-
this.setRequestHandler(
|
|
1169
|
+
this.setRequestHandler(C, async (Y, Z) => {
|
|
1075
1170
|
return X(Y.params, Z);
|
|
1076
1171
|
});
|
|
1077
1172
|
}
|
|
1173
|
+
set onrequestteardown(X) {
|
|
1174
|
+
this.setNotificationHandler(M, (Y) => X(Y.params));
|
|
1175
|
+
}
|
|
1078
1176
|
set onrequestdisplaymode(X) {
|
|
1079
1177
|
this.setRequestHandler(W, async (Y, Z) => {
|
|
1080
1178
|
return X(Y.params, Z);
|
|
@@ -1086,7 +1184,7 @@ var oQ = class extends require_protocol.Protocol {
|
|
|
1086
1184
|
});
|
|
1087
1185
|
}
|
|
1088
1186
|
set onupdatemodelcontext(X) {
|
|
1089
|
-
this.setRequestHandler(
|
|
1187
|
+
this.setRequestHandler(f, async (Y, Z) => {
|
|
1090
1188
|
return X(Y.params, Z);
|
|
1091
1189
|
});
|
|
1092
1190
|
}
|
|
@@ -1148,7 +1246,7 @@ var oQ = class extends require_protocol.Protocol {
|
|
|
1148
1246
|
async _oninitialize(X) {
|
|
1149
1247
|
let Y = X.params.protocolVersion;
|
|
1150
1248
|
return this._appCapabilities = X.params.appCapabilities, this._appInfo = X.params.appInfo, {
|
|
1151
|
-
protocolVersion:
|
|
1249
|
+
protocolVersion: aQ.includes(Y) ? Y : G,
|
|
1152
1250
|
hostCapabilities: this.getCapabilities(),
|
|
1153
1251
|
hostInfo: this._hostInfo,
|
|
1154
1252
|
hostContext: this._hostContext
|
|
@@ -1158,7 +1256,7 @@ var oQ = class extends require_protocol.Protocol {
|
|
|
1158
1256
|
let Y = {}, Z = !1;
|
|
1159
1257
|
for (let $ of Object.keys(X)) {
|
|
1160
1258
|
let K = this._hostContext[$], J = X[$];
|
|
1161
|
-
if (
|
|
1259
|
+
if (sQ(K, J)) continue;
|
|
1162
1260
|
Y[$] = J, Z = !0;
|
|
1163
1261
|
}
|
|
1164
1262
|
if (Z) this._hostContext = X, this.sendHostContextChange(Y);
|
|
@@ -1203,7 +1301,7 @@ var oQ = class extends require_protocol.Protocol {
|
|
|
1203
1301
|
return this.request({
|
|
1204
1302
|
method: "ui/resource-teardown",
|
|
1205
1303
|
params: X
|
|
1206
|
-
},
|
|
1304
|
+
}, H, Y);
|
|
1207
1305
|
}
|
|
1208
1306
|
sendResourceTeardown = this.teardownResource;
|
|
1209
1307
|
async connect(X) {
|
|
@@ -1249,7 +1347,7 @@ var oQ = class extends require_protocol.Protocol {
|
|
|
1249
1347
|
return super.connect(X);
|
|
1250
1348
|
}
|
|
1251
1349
|
};
|
|
1252
|
-
function
|
|
1350
|
+
function sQ(X, Y) {
|
|
1253
1351
|
return JSON.stringify(X) === JSON.stringify(Y);
|
|
1254
1352
|
}
|
|
1255
1353
|
//#endregion
|
|
@@ -1283,10 +1381,11 @@ var McpAppHost = class {
|
|
|
1283
1381
|
_prevDisplayMode;
|
|
1284
1382
|
_pendingToolInput = null;
|
|
1285
1383
|
_pendingToolResult = null;
|
|
1384
|
+
_messageListener = null;
|
|
1286
1385
|
constructor(options = {}) {
|
|
1287
1386
|
this.options = options;
|
|
1288
1387
|
this._prevDisplayMode = options.hostContext?.displayMode;
|
|
1289
|
-
this.bridge = new
|
|
1388
|
+
this.bridge = new tQ(null, options.hostInfo ?? DEFAULT_HOST_INFO, options.hostCapabilities ?? DEFAULT_HOST_CAPABILITIES, { hostContext: options.hostContext });
|
|
1290
1389
|
this.bridge.oninitialized = () => {
|
|
1291
1390
|
this._initialized = true;
|
|
1292
1391
|
if (this._pendingToolInput) {
|
|
@@ -1299,38 +1398,35 @@ var McpAppHost = class {
|
|
|
1299
1398
|
}
|
|
1300
1399
|
};
|
|
1301
1400
|
this.bridge.onopenlink = async ({ url }) => {
|
|
1302
|
-
console.log("[MCP App] openLink:", url);
|
|
1303
1401
|
if (this.options.onOpenLink) this.options.onOpenLink(url);
|
|
1304
|
-
else {
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
}
|
|
1311
|
-
} catch {
|
|
1312
|
-
console.warn("[MCP App] openLink blocked invalid URL:", url);
|
|
1313
|
-
return {};
|
|
1314
|
-
}
|
|
1315
|
-
window.open(url, "_blank");
|
|
1402
|
+
else try {
|
|
1403
|
+
const parsed = new URL(url);
|
|
1404
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") console.warn("[MCP App] openLink blocked non-http(s) URL:", url);
|
|
1405
|
+
else window.open(url, "_blank");
|
|
1406
|
+
} catch {
|
|
1407
|
+
console.warn("[MCP App] openLink blocked invalid URL:", url);
|
|
1316
1408
|
}
|
|
1317
|
-
|
|
1409
|
+
const ack = {};
|
|
1410
|
+
console.log(`%c[MCP ↓]%c host → app: %copenLink ack`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", ack);
|
|
1411
|
+
return ack;
|
|
1318
1412
|
};
|
|
1319
1413
|
this.bridge.onmessage = async ({ role, content }) => {
|
|
1320
1414
|
if (this.options.onMessage) this.options.onMessage(role, content);
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
});
|
|
1325
|
-
return {};
|
|
1415
|
+
const ack = {};
|
|
1416
|
+
console.log(`%c[MCP ↓]%c host → app: %csendMessage ack`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", ack);
|
|
1417
|
+
return ack;
|
|
1326
1418
|
};
|
|
1327
1419
|
this.bridge.onrequestdisplaymode = async ({ mode }) => {
|
|
1328
1420
|
this.options.onDisplayModeChange?.(mode);
|
|
1329
|
-
|
|
1421
|
+
const result = { mode };
|
|
1422
|
+
console.log(`%c[MCP ↓]%c host → app: %crequestDisplayMode result`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", result);
|
|
1423
|
+
return result;
|
|
1330
1424
|
};
|
|
1331
1425
|
this.bridge.onupdatemodelcontext = async ({ content, structuredContent }) => {
|
|
1332
1426
|
this.options.onUpdateModelContext?.(content ?? [], structuredContent);
|
|
1333
|
-
|
|
1427
|
+
const ack = {};
|
|
1428
|
+
console.log(`%c[MCP ↓]%c host → app: %cupdateModelContext ack`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", ack);
|
|
1429
|
+
return ack;
|
|
1334
1430
|
};
|
|
1335
1431
|
this.bridge.onsizechange = (params) => {
|
|
1336
1432
|
this.options.onSizeChanged?.(params);
|
|
@@ -1347,17 +1443,24 @@ var McpAppHost = class {
|
|
|
1347
1443
|
}
|
|
1348
1444
|
};
|
|
1349
1445
|
this.bridge.oncalltool = async (params) => {
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1446
|
+
let result;
|
|
1447
|
+
if (this.options.onCallTool) result = await this.options.onCallTool(params);
|
|
1448
|
+
else result = { content: [{
|
|
1353
1449
|
type: "text",
|
|
1354
1450
|
text: `[Inspector] Tool "${params.name}" called (no handler configured)`
|
|
1355
1451
|
}] };
|
|
1452
|
+
console.log(`%c[MCP ↓]%c host → app: %ccallServerTool result(${params.name})`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", result);
|
|
1453
|
+
return result;
|
|
1356
1454
|
};
|
|
1357
1455
|
this.bridge.ondownloadfile = async ({ contents }) => {
|
|
1358
1456
|
if (this.options.onDownloadFile) this.options.onDownloadFile(contents);
|
|
1359
|
-
|
|
1360
|
-
|
|
1457
|
+
const ack = {};
|
|
1458
|
+
console.log(`%c[MCP ↓]%c host → app: %cdownloadFile ack`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", ack);
|
|
1459
|
+
return ack;
|
|
1460
|
+
};
|
|
1461
|
+
this.bridge.onrequestteardown = () => {
|
|
1462
|
+
if (this.options.onRequestTeardown) this.options.onRequestTeardown();
|
|
1463
|
+
else console.log("[MCP App] requestTeardown (app requested close)");
|
|
1361
1464
|
};
|
|
1362
1465
|
this.bridge.onsandboxready = () => {
|
|
1363
1466
|
this.options.onSandboxReady?.();
|
|
@@ -1367,7 +1470,18 @@ var McpAppHost = class {
|
|
|
1367
1470
|
* Connect to an iframe's contentWindow.
|
|
1368
1471
|
*/
|
|
1369
1472
|
async connectToIframe(contentWindow) {
|
|
1473
|
+
if (this._messageListener) window.removeEventListener("message", this._messageListener);
|
|
1370
1474
|
this._contentWindow = contentWindow;
|
|
1475
|
+
this._messageListener = (event) => {
|
|
1476
|
+
if (event.source !== contentWindow) return;
|
|
1477
|
+
const data = event.data;
|
|
1478
|
+
if (!data || typeof data !== "object") return;
|
|
1479
|
+
const method = data.method;
|
|
1480
|
+
if (method?.startsWith("sunpeak/") || method === "ui/notifications/sandbox-proxy-ready") return;
|
|
1481
|
+
const label = method ?? (data.id != null ? `response #${data.id}` : "unknown");
|
|
1482
|
+
console.log(`%c[MCP ↑]%c app → host: %c${label}`, "color:#6ee7b7", "color:inherit", "color:#93c5fd", data);
|
|
1483
|
+
};
|
|
1484
|
+
window.addEventListener("message", this._messageListener);
|
|
1371
1485
|
const transport = new N(contentWindow, contentWindow);
|
|
1372
1486
|
await this.bridge.connect(transport);
|
|
1373
1487
|
}
|
|
@@ -1402,11 +1516,12 @@ var McpAppHost = class {
|
|
|
1402
1516
|
this._fenceCleanup = cleanup;
|
|
1403
1517
|
window.addEventListener("message", handler);
|
|
1404
1518
|
try {
|
|
1405
|
-
|
|
1519
|
+
const fenceMsg = {
|
|
1406
1520
|
jsonrpc: "2.0",
|
|
1407
1521
|
method: "sunpeak/fence",
|
|
1408
1522
|
params: { fenceId: id }
|
|
1409
|
-
}
|
|
1523
|
+
};
|
|
1524
|
+
win.postMessage(fenceMsg, "*");
|
|
1410
1525
|
} catch {
|
|
1411
1526
|
cleanup();
|
|
1412
1527
|
resolve();
|
|
@@ -1419,6 +1534,7 @@ var McpAppHost = class {
|
|
|
1419
1534
|
* to commit its DOM before firing onDisplayModeReady.
|
|
1420
1535
|
*/
|
|
1421
1536
|
setHostContext(context) {
|
|
1537
|
+
console.log(`%c[MCP ↓]%c host → app: %csetHostContext`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", context);
|
|
1422
1538
|
this.bridge.setHostContext(context);
|
|
1423
1539
|
const currentMode = context.displayMode;
|
|
1424
1540
|
if (currentMode && currentMode !== this._prevDisplayMode) {
|
|
@@ -1435,6 +1551,7 @@ var McpAppHost = class {
|
|
|
1435
1551
|
*/
|
|
1436
1552
|
sendToolInput(args) {
|
|
1437
1553
|
const params = { arguments: args };
|
|
1554
|
+
console.log(`%c[MCP ↓]%c host → app: %csendToolInput`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", params);
|
|
1438
1555
|
if (this._initialized) this.bridge.sendToolInput(params);
|
|
1439
1556
|
else this._pendingToolInput = params;
|
|
1440
1557
|
}
|
|
@@ -1443,6 +1560,7 @@ var McpAppHost = class {
|
|
|
1443
1560
|
* If the app hasn't initialized yet, the result is queued.
|
|
1444
1561
|
*/
|
|
1445
1562
|
sendToolResult(result) {
|
|
1563
|
+
console.log(`%c[MCP ↓]%c host → app: %csendToolResult`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", result);
|
|
1446
1564
|
if (this._initialized) this.bridge.sendToolResult(result);
|
|
1447
1565
|
else this._pendingToolResult = result;
|
|
1448
1566
|
}
|
|
@@ -1452,6 +1570,7 @@ var McpAppHost = class {
|
|
|
1452
1570
|
*/
|
|
1453
1571
|
sendToolInputPartial(args) {
|
|
1454
1572
|
const params = { arguments: args };
|
|
1573
|
+
console.log(`%c[MCP ↓]%c host → app: %csendToolInputPartial`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", params);
|
|
1455
1574
|
if (this._initialized) this.bridge.sendToolInputPartial(params);
|
|
1456
1575
|
}
|
|
1457
1576
|
/**
|
|
@@ -1460,6 +1579,7 @@ var McpAppHost = class {
|
|
|
1460
1579
|
*/
|
|
1461
1580
|
sendToolCancelled(reason) {
|
|
1462
1581
|
const params = reason ? { reason } : {};
|
|
1582
|
+
console.log(`%c[MCP ↓]%c host → app: %csendToolCancelled`, "color:#f9a8d4", "color:inherit", "color:#93c5fd", params);
|
|
1463
1583
|
if (this._initialized) this.bridge.sendToolCancelled(params);
|
|
1464
1584
|
}
|
|
1465
1585
|
/**
|
|
@@ -1483,6 +1603,10 @@ var McpAppHost = class {
|
|
|
1483
1603
|
* Close the connection.
|
|
1484
1604
|
*/
|
|
1485
1605
|
async close() {
|
|
1606
|
+
if (this._messageListener) {
|
|
1607
|
+
window.removeEventListener("message", this._messageListener);
|
|
1608
|
+
this._messageListener = null;
|
|
1609
|
+
}
|
|
1486
1610
|
this._fenceCleanup?.();
|
|
1487
1611
|
this._fenceCleanup = null;
|
|
1488
1612
|
try {
|
|
@@ -1593,7 +1717,7 @@ function generateSandboxProxyHtml(platformScript) {
|
|
|
1593
1717
|
<head>
|
|
1594
1718
|
<meta name="color-scheme" content="${colorScheme}" />
|
|
1595
1719
|
<style>
|
|
1596
|
-
html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; }
|
|
1720
|
+
html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: transparent; }
|
|
1597
1721
|
iframe { border: none; width: 100%; height: 100%; display: block; }
|
|
1598
1722
|
</style>
|
|
1599
1723
|
</head>
|
|
@@ -1656,6 +1780,16 @@ iframe { border: none; width: 100%; height: 100%; display: block; }
|
|
|
1656
1780
|
return;
|
|
1657
1781
|
}
|
|
1658
1782
|
|
|
1783
|
+
// Sync color-scheme on the inner iframe element when theme changes.
|
|
1784
|
+
// This ensures prefers-color-scheme resolves correctly inside the app.
|
|
1785
|
+
// Important: do NOT set color-scheme on the proxy's own document —
|
|
1786
|
+
// changing it from the initial 'dark' causes Chrome to re-evaluate
|
|
1787
|
+
// the CSS Canvas as opaque white, blocking the host's conversation
|
|
1788
|
+
// background from showing through the transparent proxy.
|
|
1789
|
+
if (data.method === 'ui/notifications/host-context-changed' && data.params && data.params.theme) {
|
|
1790
|
+
if (innerFrame) innerFrame.style.colorScheme = data.params.theme;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1659
1793
|
// Forward all other messages to the inner iframe
|
|
1660
1794
|
if (innerWindow) {
|
|
1661
1795
|
try { innerWindow.postMessage(data, '*'); } catch(e) { /* detached */ }
|
|
@@ -2204,6 +2338,10 @@ function parseUrlParams() {
|
|
|
2204
2338
|
const host = params.get("host") ?? void 0;
|
|
2205
2339
|
const prodResourcesParam = params.get("prodResources");
|
|
2206
2340
|
const prodResources = prodResourcesParam === "true" ? true : prodResourcesParam === "false" ? false : void 0;
|
|
2341
|
+
const sidebarParam = params.get("sidebar");
|
|
2342
|
+
const sidebar = sidebarParam === "false" ? false : sidebarParam === "true" ? true : void 0;
|
|
2343
|
+
const devOverlayParam = params.get("devOverlay");
|
|
2344
|
+
const devOverlay = devOverlayParam === "false" ? false : devOverlayParam === "true" ? true : void 0;
|
|
2207
2345
|
const deviceType = params.get("deviceType");
|
|
2208
2346
|
let platform;
|
|
2209
2347
|
if (deviceType === "mobile" || deviceType === "tablet") platform = "mobile";
|
|
@@ -2236,7 +2374,9 @@ function parseUrlParams() {
|
|
|
2236
2374
|
deviceCapabilities,
|
|
2237
2375
|
safeAreaInsets,
|
|
2238
2376
|
host: host ?? void 0,
|
|
2239
|
-
prodResources
|
|
2377
|
+
prodResources,
|
|
2378
|
+
sidebar,
|
|
2379
|
+
devOverlay
|
|
2240
2380
|
};
|
|
2241
2381
|
}
|
|
2242
2382
|
function useInspectorState({ simulations, defaultHost = "chatgpt" }) {
|
|
@@ -2487,7 +2627,9 @@ function useInspectorState({ simulations, defaultHost = "chatgpt" }) {
|
|
|
2487
2627
|
permissions: resourceMeta?.permissions,
|
|
2488
2628
|
prefersBorder: resourceMeta?.prefersBorder ?? false,
|
|
2489
2629
|
urlTool: urlParams.tool,
|
|
2490
|
-
urlProdResources: urlParams.prodResources
|
|
2630
|
+
urlProdResources: urlParams.prodResources,
|
|
2631
|
+
urlSidebar: urlParams.sidebar,
|
|
2632
|
+
urlDevOverlay: urlParams.devOverlay
|
|
2491
2633
|
};
|
|
2492
2634
|
}
|
|
2493
2635
|
//#endregion
|
|
@@ -2508,15 +2650,17 @@ function useMcpConnection(initialServerUrl) {
|
|
|
2508
2650
|
const [error, setError] = (0, react.useState)();
|
|
2509
2651
|
const [simulations, setSimulations] = (0, react.useState)();
|
|
2510
2652
|
const [hasReconnected, setHasReconnected] = (0, react.useState)(false);
|
|
2511
|
-
const reconnect = (0, react.useCallback)(async (url) => {
|
|
2653
|
+
const reconnect = (0, react.useCallback)(async (url, auth) => {
|
|
2512
2654
|
setHasReconnected(true);
|
|
2513
2655
|
setStatus("connecting");
|
|
2514
2656
|
setError(void 0);
|
|
2515
2657
|
try {
|
|
2658
|
+
const body = { url };
|
|
2659
|
+
if (auth && auth.type !== "none") body.auth = auth;
|
|
2516
2660
|
const res = await fetch("/__sunpeak/connect", {
|
|
2517
2661
|
method: "POST",
|
|
2518
2662
|
headers: { "Content-Type": "application/json" },
|
|
2519
|
-
body: JSON.stringify(
|
|
2663
|
+
body: JSON.stringify(body)
|
|
2520
2664
|
});
|
|
2521
2665
|
if (!res.ok) {
|
|
2522
2666
|
let message = `Connection failed (${res.status})`;
|
|
@@ -2535,6 +2679,12 @@ function useMcpConnection(initialServerUrl) {
|
|
|
2535
2679
|
setSimulations(void 0);
|
|
2536
2680
|
}
|
|
2537
2681
|
}, []);
|
|
2682
|
+
const setConnected = (0, react.useCallback)((sims) => {
|
|
2683
|
+
setHasReconnected(true);
|
|
2684
|
+
setStatus("connected");
|
|
2685
|
+
setError(void 0);
|
|
2686
|
+
setSimulations(sims);
|
|
2687
|
+
}, []);
|
|
2538
2688
|
(0, react.useEffect)(() => {
|
|
2539
2689
|
if (!initialServerUrl) return;
|
|
2540
2690
|
let cancelled = false;
|
|
@@ -2560,7 +2710,8 @@ function useMcpConnection(initialServerUrl) {
|
|
|
2560
2710
|
error,
|
|
2561
2711
|
simulations,
|
|
2562
2712
|
hasReconnected,
|
|
2563
|
-
reconnect
|
|
2713
|
+
reconnect,
|
|
2714
|
+
setConnected
|
|
2564
2715
|
};
|
|
2565
2716
|
}
|
|
2566
2717
|
//#endregion
|
|
@@ -3044,22 +3195,146 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
3044
3195
|
defaultHost
|
|
3045
3196
|
});
|
|
3046
3197
|
const [serverUrl, setServerUrl] = react.useState(mcpServerUrl ?? "");
|
|
3198
|
+
const [authType, setAuthType] = react.useState("none");
|
|
3199
|
+
const [bearerToken, setBearerToken] = react.useState("");
|
|
3200
|
+
const [oauthScopes, setOauthScopes] = react.useState("");
|
|
3201
|
+
const [oauthClientId, setOauthClientId] = react.useState("");
|
|
3202
|
+
const [oauthClientSecret, setOauthClientSecret] = react.useState("");
|
|
3203
|
+
const [oauthStatus, setOauthStatus] = react.useState("none");
|
|
3204
|
+
const [oauthError, setOauthError] = react.useState();
|
|
3047
3205
|
const connection = useMcpConnection(mcpServerUrl || void 0);
|
|
3048
3206
|
const [prodResources, setProdResources] = react.useState(state.urlProdResources ?? defaultProdResources);
|
|
3207
|
+
const showSidebar = state.urlSidebar !== false;
|
|
3208
|
+
const showDevOverlay = state.urlDevOverlay !== false;
|
|
3049
3209
|
const [isRunning, setIsRunning] = react.useState(false);
|
|
3050
3210
|
const [hasRun, setHasRun] = react.useState(false);
|
|
3051
3211
|
const [showCheck, setShowCheck] = react.useState(false);
|
|
3052
3212
|
const checkTimerRef = react.useRef(void 0);
|
|
3213
|
+
const oauthCleanupRef = react.useRef(void 0);
|
|
3053
3214
|
react.useEffect(() => {
|
|
3054
3215
|
state.setSelectedSimulationName(effectiveSimulationName);
|
|
3055
3216
|
}, [effectiveSimulationName]);
|
|
3217
|
+
const currentAuthConfig = react.useMemo(() => {
|
|
3218
|
+
if (authType === "bearer" && bearerToken) return {
|
|
3219
|
+
type: "bearer",
|
|
3220
|
+
bearerToken
|
|
3221
|
+
};
|
|
3222
|
+
if (authType === "oauth") return { type: "oauth" };
|
|
3223
|
+
}, [authType, bearerToken]);
|
|
3056
3224
|
const prevServerUrlRef = react.useRef(serverUrl);
|
|
3057
3225
|
react.useEffect(() => {
|
|
3058
3226
|
const urlChanged = serverUrl !== prevServerUrlRef.current;
|
|
3059
3227
|
prevServerUrlRef.current = serverUrl;
|
|
3060
3228
|
if (!urlChanged) return;
|
|
3061
|
-
if (serverUrl)
|
|
3062
|
-
|
|
3229
|
+
if (serverUrl) {
|
|
3230
|
+
setOauthStatus("none");
|
|
3231
|
+
setOauthError(void 0);
|
|
3232
|
+
if (authType === "oauth") return;
|
|
3233
|
+
connection.reconnect(serverUrl, currentAuthConfig);
|
|
3234
|
+
}
|
|
3235
|
+
}, [
|
|
3236
|
+
serverUrl,
|
|
3237
|
+
connection.reconnect,
|
|
3238
|
+
authType,
|
|
3239
|
+
currentAuthConfig
|
|
3240
|
+
]);
|
|
3241
|
+
const handleStartOAuth = react.useCallback(async () => {
|
|
3242
|
+
if (!serverUrl || demoMode) return;
|
|
3243
|
+
setOauthStatus("authorizing");
|
|
3244
|
+
setOauthError(void 0);
|
|
3245
|
+
const popup = window.open("about:blank", `sunpeak-oauth-${Date.now()}`, "width=600,height=700,popup=yes");
|
|
3246
|
+
try {
|
|
3247
|
+
const res = await fetch("/__sunpeak/oauth/start", {
|
|
3248
|
+
method: "POST",
|
|
3249
|
+
headers: { "Content-Type": "application/json" },
|
|
3250
|
+
body: JSON.stringify({
|
|
3251
|
+
url: serverUrl,
|
|
3252
|
+
scope: oauthScopes || void 0,
|
|
3253
|
+
clientId: oauthClientId || void 0,
|
|
3254
|
+
clientSecret: oauthClientSecret || void 0
|
|
3255
|
+
})
|
|
3256
|
+
});
|
|
3257
|
+
if (!res.ok) {
|
|
3258
|
+
let message = `OAuth start failed (${res.status})`;
|
|
3259
|
+
try {
|
|
3260
|
+
const json = await res.json();
|
|
3261
|
+
if (json.error) message = json.error;
|
|
3262
|
+
} catch {}
|
|
3263
|
+
throw new Error(message);
|
|
3264
|
+
}
|
|
3265
|
+
const data = await res.json();
|
|
3266
|
+
if (data.error) {
|
|
3267
|
+
popup?.close();
|
|
3268
|
+
setOauthError(data.error);
|
|
3269
|
+
setOauthStatus("error");
|
|
3270
|
+
return;
|
|
3271
|
+
}
|
|
3272
|
+
if (data.status === "authorized") {
|
|
3273
|
+
popup?.close();
|
|
3274
|
+
setOauthStatus("authorized");
|
|
3275
|
+
connection.setConnected(data.simulations);
|
|
3276
|
+
return;
|
|
3277
|
+
}
|
|
3278
|
+
if (data.status === "redirect" && data.authUrl) {
|
|
3279
|
+
if (!popup || popup.closed) {
|
|
3280
|
+
setOauthError("Popup was blocked. Allow popups for this site and try again.");
|
|
3281
|
+
setOauthStatus("error");
|
|
3282
|
+
return;
|
|
3283
|
+
}
|
|
3284
|
+
popup.location.href = data.authUrl;
|
|
3285
|
+
let checkClosed;
|
|
3286
|
+
let bc;
|
|
3287
|
+
const cleanup = () => {
|
|
3288
|
+
clearInterval(checkClosed);
|
|
3289
|
+
window.removeEventListener("message", handleMessage);
|
|
3290
|
+
bc?.close();
|
|
3291
|
+
oauthCleanupRef.current = void 0;
|
|
3292
|
+
};
|
|
3293
|
+
oauthCleanupRef.current?.();
|
|
3294
|
+
oauthCleanupRef.current = cleanup;
|
|
3295
|
+
const handleOAuthResult = (result) => {
|
|
3296
|
+
cleanup();
|
|
3297
|
+
if (result.error) {
|
|
3298
|
+
setOauthError(result.errorDescription || result.error);
|
|
3299
|
+
setOauthStatus("error");
|
|
3300
|
+
} else if (result.success) {
|
|
3301
|
+
setOauthStatus("authorized");
|
|
3302
|
+
connection.setConnected(result.simulations);
|
|
3303
|
+
}
|
|
3304
|
+
};
|
|
3305
|
+
const handleMessage = (event) => {
|
|
3306
|
+
if (event.origin !== window.location.origin) return;
|
|
3307
|
+
if (event.data?.type !== "sunpeak-oauth-callback") return;
|
|
3308
|
+
handleOAuthResult(event.data);
|
|
3309
|
+
};
|
|
3310
|
+
window.addEventListener("message", handleMessage);
|
|
3311
|
+
if (typeof BroadcastChannel !== "undefined") {
|
|
3312
|
+
bc = new BroadcastChannel("sunpeak-oauth");
|
|
3313
|
+
bc.onmessage = (event) => {
|
|
3314
|
+
if (event.data?.type !== "sunpeak-oauth-callback") return;
|
|
3315
|
+
handleOAuthResult(event.data);
|
|
3316
|
+
};
|
|
3317
|
+
}
|
|
3318
|
+
checkClosed = setInterval(() => {
|
|
3319
|
+
if (popup?.closed) {
|
|
3320
|
+
cleanup();
|
|
3321
|
+
setOauthStatus((prev) => prev === "authorizing" ? "none" : prev);
|
|
3322
|
+
}
|
|
3323
|
+
}, 500);
|
|
3324
|
+
}
|
|
3325
|
+
} catch (err) {
|
|
3326
|
+
popup?.close();
|
|
3327
|
+
setOauthError(err instanceof Error ? err.message : String(err));
|
|
3328
|
+
setOauthStatus("error");
|
|
3329
|
+
}
|
|
3330
|
+
}, [
|
|
3331
|
+
serverUrl,
|
|
3332
|
+
oauthScopes,
|
|
3333
|
+
oauthClientId,
|
|
3334
|
+
oauthClientSecret,
|
|
3335
|
+
demoMode,
|
|
3336
|
+
connection
|
|
3337
|
+
]);
|
|
3063
3338
|
react.useEffect(() => {
|
|
3064
3339
|
if (connection.simulations) setSimulations(connection.simulations);
|
|
3065
3340
|
else if (connection.status === "error" && connection.hasReconnected) setSimulations({});
|
|
@@ -3091,33 +3366,57 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
3091
3366
|
react.useEffect(() => {
|
|
3092
3367
|
setHasRun(false);
|
|
3093
3368
|
}, [effectiveSimulationName]);
|
|
3094
|
-
react.useEffect(() => () =>
|
|
3369
|
+
react.useEffect(() => () => {
|
|
3370
|
+
clearTimeout(checkTimerRef.current);
|
|
3371
|
+
oauthCleanupRef.current?.();
|
|
3372
|
+
}, []);
|
|
3095
3373
|
const handleRun = react.useCallback(async () => {
|
|
3096
3374
|
const caller = onCallToolDirect ?? onCallTool;
|
|
3097
3375
|
const sim = simulations[effectiveSimulationName];
|
|
3098
3376
|
if (!caller || !sim) return;
|
|
3099
3377
|
const toolName = sim.tool.name;
|
|
3100
3378
|
setIsRunning(true);
|
|
3379
|
+
const startTime = performance.now();
|
|
3101
3380
|
try {
|
|
3102
3381
|
const result = await caller({
|
|
3103
3382
|
name: toolName,
|
|
3104
3383
|
arguments: state.toolInput
|
|
3105
3384
|
});
|
|
3106
|
-
|
|
3107
|
-
|
|
3385
|
+
const clientMs = Math.round((performance.now() - startTime) * 10) / 10;
|
|
3386
|
+
const resultMeta = result?._meta;
|
|
3387
|
+
const serverMs = (resultMeta?._sunpeak)?.requestTimeMs;
|
|
3388
|
+
const durationMs = typeof serverMs === "number" ? serverMs : clientMs;
|
|
3389
|
+
const resultWithTiming = {
|
|
3390
|
+
...result,
|
|
3391
|
+
_meta: {
|
|
3392
|
+
...resultMeta,
|
|
3393
|
+
_sunpeak: { requestTimeMs: durationMs }
|
|
3394
|
+
}
|
|
3395
|
+
};
|
|
3396
|
+
state.setToolResult(resultWithTiming);
|
|
3397
|
+
const displayResult = resultMeta?._sunpeak ? (() => {
|
|
3398
|
+
const { _sunpeak: _, ...cleanMeta } = resultMeta;
|
|
3399
|
+
const clean = { ...result };
|
|
3400
|
+
clean._meta = Object.keys(cleanMeta).length > 0 ? cleanMeta : void 0;
|
|
3401
|
+
if (clean._meta === void 0) delete clean._meta;
|
|
3402
|
+
return clean;
|
|
3403
|
+
})() : result;
|
|
3404
|
+
state.setToolResultJson(JSON.stringify(displayResult, null, 2));
|
|
3108
3405
|
state.setToolResultError("");
|
|
3109
3406
|
setHasRun(true);
|
|
3110
3407
|
setShowCheck(true);
|
|
3111
3408
|
clearTimeout(checkTimerRef.current);
|
|
3112
3409
|
checkTimerRef.current = setTimeout(() => setShowCheck(false), 2e3);
|
|
3113
3410
|
} catch (err) {
|
|
3411
|
+
const durationMs = Math.round((performance.now() - startTime) * 10) / 10;
|
|
3114
3412
|
const message = err instanceof Error ? err.message : String(err);
|
|
3115
3413
|
state.setToolResult({
|
|
3116
3414
|
content: [{
|
|
3117
3415
|
type: "text",
|
|
3118
3416
|
text: `Error: ${message}`
|
|
3119
3417
|
}],
|
|
3120
|
-
isError: true
|
|
3418
|
+
isError: true,
|
|
3419
|
+
_meta: { _sunpeak: { requestTimeMs: durationMs } }
|
|
3121
3420
|
});
|
|
3122
3421
|
state.setToolResultJson(JSON.stringify({
|
|
3123
3422
|
content: [{
|
|
@@ -3146,16 +3445,26 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
3146
3445
|
const ctx = { ...state.hostContext };
|
|
3147
3446
|
if (styleVars) ctx.styles = { variables: styleVars };
|
|
3148
3447
|
if (userAgent) ctx.userAgent = userAgent;
|
|
3448
|
+
if (activeShell?.availableDisplayModes) ctx.availableDisplayModes = activeShell.availableDisplayModes;
|
|
3149
3449
|
return ctx;
|
|
3150
3450
|
}, [state.hostContext, activeShell]);
|
|
3451
|
+
const { displayMode, setDisplayMode } = state;
|
|
3151
3452
|
react.useEffect(() => {
|
|
3453
|
+
const modes = activeShell?.availableDisplayModes;
|
|
3454
|
+
if (modes && !modes.includes(displayMode)) setDisplayMode("inline");
|
|
3455
|
+
}, [
|
|
3456
|
+
activeShell,
|
|
3457
|
+
displayMode,
|
|
3458
|
+
setDisplayMode
|
|
3459
|
+
]);
|
|
3460
|
+
react.useLayoutEffect(() => {
|
|
3152
3461
|
const vars = activeShell?.styleVariables;
|
|
3153
3462
|
if (!vars) return;
|
|
3154
3463
|
const root = document.documentElement;
|
|
3155
3464
|
for (const [key, value] of Object.entries(vars)) if (value) root.style.setProperty(key, value);
|
|
3156
3465
|
}, [activeShell]);
|
|
3157
3466
|
const prevPageStyleKeysRef = react.useRef([]);
|
|
3158
|
-
react.
|
|
3467
|
+
react.useLayoutEffect(() => {
|
|
3159
3468
|
const root = document.documentElement;
|
|
3160
3469
|
for (const key of prevPageStyleKeysRef.current) root.style.removeProperty(key);
|
|
3161
3470
|
const pageStyles = activeShell?.pageStyles;
|
|
@@ -3168,6 +3477,22 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
3168
3477
|
prevPageStyleKeysRef.current = keys;
|
|
3169
3478
|
} else prevPageStyleKeysRef.current = [];
|
|
3170
3479
|
}, [activeShell]);
|
|
3480
|
+
react.useLayoutEffect(() => {
|
|
3481
|
+
const fontCss = activeShell?.fontCss;
|
|
3482
|
+
const id = "sunpeak-host-fonts";
|
|
3483
|
+
const existing = document.getElementById(id);
|
|
3484
|
+
if (!fontCss) {
|
|
3485
|
+
existing?.remove();
|
|
3486
|
+
return;
|
|
3487
|
+
}
|
|
3488
|
+
if (existing) existing.textContent = fontCss;
|
|
3489
|
+
else {
|
|
3490
|
+
const style = document.createElement("style");
|
|
3491
|
+
style.id = id;
|
|
3492
|
+
style.textContent = fontCss;
|
|
3493
|
+
document.head.appendChild(style);
|
|
3494
|
+
}
|
|
3495
|
+
}, [activeShell]);
|
|
3171
3496
|
const handleCallTool = react.useCallback((params) => {
|
|
3172
3497
|
if (activeSimulationName) {
|
|
3173
3498
|
const mock = simulations[activeSimulationName]?.serverTools?.[params.name];
|
|
@@ -3226,7 +3551,8 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
3226
3551
|
clearTimeout(timer);
|
|
3227
3552
|
};
|
|
3228
3553
|
}, [prodResourcesPath]);
|
|
3229
|
-
const
|
|
3554
|
+
const baseResourceUrl = (prodResourcesPath && prodResourcesReady ? prodResourcesPath : void 0) ?? state.resourceUrl;
|
|
3555
|
+
const effectiveResourceUrl = baseResourceUrl && !showDevOverlay ? `${baseResourceUrl}${baseResourceUrl.includes("?") ? "&" : "?"}devOverlay=false` : baseResourceUrl;
|
|
3230
3556
|
const prodResourcesLoading = !!prodResourcesPath && !prodResourcesReady;
|
|
3231
3557
|
const hasTools = toolNames.length > 0;
|
|
3232
3558
|
const showEmptyState = !(activeSimulationName !== null && currentSim?.toolResult != null) && !hasRun;
|
|
@@ -3344,6 +3670,26 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
3344
3670
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M0 0L10 6L0 12V0Z" })
|
|
3345
3671
|
}), "Run"]
|
|
3346
3672
|
}) : void 0;
|
|
3673
|
+
const conversationContent = ShellConversation ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShellConversation, {
|
|
3674
|
+
screenWidth: state.screenWidth,
|
|
3675
|
+
displayMode: state.displayMode,
|
|
3676
|
+
platform: state.platform,
|
|
3677
|
+
onRequestDisplayMode: state.handleDisplayModeChange,
|
|
3678
|
+
appName,
|
|
3679
|
+
appIcon,
|
|
3680
|
+
userMessage,
|
|
3681
|
+
onContentWidthChange: state.handleContentWidthChange,
|
|
3682
|
+
headerAction: runButton,
|
|
3683
|
+
children: content
|
|
3684
|
+
}) : content;
|
|
3685
|
+
if (!showSidebar) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeProvider, {
|
|
3686
|
+
theme: state.theme,
|
|
3687
|
+
applyTheme,
|
|
3688
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3689
|
+
className: "flex h-screen w-screen",
|
|
3690
|
+
children: conversationContent
|
|
3691
|
+
})
|
|
3692
|
+
});
|
|
3347
3693
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeProvider, {
|
|
3348
3694
|
theme: state.theme,
|
|
3349
3695
|
applyTheme,
|
|
@@ -3371,6 +3717,92 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
3371
3717
|
disabled: demoMode
|
|
3372
3718
|
})
|
|
3373
3719
|
}),
|
|
3720
|
+
!demoMode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarCollapsibleControl, {
|
|
3721
|
+
label: "Authentication",
|
|
3722
|
+
defaultCollapsed: authType === "none",
|
|
3723
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3724
|
+
className: "space-y-1",
|
|
3725
|
+
children: [
|
|
3726
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSelect, {
|
|
3727
|
+
value: authType,
|
|
3728
|
+
onChange: (value) => {
|
|
3729
|
+
const newType = value;
|
|
3730
|
+
setAuthType(newType);
|
|
3731
|
+
setOauthStatus("none");
|
|
3732
|
+
setOauthError(void 0);
|
|
3733
|
+
if (newType === "none" && serverUrl) connection.reconnect(serverUrl);
|
|
3734
|
+
},
|
|
3735
|
+
options: [
|
|
3736
|
+
{
|
|
3737
|
+
value: "none",
|
|
3738
|
+
label: "None"
|
|
3739
|
+
},
|
|
3740
|
+
{
|
|
3741
|
+
value: "bearer",
|
|
3742
|
+
label: "Bearer Token"
|
|
3743
|
+
},
|
|
3744
|
+
{
|
|
3745
|
+
value: "oauth",
|
|
3746
|
+
label: "OAuth"
|
|
3747
|
+
}
|
|
3748
|
+
]
|
|
3749
|
+
}),
|
|
3750
|
+
authType === "bearer" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarInput, {
|
|
3751
|
+
type: "password",
|
|
3752
|
+
value: bearerToken,
|
|
3753
|
+
onChange: (value) => {
|
|
3754
|
+
setBearerToken(value);
|
|
3755
|
+
if (serverUrl && value) connection.reconnect(serverUrl, {
|
|
3756
|
+
type: "bearer",
|
|
3757
|
+
bearerToken: value
|
|
3758
|
+
});
|
|
3759
|
+
},
|
|
3760
|
+
applyOnBlur: true,
|
|
3761
|
+
placeholder: "Paste your token"
|
|
3762
|
+
}),
|
|
3763
|
+
authType === "oauth" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3764
|
+
className: "space-y-1",
|
|
3765
|
+
children: [
|
|
3766
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarInput, {
|
|
3767
|
+
value: oauthClientId,
|
|
3768
|
+
onChange: setOauthClientId,
|
|
3769
|
+
applyOnBlur: true,
|
|
3770
|
+
placeholder: "Client ID (optional)"
|
|
3771
|
+
}),
|
|
3772
|
+
oauthClientId && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarInput, {
|
|
3773
|
+
type: "password",
|
|
3774
|
+
value: oauthClientSecret,
|
|
3775
|
+
onChange: setOauthClientSecret,
|
|
3776
|
+
applyOnBlur: true,
|
|
3777
|
+
placeholder: "Client Secret (optional)"
|
|
3778
|
+
}),
|
|
3779
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarInput, {
|
|
3780
|
+
value: oauthScopes,
|
|
3781
|
+
onChange: setOauthScopes,
|
|
3782
|
+
applyOnBlur: true,
|
|
3783
|
+
placeholder: "Scopes (optional)"
|
|
3784
|
+
}),
|
|
3785
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3786
|
+
type: "button",
|
|
3787
|
+
onClick: handleStartOAuth,
|
|
3788
|
+
disabled: !serverUrl || oauthStatus === "authorizing",
|
|
3789
|
+
className: "w-full h-7 text-xs rounded-md px-2 transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3790
|
+
style: {
|
|
3791
|
+
backgroundColor: oauthStatus === "authorized" ? "#22c55e" : "var(--color-text-primary)",
|
|
3792
|
+
color: "var(--color-background-primary)"
|
|
3793
|
+
},
|
|
3794
|
+
children: oauthStatus === "authorizing" ? "Authorizing…" : oauthStatus === "authorized" ? "Authorized" : "Authorize"
|
|
3795
|
+
}),
|
|
3796
|
+
oauthError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3797
|
+
className: "text-[9px]",
|
|
3798
|
+
style: { color: "var(--color-text-danger, #dc2626)" },
|
|
3799
|
+
children: oauthError
|
|
3800
|
+
})
|
|
3801
|
+
]
|
|
3802
|
+
})
|
|
3803
|
+
]
|
|
3804
|
+
})
|
|
3805
|
+
}, `auth-${authType === "none" ? "none" : "active"}`),
|
|
3374
3806
|
!hideInspectorModes && !demoMode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarCheckbox, {
|
|
3375
3807
|
checked: prodResources,
|
|
3376
3808
|
onChange: setProdResources,
|
|
@@ -3526,7 +3958,7 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
3526
3958
|
value: "fullscreen",
|
|
3527
3959
|
label: "Full"
|
|
3528
3960
|
}
|
|
3529
|
-
]
|
|
3961
|
+
].filter((opt) => !activeShell?.availableDisplayModes || activeShell.availableDisplayModes.includes(opt.value))
|
|
3530
3962
|
})
|
|
3531
3963
|
}),
|
|
3532
3964
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -3790,18 +4222,7 @@ function Inspector({ children, simulations: initialSimulations = {}, appName = "
|
|
|
3790
4222
|
})
|
|
3791
4223
|
]
|
|
3792
4224
|
}),
|
|
3793
|
-
children:
|
|
3794
|
-
screenWidth: state.screenWidth,
|
|
3795
|
-
displayMode: state.displayMode,
|
|
3796
|
-
platform: state.platform,
|
|
3797
|
-
onRequestDisplayMode: state.handleDisplayModeChange,
|
|
3798
|
-
appName,
|
|
3799
|
-
appIcon,
|
|
3800
|
-
userMessage,
|
|
3801
|
-
onContentWidthChange: state.handleContentWidthChange,
|
|
3802
|
-
headerAction: runButton,
|
|
3803
|
-
children: content
|
|
3804
|
-
}) : content
|
|
4225
|
+
children: conversationContent
|
|
3805
4226
|
})
|
|
3806
4227
|
});
|
|
3807
4228
|
}
|
|
@@ -3939,4 +4360,4 @@ Object.defineProperty(exports, "useThemeContext", {
|
|
|
3939
4360
|
}
|
|
3940
4361
|
});
|
|
3941
4362
|
|
|
3942
|
-
//# sourceMappingURL=inspector-
|
|
4363
|
+
//# sourceMappingURL=inspector-CKc58UuI.cjs.map
|