@superblocksteam/gateway 2.0.161 → 2.0.162-next.1

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 (235) hide show
  1. package/README.md +135 -39
  2. package/dist/agents/resolve-orchestrator-url.d.ts +18 -0
  3. package/dist/agents/resolve-orchestrator-url.js +64 -1
  4. package/dist/agents/resolve-orchestrator-url.js.map +1 -1
  5. package/dist/capabilities/lifecycle.d.ts +46 -29
  6. package/dist/capabilities/lifecycle.js +1731 -843
  7. package/dist/capabilities/lifecycle.js.map +1 -1
  8. package/dist/capabilities/query-integration.d.ts +14 -0
  9. package/dist/capabilities/query-integration.js +172 -0
  10. package/dist/capabilities/query-integration.js.map +1 -0
  11. package/dist/capabilities/source-files-archive.d.ts +11 -0
  12. package/dist/capabilities/source-files-archive.js +54 -0
  13. package/dist/capabilities/source-files-archive.js.map +1 -0
  14. package/dist/capabilities/types.d.ts +197 -119
  15. package/dist/capabilities/types.js +45 -6
  16. package/dist/capabilities/types.js.map +1 -1
  17. package/dist/capture/browser-contract.d.ts +15 -5
  18. package/dist/capture/browser-contract.js +13 -3
  19. package/dist/capture/browser-contract.js.map +1 -1
  20. package/dist/capture/browser-instructions.d.ts +3 -2
  21. package/dist/capture/browser-instructions.js +3 -2
  22. package/dist/capture/browser-instructions.js.map +1 -1
  23. package/dist/capture/mode.d.ts +8 -1
  24. package/dist/capture/mode.js +22 -2
  25. package/dist/capture/mode.js.map +1 -1
  26. package/dist/config.d.ts +22 -23
  27. package/dist/config.js +13 -12
  28. package/dist/config.js.map +1 -1
  29. package/dist/deps.d.ts +7 -7
  30. package/dist/index.d.ts +2 -4
  31. package/dist/index.js +2 -4
  32. package/dist/index.js.map +1 -1
  33. package/dist/integrations/read-only-postgres-query.d.ts +2 -0
  34. package/dist/integrations/read-only-postgres-query.js +164 -0
  35. package/dist/integrations/read-only-postgres-query.js.map +1 -0
  36. package/dist/main.js +1 -1
  37. package/dist/main.js.map +1 -1
  38. package/dist/playwright/ensure-chromium.d.ts +5 -7
  39. package/dist/playwright/ensure-chromium.js +13 -13
  40. package/dist/playwright/ensure-chromium.js.map +1 -1
  41. package/dist/preview/capture-screenshot.d.ts +30 -4
  42. package/dist/preview/capture-screenshot.js +67 -17
  43. package/dist/preview/capture-screenshot.js.map +1 -1
  44. package/dist/preview/viewer-url.js +3 -1
  45. package/dist/preview/viewer-url.js.map +1 -1
  46. package/dist/process/fault-barrier.js +1 -1
  47. package/dist/process/fault-barrier.js.map +1 -1
  48. package/dist/sabs/agent-facing-text.d.ts +2 -0
  49. package/dist/sabs/agent-facing-text.js +56 -2
  50. package/dist/sabs/agent-facing-text.js.map +1 -1
  51. package/dist/sabs/app-state.d.ts +126 -0
  52. package/dist/sabs/app-state.js +332 -0
  53. package/dist/sabs/app-state.js.map +1 -0
  54. package/dist/sabs/awaited-decision.d.ts +49 -0
  55. package/dist/sabs/awaited-decision.js +129 -0
  56. package/dist/sabs/awaited-decision.js.map +1 -0
  57. package/dist/sabs/editor-client-methods.d.ts +23 -5
  58. package/dist/sabs/editor-client-methods.js +45 -4
  59. package/dist/sabs/editor-client-methods.js.map +1 -1
  60. package/dist/sabs/editor-socket.d.ts +85 -0
  61. package/dist/sabs/editor-socket.js +67 -0
  62. package/dist/sabs/editor-socket.js.map +1 -0
  63. package/dist/sabs/session-peer.d.ts +119 -82
  64. package/dist/sabs/session-peer.js +10 -1
  65. package/dist/sabs/session-peer.js.map +1 -1
  66. package/dist/sabs/streamed-reply.d.ts +45 -0
  67. package/dist/sabs/streamed-reply.js +125 -0
  68. package/dist/sabs/streamed-reply.js.map +1 -0
  69. package/dist/sabs/turn-collector.d.ts +50 -35
  70. package/dist/sabs/turn-collector.js +110 -176
  71. package/dist/sabs/turn-collector.js.map +1 -1
  72. package/dist/sabs/websocket-session-peer.d.ts +104 -69
  73. package/dist/sabs/websocket-session-peer.js +1333 -477
  74. package/dist/sabs/websocket-session-peer.js.map +1 -1
  75. package/dist/server/client.d.ts +41 -9
  76. package/dist/server/client.js +126 -21
  77. package/dist/server/client.js.map +1 -1
  78. package/dist/start.d.ts +1 -1
  79. package/dist/start.js +30 -8
  80. package/dist/start.js.map +1 -1
  81. package/dist/stores/memory.d.ts +46 -0
  82. package/dist/stores/memory.js +163 -0
  83. package/dist/stores/memory.js.map +1 -0
  84. package/dist/stores/types.d.ts +92 -0
  85. package/dist/stores/types.js +11 -0
  86. package/dist/stores/types.js.map +1 -0
  87. package/dist/telemetry/mcp-client.d.ts +6 -1
  88. package/dist/telemetry/mcp-client.js +100 -4
  89. package/dist/telemetry/mcp-client.js.map +1 -1
  90. package/dist/telemetry/metrics.d.ts +12 -3
  91. package/dist/telemetry/metrics.js +60 -14
  92. package/dist/telemetry/metrics.js.map +1 -1
  93. package/dist/telemetry/runtime.js +4 -6
  94. package/dist/telemetry/runtime.js.map +1 -1
  95. package/dist/transports/mcp/admin-tools.d.ts +8 -0
  96. package/dist/transports/mcp/admin-tools.js +115 -4
  97. package/dist/transports/mcp/admin-tools.js.map +1 -1
  98. package/dist/transports/mcp/app-status-html.d.ts +4 -8
  99. package/dist/transports/mcp/app-status-html.js +336 -128
  100. package/dist/transports/mcp/app-status-html.js.map +1 -1
  101. package/dist/transports/mcp/client-presentation.d.ts +16 -0
  102. package/dist/transports/mcp/client-presentation.js +13 -0
  103. package/dist/transports/mcp/client-presentation.js.map +1 -0
  104. package/dist/transports/mcp/cowork-editor-url.d.ts +6 -0
  105. package/dist/transports/mcp/cowork-editor-url.js +10 -0
  106. package/dist/transports/mcp/cowork-editor-url.js.map +1 -0
  107. package/dist/transports/mcp/decision-card-html.d.ts +26 -0
  108. package/dist/transports/mcp/decision-card-html.js +876 -0
  109. package/dist/transports/mcp/decision-card-html.js.map +1 -0
  110. package/dist/transports/mcp/decision-elicitation.d.ts +42 -0
  111. package/dist/transports/mcp/decision-elicitation.js +59 -0
  112. package/dist/transports/mcp/decision-elicitation.js.map +1 -1
  113. package/dist/transports/mcp/editor-document-probe.d.ts +4 -0
  114. package/dist/transports/mcp/editor-document-probe.js +35 -0
  115. package/dist/transports/mcp/editor-document-probe.js.map +1 -0
  116. package/dist/transports/mcp/editor-integration-setup-url.d.ts +14 -0
  117. package/dist/transports/mcp/editor-integration-setup-url.js +29 -0
  118. package/dist/transports/mcp/editor-integration-setup-url.js.map +1 -0
  119. package/dist/transports/mcp/format-tool-content.d.ts +13 -18
  120. package/dist/transports/mcp/format-tool-content.js +172 -13
  121. package/dist/transports/mcp/format-tool-content.js.map +1 -1
  122. package/dist/transports/mcp/instructions/index.d.ts +23 -0
  123. package/dist/transports/mcp/instructions/index.js +81 -0
  124. package/dist/transports/mcp/instructions/index.js.map +1 -0
  125. package/dist/transports/mcp/instructions/result.d.ts +18 -0
  126. package/dist/transports/mcp/instructions/result.js +58 -0
  127. package/dist/transports/mcp/instructions/result.js.map +1 -0
  128. package/dist/transports/mcp/instructions/tools/ask-user.d.ts +2 -0
  129. package/dist/transports/mcp/instructions/tools/ask-user.js +20 -0
  130. package/dist/transports/mcp/instructions/tools/ask-user.js.map +1 -0
  131. package/dist/transports/mcp/instructions/tools/build-app.d.ts +4 -0
  132. package/dist/transports/mcp/instructions/tools/build-app.js +54 -0
  133. package/dist/transports/mcp/instructions/tools/build-app.js.map +1 -0
  134. package/dist/transports/mcp/instructions/tools/check-app-progress.d.ts +3 -0
  135. package/dist/transports/mcp/instructions/tools/check-app-progress.js +79 -0
  136. package/dist/transports/mcp/instructions/tools/check-app-progress.js.map +1 -0
  137. package/dist/transports/mcp/instructions/tools/check-publish-progress.d.ts +3 -0
  138. package/dist/transports/mcp/instructions/tools/check-publish-progress.js +23 -0
  139. package/dist/transports/mcp/instructions/tools/check-publish-progress.js.map +1 -0
  140. package/dist/transports/mcp/instructions/tools/copy.d.ts +18 -0
  141. package/dist/transports/mcp/instructions/tools/copy.js +49 -0
  142. package/dist/transports/mcp/instructions/tools/copy.js.map +1 -0
  143. package/dist/transports/mcp/instructions/tools/create-integration.d.ts +4 -0
  144. package/dist/transports/mcp/instructions/tools/create-integration.js +41 -0
  145. package/dist/transports/mcp/instructions/tools/create-integration.js.map +1 -0
  146. package/dist/transports/mcp/instructions/tools/edit-app.d.ts +3 -0
  147. package/dist/transports/mcp/instructions/tools/edit-app.js +18 -0
  148. package/dist/transports/mcp/instructions/tools/edit-app.js.map +1 -0
  149. package/dist/transports/mcp/instructions/tools/get-app.d.ts +3 -0
  150. package/dist/transports/mcp/instructions/tools/get-app.js +49 -0
  151. package/dist/transports/mcp/instructions/tools/get-app.js.map +1 -0
  152. package/dist/transports/mcp/instructions/tools/get-integration-metadata.d.ts +2 -0
  153. package/dist/transports/mcp/instructions/tools/get-integration-metadata.js +13 -0
  154. package/dist/transports/mcp/instructions/tools/get-integration-metadata.js.map +1 -0
  155. package/dist/transports/mcp/instructions/tools/index.d.ts +7 -0
  156. package/dist/transports/mcp/instructions/tools/index.js +31 -0
  157. package/dist/transports/mcp/instructions/tools/index.js.map +1 -0
  158. package/dist/transports/mcp/instructions/tools/publish-app.d.ts +3 -0
  159. package/dist/transports/mcp/instructions/tools/publish-app.js +23 -0
  160. package/dist/transports/mcp/instructions/tools/publish-app.js.map +1 -0
  161. package/dist/transports/mcp/instructions/tools/start-app.d.ts +3 -0
  162. package/dist/transports/mcp/instructions/tools/start-app.js +22 -0
  163. package/dist/transports/mcp/instructions/tools/start-app.js.map +1 -0
  164. package/dist/transports/mcp/instructions/tools/upload-artifact.d.ts +2 -0
  165. package/dist/transports/mcp/instructions/tools/upload-artifact.js +13 -0
  166. package/dist/transports/mcp/instructions/tools/upload-artifact.js.map +1 -0
  167. package/dist/transports/mcp/mcp-app-brand-css.d.ts +1 -0
  168. package/dist/transports/mcp/mcp-app-brand-css.js +180 -0
  169. package/dist/transports/mcp/mcp-app-brand-css.js.map +1 -0
  170. package/dist/transports/mcp/mount.d.ts +14 -1
  171. package/dist/transports/mcp/mount.js +729 -172
  172. package/dist/transports/mcp/mount.js.map +1 -1
  173. package/dist/transports/mcp/native-browser-presence.d.ts +45 -0
  174. package/dist/transports/mcp/native-browser-presence.js +158 -0
  175. package/dist/transports/mcp/native-browser-presence.js.map +1 -0
  176. package/dist/transports/mcp/plan-approval.d.ts +44 -0
  177. package/dist/transports/mcp/plan-approval.js +179 -0
  178. package/dist/transports/mcp/plan-approval.js.map +1 -0
  179. package/dist/transports/mcp/session-directory.d.ts +7 -0
  180. package/dist/transports/mcp/session-directory.js +18 -0
  181. package/dist/transports/mcp/session-directory.js.map +1 -0
  182. package/dist/transports/mcp/tool-names.d.ts +2 -0
  183. package/dist/transports/mcp/tool-names.js +2 -0
  184. package/dist/transports/mcp/tool-names.js.map +1 -0
  185. package/package.json +16 -7
  186. package/skills/superblocks-build/SKILL.md +59 -0
  187. package/skills/superblocks-import/SKILL.md +125 -0
  188. package/dist/capabilities/import-prompt.d.ts +0 -11
  189. package/dist/capabilities/import-prompt.js +0 -96
  190. package/dist/capabilities/import-prompt.js.map +0 -1
  191. package/dist/capabilities/persisted-progress.d.ts +0 -46
  192. package/dist/capabilities/persisted-progress.js +0 -246
  193. package/dist/capabilities/persisted-progress.js.map +0 -1
  194. package/dist/events/cursor.d.ts +0 -43
  195. package/dist/events/cursor.js +0 -78
  196. package/dist/events/cursor.js.map +0 -1
  197. package/dist/events/memory-event-store.d.ts +0 -34
  198. package/dist/events/memory-event-store.js +0 -110
  199. package/dist/events/memory-event-store.js.map +0 -1
  200. package/dist/events/merge.d.ts +0 -23
  201. package/dist/events/merge.js +0 -97
  202. package/dist/events/merge.js.map +0 -1
  203. package/dist/events/normalized-collector.d.ts +0 -62
  204. package/dist/events/normalized-collector.js +0 -156
  205. package/dist/events/normalized-collector.js.map +0 -1
  206. package/dist/events/schema.d.ts +0 -9
  207. package/dist/events/schema.js +0 -93
  208. package/dist/events/schema.js.map +0 -1
  209. package/dist/events/snapshot.d.ts +0 -32
  210. package/dist/events/snapshot.js +0 -57
  211. package/dist/events/snapshot.js.map +0 -1
  212. package/dist/events/stream-key.d.ts +0 -2
  213. package/dist/events/stream-key.js +0 -31
  214. package/dist/events/stream-key.js.map +0 -1
  215. package/dist/events/types.d.ts +0 -179
  216. package/dist/events/types.js +0 -66
  217. package/dist/events/types.js.map +0 -1
  218. package/dist/resume/memory-progress-store.d.ts +0 -39
  219. package/dist/resume/memory-progress-store.js +0 -82
  220. package/dist/resume/memory-progress-store.js.map +0 -1
  221. package/dist/resume/memory-recent-app-store.d.ts +0 -14
  222. package/dist/resume/memory-recent-app-store.js +0 -27
  223. package/dist/resume/memory-recent-app-store.js.map +0 -1
  224. package/dist/resume/memory-turn-store.d.ts +0 -18
  225. package/dist/resume/memory-turn-store.js +0 -73
  226. package/dist/resume/memory-turn-store.js.map +0 -1
  227. package/dist/resume/progress-key.d.ts +0 -21
  228. package/dist/resume/progress-key.js +0 -58
  229. package/dist/resume/progress-key.js.map +0 -1
  230. package/dist/resume/stores.d.ts +0 -14
  231. package/dist/resume/stores.js +0 -18
  232. package/dist/resume/stores.js.map +0 -1
  233. package/dist/resume/types.d.ts +0 -124
  234. package/dist/resume/types.js +0 -13
  235. package/dist/resume/types.js.map +0 -1
@@ -1,6 +1,9 @@
1
1
  import { z } from "zod";
2
2
  import { buildToolRegistry, executeToolCall, runWithAuthContext, toolDefinitions, } from "@superblocksteam/mcp-server";
3
3
  import { gatewayDebug, gatewayDebugStack } from "../../debug.js";
4
+ import { attachAdminAgentInstructions } from "./instructions/index.js";
5
+ import { isRecord } from "./instructions/result.js";
6
+ import { isPublicIntegration } from "./instructions/tools/create-integration.js";
4
7
  /**
5
8
  * Loose JSON-Schema -> Zod conversion so `registerTool` can list Admin tools
6
9
  * with usable shapes. Handlers still validate through `@superblocksteam/mcp-server`.
@@ -29,6 +32,14 @@ export function jsonSchemaToZodShape(inputSchema, options = {}) {
29
32
  const GATEWAY_SUPPLIED_ARGUMENTS = {
30
33
  base_url: "Omit this. The gateway always sends its own Superblocks Server URL; any value here is replaced.",
31
34
  };
35
+ /**
36
+ * Gateway-only argument on `create_integration`, and the one thing this process
37
+ * cannot work out for itself: which application the conversation is building.
38
+ * Stripped before the shared Admin handler, whose schema is strict.
39
+ */
40
+ const CREATE_INTEGRATION_APPLICATION_ID = "application_id";
41
+ const CREATE_INTEGRATION_APPLICATION_ID_DESCRIPTION = "The application this conversation is building, when there is one. Pass it so credential entry opens on the Integrations tab inside that editor and the user stays where they are. Omit it when this conversation has not started or edited an application: the result then links the org Integrations page. Never pass an application another conversation is working on.";
42
+ const CREATE_INTEGRATION_GUIDANCE = " When this conversation has already started or edited an application, pass its applicationId as application_id so credential entry opens inside that editor.";
32
43
  /**
33
44
  * Admin tools the gateway keeps to itself.
34
45
  *
@@ -118,6 +129,70 @@ export function completeToolAnnotations(annotations) {
118
129
  readOnlyHint,
119
130
  };
120
131
  }
132
+ function parseCreateIntegrationPayload(result) {
133
+ if (result.isError || result.content[0]?.type !== "text") {
134
+ return undefined;
135
+ }
136
+ let value;
137
+ try {
138
+ value = JSON.parse(result.content[0].text);
139
+ }
140
+ catch {
141
+ return undefined;
142
+ }
143
+ return isRecord(value) ? value : undefined;
144
+ }
145
+ function withCreateIntegrationPayload(result, value) {
146
+ return {
147
+ ...result,
148
+ content: [{ type: "text", text: JSON.stringify(value) }],
149
+ };
150
+ }
151
+ async function withEditorIntegrationSetupUrl(result, resolveUrl, applicationId) {
152
+ const value = parseCreateIntegrationPayload(result);
153
+ if (!value ||
154
+ isPublicIntegration(value) ||
155
+ (isRecord(value.integration) && value.integration.kind === "SECRET") ||
156
+ typeof value.integration_id !== "string" ||
157
+ !value.integration_id ||
158
+ !resolveUrl) {
159
+ return result;
160
+ }
161
+ let editorUrl;
162
+ try {
163
+ editorUrl = await resolveUrl(value.integration_id, applicationId);
164
+ }
165
+ catch (error) {
166
+ gatewayDebug("create_integration editor URL enrichment failed", {
167
+ integrationId: value.integration_id,
168
+ message: error instanceof Error ? error.message : String(error),
169
+ });
170
+ return result;
171
+ }
172
+ if (!editorUrl) {
173
+ return result;
174
+ }
175
+ return withCreateIntegrationPayload(result, {
176
+ ...value,
177
+ integration_url: editorUrl,
178
+ });
179
+ }
180
+ function withCreateIntegrationBrowserNavigation(result) {
181
+ const value = parseCreateIntegrationPayload(result);
182
+ if (!value || typeof value.integration_url !== "string") {
183
+ return result;
184
+ }
185
+ return {
186
+ ...result,
187
+ structuredContent: {
188
+ ...value,
189
+ browserNavigation: {
190
+ action: "open_editor",
191
+ url: value.integration_url,
192
+ },
193
+ },
194
+ };
195
+ }
121
196
  /**
122
197
  * Registers customer-profile Admin MCP tools on the same McpServer as Builder
123
198
  * tools. Each call runs under `runWithAuthContext` with the Gateway's
@@ -132,10 +207,21 @@ export function registerAdminTools(server, options) {
132
207
  continue;
133
208
  }
134
209
  const definition = toolDefinitions.find((d) => d.name === tool.name);
210
+ const isCreateIntegration = tool.name === "create_integration";
135
211
  server.registerTool(tool.name, {
136
212
  annotations: completeToolAnnotations(tool.annotations),
137
- description: superblocksProductCopy(tool.description ?? ""),
138
- inputSchema: gatewayAdminInputShape(tool.inputSchema),
213
+ description: superblocksProductCopy(tool.description ?? "") +
214
+ (isCreateIntegration ? CREATE_INTEGRATION_GUIDANCE : ""),
215
+ inputSchema: isCreateIntegration
216
+ ? {
217
+ ...gatewayAdminInputShape(tool.inputSchema),
218
+ [CREATE_INTEGRATION_APPLICATION_ID]: z
219
+ .string()
220
+ .uuid()
221
+ .optional()
222
+ .describe(CREATE_INTEGRATION_APPLICATION_ID_DESCRIPTION),
223
+ }
224
+ : gatewayAdminInputShape(tool.inputSchema),
139
225
  title: tool.title ?? definition?.title,
140
226
  }, async (args, extra) => {
141
227
  gatewayDebugStack("admin tool started", {
@@ -145,20 +231,45 @@ export function registerAdminTools(server, options) {
145
231
  try {
146
232
  const token = await resolveToken(options, extra.authInfo);
147
233
  const baseUrl = options.serverUrl.replace(/\/$/, "");
234
+ const rawArgs = args;
235
+ const setupApplicationId = isCreateIntegration &&
236
+ typeof rawArgs[CREATE_INTEGRATION_APPLICATION_ID] === "string"
237
+ ? rawArgs[CREATE_INTEGRATION_APPLICATION_ID]
238
+ : undefined;
148
239
  const callArgs = {
149
- ...args,
240
+ ...rawArgs,
150
241
  // Overwritten, never merged. The credential this call runs with belongs
151
242
  // to the Gateway's own control plane, so a base_url from the model
152
243
  // would send that credential to a host the model chose - reachable
153
244
  // through any prompt injection that gets as far as a tool call.
154
245
  base_url: baseUrl,
155
246
  };
247
+ if (isCreateIntegration) {
248
+ // The shared Admin schema is strict and knows nothing about it.
249
+ delete callArgs[CREATE_INTEGRATION_APPLICATION_ID];
250
+ }
156
251
  const result = await runWithAuthContext({ baseUrl, token }, () => executeToolCall(tool.name, callArgs, registry));
157
252
  gatewayDebug("admin tool finished", {
158
253
  "result.kind": "success",
159
254
  "tool.name": tool.name,
160
255
  });
161
- return result;
256
+ const profile = options.clientProfile?.();
257
+ if (!isCreateIntegration) {
258
+ if (profile &&
259
+ (tool.name === "get_application_access" ||
260
+ tool.name === "get_application_deployment_history" ||
261
+ tool.name === "get_application_summary")) {
262
+ return attachAdminAgentInstructions(tool.name, result, profile);
263
+ }
264
+ return result;
265
+ }
266
+ const withEditorUrl = await withEditorIntegrationSetupUrl(result, options.resolveEditorIntegrationSetupUrl, setupApplicationId);
267
+ const withBrowser = profile?.hasNativeBrowser === true
268
+ ? withCreateIntegrationBrowserNavigation(withEditorUrl)
269
+ : withEditorUrl;
270
+ return profile
271
+ ? attachAdminAgentInstructions("create_integration", withBrowser, profile)
272
+ : withBrowser;
162
273
  }
163
274
  catch (error) {
164
275
  gatewayDebug("admin tool finished", {
@@ -1 +1 @@
1
- {"version":3,"file":"admin-tools.js","sourceRoot":"","sources":["../../../src/transports/mcp/admin-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"admin-tools.js","sourceRoot":"","sources":["../../../src/transports/mcp/admin-tools.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,11 @@
1
1
  /**
2
- * Self-contained MCP App HTML for Gateway status / open-link buttons.
2
+ * Self-contained MCP App HTML for Gateway status and open-link buttons.
3
3
  *
4
- * Nested iframes of Superblocks (preview / editor / live) were removed: Claude's
5
- * widget origin cannot hold a Superblocks Auth0 session, and Private Network
6
- * Access blocks localhost from a public parent. Display-mode controls (pip /
7
- * fullscreen / inline) were also removed — without an iframe they only resized
8
- * the status card. openLink buttons keep URLs in JS memory only (not printed).
4
+ * openLink buttons keep URLs in JS memory only (not printed).
9
5
  *
10
6
  * Speaks the MCP Apps postMessage dialect without bundling ext-apps into the
11
7
  * card (hosts cache UI resources; keep this file small and inline). Bump the
12
8
  * resource URI when the HTML changes so Claude Desktop refreshes its cache.
13
9
  */
14
- export declare const APP_STATUS_RESOURCE_URI = "ui://gateway/app-status-v8.html";
15
- export declare const APP_STATUS_HTML = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Superblocks app</title>\n <style>\n :root {\n color-scheme: light dark;\n }\n body {\n margin: 0;\n font-family: var(--font-sans, system-ui, -apple-system, sans-serif);\n font-size: var(--font-text-sm-size, 13px);\n line-height: var(--font-text-sm-line-height, 1.45);\n color: var(--color-text-primary, #0f172a);\n background: transparent;\n }\n .card {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px;\n border: var(--border-width-regular, 1px) solid\n var(--color-border-primary, #e2e8f0);\n border-radius: var(--border-radius-lg, 12px);\n background: var(--color-background-primary, #ffffff);\n }\n .head {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n h1 {\n flex: 1;\n margin: 0;\n font-size: var(--font-text-md-size, 14px);\n font-weight: var(--font-weight-semibold, 600);\n }\n .status {\n padding: 2px 8px;\n border-radius: var(--border-radius-full, 999px);\n background: var(--color-background-secondary, #f1f5f9);\n color: var(--color-text-secondary, #64748b);\n font-size: var(--font-text-xs-size, 12px);\n text-transform: lowercase;\n }\n .meta {\n color: var(--color-text-tertiary, #94a3b8);\n font-size: var(--font-text-xs-size, 12px);\n }\n .note {\n display: none;\n color: var(--color-text-warning, #b45309);\n font-size: var(--font-text-xs-size, 12px);\n }\n .note.shown {\n display: block;\n }\n .shot {\n display: none;\n width: 100%;\n border: var(--border-width-regular, 1px) solid\n var(--color-border-primary, #e2e8f0);\n border-radius: var(--border-radius-md, 8px);\n }\n .shot.shown {\n display: block;\n }\n .actions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n }\n button {\n appearance: none;\n border: var(--border-width-regular, 1px) solid\n var(--color-border-primary, #e2e8f0);\n border-radius: var(--border-radius-md, 8px);\n padding: 7px 12px;\n background: var(--color-background-secondary, #f8fafc);\n color: var(--color-text-primary, #0f172a);\n font: inherit;\n font-weight: var(--font-weight-medium, 500);\n cursor: pointer;\n }\n button:hover:not(:disabled) {\n background: var(--color-background-tertiary, #f1f5f9);\n }\n button:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"head\">\n <h1>Superblocks app</h1>\n <span id=\"status\" class=\"status\">loading</span>\n </div>\n <div id=\"appId\" class=\"meta\"></div>\n <img id=\"shot\" class=\"shot\" alt=\"Preview of the running app\" />\n <div id=\"note\" class=\"note\"></div>\n <div class=\"actions\">\n <button id=\"openEditor\" type=\"button\" disabled>Open editor</button>\n <button id=\"openPreview\" type=\"button\" disabled>Open preview</button>\n <button id=\"publishApp\" type=\"button\" disabled>Publish app</button>\n </div>\n </div>\n <script>\n (() => {\n const PROTOCOL_VERSION = \"2026-01-26\";\n // Statuses get_app reports when the app is still the empty starter\n // template. \"building\" is deliberately absent: the card only hears a\n // build finished if a new result arrives, so a stale badge would strand\n // the button.\n const UNBUILT_STATUSES = [\n \"cancelled\",\n \"live_edit_terminated\",\n \"needs_decision\",\n \"no_changes\",\n \"timeout\",\n ];\n const BLOCKED_ACTIONS = [\n \"answer_question\",\n \"approve_plan\",\n \"retry_build\",\n \"retry_import\",\n ];\n let nextId = 1;\n const pending = new Map();\n let applicationId = \"\";\n let appName = \"\";\n let commitId = \"\";\n let pendingAction = \"\";\n let editUrl = \"\";\n let previewUrl = \"\";\n let publishUrl = \"\";\n let canOpenLinks = false;\n let canCallTools = false;\n let publishing = false;\n let lastHeight = 0;\n let refreshInFlight = false;\n let refreshTimer = 0;\n let refreshGeneration = 0;\n let refreshAttempts = 0;\n let pollAfterMs = 2000;\n const MIN_POLL_MS = 2000;\n const MAX_REFRESH_ATTEMPTS = 40;\n\n function post(message) {\n window.parent.postMessage(message, \"*\");\n }\n\n function notify(method, params) {\n post({ jsonrpc: \"2.0\", method, params });\n }\n\n function request(method, params) {\n const id = nextId++;\n return new Promise((resolve, reject) => {\n pending.set(id, { resolve, reject });\n post({ jsonrpc: \"2.0\", id, method, params });\n });\n }\n\n function element(id) {\n return document.getElementById(id);\n }\n\n function show(id, on) {\n const node = element(id);\n if (node && node.classList) {\n node.classList.toggle(\"shown\", on);\n }\n }\n\n // Hosts size the card from this notification alone; without it the card\n // is laid out at zero height and never appears.\n function reportSize() {\n const height = Math.ceil(document.documentElement.scrollHeight || 0);\n if (height <= 0 || height === lastHeight) {\n return;\n }\n lastHeight = height;\n notify(\"ui/notifications/size-changed\", {\n height,\n width: Math.ceil(window.innerWidth || 0),\n });\n }\n\n function note(text) {\n element(\"note\").textContent = text;\n show(\"note\", Boolean(text));\n reportSize();\n }\n\n function isPlainHttp(url) {\n return url.slice(0, 5).toLowerCase() === \"http:\";\n }\n\n /** A UUID says nothing; the name the user asked Superblocks for does. */\n function renderIdentity() {\n element(\"appId\").textContent = appName || applicationId;\n }\n\n /**\n * Draws the screenshot the tool captured.\n *\n * Hosts that render an MCP App render it *instead of* the tool's content\n * blocks, so the image block get_app returns never reaches the user on\n * its own \u2014 the card has to take it out of the result and show it.\n */\n function showScreenshot(dataBase64, mimeType) {\n if (typeof dataBase64 !== \"string\" || !dataBase64) {\n return;\n }\n element(\"shot\").src =\n \"data:\" + (mimeType || \"image/jpeg\") + \";base64,\" + dataBase64;\n show(\"shot\", true);\n reportSize();\n }\n\n /** Applies every part of an MCP content array the card understands. */\n function applyContent(content) {\n for (const part of content || []) {\n if (!part) {\n continue;\n }\n if (part.type === \"text\" && typeof part.text === \"string\") {\n applyPayload(part.text);\n }\n if (part.type === \"image\") {\n showScreenshot(part.data, part.mimeType);\n }\n }\n }\n\n /**\n * True when publishing would deploy the empty starter template.\n * pendingAction is the server's own \"nothing to preview\" signal;\n * wait_for_build is the building exception. Status is only a fallback\n * when the payload omitted pendingAction. loading/waiting with no\n * preview fail closed so Publish is not clickable before get_app\n * returns.\n */\n function nothingToPublish() {\n if (previewUrl || publishUrl) {\n return false;\n }\n if (pendingAction === \"wait_for_build\") {\n return false;\n }\n if (BLOCKED_ACTIONS.indexOf(pendingAction) !== -1) {\n return true;\n }\n const badge = element(\"status\").textContent;\n if (!badge || badge === \"loading\" || badge === \"waiting\") {\n return true;\n }\n return UNBUILT_STATUSES.indexOf(badge) !== -1;\n }\n\n /**\n * Keep URLs in memory for openLink \u2014 never print them (preview JWTs are\n * huge and ugly in the card).\n */\n function renderActions() {\n element(\"openEditor\").disabled = !editUrl || !canOpenLinks;\n element(\"openPreview\").disabled = !previewUrl || !canOpenLinks;\n // Once the app is live, publishing again is not what anyone wants from\n // this button \u2014 going to the live app is.\n element(\"publishApp\").textContent = publishUrl\n ? \"Open published app\"\n : \"Publish app\";\n element(\"publishApp\").disabled = publishUrl\n ? !canOpenLinks\n : !applicationId ||\n !canCallTools ||\n publishing ||\n nothingToPublish();\n // Only warn about what is actually broken. Hosts that do open links\n // handle local http fine; if one refuses, refused() says so then.\n if (!canOpenLinks && (editUrl || previewUrl) && !publishUrl) {\n note(\"This host cannot open links for me \u2014 ask the model for an https preview URL.\");\n }\n reportSize();\n }\n\n /** Only ever ask the host to open a real web address. */\n function webUrl(candidate) {\n try {\n const parsed = new URL(candidate);\n return parsed.protocol === \"http:\" || parsed.protocol === \"https:\"\n ? candidate\n : \"\";\n } catch {\n return \"\";\n }\n }\n\n /**\n * Merges whatever the host sent. Hosts replay tool input as well as tool\n * results, and the input carries no status or URLs \u2014 overwriting from a\n * partial payload is what showed the card as \"unknown\".\n *\n * Hosts also disagree on the shape: some pass the capability JSON, some\n * pass the MCP content/text envelope (Claude Desktop on initialize), and\n * some nest that under structuredContent.\n */\n function applyPayload(raw) {\n let data = raw;\n if (typeof raw === \"string\") {\n try {\n data = JSON.parse(raw);\n } catch {\n return;\n }\n }\n if (!data || typeof data !== \"object\") {\n return;\n }\n // MCP tool-result / initialize toolResult envelope.\n if (Array.isArray(data.content)) {\n applyContent(data.content);\n if (data.structuredContent) {\n applyPayload(data.structuredContent);\n }\n return;\n }\n if (data.result && typeof data.result === \"object\") {\n applyPayload(data.result);\n return;\n }\n const value = data.kind === \"ok\" ? data.value : data;\n if (!value || typeof value !== \"object\") {\n return;\n }\n if (typeof value.status === \"string\") {\n element(\"status\").textContent = value.status;\n }\n if (typeof value.applicationId === \"string\") {\n applicationId = value.applicationId;\n renderIdentity();\n }\n if (typeof value.name === \"string\" && value.name) {\n appName = value.name;\n renderIdentity();\n }\n if (typeof value.commitId === \"string\") {\n commitId = value.commitId;\n }\n if (typeof value.pendingAction === \"string\") {\n pendingAction = value.pendingAction;\n } else if (typeof value.status === \"string\") {\n pendingAction = \"\";\n }\n if (typeof value.screenshotBase64 === \"string\") {\n showScreenshot(value.screenshotBase64, \"image/jpeg\");\n }\n if (typeof value.editUrl === \"string\") {\n editUrl = webUrl(value.editUrl);\n }\n if (typeof value.previewUrl === \"string\") {\n previewUrl = webUrl(value.previewUrl);\n }\n if (typeof value.publishUrl === \"string\") {\n publishUrl = webUrl(value.publishUrl);\n }\n if (typeof value.nextPollAfterMs === \"number\") {\n pollAfterMs = value.nextPollAfterMs;\n }\n // Hosts that deliver URLs without a status left the badge on the HTML\n // default (\"loading\") even after the app was built.\n const badge = element(\"status\").textContent;\n if (\n !value.status &&\n editUrl &&\n (badge === \"\" || badge === \"loading\" || badge === \"waiting\")\n ) {\n element(\"status\").textContent = previewUrl ? \"ready\" : \"building\";\n }\n renderActions();\n }\n\n /**\n * Re-ask get_app when the host gave us no result, or while status is\n * still building. wait:false and ensurePreview:false so polls only\n * ask for status. Honor nextPollAfterMs; 0 means stop.\n */\n function clearRefreshTimer() {\n if (refreshTimer) {\n clearTimeout(refreshTimer);\n refreshTimer = 0;\n }\n }\n\n function retryDelay() {\n return Math.max(MIN_POLL_MS, pollAfterMs || MIN_POLL_MS);\n }\n\n function scheduleRefresh(delayMs) {\n clearRefreshTimer();\n if (refreshAttempts >= MAX_REFRESH_ATTEMPTS) {\n note(\"Stopped checking whether the app is still building.\");\n return;\n }\n refreshTimer = setTimeout(() => {\n refreshTimer = 0;\n refreshFromServer();\n }, delayMs);\n }\n\n function refreshFromServer() {\n clearRefreshTimer();\n if (!canCallTools || !applicationId || refreshInFlight) {\n return;\n }\n if (typeof document.hidden === \"boolean\" && document.hidden) {\n scheduleRefresh(retryDelay());\n return;\n }\n const badge = element(\"status\").textContent;\n if (editUrl && badge !== \"building\") {\n return;\n }\n if (refreshAttempts >= MAX_REFRESH_ATTEMPTS) {\n note(\"Stopped checking whether the app is still building.\");\n return;\n }\n refreshAttempts += 1;\n const generation = refreshGeneration;\n refreshInFlight = true;\n request(\"tools/call\", {\n name: \"get_app\",\n arguments: {\n applicationId,\n ensurePreview: false,\n wait: false,\n },\n })\n .then((result) => {\n refreshInFlight = false;\n if (generation !== refreshGeneration) {\n if (element(\"status\").textContent === \"building\") {\n scheduleRefresh(retryDelay());\n }\n return;\n }\n if (!result || result.isError) {\n scheduleRefresh(retryDelay());\n return;\n }\n applyPayload(result);\n if (result.structuredContent) {\n applyPayload(result.structuredContent);\n }\n if (element(\"status\").textContent !== \"building\") {\n return;\n }\n if (pollAfterMs === 0) {\n return;\n }\n scheduleRefresh(retryDelay());\n })\n .catch(() => {\n refreshInFlight = false;\n if (generation !== refreshGeneration) {\n return;\n }\n scheduleRefresh(retryDelay());\n });\n }\n\n function applyHostContext(context) {\n if (!context || typeof context !== \"object\") {\n return;\n }\n const variables = context.styles && context.styles.variables;\n const style = document.documentElement.style;\n if (variables && style && typeof style.setProperty === \"function\") {\n for (const name of Object.keys(variables)) {\n const value = variables[name];\n if (typeof value === \"string\") {\n style.setProperty(name, value);\n }\n }\n }\n reportSize();\n }\n\n function refused(url) {\n note(\n isPlainHttp(url)\n ? \"This host only opens https links, and this app is served over http \u2014 ask for an https preview URL.\"\n : \"The host could not open the link \u2014 try again or ask the model for another URL.\",\n );\n }\n\n function openLink(url) {\n if (!url || !canOpenLinks) {\n return;\n }\n request(\"ui/open-link\", { url })\n .then((result) => {\n if (result && result.isError) {\n refused(url);\n return;\n }\n note(\"\");\n })\n .catch(() => refused(url));\n }\n\n /**\n * Asks the host to proxy publish_app back to this MCP server. The prompt\n * is the commit message createCommit needs; the card supplies a fixed one\n * so the user does not have to type through the model.\n */\n function publish() {\n if (!applicationId || !canCallTools || publishing) {\n return;\n }\n if (nothingToPublish()) {\n note(\"Nothing to publish yet: this turn did not build the app.\");\n return;\n }\n publishing = true;\n renderActions();\n note(\"Publishing\u2026\");\n const args = {\n applicationId,\n idempotencyKey:\n \"mcp-app-publish:\" + applicationId + \":\" + Date.now(),\n prompt: \"Published from Gateway status card\",\n };\n if (commitId) {\n args.commitId = commitId;\n }\n request(\"tools/call\", { name: \"publish_app\", arguments: args })\n .then((result) => {\n publishing = false;\n if (!result || result.isError) {\n const text =\n result &&\n Array.isArray(result.content) &&\n result.content[0] &&\n result.content[0].text\n ? String(result.content[0].text)\n : \"Publish failed.\";\n note(text.slice(0, 280));\n renderActions();\n return;\n }\n applyContent(result.content || []);\n if (result.structuredContent) {\n applyPayload(result.structuredContent);\n }\n note(\n publishUrl\n ? \"Published \u2014 open the live app with Open published app.\"\n : \"Published \u2014 the app is live.\",\n );\n renderActions();\n })\n .catch((error) => {\n publishing = false;\n note(\n (error && error.message) ||\n \"The host could not call publish_app.\",\n );\n renderActions();\n });\n }\n\n function handleHostMessage(event) {\n // App documents are opaque-origin, so the host window is the only\n // identity available to authenticate a message against.\n if (event.source !== window.parent) {\n return;\n }\n const data = event.data;\n if (!data || typeof data !== \"object\") {\n return;\n }\n if (data.method === \"ping\") {\n post({ jsonrpc: \"2.0\", id: data.id, result: {} });\n return;\n }\n if (data.id != null && pending.has(data.id)) {\n const waiter = pending.get(data.id);\n pending.delete(data.id);\n if (data.error) {\n waiter.reject(data.error);\n } else {\n waiter.resolve(data.result);\n }\n return;\n }\n const method = data.method;\n const params = data.params || {};\n if (\n method === \"ui/notifications/tool-result\" ||\n method === \"ui/tool-result\" ||\n method === \"tools/call\"\n ) {\n applyContent(params.content || params.result?.content || []);\n if (params.structuredContent) {\n applyPayload(params.structuredContent);\n }\n refreshGeneration += 1;\n if (element(\"status\").textContent === \"building\") {\n refreshFromServer();\n }\n }\n if (method === \"ui/notifications/tool-input\" && params.arguments) {\n applyPayload(params.arguments);\n refreshFromServer();\n }\n if (method === \"ui/notifications/host-context-changed\") {\n applyHostContext(params);\n }\n }\n\n window.addEventListener(\"message\", handleHostMessage);\n\n element(\"openEditor\").addEventListener(\"click\", () => openLink(editUrl));\n element(\"openPreview\").addEventListener(\"click\", () =>\n openLink(previewUrl),\n );\n element(\"publishApp\").addEventListener(\"click\", () => {\n if (publishUrl) {\n openLink(publishUrl);\n return;\n }\n publish();\n });\n\n if (typeof ResizeObserver === \"function\") {\n new ResizeObserver(reportSize).observe(document.documentElement);\n }\n\n void request(\"ui/initialize\", {\n appCapabilities: {\n availableDisplayModes: [\"inline\"],\n },\n appInfo: { name: \"gateway-app-status\", version: \"0.0.6\" },\n protocolVersion: PROTOCOL_VERSION,\n })\n .then((result) => {\n // Hosts hold back tool results until the app confirms it is ready.\n notify(\"ui/notifications/initialized\", {});\n // Buttons that cannot work are worse than no buttons: hosts without\n // openLinks silently drop ui/open-link.\n canOpenLinks = Boolean(\n result && result.hostCapabilities && result.hostCapabilities.openLinks,\n );\n canCallTools = Boolean(\n result &&\n result.hostCapabilities &&\n result.hostCapabilities.serverTools,\n );\n applyHostContext(result && result.hostContext);\n renderActions();\n if (result && result.toolResult) {\n applyPayload(result.toolResult);\n }\n refreshFromServer();\n })\n .catch(() => {\n // Hosts that push tool results via notification still work.\n })\n .finally(reportSize);\n })();\n </script>\n</body>\n</html>\n";
10
+ export declare const APP_STATUS_RESOURCE_URI = "ui://gateway/app-status-v37.html";
11
+ export declare const APP_STATUS_HTML = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Superblocks app</title>\n <style>\n .head {\n display: flex;\n min-width: 0;\n align-items: center;\n gap: 8px;\n }\n h1 {\n flex: 1;\n margin: 0;\n font-size: var(--font-text-md-size, 14px);\n font-weight: var(--font-weight-semibold, 600);\n }\n .status {\n padding: 2px 8px;\n border: var(--border-width-regular, 1px) solid var(--sb-app-border);\n border-radius: var(--border-radius-full, 999px);\n background: var(--sb-app-background-subtle);\n color: var(--sb-app-text-secondary);\n font-size: var(--font-text-xs-size, 12px);\n text-transform: lowercase;\n }\n .status[data-tone=\"info\"] {\n border-color: var(--sb-app-info-border);\n background: var(--sb-app-info-background);\n color: var(--sb-app-info-text);\n }\n .status[data-tone=\"success\"] {\n border-color: var(--sb-app-success-border);\n background: var(--sb-app-success-background);\n color: var(--sb-app-success-text);\n }\n .status[data-tone=\"warning\"] {\n border-color: var(--sb-app-warning-border);\n background: var(--sb-app-warning-background);\n color: var(--sb-app-warning-text);\n }\n .status[data-tone=\"danger\"] {\n border-color: var(--sb-app-danger-border);\n background: var(--sb-app-danger-background);\n color: var(--sb-app-danger-text);\n }\n .meta {\n color: var(--sb-app-text-tertiary);\n font-size: var(--font-text-xs-size, 12px);\n }\n .note {\n color: var(--sb-app-warning-text);\n font-size: var(--font-text-xs-size, 12px);\n }\n .shot {\n display: none;\n max-width: 100%;\n width: 100%;\n border: var(--border-width-regular, 1px) solid var(--sb-app-border);\n border-radius: var(--border-radius-md, 8px);\n }\n .shot.shown {\n display: block;\n }\n .actions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n }\n @media (max-width: 360px) {\n .head {\n align-items: flex-start;\n flex-direction: column;\n }\n }\n\n :root {\n color-scheme: light dark;\n --sb-app-background: var(\n --color-background-primary,\n light-dark(#ffffff, #1b1c1f)\n );\n --sb-app-background-subtle: var(\n --color-background-secondary,\n light-dark(#f9fafb, #24272b)\n );\n --sb-app-background-hover: var(\n --color-background-tertiary,\n light-dark(#f3f4f6, #2f3437)\n );\n --sb-app-background-inverse: var(\n --color-background-inverse,\n light-dark(#121517, #f9fafb)\n );\n --sb-app-text: var(\n --color-text-primary,\n light-dark(#121517, #f9fafb)\n );\n --sb-app-text-secondary: var(\n --color-text-secondary,\n light-dark(#5a6272, #c6cad2)\n );\n --sb-app-text-tertiary: var(\n --color-text-tertiary,\n light-dark(#6b7280, #a4aab7)\n );\n --sb-app-text-inverse: var(\n --color-text-inverse,\n light-dark(#ffffff, #121517)\n );\n --sb-app-border: var(\n --color-border-primary,\n light-dark(#e8eaed, #454d5f)\n );\n --sb-app-ring: var(\n --color-ring-primary,\n light-dark(#0077b6, #27bbff)\n );\n --sb-app-info-background: var(\n --color-background-info,\n light-dark(#e6f5ff, #083a50)\n );\n --sb-app-info-text: var(\n --color-text-info,\n light-dark(#00679e, #7dd3fc)\n );\n --sb-app-info-border: var(\n --color-border-info,\n light-dark(#c2e7ff, #075985)\n );\n --sb-app-success-background: var(\n --color-background-success,\n light-dark(#e8f8ef, #0a3926)\n );\n --sb-app-success-text: var(\n --color-text-success,\n light-dark(#087a43, #6ee7b7)\n );\n --sb-app-success-border: var(\n --color-border-success,\n light-dark(#b8e8cf, #087a43)\n );\n --sb-app-warning-background: var(\n --color-background-warning,\n light-dark(#fff7e6, #49350a)\n );\n --sb-app-warning-text: var(\n --color-text-warning,\n light-dark(#946200, #fcd34d)\n );\n --sb-app-warning-border: var(\n --color-border-warning,\n light-dark(#f5d996, #946200)\n );\n --sb-app-danger-background: var(\n --color-background-danger,\n light-dark(#fff1f1, #4a1d1d)\n );\n --sb-app-danger-text: var(\n --color-text-danger,\n light-dark(#c54141, #fca5a5)\n );\n --sb-app-danger-border: var(\n --color-border-danger,\n light-dark(#ffcaca, #c54141)\n );\n }\n * {\n box-sizing: border-box;\n }\n body {\n min-width: 0;\n margin: 0;\n overflow-x: hidden;\n background: transparent;\n color: var(--sb-app-text);\n font-family: var(--font-sans, system-ui, -apple-system, sans-serif);\n font-size: var(--font-text-sm-size, 13px);\n line-height: var(--font-text-sm-line-height, 1.45);\n }\n .card {\n display: flex;\n min-width: 0;\n flex-direction: column;\n gap: 12px;\n padding: 16px;\n border: var(--border-width-regular, 1px) solid var(--sb-app-border);\n border-radius: var(--border-radius-lg, 12px);\n background: var(--sb-app-background);\n box-shadow: var(--shadow-sm, 0 1px 2px rgba(18, 21, 23, 0.08));\n }\n h1,\n .meta,\n .note {\n min-width: 0;\n overflow-wrap: anywhere;\n }\n .note:empty {\n position: absolute;\n }\n button,\n textarea {\n font: inherit;\n }\n button {\n appearance: none;\n min-width: 0;\n padding: 8px 12px;\n border: var(--border-width-regular, 1px) solid var(--sb-app-border);\n border-radius: var(--border-radius-md, 8px);\n background: var(--sb-app-background-subtle);\n color: var(--sb-app-text);\n font-weight: var(--font-weight-medium, 500);\n line-height: var(--font-text-sm-line-height, 1.45);\n cursor: pointer;\n }\n button:hover:not(:disabled) {\n background: var(--sb-app-background-hover);\n }\n .button-primary {\n border-color: var(--sb-app-background-inverse);\n background: var(--sb-app-background-inverse);\n color: var(--sb-app-text-inverse);\n }\n .button-primary:hover:not(:disabled) {\n border-color: var(--sb-app-background-inverse);\n background: var(--sb-app-background-inverse);\n }\n button:focus-visible,\n textarea:focus-visible,\n a:focus-visible {\n outline: 2px solid var(--sb-app-ring);\n outline-offset: 2px;\n }\n button:disabled {\n opacity: 0.48;\n cursor: not-allowed;\n }\n .actions {\n min-width: 0;\n }\n .actions > button {\n overflow-wrap: anywhere;\n }\n @media (max-width: 360px) {\n .actions {\n flex-direction: column;\n flex-wrap: nowrap;\n }\n .actions > button {\n width: 100%;\n }\n }\n\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"head\">\n <h1>Superblocks app</h1>\n <span id=\"status\" class=\"status\" data-tone=\"info\" aria-live=\"polite\">loading</span>\n </div>\n <div id=\"appId\" class=\"meta\"></div>\n <img id=\"shot\" class=\"shot\" alt=\"Preview of the running app\" />\n <div id=\"note\" class=\"note\" aria-live=\"polite\"></div>\n <div class=\"actions\">\n <button id=\"openEditor\" class=\"button-secondary\" type=\"button\" disabled>Open editor</button>\n <button id=\"openPreview\" class=\"button-secondary\" type=\"button\" disabled>Open preview</button>\n <button id=\"publishApp\" class=\"button-primary\" type=\"button\" disabled>Publish app</button>\n </div>\n </div>\n <script>\n (() => {\n const PROTOCOL_VERSION = \"2026-01-26\";\n // Statuses with no usable build to publish. \"building\" is deliberately\n // absent because a stale badge should not strand the button.\n const UNBUILT_STATUSES = [\n \"cancelled\",\n \"checkpoint_failed\",\n \"detached\",\n \"failed\",\n \"live_edit_terminated\",\n \"needs_decision\",\n \"no_changes\",\n \"timeout\",\n ];\n const BLOCKED_ACTIONS = [\n \"answer_question\",\n \"approve_plan\",\n \"open_editor\",\n \"retry_build\",\n ];\n const STATUS_TONES = {\n building: \"info\",\n cancelled: \"warning\",\n checkpoint_failed: \"danger\",\n deployed: \"success\",\n detached: \"warning\",\n failed: \"danger\",\n live_edit_terminated: \"danger\",\n loading: \"info\",\n needs_decision: \"warning\",\n no_changes: \"warning\",\n publish_failed: \"danger\",\n publishing: \"info\",\n ready: \"success\",\n timeout: \"danger\",\n waiting: \"info\",\n };\n let nextId = 1;\n const pending = new Map();\n let applicationId = \"\";\n let appName = \"\";\n let branch = \"\";\n let commitId = \"\";\n let directoryHash = \"\";\n let pendingAction = \"\";\n let editUrl = \"\";\n let previewUrl = \"\";\n let publishUrl = \"\";\n let canOpenLinks = false;\n let canCallTools = false;\n let publishing = false;\n let teardownRequested = false;\n let lastHeight = 0;\n let buildWatchStartedAtMs;\n let refreshInFlightGeneration = -1;\n let refreshTimer = 0;\n let refreshGeneration = 0;\n const BUILD_WATCH_MS = 20 * 60_000;\n const POLL_INTERVAL_MS = 2000;\n\n function post(message) {\n window.parent.postMessage(message, \"*\");\n }\n\n function notify(method, params) {\n post({ jsonrpc: \"2.0\", method, params });\n }\n\n function request(method, params) {\n const id = nextId++;\n return new Promise((resolve, reject) => {\n pending.set(id, { resolve, reject });\n post({ jsonrpc: \"2.0\", id, method, params });\n });\n }\n\n function element(id) {\n return document.getElementById(id);\n }\n\n function show(id, on) {\n const node = element(id);\n if (node && node.classList) {\n node.classList.toggle(\"shown\", on);\n }\n }\n\n function renderStatus(status) {\n const badge = element(\"status\");\n badge.textContent = status;\n badge.setAttribute(\n \"data-tone\",\n Object.hasOwn(STATUS_TONES, status) ? STATUS_TONES[status] : \"neutral\",\n );\n }\n\n // Hosts size the card from this notification alone; without it the card\n // is laid out at zero height and never appears.\n function reportSize() {\n if (teardownRequested) {\n return;\n }\n const height = Math.ceil(document.documentElement.scrollHeight || 0);\n if (height <= 0 || height === lastHeight) {\n return;\n }\n lastHeight = height;\n notify(\"ui/notifications/size-changed\", {\n height,\n width: Math.ceil(window.innerWidth || 0),\n });\n }\n\n function note(text) {\n element(\"note\").textContent = text;\n show(\"note\", Boolean(text));\n reportSize();\n }\n\n function isPlainHttp(url) {\n return url.slice(0, 5).toLowerCase() === \"http:\";\n }\n\n /** A UUID says nothing; the name the user asked Superblocks for does. */\n function renderIdentity() {\n element(\"appId\").textContent = appName || applicationId;\n }\n\n /**\n * Draws the screenshot the tool captured.\n *\n * Hosts that render an MCP App render it *instead of* the tool's content\n * blocks, so the image block get_app returns never reaches the user on\n * its own \u2014 the card has to take it out of the result and show it.\n */\n function showScreenshot(dataBase64, mimeType) {\n if (typeof dataBase64 !== \"string\" || !dataBase64) {\n return;\n }\n element(\"shot\").src =\n \"data:\" + (mimeType || \"image/jpeg\") + \";base64,\" + dataBase64;\n show(\"shot\", true);\n reportSize();\n }\n\n /** Applies every part of an MCP content array the card understands. */\n function applyContent(content) {\n for (const part of content || []) {\n if (!part) {\n continue;\n }\n if (part.type === \"text\" && typeof part.text === \"string\") {\n applyPayload(part.text);\n }\n if (part.type === \"image\") {\n showScreenshot(part.data, part.mimeType);\n }\n }\n }\n\n /**\n * True when publishing would deploy the empty starter template.\n * pendingAction is the server's own \"nothing to preview\" signal;\n * wait_for_build is the building exception. Status is only a fallback\n * when the payload omitted pendingAction. loading/waiting with no\n * preview fail closed so Publish is not clickable before get_app\n * returns.\n */\n function nothingToPublish() {\n const badge = element(\"status\").textContent;\n if (UNBUILT_STATUSES.indexOf(badge) !== -1) {\n return true;\n }\n if (previewUrl || publishUrl) {\n return false;\n }\n if (pendingAction === \"wait_for_build\") {\n return false;\n }\n if (BLOCKED_ACTIONS.indexOf(pendingAction) !== -1) {\n return true;\n }\n if (!badge || badge === \"loading\" || badge === \"waiting\") {\n return true;\n }\n return false;\n }\n\n /**\n * Keep URLs in memory for openLink \u2014 never print them (preview JWTs are\n * huge and ugly in the card).\n */\n function renderActions() {\n const status = element(\"status\").textContent;\n const previewReady = status === \"ready\";\n const rollingOut = status === \"publishing\";\n const published = Boolean(publishUrl) && !rollingOut;\n element(\"openEditor\").disabled = !editUrl || !canOpenLinks;\n element(\"openPreview\").disabled =\n !previewReady || !previewUrl || !canOpenLinks;\n // Once the app is live, publishing again is not what anyone wants from\n // this button \u2014 going to the live app is.\n element(\"publishApp\").textContent = rollingOut\n ? \"Publishing...\"\n : published\n ? \"Open published app\"\n : \"Publish app\";\n element(\"publishApp\").disabled = rollingOut\n ? true\n : published\n ? !canOpenLinks\n : !applicationId ||\n !canCallTools ||\n publishing ||\n nothingToPublish();\n // Only warn about what is actually broken. Hosts that do open links\n // handle local http fine; if one refuses, refused() says so then.\n if (!canOpenLinks && (editUrl || previewUrl) && !publishUrl) {\n note(\"This host cannot open links for me \u2014 ask the model for an https preview URL.\");\n }\n reportSize();\n }\n\n /** Only ever ask the host to open a real web address. */\n function webUrl(candidate) {\n try {\n const parsed = new URL(candidate);\n return parsed.protocol === \"http:\" || parsed.protocol === \"https:\"\n ? candidate\n : \"\";\n } catch {\n return \"\";\n }\n }\n\n /**\n * Merges whatever the host sent. Hosts replay tool input as well as tool\n * results, and the input carries no status or URLs \u2014 overwriting from a\n * partial payload is what showed the card as \"unknown\".\n *\n * Hosts also disagree on the shape: some pass the capability JSON, some\n * pass the MCP content/text envelope (Claude Desktop on initialize), and\n * some nest that under structuredContent.\n */\n function applyPayload(raw) {\n let data = raw;\n if (typeof raw === \"string\") {\n try {\n data = JSON.parse(raw);\n } catch {\n return;\n }\n }\n if (!data || typeof data !== \"object\") {\n return;\n }\n // MCP tool-result / initialize toolResult envelope.\n if (Array.isArray(data.content)) {\n applyContent(data.content);\n if (data.structuredContent) {\n applyPayload(data.structuredContent);\n }\n return;\n }\n if (data.result && typeof data.result === \"object\") {\n applyPayload(data.result);\n return;\n }\n const value = data.kind === \"ok\" ? data.value : data;\n if (!value || typeof value !== \"object\") {\n return;\n }\n if (\n value.browserNavigation &&\n typeof value.browserNavigation === \"object\" &&\n value.browserNavigation.action === \"open_editor\"\n ) {\n if (!teardownRequested) {\n teardownRequested = true;\n refreshGeneration += 1;\n clearRefreshTimer();\n document.body.hidden = true;\n notify(\"ui/notifications/size-changed\", { height: 0, width: 0 });\n notify(\"ui/notifications/request-teardown\", {});\n }\n return;\n }\n if (teardownRequested) {\n return;\n }\n if (typeof value.status === \"string\") {\n if (value.status !== \"building\") {\n buildWatchStartedAtMs = undefined;\n }\n renderStatus(value.status);\n }\n if (typeof value.applicationId === \"string\") {\n applicationId = value.applicationId;\n renderIdentity();\n }\n if (typeof value.name === \"string\" && value.name) {\n appName = value.name;\n renderIdentity();\n }\n if (typeof value.branch === \"string\") {\n branch = value.branch;\n }\n if (typeof value.directoryHash === \"string\") {\n directoryHash = value.directoryHash;\n }\n if (\n typeof value.commitId === \"string\" ||\n typeof value.previewUrl === \"string\" ||\n (typeof value.applicationId === \"string\" &&\n typeof value.status === \"string\")\n ) {\n commitId =\n typeof value.commitId === \"string\" ? value.commitId : \"\";\n }\n if (typeof value.pendingAction === \"string\") {\n pendingAction = value.pendingAction;\n } else if (typeof value.status === \"string\") {\n pendingAction = \"\";\n }\n if (typeof value.screenshotBase64 === \"string\") {\n showScreenshot(value.screenshotBase64, \"image/jpeg\");\n }\n if (typeof value.editUrl === \"string\") {\n editUrl = webUrl(value.editUrl);\n }\n if (typeof value.previewUrl === \"string\") {\n previewUrl = webUrl(value.previewUrl);\n } else if (typeof value.status === \"string\" && !commitId) {\n previewUrl = \"\";\n }\n if (typeof value.publishUrl === \"string\") {\n publishUrl = webUrl(value.publishUrl);\n }\n // Hosts that deliver URLs without a status left the badge on the HTML\n // default (\"loading\") even after the app was built.\n const badge = element(\"status\").textContent;\n if (\n !value.status &&\n editUrl &&\n (badge === \"\" || badge === \"loading\" || badge === \"waiting\")\n ) {\n renderStatus(previewUrl ? \"ready\" : \"building\");\n }\n renderActions();\n if (\n canCallTools &&\n commitId &&\n element(\"status\").textContent === \"publishing\"\n ) {\n scheduleRefresh(retryDelay());\n }\n }\n\n /**\n * Ask the app-only status tool when the host gave us no result, or while\n * status is still building.\n */\n function clearRefreshTimer() {\n if (refreshTimer) {\n clearTimeout(refreshTimer);\n refreshTimer = 0;\n }\n }\n\n function retryDelay() {\n return POLL_INTERVAL_MS;\n }\n\n function scheduleRefresh(delayMs) {\n clearRefreshTimer();\n if (\n element(\"status\").textContent !== \"publishing\" &&\n buildWatchStartedAtMs !== undefined &&\n Date.now() - buildWatchStartedAtMs >= BUILD_WATCH_MS\n ) {\n note(\"Stopped checking whether the app is still building.\");\n return;\n }\n refreshTimer = setTimeout(() => {\n refreshTimer = 0;\n refreshFromServer();\n }, delayMs);\n }\n\n function refreshFromServer() {\n clearRefreshTimer();\n if (\n teardownRequested ||\n !canCallTools ||\n refreshInFlightGeneration === refreshGeneration ||\n publishing\n ) {\n return;\n }\n if (typeof document.hidden === \"boolean\" && document.hidden) {\n scheduleRefresh(retryDelay());\n return;\n }\n const badge = element(\"status\").textContent;\n const publishStatus = badge === \"publishing\";\n if (editUrl && badge !== \"building\" && !publishStatus) {\n buildWatchStartedAtMs = undefined;\n return;\n }\n if (!publishStatus) {\n if (badge === \"building\") {\n if (buildWatchStartedAtMs === undefined) {\n buildWatchStartedAtMs = Date.now();\n }\n } else {\n buildWatchStartedAtMs = undefined;\n }\n if (\n buildWatchStartedAtMs !== undefined &&\n Date.now() - buildWatchStartedAtMs >= BUILD_WATCH_MS\n ) {\n note(\"Stopped checking whether the app is still building.\");\n return;\n }\n }\n const generation = refreshGeneration;\n refreshInFlightGeneration = generation;\n const previewStatus = !publishStatus && Boolean(commitId && directoryHash);\n request(\"tools/call\", {\n name: publishStatus\n ? \"check_publish_progress\"\n : previewStatus\n ? \"get_preview_status\"\n : \"get_app_status\",\n arguments: {\n ...(applicationId ? { applicationId } : {}),\n ...(!publishStatus && branch ? { branch } : {}),\n ...(publishStatus && commitId ? { commitId } : {}),\n ...(previewStatus ? { commitId, directoryHash, wait: false } : {}),\n },\n })\n .then((result) => {\n if (refreshInFlightGeneration === generation) {\n refreshInFlightGeneration = -1;\n }\n if (generation !== refreshGeneration) {\n if (\n !publishing &&\n element(\"status\").textContent === \"building\" &&\n refreshInFlightGeneration !== refreshGeneration\n ) {\n scheduleRefresh(retryDelay());\n }\n return;\n }\n const publishError = publishStatus\n ? terminalPublishErrorOf(result)\n : \"\";\n if (publishError) {\n refreshGeneration += 1;\n clearRefreshTimer();\n publishUrl = \"\";\n renderStatus(\"publish_failed\");\n note(publishError);\n renderActions();\n return;\n }\n if (!result || result.isError) {\n scheduleRefresh(retryDelay());\n return;\n }\n applyPayload(result);\n if (result.structuredContent) {\n applyPayload(result.structuredContent);\n }\n const status = element(\"status\").textContent;\n if (status === \"deployed\") {\n note(\n publishUrl\n ? \"Published - open the live app with Open published app.\"\n : \"Published - the app is live.\",\n );\n return;\n }\n if (status === \"publishing\") {\n scheduleRefresh(retryDelay());\n return;\n }\n if (status !== \"building\") {\n return;\n }\n scheduleRefresh(retryDelay());\n })\n .catch(() => {\n if (refreshInFlightGeneration === generation) {\n refreshInFlightGeneration = -1;\n }\n if (generation !== refreshGeneration) {\n return;\n }\n scheduleRefresh(retryDelay());\n });\n }\n\n function applyHostContext(context) {\n if (!context || typeof context !== \"object\") {\n return;\n }\n const root = document.documentElement;\n if (context.theme === \"light\" || context.theme === \"dark\") {\n root.setAttribute(\"data-theme\", context.theme);\n root.style.colorScheme = context.theme;\n }\n const variables = context.styles && context.styles.variables;\n const style = root.style;\n if (variables && style && typeof style.setProperty === \"function\") {\n for (const name of Object.keys(variables)) {\n const value = variables[name];\n if (typeof value === \"string\") {\n style.setProperty(name, value);\n }\n }\n }\n const fonts = context.styles && context.styles.css?.fonts;\n if (typeof fonts === \"string\") {\n let fontStyle = document.getElementById(\"__mcp-host-fonts\");\n if (!fontStyle) {\n fontStyle = document.createElement(\"style\");\n fontStyle.id = \"__mcp-host-fonts\";\n document.head.appendChild(fontStyle);\n }\n fontStyle.textContent = fonts;\n }\n reportSize();\n }\n\n function capabilityFailureOf(result) {\n if (!result || !Array.isArray(result.content)) {\n return null;\n }\n for (const block of result.content) {\n if (!block || block.type !== \"text\" || !block.text) {\n continue;\n }\n try {\n const parsed = JSON.parse(block.text);\n if (parsed && parsed.kind === \"error\") {\n return {\n code: parsed.code || \"\",\n message: parsed.message || parsed.code || \"Tool call failed.\",\n };\n }\n } catch {\n continue;\n }\n }\n return null;\n }\n\n function capabilityErrorOf(result) {\n return capabilityFailureOf(result)?.message || \"\";\n }\n\n function terminalPublishErrorOf(result) {\n const failure = capabilityFailureOf(result);\n if (\n !failure ||\n ![\n \"publish_failed\",\n \"publish_needs_acknowledgement\",\n \"publish_timeout\",\n ].includes(failure.code)\n ) {\n return \"\";\n }\n return failure.message;\n }\n\n /** First text block of a failed tool result, for the note line. */\n function errorTextOf(result, fallback) {\n const capabilityError = capabilityErrorOf(result);\n if (capabilityError) {\n return capabilityError;\n }\n const first =\n result && Array.isArray(result.content) ? result.content[0] : null;\n return first && first.text ? String(first.text).slice(0, 280) : fallback;\n }\n\n function refused(url) {\n note(\n isPlainHttp(url)\n ? \"This host only opens https links, and this app is served over http \u2014 ask for an https preview URL.\"\n : \"The host could not open the link \u2014 try again or ask the model for another URL.\",\n );\n }\n\n function openLink(url) {\n if (!url || !canOpenLinks) {\n return;\n }\n request(\"ui/open-link\", { url })\n .then((result) => {\n if (result && result.isError) {\n refused(url);\n return;\n }\n note(\"\");\n })\n .catch(() => refused(url));\n }\n\n /**\n * Asks the host to proxy publish_app back to this MCP server. The prompt\n * is the commit message createCommit needs; the card supplies a fixed one\n * so the user does not have to type through the model.\n */\n function publish() {\n if (!applicationId || !canCallTools || publishing) {\n return;\n }\n if (nothingToPublish()) {\n note(\"Nothing to publish yet: this turn did not build the app.\");\n return;\n }\n publishing = true;\n refreshGeneration += 1;\n clearRefreshTimer();\n renderActions();\n note(\"Publishing\u2026\");\n const args = {\n applicationId,\n idempotencyKey:\n \"mcp-app-publish:\" + applicationId + \":\" + Date.now(),\n prompt: \"Published from Gateway status card\",\n };\n if (commitId) {\n args.commitId = commitId;\n }\n if (branch) {\n args.branch = branch;\n }\n request(\"tools/call\", { name: \"publish_app\", arguments: args })\n .then((result) => {\n publishing = false;\n const publishError = capabilityErrorOf(result);\n if (!result || result.isError || publishError) {\n note(errorTextOf(result, \"Publish failed.\"));\n renderActions();\n refreshFromServer();\n return;\n }\n applyContent(result.content || []);\n if (result.structuredContent) {\n applyPayload(result.structuredContent);\n }\n const status = element(\"status\").textContent;\n note(\n status === \"publishing\"\n ? \"Publish accepted; the deploy is still rolling out.\"\n : publishUrl\n ? \"Published - open the live app with Open published app.\"\n : \"Published - the app is live.\",\n );\n renderActions();\n })\n .catch((error) => {\n publishing = false;\n note(\n (error && error.message) ||\n \"The host could not call publish_app.\",\n );\n renderActions();\n refreshFromServer();\n });\n }\n\n function handleHostMessage(event) {\n // App documents are opaque-origin, so the host window is the only\n // identity available to authenticate a message against.\n if (event.source !== window.parent) {\n return;\n }\n const data = event.data;\n if (!data || typeof data !== \"object\") {\n return;\n }\n if (data.method === \"ping\") {\n post({ jsonrpc: \"2.0\", id: data.id, result: {} });\n return;\n }\n if (data.id != null && pending.has(data.id)) {\n const waiter = pending.get(data.id);\n pending.delete(data.id);\n if (data.error) {\n waiter.reject(data.error);\n } else {\n waiter.resolve(data.result);\n }\n return;\n }\n const method = data.method;\n const params = data.params || {};\n if (\n method === \"ui/notifications/tool-result\" ||\n method === \"ui/tool-result\" ||\n method === \"tools/call\"\n ) {\n applyContent(params.content || params.result?.content || []);\n if (params.structuredContent) {\n applyPayload(params.structuredContent);\n }\n refreshGeneration += 1;\n if (element(\"status\").textContent === \"building\") {\n refreshFromServer();\n }\n }\n if (method === \"ui/notifications/tool-input\" && params.arguments) {\n applyPayload(params.arguments);\n refreshFromServer();\n }\n if (method === \"ui/notifications/host-context-changed\") {\n applyHostContext(params);\n }\n }\n\n window.addEventListener(\"message\", handleHostMessage);\n\n element(\"openEditor\").addEventListener(\"click\", () => openLink(editUrl));\n element(\"openPreview\").addEventListener(\"click\", () =>\n openLink(previewUrl),\n );\n element(\"publishApp\").addEventListener(\"click\", () => {\n if (element(\"status\").textContent === \"publishing\") {\n return;\n }\n if (publishUrl) {\n openLink(publishUrl);\n return;\n }\n publish();\n });\n\n if (typeof ResizeObserver === \"function\") {\n new ResizeObserver(reportSize).observe(document.documentElement);\n }\n\n void request(\"ui/initialize\", {\n appCapabilities: {\n availableDisplayModes: [\"inline\"],\n },\n appInfo: { name: \"gateway-app-status\", version: \"0.0.8\" },\n protocolVersion: PROTOCOL_VERSION,\n })\n .then((result) => {\n // Hosts hold back tool results until the app confirms it is ready.\n notify(\"ui/notifications/initialized\", {});\n // Buttons that cannot work are worse than no buttons: hosts without\n // openLinks silently drop ui/open-link.\n canOpenLinks = Boolean(\n result && result.hostCapabilities && result.hostCapabilities.openLinks,\n );\n canCallTools = Boolean(\n result &&\n result.hostCapabilities &&\n result.hostCapabilities.serverTools,\n );\n if (result && result.toolResult) {\n applyPayload(result.toolResult);\n }\n if (teardownRequested) {\n return;\n }\n applyHostContext(result && result.hostContext);\n renderActions();\n const badge = element(\"status\").textContent;\n if (badge === \"publishing\") {\n return;\n }\n if (!applicationId && (!badge || badge === \"loading\")) {\n scheduleRefresh(500);\n } else {\n refreshFromServer();\n }\n })\n .catch(() => {\n // Hosts that push tool results via notification still work.\n })\n .finally(reportSize);\n })();\n </script>\n</body>\n</html>\n";