sunpeak 0.19.2 → 0.19.10

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 (90) hide show
  1. package/README.md +6 -4
  2. package/bin/commands/dev.mjs +1 -1
  3. package/bin/commands/inspect.mjs +1 -1
  4. package/bin/commands/new.mjs +9 -5
  5. package/bin/commands/start.mjs +3 -1
  6. package/bin/commands/test-init.mjs +478 -76
  7. package/bin/commands/test.mjs +357 -4
  8. package/bin/lib/eval/eval-reporter.mjs +105 -0
  9. package/bin/lib/eval/eval-runner.mjs +310 -0
  10. package/bin/lib/eval/eval-types.d.mts +168 -0
  11. package/bin/lib/eval/eval-vitest-plugin.mjs +158 -0
  12. package/bin/lib/eval/model-registry.mjs +73 -0
  13. package/bin/lib/sandbox-server.mjs +5 -2
  14. package/bin/sunpeak.js +1 -0
  15. package/dist/chatgpt/index.cjs +1 -1
  16. package/dist/chatgpt/index.js +1 -1
  17. package/dist/claude/index.cjs +1 -1
  18. package/dist/claude/index.js +1 -1
  19. package/dist/host/chatgpt/index.cjs +1 -1
  20. package/dist/host/chatgpt/index.js +1 -1
  21. package/dist/index.cjs +134 -124
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.ts +3 -1
  24. package/dist/index.js +71 -62
  25. package/dist/index.js.map +1 -1
  26. package/dist/inspector/index.cjs +1 -1
  27. package/dist/inspector/index.js +1 -1
  28. package/dist/{inspector-Cdo5BK2D.js → inspector-D5DckQuU.js} +236 -98
  29. package/dist/inspector-D5DckQuU.js.map +1 -0
  30. package/dist/{inspector-8nPV2A-z.cjs → inspector-jY9O18z9.cjs} +237 -99
  31. package/dist/inspector-jY9O18z9.cjs.map +1 -0
  32. package/dist/mcp/index.cjs +237 -140
  33. package/dist/mcp/index.cjs.map +1 -1
  34. package/dist/mcp/index.d.ts +1 -1
  35. package/dist/mcp/index.js +230 -134
  36. package/dist/mcp/index.js.map +1 -1
  37. package/dist/mcp/production-server.d.ts +31 -0
  38. package/dist/{protocol-C7kTcBr_.cjs → protocol-C8pFDmcy.cjs} +8194 -8187
  39. package/dist/protocol-C8pFDmcy.cjs.map +1 -0
  40. package/dist/{protocol-BfAACnv0.js → protocol-CRqiPTLT.js} +8186 -8185
  41. package/dist/protocol-CRqiPTLT.js.map +1 -0
  42. package/dist/{use-app-CfP9VypY.js → use-app-Bfargfa3.js} +194 -94
  43. package/dist/use-app-Bfargfa3.js.map +1 -0
  44. package/dist/{use-app-CzcYw1Kz.cjs → use-app-CbsBEmwv.cjs} +254 -148
  45. package/dist/use-app-CbsBEmwv.cjs.map +1 -0
  46. package/package.json +27 -3
  47. package/template/README.md +17 -7
  48. package/template/_gitignore +2 -0
  49. package/template/dist/albums/albums.html +15 -15
  50. package/template/dist/albums/albums.json +1 -1
  51. package/template/dist/carousel/carousel.html +19 -19
  52. package/template/dist/carousel/carousel.json +1 -1
  53. package/template/dist/map/map.html +14 -14
  54. package/template/dist/map/map.json +1 -1
  55. package/template/dist/review/review.html +11 -11
  56. package/template/dist/review/review.json +1 -1
  57. package/template/node_modules/.bin/vitest +2 -2
  58. package/template/node_modules/.vite/deps/_metadata.json +3 -3
  59. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +192 -91
  60. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
  61. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +231 -92
  62. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
  63. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +208 -105
  64. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
  65. package/template/node_modules/.vite-mcp/deps/_metadata.json +25 -25
  66. package/template/node_modules/.vite-mcp/deps/{protocol-B_qKkui_.js → protocol-BqGB4zBx.js} +45 -45
  67. package/template/node_modules/.vite-mcp/deps/protocol-BqGB4zBx.js.map +1 -0
  68. package/template/node_modules/.vite-mcp/deps/vitest.js +7 -7
  69. package/template/node_modules/.vite-mcp/deps/vitest.js.map +1 -1
  70. package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-chatgpt-darwin.png +0 -0
  71. package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-claude-darwin.png +0 -0
  72. package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-chatgpt-darwin.png +0 -0
  73. package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-darwin.png +0 -0
  74. package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-chatgpt-darwin.png +0 -0
  75. package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-claude-darwin.png +0 -0
  76. package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-chatgpt-darwin.png +0 -0
  77. package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-claude-darwin.png +0 -0
  78. package/template/tests/evals/.env.example +5 -0
  79. package/template/tests/evals/albums.eval.ts +28 -0
  80. package/template/tests/evals/carousel.eval.ts +26 -0
  81. package/template/tests/evals/eval.config.ts +26 -0
  82. package/template/tests/evals/map.eval.ts +23 -0
  83. package/template/tests/evals/review.eval.ts +48 -0
  84. package/dist/inspector-8nPV2A-z.cjs.map +0 -1
  85. package/dist/inspector-Cdo5BK2D.js.map +0 -1
  86. package/dist/protocol-BfAACnv0.js.map +0 -1
  87. package/dist/protocol-C7kTcBr_.cjs.map +0 -1
  88. package/dist/use-app-CfP9VypY.js.map +0 -1
  89. package/dist/use-app-CzcYw1Kz.cjs.map +0 -1
  90. package/template/node_modules/.vite-mcp/deps/protocol-B_qKkui_.js.map +0 -1
@@ -1,9 +1,65 @@
1
- import { $ as literal, D as ListResourcesResultSchema, I as ReadResourceResultSchema, L as RequestIdSchema, N as PingRequestSchema, Q as boolean, R as ResourceLinkSchema, U as ToolSchema, X as _undefined, Z as array, _ as ImplementationSchema, a as CallToolResultSchema, at as unknown, b as JSONRPCMessageSchema, et as number, i as CallToolRequestSchema, it as union, k as ListToolsRequestSchema, m as EmptyResultSchema, nt as record, p as EmbeddedResourceSchema, rt as string, s as ContentBlockSchema, t as Protocol, tt as object } from "./protocol-BfAACnv0.js";
1
+ import { A as JSONRPCMessageSchema, C as EmbeddedResourceSchema, D as ImplementationSchema, J as RequestIdSchema, L as ListResourcesResultSchema, W as PingRequestSchema, Y as ResourceLinkSchema, _ as ContentBlockSchema, ct as array, dt as number, et as ToolSchema, ft as object, gt as unknown, h as CallToolResultSchema, ht as union, lt as boolean, m as CallToolRequestSchema, mt as string, pt as record, q as ReadResourceResultSchema, st as _undefined, t as Protocol, ut as literal, w as EmptyResultSchema, z as ListToolsRequestSchema } from "./protocol-CRqiPTLT.js";
2
2
  import { createContext, useContext, useEffect, useState } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
- //#region ../../node_modules/.pnpm/@modelcontextprotocol+ext-apps@1.3.2_@modelcontextprotocol+sdk@1.29.0_zod@4.3.6__react-_38e5f6c50a4ca9cf3f1dffc73a60c951/node_modules/@modelcontextprotocol/ext-apps/dist/src/app.js
5
- var E = "2026-01-26", y = "ui/open-link", u = "ui/download-file", f = "ui/message", m = "ui/notifications/size-changed", i = "ui/notifications/tool-input", z = "ui/notifications/tool-input-partial", l = "ui/notifications/tool-result", r = "ui/notifications/tool-cancelled", c = "ui/notifications/host-context-changed", p = "ui/notifications/request-teardown", n = "ui/resource-teardown", a = "ui/initialize", o = "ui/notifications/initialized", s = "ui/request-display-mode";
6
- var K = class {
4
+ //#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/app.js
5
+ var z = class extends Protocol {
6
+ _registeredMethods = /* @__PURE__ */ new Set();
7
+ _eventSlots = /* @__PURE__ */ new Map();
8
+ onEventDispatch(X, Y) {}
9
+ _ensureEventSlot(X) {
10
+ let Y = this._eventSlots.get(X);
11
+ if (!Y) {
12
+ let Z = this.eventSchemas[X];
13
+ if (!Z) throw Error(`Unknown event: ${String(X)}`);
14
+ Y = { listeners: [] }, this._eventSlots.set(X, Y);
15
+ let $ = Z.shape.method.value;
16
+ this._registeredMethods.add($);
17
+ let D = Y;
18
+ super.setNotificationHandler(Z, (J) => {
19
+ let G = J.params;
20
+ this.onEventDispatch(X, G), D.onHandler?.(G);
21
+ for (let V of [...D.listeners]) V(G);
22
+ });
23
+ }
24
+ return Y;
25
+ }
26
+ setEventHandler(X, Y) {
27
+ let Z = this._ensureEventSlot(X);
28
+ if (Z.onHandler && Y) console.warn(`[MCP Apps] on${String(X)} handler replaced. Use addEventListener("${String(X)}", …) to add multiple listeners without replacing.`);
29
+ Z.onHandler = Y;
30
+ }
31
+ getEventHandler(X) {
32
+ return this._eventSlots.get(X)?.onHandler;
33
+ }
34
+ addEventListener(X, Y) {
35
+ this._ensureEventSlot(X).listeners.push(Y);
36
+ }
37
+ removeEventListener(X, Y) {
38
+ let Z = this._eventSlots.get(X);
39
+ if (!Z) return;
40
+ let $ = Z.listeners.indexOf(Y);
41
+ if ($ !== -1) Z.listeners.splice($, 1);
42
+ }
43
+ setRequestHandler = (X, Y) => {
44
+ this._assertMethodNotRegistered(X, "setRequestHandler"), super.setRequestHandler(X, Y);
45
+ };
46
+ setNotificationHandler = (X, Y) => {
47
+ this._assertMethodNotRegistered(X, "setNotificationHandler"), super.setNotificationHandler(X, Y);
48
+ };
49
+ warnIfRequestHandlerReplaced(X, Y, Z) {
50
+ if (Y && Z) console.warn(`[MCP Apps] ${X} handler replaced. Previous handler will no longer be called.`);
51
+ }
52
+ replaceRequestHandler = (X, Y) => {
53
+ let Z = X.shape.method.value;
54
+ this._registeredMethods.add(Z), super.setRequestHandler(X, Y);
55
+ };
56
+ _assertMethodNotRegistered(X, Y) {
57
+ let Z = X.shape.method.value;
58
+ if (this._registeredMethods.has(Z)) throw Error(`Handler for "${Z}" already registered (via ${Y}). Use addEventListener() to attach multiple listeners, or the on* setter for replace semantics.`);
59
+ this._registeredMethods.add(Z);
60
+ }
61
+ }, B = "2026-01-26", u = "ui/open-link", d = "ui/download-file", h = "ui/message", p = "ui/notifications/size-changed", r = "ui/notifications/tool-input", E = "ui/notifications/tool-input-partial", c = "ui/notifications/tool-result", l = "ui/notifications/tool-cancelled", n = "ui/notifications/host-context-changed", a = "ui/notifications/request-teardown", o = "ui/resource-teardown", s = "ui/initialize", t = "ui/notifications/initialized", e = "ui/request-display-mode";
62
+ var N = class {
7
63
  eventTarget;
8
64
  eventSource;
9
65
  messageListener;
@@ -36,11 +92,11 @@ var K = class {
36
92
  onmessage;
37
93
  sessionId;
38
94
  setProtocolVersion;
39
- }, v = union([literal("light"), literal("dark")]).describe("Color theme preference for the host environment."), D = union([
95
+ }, k = union([literal("light"), literal("dark")]).describe("Color theme preference for the host environment."), K = union([
40
96
  literal("inline"),
41
97
  literal("fullscreen"),
42
98
  literal("pip")
43
- ]).describe("Display mode for UI presentation."), DQ = record(union([
99
+ ]).describe("Display mode for UI presentation."), KQ = record(union([
44
100
  literal("--color-background-primary"),
45
101
  literal("--color-background-secondary"),
46
102
  literal("--color-background-tertiary"),
@@ -135,15 +191,15 @@ Individual style keys are optional - hosts may provide any subset of these value
135
191
  Values are strings containing CSS values (colors, sizes, font stacks, etc.).
136
192
 
137
193
  Note: This type uses \`Record<K, string | undefined>\` rather than \`Partial<Record<K, string>>\`
138
- for compatibility with Zod schema generation. Both are functionally equivalent for validation.`), JQ = object({
194
+ for compatibility with Zod schema generation. Both are functionally equivalent for validation.`), GQ = object({
139
195
  method: literal("ui/open-link"),
140
196
  params: object({ url: string().describe("URL to open in the host's browser") })
141
- }), B = object({ isError: boolean().optional().describe("True if the host failed to open the URL (e.g., due to security policy).") }).passthrough(), _ = object({ isError: boolean().optional().describe("True if the download failed (e.g., user cancelled or host denied).") }).passthrough(), O = object({ isError: boolean().optional().describe("True if the host rejected or failed to deliver the message.") }).passthrough();
197
+ }), O = object({ isError: boolean().optional().describe("True if the host failed to open the URL (e.g., due to security policy).") }).passthrough(), I = object({ isError: boolean().optional().describe("True if the download failed (e.g., user cancelled or host denied).") }).passthrough(), w = object({ isError: boolean().optional().describe("True if the host rejected or failed to deliver the message.") }).passthrough();
142
198
  object({
143
199
  method: literal("ui/notifications/sandbox-proxy-ready"),
144
200
  params: object({})
145
201
  });
146
- var G = object({
202
+ var W = object({
147
203
  connectDomains: array(string()).optional().describe(`Origins for network requests (fetch/XHR/WebSocket).
148
204
 
149
205
  - Maps to CSP \`connect-src\` directive
@@ -151,43 +207,43 @@ var G = object({
151
207
  resourceDomains: array(string()).optional().describe("Origins for static resources (images, scripts, stylesheets, fonts, media).\n\n- Maps to CSP `img-src`, `script-src`, `style-src`, `font-src`, `media-src` directives\n- Wildcard subdomains supported: `https://*.example.com`\n- Empty or omitted → no network resources (secure default)"),
152
208
  frameDomains: array(string()).optional().describe("Origins for nested iframes.\n\n- Maps to CSP `frame-src` directive\n- Empty or omitted → no nested iframes allowed (`frame-src 'none'`)"),
153
209
  baseUriDomains: array(string()).optional().describe("Allowed base URIs for the document.\n\n- Maps to CSP `base-uri` directive\n- Empty or omitted → only same origin allowed (`base-uri 'self'`)")
154
- }), V = object({
210
+ }), j = object({
155
211
  camera: object({}).optional().describe("Request camera access.\n\nMaps to Permission Policy `camera` feature."),
156
212
  microphone: object({}).optional().describe("Request microphone access.\n\nMaps to Permission Policy `microphone` feature."),
157
213
  geolocation: object({}).optional().describe("Request geolocation access.\n\nMaps to Permission Policy `geolocation` feature."),
158
214
  clipboardWrite: object({}).optional().describe("Request clipboard write access.\n\nMaps to Permission Policy `clipboard-write` feature.")
159
- }), GQ = object({
215
+ }), NQ = object({
160
216
  method: literal("ui/notifications/size-changed"),
161
217
  params: object({
162
218
  width: number().optional().describe("New width in pixels."),
163
219
  height: number().optional().describe("New height in pixels.")
164
220
  })
165
- }), I = object({
221
+ }), A = object({
166
222
  method: literal("ui/notifications/tool-input"),
167
223
  params: object({ arguments: record(string(), unknown().describe("Complete tool call arguments as key-value pairs.")).optional().describe("Complete tool call arguments as key-value pairs.") })
168
- }), w = object({
224
+ }), F = object({
169
225
  method: literal("ui/notifications/tool-input-partial"),
170
226
  params: object({ arguments: record(string(), unknown().describe("Partial tool call arguments (incomplete, may change).")).optional().describe("Partial tool call arguments (incomplete, may change).") })
171
- }), A = object({
227
+ }), P = object({
172
228
  method: literal("ui/notifications/tool-cancelled"),
173
229
  params: object({ reason: string().optional().describe("Optional reason for the cancellation (e.g., \"user action\", \"timeout\").") })
174
- }), b = object({ fonts: string().optional() }), k = object({
175
- variables: DQ.optional().describe("CSS variables for theming the app."),
176
- css: b.optional().describe("CSS blocks that apps can inject.")
177
- }), F = object({
230
+ }), g = object({ fonts: string().optional() }), x = object({
231
+ variables: KQ.optional().describe("CSS variables for theming the app."),
232
+ css: g.optional().describe("CSS blocks that apps can inject.")
233
+ }), q = object({
178
234
  method: literal("ui/resource-teardown"),
179
235
  params: object({})
180
- }), VQ = record(string(), unknown()), L = object({
236
+ }), WQ = record(string(), unknown()), _ = object({
181
237
  text: object({}).optional().describe("Host supports text content blocks."),
182
238
  image: object({}).optional().describe("Host supports image content blocks."),
183
239
  audio: object({}).optional().describe("Host supports audio content blocks."),
184
240
  resource: object({}).optional().describe("Host supports resource content blocks."),
185
241
  resourceLink: object({}).optional().describe("Host supports resource link content blocks."),
186
242
  structuredContent: object({}).optional().describe("Host supports structured content.")
187
- }), WQ = object({
243
+ }), jQ = object({
188
244
  method: literal("ui/notifications/request-teardown"),
189
245
  params: object({}).optional()
190
- }), C = object({
246
+ }), S = object({
191
247
  experimental: object({}).optional().describe("Experimental features (structure TBD)."),
192
248
  openLinks: object({}).optional().describe("Host supports opening external URLs."),
193
249
  downloadFile: object({}).optional().describe("Host supports file downloads via ui/download-file."),
@@ -195,21 +251,21 @@ var G = object({
195
251
  serverResources: object({ listChanged: boolean().optional().describe("Host supports resources/list_changed notifications.") }).optional().describe("Host can proxy resource reads to the MCP server."),
196
252
  logging: object({}).optional().describe("Host accepts log messages."),
197
253
  sandbox: object({
198
- permissions: V.optional().describe("Permissions granted by the host (camera, microphone, geolocation)."),
199
- csp: G.optional().describe("CSP domains approved by the host.")
254
+ permissions: j.optional().describe("Permissions granted by the host (camera, microphone, geolocation)."),
255
+ csp: W.optional().describe("CSP domains approved by the host.")
200
256
  }).optional().describe("Sandbox configuration applied by the host."),
201
- updateModelContext: L.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),
202
- message: L.optional().describe("Host supports receiving content messages (ui/message) from the view.")
203
- }), x = object({
257
+ updateModelContext: _.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."),
258
+ message: _.optional().describe("Host supports receiving content messages (ui/message) from the view.")
259
+ }), y = object({
204
260
  experimental: object({}).optional().describe("Experimental features (structure TBD)."),
205
261
  tools: object({ listChanged: boolean().optional().describe("App supports tools/list_changed notifications.") }).optional().describe("App exposes MCP-style tools that the host can call."),
206
- availableDisplayModes: array(D).optional().describe("Display modes the app supports.")
207
- }), NQ = object({
262
+ availableDisplayModes: array(K).optional().describe("Display modes the app supports.")
263
+ }), LQ = object({
208
264
  method: literal("ui/notifications/initialized"),
209
265
  params: object({}).optional()
210
- }), jQ = object({
211
- csp: G.optional().describe("Content Security Policy configuration for UI resources."),
212
- permissions: V.optional().describe("Sandbox permissions requested by the UI resource."),
266
+ }), zQ = object({
267
+ csp: W.optional().describe("Content Security Policy configuration for UI resources."),
268
+ permissions: j.optional().describe("Sandbox permissions requested by the UI resource."),
213
269
  domain: string().optional().describe(`Dedicated origin for view sandbox.
214
270
 
215
271
  Useful when views need stable, dedicated origins for OAuth callbacks, CORS policies, or API key allowlists.
@@ -226,20 +282,20 @@ Boolean requesting whether a visible border and background is provided by the ho
226
282
  - \`true\`: request visible border + background
227
283
  - \`false\`: request no visible border + background
228
284
  - omitted: host decides border`)
229
- }), EQ = object({
285
+ }), BQ = object({
230
286
  method: literal("ui/request-display-mode"),
231
- params: object({ mode: D.describe("The display mode being requested.") })
232
- }), P = object({ mode: D.describe("The display mode that was actually set. May differ from requested if not supported.") }).passthrough(), g = union([literal("model"), literal("app")]).describe("Tool visibility scope - who can access the tool."), zQ = object({
287
+ params: object({ mode: K.describe("The display mode being requested.") })
288
+ }), T = object({ mode: K.describe("The display mode that was actually set. May differ from requested if not supported.") }).passthrough(), v = union([literal("model"), literal("app")]).describe("Tool visibility scope - who can access the tool."), EQ = object({
233
289
  resourceUri: string().optional(),
234
- visibility: array(g).optional().describe(`Who can access this tool. Default: ["model", "app"]
290
+ visibility: array(v).optional().describe(`Who can access this tool. Default: ["model", "app"]
235
291
  - "model": Tool visible to and callable by the agent
236
292
  - "app": Tool callable by the app from this server only`)
237
293
  });
238
294
  object({ mimeTypes: array(string()).optional().describe("Array of supported MIME types for UI resources.\nMust include `\"text/html;profile=mcp-app\"` for MCP Apps support.") });
239
- var LQ = object({
295
+ var _Q = object({
240
296
  method: literal("ui/download-file"),
241
297
  params: object({ contents: array(union([EmbeddedResourceSchema, ResourceLinkSchema])).describe("Resource contents to download — embedded (inline data) or linked (host fetches). Uses standard MCP resource types.") })
242
- }), BQ = object({
298
+ }), OQ = object({
243
299
  method: literal("ui/message"),
244
300
  params: object({
245
301
  role: literal("user").describe("Message role, currently only \"user\" is supported."),
@@ -251,22 +307,22 @@ object({
251
307
  params: object({
252
308
  html: string().describe("HTML content to load into the inner iframe."),
253
309
  sandbox: string().optional().describe("Optional override for the inner iframe's sandbox attribute."),
254
- csp: G.optional().describe("CSP configuration from resource metadata."),
255
- permissions: V.optional().describe("Sandbox permissions from resource metadata.")
310
+ csp: W.optional().describe("CSP configuration from resource metadata."),
311
+ permissions: j.optional().describe("Sandbox permissions from resource metadata.")
256
312
  })
257
313
  });
258
- var q = object({
314
+ var R = object({
259
315
  method: literal("ui/notifications/tool-result"),
260
316
  params: CallToolResultSchema.describe("Standard MCP tool execution result.")
261
- }), T = object({
317
+ }), U = object({
262
318
  toolInfo: object({
263
319
  id: RequestIdSchema.optional().describe("JSON-RPC id of the tools/call request."),
264
320
  tool: ToolSchema.describe("Tool definition including name, inputSchema, etc.")
265
321
  }).optional().describe("Metadata of the tool call that instantiated this App."),
266
- theme: v.optional().describe("Current color theme preference."),
267
- styles: k.optional().describe("Style configuration for theming the app."),
268
- displayMode: D.optional().describe("How the UI is currently displayed."),
269
- availableDisplayModes: array(D).optional().describe("Display modes the host supports."),
322
+ theme: k.optional().describe("Current color theme preference."),
323
+ styles: x.optional().describe("Style configuration for theming the app."),
324
+ displayMode: K.optional().describe("How the UI is currently displayed."),
325
+ availableDisplayModes: array(K).optional().describe("Display modes the host supports."),
270
326
  containerDimensions: union([object({ height: number().describe("Fixed container height in pixels.") }), object({ maxHeight: union([number(), _undefined()]).optional().describe("Maximum container height in pixels.") })]).and(union([object({ width: number().describe("Fixed container width in pixels.") }), object({ maxWidth: union([number(), _undefined()]).optional().describe("Maximum container width in pixels.") })])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
271
327
  container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),
272
328
  locale: string().optional().describe("User's language and region preference in BCP 47 format."),
@@ -287,53 +343,66 @@ container holding the app. Specify either width or maxWidth, and either height o
287
343
  bottom: number().describe("Bottom safe area inset in pixels."),
288
344
  left: number().describe("Left safe area inset in pixels.")
289
345
  }).optional().describe("Mobile safe area boundaries in pixels.")
290
- }).passthrough(), R = object({
346
+ }).passthrough(), H = object({
291
347
  method: literal("ui/notifications/host-context-changed"),
292
- params: T.describe("Partial context update containing only changed fields.")
293
- }), OQ = object({
348
+ params: U.describe("Partial context update containing only changed fields.")
349
+ }), wQ = object({
294
350
  method: literal("ui/update-model-context"),
295
351
  params: object({
296
352
  content: array(ContentBlockSchema).optional().describe("Context content blocks (text, image, etc.)."),
297
353
  structuredContent: record(string(), unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")
298
354
  })
299
- }), IQ = object({
355
+ }), AQ = object({
300
356
  method: literal("ui/initialize"),
301
357
  params: object({
302
358
  appInfo: ImplementationSchema.describe("App identification (name and version)."),
303
- appCapabilities: x.describe("Features and capabilities this app provides."),
359
+ appCapabilities: y.describe("Features and capabilities this app provides."),
304
360
  protocolVersion: string().describe("Protocol version this app supports.")
305
361
  })
306
- }), U = object({
362
+ }), M = object({
307
363
  protocolVersion: string().describe("Negotiated protocol version string (e.g., \"2025-11-21\")."),
308
364
  hostInfo: ImplementationSchema.describe("Host application identification and version."),
309
- hostCapabilities: C.describe("Features and capabilities provided by the host."),
310
- hostContext: T.describe("Rich context about the host environment.")
365
+ hostCapabilities: S.describe("Features and capabilities provided by the host."),
366
+ hostContext: U.describe("Rich context about the host environment.")
311
367
  }).passthrough();
312
- function wQ() {
368
+ function FQ() {
313
369
  let X = document.documentElement.getAttribute("data-theme");
314
370
  if (X === "dark" || X === "light") return X;
315
371
  return document.documentElement.classList.contains("dark") ? "dark" : "light";
316
372
  }
317
- function AQ(X) {
373
+ function PQ(X) {
318
374
  let Y = document.documentElement;
319
375
  Y.setAttribute("data-theme", X), Y.style.colorScheme = X;
320
376
  }
321
- function FQ(X, Y = document.documentElement) {
377
+ function qQ(X, Y = document.documentElement) {
322
378
  for (let [Z, $] of Object.entries(X)) if ($ !== void 0) Y.style.setProperty(Z, $);
323
379
  }
324
- function PQ(X) {
380
+ function TQ(X) {
325
381
  if (document.getElementById("__mcp-host-fonts")) return;
326
382
  let Z = document.createElement("style");
327
383
  Z.id = "__mcp-host-fonts", Z.textContent = X, document.head.appendChild(Z);
328
384
  }
329
- var RX = "ui/resourceUri", UX = "text/html;profile=mcp-app";
330
- var kQ = class extends Protocol {
385
+ var MX = "ui/resourceUri", CX = "text/html;profile=mcp-app";
386
+ var gQ = class extends z {
331
387
  _appInfo;
332
388
  _capabilities;
333
389
  options;
334
390
  _hostCapabilities;
335
391
  _hostInfo;
336
392
  _hostContext;
393
+ eventSchemas = {
394
+ toolinput: A,
395
+ toolinputpartial: F,
396
+ toolresult: R,
397
+ toolcancelled: P,
398
+ hostcontextchanged: H
399
+ };
400
+ onEventDispatch(X, Y) {
401
+ if (X === "hostcontextchanged") this._hostContext = {
402
+ ...this._hostContext,
403
+ ...Y
404
+ };
405
+ }
337
406
  constructor(X, Y = {}, Z = { autoResize: !0 }) {
338
407
  super(Z);
339
408
  this._appInfo = X;
@@ -341,7 +410,7 @@ var kQ = class extends Protocol {
341
410
  this.options = Z;
342
411
  this.setRequestHandler(PingRequestSchema, ($) => {
343
412
  return console.log("Received ping:", $.params), {};
344
- }), this.onhostcontextchanged = () => {};
413
+ }), this.setEventHandler("hostcontextchanged", void 0);
345
414
  }
346
415
  getHostCapabilities() {
347
416
  return this._hostCapabilities;
@@ -352,34 +421,65 @@ var kQ = class extends Protocol {
352
421
  getHostContext() {
353
422
  return this._hostContext;
354
423
  }
424
+ get ontoolinput() {
425
+ return this.getEventHandler("toolinput");
426
+ }
355
427
  set ontoolinput(X) {
356
- this.setNotificationHandler(I, (Y) => X(Y.params));
428
+ this.setEventHandler("toolinput", X);
429
+ }
430
+ get ontoolinputpartial() {
431
+ return this.getEventHandler("toolinputpartial");
357
432
  }
358
433
  set ontoolinputpartial(X) {
359
- this.setNotificationHandler(w, (Y) => X(Y.params));
434
+ this.setEventHandler("toolinputpartial", X);
435
+ }
436
+ get ontoolresult() {
437
+ return this.getEventHandler("toolresult");
360
438
  }
361
439
  set ontoolresult(X) {
362
- this.setNotificationHandler(q, (Y) => X(Y.params));
440
+ this.setEventHandler("toolresult", X);
441
+ }
442
+ get ontoolcancelled() {
443
+ return this.getEventHandler("toolcancelled");
363
444
  }
364
445
  set ontoolcancelled(X) {
365
- this.setNotificationHandler(A, (Y) => X(Y.params));
446
+ this.setEventHandler("toolcancelled", X);
447
+ }
448
+ get onhostcontextchanged() {
449
+ return this.getEventHandler("hostcontextchanged");
366
450
  }
367
451
  set onhostcontextchanged(X) {
368
- this.setNotificationHandler(R, (Y) => {
369
- this._hostContext = {
370
- ...this._hostContext,
371
- ...Y.params
372
- }, X(Y.params);
373
- });
452
+ this.setEventHandler("hostcontextchanged", X);
453
+ }
454
+ _onteardown;
455
+ get onteardown() {
456
+ return this._onteardown;
374
457
  }
375
458
  set onteardown(X) {
376
- this.setRequestHandler(F, (Y, Z) => X(Y.params, Z));
459
+ this.warnIfRequestHandlerReplaced("onteardown", this._onteardown, X), this._onteardown = X, this.replaceRequestHandler(q, (Y, Z) => {
460
+ if (!this._onteardown) throw Error("No onteardown handler set");
461
+ return this._onteardown(Y.params, Z);
462
+ });
463
+ }
464
+ _oncalltool;
465
+ get oncalltool() {
466
+ return this._oncalltool;
377
467
  }
378
468
  set oncalltool(X) {
379
- this.setRequestHandler(CallToolRequestSchema, (Y, Z) => X(Y.params, Z));
469
+ this.warnIfRequestHandlerReplaced("oncalltool", this._oncalltool, X), this._oncalltool = X, this.replaceRequestHandler(CallToolRequestSchema, (Y, Z) => {
470
+ if (!this._oncalltool) throw Error("No oncalltool handler set");
471
+ return this._oncalltool(Y.params, Z);
472
+ });
473
+ }
474
+ _onlisttools;
475
+ get onlisttools() {
476
+ return this._onlisttools;
380
477
  }
381
478
  set onlisttools(X) {
382
- this.setRequestHandler(ListToolsRequestSchema, (Y, Z) => X(Y.params, Z));
479
+ this.warnIfRequestHandlerReplaced("onlisttools", this._onlisttools, X), this._onlisttools = X, this.replaceRequestHandler(ListToolsRequestSchema, (Y, Z) => {
480
+ if (!this._onlisttools) throw Error("No onlisttools handler set");
481
+ return this._onlisttools(Y.params, Z);
482
+ });
383
483
  }
384
484
  assertCapabilityForMethod(X) {}
385
485
  assertRequestHandlerCapability(X) {
@@ -423,7 +523,7 @@ var kQ = class extends Protocol {
423
523
  return this.request({
424
524
  method: "ui/message",
425
525
  params: X
426
- }, O, Y);
526
+ }, w, Y);
427
527
  }
428
528
  sendLog(X) {
429
529
  return this.notification({
@@ -441,14 +541,14 @@ var kQ = class extends Protocol {
441
541
  return this.request({
442
542
  method: "ui/open-link",
443
543
  params: X
444
- }, B, Y);
544
+ }, O, Y);
445
545
  }
446
546
  sendOpenLink = this.openLink;
447
547
  downloadFile(X, Y) {
448
548
  return this.request({
449
549
  method: "ui/download-file",
450
550
  params: X
451
- }, _, Y);
551
+ }, I, Y);
452
552
  }
453
553
  requestTeardown(X = {}) {
454
554
  return this.notification({
@@ -460,7 +560,7 @@ var kQ = class extends Protocol {
460
560
  return this.request({
461
561
  method: "ui/request-display-mode",
462
562
  params: X
463
- }, P, Y);
563
+ }, T, Y);
464
564
  }
465
565
  sendSizeChanged(X) {
466
566
  return this.notification({
@@ -473,22 +573,22 @@ var kQ = class extends Protocol {
473
573
  if (X) return;
474
574
  X = !0, requestAnimationFrame(() => {
475
575
  X = !1;
476
- let J = document.documentElement, S = J.style.height;
576
+ let J = document.documentElement, G = J.style.height;
477
577
  J.style.height = "max-content";
478
- let N = Math.ceil(J.getBoundingClientRect().height);
479
- J.style.height = S;
480
- let j = Math.ceil(window.innerWidth);
481
- if (j !== Y || N !== Z) Y = j, Z = N, this.sendSizeChanged({
482
- width: j,
483
- height: N
578
+ let V = Math.ceil(J.getBoundingClientRect().height);
579
+ J.style.height = G;
580
+ let L = Math.ceil(window.innerWidth);
581
+ if (L !== Y || V !== Z) Y = L, Z = V, this.sendSizeChanged({
582
+ width: L,
583
+ height: V
484
584
  });
485
585
  });
486
586
  };
487
587
  $();
488
- let W = new ResizeObserver($);
489
- return W.observe(document.documentElement), W.observe(document.body), () => W.disconnect();
588
+ let D = new ResizeObserver($);
589
+ return D.observe(document.documentElement), D.observe(document.body), () => D.disconnect();
490
590
  }
491
- async connect(X = new K(window.parent, window.parent), Y) {
591
+ async connect(X = new N(window.parent, window.parent), Y) {
492
592
  if (this.transport) throw Error("App is already connected. Call close() before connecting again.");
493
593
  await super.connect(X);
494
594
  try {
@@ -497,9 +597,9 @@ var kQ = class extends Protocol {
497
597
  params: {
498
598
  appCapabilities: this._capabilities,
499
599
  appInfo: this._appInfo,
500
- protocolVersion: E
600
+ protocolVersion: B
501
601
  }
502
- }, U, Y);
602
+ }, M, Y);
503
603
  if (Z === void 0) throw Error(`Server sent invalid initialize result: ${Z}`);
504
604
  if (this._hostCapabilities = Z.hostCapabilities, this._hostInfo = Z.hostInfo, this._hostContext = Z.hostContext, await this.notification({ method: "ui/notifications/initialized" }), this.options?.autoResize) this.setupSizeChangedNotifications();
505
605
  } catch (Z) {
@@ -568,8 +668,8 @@ async function connectWithRetry(appInfo, capabilities, onAppCreated) {
568
668
  }
569
669
  let transport = null;
570
670
  try {
571
- transport = new K(window.parent, window.parent);
572
- const newApp = new kQ(appInfo, capabilities);
671
+ transport = new N(window.parent, window.parent);
672
+ const newApp = new gQ(appInfo, capabilities);
573
673
  onAppCreated?.(newApp);
574
674
  await withTimeout(newApp.connect(transport), CONNECT_TIMEOUT_MS);
575
675
  return newApp;
@@ -581,7 +681,7 @@ async function connectWithRetry(appInfo, capabilities, onAppCreated) {
581
681
  if (attempt < MAX_RETRIES) console.warn(`[sunpeak] Connection attempt ${attempt + 1}/${MAX_RETRIES + 1} failed, retrying...`, lastError.message);
582
682
  }
583
683
  }
584
- console.error("[sunpeak] All connection attempts failed. Try refreshing the page or opening a new chat.\nTroubleshooting: https://sunpeak.ai/docs/guides/troubleshooting");
684
+ console.error("[sunpeak] All connection attempts failed. Try refreshing the page or opening a new chat.\nTroubleshooting: https://sunpeak.ai/docs/app-framework/guides/troubleshooting");
585
685
  throw lastError ?? /* @__PURE__ */ new Error("Failed to connect");
586
686
  }
587
687
  function AppProvider({ appInfo, capabilities, onAppCreated, children }) {
@@ -653,6 +753,6 @@ function useApp() {
653
753
  return useContext(AppContext).app;
654
754
  }
655
755
  //#endregion
656
- export { v as $, UX as A, i as B, OQ as C, RX as D, R as E, a as F, m as G, k as H, b as I, p as J, n as K, c as L, VQ as M, WQ as N, T as O, _ as P, u as Q, f as R, O as S, PQ as T, kQ as U, jQ as V, l as W, r as X, q as Y, s as Z, JQ as _, B as a, zQ as at, LQ as b, D as c, F as d, w as et, FQ as f, IQ as g, I as h, AQ as i, z as it, V as j, U as k, E as l, GQ as m, AppProvider as n, x as nt, BQ as o, G as p, o as q, A as r, y as rt, C as s, useApp as t, wQ as tt, EQ as u, K as v, P as w, NQ as x, L as y, g as z };
756
+ export { u as $, W as A, h as B, P as C, T as D, S as E, c as F, n as G, jQ as H, d as I, q as J, o as K, e as L, _ as M, _Q as N, TQ as O, a as P, t as Q, g as R, OQ as S, R as T, k as U, j as V, l as W, r as X, qQ as Y, s as Z, M as _, B as a, z as at, NQ as b, E as c, FQ as d, v as et, GQ as f, LQ as g, K as h, AQ as i, y as it, WQ as j, U as k, EQ as l, I as m, AppProvider as n, wQ as nt, BQ as o, zQ as ot, H as p, p as q, A as r, x as rt, CX as s, useApp as t, w as tt, F as u, MX as v, PQ as w, O as x, N as y, gQ as z };
657
757
 
658
- //# sourceMappingURL=use-app-CfP9VypY.js.map
758
+ //# sourceMappingURL=use-app-Bfargfa3.js.map