(args: z.infer<typeof PreviewArgs>, ctx: ToolContext)
| 178 | description = 'Render an artifact in a real browser: builds a self-contained preview page (React/Vue render via an in-browser harness, no build step) and starts a local static server. Returns a URL — follow with browser_navigate then browser_screenshot to SEE the result. Needs python3 for the static server.'; |
| 179 | argsSchema = PreviewArgs; |
| 180 | isReadOnly = false; |
| 181 | isDestructive = false; |
| 182 | |
| 183 | async execute(args: z.infer<typeof PreviewArgs>, ctx: ToolContext): Promise<ToolResult> { |
| 184 | let manifest, version, content, absFile; |
| 185 | try { |
| 186 | ({ manifest, version, content, absFile } = await getArtifact(ctx.cwd, resolveArtifactId(args), args.version)); |
| 187 | } catch (e: any) { |
| 188 | return { content: e?.message ?? String(e), isError: true }; |
| 189 | } |
| 190 | |
| 191 | // Build + write the preview page next to the artifact's version file. |
| 192 | const html = buildPreviewHtml(manifest.type, content); |
| 193 | const versionDir = path.dirname(absFile); |
| 194 | const previewPath = path.join(versionDir, PREVIEW_FILE); |
| 195 | await ctx.transaction.write(previewPath, html); |
| 196 | |
| 197 | const port = previewPort(manifest.id); |
| 198 | const name = previewServerName(manifest.id); |
| 199 | const url = `http://localhost:${port}/${PREVIEW_FILE}`; |
| 200 | |
| 201 | // Serve the version dir statically. python3 is near-universal on macOS/Linux and needs |
| 202 | // no project deps. If it isn't available, hand back the page path + a manual fallback. |
| 203 | try { |
| 204 | await processRegistry.start({ |
| 205 | name, |
| 206 | command: `python3 -m http.server ${port} --bind 127.0.0.1 --directory ${JSON.stringify(versionDir)}`, |
| 207 | cwd: versionDir, |
| 208 | replace: true, |
| 209 | }); |
| 210 | } catch (e: any) { |
| 211 | return { |
| 212 | content: |
| 213 | `Preview page written to ${previewPath}, but the static server could not start ` + |
| 214 | `(${e?.message ?? e}). Serve it yourself, e.g.:\n` + |
| 215 | ` dev_server_start name="${name}" command="python3 -m http.server ${port}" cwd="${versionDir}"\n` + |
| 216 | `then browser_navigate ${url} and browser_screenshot.`, |
| 217 | metadata: { artifactId: manifest.id, version, previewPath, url, served: false }, |
| 218 | }; |
| 219 | } |
| 220 | |
| 221 | ctx.emit({ type: 'progress', message: `Serving artifact "${manifest.id}" v${version} at ${url}` }); |
| 222 | return { |
| 223 | content: |
| 224 | `Preview of "${manifest.id}" v${version} (${manifest.type}) is live at ${url}\n` + |
| 225 | `Next: browser_navigate to that URL, then browser_screenshot to see how it rendered. ` + |
| 226 | `Stop the server later with dev_server_stop name="${name}".`, |
| 227 | metadata: { artifactId: manifest.id, version, type: manifest.type, url, server: name, served: true }, |
| 228 | }; |
| 229 | } |
nothing calls this directly
no test coverage detected