agentation 1.3.2 → 2.1.0

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.
package/README.md CHANGED
@@ -1,6 +1,9 @@
1
- # agentation
1
+ <img src="https://raw.githubusercontent.com/benjitaylor/agentation/main/package/logo.svg" alt="Agentation" width="50" />
2
2
 
3
- Agentation is an agent-agnostic visual feedback tool. Click elements on your page, add notes, and copy structured output that helps AI coding agents find the exact code you're referring to.
3
+ [![npm version](https://img.shields.io/npm/v/agentation)](https://www.npmjs.com/package/agentation)
4
+ [![downloads](https://img.shields.io/npm/dm/agentation)](https://www.npmjs.com/package/agentation)
5
+
6
+ **[Agentation](https://agentation.dev)** is an agent-agnostic visual feedback tool. Click elements on your page, add notes, and copy structured output that helps AI coding agents find the exact code you're referring to.
4
7
 
5
8
  ## Install
6
9
 
@@ -34,7 +37,7 @@ The toolbar appears in the bottom-right corner. Click to activate, then click an
34
37
  - **Animation pause** – Freeze CSS animations to capture specific states
35
38
  - **Structured output** – Copy markdown with selectors, positions, and context
36
39
  - **Programmatic access** – Callback prop for direct integration with tools
37
- - **Dark/light mode** – Matches your preference or set manually
40
+ - **Dark/light mode** – Toggle in settings, persists to localStorage
38
41
  - **Zero dependencies** – Pure CSS animations, no runtime libraries
39
42
 
40
43
  ## Props
@@ -46,7 +49,12 @@ The toolbar appears in the bottom-right corner. Click to activate, then click an
46
49
  | `onAnnotationUpdate` | `(annotation: Annotation) => void` | - | Called when an annotation is edited |
47
50
  | `onAnnotationsClear` | `(annotations: Annotation[]) => void` | - | Called when all annotations are cleared |
48
51
  | `onCopy` | `(markdown: string) => void` | - | Callback with markdown output when copy is clicked |
52
+ | `onSubmit` | `(output: string, annotations: Annotation[]) => void` | - | Called when "Send Annotations" is clicked |
49
53
  | `copyToClipboard` | `boolean` | `true` | Set to false to prevent writing to clipboard |
54
+ | `endpoint` | `string` | - | Server URL for Agent Sync (e.g., `"http://localhost:4747"`) |
55
+ | `sessionId` | `string` | - | Pre-existing session ID to join |
56
+ | `onSessionCreated` | `(sessionId: string) => void` | - | Called when a new session is created |
57
+ | `webhookUrl` | `string` | - | Webhook URL to receive annotation events |
50
58
 
51
59
  ### Programmatic Integration
52
60
 
@@ -85,7 +93,7 @@ function App() {
85
93
  type Annotation = {
86
94
  id: string;
87
95
  x: number; // % of viewport width
88
- y: number; // px from top (viewport if fixed)
96
+ y: number; // px from top of document (absolute) OR viewport (if isFixed)
89
97
  comment: string; // User's note
90
98
  element: string; // e.g., "Button"
91
99
  elementPath: string; // e.g., "body > div > button"
@@ -105,6 +113,8 @@ type Annotation = {
105
113
  };
106
114
  ```
107
115
 
116
+ > **Note:** This is a simplified type. The full type includes additional fields for Agent Sync (`url`, `status`, `thread`, `reactComponents`, etc.). See [agentation.dev/schema](https://agentation.dev/schema) for the complete schema.
117
+
108
118
  ## How it works
109
119
 
110
120
  Agentation captures class names, selectors, and element positions so AI agents can `grep` for the exact code you're referring to. Instead of describing "the blue button in the sidebar," you give the agent `.sidebar > button.primary` and your feedback.
@@ -121,4 +131,5 @@ Full documentation at [agentation.dev](https://agentation.dev)
121
131
  ## License
122
132
 
123
133
  © 2026 Benji Taylor
134
+
124
135
  Licensed under PolyForm Shield 1.0.0
package/dist/index.d.mts CHANGED
@@ -24,6 +24,34 @@ type Annotation = {
24
24
  accessibility?: string;
25
25
  isMultiSelect?: boolean;
26
26
  isFixed?: boolean;
27
+ reactComponents?: string;
28
+ elementBoundingBoxes?: Array<{
29
+ x: number;
30
+ y: number;
31
+ width: number;
32
+ height: number;
33
+ }>;
34
+ sessionId?: string;
35
+ url?: string;
36
+ intent?: AnnotationIntent;
37
+ severity?: AnnotationSeverity;
38
+ status?: AnnotationStatus;
39
+ thread?: ThreadMessage[];
40
+ createdAt?: string;
41
+ updatedAt?: string;
42
+ resolvedAt?: string;
43
+ resolvedBy?: "human" | "agent";
44
+ authorId?: string;
45
+ _syncedTo?: string;
46
+ };
47
+ type AnnotationIntent = "fix" | "change" | "question" | "approve";
48
+ type AnnotationSeverity = "blocking" | "important" | "suggestion";
49
+ type AnnotationStatus = "pending" | "acknowledged" | "resolved" | "dismissed";
50
+ type ThreadMessage = {
51
+ id: string;
52
+ role: "human" | "agent";
53
+ content: string;
54
+ timestamp: number;
27
55
  };
28
56
 
29
57
  type DemoAnnotation = {
@@ -45,12 +73,22 @@ type PageFeedbackToolbarCSSProps = {
45
73
  onAnnotationsClear?: (annotations: Annotation[]) => void;
46
74
  /** Callback fired when the copy button is clicked. Receives the markdown output. */
47
75
  onCopy?: (markdown: string) => void;
76
+ /** Callback fired when "Send to Agent" is clicked. Receives the markdown output and annotations. */
77
+ onSubmit?: (output: string, annotations: Annotation[]) => void;
48
78
  /** Whether to copy to clipboard when the copy button is clicked. Defaults to true. */
49
79
  copyToClipboard?: boolean;
80
+ /** Server URL for sync (e.g., "http://localhost:4747"). If not provided, uses localStorage only. */
81
+ endpoint?: string;
82
+ /** Pre-existing session ID to join. If not provided with endpoint, creates a new session. */
83
+ sessionId?: string;
84
+ /** Called when a new session is created (only when endpoint is provided without sessionId). */
85
+ onSessionCreated?: (sessionId: string) => void;
86
+ /** Webhook URL to receive annotation events. */
87
+ webhookUrl?: string;
50
88
  };
51
89
  /** Alias for PageFeedbackToolbarCSSProps */
52
90
  type AgentationProps = PageFeedbackToolbarCSSProps;
53
- declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, copyToClipboard, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
91
+ declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, onSubmit, copyToClipboard, endpoint, sessionId: initialSessionId, onSessionCreated, webhookUrl, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
54
92
 
55
93
  interface AnnotationPopupCSSProps {
56
94
  /** Element name to display in header */
@@ -69,6 +107,8 @@ interface AnnotationPopupCSSProps {
69
107
  onSubmit: (text: string) => void;
70
108
  /** Called when popup is cancelled/dismissed */
71
109
  onCancel: () => void;
110
+ /** Called when delete button is clicked (only shown if provided) */
111
+ onDelete?: () => void;
72
112
  /** Position styles (left, top) */
73
113
  style?: React.CSSProperties;
74
114
  /** Custom color for submit button and textarea focus (hex) */
@@ -115,6 +155,14 @@ declare const IconCopyAnimated: ({ size, copied }: {
115
155
  size?: number;
116
156
  copied?: boolean;
117
157
  }) => react_jsx_runtime.JSX.Element;
158
+ declare const IconSendArrow: ({ size, state }: {
159
+ size?: number;
160
+ state?: "idle" | "sending" | "sent" | "failed";
161
+ }) => react_jsx_runtime.JSX.Element;
162
+ declare const IconSendAnimated: ({ size, sent }: {
163
+ size?: number;
164
+ sent?: boolean;
165
+ }) => react_jsx_runtime.JSX.Element;
118
166
  declare const IconEye: ({ size }: {
119
167
  size?: number;
120
168
  }) => react_jsx_runtime.JSX.Element;
@@ -175,13 +223,38 @@ declare const IconSun: ({ size }: {
175
223
  declare const IconMoon: ({ size }: {
176
224
  size?: number;
177
225
  }) => react_jsx_runtime.JSX.Element;
226
+ declare const IconEdit: ({ size }: {
227
+ size?: number;
228
+ }) => react_jsx_runtime.JSX.Element;
229
+ declare const IconTrash: ({ size }: {
230
+ size?: number;
231
+ }) => react_jsx_runtime.JSX.Element;
232
+ declare const IconChevronLeft: ({ size }: {
233
+ size?: number;
234
+ }) => react_jsx_runtime.JSX.Element;
235
+ declare const IconChevronRight: ({ size }: {
236
+ size?: number;
237
+ }) => react_jsx_runtime.JSX.Element;
178
238
  declare const AnimatedBunny: ({ size, color, }: {
179
239
  size?: number;
180
240
  color?: string;
181
241
  }) => react_jsx_runtime.JSX.Element;
182
242
 
243
+ /**
244
+ * Finds the closest ancestor matching a selector, crossing shadow DOM boundaries.
245
+ */
246
+ declare function closestCrossingShadow(element: Element, selector: string): Element | null;
247
+ /**
248
+ * Checks if an element is inside a shadow DOM
249
+ */
250
+ declare function isInShadowDOM(element: Element): boolean;
251
+ /**
252
+ * Gets the shadow host for an element, or null if not in shadow DOM
253
+ */
254
+ declare function getShadowHost(element: Element): Element | null;
183
255
  /**
184
256
  * Gets a readable path for an element (e.g., "article > section > p")
257
+ * Supports elements inside shadow DOM by crossing shadow boundaries.
185
258
  */
186
259
  declare function getElementPath(target: HTMLElement, maxDepth?: number): string;
187
260
  /**
@@ -208,4 +281,4 @@ declare function getStorageKey(pathname: string): string;
208
281
  declare function loadAnnotations<T = Annotation>(pathname: string): T[];
209
282
  declare function saveAnnotations<T = Annotation>(pathname: string, annotations: T[]): void;
210
283
 
211
- export { PageFeedbackToolbarCSS as Agentation, type AgentationProps, AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconClose, IconCopyAlt, IconCopyAnimated, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSun, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, getElementClasses, getElementPath, getNearbyText, getStorageKey, identifyAnimationElement, identifyElement, loadAnnotations, saveAnnotations };
284
+ export { PageFeedbackToolbarCSS as Agentation, type AgentationProps, AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconChevronLeft, IconChevronRight, IconClose, IconCopyAlt, IconCopyAnimated, IconEdit, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSendAnimated, IconSendArrow, IconSun, IconTrash, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, closestCrossingShadow, getElementClasses, getElementPath, getNearbyText, getShadowHost, getStorageKey, identifyAnimationElement, identifyElement, isInShadowDOM, loadAnnotations, saveAnnotations };
package/dist/index.d.ts CHANGED
@@ -24,6 +24,34 @@ type Annotation = {
24
24
  accessibility?: string;
25
25
  isMultiSelect?: boolean;
26
26
  isFixed?: boolean;
27
+ reactComponents?: string;
28
+ elementBoundingBoxes?: Array<{
29
+ x: number;
30
+ y: number;
31
+ width: number;
32
+ height: number;
33
+ }>;
34
+ sessionId?: string;
35
+ url?: string;
36
+ intent?: AnnotationIntent;
37
+ severity?: AnnotationSeverity;
38
+ status?: AnnotationStatus;
39
+ thread?: ThreadMessage[];
40
+ createdAt?: string;
41
+ updatedAt?: string;
42
+ resolvedAt?: string;
43
+ resolvedBy?: "human" | "agent";
44
+ authorId?: string;
45
+ _syncedTo?: string;
46
+ };
47
+ type AnnotationIntent = "fix" | "change" | "question" | "approve";
48
+ type AnnotationSeverity = "blocking" | "important" | "suggestion";
49
+ type AnnotationStatus = "pending" | "acknowledged" | "resolved" | "dismissed";
50
+ type ThreadMessage = {
51
+ id: string;
52
+ role: "human" | "agent";
53
+ content: string;
54
+ timestamp: number;
27
55
  };
28
56
 
29
57
  type DemoAnnotation = {
@@ -45,12 +73,22 @@ type PageFeedbackToolbarCSSProps = {
45
73
  onAnnotationsClear?: (annotations: Annotation[]) => void;
46
74
  /** Callback fired when the copy button is clicked. Receives the markdown output. */
47
75
  onCopy?: (markdown: string) => void;
76
+ /** Callback fired when "Send to Agent" is clicked. Receives the markdown output and annotations. */
77
+ onSubmit?: (output: string, annotations: Annotation[]) => void;
48
78
  /** Whether to copy to clipboard when the copy button is clicked. Defaults to true. */
49
79
  copyToClipboard?: boolean;
80
+ /** Server URL for sync (e.g., "http://localhost:4747"). If not provided, uses localStorage only. */
81
+ endpoint?: string;
82
+ /** Pre-existing session ID to join. If not provided with endpoint, creates a new session. */
83
+ sessionId?: string;
84
+ /** Called when a new session is created (only when endpoint is provided without sessionId). */
85
+ onSessionCreated?: (sessionId: string) => void;
86
+ /** Webhook URL to receive annotation events. */
87
+ webhookUrl?: string;
50
88
  };
51
89
  /** Alias for PageFeedbackToolbarCSSProps */
52
90
  type AgentationProps = PageFeedbackToolbarCSSProps;
53
- declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, copyToClipboard, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
91
+ declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, onSubmit, copyToClipboard, endpoint, sessionId: initialSessionId, onSessionCreated, webhookUrl, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
54
92
 
55
93
  interface AnnotationPopupCSSProps {
56
94
  /** Element name to display in header */
@@ -69,6 +107,8 @@ interface AnnotationPopupCSSProps {
69
107
  onSubmit: (text: string) => void;
70
108
  /** Called when popup is cancelled/dismissed */
71
109
  onCancel: () => void;
110
+ /** Called when delete button is clicked (only shown if provided) */
111
+ onDelete?: () => void;
72
112
  /** Position styles (left, top) */
73
113
  style?: React.CSSProperties;
74
114
  /** Custom color for submit button and textarea focus (hex) */
@@ -115,6 +155,14 @@ declare const IconCopyAnimated: ({ size, copied }: {
115
155
  size?: number;
116
156
  copied?: boolean;
117
157
  }) => react_jsx_runtime.JSX.Element;
158
+ declare const IconSendArrow: ({ size, state }: {
159
+ size?: number;
160
+ state?: "idle" | "sending" | "sent" | "failed";
161
+ }) => react_jsx_runtime.JSX.Element;
162
+ declare const IconSendAnimated: ({ size, sent }: {
163
+ size?: number;
164
+ sent?: boolean;
165
+ }) => react_jsx_runtime.JSX.Element;
118
166
  declare const IconEye: ({ size }: {
119
167
  size?: number;
120
168
  }) => react_jsx_runtime.JSX.Element;
@@ -175,13 +223,38 @@ declare const IconSun: ({ size }: {
175
223
  declare const IconMoon: ({ size }: {
176
224
  size?: number;
177
225
  }) => react_jsx_runtime.JSX.Element;
226
+ declare const IconEdit: ({ size }: {
227
+ size?: number;
228
+ }) => react_jsx_runtime.JSX.Element;
229
+ declare const IconTrash: ({ size }: {
230
+ size?: number;
231
+ }) => react_jsx_runtime.JSX.Element;
232
+ declare const IconChevronLeft: ({ size }: {
233
+ size?: number;
234
+ }) => react_jsx_runtime.JSX.Element;
235
+ declare const IconChevronRight: ({ size }: {
236
+ size?: number;
237
+ }) => react_jsx_runtime.JSX.Element;
178
238
  declare const AnimatedBunny: ({ size, color, }: {
179
239
  size?: number;
180
240
  color?: string;
181
241
  }) => react_jsx_runtime.JSX.Element;
182
242
 
243
+ /**
244
+ * Finds the closest ancestor matching a selector, crossing shadow DOM boundaries.
245
+ */
246
+ declare function closestCrossingShadow(element: Element, selector: string): Element | null;
247
+ /**
248
+ * Checks if an element is inside a shadow DOM
249
+ */
250
+ declare function isInShadowDOM(element: Element): boolean;
251
+ /**
252
+ * Gets the shadow host for an element, or null if not in shadow DOM
253
+ */
254
+ declare function getShadowHost(element: Element): Element | null;
183
255
  /**
184
256
  * Gets a readable path for an element (e.g., "article > section > p")
257
+ * Supports elements inside shadow DOM by crossing shadow boundaries.
185
258
  */
186
259
  declare function getElementPath(target: HTMLElement, maxDepth?: number): string;
187
260
  /**
@@ -208,4 +281,4 @@ declare function getStorageKey(pathname: string): string;
208
281
  declare function loadAnnotations<T = Annotation>(pathname: string): T[];
209
282
  declare function saveAnnotations<T = Annotation>(pathname: string, annotations: T[]): void;
210
283
 
211
- export { PageFeedbackToolbarCSS as Agentation, type AgentationProps, AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconClose, IconCopyAlt, IconCopyAnimated, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSun, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, getElementClasses, getElementPath, getNearbyText, getStorageKey, identifyAnimationElement, identifyElement, loadAnnotations, saveAnnotations };
284
+ export { PageFeedbackToolbarCSS as Agentation, type AgentationProps, AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconChevronLeft, IconChevronRight, IconClose, IconCopyAlt, IconCopyAnimated, IconEdit, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSendAnimated, IconSendArrow, IconSun, IconTrash, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, closestCrossingShadow, getElementClasses, getElementPath, getNearbyText, getShadowHost, getStorageKey, identifyAnimationElement, identifyElement, isInShadowDOM, loadAnnotations, saveAnnotations };