sunpeak 0.20.36 → 0.20.47
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/README.md +4 -2
- package/bin/commands/inspect.mjs +291 -64
- package/bin/commands/test-init.mjs +6 -0
- package/bin/lib/eval/eval-runner.mjs +53 -1
- package/bin/lib/eval/eval-types.d.mts +27 -0
- package/bin/lib/eval/model-registry.mjs +2 -2
- package/dist/chatgpt/index.cjs +1 -1
- package/dist/chatgpt/index.js +1 -1
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/embed.css +1 -1
- package/dist/hooks/tool-data-store.d.ts +26 -0
- package/dist/hooks/use-tool-data.d.ts +3 -9
- package/dist/host/chatgpt/index.cjs +1 -1
- package/dist/host/chatgpt/index.js +1 -1
- package/dist/index.cjs +35 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +35 -21
- package/dist/index.js.map +1 -1
- package/dist/inspector/index.cjs +1 -1
- package/dist/inspector/index.js +1 -1
- package/dist/inspector/inspector.d.ts +7 -0
- package/dist/inspector/use-inspector-state.d.ts +28 -0
- package/dist/{inspector-CiuT_2yA.js → inspector-BSha-CAW.js} +216 -75
- package/dist/inspector-BSha-CAW.js.map +1 -0
- package/dist/{inspector-BNWla95w.cjs → inspector-Chhc2GNO.cjs} +216 -75
- package/dist/inspector-Chhc2GNO.cjs.map +1 -0
- package/dist/lib/utils.d.ts +8 -7
- package/dist/mcp/index.cjs +5 -3
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +5 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.d.ts +12 -1
- package/dist/style.css +22 -0
- package/dist/{use-app-Duar2Ipu.js → use-app-CtKy52kw.js} +62 -1
- package/dist/use-app-CtKy52kw.js.map +1 -0
- package/dist/{use-app-DUdnDLP5.cjs → use-app-xaiN0HAd.cjs} +62 -1
- package/dist/use-app-xaiN0HAd.cjs.map +1 -0
- package/package.json +8 -8
- 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 +4 -4
- 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/.bin/tsc +2 -2
- package/template/node_modules/.bin/tsserver +2 -2
- package/template/node_modules/.bin/vitest +2 -2
- package/template/node_modules/.vite/deps/_metadata.json +3 -3
- package/template/node_modules/.vite-mcp/deps/_metadata.json +20 -20
- package/template/node_modules/.vite-mcp/deps/vitest.js +7 -7
- package/template/node_modules/.vite-mcp/deps/vitest.js.map +1 -1
- package/template/package.json +1 -1
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-chatgpt-linux.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-linux.png +0 -0
- package/template/tsconfig.json +2 -0
- package/dist/inspector-BNWla95w.cjs.map +0 -1
- package/dist/inspector-CiuT_2yA.js.map +0 -1
- package/dist/use-app-DUdnDLP5.cjs.map +0 -1
- package/dist/use-app-Duar2Ipu.js.map +0 -1
|
@@ -3481,20 +3481,50 @@ var twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
|
|
|
3481
3481
|
function cn(...inputs) {
|
|
3482
3482
|
return twMerge(clsx(inputs));
|
|
3483
3483
|
}
|
|
3484
|
+
function currentPageIsLoopback() {
|
|
3485
|
+
if (typeof window === "undefined") return true;
|
|
3486
|
+
return isLocalNetworkHostname(window.location.hostname);
|
|
3487
|
+
}
|
|
3488
|
+
function normalizeHostname(hostname) {
|
|
3489
|
+
return hostname.toLowerCase().replace(/^\[(.*)\]$/, "$1");
|
|
3490
|
+
}
|
|
3491
|
+
function isLocalNetworkHostname(hostname) {
|
|
3492
|
+
const host = normalizeHostname(hostname);
|
|
3493
|
+
if (host === "localhost" || host === "0.0.0.0" || host === "::1") return true;
|
|
3494
|
+
if (host.startsWith("127.")) return true;
|
|
3495
|
+
const ipv4 = host.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
|
|
3496
|
+
if (ipv4) {
|
|
3497
|
+
const octets = ipv4.slice(1).map(Number);
|
|
3498
|
+
if (octets.some((octet) => octet < 0 || octet > 255)) return false;
|
|
3499
|
+
const [a, b] = octets;
|
|
3500
|
+
return a === 10 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 169 && b === 254;
|
|
3501
|
+
}
|
|
3502
|
+
return host.startsWith("fc") || host.startsWith("fd") || host.startsWith("fe80:");
|
|
3503
|
+
}
|
|
3484
3504
|
/**
|
|
3485
3505
|
* Returns true when `icon` is safe to use as the `src` of an `<img>` rendered
|
|
3486
|
-
* inside the inspector chrome. Accepts http
|
|
3487
|
-
*
|
|
3488
|
-
*
|
|
3489
|
-
*
|
|
3490
|
-
*
|
|
3491
|
-
*
|
|
3492
|
-
* text
|
|
3506
|
+
* inside the inspector chrome. Accepts https URLs, local http URLs while the
|
|
3507
|
+
* inspector itself is running locally, and `data:image/*` URIs for raster image
|
|
3508
|
+
* types only. SVG data URIs are rejected because they can include
|
|
3509
|
+
* `<script>`/event handlers that execute when the document parses the inline
|
|
3510
|
+
* document (the `<img>` tag itself does not run scripts in modern browsers,
|
|
3511
|
+
* but adjacent <object>/<embed>/<iframe> renders would). Anything else (emoji,
|
|
3512
|
+
* plain text, javascript:, file:, etc.) falls through to the text-rendering
|
|
3513
|
+
* path that already handles emoji icons.
|
|
3493
3514
|
*/
|
|
3494
3515
|
function isAllowedIconUrl(icon) {
|
|
3495
|
-
if (
|
|
3496
|
-
|
|
3497
|
-
|
|
3516
|
+
if (/^data:image\/(?:png|jpeg|gif|webp)(?:[;,]|$)/i.test(icon)) return true;
|
|
3517
|
+
let url;
|
|
3518
|
+
try {
|
|
3519
|
+
url = new URL(icon);
|
|
3520
|
+
} catch {
|
|
3521
|
+
return false;
|
|
3522
|
+
}
|
|
3523
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
3524
|
+
const inspectorIsLocal = currentPageIsLoopback();
|
|
3525
|
+
if (isLocalNetworkHostname(url.hostname) && !inspectorIsLocal) return false;
|
|
3526
|
+
if (url.protocol === "http:" && !inspectorIsLocal) return false;
|
|
3527
|
+
return true;
|
|
3498
3528
|
}
|
|
3499
3529
|
//#endregion
|
|
3500
3530
|
//#region src/inspector/hosts.ts
|
|
@@ -5992,16 +6022,12 @@ var SUNPEAK_INLINE_HELPER_SCRIPT = `
|
|
|
5992
6022
|
//#region src/inspector/iframe-resource.tsx
|
|
5993
6023
|
/**
|
|
5994
6024
|
* Allowed origins for cross-origin script loading.
|
|
5995
|
-
* - Local development: localhost, 127.0.0.1, file://
|
|
5996
6025
|
* - Production: sunpeak-prod-app-storage.s3.us-east-2.amazonaws.com (serves user scripts)
|
|
6026
|
+
*
|
|
6027
|
+
* Loopback script URLs are handled separately in isAllowedUrl() so hosted
|
|
6028
|
+
* inspectors cannot be tricked into loading scripts from a visitor's machine.
|
|
5997
6029
|
*/
|
|
5998
|
-
var ALLOWED_SCRIPT_ORIGINS = [
|
|
5999
|
-
"https://sunpeak-prod-app-storage.s3.us-east-2.amazonaws.com",
|
|
6000
|
-
"http://localhost",
|
|
6001
|
-
"https://localhost",
|
|
6002
|
-
"http://127.0.0.1",
|
|
6003
|
-
"https://127.0.0.1"
|
|
6004
|
-
];
|
|
6030
|
+
var ALLOWED_SCRIPT_ORIGINS = ["https://sunpeak-prod-app-storage.s3.us-east-2.amazonaws.com"];
|
|
6005
6031
|
/**
|
|
6006
6032
|
* Escapes HTML special characters to prevent XSS via attribute injection.
|
|
6007
6033
|
*/
|
|
@@ -6539,6 +6565,9 @@ var VALID_SCREEN_WIDTHS = new Set([
|
|
|
6539
6565
|
"tablet",
|
|
6540
6566
|
"full"
|
|
6541
6567
|
]);
|
|
6568
|
+
function isSafeStoredString(value) {
|
|
6569
|
+
return typeof value === "string" && value.length <= 200 && !/[\u0000-\u001f\u007f]/.test(value);
|
|
6570
|
+
}
|
|
6542
6571
|
function sanitizeStoredPrefs(raw) {
|
|
6543
6572
|
if (!raw || typeof raw !== "object") return {};
|
|
6544
6573
|
const obj = raw;
|
|
@@ -6546,6 +6575,8 @@ function sanitizeStoredPrefs(raw) {
|
|
|
6546
6575
|
if (typeof obj.theme === "string" && VALID_THEMES.has(obj.theme)) prefs.theme = obj.theme;
|
|
6547
6576
|
if (typeof obj.locale === "string") prefs.locale = obj.locale;
|
|
6548
6577
|
if (typeof obj.displayMode === "string" && VALID_DISPLAY_MODES.has(obj.displayMode)) prefs.displayMode = obj.displayMode;
|
|
6578
|
+
if (typeof obj.containerHeight === "number" && Number.isFinite(obj.containerHeight)) prefs.containerHeight = obj.containerHeight;
|
|
6579
|
+
if (typeof obj.containerWidth === "number" && Number.isFinite(obj.containerWidth)) prefs.containerWidth = obj.containerWidth;
|
|
6549
6580
|
if (typeof obj.containerMaxHeight === "number" && Number.isFinite(obj.containerMaxHeight)) prefs.containerMaxHeight = obj.containerMaxHeight;
|
|
6550
6581
|
if (typeof obj.containerMaxWidth === "number" && Number.isFinite(obj.containerMaxWidth)) prefs.containerMaxWidth = obj.containerMaxWidth;
|
|
6551
6582
|
if (obj.safeAreaInsets && typeof obj.safeAreaInsets === "object") {
|
|
@@ -6564,6 +6595,10 @@ function sanitizeStoredPrefs(raw) {
|
|
|
6564
6595
|
if (typeof obj.screenWidth === "string" && VALID_SCREEN_WIDTHS.has(obj.screenWidth)) prefs.screenWidth = obj.screenWidth;
|
|
6565
6596
|
if (typeof obj.sidebarWidth === "number" && Number.isFinite(obj.sidebarWidth)) prefs.sidebarWidth = Math.max(DEFAULT_SIDEBAR_WIDTH$1, Math.round(obj.sidebarWidth));
|
|
6566
6597
|
if (typeof obj.rightSidebarWidth === "number" && Number.isFinite(obj.rightSidebarWidth)) prefs.rightSidebarWidth = Math.max(DEFAULT_SIDEBAR_WIDTH$1, Math.round(obj.rightSidebarWidth));
|
|
6598
|
+
if (typeof obj.timeZone === "string") prefs.timeZone = obj.timeZone;
|
|
6599
|
+
if (typeof obj.prodResources === "boolean") prefs.prodResources = obj.prodResources;
|
|
6600
|
+
if (isSafeStoredString(obj.modelProvider)) prefs.modelProvider = obj.modelProvider;
|
|
6601
|
+
if (isSafeStoredString(obj.modelId)) prefs.modelId = obj.modelId;
|
|
6567
6602
|
return prefs;
|
|
6568
6603
|
}
|
|
6569
6604
|
function readStoredPrefs() {
|
|
@@ -6576,6 +6611,12 @@ function readStoredPrefs() {
|
|
|
6576
6611
|
return {};
|
|
6577
6612
|
}
|
|
6578
6613
|
}
|
|
6614
|
+
function writeStoredPrefs(prefs) {
|
|
6615
|
+
if (typeof window === "undefined") return;
|
|
6616
|
+
try {
|
|
6617
|
+
localStorage.setItem(PREFS_KEY, JSON.stringify(prefs));
|
|
6618
|
+
} catch {}
|
|
6619
|
+
}
|
|
6579
6620
|
function deriveContainerDimensions({ displayMode, containerHeight, containerWidth, containerMaxHeight, containerMaxWidth, measuredContentWidth, viewportHeight = 800, viewportWidth = 1280 }) {
|
|
6580
6621
|
if (containerHeight != null || containerWidth != null || containerMaxHeight != null || containerMaxWidth != null) return {
|
|
6581
6622
|
...containerHeight != null ? { height: containerHeight } : {},
|
|
@@ -6624,8 +6665,8 @@ function useInspectorState({ simulations, defaultHost = "chatgpt", preserveToolD
|
|
|
6624
6665
|
const [theme, setTheme] = (0, react.useState)(urlParams.theme ?? storedPrefs.theme ?? DEFAULT_THEME);
|
|
6625
6666
|
const [displayMode, _setDisplayMode] = (0, react.useState)(urlParams.displayMode ?? storedPrefs.displayMode ?? DEFAULT_DISPLAY_MODE);
|
|
6626
6667
|
const [locale, setLocale] = (0, react.useState)(urlParams.locale ?? storedPrefs.locale ?? "en-US");
|
|
6627
|
-
const [containerHeight, setContainerHeight] = (0, react.useState)(
|
|
6628
|
-
const [containerWidth, setContainerWidth] = (0, react.useState)(
|
|
6668
|
+
const [containerHeight, setContainerHeight] = (0, react.useState)(storedPrefs.containerHeight);
|
|
6669
|
+
const [containerWidth, setContainerWidth] = (0, react.useState)(storedPrefs.containerWidth);
|
|
6629
6670
|
const [containerMaxHeight, setContainerMaxHeight] = (0, react.useState)(urlParams.containerMaxHeight ?? storedPrefs.containerMaxHeight);
|
|
6630
6671
|
const [containerMaxWidth, setContainerMaxWidth] = (0, react.useState)(urlParams.containerMaxWidth ?? storedPrefs.containerMaxWidth);
|
|
6631
6672
|
const [platform, setPlatform] = (0, react.useState)(urlParams.platform ?? storedPrefs.platform ?? DEFAULT_PLATFORM);
|
|
@@ -6637,7 +6678,7 @@ function useInspectorState({ simulations, defaultHost = "chatgpt", preserveToolD
|
|
|
6637
6678
|
left: 0,
|
|
6638
6679
|
right: 0
|
|
6639
6680
|
});
|
|
6640
|
-
const [timeZone, setTimeZone] = (0, react.useState)(() => Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
6681
|
+
const [timeZone, setTimeZone] = (0, react.useState)(() => storedPrefs.timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
6641
6682
|
const isFirstRender = (0, react.useRef)(true);
|
|
6642
6683
|
(0, react.useEffect)(() => {
|
|
6643
6684
|
if (isFirstRender.current) {
|
|
@@ -6645,29 +6686,32 @@ function useInspectorState({ simulations, defaultHost = "chatgpt", preserveToolD
|
|
|
6645
6686
|
return;
|
|
6646
6687
|
}
|
|
6647
6688
|
if (autoRun) return;
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6689
|
+
writeStoredPrefs({
|
|
6690
|
+
...readStoredPrefs(),
|
|
6691
|
+
theme,
|
|
6692
|
+
locale,
|
|
6693
|
+
displayMode,
|
|
6694
|
+
containerHeight,
|
|
6695
|
+
containerWidth,
|
|
6696
|
+
containerMaxHeight,
|
|
6697
|
+
containerMaxWidth,
|
|
6698
|
+
safeAreaInsets,
|
|
6699
|
+
activeHost,
|
|
6700
|
+
platform,
|
|
6701
|
+
hover,
|
|
6702
|
+
touch,
|
|
6703
|
+
screenWidth,
|
|
6704
|
+
sidebarWidth,
|
|
6705
|
+
rightSidebarWidth,
|
|
6706
|
+
timeZone
|
|
6707
|
+
});
|
|
6666
6708
|
}, [
|
|
6667
6709
|
autoRun,
|
|
6668
6710
|
theme,
|
|
6669
6711
|
locale,
|
|
6670
6712
|
displayMode,
|
|
6713
|
+
containerHeight,
|
|
6714
|
+
containerWidth,
|
|
6671
6715
|
containerMaxHeight,
|
|
6672
6716
|
containerMaxWidth,
|
|
6673
6717
|
safeAreaInsets,
|
|
@@ -6677,7 +6721,8 @@ function useInspectorState({ simulations, defaultHost = "chatgpt", preserveToolD
|
|
|
6677
6721
|
touch,
|
|
6678
6722
|
screenWidth,
|
|
6679
6723
|
sidebarWidth,
|
|
6680
|
-
rightSidebarWidth
|
|
6724
|
+
rightSidebarWidth,
|
|
6725
|
+
timeZone
|
|
6681
6726
|
]);
|
|
6682
6727
|
const [measuredContentWidth, setMeasuredContentWidth] = (0, react.useState)(void 0);
|
|
6683
6728
|
const handleContentWidthChange = (0, react.useCallback)((width) => {
|
|
@@ -7590,12 +7635,16 @@ var DOCS_BASE_URL = "https://sunpeak.ai/docs";
|
|
|
7590
7635
|
var DEFAULT_MODEL_PROVIDERS = [{
|
|
7591
7636
|
id: "openai",
|
|
7592
7637
|
label: "OpenAI",
|
|
7593
|
-
defaultModel: "gpt-
|
|
7638
|
+
defaultModel: "gpt-5.5"
|
|
7594
7639
|
}, {
|
|
7595
7640
|
id: "anthropic",
|
|
7596
7641
|
label: "Anthropic",
|
|
7597
|
-
defaultModel: "claude-
|
|
7642
|
+
defaultModel: "claude-sonnet-4-20250514"
|
|
7598
7643
|
}];
|
|
7644
|
+
function createModelConversationId() {
|
|
7645
|
+
const random = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : Math.random().toString(36).slice(2);
|
|
7646
|
+
return `model-chat-${Date.now()}-${random}`;
|
|
7647
|
+
}
|
|
7599
7648
|
function splitCssArgs(value) {
|
|
7600
7649
|
const args = [];
|
|
7601
7650
|
let depth = 0;
|
|
@@ -7688,6 +7737,7 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
7688
7737
|
autoRun: params.get("autoRun") === "true"
|
|
7689
7738
|
};
|
|
7690
7739
|
}, []);
|
|
7740
|
+
const storedPrefs = react.useMemo(() => initUrlParams.autoRun ? {} : readStoredPrefs(), [initUrlParams.autoRun]);
|
|
7691
7741
|
const [selectedToolName, setSelectedToolName] = react.useState(() => {
|
|
7692
7742
|
if (initUrlParams.tool && toolMap.has(initUrlParams.tool)) return initUrlParams.tool;
|
|
7693
7743
|
if (initUrlParams.simulation) {
|
|
@@ -7737,7 +7787,7 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
7737
7787
|
const [oauthStatus, setOauthStatus] = react.useState("none");
|
|
7738
7788
|
const [oauthError, setOauthError] = react.useState();
|
|
7739
7789
|
const connection = useMcpConnection(isEmbedded ? void 0 : mcpServerUrl || void 0, inspectorApiBaseUrl);
|
|
7740
|
-
const [prodResources, setProdResources] = react.useState(state.urlProdResources ?? defaultProdResources);
|
|
7790
|
+
const [prodResources, setProdResources] = react.useState(state.urlProdResources ?? storedPrefs.prodResources ?? defaultProdResources);
|
|
7741
7791
|
const showSidebar = state.urlSidebar !== false;
|
|
7742
7792
|
const showDevOverlay = state.urlDevOverlay !== false;
|
|
7743
7793
|
const [isRunning, setIsRunning] = react.useState(false);
|
|
@@ -7759,6 +7809,15 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
7759
7809
|
if (requested && modelProviderOptions.some((provider) => provider.id === requested)) return requested;
|
|
7760
7810
|
return modelProviderOptions[0]?.id ?? "openai";
|
|
7761
7811
|
}, [modelChat?.defaultProvider, modelProviderOptions]);
|
|
7812
|
+
const initialModelProvider = react.useMemo(() => {
|
|
7813
|
+
const stored = storedPrefs.modelProvider;
|
|
7814
|
+
if (stored && modelProviderOptions.some((provider) => provider.id === stored)) return stored;
|
|
7815
|
+
return defaultModelProvider;
|
|
7816
|
+
}, [
|
|
7817
|
+
defaultModelProvider,
|
|
7818
|
+
modelProviderOptions,
|
|
7819
|
+
storedPrefs.modelProvider
|
|
7820
|
+
]);
|
|
7762
7821
|
const getDefaultModelId = react.useCallback((provider) => {
|
|
7763
7822
|
const option = modelProviderOptions.find((item) => item.id === provider);
|
|
7764
7823
|
const candidates = [
|
|
@@ -7770,8 +7829,20 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
7770
7829
|
if (providerModels.length === 0) return candidates.find(Boolean) ?? "";
|
|
7771
7830
|
return candidates.find((model) => model && providerModels.includes(model)) ?? providerModels[0];
|
|
7772
7831
|
}, [modelChat?.defaultModel, modelProviderOptions]);
|
|
7773
|
-
const
|
|
7774
|
-
|
|
7832
|
+
const getInitialModelId = react.useCallback((provider) => {
|
|
7833
|
+
const stored = storedPrefs.modelId;
|
|
7834
|
+
if (storedPrefs.modelProvider && storedPrefs.modelProvider !== provider) return getDefaultModelId(provider);
|
|
7835
|
+
const providerModels = modelProviderOptions.find((item) => item.id === provider)?.models ?? [];
|
|
7836
|
+
if (stored && (providerModels.length === 0 || providerModels.includes(stored))) return stored;
|
|
7837
|
+
return getDefaultModelId(provider);
|
|
7838
|
+
}, [
|
|
7839
|
+
getDefaultModelId,
|
|
7840
|
+
modelProviderOptions,
|
|
7841
|
+
storedPrefs.modelId,
|
|
7842
|
+
storedPrefs.modelProvider
|
|
7843
|
+
]);
|
|
7844
|
+
const [modelProvider, setModelProvider] = react.useState(initialModelProvider);
|
|
7845
|
+
const [modelId, setModelId] = react.useState(() => getInitialModelId(initialModelProvider));
|
|
7775
7846
|
const [apiKeyDraft, setApiKeyDraft] = react.useState("");
|
|
7776
7847
|
const [keyStatus, setKeyStatus] = react.useState({ hasKey: false });
|
|
7777
7848
|
const [isKeyStatusLoading, setIsKeyStatusLoading] = react.useState(usesApiKeyUi);
|
|
@@ -7780,6 +7851,7 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
7780
7851
|
const [chatInput, setChatInput] = react.useState("");
|
|
7781
7852
|
const [isChatting, setIsChatting] = react.useState(false);
|
|
7782
7853
|
const [chatStatus, setChatStatus] = react.useState("");
|
|
7854
|
+
const modelConversationIdRef = react.useRef(createModelConversationId());
|
|
7783
7855
|
const currentModelProvider = react.useMemo(() => modelProviderOptions.find((provider) => provider.id === modelProvider), [modelProvider, modelProviderOptions]);
|
|
7784
7856
|
const selectedProviderModelOptions = react.useMemo(() => currentModelProvider?.models ?? [], [currentModelProvider?.models]);
|
|
7785
7857
|
const modelCallableTools = react.useMemo(() => {
|
|
@@ -7790,6 +7862,25 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
7790
7862
|
}
|
|
7791
7863
|
return Array.from(map.values());
|
|
7792
7864
|
}, [simulations]);
|
|
7865
|
+
const isFirstInspectorPrefsRender = react.useRef(true);
|
|
7866
|
+
react.useEffect(() => {
|
|
7867
|
+
if (isFirstInspectorPrefsRender.current) {
|
|
7868
|
+
isFirstInspectorPrefsRender.current = false;
|
|
7869
|
+
return;
|
|
7870
|
+
}
|
|
7871
|
+
if (initUrlParams.autoRun) return;
|
|
7872
|
+
writeStoredPrefs({
|
|
7873
|
+
...readStoredPrefs(),
|
|
7874
|
+
prodResources,
|
|
7875
|
+
modelProvider,
|
|
7876
|
+
modelId
|
|
7877
|
+
});
|
|
7878
|
+
}, [
|
|
7879
|
+
initUrlParams.autoRun,
|
|
7880
|
+
modelId,
|
|
7881
|
+
modelProvider,
|
|
7882
|
+
prodResources
|
|
7883
|
+
]);
|
|
7793
7884
|
react.useEffect(() => {
|
|
7794
7885
|
setServerUrl(mcpServerUrl ?? "");
|
|
7795
7886
|
}, [mcpServerUrl]);
|
|
@@ -7899,6 +7990,13 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
7899
7990
|
usesApiKeyUi,
|
|
7900
7991
|
usesLocalModelEndpoints
|
|
7901
7992
|
]);
|
|
7993
|
+
const handleResetModelConversation = react.useCallback(() => {
|
|
7994
|
+
modelConversationIdRef.current = createModelConversationId();
|
|
7995
|
+
setChatMessages([]);
|
|
7996
|
+
setChatInput("");
|
|
7997
|
+
setChatStatus("");
|
|
7998
|
+
setIsChatting(false);
|
|
7999
|
+
}, []);
|
|
7902
8000
|
react.useEffect(() => {
|
|
7903
8001
|
state.setSelectedSimulationName(effectiveSimulationName);
|
|
7904
8002
|
}, [effectiveSimulationName]);
|
|
@@ -8159,15 +8257,18 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
8159
8257
|
state.setToolResultJson("");
|
|
8160
8258
|
state.setToolResultError("");
|
|
8161
8259
|
setHasRun(false);
|
|
8260
|
+
const requestConversationId = modelConversationIdRef.current;
|
|
8162
8261
|
try {
|
|
8163
8262
|
const messages = nextMessages.map((message) => ({
|
|
8164
8263
|
role: message.role,
|
|
8165
|
-
content: message.content
|
|
8166
|
-
}));
|
|
8264
|
+
content: message.content.trim()
|
|
8265
|
+
})).filter((message) => message.content.length > 0);
|
|
8167
8266
|
let data;
|
|
8168
8267
|
if (modelChatHandler) data = await modelChatHandler({
|
|
8268
|
+
conversationId: requestConversationId,
|
|
8169
8269
|
provider: modelProvider,
|
|
8170
8270
|
modelId,
|
|
8271
|
+
host: state.activeHost,
|
|
8171
8272
|
messages,
|
|
8172
8273
|
tools: modelCallableTools,
|
|
8173
8274
|
appContext: state.modelAppContext ?? void 0
|
|
@@ -8178,8 +8279,10 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
8178
8279
|
method: "POST",
|
|
8179
8280
|
headers: { "Content-Type": "application/json" },
|
|
8180
8281
|
body: JSON.stringify({
|
|
8282
|
+
conversationId: requestConversationId,
|
|
8181
8283
|
provider: modelProvider,
|
|
8182
8284
|
modelId,
|
|
8285
|
+
host: state.activeHost,
|
|
8183
8286
|
messages,
|
|
8184
8287
|
appContext: state.modelAppContext ?? void 0
|
|
8185
8288
|
})
|
|
@@ -8188,6 +8291,7 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
8188
8291
|
if (!res.ok || data.error) throw new Error(data.error ?? `Model request failed (${res.status})`);
|
|
8189
8292
|
}
|
|
8190
8293
|
if (data.error) throw new Error(data.error);
|
|
8294
|
+
if (requestConversationId !== modelConversationIdRef.current) return;
|
|
8191
8295
|
let rendersApp = false;
|
|
8192
8296
|
const toolCalls = data.toolCalls ?? [];
|
|
8193
8297
|
for (let index = toolCalls.length - 1; index >= 0; index--) {
|
|
@@ -8225,6 +8329,7 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
8225
8329
|
});
|
|
8226
8330
|
setChatStatus("");
|
|
8227
8331
|
} catch (err) {
|
|
8332
|
+
if (requestConversationId !== modelConversationIdRef.current) return;
|
|
8228
8333
|
const message = err instanceof Error ? err.message : String(err);
|
|
8229
8334
|
setChatMessages((messages) => [...messages, {
|
|
8230
8335
|
id: `assistant-error-${Date.now()}`,
|
|
@@ -8233,7 +8338,7 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
8233
8338
|
}]);
|
|
8234
8339
|
setChatStatus(message);
|
|
8235
8340
|
} finally {
|
|
8236
|
-
setIsChatting(false);
|
|
8341
|
+
if (requestConversationId === modelConversationIdRef.current) setIsChatting(false);
|
|
8237
8342
|
}
|
|
8238
8343
|
}, [
|
|
8239
8344
|
canUseModelChat,
|
|
@@ -8847,33 +8952,69 @@ function Inspector({ children, app, simulations: initialSimulationsProp = EMPTY_
|
|
|
8847
8952
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8848
8953
|
className: "space-y-1",
|
|
8849
8954
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8850
|
-
className: "grid grid-cols-
|
|
8851
|
-
children: [
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
|
|
8955
|
+
className: "grid grid-cols-[0.7fr_minmax(0,1fr)_1.75rem] items-end gap-2",
|
|
8956
|
+
children: [
|
|
8957
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarControl, {
|
|
8958
|
+
label: "Provider",
|
|
8959
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSelect, {
|
|
8960
|
+
value: modelProvider,
|
|
8961
|
+
onChange: handleModelProviderChange,
|
|
8962
|
+
options: modelProviderOptions.map((provider) => ({
|
|
8963
|
+
value: provider.id,
|
|
8964
|
+
label: provider.label ?? provider.id
|
|
8965
|
+
}))
|
|
8966
|
+
})
|
|
8967
|
+
}),
|
|
8968
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarControl, {
|
|
8969
|
+
label: "Model",
|
|
8970
|
+
children: selectedProviderModelOptions.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarSelect, {
|
|
8971
|
+
value: modelId,
|
|
8972
|
+
onChange: setModelId,
|
|
8973
|
+
options: selectedProviderModelOptions.map((model) => ({
|
|
8974
|
+
value: model,
|
|
8975
|
+
label: model
|
|
8976
|
+
}))
|
|
8977
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarInput, {
|
|
8978
|
+
value: modelId,
|
|
8979
|
+
onChange: setModelId,
|
|
8980
|
+
applyOnBlur: true,
|
|
8981
|
+
placeholder: getDefaultModelId(modelProvider)
|
|
8982
|
+
})
|
|
8983
|
+
}),
|
|
8984
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8985
|
+
className: "group relative flex h-7 items-center self-end",
|
|
8986
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8987
|
+
type: "button",
|
|
8988
|
+
onClick: handleResetModelConversation,
|
|
8989
|
+
disabled: chatMessages.length === 0 && !isChatting && !chatStatus,
|
|
8990
|
+
"aria-label": "Reset model conversation",
|
|
8991
|
+
"aria-describedby": "reset-model-conversation-tooltip",
|
|
8992
|
+
title: "Reset conversation",
|
|
8993
|
+
className: "flex h-7 w-7 cursor-pointer items-center justify-center rounded-full transition-colors disabled:cursor-not-allowed disabled:opacity-40",
|
|
8994
|
+
style: {
|
|
8995
|
+
backgroundColor: "var(--color-background-primary)",
|
|
8996
|
+
color: "var(--color-text-primary)"
|
|
8997
|
+
},
|
|
8998
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
8999
|
+
width: "18",
|
|
9000
|
+
height: "18",
|
|
9001
|
+
viewBox: "0 0 24 24",
|
|
9002
|
+
fill: "currentColor",
|
|
9003
|
+
"aria-hidden": "true",
|
|
9004
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-8 3.58-8 8s3.58 8 8 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h8V3z" })
|
|
9005
|
+
})
|
|
9006
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9007
|
+
id: "reset-model-conversation-tooltip",
|
|
9008
|
+
role: "tooltip",
|
|
9009
|
+
className: "pointer-events-none absolute right-0 top-full z-[1000] mt-1 hidden whitespace-nowrap rounded px-2 py-1 text-[11px] font-normal leading-tight group-focus-within:block group-hover:block",
|
|
9010
|
+
style: {
|
|
9011
|
+
backgroundColor: "var(--color-text-primary)",
|
|
9012
|
+
color: "var(--color-background-primary)"
|
|
9013
|
+
},
|
|
9014
|
+
children: "Reset conversation"
|
|
9015
|
+
})]
|
|
8875
9016
|
})
|
|
8876
|
-
|
|
9017
|
+
]
|
|
8877
9018
|
}), usesApiKeyUi && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(SidebarControl, {
|
|
8878
9019
|
label: "API Key",
|
|
8879
9020
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -9404,4 +9545,4 @@ Object.defineProperty(exports, "useThemeContext", {
|
|
|
9404
9545
|
}
|
|
9405
9546
|
});
|
|
9406
9547
|
|
|
9407
|
-
//# sourceMappingURL=inspector-
|
|
9548
|
+
//# sourceMappingURL=inspector-Chhc2GNO.cjs.map
|