sunpeak 0.19.12 → 0.20.2

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.
Files changed (85) hide show
  1. package/README.md +2 -2
  2. package/bin/commands/inspect.mjs +361 -12
  3. package/bin/commands/test-init.mjs +190 -118
  4. package/bin/commands/test.mjs +12 -1
  5. package/bin/lib/eval/eval-runner.mjs +7 -1
  6. package/bin/lib/inspect/inspect-config.mjs +17 -2
  7. package/bin/lib/inspect/inspect-server.d.mts +32 -0
  8. package/bin/lib/inspect/inspect-server.mjs +11 -0
  9. package/bin/lib/live/live-config.d.mts +10 -0
  10. package/bin/lib/live/live-config.mjs +34 -2
  11. package/bin/lib/resolve-bin.mjs +39 -0
  12. package/bin/lib/test/base-config.mjs +6 -3
  13. package/bin/lib/test/matchers.mjs +2 -2
  14. package/bin/lib/test/test-config.mjs +19 -8
  15. package/bin/lib/test/test-fixtures.d.mts +52 -92
  16. package/bin/lib/test/test-fixtures.mjs +174 -147
  17. package/dist/chatgpt/index.cjs +1 -1
  18. package/dist/chatgpt/index.js +1 -1
  19. package/dist/claude/index.cjs +1 -1
  20. package/dist/claude/index.js +1 -1
  21. package/dist/host/chatgpt/index.cjs +1 -1
  22. package/dist/host/chatgpt/index.js +1 -1
  23. package/dist/index.cjs +4 -4
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.js +3 -3
  26. package/dist/index.js.map +1 -1
  27. package/dist/inspector/index.cjs +1 -1
  28. package/dist/inspector/index.js +1 -1
  29. package/dist/{inspector-D5DckQuU.js → inspector-BBDa5yCm.js} +57 -23
  30. package/dist/inspector-BBDa5yCm.js.map +1 -0
  31. package/dist/{inspector-jY9O18z9.cjs → inspector-DAA1Wiyh.cjs} +58 -24
  32. package/dist/inspector-DAA1Wiyh.cjs.map +1 -0
  33. package/dist/lib/discovery-cli.cjs +1 -1
  34. package/dist/mcp/index.cjs +22 -25
  35. package/dist/mcp/index.cjs.map +1 -1
  36. package/dist/mcp/index.js +19 -22
  37. package/dist/mcp/index.js.map +1 -1
  38. package/dist/{use-app-Bfargfa3.js → use-app-Cr0auUa1.js} +2 -2
  39. package/dist/{use-app-Bfargfa3.js.map → use-app-Cr0auUa1.js.map} +1 -1
  40. package/dist/{use-app-CbsBEmwv.cjs → use-app-DPkj5Jp_.cjs} +2 -2
  41. package/dist/{use-app-CbsBEmwv.cjs.map → use-app-DPkj5Jp_.cjs.map} +1 -1
  42. package/package.json +17 -11
  43. package/template/dist/albums/albums.html +4 -4
  44. package/template/dist/albums/albums.json +1 -1
  45. package/template/dist/carousel/carousel.html +4 -4
  46. package/template/dist/carousel/carousel.json +1 -1
  47. package/template/dist/map/map.html +6 -6
  48. package/template/dist/map/map.json +1 -1
  49. package/template/dist/review/review.html +4 -4
  50. package/template/dist/review/review.json +1 -1
  51. package/template/node_modules/.bin/vite +2 -2
  52. package/template/node_modules/.bin/vitest +2 -2
  53. package/template/node_modules/.vite/deps/_metadata.json +4 -4
  54. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +1 -1
  55. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
  56. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +1 -1
  57. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
  58. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +1 -1
  59. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
  60. package/template/node_modules/.vite-mcp/deps/@testing-library_react.js +4 -4
  61. package/template/node_modules/.vite-mcp/deps/@testing-library_react.js.map +1 -1
  62. package/template/node_modules/.vite-mcp/deps/_metadata.json +33 -33
  63. package/template/node_modules/.vite-mcp/deps/{client-CU1wWud4.js → client-B_5CX--u.js} +7 -7
  64. package/template/node_modules/.vite-mcp/deps/{client-CU1wWud4.js.map → client-B_5CX--u.js.map} +1 -1
  65. package/template/node_modules/.vite-mcp/deps/embla-carousel-react.js +1 -1
  66. package/template/node_modules/.vite-mcp/deps/embla-carousel-react.js.map +1 -1
  67. package/template/node_modules/.vite-mcp/deps/react-dom.js +3 -3
  68. package/template/node_modules/.vite-mcp/deps/react-dom.js.map +1 -1
  69. package/template/node_modules/.vite-mcp/deps/react-dom_client.js +1 -1
  70. package/template/node_modules/.vite-mcp/deps/react.js +3 -3
  71. package/template/node_modules/.vite-mcp/deps/react.js.map +1 -1
  72. package/template/node_modules/.vite-mcp/deps/react_jsx-dev-runtime.js +2 -2
  73. package/template/node_modules/.vite-mcp/deps/react_jsx-dev-runtime.js.map +1 -1
  74. package/template/node_modules/.vite-mcp/deps/react_jsx-runtime.js +2 -2
  75. package/template/node_modules/.vite-mcp/deps/react_jsx-runtime.js.map +1 -1
  76. package/template/node_modules/.vite-mcp/deps/vitest.js +1024 -622
  77. package/template/node_modules/.vite-mcp/deps/vitest.js.map +1 -1
  78. package/template/package.json +6 -6
  79. package/template/tests/e2e/albums.spec.ts +24 -52
  80. package/template/tests/e2e/carousel.spec.ts +36 -58
  81. package/template/tests/e2e/map.spec.ts +35 -56
  82. package/template/tests/e2e/review.spec.ts +56 -85
  83. package/template/tests/e2e/visual.spec.ts +14 -12
  84. package/dist/inspector-D5DckQuU.js.map +0 -1
  85. package/dist/inspector-jY9O18z9.cjs.map +0 -1
@@ -1,20 +1,24 @@
1
1
  /**
2
- * MCP-first Playwright fixtures for testing MCP servers.
2
+ * Playwright fixtures for testing MCP servers.
3
3
  *
4
- * Provides an `mcp` fixture that abstracts the inspector, double-iframe
5
- * traversal, URL construction, and host selection. Tests read like MCP
6
- * operations, not browser automation.
4
+ * Two fixtures, cleanly separated:
5
+ * - `mcp` MCP protocol primitives (callTool, listTools, listResources, readResource)
6
+ * - `inspector` sunpeak inspector for rendering and visual testing (renderTool, host)
7
7
  *
8
8
  * Usage:
9
9
  * import { test, expect } from 'sunpeak/test';
10
10
  *
11
- * test('weather tool', async ({ mcp }) => {
12
- * const result = await mcp.callTool('get-weather', { city: 'SF' });
13
- * expect(result).not.toBeError();
14
- * expect(result).toHaveTextContent('temperature');
11
+ * test('protocol test', async ({ mcp }) => {
12
+ * const tools = await mcp.listTools();
13
+ * const result = await mcp.callTool('search', { query: 'headphones' });
14
+ * expect(result.isError).toBeFalsy();
15
+ * });
15
16
  *
16
- * const app = result.app();
17
- * await expect(app.getByText('San Francisco')).toBeVisible();
17
+ * test('UI test', async ({ inspector }) => {
18
+ * const result = await inspector.renderTool('search', { query: 'headphones' });
19
+ * expect(result).not.toBeError();
20
+ * await expect(result.app().getByText('headphones')).toBeVisible();
21
+ * await result.screenshot('search-results');
18
22
  * });
19
23
  */
20
24
  import { resolvePlaywrightESM } from '../live/utils.mjs';
@@ -26,10 +30,8 @@ const { test: base, expect } = await resolvePlaywrightESM(projectRoot);
26
30
  // Register MCP-native matchers
27
31
  registerMatchers(expect);
28
32
 
29
- /**
30
- * Build an inspector URL path with query parameters.
31
- * Inlined to avoid importing from dist (which pulls in React).
32
- */
33
+ // ── Helpers ──
34
+
33
35
  function buildInspectorUrl(params) {
34
36
  const sp = new URLSearchParams();
35
37
  for (const [key, value] of Object.entries(params)) {
@@ -37,15 +39,11 @@ function buildInspectorUrl(params) {
37
39
  sp.set(key, String(value));
38
40
  }
39
41
  }
40
- // Always disable dev overlay in tests
41
42
  sp.set('devOverlay', 'false');
42
43
  const qs = sp.toString();
43
44
  return qs ? `/?${qs}` : '/';
44
45
  }
45
46
 
46
- /**
47
- * Resolve the host ID from the Playwright project name.
48
- */
49
47
  function resolveHostId(projectName) {
50
48
  if (!projectName) return 'chatgpt';
51
49
  if (projectName.startsWith('chatgpt')) return 'chatgpt';
@@ -53,57 +51,186 @@ function resolveHostId(projectName) {
53
51
  return projectName;
54
52
  }
55
53
 
54
+ async function fetchJson(page, path) {
55
+ const baseURL = page.context()._options?.baseURL || '';
56
+ const response = await page.request.get(`${baseURL}${path}`);
57
+ if (!response.ok()) {
58
+ throw new Error(`${path} returned ${response.status()}: ${await response.text()}`);
59
+ }
60
+ return response.json();
61
+ }
62
+
56
63
  /**
57
- * Create a ToolResult wrapper around the inspector's rendered state.
64
+ * Read the tool result from the inspector's <script id="__tool-result"> element.
58
65
  */
59
- function createToolResult(page, resultData) {
66
+ async function readToolResult(page, timeout) {
67
+ try {
68
+ const script = page.locator('#__tool-result');
69
+ await script.waitFor({ state: 'attached', timeout: Math.min(timeout, 5_000) });
70
+ const json = await script.evaluate(
71
+ (el, t) =>
72
+ new Promise((resolve) => {
73
+ const check = () => {
74
+ const text = el.textContent?.trim();
75
+ if (text && text !== 'null') return resolve(text);
76
+ let timer;
77
+ const observer = new MutationObserver(() => {
78
+ const updated = el.textContent?.trim();
79
+ if (updated && updated !== 'null') {
80
+ observer.disconnect();
81
+ clearTimeout(timer);
82
+ resolve(updated);
83
+ }
84
+ });
85
+ observer.observe(el, { childList: true, characterData: true, subtree: true });
86
+ timer = setTimeout(() => { observer.disconnect(); resolve(null); }, t);
87
+ };
88
+ check();
89
+ }),
90
+ Math.min(timeout, 10_000)
91
+ );
92
+ if (json) {
93
+ const parsed = JSON.parse(json);
94
+ return {
95
+ content: parsed?.content || [],
96
+ structuredContent: parsed?.structuredContent,
97
+ isError: parsed?.isError || false,
98
+ source: parsed?.source || 'server',
99
+ };
100
+ }
101
+ } catch {
102
+ // Fall back to empty
103
+ }
104
+ return { content: [], structuredContent: undefined, isError: false, source: 'server' };
105
+ }
106
+
107
+ /**
108
+ * Create an InspectorResult from the rendered state.
109
+ */
110
+ function createInspectorResult(page, resultData) {
60
111
  return {
61
112
  content: resultData?.content || [],
62
113
  structuredContent: resultData?.structuredContent,
63
114
  isError: resultData?.isError || false,
115
+ source: resultData?.source || 'server',
64
116
 
65
- /**
66
- * Get a FrameLocator for the rendered resource UI.
67
- * Handles the double-iframe traversal (outer sandbox proxy + inner app).
68
- * Returns the locator regardless — Playwright will throw with a clear
69
- * error if no iframe exists when you interact with it.
70
- */
117
+ /** Get a FrameLocator for the rendered resource UI (handles double-iframe). */
71
118
  app() {
72
119
  return page.frameLocator('iframe').frameLocator('iframe');
73
120
  },
121
+
122
+ /**
123
+ * Take a screenshot and compare against a baseline.
124
+ * Only runs when visual testing is enabled (`sunpeak test --visual`).
125
+ * Silently skips otherwise.
126
+ *
127
+ * @param {string} [name] - Snapshot name (auto-generated if omitted)
128
+ * @param {Object} [options] - Playwright toHaveScreenshot options
129
+ */
130
+ async screenshot(name, options = {}) {
131
+ if (process.env.SUNPEAK_VISUAL !== 'true') return;
132
+
133
+ if (typeof name === 'object' && name !== null) {
134
+ options = name;
135
+ name = undefined;
136
+ }
137
+
138
+ const { target = 'app', element, ...playwrightOptions } = options;
139
+ let locator;
140
+ if (element) {
141
+ locator = element;
142
+ } else if (target === 'page') {
143
+ locator = page.locator('#root');
144
+ } else {
145
+ locator = page.frameLocator('iframe').frameLocator('iframe').locator('body');
146
+ }
147
+ const fullName = name && !name.endsWith('.png') ? `${name}.png` : name;
148
+ const args = fullName ? [fullName, playwrightOptions] : [playwrightOptions];
149
+ await expect(locator).toHaveScreenshot(...args);
150
+ },
74
151
  };
75
152
  }
76
153
 
154
+ // ── Fixtures ──
155
+
77
156
  const test = base.extend({
78
- mcp: async ({ page }, use, testInfo) => {
157
+ /**
158
+ * MCP protocol fixture. Maps 1:1 to MCP protocol operations.
159
+ * No rendering, no inspector UI, no sunpeak concepts.
160
+ */
161
+ mcp: async ({ page }, use) => {
162
+ const fixture = {
163
+ async listTools() {
164
+ const result = await fetchJson(page, '/__sunpeak/list-tools');
165
+ return result.tools || [];
166
+ },
167
+
168
+ async callTool(name, input) {
169
+ const baseURL = page.context()._options?.baseURL || '';
170
+ const response = await page.request.post(`${baseURL}/__sunpeak/call-tool`, {
171
+ data: { name, arguments: input || {} },
172
+ });
173
+ if (!response.ok()) {
174
+ throw new Error(`callTool(${name}) returned ${response.status()}: ${await response.text()}`);
175
+ }
176
+ return response.json();
177
+ },
178
+
179
+ async listResources() {
180
+ const result = await fetchJson(page, '/__sunpeak/list-resources');
181
+ return result.resources || [];
182
+ },
183
+
184
+ async readResource(uri) {
185
+ const baseURL = page.context()._options?.baseURL || '';
186
+ const response = await page.request.get(
187
+ `${baseURL}/__sunpeak/read-resource?uri=${encodeURIComponent(uri)}`
188
+ );
189
+ if (!response.ok()) {
190
+ throw new Error(`readResource(${uri}) returned ${response.status()}: ${await response.text()}`);
191
+ }
192
+ return response.text();
193
+ },
194
+ };
195
+
196
+ await use(fixture);
197
+ },
198
+
199
+ /**
200
+ * sunpeak inspector fixture. Renders tools in simulated host environments.
201
+ * Built on top of the inspector, not the MCP protocol.
202
+ */
203
+ inspector: async ({ page }, use, testInfo) => {
79
204
  const host = resolveHostId(testInfo.project.name);
80
205
 
81
206
  const fixture = {
82
- page,
207
+ /** Current host ID ('chatgpt' or 'claude') from Playwright project. */
83
208
  host,
84
209
 
210
+ /** The underlying Playwright Page (for advanced assertions). */
211
+ page,
212
+
85
213
  /**
86
- * Call a tool and get the rendered result.
214
+ * Render a tool in the inspector and return the result.
87
215
  *
88
- * For sunpeak projects: navigates to the matching simulation (simulation
89
- * fixture data including toolInput is served by sunpeak dev).
90
- * For external servers: navigates to the matching simulation created by
91
- * inspectServer from discovered tools.
216
+ * With `input`, the tool is called on the real server (bypasses fixtures).
217
+ * Without `input`, simulation fixture data is used when available.
92
218
  *
93
- * Note: The `input` parameter is accepted for API consistency and future
94
- * use but is not currently passed to the inspector. Simulation fixture
95
- * data provides the tool input for rendering.
96
- *
97
- * @param {string} name - Tool/simulation name (e.g., 'show-albums')
98
- * @param {Record<string, unknown>} [_input] - Reserved for future use
219
+ * @param {string} name - Tool name
220
+ * @param {Record<string, unknown>} [input] - Tool arguments (real server call)
99
221
  * @param {Object} [options] - Display options
100
- * @returns {Promise<ToolResult>}
222
+ * @param {'light' | 'dark'} [options.theme]
223
+ * @param {'inline' | 'pip' | 'fullscreen'} [options.displayMode]
224
+ * @param {number} [options.timeout] - Timeout in ms (default: 15s or mcpTimeout from config)
225
+ * @returns {Promise<InspectorResult>}
101
226
  */
102
- async callTool(name, _input, options = {}) {
103
- const { theme, displayMode, ...rest } = options;
227
+ async renderTool(name, input, options = {}) {
228
+ const { theme, displayMode, timeout: callTimeout, ...rest } = options;
104
229
 
230
+ const hasInput = input != null && Object.keys(input).length > 0;
105
231
  const params = {
106
- simulation: name,
232
+ ...(hasInput ? { tool: name, toolInput: JSON.stringify(input) } : { simulation: name }),
233
+ autoRun: 'true',
107
234
  host,
108
235
  ...(theme && { theme }),
109
236
  ...(displayMode && { displayMode }),
@@ -112,116 +239,16 @@ const test = base.extend({
112
239
 
113
240
  await page.goto(buildInspectorUrl(params));
114
241
 
115
- // Wait for the resource iframe to have content
242
+ const resolvedTimeout = callTimeout ?? testInfo.project.use?.mcpTimeout ?? 15_000;
116
243
  try {
117
244
  const frame = page.frameLocator('iframe').frameLocator('iframe');
118
- await frame.locator('body').waitFor({ state: 'attached', timeout: 15_000 });
245
+ await frame.locator('body').waitFor({ state: 'attached', timeout: resolvedTimeout });
119
246
  } catch {
120
247
  // Tool may not have a resource (no UI)
121
248
  }
122
249
 
123
- return createToolResult(page, {
124
- content: [],
125
- structuredContent: undefined,
126
- isError: false,
127
- });
128
- },
129
-
130
- /**
131
- * Navigate to a tool with no mock data ("Press Run" state).
132
- * Use for testing the empty/loading state before a tool is executed.
133
- */
134
- async openTool(name, options = {}) {
135
- const { theme, ...rest } = options;
136
- const params = {
137
- tool: name,
138
- host,
139
- ...(theme && { theme }),
140
- ...rest,
141
- };
142
- await page.goto(buildInspectorUrl(params));
143
- await page.locator('#root').waitFor({ state: 'attached' });
144
- },
145
-
146
- /**
147
- * Click the Run button and wait for the resource to render.
148
- * Use after openTool() in Prod Tools mode.
149
- */
150
- async runTool() {
151
- await page.locator('button:has-text("Run")').click();
152
- await page.locator('iframe').waitFor({ state: 'attached', timeout: 30_000 });
153
- return createToolResult(page, {
154
- content: [],
155
- structuredContent: undefined,
156
- isError: false,
157
- });
158
- },
159
-
160
- /**
161
- * Change the theme via the sidebar toggle.
162
- */
163
- async setTheme(theme) {
164
- const label = theme === 'light' ? 'Light' : 'Dark';
165
- const button = page.locator(`button:has-text("${label}")`);
166
- if (await button.isVisible().catch(() => false)) {
167
- await button.click();
168
- // Wait for theme to propagate to the iframe
169
- await page.waitForTimeout(300);
170
- }
171
- },
172
-
173
- /**
174
- * Change the display mode via the sidebar buttons.
175
- */
176
- async setDisplayMode(mode) {
177
- const labels = { inline: 'Inline', pip: 'PiP', fullscreen: 'Full' };
178
- const label = labels[mode] || mode;
179
- await page.locator(`button:has-text("${label}")`).click();
180
- // Wait for display mode transition
181
- await page.waitForTimeout(500);
182
- },
183
-
184
- /**
185
- * Take a screenshot and compare against a baseline.
186
- * Only performs the comparison when visual testing is enabled
187
- * (`sunpeak test --visual`). Silently skips otherwise, so tests
188
- * that include screenshot() calls still pass during normal runs.
189
- *
190
- * Accepts all Playwright toHaveScreenshot() options (threshold,
191
- * maxDiffPixelRatio, maxDiffPixels, mask, animations, caret,
192
- * fullPage, clip, scale, stylePath, etc.) and passes them through.
193
- *
194
- * @param {string} [name] - Snapshot name (auto-generated from test title if omitted)
195
- * @param {Object} [options] - Screenshot and comparison options
196
- * @param {'app' | 'page'} [options.target='app'] - What to screenshot
197
- * @param {import('@playwright/test').Locator} [options.element] - Specific locator to screenshot
198
- */
199
- async screenshot(name, options = {}) {
200
- if (process.env.SUNPEAK_VISUAL !== 'true') return;
201
-
202
- // Support screenshot(options) without a name
203
- if (typeof name === 'object' && name !== null) {
204
- options = name;
205
- name = undefined;
206
- }
207
-
208
- const { target = 'app', element, ...playwrightOptions } = options;
209
-
210
- let locator;
211
- if (element) {
212
- locator = element;
213
- } else if (target === 'page') {
214
- locator = page.locator('#root');
215
- } else {
216
- locator = page.frameLocator('iframe').frameLocator('iframe').locator('body');
217
- }
218
-
219
- const fullName = name && !name.endsWith('.png') ? `${name}.png` : name;
220
- const args = fullName
221
- ? [fullName, playwrightOptions]
222
- : [playwrightOptions];
223
-
224
- await expect(locator).toHaveScreenshot(...args);
250
+ const resultData = await readToolResult(page, resolvedTimeout);
251
+ return createInspectorResult(page, resultData);
225
252
  },
226
253
  };
227
254
 
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../chunk-9hOWP6kD.cjs");
3
- const require_inspector = require("../inspector-jY9O18z9.cjs");
3
+ const require_inspector = require("../inspector-DAA1Wiyh.cjs");
4
4
  const require_inspector_url = require("../inspector-url-C3LTKgXt.cjs");
5
5
  const require_discovery = require("../discovery-Clu4uHp1.cjs");
6
6
  //#region src/chatgpt/index.ts
@@ -1,5 +1,5 @@
1
1
  import { r as __exportAll } from "../chunk-D6g4UhsZ.js";
2
- import { _ as McpAppHost, d as ThemeProvider, f as useThemeContext, g as extractResourceCSP, h as IframeResource, n as resolveServerToolResult, t as Inspector, v as SCREEN_WIDTHS } from "../inspector-D5DckQuU.js";
2
+ import { _ as McpAppHost, d as ThemeProvider, f as useThemeContext, g as extractResourceCSP, h as IframeResource, n as resolveServerToolResult, t as Inspector, v as SCREEN_WIDTHS } from "../inspector-BBDa5yCm.js";
3
3
  import { t as createInspectorUrl } from "../inspector-url-CyQcuBI9.js";
4
4
  import { c as toPascalCase, i as findResourceKey, n as extractSimulationKey, r as findResourceDirs, s as getComponentName, t as extractResourceKey } from "../discovery-Cgoegt62.js";
5
5
  //#region src/chatgpt/index.ts
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../chunk-9hOWP6kD.cjs");
3
- const require_inspector = require("../inspector-jY9O18z9.cjs");
3
+ const require_inspector = require("../inspector-DAA1Wiyh.cjs");
4
4
  exports.Inspector = require_inspector.Inspector;
@@ -1,2 +1,2 @@
1
- import { t as Inspector } from "../inspector-D5DckQuU.js";
1
+ import { t as Inspector } from "../inspector-BBDa5yCm.js";
2
2
  export { Inspector };
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../chunk-9hOWP6kD.cjs");
3
- const require_use_app = require("../../use-app-CbsBEmwv.cjs");
3
+ const require_use_app = require("../../use-app-DPkj5Jp_.cjs");
4
4
  let react = require("react");
5
5
  //#region src/host/chatgpt/openai-types.ts
6
6
  /**
@@ -1,4 +1,4 @@
1
- import { t as useApp } from "../../use-app-Bfargfa3.js";
1
+ import { t as useApp } from "../../use-app-Cr0auUa1.js";
2
2
  import { useCallback } from "react";
3
3
  //#region src/host/chatgpt/openai-types.ts
4
4
  /**
package/dist/index.cjs CHANGED
@@ -1,15 +1,15 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-9hOWP6kD.cjs");
3
3
  const require_protocol = require("./protocol-C8pFDmcy.cjs");
4
- const require_use_app = require("./use-app-CbsBEmwv.cjs");
5
- const require_inspector = require("./inspector-jY9O18z9.cjs");
4
+ const require_use_app = require("./use-app-DPkj5Jp_.cjs");
5
+ const require_inspector = require("./inspector-DAA1Wiyh.cjs");
6
6
  const require_host_index = require("./host/index.cjs");
7
7
  const require_inspector_index = require("./inspector/index.cjs");
8
8
  const require_chatgpt_index = require("./chatgpt/index.cjs");
9
9
  let react = require("react");
10
- react = require_chunk.__toESM(react);
10
+ react = require_chunk.__toESM(react, 1);
11
11
  let react_jsx_runtime = require("react/jsx-runtime");
12
- //#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.5.0_@modelcontextprotocol+sdk@1.29.0_zod@4.3.6__react-_f4871531d9cf52c692eb6edc1ee416ef/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/index.js
12
+ //#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.5.0_@modelcontextprotocol+sdk@1.29.0_zod@4.3.6__react-_a8a8e071c354e7dd6f62871eadf46f99/node_modules/@modelcontextprotocol/ext-apps/dist/src/react/index.js
13
13
  var m = require_protocol.union([require_protocol.literal("light"), require_protocol.literal("dark")]).describe("Color theme preference for the host environment."), N$1 = require_protocol.union([
14
14
  require_protocol.literal("inline"),
15
15
  require_protocol.literal("fullscreen"),