@pinagent/vite-plugin
v0.11.1
Published
Vite plugin for Pinagent — capture in-browser UI feedback with file:line and a screenshot, hand it to your coding agent over MCP.
Downloads
2,206
Readme
@pinagent/vite-plugin
Vite plugin (dev-only) that:
- Tags every element with
data-pa-loc="<relPath>:<line>:<col>"(and adata-pa-compcomponent name) — JSX opening elements via a Babel transform, Vue SFC<template>markup via@pinagent/vue-plugin, and Svelte component markup via@pinagent/svelte-plugin. Thetransformhook dispatches on extension, so React (.tsx/.jsx), Vue (.vue), and Svelte (.svelte) apps all work. - Injects a
<script src="/__pinagent/widget.js">into served HTML. - Serves middleware under
/__pinagent/*that writes captured feedback to.pinagent/feedback/.
Install
pnpm add -D @pinagent/vite-pluginUsage
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import pinagent from '@pinagent/vite-plugin';
export default defineConfig({
plugins: [pinagent(), react()],
});For a Vue app, put pinagent() ahead of @vitejs/plugin-vue — it runs with
enforce: 'pre', so it tags the raw SFC before plugin-vue compiles it:
// vite.config.ts
import vue from '@vitejs/plugin-vue';
import pinagent from '@pinagent/vite-plugin';
export default defineConfig({
plugins: [pinagent(), vue()],
});Svelte is the same shape — pinagent() ahead of @sveltejs/vite-plugin-svelte
so it tags the raw component before svelte compiles it:
// vite.config.ts
import { svelte } from '@sveltejs/vite-plugin-svelte';
import pinagent from '@pinagent/vite-plugin';
export default defineConfig({
plugins: [pinagent(), svelte()],
});The plugin is apply: 'serve' — it does nothing on vite build.
Endpoints
| Method | Path | Purpose |
| ------ | ------------------------------------- | -------------------------------------------------- |
| GET | /__pinagent/widget.js | Bundled IIFE (embedded at publish time). |
| POST | /__pinagent/feedback | Receive a comment + screenshot. Returns { id }. |
| GET | /__pinagent/feedback | List all feedback (shallow, no screenshot blob). |
| GET | /__pinagent/feedback/:id | Full record including base64 screenshot. |
| GET | /__pinagent/feedback/:id/messages | Full agent transcript for one conversation. |
| PATCH | /__pinagent/feedback/:id | Update status, note, commitSha. |
Files land in <project root>/.pinagent/. Make sure that path is git-ignored.
Transcript endpoint
GET /__pinagent/feedback/:id/messages returns the full persisted
agent transcript for one conversation — every AgentEvent that has
been appended to the bus, in insertion order. This is a non-streaming
HTTP read; for live updates, the dock uses a WebSocket subscription
instead. Intended for surfaces where a WebSocket is awkward (CLI,
export tooling, hosted dashboards) and as a cold-load prefetch the
dock fires alongside its WS subscribe so the detail view has content
before the socket connects.
Response shape:
{
"messages": [
{ "type": "init", "sessionId": "...", "model": "...", "permissionMode": "...", "apiKeySource": "..." },
{ "type": "text", "text": "..." },
{ "type": "tool_use", "name": "Edit", "summary": "src/Foo.tsx" },
{ "type": "tool_result", "ok": true }
]
}Event shapes are pinned by AgentEventSchema in @pinagent/shared.
init and result events are included (the transcript view wants
them); the internal __finished bus sentinel is excluded. Status
codes: 400 on a malformed id, 404 on an unknown conversation,
200 with { "messages": [] } for a fresh conversation that hasn't
published anything yet.
