sunpeak 0.17.4 → 0.17.6
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 +4 -3
- package/bin/commands/inspect.mjs +58 -33
- package/dist/chatgpt/globals.css +5 -0
- 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/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp/index.cjs +1 -1
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/types.d.ts +7 -0
- package/dist/simulator/index.cjs +2 -2
- package/dist/simulator/index.cjs.map +1 -1
- package/dist/simulator/index.js +2 -2
- package/dist/simulator/index.js.map +1 -1
- package/dist/simulator/simulator-url.d.ts +32 -41
- package/dist/simulator/simulator.d.ts +14 -10
- package/dist/simulator/use-mcp-connection.d.ts +12 -7
- package/dist/simulator/use-simulator-state.d.ts +1 -1
- package/dist/{simulator-Dl8B-Ljb.js → simulator-BijjlOXb.js} +278 -143
- package/dist/simulator-BijjlOXb.js.map +1 -0
- package/dist/{simulator-CH9hs0N6.cjs → simulator-DqWETA_1.cjs} +278 -143
- package/dist/simulator-DqWETA_1.cjs.map +1 -0
- package/dist/{simulator-url-CozKF1jf.cjs → simulator-url-3ATCsPOT.cjs} +11 -30
- package/dist/simulator-url-3ATCsPOT.cjs.map +1 -0
- package/dist/{simulator-url-KoS_ToP6.js → simulator-url-BbuuWa7S.js} +11 -30
- package/dist/simulator-url-BbuuWa7S.js.map +1 -0
- package/dist/style.css +5 -0
- package/package.json +1 -1
- package/template/dist/albums/albums.html +1 -1
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.html +1 -1
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.html +1 -1
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.html +1 -1
- package/template/dist/review/review.json +1 -1
- package/template/tests/e2e/albums.spec.ts +3 -9
- package/template/tests/e2e/carousel.spec.ts +3 -9
- package/template/tests/e2e/map.spec.ts +3 -9
- package/template/tests/e2e/review.spec.ts +3 -9
- package/dist/simulator-CH9hs0N6.cjs.map +0 -1
- package/dist/simulator-Dl8B-Ljb.js.map +0 -1
- package/dist/simulator-url-CozKF1jf.cjs.map +0 -1
- package/dist/simulator-url-KoS_ToP6.js.map +0 -1
|
@@ -2186,13 +2186,14 @@ var DEFAULT_PLATFORM = "desktop";
|
|
|
2186
2186
|
* - touch: 'true' | 'false'
|
|
2187
2187
|
* - safeAreaTop, safeAreaBottom, safeAreaLeft, safeAreaRight: number
|
|
2188
2188
|
* - host: 'chatgpt' | 'claude'
|
|
2189
|
-
* -
|
|
2189
|
+
* - tool: tool name (e.g., 'show-albums') — selects tool without mock data
|
|
2190
2190
|
* - prodResources: 'true' | 'false'
|
|
2191
2191
|
*/
|
|
2192
2192
|
function parseUrlParams() {
|
|
2193
2193
|
if (typeof window === "undefined") return {};
|
|
2194
2194
|
const params = new URLSearchParams(window.location.search);
|
|
2195
2195
|
const simulation = params.get("simulation") ?? void 0;
|
|
2196
|
+
const tool = params.get("tool") ?? void 0;
|
|
2196
2197
|
const theme = params.get("theme");
|
|
2197
2198
|
const displayMode = params.get("displayMode");
|
|
2198
2199
|
const locale = params.get("locale");
|
|
@@ -2201,8 +2202,6 @@ function parseUrlParams() {
|
|
|
2201
2202
|
const maxWidthParam = params.get("maxWidth");
|
|
2202
2203
|
const containerMaxWidth = maxWidthParam ? Number(maxWidthParam) : void 0;
|
|
2203
2204
|
const host = params.get("host") ?? void 0;
|
|
2204
|
-
const prodToolsParam = params.get("prodTools");
|
|
2205
|
-
const prodTools = prodToolsParam === "true" ? true : prodToolsParam === "false" ? false : void 0;
|
|
2206
2205
|
const prodResourcesParam = params.get("prodResources");
|
|
2207
2206
|
const prodResources = prodResourcesParam === "true" ? true : prodResourcesParam === "false" ? false : void 0;
|
|
2208
2207
|
const deviceType = params.get("deviceType");
|
|
@@ -2227,6 +2226,7 @@ function parseUrlParams() {
|
|
|
2227
2226
|
} : void 0;
|
|
2228
2227
|
return {
|
|
2229
2228
|
simulation,
|
|
2229
|
+
tool,
|
|
2230
2230
|
theme: theme ?? void 0,
|
|
2231
2231
|
displayMode: displayMode ?? void 0,
|
|
2232
2232
|
locale: locale ?? void 0,
|
|
@@ -2236,7 +2236,6 @@ function parseUrlParams() {
|
|
|
2236
2236
|
deviceCapabilities,
|
|
2237
2237
|
safeAreaInsets,
|
|
2238
2238
|
host: host ?? void 0,
|
|
2239
|
-
prodTools,
|
|
2240
2239
|
prodResources
|
|
2241
2240
|
};
|
|
2242
2241
|
}
|
|
@@ -2487,7 +2486,7 @@ function useSimulatorState({ simulations, defaultHost = "chatgpt" }) {
|
|
|
2487
2486
|
csp,
|
|
2488
2487
|
permissions: resourceMeta?.permissions,
|
|
2489
2488
|
prefersBorder: resourceMeta?.prefersBorder ?? false,
|
|
2490
|
-
|
|
2489
|
+
urlTool: urlParams.tool,
|
|
2491
2490
|
urlProdResources: urlParams.prodResources
|
|
2492
2491
|
};
|
|
2493
2492
|
}
|
|
@@ -2496,17 +2495,21 @@ function useSimulatorState({ simulations, defaultHost = "chatgpt" }) {
|
|
|
2496
2495
|
/**
|
|
2497
2496
|
* Hook for managing MCP server connection status via the dev server proxy.
|
|
2498
2497
|
*
|
|
2499
|
-
* On mount (when `
|
|
2500
|
-
* by fetching `/__sunpeak/list-tools`.
|
|
2501
|
-
*
|
|
2498
|
+
* On mount (when `initialServerUrl` is provided), verifies the connection is alive
|
|
2499
|
+
* by fetching `/__sunpeak/list-tools`. URL changes are handled by the caller
|
|
2500
|
+
* via `reconnect()`, which posts to `/__sunpeak/connect`.
|
|
2502
2501
|
*
|
|
2503
|
-
*
|
|
2504
|
-
*
|
|
2502
|
+
* This split avoids React StrictMode issues: the mount-only health check runs
|
|
2503
|
+
* once (or safely twice with cancellation), while explicit `reconnect()` calls
|
|
2504
|
+
* are triggered by the Simulator's URL-change effect.
|
|
2505
2505
|
*/
|
|
2506
|
-
function useMcpConnection(
|
|
2507
|
-
const [status, setStatus] = (0, react.useState)(
|
|
2506
|
+
function useMcpConnection(initialServerUrl) {
|
|
2507
|
+
const [status, setStatus] = (0, react.useState)(initialServerUrl ? "connecting" : "disconnected");
|
|
2508
2508
|
const [error, setError] = (0, react.useState)();
|
|
2509
|
+
const [simulations, setSimulations] = (0, react.useState)();
|
|
2510
|
+
const [hasReconnected, setHasReconnected] = (0, react.useState)(false);
|
|
2509
2511
|
const reconnect = (0, react.useCallback)(async (url) => {
|
|
2512
|
+
setHasReconnected(true);
|
|
2510
2513
|
setStatus("connecting");
|
|
2511
2514
|
setError(void 0);
|
|
2512
2515
|
try {
|
|
@@ -2516,23 +2519,27 @@ function useMcpConnection(serverUrl) {
|
|
|
2516
2519
|
body: JSON.stringify({ url })
|
|
2517
2520
|
});
|
|
2518
2521
|
if (!res.ok) {
|
|
2519
|
-
|
|
2520
|
-
|
|
2522
|
+
let message = `Connection failed (${res.status})`;
|
|
2523
|
+
try {
|
|
2524
|
+
const json = await res.json();
|
|
2525
|
+
if (json.error) message = json.error;
|
|
2526
|
+
} catch {}
|
|
2527
|
+
throw new Error(message);
|
|
2521
2528
|
}
|
|
2529
|
+
const data = await res.json();
|
|
2522
2530
|
setStatus("connected");
|
|
2531
|
+
setSimulations(data.simulations ?? void 0);
|
|
2523
2532
|
} catch (err) {
|
|
2524
2533
|
setError(err instanceof Error ? err.message : String(err));
|
|
2525
2534
|
setStatus("error");
|
|
2535
|
+
setSimulations(void 0);
|
|
2526
2536
|
}
|
|
2527
2537
|
}, []);
|
|
2528
2538
|
(0, react.useEffect)(() => {
|
|
2529
|
-
if (!
|
|
2530
|
-
setStatus("disconnected");
|
|
2531
|
-
return;
|
|
2532
|
-
}
|
|
2539
|
+
if (!initialServerUrl) return;
|
|
2533
2540
|
let cancelled = false;
|
|
2541
|
+
setStatus("connecting");
|
|
2534
2542
|
(async () => {
|
|
2535
|
-
setStatus("connecting");
|
|
2536
2543
|
try {
|
|
2537
2544
|
const res = await fetch("/__sunpeak/list-tools");
|
|
2538
2545
|
if (cancelled) return;
|
|
@@ -2547,10 +2554,12 @@ function useMcpConnection(serverUrl) {
|
|
|
2547
2554
|
return () => {
|
|
2548
2555
|
cancelled = true;
|
|
2549
2556
|
};
|
|
2550
|
-
}, [
|
|
2557
|
+
}, []);
|
|
2551
2558
|
return {
|
|
2552
2559
|
status,
|
|
2553
2560
|
error,
|
|
2561
|
+
simulations,
|
|
2562
|
+
hasReconnected,
|
|
2554
2563
|
reconnect
|
|
2555
2564
|
};
|
|
2556
2565
|
}
|
|
@@ -2704,7 +2713,7 @@ function SimpleSidebar({ children, controls, headerRight }) {
|
|
|
2704
2713
|
]
|
|
2705
2714
|
});
|
|
2706
2715
|
}
|
|
2707
|
-
var DOCS_BASE_URL = "https://sunpeak.ai/docs";
|
|
2716
|
+
var DOCS_BASE_URL$1 = "https://sunpeak.ai/docs";
|
|
2708
2717
|
function HelpIcon({ tooltip, docsPath }) {
|
|
2709
2718
|
const [pos, setPos] = react.useState(null);
|
|
2710
2719
|
const ref = react.useRef(null);
|
|
@@ -2717,7 +2726,7 @@ function HelpIcon({ tooltip, docsPath }) {
|
|
|
2717
2726
|
};
|
|
2718
2727
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
|
|
2719
2728
|
ref,
|
|
2720
|
-
href: `${DOCS_BASE_URL}/${docsPath}`,
|
|
2729
|
+
href: `${DOCS_BASE_URL$1}/${docsPath}`,
|
|
2721
2730
|
target: "_blank",
|
|
2722
2731
|
rel: "noopener noreferrer",
|
|
2723
2732
|
className: "inline-flex items-center justify-center no-underline flex-shrink-0 transition-colors",
|
|
@@ -2839,6 +2848,13 @@ function SidebarInput({ value, onChange, applyOnBlur = false, placeholder, type
|
|
|
2839
2848
|
setIsEditing(false);
|
|
2840
2849
|
onChange(draft);
|
|
2841
2850
|
},
|
|
2851
|
+
onKeyDown: (e) => {
|
|
2852
|
+
if (e.key === "Enter") {
|
|
2853
|
+
setIsEditing(false);
|
|
2854
|
+
onChange(draft);
|
|
2855
|
+
e.target.blur();
|
|
2856
|
+
}
|
|
2857
|
+
},
|
|
2842
2858
|
placeholder,
|
|
2843
2859
|
disabled,
|
|
2844
2860
|
className: "w-full h-7 text-xs rounded-md px-2 outline-none disabled:opacity-50 disabled:cursor-not-allowed",
|
|
@@ -2949,54 +2965,142 @@ function resolveServerToolResult(mock, args) {
|
|
|
2949
2965
|
}
|
|
2950
2966
|
//#endregion
|
|
2951
2967
|
//#region src/simulator/simulator.tsx
|
|
2952
|
-
|
|
2953
|
-
|
|
2968
|
+
var DOCS_BASE_URL = "https://sunpeak.ai/docs";
|
|
2969
|
+
/** Check whether a simulation has user-authored fixture data. */
|
|
2970
|
+
function hasFixtureData(sim) {
|
|
2971
|
+
return sim.toolResult != null || sim.toolInput != null || sim.serverTools != null;
|
|
2972
|
+
}
|
|
2973
|
+
function Simulator({ children, simulations: initialSimulations = {}, appName = "Sunpeak", appIcon, defaultHost = "chatgpt", onCallTool, onCallToolDirect, defaultProdResources = false, hideSimulatorModes = false, demoMode = false, sandboxUrl, mcpServerUrl }) {
|
|
2974
|
+
const [simulations, setSimulations] = react.useState(initialSimulations);
|
|
2975
|
+
react.useEffect(() => {
|
|
2976
|
+
setSimulations(initialSimulations);
|
|
2977
|
+
}, [initialSimulations]);
|
|
2978
|
+
const toolMap = react.useMemo(() => {
|
|
2979
|
+
const map = /* @__PURE__ */ new Map();
|
|
2980
|
+
for (const [simName, sim] of Object.entries(simulations)) {
|
|
2981
|
+
if (!sim.resource) continue;
|
|
2982
|
+
const toolName = sim.tool.name;
|
|
2983
|
+
if (!map.has(toolName)) map.set(toolName, {
|
|
2984
|
+
tool: sim.tool,
|
|
2985
|
+
resource: sim.resource,
|
|
2986
|
+
simNames: [],
|
|
2987
|
+
fixtureSimNames: []
|
|
2988
|
+
});
|
|
2989
|
+
const info = map.get(toolName);
|
|
2990
|
+
info.simNames.push(simName);
|
|
2991
|
+
if (hasFixtureData(sim)) info.fixtureSimNames.push(simName);
|
|
2992
|
+
}
|
|
2993
|
+
return map;
|
|
2994
|
+
}, [simulations]);
|
|
2995
|
+
const toolNames = react.useMemo(() => Array.from(toolMap.keys()).sort((a, b) => {
|
|
2996
|
+
const infoA = toolMap.get(a);
|
|
2997
|
+
const infoB = toolMap.get(b);
|
|
2998
|
+
const labelA = infoA.tool.title || a;
|
|
2999
|
+
const labelB = infoB.tool.title || b;
|
|
3000
|
+
return labelA.localeCompare(labelB);
|
|
3001
|
+
}), [toolMap]);
|
|
3002
|
+
const initUrlParams = react.useMemo(() => {
|
|
3003
|
+
if (typeof window === "undefined") return {
|
|
3004
|
+
tool: null,
|
|
3005
|
+
simulation: null,
|
|
3006
|
+
noMockData: false
|
|
3007
|
+
};
|
|
3008
|
+
const params = new URLSearchParams(window.location.search);
|
|
3009
|
+
const prodTools = params.get("prodTools") === "true";
|
|
3010
|
+
return {
|
|
3011
|
+
tool: params.get("tool"),
|
|
3012
|
+
simulation: params.get("simulation"),
|
|
3013
|
+
noMockData: prodTools
|
|
3014
|
+
};
|
|
3015
|
+
}, []);
|
|
3016
|
+
const [selectedToolName, setSelectedToolName] = react.useState(() => {
|
|
3017
|
+
if (initUrlParams.tool && toolMap.has(initUrlParams.tool)) return initUrlParams.tool;
|
|
3018
|
+
if (initUrlParams.simulation) {
|
|
3019
|
+
for (const [toolName, info] of toolMap) if (info.simNames.includes(initUrlParams.simulation)) return toolName;
|
|
3020
|
+
}
|
|
3021
|
+
return toolNames[0] ?? "";
|
|
3022
|
+
});
|
|
3023
|
+
const prevToolNamesRef = react.useRef(toolNames);
|
|
3024
|
+
if (prevToolNamesRef.current !== toolNames) {
|
|
3025
|
+
prevToolNamesRef.current = toolNames;
|
|
3026
|
+
if (toolNames.length > 0 && !toolMap.has(selectedToolName)) setSelectedToolName(toolNames[0]);
|
|
3027
|
+
}
|
|
3028
|
+
const selectedToolInfo = toolMap.get(selectedToolName);
|
|
3029
|
+
const [activeSimulationName, setActiveSimulationName] = react.useState(() => {
|
|
3030
|
+
if (!selectedToolInfo) return null;
|
|
3031
|
+
if (initUrlParams.noMockData) return null;
|
|
3032
|
+
if (initUrlParams.tool && !initUrlParams.simulation) return null;
|
|
3033
|
+
if (initUrlParams.simulation && selectedToolInfo.fixtureSimNames.includes(initUrlParams.simulation)) return initUrlParams.simulation;
|
|
3034
|
+
return selectedToolInfo.fixtureSimNames[0] ?? null;
|
|
3035
|
+
});
|
|
3036
|
+
const prevToolNameRef = react.useRef(selectedToolName);
|
|
3037
|
+
if (prevToolNameRef.current !== selectedToolName) {
|
|
3038
|
+
prevToolNameRef.current = selectedToolName;
|
|
3039
|
+
setActiveSimulationName(toolMap.get(selectedToolName)?.fixtureSimNames[0] ?? null);
|
|
3040
|
+
}
|
|
3041
|
+
const effectiveSimulationName = activeSimulationName ?? selectedToolInfo?.simNames[0] ?? "";
|
|
3042
|
+
const currentSim = simulations[effectiveSimulationName];
|
|
2954
3043
|
const state = useSimulatorState({
|
|
2955
3044
|
simulations,
|
|
2956
3045
|
defaultHost
|
|
2957
3046
|
});
|
|
2958
|
-
const
|
|
2959
|
-
const
|
|
3047
|
+
const [serverUrl, setServerUrl] = react.useState(mcpServerUrl ?? "");
|
|
3048
|
+
const connection = useMcpConnection(mcpServerUrl || void 0);
|
|
2960
3049
|
const [prodResources, setProdResources] = react.useState(state.urlProdResources ?? defaultProdResources);
|
|
2961
3050
|
const [isRunning, setIsRunning] = react.useState(false);
|
|
2962
3051
|
const [hasRun, setHasRun] = react.useState(false);
|
|
2963
3052
|
const [showCheck, setShowCheck] = react.useState(false);
|
|
2964
3053
|
const checkTimerRef = react.useRef(void 0);
|
|
2965
3054
|
react.useEffect(() => {
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
3055
|
+
state.setSelectedSimulationName(effectiveSimulationName);
|
|
3056
|
+
}, [effectiveSimulationName]);
|
|
3057
|
+
const prevServerUrlRef = react.useRef(serverUrl);
|
|
3058
|
+
react.useEffect(() => {
|
|
3059
|
+
const urlChanged = serverUrl !== prevServerUrlRef.current;
|
|
3060
|
+
prevServerUrlRef.current = serverUrl;
|
|
3061
|
+
if (!urlChanged) return;
|
|
3062
|
+
if (serverUrl) connection.reconnect(serverUrl);
|
|
3063
|
+
}, [serverUrl, connection.reconnect]);
|
|
3064
|
+
react.useEffect(() => {
|
|
3065
|
+
if (connection.simulations) setSimulations(connection.simulations);
|
|
3066
|
+
else if (connection.status === "error" && connection.hasReconnected) setSimulations({});
|
|
3067
|
+
}, [
|
|
3068
|
+
connection.simulations,
|
|
3069
|
+
connection.status,
|
|
3070
|
+
connection.hasReconnected
|
|
3071
|
+
]);
|
|
3072
|
+
const { setToolResult, setToolResultJson, setToolResultError } = state;
|
|
3073
|
+
react.useEffect(() => {
|
|
3074
|
+
if (activeSimulationName === null) {
|
|
3075
|
+
setToolResult(void 0);
|
|
3076
|
+
setToolResultJson("");
|
|
3077
|
+
setToolResultError("");
|
|
2971
3078
|
} else {
|
|
2972
|
-
const
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
react.useEffect(() => () => clearTimeout(checkTimerRef.current), []);
|
|
2977
|
-
const toolOptions = react.useMemo(() => {
|
|
2978
|
-
if (!prodTools) return [];
|
|
2979
|
-
const seen = /* @__PURE__ */ new Map();
|
|
2980
|
-
for (const simName of state.simulationNames) {
|
|
2981
|
-
const toolName = simulations[simName].tool.name;
|
|
2982
|
-
if (!seen.has(toolName)) seen.set(toolName, simName);
|
|
3079
|
+
const result = simulations[activeSimulationName]?.toolResult ?? void 0;
|
|
3080
|
+
setToolResult(result);
|
|
3081
|
+
setToolResultJson(result ? JSON.stringify(result, null, 2) : "");
|
|
3082
|
+
setToolResultError("");
|
|
2983
3083
|
}
|
|
2984
|
-
return Array.from(seen.entries()).map(([toolName, simName]) => ({
|
|
2985
|
-
value: simName,
|
|
2986
|
-
label: simulations[simName].tool.title || toolName
|
|
2987
|
-
}));
|
|
2988
3084
|
}, [
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
simulations
|
|
3085
|
+
activeSimulationName,
|
|
3086
|
+
effectiveSimulationName,
|
|
3087
|
+
simulations,
|
|
3088
|
+
setToolResult,
|
|
3089
|
+
setToolResultJson,
|
|
3090
|
+
setToolResultError
|
|
2992
3091
|
]);
|
|
3092
|
+
react.useEffect(() => {
|
|
3093
|
+
setHasRun(false);
|
|
3094
|
+
}, [effectiveSimulationName]);
|
|
3095
|
+
react.useEffect(() => () => clearTimeout(checkTimerRef.current), []);
|
|
2993
3096
|
const handleRun = react.useCallback(async () => {
|
|
2994
3097
|
const caller = onCallToolDirect ?? onCallTool;
|
|
2995
|
-
|
|
2996
|
-
|
|
3098
|
+
const sim = simulations[effectiveSimulationName];
|
|
3099
|
+
if (!caller || !sim) return;
|
|
3100
|
+
const toolName = sim.tool.name;
|
|
2997
3101
|
setIsRunning(true);
|
|
2998
3102
|
try {
|
|
2999
|
-
const result =
|
|
3103
|
+
const result = await caller({
|
|
3000
3104
|
name: toolName,
|
|
3001
3105
|
arguments: state.toolInput
|
|
3002
3106
|
});
|
|
@@ -3023,14 +3127,16 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3023
3127
|
}],
|
|
3024
3128
|
isError: true
|
|
3025
3129
|
}, null, 2));
|
|
3130
|
+
setHasRun(true);
|
|
3026
3131
|
} finally {
|
|
3027
3132
|
setIsRunning(false);
|
|
3028
3133
|
}
|
|
3029
3134
|
}, [
|
|
3030
3135
|
onCallTool,
|
|
3031
3136
|
onCallToolDirect,
|
|
3032
|
-
|
|
3033
|
-
|
|
3137
|
+
simulations,
|
|
3138
|
+
effectiveSimulationName,
|
|
3139
|
+
state
|
|
3034
3140
|
]);
|
|
3035
3141
|
const activeShell = getHostShell(state.activeHost);
|
|
3036
3142
|
const registeredHosts = getRegisteredHosts();
|
|
@@ -3064,8 +3170,8 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3064
3170
|
} else prevPageStyleKeysRef.current = [];
|
|
3065
3171
|
}, [activeShell]);
|
|
3066
3172
|
const handleCallTool = react.useCallback((params) => {
|
|
3067
|
-
if (
|
|
3068
|
-
const mock =
|
|
3173
|
+
if (activeSimulationName) {
|
|
3174
|
+
const mock = simulations[activeSimulationName]?.serverTools?.[params.name];
|
|
3069
3175
|
if (mock) {
|
|
3070
3176
|
const result = resolveServerToolResult(mock, params.arguments);
|
|
3071
3177
|
if (result) return result;
|
|
@@ -3074,15 +3180,15 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3074
3180
|
if (onCallTool) return onCallTool(params);
|
|
3075
3181
|
return { content: [{
|
|
3076
3182
|
type: "text",
|
|
3077
|
-
text: `[Simulator] Tool "${params.name}" called — no serverTools mock found in simulation "${
|
|
3183
|
+
text: `[Simulator] Tool "${params.name}" called — no serverTools mock found in simulation "${effectiveSimulationName}".`
|
|
3078
3184
|
}] };
|
|
3079
3185
|
}, [
|
|
3080
3186
|
onCallTool,
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3187
|
+
activeSimulationName,
|
|
3188
|
+
simulations,
|
|
3189
|
+
effectiveSimulationName
|
|
3084
3190
|
]);
|
|
3085
|
-
const
|
|
3191
|
+
const userMessage = currentSim ? currentSim.userMessage ?? `Call my ${currentSim.tool.title || currentSim.tool.name} tool` : void 0;
|
|
3086
3192
|
const prodResourcesPath = react.useMemo(() => {
|
|
3087
3193
|
if (!prodResources || !state.selectedSim?.resource) return void 0;
|
|
3088
3194
|
const name = state.selectedSim.resource.name;
|
|
@@ -3123,10 +3229,23 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3123
3229
|
}, [prodResourcesPath]);
|
|
3124
3230
|
const effectiveResourceUrl = (prodResourcesPath && prodResourcesReady ? prodResourcesPath : void 0) ?? state.resourceUrl;
|
|
3125
3231
|
const prodResourcesLoading = !!prodResourcesPath && !prodResourcesReady;
|
|
3126
|
-
const
|
|
3232
|
+
const hasTools = toolNames.length > 0;
|
|
3233
|
+
const showEmptyState = !(activeSimulationName !== null && currentSim?.toolResult != null) && !hasRun;
|
|
3127
3234
|
let content;
|
|
3128
3235
|
const iframeBg = "var(--sim-bg-conversation, var(--color-background-primary, transparent))";
|
|
3129
|
-
if (
|
|
3236
|
+
if (!hasTools) {
|
|
3237
|
+
const isConnected = connection.status === "connected";
|
|
3238
|
+
const isError = connection.status === "error";
|
|
3239
|
+
content = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3240
|
+
className: "h-full w-full flex items-center justify-center",
|
|
3241
|
+
style: { background: iframeBg },
|
|
3242
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3243
|
+
className: "text-sm text-center max-w-xs",
|
|
3244
|
+
style: { color: "var(--color-text-secondary)" },
|
|
3245
|
+
children: isError ? "Could not connect to MCP server" : isConnected ? "No tools with UI resources found on this server" : serverUrl ? "Connecting…" : "Enter an MCP server URL to get started"
|
|
3246
|
+
})
|
|
3247
|
+
});
|
|
3248
|
+
} else if (showEmptyState) content = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3130
3249
|
className: "h-full w-full flex items-center justify-center",
|
|
3131
3250
|
style: { background: iframeBg },
|
|
3132
3251
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
@@ -3170,7 +3289,7 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3170
3289
|
injectOpenAIRuntime: state.activeHost === "chatgpt",
|
|
3171
3290
|
sandboxUrl,
|
|
3172
3291
|
className: "h-full w-full"
|
|
3173
|
-
}, `${state.activeHost}-${
|
|
3292
|
+
}, `${state.activeHost}-${effectiveResourceUrl}-${prodResources}-${prodResourcesGeneration}`)
|
|
3174
3293
|
});
|
|
3175
3294
|
else if (!prodResources && state.resourceScript) content = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3176
3295
|
className: "h-full w-full",
|
|
@@ -3195,10 +3314,37 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3195
3314
|
injectOpenAIRuntime: state.activeHost === "chatgpt",
|
|
3196
3315
|
sandboxUrl,
|
|
3197
3316
|
className: "h-full w-full"
|
|
3198
|
-
}, `${state.activeHost}-${state.
|
|
3317
|
+
}, `${state.activeHost}-${state.resourceScript}`)
|
|
3199
3318
|
});
|
|
3200
3319
|
else content = children;
|
|
3201
3320
|
const applyTheme = activeShell?.applyTheme;
|
|
3321
|
+
const runButton = !demoMode && onCallTool && currentSim && activeSimulationName === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3322
|
+
type: "button",
|
|
3323
|
+
onClick: handleRun,
|
|
3324
|
+
disabled: isRunning,
|
|
3325
|
+
className: "rounded-full px-3 py-1 text-sm font-medium transition-opacity disabled:opacity-40 flex items-center gap-1.5 cursor-pointer",
|
|
3326
|
+
style: {
|
|
3327
|
+
backgroundColor: "var(--color-text-primary)",
|
|
3328
|
+
color: "var(--color-background-primary)"
|
|
3329
|
+
},
|
|
3330
|
+
children: [showCheck ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
3331
|
+
width: "12",
|
|
3332
|
+
height: "12",
|
|
3333
|
+
viewBox: "0 0 12 12",
|
|
3334
|
+
fill: "none",
|
|
3335
|
+
stroke: "currentColor",
|
|
3336
|
+
strokeWidth: "2",
|
|
3337
|
+
strokeLinecap: "round",
|
|
3338
|
+
strokeLinejoin: "round",
|
|
3339
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2 6L5 9L10 3" })
|
|
3340
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
3341
|
+
width: "10",
|
|
3342
|
+
height: "12",
|
|
3343
|
+
viewBox: "0 0 10 12",
|
|
3344
|
+
fill: "currentColor",
|
|
3345
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M0 0L10 6L0 12V0Z" })
|
|
3346
|
+
}), "Run"]
|
|
3347
|
+
}) : void 0;
|
|
3202
3348
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeProvider, {
|
|
3203
3349
|
theme: state.theme,
|
|
3204
3350
|
applyTheme,
|
|
@@ -3206,39 +3352,82 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3206
3352
|
controls: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3207
3353
|
className: "space-y-1",
|
|
3208
3354
|
children: [
|
|
3209
|
-
|
|
3355
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarControl, {
|
|
3210
3356
|
label: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3211
3357
|
className: "flex items-center gap-1.5",
|
|
3212
|
-
children: ["MCP Server", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3358
|
+
children: ["MCP Server", serverUrl && !demoMode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3213
3359
|
className: "inline-block w-2 h-2 rounded-full",
|
|
3214
|
-
"data-testid": "
|
|
3360
|
+
"data-testid": "connection-status",
|
|
3215
3361
|
style: { backgroundColor: connection.status === "connected" ? "#22c55e" : connection.status === "connecting" ? "#eab308" : connection.status === "error" ? "#ef4444" : "#6b7280" },
|
|
3216
3362
|
title: connection.error ?? connection.status
|
|
3217
3363
|
})]
|
|
3218
3364
|
}),
|
|
3219
|
-
tooltip: "MCP server URL
|
|
3220
|
-
"data-testid": "
|
|
3365
|
+
tooltip: "MCP server URL",
|
|
3366
|
+
"data-testid": "server-url",
|
|
3221
3367
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarInput, {
|
|
3222
|
-
value:
|
|
3223
|
-
onChange: () => {},
|
|
3224
|
-
|
|
3225
|
-
placeholder: "http://localhost:8000/mcp"
|
|
3368
|
+
value: demoMode ? "http://localhost:8000/mcp" : serverUrl,
|
|
3369
|
+
onChange: demoMode ? () => {} : setServerUrl,
|
|
3370
|
+
applyOnBlur: true,
|
|
3371
|
+
placeholder: "http://localhost:8000/mcp",
|
|
3372
|
+
disabled: demoMode
|
|
3226
3373
|
})
|
|
3227
3374
|
}),
|
|
3228
|
-
!
|
|
3229
|
-
checked: prodTools,
|
|
3230
|
-
onChange: setProdTools,
|
|
3231
|
-
label: "Prod Tools",
|
|
3232
|
-
tooltip: "Use real tool handlers instead of simulations",
|
|
3233
|
-
docsPath: "api-reference/cli/dev#prod-tools-and-prod-resources-flags"
|
|
3234
|
-
}),
|
|
3235
|
-
!isInspectMode && !hideSimulatorModes && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarCheckbox, {
|
|
3375
|
+
!hideSimulatorModes && !demoMode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarCheckbox, {
|
|
3236
3376
|
checked: prodResources,
|
|
3237
3377
|
onChange: setProdResources,
|
|
3238
3378
|
label: "Prod Resources",
|
|
3239
3379
|
tooltip: "Load resources from dist/ builds instead of HMR",
|
|
3240
3380
|
docsPath: "api-reference/cli/dev#prod-tools-and-prod-resources-flags"
|
|
3241
3381
|
}),
|
|
3382
|
+
hasTools && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3383
|
+
className: "grid grid-cols-2 gap-2",
|
|
3384
|
+
"data-testid": "tool-simulation-row",
|
|
3385
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarControl, {
|
|
3386
|
+
label: "Tool",
|
|
3387
|
+
tooltip: "Tool to inspect",
|
|
3388
|
+
docsPath: "api-reference/cli/dev",
|
|
3389
|
+
"data-testid": "tool-selector",
|
|
3390
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSelect, {
|
|
3391
|
+
value: selectedToolName,
|
|
3392
|
+
onChange: (value) => setSelectedToolName(value),
|
|
3393
|
+
options: toolNames.map((name) => {
|
|
3394
|
+
return {
|
|
3395
|
+
value: name,
|
|
3396
|
+
label: toolMap.get(name).tool.title || name
|
|
3397
|
+
};
|
|
3398
|
+
})
|
|
3399
|
+
})
|
|
3400
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarControl, {
|
|
3401
|
+
label: selectedToolInfo && selectedToolInfo.fixtureSimNames.length > 0 ? "Simulation" : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3402
|
+
href: `${DOCS_BASE_URL}/api-reference/simulations/simulation`,
|
|
3403
|
+
target: "_blank",
|
|
3404
|
+
rel: "noopener noreferrer",
|
|
3405
|
+
className: "no-underline transition-colors",
|
|
3406
|
+
style: { color: "var(--color-text-secondary)" },
|
|
3407
|
+
onMouseEnter: (e) => {
|
|
3408
|
+
e.target.style.color = "var(--color-text-primary)";
|
|
3409
|
+
},
|
|
3410
|
+
onMouseLeave: (e) => {
|
|
3411
|
+
e.target.style.color = "var(--color-text-secondary)";
|
|
3412
|
+
},
|
|
3413
|
+
children: "Simulation"
|
|
3414
|
+
}),
|
|
3415
|
+
tooltip: selectedToolInfo && selectedToolInfo.fixtureSimNames.length > 0 ? "Test fixture with mock data" : "Create simulations for faster testing",
|
|
3416
|
+
docsPath: "api-reference/simulations/simulation",
|
|
3417
|
+
"data-testid": "simulation-selector",
|
|
3418
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSelect, {
|
|
3419
|
+
value: activeSimulationName ?? "__none__",
|
|
3420
|
+
onChange: (value) => setActiveSimulationName(value === "__none__" ? null : value),
|
|
3421
|
+
options: [...demoMode ? [] : [{
|
|
3422
|
+
value: "__none__",
|
|
3423
|
+
label: selectedToolInfo && selectedToolInfo.fixtureSimNames.length > 0 ? "None (call server)" : "None"
|
|
3424
|
+
}], ...(selectedToolInfo?.fixtureSimNames ?? []).map((simName) => ({
|
|
3425
|
+
value: simName,
|
|
3426
|
+
label: simName
|
|
3427
|
+
}))]
|
|
3428
|
+
})
|
|
3429
|
+
})]
|
|
3430
|
+
}),
|
|
3242
3431
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3243
3432
|
className: "grid grid-cols-2 gap-2",
|
|
3244
3433
|
children: [registeredHosts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarControl, {
|
|
@@ -3281,34 +3470,6 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3281
3470
|
})
|
|
3282
3471
|
})]
|
|
3283
3472
|
}),
|
|
3284
|
-
prodTools && toolOptions.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarControl, {
|
|
3285
|
-
label: "Tool",
|
|
3286
|
-
tooltip: "Tool to call with prod handler",
|
|
3287
|
-
docsPath: "api-reference/cli/dev",
|
|
3288
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSelect, {
|
|
3289
|
-
value: state.selectedSimulationName,
|
|
3290
|
-
onChange: (value) => state.setSelectedSimulationName(value),
|
|
3291
|
-
options: toolOptions
|
|
3292
|
-
})
|
|
3293
|
-
}),
|
|
3294
|
-
!prodTools && state.simulationNames.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarControl, {
|
|
3295
|
-
label: "Simulation",
|
|
3296
|
-
tooltip: "Test fixture to render",
|
|
3297
|
-
docsPath: "api-reference/simulations/simulation",
|
|
3298
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSelect, {
|
|
3299
|
-
value: state.selectedSimulationName,
|
|
3300
|
-
onChange: (value) => state.setSelectedSimulationName(value),
|
|
3301
|
-
options: state.simulationNames.map((name) => {
|
|
3302
|
-
const sim = simulations[name];
|
|
3303
|
-
const resourceTitle = sim.resource ? sim.resource.title || sim.resource.name : void 0;
|
|
3304
|
-
const toolTitle = sim.tool.title || sim.tool.name;
|
|
3305
|
-
return {
|
|
3306
|
-
value: name,
|
|
3307
|
-
label: resourceTitle ? `${resourceTitle}: ${toolTitle}` : toolTitle
|
|
3308
|
-
};
|
|
3309
|
-
})
|
|
3310
|
-
})
|
|
3311
|
-
}),
|
|
3312
3473
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarCollapsibleControl, {
|
|
3313
3474
|
label: "Host Context",
|
|
3314
3475
|
defaultCollapsed: false,
|
|
@@ -3590,7 +3751,7 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3590
3751
|
}),
|
|
3591
3752
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarCollapsibleControl, {
|
|
3592
3753
|
label: "Tool Input (JSON)",
|
|
3593
|
-
defaultCollapsed:
|
|
3754
|
+
defaultCollapsed: false,
|
|
3594
3755
|
tooltip: "Arguments passed to the tool",
|
|
3595
3756
|
docsPath: "api-reference/hooks/use-tool-data",
|
|
3596
3757
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarTextarea, {
|
|
@@ -3601,10 +3762,10 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3601
3762
|
error: state.toolInputError,
|
|
3602
3763
|
maxRows: 8
|
|
3603
3764
|
})
|
|
3604
|
-
}
|
|
3765
|
+
}),
|
|
3605
3766
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarCollapsibleControl, {
|
|
3606
3767
|
label: "Tool Result (JSON)",
|
|
3607
|
-
defaultCollapsed:
|
|
3768
|
+
defaultCollapsed: false,
|
|
3608
3769
|
tooltip: "Structured content returned by the tool",
|
|
3609
3770
|
docsPath: "api-reference/hooks/use-tool-data",
|
|
3610
3771
|
"data-testid": "tool-result-section",
|
|
@@ -3627,7 +3788,7 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3627
3788
|
error: state.toolResultError,
|
|
3628
3789
|
maxRows: 8
|
|
3629
3790
|
})
|
|
3630
|
-
}
|
|
3791
|
+
})
|
|
3631
3792
|
]
|
|
3632
3793
|
}),
|
|
3633
3794
|
children: ShellConversation ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShellConversation, {
|
|
@@ -3637,35 +3798,9 @@ function Simulator({ children, simulations = {}, appName = "Sunpeak", appIcon, d
|
|
|
3637
3798
|
onRequestDisplayMode: state.handleDisplayModeChange,
|
|
3638
3799
|
appName,
|
|
3639
3800
|
appIcon,
|
|
3640
|
-
userMessage
|
|
3801
|
+
userMessage,
|
|
3641
3802
|
onContentWidthChange: state.handleContentWidthChange,
|
|
3642
|
-
headerAction:
|
|
3643
|
-
type: "button",
|
|
3644
|
-
onClick: handleRun,
|
|
3645
|
-
disabled: isRunning,
|
|
3646
|
-
className: "rounded-full px-3 py-1 text-sm font-medium transition-opacity disabled:opacity-40 flex items-center gap-1.5 cursor-pointer",
|
|
3647
|
-
style: {
|
|
3648
|
-
backgroundColor: "var(--color-text-primary)",
|
|
3649
|
-
color: "var(--color-background-primary)"
|
|
3650
|
-
},
|
|
3651
|
-
children: [showCheck ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
3652
|
-
width: "12",
|
|
3653
|
-
height: "12",
|
|
3654
|
-
viewBox: "0 0 12 12",
|
|
3655
|
-
fill: "none",
|
|
3656
|
-
stroke: "currentColor",
|
|
3657
|
-
strokeWidth: "2",
|
|
3658
|
-
strokeLinecap: "round",
|
|
3659
|
-
strokeLinejoin: "round",
|
|
3660
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2 6L5 9L10 3" })
|
|
3661
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
3662
|
-
width: "10",
|
|
3663
|
-
height: "12",
|
|
3664
|
-
viewBox: "0 0 10 12",
|
|
3665
|
-
fill: "currentColor",
|
|
3666
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M0 0L10 6L0 12V0Z" })
|
|
3667
|
-
}), "Run"]
|
|
3668
|
-
}) : void 0,
|
|
3803
|
+
headerAction: runButton,
|
|
3669
3804
|
children: content
|
|
3670
3805
|
}) : content
|
|
3671
3806
|
})
|
|
@@ -3805,4 +3940,4 @@ Object.defineProperty(exports, "useThemeContext", {
|
|
|
3805
3940
|
}
|
|
3806
3941
|
});
|
|
3807
3942
|
|
|
3808
|
-
//# sourceMappingURL=simulator-
|
|
3943
|
+
//# sourceMappingURL=simulator-DqWETA_1.cjs.map
|