anniedrawing 0.3.2 → 0.4.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +5 -1
  3. package/dist/agent/index.js +1 -1
  4. package/dist/agent/index.js.map +1 -1
  5. package/dist/agent/toolDefs.d.ts +1 -0
  6. package/dist/board.d.ts +7 -1
  7. package/dist/core/catalog.d.ts +1 -1
  8. package/dist/core/index.js +1 -1
  9. package/dist/core/textFit.d.ts +13 -0
  10. package/dist/core/types.d.ts +12 -0
  11. package/dist/docs/agents-repository.md +2 -2
  12. package/dist/docs/agents.md +6 -2
  13. package/dist/docs/api.md +7 -3
  14. package/dist/docs/board-js.md +20 -16
  15. package/dist/docs/decisions.md +21 -1
  16. package/dist/docs/format.md +2 -2
  17. package/dist/docs/index.html +15 -7
  18. package/dist/docs/llms-full.txt +20 -16
  19. package/dist/docs/llms.txt +14 -10
  20. package/dist/docs/mcp.md +1 -1
  21. package/dist/fellow.d.ts +2 -2
  22. package/dist/fellow.js +1 -1
  23. package/dist/fellow.js.map +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/shared/board-OPwsZ2_V.js +2 -0
  26. package/dist/shared/board-OPwsZ2_V.js.map +1 -0
  27. package/dist/shared/{cards-DWgSVE54.js → cards-D_9Lly1d.js} +2 -2
  28. package/dist/shared/{cards-DWgSVE54.js.map → cards-D_9Lly1d.js.map} +1 -1
  29. package/dist/shared/defaults-DZEoAeRz.js +2 -0
  30. package/dist/shared/defaults-DZEoAeRz.js.map +1 -0
  31. package/dist/shared/describe-o3vER0cL.js +3 -0
  32. package/dist/shared/{describe-DaWyf3qV.js.map → describe-o3vER0cL.js.map} +1 -1
  33. package/dist/shared/{paste-C22i8o-g.js → paste-B4b0C9Jh.js} +2 -2
  34. package/dist/shared/{paste-C22i8o-g.js.map → paste-B4b0C9Jh.js.map} +1 -1
  35. package/dist/shared/picker-ciuPQvRn.js +2 -0
  36. package/dist/shared/picker-ciuPQvRn.js.map +1 -0
  37. package/dist/shared/textFit-BrGz6lhQ.js +2 -0
  38. package/dist/shared/textFit-BrGz6lhQ.js.map +1 -0
  39. package/dist/shared/ui-c98N8xEV.js +2 -0
  40. package/dist/shared/ui-c98N8xEV.js.map +1 -0
  41. package/dist/shared/{urlPaste-DN4JtgeB.js → urlPaste-BqcpeQ-c.js} +2 -2
  42. package/dist/shared/{urlPaste-DN4JtgeB.js.map → urlPaste-BqcpeQ-c.js.map} +1 -1
  43. package/dist/style.css +1 -1
  44. package/dist/ui/index.js +1 -1
  45. package/dist/ui/version.d.ts +1 -1
  46. package/llms-full.txt +20 -16
  47. package/llms.txt +14 -10
  48. package/package.json +1 -1
  49. package/dist/shared/board-DV5lzxNR.js +0 -2
  50. package/dist/shared/board-DV5lzxNR.js.map +0 -1
  51. package/dist/shared/defaults-C-aC_B4z.js +0 -2
  52. package/dist/shared/defaults-C-aC_B4z.js.map +0 -1
  53. package/dist/shared/describe-DaWyf3qV.js +0 -3
  54. package/dist/shared/picker-Dv_i4iNP.js +0 -2
  55. package/dist/shared/picker-Dv_i4iNP.js.map +0 -1
  56. package/dist/shared/ui-DEBI1jv_.js +0 -2
  57. package/dist/shared/ui-DEBI1jv_.js.map +0 -1
package/dist/docs/api.md CHANGED
@@ -101,6 +101,8 @@ stop();
101
101
 
102
102
  Reads scoped to `page`, `selection`, or `viewport` include only media referenced by the returned items. Whole-document reads keep the complete media table. Scoped exports follow the same boundary, so exporting a selection does not include unrelated embedded images.
103
103
 
104
+ `board.getPointer()` returns a copy of the last human pointer: `{ x, y, pageId, inside, pointerType, ageMs, itemId }`, or `null` before a pointer is observed, after a page switch, or after destruction. Coordinates are page-space. While `inside` is true they follow pan and zoom; `itemId` is the topmost hittable item or `null`. Editor controls are excluded. Leaving, blur, hidden tabs, cancel, or touch release sets `inside: false` and preserves the last point. `ageMs` measures time since the last pointer event, not camera changes. Treat an outside point as historical; ask the user to point again when ambiguous. Pointer state is never serialized.
105
+
104
106
  ## apply
105
107
 
106
108
  ```ts
@@ -116,11 +118,13 @@ const result = board.apply(ops, {
116
118
  // { ok, created: string[], errors: [...], warnings: [...], skipped?: [...] }
117
119
  ```
118
120
 
121
+ Pass `expectedRevision` from the read that informed an edit to `apply` or `board_apply`. A mismatch returns `STALE_REVISION` without applying any operation, including in lenient or dry-run mode. Read again before retrying. This guards one session only: `load()` and `clear()` reset revisions.
122
+
119
123
  Supported operations: `add`, `set`, `remove`, `order`, `reparent`, `page.add`, `page.set`, `page.remove`, `meta.set`, `media.set`, and `media.remove`. A batch is all-or-nothing unless `lenient: true`. Then failed operations go to `skipped` and the rest commit as one transaction. If nothing commits, `ok` is false and the document is unchanged. `set` merges `style`, `text`, and `data` one level deep. Do not change an item's ID. Add operations may provide IDs so later operations in the same batch can reference the new items. `add` also accepts `page`, `parent`, and `index`. `page.add` accepts `index`. `order.to` is `front`, `back`, `forward`, `backward`, or a numeric index.
120
124
 
121
125
  `add.item.kind` accepts `rectangle` (stored `rect`) and `arrow` (stored `connector` with an end arrow and elbow route when those fields are omitted). `query({ kind: 'rectangle' })` and `query({ kind: 'arrow' })` match those stored kinds. Color strings `black`, `grey`, `gray`, `blue`, `light-blue`, `green`, `light-green`, `red`, `light-red`, `orange`, `yellow`, `violet`, and `light-violet` store the matching palette token. Connector `from` and `to` accept `{ item, side }`, `{ x, y }`, or a string item id (`{ item, side: 'auto' }`). Compact JSON writes tokens and structured endpoints.
122
126
 
123
- `place` requires exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32 (`agentPlaceGap` when origin starts with `agent:` and `gap` is omitted). Default `align` is `middle`. `inside` requires a `group` and finds a free slot; it fails if the group is full. `near` searches rings around the reference. Omitted `w` and `h` use the built-in default size for that kind.
127
+ `place` requires exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32 (`agentPlaceGap` when origin starts with `agent:` and `gap` is omitted). Default `align` is `middle`. `inside` requires a `group` and finds a free slot; it fails if the group is full. `near` searches rings around the reference. `rightOf` / `leftOf` / `above` / `below` slide further along that axis when the first slot is occupied. Omitted `w` and `h` use the built-in default size for that kind. An `agent:` create or text patch on `rect`, `ellipse`, `diamond`, `note`, or `text` grows that size so the label fits. Standalone `text` defaults to 600 wide. A larger explicit size is kept. An `agent:` connector that omits `route` stores `elbow`. Elbows go around intervening boxes. Straight and curve routes, and elbows with waypoints, stay as written.
124
128
 
125
129
  `result.created` is the stored ids for that batch. Warnings do not roll back:
126
130
 
@@ -173,7 +177,7 @@ board.apply([
173
177
  board.setPage('p_planning');
174
178
  ```
175
179
 
176
- A browser text item with `autoWidth: true` measures its plain text when it is added, when its text is set through `apply`, or when a text edit commits. Measurement uses a hidden DOM measurer and cache. The resulting width and height are saved in the document. A headless document keeps stored dimensions and does not measure fonts.
180
+ A browser text item with `autoWidth: true` measures its plain text when it is added, when its text is set through `apply`, or when a text edit commits. `agent:` creates of `text` set `autoWidth` when it is omitted. Measurement uses a hidden DOM measurer and cache. The resulting width and height are saved in the document. A headless document keeps stored or grown dimensions and does not measure fonts. The default omitted size is 600×48.
177
181
 
178
182
  ## Agent origin presentation
179
183
 
@@ -185,7 +189,7 @@ The cursor ignores pointer events. Selection, focus, and the person's native cur
185
189
 
186
190
  ## Editor chrome
187
191
 
188
- The built-in toolbar shows select, hand, eraser, then Shapes, draw, text, sticky note, and image. Shapes groups rectangle, ellipse, diamond, line, and arrow. On phones, including landscape, hand moves into the AnnieDrawing menu so the bottom bar stays tappable, unless that menu is hidden. A short desktop host keeps the sidebar centered and uses smaller icons and tighter padding. That menu also opens appearance, document actions, documentation, and the GitHub repository, and shows the package version. Export downloads the current page. Hosts choose PNG, SVG, and AnnieDoc (`json`); an imported board defaults to PNG and SVG. Page chips in the bottom bar switch pages. `+` adds a page. All pages appears when the chips overflow. The active page stays visible. Right-click a page chip to rename or delete that page. The last page cannot be deleted. Arrow keys, Home, and End navigate page tabs. The zoom percentage opens zoom controls.
192
+ The built-in toolbar shows select, hand, eraser, then Shapes, draw, text, sticky note, and image. Shapes groups rectangle, ellipse, diamond, line, and arrow. On phones, including landscape, hand moves into the AnnieDrawing menu so the bottom bar stays tappable, unless that menu is hidden. Pages, zoom, undo, redo, and Export move into Board controls at the top right. A short desktop host keeps the sidebar centered. When the AnnieDrawing menu or page chips are present, icons and padding tighten at 640px host height. Without those bars, 640px reduces the left inset and uses a middle tool size; tools fully shrink at 500px. That menu also opens appearance, document actions, documentation, and the GitHub repository, and shows the package version. Export downloads the current page. Hosts choose PNG, SVG, and AnnieDoc (`json`); an imported board defaults to PNG and SVG. Page chips in the bottom bar switch pages. `+` adds a page. All pages appears when the chips overflow. The active page stays visible. Right-click a page chip to rename or delete that page. The last page cannot be deleted. Arrow keys, Home, and End navigate page tabs. The zoom percentage opens zoom controls.
189
193
 
190
194
  Selecting an item opens a compact inspector for that item type. Fill, Line, and Opacity share one row. Color replaces fill and line on plain text. Fill, line, and text color open a palette. Text-capable shapes, including empty ones, show Text (S/M/L/XL), Align, and Font on their own rows. Font choices are Friendly (`sans`), Serif, Mono, and Handwritten (`hand`, the default). Stroked shapes also get line weight (1, 2, 4, or 8) and Pattern (solid, dashed, or dotted) on separate rows. Open freehand paths omit pattern. Sticky notes keep fill and text controls and omit line color, weight, and pattern. Images, videos, and link cards omit line and text controls. A selected video offers Edit Video URL; a selected link card offers Edit URL. Opacity opens a 0-100% slider; the document stores opacity as 0-1. The lock icon beside Delete locks or unlocks the selection. Connector route and arrowhead controls appear for a selected connector. More arrangement options opens align, distribute, group, ungroup, and stacking. Deselect to hide the inspector. The inspector does not expose `fillMode: 'hatch'`; set that through `apply`.
191
195
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Operate a live or headless board through JavaScript. This is the full AI reference for creating items and reading what is on the board. It does not cover installing, running, or changing the library.
4
4
 
5
- Kind catalog: 1
5
+ Kind catalog: 2
6
6
 
7
7
  `kindsSince(since?)` lists built-in kinds added or last changed after that catalog version. Omit `since`, or pass `0`, to list every built-in kind. Remember the returned `version` and pass it next time you want only what is new.
8
8
 
@@ -32,12 +32,12 @@ const board = createDoc();
32
32
 
33
33
  ```js
34
34
  board.kindsSince(); // every built-in kind; same as board.kindsSince(0)
35
- board.kindsSince(1); // kinds added or changed after catalog 1 (empty today)
35
+ board.kindsSince(1); // kinds added or changed after catalog 1
36
36
  ```
37
37
 
38
38
  Also exported as `kindsSince` and `CATALOG_VERSION` from `anniedrawing`, `anniedrawing/core`, and `anniedrawing/agent`.
39
39
 
40
- Each entry is `{ kind, since, w, h, note }`. `w` and `h` are the default size when those fields are omitted on `add`. Custom host kinds do not appear here.
40
+ Each entry is `{ kind, since, w, h, note }`. `w` and `h` are the default size when those fields are omitted on `add`. An `agent:` create can store a larger box so `text` fits. An `agent:` connector that omits `route` stores `elbow`. Custom host kinds do not appear here.
41
41
 
42
42
  The catalog version is independent of the `.annie` document format version (`2`) and the package version.
43
43
 
@@ -68,6 +68,8 @@ board.toJSON(); // portable document
68
68
 
69
69
  DOM nodes may show `[data-ad-id]` and `[data-ad-kind]`. Do not treat DOM edits as a write API.
70
70
 
71
+ `board.getPointer()` returns a copy of the last human pointer: `{ x, y, pageId, inside, pointerType, ageMs, itemId }`, or `null` before a pointer is observed, after a page switch, or after destruction. Coordinates are page-space. While `inside` is true they follow pan and zoom; `itemId` is the topmost hittable item or `null`. Editor controls are excluded. Leaving, blur, hidden tabs, cancel, or touch release sets `inside: false` and preserves the last point. `ageMs` measures time since the last pointer event, not camera changes. Treat an outside point as historical; ask the user to point again when ambiguous. Pointer state is never serialized.
72
+
71
73
  ## Write
72
74
 
73
75
  ```js
@@ -81,6 +83,8 @@ const result = board.apply(ops, {
81
83
  // { ok, created, errors, warnings, skipped? }
82
84
  ```
83
85
 
86
+ Pass `expectedRevision` from the read that informed an edit to `apply` or `board_apply`. A mismatch returns `STALE_REVISION` without applying any operation, including in lenient or dry-run mode. Read again before retrying. This guards one session only: `load()` and `clear()` reset revisions.
87
+
84
88
  A failed batch changes nothing. `dryRun: true` validates and does not write. It does not reserve IDs. Do not call `load()` to patch a few items. Do not set `merge: true` unless you intend to fold this commit into the previous history entry with the same origin and label. `lenient: true` is available on `apply` only.
85
89
 
86
90
  Use stable IDs when later operations in the same batch need to reference new items. Generated prefixes are `i_`, `p_`, and `m_`.
@@ -89,7 +93,7 @@ Operations: `add`, `set`, `remove`, `order`, `reparent`, `page.add`, `page.set`,
89
93
 
90
94
  `set` merges `style`, `text`, and `data` one level deep. Other fields are replaced. Do not change `id` with `set`. `order.to` is `front`, `back`, `forward`, `backward`, or a numeric index.
91
95
 
92
- `add` accepts `page`, `parent`, `index`, and `place`. `place` needs exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. Kind aliases: `rectangle` stores `rect`; `arrow` stores `connector` with an end arrow. `from` / `to` accept `{ item, side }`, `{ x, y }`, or a string item id.
96
+ `add` accepts `page`, `parent`, `index`, and `place`. `place` needs exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. `rightOf` / `leftOf` / `above` / `below` slide further along that axis when the first slot is occupied. Kind aliases: `rectangle` stores `rect`; `arrow` stores `connector` with an end arrow. `from` / `to` accept `{ item, side }`, `{ x, y }`, or a string item id. An `agent:` connector that omits `route` stores `elbow`. Elbows go around intervening boxes.
93
97
 
94
98
  `OVERLAPS_EXISTING` and `ID_REMAPPED` are warnings. The batch still committed. An `agent:` create that reuses an id is stored as `id_1`, then `_2`. Same-batch `place`, parent, and connector refs follow the stored id. `get` with the id you sent returns the older item. User and API origins still reject duplicates.
95
99
 
@@ -175,7 +179,7 @@ Named colors: `ink`, `slate`, `coral`, `amber`, `moss`, `teal`, `sky`, `violet`,
175
179
 
176
180
  ## Built-in kinds
177
181
 
178
- Omit `w` / `h` to use the default size in the catalog.
182
+ Omit `w` / `h` to use the default size in the catalog. An `agent:` create or text patch on `rect`, `ellipse`, `diamond`, `note`, or `text` grows the stored size so the label fits. Standalone `text` defaults to 600 wide. A larger explicit size is kept.
179
183
 
180
184
  ### `rect`
181
185
 
@@ -209,7 +213,7 @@ Omit `w` / `h` to use the default size in the catalog.
209
213
 
210
214
  ### `connector`
211
215
 
212
- `from` / `to` are `{ item, side?, anchor? }`, `{ x, y }`, or a string item id stored as `{ item, side: 'auto' }`. `side` is `auto` / `top` / `right` / `bottom` / `left`. `route` is `straight` / `elbow` / `curve`. Heads: `none` / `arrow` / `dot`. Optional `waypoints` are page-space `[x, y]`. Bound ends detach to their last point when the target disappears. `kind: 'arrow'` stores `connector` with an end arrow.
216
+ `from` / `to` are `{ item, side?, anchor? }`, `{ x, y }`, or a string item id stored as `{ item, side: 'auto' }`. `side` is `auto` / `top` / `right` / `bottom` / `left`. `route` is `straight` / `elbow` / `curve`. Heads: `none` / `arrow` / `dot`. Optional `waypoints` are page-space `[x, y]`. An `agent:` create that omits `route` stores `elbow`. Elbows pick a channel that misses intervening boxes. Bound ends detach to their last point when the target disappears. `kind: 'arrow'` stores `connector` with an end arrow.
213
217
 
214
218
  ```js
215
219
  { op: 'add', item: { id: 'i_flow', kind: 'connector',
@@ -229,11 +233,11 @@ Freehand points may include pressure: `[x, y, pressure]`. `closed: true` closes
229
233
  ### `text`
230
234
 
231
235
  ```js
232
- { op: 'add', item: { id: 'i_title', kind: 'text', x: 80, y: 40, w: 280, h: 48,
236
+ { op: 'add', item: { id: 'i_title', kind: 'text', x: 80, y: 40,
233
237
  text: { value: 'Architecture', size: 'l', align: 'start' } } }
234
238
  ```
235
239
 
236
- A browser `text` item with `autoWidth: true` stores measured width and height. Headless documents keep the stored size.
240
+ Omitted `w` is 600. A browser `text` item with `autoWidth: true` (set for `agent:` creates) stores measured width and height. Headless documents keep the stored or grown size.
237
241
 
238
242
  ### `note`
239
243
 
@@ -323,14 +327,14 @@ PNG `labels: true` draws item IDs for vision models and defaults to a 32-color i
323
327
 
324
328
  Optional wrapper around the same APIs. Import `toolDefs` and `runTool` from `anniedrawing/agent`. Map `name`, `description`, and `inputSchema` into the provider envelope. Do not change the operations schema.
325
329
 
326
- | Tool | Use |
327
- | ---------------- | -------------------------------------------------------------------------------------------------------------- |
328
- | `board_describe` | Text with IDs. Start here. |
329
- | `board_read` | Deep JSON copy. Headless accepts only `scope: 'doc'`. |
330
- | `board_query` | Same filters as `query`. |
331
- | `board_apply` | Atomic ops. `runTool` forces an `agent:` origin (`agent:tool` if omitted). Duplicate create ids become `id_1`. |
332
- | `board_snapshot` | Browser PNG. Defaults: viewport, scale 2, labels on, 32 colors, 240 KiB. |
333
- | `board_view_fit` | Browser camera. Optional `ids`. |
330
+ | Tool | Use |
331
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
332
+ | `board_describe` | Text with IDs. Start here. |
333
+ | `board_read` | Deep JSON copy. Headless accepts only `scope: 'doc'`. |
334
+ | `board_query` | Same filters as `query`. |
335
+ | `board_apply` | Atomic ops. Grows labels, slides directional place, omitted route → elbow. `runTool` forces an `agent:` origin (`agent:tool` if omitted). Duplicate create ids become `id_1`. |
336
+ | `board_snapshot` | Browser PNG. Defaults: viewport, scale 2, labels on, 32 colors, 240 KiB. |
337
+ | `board_view_fit` | Browser camera. Optional `ids`. |
334
338
 
335
339
  `board_snapshot` and `board_view_fit` need a live board.
336
340
 
@@ -1,5 +1,19 @@
1
1
  # Design decisions
2
2
 
3
+ ## 2026-09-20: Elbows miss boxes; place does not stack
4
+
5
+ Agent diagrams go wrong in two cheap ways: several `rightOf` the same node land on one point, and a straight or midpoint elbow walks through the node in between. Orthogonal routing literature (channel + obstacle) and simple packing fix both without a graph layout pass.
6
+
7
+ Elbows stay derived. The default midpoint channel is kept when it is clear. If it hits a box, try the other orientation, then a channel just outside the blocker. Waypoints and non-elbow routes are untouched. Other connectors are not obstacles, so routing cannot cycle.
8
+
9
+ `rightOf` / `leftOf` / `above` / `below` already named an axis. When that slot intersects a solid item, slide further along the same axis by the occupant plus `gap`. `near` and `inside` already searched.
10
+
11
+ An `agent:` connector that omits `route` stores `elbow`. Omitted `route` on disk stays straight.
12
+
13
+ ## 2026-09-20: Agent labeled boxes grow to the text
14
+
15
+ Agents often send catalog defaults or example 200×100 boxes with a paragraph of `text`. The label then overflows. An `agent:` `add` or text `set` on `rect`, `ellipse`, `diamond`, `note`, or `text` grows stored `w`/`h` so the label fits, wrapping long lines at a comfortable width. Standalone `text` defaults to 600 wide so graph titles are not capped at the old 200. User and API origins keep the size they wrote. A larger explicit size is kept. The measurement is a headless heuristic so MCP and the browser store the same box. Browser `agent:` text also sets `autoWidth`. Kind catalog 2 records that create contract.
16
+
3
17
  ## 2026-09-20: Public unfurl hosts
4
18
 
5
19
  Unfurl is a same-browser GET of a user-pasted URL, not a metadata proxy. `isPublicHttpUrl` is a hostname check: it rejects loopback, RFC1918, link-local, ULA, IPv4-mapped IPv6, NAT64, multicast, and names that start with a private IPv4. It does not look up DNS. Preview images from Open Graph go through the same check so a public page cannot point the card at a private URL. The local Vite `/__ad-unfurl` plugin additionally resolves A/AAAA records and refuses private answers. Hosts that need stricter policy pass `unfurl: false` or their own function.
@@ -70,7 +84,7 @@ Version 2 uses pages in the document, scopes, and editing API. Version 1 documen
70
84
 
71
85
  ## 2026-09-19: Toolbar and inspector layout
72
86
 
73
- Keep primary drawing tools on the sidebar: eraser after hand, image after sticky note, and line and arrow inside Shapes. Do not hide those tools behind a More overflow. On phones, including landscape, and on short tablet-width hosts, the tools move to a bottom bar and hand stays in the board menu so that bar remains tappable, unless a host hides that menu. A short desktop host keeps the tool sidebar and inspector vertically centered and tightens chrome padding and icons instead of pinning those bars to the top. The selection inspector is vertically centered like the tool sidebar. Export downloads the current page. An imported board offers PNG and SVG; AnnieDoc is opt-in through `ui.export`. The local demo offers all three. The AnnieDrawing control opens the same kind of menu for document, appearance, documentation, and GitHub, with the package version at the bottom, and hosts may hide it. Show item-specific style controls only when something is selected, with palettes opened on demand and compact line and text controls visible beside the selection. The inspector does not repeat the selected kind as a title. Page management remains in the bottom bar. Positioning and rotation follow the user's pointer. Shift constrains the move axis or resize proportions.
87
+ Keep primary drawing tools on the sidebar: eraser after hand, image after sticky note, and line and arrow inside Shapes. Do not hide those tools behind a More overflow. On phones, including landscape, and on short tablet-width hosts, the tools move to a bottom bar and hand stays in the board menu so that bar remains tappable, unless a host hides that menu. Pages, zoom, undo, redo, and Export live in a Board controls menu at the top right so they do not compete with that bar. A short desktop host keeps the tool sidebar and inspector vertically centered and tightens chrome padding and icons instead of pinning those bars to the top. That tighter chrome starts at 640px host height when the AnnieDrawing menu or page chips are present. Without those bars, 640px pulls the sidebar inward and uses a middle tool size; tools and buttons fully shrink at 500px. The selection inspector is vertically centered like the tool sidebar. Export downloads the current page. An imported board offers PNG and SVG; AnnieDoc is opt-in through `ui.export`. The local demo offers all three. The AnnieDrawing control opens the same kind of menu for document, appearance, documentation, and GitHub, with the package version at the bottom, and hosts may hide it. Show item-specific style controls only when something is selected, with palettes opened on demand and compact line and text controls visible beside the selection. The inspector does not repeat the selected kind as a title. Page management remains in the bottom bar. Positioning and rotation follow the user's pointer. Shift constrains the move axis or resize proportions.
74
88
 
75
89
  ## 2026-09-19: MIT licensing and the named package
76
90
 
@@ -105,3 +119,9 @@ Portable SVG and PNG cannot keep a live player or a working Open control. Export
105
119
  ## 2026-09-19: Publish-facing library surface
106
120
 
107
121
  Package entry points export the documented API, not every helper in a folder. Host page chrome (`html`, `body`, `#app`) belongs in the demo stylesheet; `anniedrawing/style.css` styles the editor host only. Draft merges, copies, translation, and connector detach share one implementation. Comments mark non-obvious contracts. Tests cover invariants, not restated implementation.
122
+
123
+ ## 2026-09-20: Human pointing and revision-checked edits
124
+
125
+ Expose pointing through the browser board as transient page-space state, separate from the animated agent cursor and document JSON. Report inside/outside and age instead of guessing that a previous pointer is still current. Hosts decide whether a historical point answers “here.”
126
+
127
+ Put optional optimistic concurrency in the shared `apply` boundary, not in each host adapter. `expectedRevision` is checked before any operation, including lenient batches and previews. This is a session guard, not a persistent document version; document replacement resets it.
@@ -42,7 +42,7 @@ The model expands defaults internally and omits default style flags on serializa
42
42
 
43
43
  Built-in kinds: `rect`, `ellipse`, `diamond`, `line`, `connector`, `path`, `text`, `note`, `image`, `video`, `link`, `group`, and `html`. Unknown kinds are kept and shown as a placeholder. Load and save do not drop custom content.
44
44
 
45
- Default sizes when `w` and `h` are omitted: rect and ellipse 180×110, diamond 160×140, line 180×0, connector 0×0, path 0×0, text 200×48, note 200×180, image 240×180, video 480×270, link 220×200, group 0×0, html 240×160.
45
+ Default sizes when `w` and `h` are omitted: rect and ellipse 180×110, diamond 160×140, line 180×0, connector 0×0, path 0×0, text 600×48, note 200×180, image 240×180, video 480×270, link 220×200, group 0×0, html 240×160. An `agent:` create or text patch on `rect`, `ellipse`, `diamond`, `note`, or `text` may store a larger size so the label fits.
46
46
 
47
47
  `text` has a plain `value`, horizontal `align` (`start`, `center`, `end`), vertical `valign` (`top`, `middle`, `bottom`), `size` (`s`, `m`, `l`, `xl`, or a number from 1 to 1000), and `font` (`sans`, `serif`, `mono`, `hand`). Omitted `font` is `hand`, the handwritten Comic Sans-like stack. `autoWidth: true` on a browser `text` item stores measured width and height.
48
48
 
@@ -54,7 +54,7 @@ Named colors: `ink`, `slate`, `coral`, `amber`, `moss`, `teal`, `sky`, `violet`,
54
54
 
55
55
  ## Connectors and paths
56
56
 
57
- A connector has `from` and `to`. Each stored end is either `{ "item": "i_note", "side": "right" }` or a free `{ "x": 100, "y": 200 }` point. `apply` also accepts a string item id, stored as `{ item, side: "auto" }`. `side` is `auto`, `top`, `right`, `bottom`, or `left`. An attached endpoint can use a normalized `anchor: [0, 0.5]`. Routes are `straight`, `elbow`, or `curve`. Heads accept `none`, `arrow`, or `dot`. Optional `waypoints` are page-space `[x, y]` points between the ends. When a target disappears, that endpoint becomes a free point at its last position in the same atomic edit.
57
+ A connector has `from` and `to`. Each stored end is either `{ "item": "i_note", "side": "right" }` or a free `{ "x": 100, "y": 200 }` point. `apply` also accepts a string item id, stored as `{ item, side: "auto" }`. `side` is `auto`, `top`, `right`, `bottom`, or `left`. An attached endpoint can use a normalized `anchor: [0, 0.5]`. Routes are `straight`, `elbow`, or `curve`. An `agent:` create that omits `route` stores `elbow`. Omitted `route` in a saved file stays `straight`. Elbows pick a channel that misses intervening boxes. Heads accept `none`, `arrow`, or `dot`. Optional `waypoints` are page-space `[x, y]` points between the ends. When a target disappears, that endpoint becomes a free point at its last position in the same atomic edit.
58
58
 
59
59
  Line and freehand `points` are relative to the item's `x` and `y`. Freehand points may include pressure: `[x, y, pressure]`. `closed: true` closes a path. Item IDs and connector bindings survive moves and export or import.
60
60
 
@@ -706,10 +706,10 @@ board.apply([{ op: 'add', item: {
706
706
  to open its inspector. Fill, Line, and Color choose colors. Line also sets thickness and
707
707
  pattern. Text-capable shapes show size, alignment, and font. A selected video or link
708
708
  card can change its URL from the inspector. More arrangement options opens align,
709
- distribute, group, and stacking. Pages lists pages. The AnnieDrawing menu holds
710
- appearance, documentation, GitHub, and the package version unless the host hides it.
711
- This demo's Export control offers PNG, SVG, and AnnieDoc; an imported board defaults to
712
- PNG and SVG.
709
+ distribute, group, and stacking. Pages lists pages. On a phone, pages, zoom, undo, redo,
710
+ and Export open from Board controls. The AnnieDrawing menu holds appearance,
711
+ documentation, GitHub, and the package version unless the host hides it. This demo's
712
+ Export control offers PNG, SVG, and AnnieDoc; an imported board defaults to PNG and SVG.
713
713
  </p>
714
714
  <div class="shortcut-grid">
715
715
  <div class="shortcut"><span>Select / move</span><kbd>V</kbd></div>
@@ -787,8 +787,13 @@ board.apply([{ op: 'add', item: {
787
787
  <code>order</code>, and <code>reparent</code>, plus page, media, and document metadata
788
788
  changes. <code>place</code> takes exactly one of <code>rightOf</code>,
789
789
  <code>leftOf</code>, <code>above</code>, <code>below</code>, <code>inside</code>, or
790
- <code>near</code>. A dry run validates a batch without saving it. Failed batches apply
791
- nothing.
790
+ <code>near</code>. Directional <code>place</code> slides further along that axis when
791
+ the first slot is occupied. An <code>agent:</code> create or text patch on
792
+ <code>rect</code>, <code>ellipse</code>, <code>diamond</code>, <code>note</code>, or
793
+ <code>text</code> grows the stored size so the label fits. Standalone
794
+ <code>text</code> defaults to 600 wide. An <code>agent:</code> connector that omits
795
+ <code>route</code> stores <code>elbow</code>. Elbows go around intervening boxes. A dry
796
+ run validates a batch without saving it. Failed batches apply nothing.
792
797
  </p>
793
798
  <div class="link-row">
794
799
  <a class="pill" href="api.md">API reference</a
@@ -800,7 +805,10 @@ board.apply([{ op: 'add', item: {
800
805
  <h2>Agents</h2>
801
806
  <p>
802
807
  The document is JSON with stable item IDs. An agent can describe the scene, query items,
803
- and apply a batch. Every batch succeeds together or changes nothing. This demo sets
808
+ and apply a batch. Every batch succeeds together or changes nothing. An
809
+ <code>agent:</code> origin grows labeled boxes and titles to fit text, slides
810
+ directional <code>place</code> when a slot is taken, and stores <code>elbow</code> on
811
+ connectors that omit <code>route</code>. Elbows miss intervening boxes. This demo sets
804
812
  <code>exposeGlobal: true</code> so the board is on <code>window.__anniedrawing</code>.
805
813
  Other hosts must pass that option.
806
814
  </p>
@@ -2,7 +2,7 @@
2
2
 
3
3
  Operate a live or headless board through JavaScript. This is the full AI reference for creating items and reading what is on the board. It does not cover installing, running, or changing the library.
4
4
 
5
- Kind catalog: 1
5
+ Kind catalog: 2
6
6
 
7
7
  `kindsSince(since?)` lists built-in kinds added or last changed after that catalog version. Omit `since`, or pass `0`, to list every built-in kind. Remember the returned `version` and pass it next time you want only what is new.
8
8
 
@@ -32,12 +32,12 @@ const board = createDoc();
32
32
 
33
33
  ```js
34
34
  board.kindsSince(); // every built-in kind; same as board.kindsSince(0)
35
- board.kindsSince(1); // kinds added or changed after catalog 1 (empty today)
35
+ board.kindsSince(1); // kinds added or changed after catalog 1
36
36
  ```
37
37
 
38
38
  Also exported as `kindsSince` and `CATALOG_VERSION` from `anniedrawing`, `anniedrawing/core`, and `anniedrawing/agent`.
39
39
 
40
- Each entry is `{ kind, since, w, h, note }`. `w` and `h` are the default size when those fields are omitted on `add`. Custom host kinds do not appear here.
40
+ Each entry is `{ kind, since, w, h, note }`. `w` and `h` are the default size when those fields are omitted on `add`. An `agent:` create can store a larger box so `text` fits. An `agent:` connector that omits `route` stores `elbow`. Custom host kinds do not appear here.
41
41
 
42
42
  The catalog version is independent of the `.annie` document format version (`2`) and the package version.
43
43
 
@@ -68,6 +68,8 @@ board.toJSON(); // portable document
68
68
 
69
69
  DOM nodes may show `[data-ad-id]` and `[data-ad-kind]`. Do not treat DOM edits as a write API.
70
70
 
71
+ `board.getPointer()` returns a copy of the last human pointer: `{ x, y, pageId, inside, pointerType, ageMs, itemId }`, or `null` before a pointer is observed, after a page switch, or after destruction. Coordinates are page-space. While `inside` is true they follow pan and zoom; `itemId` is the topmost hittable item or `null`. Editor controls are excluded. Leaving, blur, hidden tabs, cancel, or touch release sets `inside: false` and preserves the last point. `ageMs` measures time since the last pointer event, not camera changes. Treat an outside point as historical; ask the user to point again when ambiguous. Pointer state is never serialized.
72
+
71
73
  ## Write
72
74
 
73
75
  ```js
@@ -81,6 +83,8 @@ const result = board.apply(ops, {
81
83
  // { ok, created, errors, warnings, skipped? }
82
84
  ```
83
85
 
86
+ Pass `expectedRevision` from the read that informed an edit to `apply` or `board_apply`. A mismatch returns `STALE_REVISION` without applying any operation, including in lenient or dry-run mode. Read again before retrying. This guards one session only: `load()` and `clear()` reset revisions.
87
+
84
88
  A failed batch changes nothing. `dryRun: true` validates and does not write. It does not reserve IDs. Do not call `load()` to patch a few items. Do not set `merge: true` unless you intend to fold this commit into the previous history entry with the same origin and label. `lenient: true` is available on `apply` only.
85
89
 
86
90
  Use stable IDs when later operations in the same batch need to reference new items. Generated prefixes are `i_`, `p_`, and `m_`.
@@ -89,7 +93,7 @@ Operations: `add`, `set`, `remove`, `order`, `reparent`, `page.add`, `page.set`,
89
93
 
90
94
  `set` merges `style`, `text`, and `data` one level deep. Other fields are replaced. Do not change `id` with `set`. `order.to` is `front`, `back`, `forward`, `backward`, or a numeric index.
91
95
 
92
- `add` accepts `page`, `parent`, `index`, and `place`. `place` needs exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. Kind aliases: `rectangle` stores `rect`; `arrow` stores `connector` with an end arrow. `from` / `to` accept `{ item, side }`, `{ x, y }`, or a string item id.
96
+ `add` accepts `page`, `parent`, `index`, and `place`. `place` needs exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. `rightOf` / `leftOf` / `above` / `below` slide further along that axis when the first slot is occupied. Kind aliases: `rectangle` stores `rect`; `arrow` stores `connector` with an end arrow. `from` / `to` accept `{ item, side }`, `{ x, y }`, or a string item id. An `agent:` connector that omits `route` stores `elbow`. Elbows go around intervening boxes.
93
97
 
94
98
  `OVERLAPS_EXISTING` and `ID_REMAPPED` are warnings. The batch still committed. An `agent:` create that reuses an id is stored as `id_1`, then `_2`. Same-batch `place`, parent, and connector refs follow the stored id. `get` with the id you sent returns the older item. User and API origins still reject duplicates.
95
99
 
@@ -175,7 +179,7 @@ Named colors: `ink`, `slate`, `coral`, `amber`, `moss`, `teal`, `sky`, `violet`,
175
179
 
176
180
  ## Built-in kinds
177
181
 
178
- Omit `w` / `h` to use the default size in the catalog.
182
+ Omit `w` / `h` to use the default size in the catalog. An `agent:` create or text patch on `rect`, `ellipse`, `diamond`, `note`, or `text` grows the stored size so the label fits. Standalone `text` defaults to 600 wide. A larger explicit size is kept.
179
183
 
180
184
  ### `rect`
181
185
 
@@ -209,7 +213,7 @@ Omit `w` / `h` to use the default size in the catalog.
209
213
 
210
214
  ### `connector`
211
215
 
212
- `from` / `to` are `{ item, side?, anchor? }`, `{ x, y }`, or a string item id stored as `{ item, side: 'auto' }`. `side` is `auto` / `top` / `right` / `bottom` / `left`. `route` is `straight` / `elbow` / `curve`. Heads: `none` / `arrow` / `dot`. Optional `waypoints` are page-space `[x, y]`. Bound ends detach to their last point when the target disappears. `kind: 'arrow'` stores `connector` with an end arrow.
216
+ `from` / `to` are `{ item, side?, anchor? }`, `{ x, y }`, or a string item id stored as `{ item, side: 'auto' }`. `side` is `auto` / `top` / `right` / `bottom` / `left`. `route` is `straight` / `elbow` / `curve`. Heads: `none` / `arrow` / `dot`. Optional `waypoints` are page-space `[x, y]`. An `agent:` create that omits `route` stores `elbow`. Elbows pick a channel that misses intervening boxes. Bound ends detach to their last point when the target disappears. `kind: 'arrow'` stores `connector` with an end arrow.
213
217
 
214
218
  ```js
215
219
  { op: 'add', item: { id: 'i_flow', kind: 'connector',
@@ -229,11 +233,11 @@ Freehand points may include pressure: `[x, y, pressure]`. `closed: true` closes
229
233
  ### `text`
230
234
 
231
235
  ```js
232
- { op: 'add', item: { id: 'i_title', kind: 'text', x: 80, y: 40, w: 280, h: 48,
236
+ { op: 'add', item: { id: 'i_title', kind: 'text', x: 80, y: 40,
233
237
  text: { value: 'Architecture', size: 'l', align: 'start' } } }
234
238
  ```
235
239
 
236
- A browser `text` item with `autoWidth: true` stores measured width and height. Headless documents keep the stored size.
240
+ Omitted `w` is 600. A browser `text` item with `autoWidth: true` (set for `agent:` creates) stores measured width and height. Headless documents keep the stored or grown size.
237
241
 
238
242
  ### `note`
239
243
 
@@ -323,14 +327,14 @@ PNG `labels: true` draws item IDs for vision models and defaults to a 32-color i
323
327
 
324
328
  Optional wrapper around the same APIs. Import `toolDefs` and `runTool` from `anniedrawing/agent`. Map `name`, `description`, and `inputSchema` into the provider envelope. Do not change the operations schema.
325
329
 
326
- | Tool | Use |
327
- | ---------------- | -------------------------------------------------------------------------------------------------------------- |
328
- | `board_describe` | Text with IDs. Start here. |
329
- | `board_read` | Deep JSON copy. Headless accepts only `scope: 'doc'`. |
330
- | `board_query` | Same filters as `query`. |
331
- | `board_apply` | Atomic ops. `runTool` forces an `agent:` origin (`agent:tool` if omitted). Duplicate create ids become `id_1`. |
332
- | `board_snapshot` | Browser PNG. Defaults: viewport, scale 2, labels on, 32 colors, 240 KiB. |
333
- | `board_view_fit` | Browser camera. Optional `ids`. |
330
+ | Tool | Use |
331
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
332
+ | `board_describe` | Text with IDs. Start here. |
333
+ | `board_read` | Deep JSON copy. Headless accepts only `scope: 'doc'`. |
334
+ | `board_query` | Same filters as `query`. |
335
+ | `board_apply` | Atomic ops. Grows labels, slides directional place, omitted route → elbow. `runTool` forces an `agent:` origin (`agent:tool` if omitted). Duplicate create ids become `id_1`. |
336
+ | `board_snapshot` | Browser PNG. Defaults: viewport, scale 2, labels on, 32 colors, 240 KiB. |
337
+ | `board_view_fit` | Browser camera. Optional `ids`. |
334
338
 
335
339
  `board_snapshot` and `board_view_fit` need a live board.
336
340
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Operate a board through JavaScript. The JSON document is the source of truth. People and agents commit through `apply(ops, options)`. This file does not cover installing or changing the library. Full examples: [board JavaScript](board-js.md) / [llms-full.txt](llms-full.txt).
4
4
 
5
- Kind catalog: 1
5
+ Kind catalog: 2
6
6
 
7
7
  ```js
8
8
  const board = window.__anniedrawing[0]; // demo; hosts pass exposeGlobal: true
@@ -20,32 +20,36 @@ board.query({ kind: 'arrow' }); // matches stored connector created as arrow
20
20
 
21
21
  Reads return copies. Mutating them does not edit the board.
22
22
 
23
+ `board.getPointer()` returns a copy of the last human pointer: `{ x, y, pageId, inside, pointerType, ageMs, itemId }`, or `null` before a pointer is observed, after a page switch, or after destruction. Coordinates are page-space. While `inside` is true they follow pan and zoom; `itemId` is the topmost hittable item or `null`. Editor controls are excluded. Leaving, blur, hidden tabs, cancel, or touch release sets `inside: false` and preserves the last point. `ageMs` measures time since the last pointer event, not camera changes. Treat an outside point as historical; ask the user to point again when ambiguous. Pointer state is never serialized.
24
+
23
25
  ## Write
24
26
 
25
27
  ```
26
28
  board.apply(ops, { origin: 'agent:name', label: 'What changed', dryRun?: false, agentName?: 'Name', reveal?: 'fit' })
27
29
  ```
28
30
 
31
+ Pass `expectedRevision` from the read that informed an edit to `apply` or `board_apply`. A mismatch returns `STALE_REVISION` without applying any operation, including in lenient or dry-run mode. Read again before retrying. This guards one session only: `load()` and `clear()` reset revisions.
32
+
29
33
  Operations: `add`, `set`, `remove`, `order`, `reparent`, `page.add`, `page.set`, `page.remove`, `meta.set`, `media.set`, `media.remove`. A failed batch changes nothing. `set` merges `style`, `text`, and `data` one level deep. Do not change `id` with `set`. `add` accepts `page`, `parent`, `index`, and `place`. `order.to` is `front`, `back`, `forward`, `backward`, or a numeric index. Kind aliases: `rectangle` → `rect`, `arrow` → `connector`. Connector `from`/`to` accept `{ item, side }`, `{ x, y }`, or a string id.
30
34
 
31
- `place` requires exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. Do not call `load()` to patch a few items.
35
+ `place` requires exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. Directional `place` slides further along that axis when the slot is taken. An `agent:` create or text patch on `rect`, `ellipse`, `diamond`, `note`, or `text` grows the stored size so the label fits. Standalone `text` defaults to 600 wide. An `agent:` connector that omits `route` stores `elbow`. Elbows go around intervening boxes. Do not call `load()` to patch a few items.
32
36
 
33
37
  Check `result.ok`, then read `result.created` for stored ids. `OVERLAPS_EXISTING` and `ID_REMAPPED` are warnings; the batch still committed. An `agent:` create that reuses an id is stored as `id_1` (then `_2`); same-batch `place` and connector refs follow that id. `get` with the id you sent returns the older item. User and API origins still reject duplicates.
34
38
 
35
39
  ## Kinds
36
40
 
37
- Built-in kinds, default size when `w`/`h` omitted, catalog `since` 1:
41
+ Built-in kinds, default size when `w`/`h` omitted. `rect`, `ellipse`, `diamond`, `connector`, `note`, and `text` are catalog 2: labeled boxes grow so the label fits; an omitted connector `route` stores `elbow`.
38
42
 
39
43
  | Kind | Size | Create |
40
44
  | ---- | ---- | ------ |
41
- | `rect` | 180×110 | Box or node. `text`, `style`. |
42
- | `ellipse` | 180×110 | Ellipse or circle. |
43
- | `diamond` | 160×140 | Decision or highlight. |
45
+ | `rect` | 180×110 | Box or node. `text`, `style`. Agent creates grow to fit text. |
46
+ | `ellipse` | 180×110 | Ellipse or circle. Agent creates grow to fit text. |
47
+ | `diamond` | 160×140 | Decision or highlight. Agent creates grow to fit text. |
44
48
  | `line` | 180×0 | Segment. Optional `points` relative to x/y. |
45
- | `connector` | 0×0 | `from`/`to` as `{ item, side? }`, `{ x, y }`, or a string item id. `route`: straight/elbow/curve. Compact JSON omits x/y/w/h. |
49
+ | `connector` | 0×0 | `from`/`to` as `{ item, side? }`, `{ x, y }`, or a string item id. `route`: straight/elbow/curve. Agent omit stores elbow. Compact JSON omits x/y/w/h. |
46
50
  | `path` | 0×0 | Freehand. `points` (`[x,y,pressure?]`), optional `closed`. |
47
- | `text` | 200×48 | Plain text. Browser `autoWidth` measures. |
48
- | `note` | 200×180 | Sticky. Default moss fill, 12px corner. |
51
+ | `text` | 600×48 | Plain text. Agent creates grow to fit a title. Browser `autoWidth` measures. |
52
+ | `note` | 200×180 | Sticky. Default moss fill, 12px corner. Agent creates grow to fit text. |
49
53
  | `image` | 240×180 | `media` key in the document media table. |
50
54
  | `video` | 480×270 | YouTube or Vimeo `href`. |
51
55
  | `link` | 220×200 | Website card. `href`, optional `description`. |
@@ -79,7 +83,7 @@ Optional. Import `toolDefs` and `runTool` from `anniedrawing/agent`. Same operat
79
83
  | `board_describe` | Text with IDs. Start here. |
80
84
  | `board_read` | Deep JSON. Headless: `scope: 'doc'` only. |
81
85
  | `board_query` | Filters combine with AND. |
82
- | `board_apply` | Atomic ops. `dryRun` validates without writing. Duplicate agent create ids become `id_1`. |
86
+ | `board_apply` | Atomic ops. Grows labels, slides directional place, omitted route → elbow. `dryRun` validates. Duplicate agent create ids become `id_1`. |
83
87
  | `board_snapshot` | Browser PNG. Defaults: viewport, scale 2, labels on, 32 colors, 240 KiB. |
84
88
  | `board_view_fit` | Browser camera. Optional `ids`. |
85
89
 
package/dist/docs/mcp.md CHANGED
@@ -50,7 +50,7 @@ Page edits use the current `page.*` operations and `page` destination property:
50
50
  }
51
51
  ```
52
52
 
53
- `board_snapshot` and `board_view_fit` return an error in headless mode because they require a browser. Other tools use the same model and schemas as the library. An unsuccessful `board_apply` result becomes a tool result with `isError: true`. A successful agent apply that reuses an item id still commits; the stored id is `id_1` (then `_2`), the result includes `ID_REMAPPED`, and `created` lists the stored ids.
53
+ `board_snapshot` and `board_view_fit` return an error in headless mode because they require a browser. Other tools use the same model and schemas as the library. A `board_apply` with an `agent:` origin grows labeled boxes and titles to fit text, slides directional `place` when a slot is taken, and stores `elbow` when a connector omits `route`. An unsuccessful `board_apply` result becomes a tool result with `isError: true`. A successful agent apply that reuses an item id still commits; the stored id is `id_1` (then `_2`), the result includes `ID_REMAPPED`, and `created` lists the stored ids.
54
54
 
55
55
  ## Connect a live board
56
56
 
package/dist/fellow.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type BoardOptions } from './board.js';
2
- import type { AgentPresenceOptions, ApplyOptions, ApplyResult, ChangeLog } from './core/types.js';
3
- export type { AgentPresenceOptions, ApplyOptions, ApplyResult, BoardOptions, ChangeLog };
2
+ import type { AgentPresenceOptions, ApplyOptions, ApplyResult, BoardPointer, ChangeLog } from './core/types.js';
3
+ export type { AgentPresenceOptions, ApplyOptions, ApplyResult, BoardOptions, BoardPointer, ChangeLog, };
4
4
  export interface FellowBoardOptions extends BoardOptions {
5
5
  fellowName?: string;
6
6
  }
package/dist/fellow.js CHANGED
@@ -1,2 +1,2 @@
1
- import{n as e}from"./shared/board-DV5lzxNR.js";function a(a,n={}){const{fellowName:t,...o}=n;return e(a,{agentHistory:"hidden",agentReveal:"fit",agentPlaceGap:120,agentPresence:{maxStops:3,durationScale:.55},exposeGlobal:!1,unfurl:!1,ui:{menu:!1,export:!1,pages:!1},...o,agentName:o.agentName??t})}export{a as createFellowBoard};
1
+ import{n as e}from"./shared/board-OPwsZ2_V.js";function a(a,n={}){const{fellowName:t,...o}=n;return e(a,{agentHistory:"hidden",agentReveal:"fit",agentPlaceGap:120,agentPresence:{maxStops:3,durationScale:.55},exposeGlobal:!1,unfurl:!1,ui:{menu:!1,export:!1,pages:!1},...o,agentName:o.agentName??t})}export{a as createFellowBoard};
2
2
  //# sourceMappingURL=fellow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fellow.js","names":[],"sources":["../src/fellow.ts"],"sourcesContent":["import { createBoard, type BoardOptions } from './board';\nimport type { AgentPresenceOptions, ApplyOptions, ApplyResult, ChangeLog } from './core/types';\n\nexport type { AgentPresenceOptions, ApplyOptions, ApplyResult, BoardOptions, ChangeLog };\n\nexport interface FellowBoardOptions extends BoardOptions {\n fellowName?: string;\n}\n\nexport function createFellowBoard(host: HTMLElement, options: FellowBoardOptions = {}) {\n const { fellowName, ...rest } = options;\n return createBoard(host, {\n agentHistory: 'hidden',\n agentReveal: 'fit',\n agentPlaceGap: 120,\n agentPresence: { maxStops: 3, durationScale: 0.55 },\n exposeGlobal: false,\n unfurl: false,\n ui: { menu: false, export: false, pages: false },\n ...rest,\n agentName: rest.agentName ?? fellowName,\n });\n}\n"],"mappings":"+CASA,SAAgB,EAAkB,EAAmB,EAA8B,CAAC,GAClF,MAAM,WAAE,KAAe,GAAS,EAChC,OAAO,EAAY,EAAM,CACvB,aAAc,SACd,YAAa,MACb,cAAe,IACf,cAAe,CAAE,SAAU,EAAG,cAAe,KAC7C,cAAc,EACd,QAAQ,EACR,GAAI,CAAE,MAAM,EAAO,QAAQ,EAAO,OAAO,MACtC,EACH,UAAW,EAAK,WAAa,GAEjC"}
1
+ {"version":3,"file":"fellow.js","names":[],"sources":["../src/fellow.ts"],"sourcesContent":["import { createBoard, type BoardOptions } from './board';\nimport type {\n AgentPresenceOptions,\n ApplyOptions,\n ApplyResult,\n BoardPointer,\n ChangeLog,\n} from './core/types';\n\nexport type {\n AgentPresenceOptions,\n ApplyOptions,\n ApplyResult,\n BoardOptions,\n BoardPointer,\n ChangeLog,\n};\n\nexport interface FellowBoardOptions extends BoardOptions {\n fellowName?: string;\n}\n\nexport function createFellowBoard(host: HTMLElement, options: FellowBoardOptions = {}) {\n const { fellowName, ...rest } = options;\n return createBoard(host, {\n agentHistory: 'hidden',\n agentReveal: 'fit',\n agentPlaceGap: 120,\n agentPresence: { maxStops: 3, durationScale: 0.55 },\n exposeGlobal: false,\n unfurl: false,\n ui: { menu: false, export: false, pages: false },\n ...rest,\n agentName: rest.agentName ?? fellowName,\n });\n}\n"],"mappings":"+CAsBA,SAAgB,EAAkB,EAAmB,EAA8B,CAAC,GAClF,MAAM,WAAE,KAAe,GAAS,EAChC,OAAO,EAAY,EAAM,CACvB,aAAc,SACd,YAAa,MACb,cAAe,IACf,cAAe,CAAE,SAAU,EAAG,cAAe,KAC7C,cAAc,EACd,QAAQ,EACR,GAAI,CAAE,MAAM,EAAO,QAAQ,EAAO,OAAO,MACtC,EACH,UAAW,EAAK,WAAa,GAEjC"}
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{b as s,v as a,y as r}from"./shared/defaults-C-aC_B4z.js";import{i as o,n as t,r as d,t as e}from"./shared/board-DV5lzxNR.js";export{e as Board,a as CATALOG_VERSION,r as KIND_CATALOG,t as createBoard,d as defineKind,s as kindsSince,o as registerKind};
1
+ import{b as s,v as a,y as r}from"./shared/defaults-DZEoAeRz.js";import{i as o,n as t,r as d,t as e}from"./shared/board-OPwsZ2_V.js";export{e as Board,a as CATALOG_VERSION,r as KIND_CATALOG,t as createBoard,d as defineKind,s as kindsSince,o as registerKind};