@jami-studio/pinpoint 0.1.12

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 (47) hide show
  1. package/.agents/skills/pinpoint/SKILL.md +77 -0
  2. package/README.md +412 -0
  3. package/dist/agent-context-HBCZ4MBN.js +13 -0
  4. package/dist/agent-context-HBCZ4MBN.js.map +1 -0
  5. package/dist/chunk-B7TY4FPP.js +569 -0
  6. package/dist/chunk-B7TY4FPP.js.map +1 -0
  7. package/dist/chunk-CGJZ7BOM.js +88 -0
  8. package/dist/chunk-CGJZ7BOM.js.map +1 -0
  9. package/dist/chunk-DGUM43GV.js +11 -0
  10. package/dist/chunk-DGUM43GV.js.map +1 -0
  11. package/dist/chunk-HAEYE6KB.js +25 -0
  12. package/dist/chunk-HAEYE6KB.js.map +1 -0
  13. package/dist/chunk-J5PXKVTM.js +53 -0
  14. package/dist/chunk-J5PXKVTM.js.map +1 -0
  15. package/dist/chunk-XBX2J7WU.js +94 -0
  16. package/dist/chunk-XBX2J7WU.js.map +1 -0
  17. package/dist/chunk-ZW7IO3EW.js +4927 -0
  18. package/dist/chunk-ZW7IO3EW.js.map +1 -0
  19. package/dist/cli.js +71 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/formatter-CR4COA5Z.js +8 -0
  22. package/dist/formatter-CR4COA5Z.js.map +1 -0
  23. package/dist/index-NvFcZ4SO.d.ts +200 -0
  24. package/dist/index.browser.d.ts +377 -0
  25. package/dist/index.browser.js +620 -0
  26. package/dist/index.browser.js.map +1 -0
  27. package/dist/index.js +936 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/open-file-WR2JHI4P.js +8 -0
  30. package/dist/open-file-WR2JHI4P.js.map +1 -0
  31. package/dist/primitives/index.js +28 -0
  32. package/dist/primitives/index.js.map +1 -0
  33. package/dist/react.d.ts +23 -0
  34. package/dist/react.js +20 -0
  35. package/dist/react.js.map +1 -0
  36. package/dist/server/index.js +457 -0
  37. package/dist/server/index.js.map +1 -0
  38. package/dist/types/index.js +1 -0
  39. package/dist/types/index.js.map +1 -0
  40. package/package.json +88 -0
  41. package/src/scripts/create-pin.ts +43 -0
  42. package/src/scripts/delete-pin.ts +16 -0
  43. package/src/scripts/get-pins.ts +36 -0
  44. package/src/scripts/list-sessions.ts +33 -0
  45. package/src/scripts/resolve-pin.ts +27 -0
  46. package/src/scripts/run.ts +8 -0
  47. package/src/scripts/update-pin.ts +32 -0
@@ -0,0 +1,77 @@
1
+ # Pinpoint — Visual Feedback Tool
2
+
3
+ You are an agent with access to Pinpoint, a visual feedback and annotation tool. Users annotate UI elements on web pages and send structured feedback to you.
4
+
5
+ ## Reading Annotations
6
+
7
+ Pins are stored as JSON files in `data/pins/{uuid}.json`:
8
+
9
+ ```json
10
+ {
11
+ "id": "uuid",
12
+ "pageUrl": "/dashboard",
13
+ "comment": "This button color is wrong",
14
+ "element": {
15
+ "tagName": "button",
16
+ "selector": ".sidebar button.primary",
17
+ "classNames": ["primary", "btn"]
18
+ },
19
+ "framework": {
20
+ "framework": "react",
21
+ "componentPath": "<Sidebar> <ActionButton>",
22
+ "sourceFile": "src/components/Sidebar.tsx:42"
23
+ },
24
+ "status": { "state": "open", "changedBy": "user" }
25
+ }
26
+ ```
27
+
28
+ **Key fields:**
29
+ - `sourceFile` — exact file and line number to edit
30
+ - `componentPath` — React/Vue component hierarchy
31
+ - `selector` — CSS selector for the DOM element
32
+ - `comment` — what the user wants changed
33
+
34
+ ## Actions
35
+
36
+ Run with `pnpm action <name>`:
37
+
38
+ | Action | Purpose | Key Args |
39
+ |--------|---------|----------|
40
+ | `get-pins` | List pins | `--pageUrl`, `--status` |
41
+ | `create-pin` | Create a pin | `--pageUrl`, `--selector`, `--comment` |
42
+ | `resolve-pin` | Mark as resolved | `--id`, `--message` |
43
+ | `update-pin` | Update a pin | `--id`, `--comment`, `--status` |
44
+ | `delete-pin` | Remove a pin | `--id` |
45
+ | `list-sessions` | List pages with pins | (none) |
46
+
47
+ ## Workflow
48
+
49
+ 1. User annotates elements in the browser
50
+ 2. Read pins: `pnpm action get-pins --status open`
51
+ 3. Use `sourceFile` to locate the code and make the requested changes
52
+ 4. Mark resolved: `pnpm action resolve-pin --id <uuid>`
53
+
54
+ ## Tips
55
+
56
+ - Always check `sourceFile` first — it points directly to the code to edit
57
+ - Use `get-pins --status open` to see only unresolved pins
58
+ - Resolve pins after fixing them so the user gets visual confirmation
59
+ - The `componentPath` helps you understand the component hierarchy when `sourceFile` is not available
60
+ - Multiple pins on the same page often relate to each other — read them all before starting fixes
61
+
62
+ ## Adding Pinpoint to a New App
63
+
64
+ If the repository does not have Pinpoint set up:
65
+
66
+ 1. `pnpm add @agent-native/pinpoint`
67
+ 2. `npx @agent-native/pinpoint init` — copies scripts and skill to your project
68
+ 3. Add `<Pinpoint />` component to the root React component:
69
+ ```tsx
70
+ import { Pinpoint } from "@agent-native/pinpoint/react";
71
+ <Pinpoint author="User" endpoint="/api/pins" autoSubmit />
72
+ ```
73
+ 4. Add server middleware in the Express setup:
74
+ ```ts
75
+ import { pagePinRoutes } from "@agent-native/pinpoint/server";
76
+ app.use("/api/pins", pagePinRoutes());
77
+ ```
package/README.md ADDED
@@ -0,0 +1,412 @@
1
+ # @agent-native/pinpoint
2
+
3
+ Visual feedback and annotation tool for web applications. Users select UI elements, add feedback, and send structured context to any AI agent.
4
+
5
+ Works standalone, with [Jami Studio](https://builder.io), or with any agent runtime that speaks the agent-native protocol (Jami Studio, Claude Code, Codex, Gemini CLI, Cursor, etc.).
6
+
7
+ ## AI Agent Setup Guide
8
+
9
+ Instructions for an AI agent (Jami Studio, Claude Code, Codex, Cursor, etc.) to add Pinpoint to an agent-native repository.
10
+
11
+ ### Step 1: Install
12
+
13
+ ```sh
14
+ pnpm add @agent-native/pinpoint
15
+ ```
16
+
17
+ ### Step 2: Initialize agent actions and skill
18
+
19
+ ```sh
20
+ npx @agent-native/pinpoint@latest init
21
+ ```
22
+
23
+ This copies agent actions to `actions/` and the Pinpoint skill to `.agents/skills/pinpoint/`. No manual file copying needed.
24
+
25
+ ### Step 3: Mount the client overlay
26
+
27
+ Find the root React component (typically `app/App.tsx` or `src/App.tsx`). Add the `<Pinpoint />` component:
28
+
29
+ ```tsx
30
+ import { Pinpoint } from "@agent-native/pinpoint/react";
31
+
32
+ // Add as a sibling to your app root — renders nothing, mounts overlay in Shadow DOM
33
+ <Pinpoint author="User" endpoint="/api/pins" autoSubmit colorScheme="auto" />;
34
+ ```
35
+
36
+ If the app is not React-based, use the imperative API:
37
+
38
+ ```ts
39
+ import { mountPinpoint } from "@agent-native/pinpoint";
40
+ mountPinpoint({ author: "User", endpoint: "/api/pins", autoSubmit: true });
41
+ ```
42
+
43
+ ### Step 4: Add server middleware
44
+
45
+ Find the Express server setup (typically `server/index.ts`). Add the pin routes:
46
+
47
+ ```ts
48
+ import { pagePinRoutes } from "@agent-native/pinpoint/server";
49
+
50
+ // Add before your page routes
51
+ app.use("/api/pins", pagePinRoutes());
52
+ ```
53
+
54
+ This creates REST endpoints at `/api/pins` for pin CRUD. Pins are stored as JSON files in `data/pins/`.
55
+
56
+ ### Step 5: Verify
57
+
58
+ 1. Start the dev server
59
+ 2. Open the app in a browser
60
+ 3. Press `Cmd+Shift+.` to toggle the Pinpoint toolbar
61
+ 4. Click any element, add a comment, click "Add Pin"
62
+ 5. Click the send button — the annotation should appear in the agent chat
63
+
64
+ ### Working with Pins
65
+
66
+ Pins are stored as individual JSON files in `data/pins/{uuid}.json`:
67
+
68
+ ```json
69
+ {
70
+ "id": "uuid",
71
+ "pageUrl": "/dashboard",
72
+ "comment": "This button color is wrong",
73
+ "element": {
74
+ "tagName": "button",
75
+ "selector": ".sidebar button.primary",
76
+ "classNames": ["primary", "btn"]
77
+ },
78
+ "framework": {
79
+ "framework": "react",
80
+ "componentPath": "<Sidebar> <ActionButton>",
81
+ "sourceFile": "src/components/Sidebar.tsx:42"
82
+ },
83
+ "status": { "state": "open" }
84
+ }
85
+ ```
86
+
87
+ **Key fields for agents:**
88
+
89
+ - `sourceFile` — the exact file and line to edit
90
+ - `componentPath` — the React/Vue component hierarchy
91
+ - `selector` — CSS selector to find the element in the DOM
92
+ - `comment` — what the user wants changed
93
+
94
+ **Agent commands** (available after `npx @agent-native/pinpoint@latest init`):
95
+
96
+ - `pnpm action get-pins --status open` — list unresolved pins
97
+ - `pnpm action resolve-pin --id <uuid>` — mark as resolved after fixing
98
+ - `pnpm action create-pin --pageUrl / --selector ".btn" --comment "Fix this"`
99
+ - `pnpm action update-pin --id <uuid> --comment "Updated feedback"`
100
+ - `pnpm action delete-pin --id <uuid>` — remove a pin
101
+
102
+ **Workflow:**
103
+
104
+ 1. User creates annotations in the browser
105
+ 2. Read with `pnpm action get-pins --status open`
106
+ 3. Use `sourceFile` to locate and edit the relevant code
107
+ 4. After fixing, mark resolved: `pnpm action resolve-pin --id <uuid>`
108
+
109
+ ### Troubleshooting
110
+
111
+ | Issue | Fix |
112
+ | ---------------------- | -------------------------------------------------------------------------- |
113
+ | Toolbar doesn't appear | Check that `<Pinpoint />` is mounted. Press `Cmd+Shift+.` |
114
+ | Pins not persisting | Ensure `endpoint="/api/pins"` is set and server middleware is added |
115
+ | `sourceFile` is empty | Source detection requires dev mode. Production builds strip `_debugSource` |
116
+ | "Cannot find module" | Run `pnpm install`. Check the package is in `dependencies` |
117
+
118
+ ---
119
+
120
+ ## Install
121
+
122
+ ```sh
123
+ pnpm add @agent-native/pinpoint
124
+ # or
125
+ npm install @agent-native/pinpoint
126
+ ```
127
+
128
+ ## Quick Start
129
+
130
+ ### React
131
+
132
+ ```tsx
133
+ import { Pinpoint } from "@agent-native/pinpoint/react";
134
+
135
+ function App() {
136
+ return (
137
+ <>
138
+ <Pinpoint author="Designer" endpoint="/api/pins" autoSubmit />
139
+ <YourApp />
140
+ </>
141
+ );
142
+ }
143
+ ```
144
+
145
+ ### Vanilla JS / Script Tag
146
+
147
+ ```html
148
+ <script src="https://unpkg.com/@agent-native/pinpoint/dist/index.browser.js"></script>
149
+ <script>
150
+ Pinpoint.mountPinpoint({ author: "Designer" });
151
+ </script>
152
+ ```
153
+
154
+ ### Imperative API (Non-React)
155
+
156
+ ```ts
157
+ import { mountPinpoint } from "@agent-native/pinpoint";
158
+
159
+ const { dispose } = mountPinpoint({
160
+ author: "Designer",
161
+ endpoint: "/api/pins",
162
+ });
163
+ // Call dispose() to unmount
164
+ ```
165
+
166
+ ## Setup in an Agent-Native App
167
+
168
+ ### 1. Install
169
+
170
+ ```sh
171
+ pnpm add @agent-native/pinpoint
172
+ ```
173
+
174
+ ### 2. Initialize
175
+
176
+ ```sh
177
+ npx @agent-native/pinpoint@latest init
178
+ ```
179
+
180
+ Copies agent actions to `actions/` and the Pinpoint skill to `.agents/skills/pinpoint/`.
181
+
182
+ ### 3. Client — Mount the overlay
183
+
184
+ ```tsx
185
+ // app/App.tsx
186
+ import { Pinpoint } from "@agent-native/pinpoint/react";
187
+
188
+ function App() {
189
+ return (
190
+ <>
191
+ <Pinpoint
192
+ author="Designer"
193
+ endpoint="/api/pins"
194
+ autoSubmit
195
+ colorScheme="auto"
196
+ />
197
+ <YourApp />
198
+ </>
199
+ );
200
+ }
201
+ ```
202
+
203
+ ### 4. Server — Add the REST middleware
204
+
205
+ ```ts
206
+ // server/index.ts
207
+ import { createServer } from "@agent-native/core/server";
208
+ import { pagePinRoutes } from "@agent-native/pinpoint/server";
209
+
210
+ const app = createServer({
211
+ /* ... */
212
+ });
213
+ app.use("/api/pins", pagePinRoutes());
214
+ ```
215
+
216
+ ## How It Works
217
+
218
+ 1. **Toggle** the toolbar: `Cmd+Shift+.` (or `Ctrl+Shift+.`)
219
+ 2. **Click** any element to annotate it
220
+ 3. **Type** feedback in the popup
221
+ 4. **Send** to the agent: `Cmd+Shift+Enter`
222
+
223
+ The agent receives structured context: CSS selector, component hierarchy, source file location, and the user's comment.
224
+
225
+ ## Configuration
226
+
227
+ All options can be passed as props to `<Pinpoint />` or as the config object to `mountPinpoint()`:
228
+
229
+ | Option | Type | Default | Description |
230
+ | -------------------- | --------------------------------------- | ------------ | ------------------------------------------------- |
231
+ | `author` | `string` | — | Who is annotating |
232
+ | `endpoint` | `string` | — | REST endpoint for persistence (e.g., `/api/pins`) |
233
+ | `colorScheme` | `'auto' \| 'light' \| 'dark'` | `'auto'` | Theme |
234
+ | `outputFormat` | `'compact' \| 'standard' \| 'detailed'` | `'standard'` | Detail level in agent output |
235
+ | `autoSubmit` | `boolean` | `true` | Auto-submit annotations to agent chat |
236
+ | `clearOnSend` | `boolean` | `false` | Clear pins after sending |
237
+ | `sendToAgent` | `(output) => void \| Promise<void>` | — | Custom bridge for annotation delivery |
238
+ | `blockInteractions` | `boolean` | `false` | Block page clicks during selection |
239
+ | `compactPopup` | `boolean` | `true` | Hide technical details behind toggle |
240
+ | `freezeJSTimers` | `boolean` | `false` | Freeze JS timers during selection |
241
+ | `allowedOrigins` | `string[]` | — | Allowed origins for postMessage |
242
+ | `webhookUrl` | `string` | — | Webhook URL for pin events |
243
+ | `includeSourcePaths` | `boolean` | — | Include source file paths in output |
244
+ | `markerColor` | `string` | `'#3b82f6'` | Badge color on annotated elements |
245
+ | `plugins` | `Plugin[]` | — | Plugin extensions |
246
+ | `storage` | `PinStorage` | — | Custom storage adapter |
247
+ | `position` | `{ x, y }` | — | Initial toolbar position |
248
+
249
+ ## CLI
250
+
251
+ ```sh
252
+ npx @agent-native/pinpoint@latest init # Copy actions and skill to your project
253
+ npx @agent-native/pinpoint@latest # Show help
254
+ ```
255
+
256
+ ## Keyboard Shortcuts
257
+
258
+ | Shortcut | Action |
259
+ | ---------------------- | ------------------------------ |
260
+ | `Cmd/Ctrl+Shift+.` | Toggle toolbar |
261
+ | `Cmd/Ctrl+Shift+C` | Copy annotations to clipboard |
262
+ | `Cmd/Ctrl+Shift+Enter` | Send annotations to agent |
263
+ | `Esc` | Close popup / collapse toolbar |
264
+ | `Shift+Drag` | Multi-select elements |
265
+
266
+ ## Package Exports
267
+
268
+ | Import Path | What It Provides |
269
+ | ----------------------------------- | ------------------------------------------------------------- |
270
+ | `@agent-native/pinpoint` | `mountPinpoint()`, `unmountPinpoint()`, types |
271
+ | `@agent-native/pinpoint/react` | `<Pinpoint />` React component |
272
+ | `@agent-native/pinpoint/server` | `pagePinRoutes()` Express middleware |
273
+ | `@agent-native/pinpoint/primitives` | `getElementContext()`, `freeze()`, `unfreeze()`, `openFile()` |
274
+ | `@agent-native/pinpoint/types` | TypeScript types (`Pin`, `PinpointConfig`, etc.) |
275
+
276
+ ## Server Middleware
277
+
278
+ Express middleware for pin CRUD:
279
+
280
+ ```ts
281
+ import { pagePinRoutes } from "@agent-native/pinpoint/server";
282
+
283
+ app.use("/api/pins", pagePinRoutes({ dataDir: "data/pins" }));
284
+ ```
285
+
286
+ | Method | Endpoint | Description |
287
+ | ------ | --------------- | -------------------------------------- |
288
+ | GET | `/api/pins` | List pins (query: `pageUrl`, `status`) |
289
+ | GET | `/api/pins/:id` | Get a pin |
290
+ | POST | `/api/pins` | Create a pin |
291
+ | PATCH | `/api/pins/:id` | Update a pin |
292
+ | DELETE | `/api/pins/:id` | Delete a pin |
293
+ | DELETE | `/api/pins` | Clear pins (query: `pageUrl`) |
294
+
295
+ ## Agent Actions
296
+
297
+ Available after running `npx @agent-native/pinpoint@latest init`:
298
+
299
+ | Action | Purpose | Args |
300
+ | --------------- | -------------------- | -------------------------------------- |
301
+ | `get-pins` | List pins | `--pageUrl`, `--status` |
302
+ | `create-pin` | Create a pin | `--pageUrl`, `--selector`, `--comment` |
303
+ | `resolve-pin` | Mark as resolved | `--id`, `--message` |
304
+ | `update-pin` | Update a pin | `--id`, `--comment`, `--status` |
305
+ | `delete-pin` | Remove a pin | `--id` |
306
+ | `list-sessions` | List pages with pins | — |
307
+
308
+ ## Primitives API
309
+
310
+ Standalone functions for programmatic element inspection (no UI):
311
+
312
+ ```ts
313
+ import {
314
+ getElementContext,
315
+ freeze,
316
+ unfreeze,
317
+ openFile,
318
+ detectFramework,
319
+ } from "@agent-native/pinpoint/primitives";
320
+
321
+ const context = getElementContext(document.querySelector(".sidebar"));
322
+
323
+ freeze(); // Pause all animations
324
+ unfreeze(); // Resume
325
+
326
+ openFile("src/components/Sidebar.tsx", 42); // Open in editor
327
+ ```
328
+
329
+ ## Plugin System
330
+
331
+ ```ts
332
+ import type { Plugin } from "@agent-native/pinpoint/types";
333
+
334
+ const myPlugin: Plugin = {
335
+ name: "analytics",
336
+ hooks: {
337
+ onPinCreate(pin) {
338
+ analytics.track("pin_created", { page: pin.pageUrl });
339
+ },
340
+ onPinResolve(pin) {
341
+ analytics.track("pin_resolved", { id: pin.id });
342
+ },
343
+ transformOutput(output) {
344
+ return output + "\n\n_Sent via Pinpoint_";
345
+ },
346
+ },
347
+ actions: [
348
+ {
349
+ label: "Export to Jira",
350
+ handler(element, context) {
351
+ createJiraTicket(context);
352
+ },
353
+ },
354
+ ],
355
+ };
356
+ ```
357
+
358
+ ## A2A & MCP
359
+
360
+ Expose pins to external agents via A2A or MCP:
361
+
362
+ ```ts
363
+ import {
364
+ registerPinpointA2A,
365
+ createPinpointMCPTools,
366
+ } from "@agent-native/pinpoint/server";
367
+
368
+ registerPinpointA2A(app); // /.well-known/agent-card.json
369
+
370
+ const { tools, handleTool } = createPinpointMCPTools(); // MCP tool handlers
371
+ ```
372
+
373
+ ## Framework Support
374
+
375
+ | Framework | Detection | Component Info | Source Location |
376
+ | ----------- | ---------------- | ------------------- | ------------------------------- |
377
+ | React 18/19 | Auto (via bippy) | Component hierarchy | `_debugSource` / element-source |
378
+ | Vue 3 | Auto (`__VUE__`) | Component tree | `$options.__file` |
379
+ | Other | Fallback | DOM-only | Not available |
380
+
381
+ ## Storage Adapters
382
+
383
+ | Adapter | Use Case | Persistence |
384
+ | ------------- | --------------------- | ----------------------------- |
385
+ | `MemoryStore` | Standalone, no server | Session only (lost on reload) |
386
+ | `RestClient` | Browser with server | Server-side via REST API |
387
+ | `FileStore` | Server-side | `data/pins/{uuid}.json` |
388
+
389
+ ## Jami Studio Integration
390
+
391
+ Inside [Jami Studio's Fusion](https://builder.io), annotations are sent via `sendToAgentChat()` from `@agent-native/core`:
392
+
393
+ ```tsx
394
+ <Pinpoint author="Jami Studio User" autoSubmit outputFormat="standard" />
395
+ ```
396
+
397
+ No additional configuration needed when running inside a Jami Studio project.
398
+
399
+ Hosts with their own chat implementation can pass `sendToAgent` to reuse Pinpoint's pin,
400
+ draw, queue, and prompt UI while delivering `{ message, context, submit }` themselves.
401
+
402
+ ## Architecture
403
+
404
+ - **SolidJS overlay** in **Shadow DOM** — zero interference with host app styles or React reconciliation
405
+ - **Canvas-based** hover highlighting with LERP interpolation — smooth 60fps
406
+ - **One file per pin** — eliminates concurrent write conflicts
407
+ - **Pluggable storage** — MemoryStore, RestClient, FileStore
408
+ - MIT libraries: [bippy](https://github.com/aidenybai/bippy), [@medv/finder](https://github.com/antonmedv/finder), [element-source](https://www.npmjs.com/package/element-source)
409
+
410
+ ## License
411
+
412
+ MIT
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import {
3
+ formatPinsForAgent,
4
+ formatQueueForAgent,
5
+ formatRichPinContext
6
+ } from "./chunk-CGJZ7BOM.js";
7
+ import "./chunk-XBX2J7WU.js";
8
+ export {
9
+ formatPinsForAgent,
10
+ formatQueueForAgent,
11
+ formatRichPinContext
12
+ };
13
+ //# sourceMappingURL=agent-context-HBCZ4MBN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}