* Handle SI UI resource request - serves MCP Apps shell with A2UI surface
(uri: string, sessionId: string)
| 2074 | * Handle SI UI resource request - serves MCP Apps shell with A2UI surface |
| 2075 | */ |
| 2076 | private async handleSiUiResource(uri: string, sessionId: string): Promise<{ |
| 2077 | contents: Array<{ uri: string; mimeType: string; text: string }>; |
| 2078 | }> { |
| 2079 | // Get the session to retrieve the latest A2UI surface |
| 2080 | const session = await siDb.getSession(sessionId); |
| 2081 | if (!session) { |
| 2082 | throw new Error(`SI session not found: ${sessionId}`); |
| 2083 | } |
| 2084 | |
| 2085 | // Get the most recent message with a surface |
| 2086 | const messages = await siDb.getSessionMessages(sessionId, 1); |
| 2087 | const latestMessage = messages[0]; |
| 2088 | |
| 2089 | // Build a surface from ui_elements if we don't have a native surface yet |
| 2090 | // This provides backwards compatibility during migration |
| 2091 | let surface = latestMessage?.ui_elements |
| 2092 | ? { |
| 2093 | surfaceId: `si-session-${sessionId}`, |
| 2094 | catalogId: "si-standard", |
| 2095 | components: (latestMessage.ui_elements as Array<{ type: string; data: Record<string, unknown> }>).map((el, idx) => ({ |
| 2096 | id: `elem-${idx}`, |
| 2097 | component: { [el.type]: el.data }, |
| 2098 | })), |
| 2099 | } |
| 2100 | : { |
| 2101 | surfaceId: `si-session-${sessionId}`, |
| 2102 | catalogId: "si-standard", |
| 2103 | components: [], |
| 2104 | }; |
| 2105 | |
| 2106 | // Read the shell template |
| 2107 | const shellPath = join(__dirname, "../public/si-apps/shell.html"); |
| 2108 | let shellHtml: string; |
| 2109 | try { |
| 2110 | shellHtml = await readFile(shellPath, "utf-8"); |
| 2111 | } catch { |
| 2112 | throw new Error("SI Apps shell template not found"); |
| 2113 | } |
| 2114 | |
| 2115 | // Inject the surface data into the shell |
| 2116 | const surfaceScript = `window.__SI_SURFACE__ = ${JSON.stringify(surface)};`; |
| 2117 | const injectedHtml = shellHtml.replace( |
| 2118 | /\/\/ This will be replaced by server-side injection[\s\S]*?\/\/ window\.__SI_SURFACE__ = .*$/m, |
| 2119 | surfaceScript |
| 2120 | ); |
| 2121 | |
| 2122 | return { |
| 2123 | contents: [ |
| 2124 | { |
| 2125 | uri, |
| 2126 | mimeType: "text/html", |
| 2127 | text: injectedHtml, |
| 2128 | }, |
| 2129 | ], |
| 2130 | }; |
| 2131 | } |
| 2132 | } |
| 2133 |
no test coverage detected