pmx-canvas 0.1.15 → 0.1.17
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/CHANGELOG.md +124 -0
- package/Readme.md +2 -2
- package/dist/canvas/global.css +25 -0
- package/dist/canvas/index.js +72 -72
- package/dist/types/client/canvas/AnnotationLayer.d.ts +4 -0
- package/dist/types/client/canvas/CanvasViewport.d.ts +4 -1
- package/dist/types/client/canvas/use-pan-zoom.d.ts +2 -1
- package/dist/types/client/icons.d.ts +4 -0
- package/dist/types/client/nodes/ContextNode.d.ts +11 -2
- package/dist/types/client/nodes/StatusNode.d.ts +1 -0
- package/dist/types/client/state/canvas-store.d.ts +22 -3
- package/dist/types/client/state/intent-bridge.d.ts +2 -0
- package/dist/types/client/types.d.ts +20 -0
- package/dist/types/mcp/canvas-access.d.ts +1 -0
- package/dist/types/server/canvas-serialization.d.ts +23 -1
- package/dist/types/server/canvas-state.d.ts +27 -1
- package/dist/types/server/index.d.ts +7 -2
- package/dist/types/server/mutation-history.d.ts +1 -1
- package/dist/types/server/spatial-analysis.d.ts +11 -2
- package/package.json +1 -1
- package/skills/pmx-canvas/SKILL.md +17 -0
- package/src/cli/agent.ts +6 -0
- package/src/client/App.tsx +60 -3
- package/src/client/canvas/AnnotationLayer.tsx +28 -0
- package/src/client/canvas/CanvasViewport.tsx +169 -10
- package/src/client/canvas/ContextPinBar.tsx +3 -1
- package/src/client/canvas/DockedNode.tsx +4 -3
- package/src/client/canvas/use-pan-zoom.ts +10 -5
- package/src/client/icons.tsx +22 -0
- package/src/client/nodes/ContextNode.tsx +128 -6
- package/src/client/nodes/StatusNode.tsx +16 -1
- package/src/client/nodes/StatusSummary.tsx +2 -1
- package/src/client/state/canvas-store.ts +65 -7
- package/src/client/state/intent-bridge.ts +5 -1
- package/src/client/state/sse-bridge.ts +36 -2
- package/src/client/theme/global.css +25 -0
- package/src/client/types.ts +17 -0
- package/src/mcp/canvas-access.ts +10 -0
- package/src/mcp/server.ts +35 -4
- package/src/server/canvas-schema.ts +25 -0
- package/src/server/canvas-serialization.ts +69 -1
- package/src/server/canvas-state.ts +74 -2
- package/src/server/diagram-presets.ts +54 -19
- package/src/server/index.ts +20 -3
- package/src/server/mutation-history.ts +2 -0
- package/src/server/server.ts +101 -3
- package/src/server/spatial-analysis.ts +46 -1
- package/src/shared/semantic-attention.ts +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,128 @@
|
|
|
3
3
|
All notable changes to `pmx-canvas` are documented here. This project follows
|
|
4
4
|
[Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [0.1.17] - 2026-05-04
|
|
7
|
+
|
|
8
|
+
Adds a freehand annotation layer so humans can draw directly on the
|
|
9
|
+
canvas and agents read compact spatial annotation context (bounds,
|
|
10
|
+
target nodes, optional label) without seeing the raw ink. Excalidraw
|
|
11
|
+
bound-text → label hoisting now covers the full set of canonical and
|
|
12
|
+
shorthand shapes the hosted app emits, and the `html` node type gets
|
|
13
|
+
its first-class entry in `canvas_describe_schema` plus a CLI
|
|
14
|
+
`--content` alias that maps to `data.html`.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Freehand canvas annotations.** A new top-level annotation layer
|
|
19
|
+
lets humans draw freehand strokes on the canvas with pen and
|
|
20
|
+
eraser tools wired into the toolbar. Annotations live alongside
|
|
21
|
+
nodes and edges in `canvasState` (their own `addAnnotation` /
|
|
22
|
+
`removeAnnotation` history operations), persist into snapshots,
|
|
23
|
+
and are rendered as SVG paths whose default `currentColor` stroke
|
|
24
|
+
follows the active theme via a new `--c-annotation` token.
|
|
25
|
+
Surfaces:
|
|
26
|
+
- HTTP: `POST /api/canvas/annotation`, `DELETE
|
|
27
|
+
/api/canvas/annotation/:id`.
|
|
28
|
+
- MCP: `canvas_remove_annotation` (the canvas now exposes 41 MCP
|
|
29
|
+
tools, was 40).
|
|
30
|
+
- Client: pen / eraser toolbar buttons with theme-aware iconography
|
|
31
|
+
and an `AnnotationLayer` that renders the strokes.
|
|
32
|
+
- **Spatial annotation context for agents.** Each pinned-context /
|
|
33
|
+
spatial-context read now includes a compact
|
|
34
|
+
`SpatialAnnotationContext` per annotation: `id`, `label`,
|
|
35
|
+
`bounds`, `targetNodeIds`, `targetNodeTitles`, and `target`
|
|
36
|
+
summary. Agents see what the annotation *circles* (which nodes it
|
|
37
|
+
overlaps), not the freehand path itself, keeping the read budget
|
|
38
|
+
small while still letting the agent act on the human's intent.
|
|
39
|
+
- **HTML node schema entry in `canvas_describe_schema`.** The `html`
|
|
40
|
+
node type added in 0.1.15 now appears in the schema tour with a
|
|
41
|
+
documented `html` field, `--content` / `--stdin` aliases, the
|
|
42
|
+
sandboxed-iframe note, and an example payload.
|
|
43
|
+
- **CLI `--content` alias for HTML nodes.** `pmx-canvas node add
|
|
44
|
+
--type html --content '<main>Hello</main>'` is accepted as a
|
|
45
|
+
shorthand for setting `data.html` (also supported via `--stdin`).
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **Excalidraw bound-text → container label hoisting now covers
|
|
50
|
+
every canonical shape.** The diagram preset
|
|
51
|
+
(`normalizeExcalidrawElementsForToolInput`) hoists text into a
|
|
52
|
+
`rectangle` / `ellipse` / `diamond` container's `label` for all
|
|
53
|
+
four patterns the hosted app emits: the canonical
|
|
54
|
+
`containerId`-pointing text, the centered-container variant,
|
|
55
|
+
pre-existing shorthand labels (preserved as-is), and the
|
|
56
|
+
`boundElements`-only path where the text lacks a back-reference.
|
|
57
|
+
Text alignment and vertical-alignment hints are forwarded into
|
|
58
|
+
the label when present.
|
|
59
|
+
|
|
60
|
+
### Internal
|
|
61
|
+
|
|
62
|
+
- Regression coverage for: annotation persistence and removal in
|
|
63
|
+
`canvasState`, annotation undo/redo history operations,
|
|
64
|
+
annotation create/delete over HTTP, html-content CLI alias
|
|
65
|
+
mapping, all four Excalidraw bound-text patterns, html node
|
|
66
|
+
rendering from server state in the browser (e2e), annotation
|
|
67
|
+
theme contrast plus eraser flow (e2e), and annotation toolbar
|
|
68
|
+
actions preserving the active light theme (e2e).
|
|
69
|
+
|
|
70
|
+
## [0.1.16] - 2026-05-04
|
|
71
|
+
|
|
72
|
+
Live-context-dock and undo-history hygiene pass on top of 0.1.15. The
|
|
73
|
+
context dock now renders the actual pinned nodes instead of falling back
|
|
74
|
+
to stale context-card data, auto-focus from ext-app opens stops
|
|
75
|
+
polluting undo history, and a couple of HTTP endpoints reject malformed
|
|
76
|
+
payloads instead of creating blank or empty nodes.
|
|
77
|
+
|
|
78
|
+
### Added
|
|
79
|
+
|
|
80
|
+
- **`ContextNode` renders the active pinned nodes.** A new exported
|
|
81
|
+
`normalizePinnedContextDisplay()` produces a stable `{id, title,
|
|
82
|
+
summary, kind, path}` shape per pinned node, and the component now
|
|
83
|
+
takes a `pinnedNodes` prop. The dock falls back to the previous
|
|
84
|
+
context-card data only when no nodes are pinned, so what the agent
|
|
85
|
+
reads via `canvas://pinned-context` and what the human sees in the
|
|
86
|
+
dock are now the same view.
|
|
87
|
+
- **`StatusNode` exposes `getStatusDisplayPhase()` with a documented
|
|
88
|
+
fallback chain.** The display phase falls back `phase → content
|
|
89
|
+
→ status → 'idle'` and is shared by the inline node, the summary,
|
|
90
|
+
and any consumer that needs the phase shown to the user.
|
|
91
|
+
|
|
92
|
+
### Changed
|
|
93
|
+
|
|
94
|
+
- **`ContextPinBar` is mutually exclusive with the Updates panel.**
|
|
95
|
+
Like the docked context node, the floating pin bar now hides while
|
|
96
|
+
the right-edge attention history panel is open so the two surfaces
|
|
97
|
+
no longer collide on the same anchor.
|
|
98
|
+
- **Browser-driven viewport updates support `recordHistory: false`.**
|
|
99
|
+
Client `focusNode(id, options)` and the matching
|
|
100
|
+
`commitViewportWithOptions()` thread an optional
|
|
101
|
+
`{ recordHistory: false }` flag through to `POST
|
|
102
|
+
/api/canvas/viewport`, which now wraps the mutation in
|
|
103
|
+
`withSuppressedRecording` when the flag is set. Auto-focus
|
|
104
|
+
triggered by ext-app opens uses this path so opening an external
|
|
105
|
+
app no longer fills undo history with viewport churn.
|
|
106
|
+
|
|
107
|
+
### Fixed
|
|
108
|
+
|
|
109
|
+
- **HTML nodes reject non-string `html` payloads.** `POST
|
|
110
|
+
/api/canvas/node` and the matching MCP path now return a 400
|
|
111
|
+
with a clear error when an html node is created with `html` (or
|
|
112
|
+
`data.html`) set to a non-string value, instead of accepting the
|
|
113
|
+
payload and producing a blank node.
|
|
114
|
+
- **Group creation rejects missing child IDs.** `POST
|
|
115
|
+
/api/canvas/group` (and `canvas_create_group`) no longer silently
|
|
116
|
+
creates an empty group when one or more of the requested children
|
|
117
|
+
do not exist; it returns a 400 listing the missing IDs.
|
|
118
|
+
|
|
119
|
+
### Internal
|
|
120
|
+
|
|
121
|
+
- Regression coverage for: client status-node display-phase fallback,
|
|
122
|
+
ext-app auto-focus history suppression on the client side, the
|
|
123
|
+
context dock rendering pinned nodes (e2e), HTML-node payload type
|
|
124
|
+
validation over HTTP, group-create child-presence validation over
|
|
125
|
+
HTTP, and the `recordHistory: false` flag on the viewport
|
|
126
|
+
endpoint.
|
|
127
|
+
|
|
6
128
|
## [0.1.15] - 2026-05-03
|
|
7
129
|
|
|
8
130
|
A bigger release focused on right-sizing what flows through MCP and the
|
|
@@ -605,6 +727,8 @@ otherwise have to discover by trial and error.
|
|
|
605
727
|
- Regression coverage for snapshot flat-`id` aliases on both MCP and
|
|
606
728
|
HTTP surfaces, plus async / top-level-`await` WebView script bodies.
|
|
607
729
|
|
|
730
|
+
[0.1.17]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.17
|
|
731
|
+
[0.1.16]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.16
|
|
608
732
|
[0.1.15]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.15
|
|
609
733
|
[0.1.14]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.14
|
|
610
734
|
[0.1.13]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.13
|
package/Readme.md
CHANGED
|
@@ -58,7 +58,7 @@ the canvas durable rather than throwaway.
|
|
|
58
58
|
|
|
59
59
|
### 05 / Any agent
|
|
60
60
|
|
|
61
|
-
Harness-agnostic. Drive the canvas from [MCP](docs/mcp.md) (
|
|
61
|
+
Harness-agnostic. Drive the canvas from [MCP](docs/mcp.md) (41 tools,
|
|
62
62
|
8 resources, change notifications), the [CLI](docs/cli.md), the
|
|
63
63
|
[HTTP API](docs/http-api.md), or the [Bun SDK](docs/sdk.md). Works with
|
|
64
64
|
Claude Code, GitHub Copilot CLI, Codex, Cursor, Windsurf, or any agent
|
|
@@ -136,7 +136,7 @@ the agent can read `canvas://skills` and pull in companion skills
|
|
|
136
136
|
the three-tier visual matrix (json-render → html → web-artifact)
|
|
137
137
|
- **[CLI reference](docs/cli.md)** — full command surface, daemon mode,
|
|
138
138
|
watch streams, WebView automation
|
|
139
|
-
- **[MCP reference](docs/mcp.md)** —
|
|
139
|
+
- **[MCP reference](docs/mcp.md)** — 41 tools, 8 resources, change
|
|
140
140
|
notifications, node-type routing
|
|
141
141
|
- **[HTTP API](docs/http-api.md)** — REST endpoints, SSE, batch operations
|
|
142
142
|
- **[Bun SDK](docs/sdk.md)** — `createCanvas()` for TypeScript on Bun
|
package/dist/canvas/global.css
CHANGED
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
--c-accent-hover: #6ECAFF;
|
|
51
51
|
--c-warn-hover: #f5d06b;
|
|
52
52
|
--c-canvas-wash: linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(0, 0, 0, 0));
|
|
53
|
+
--c-annotation: #F4EFE6;
|
|
53
54
|
/* ── Non-color tokens ────────────────────────────────────── */
|
|
54
55
|
--font: "IBM Plex Sans", "SF Pro Text", "Avenir Next", system-ui, sans-serif;
|
|
55
56
|
--mono: "IBM Plex Mono", "SF Mono", "Fira Code", monospace;
|
|
@@ -109,6 +110,7 @@
|
|
|
109
110
|
--c-accent-hover: #1588CE;
|
|
110
111
|
--c-warn-hover: #dab040;
|
|
111
112
|
--c-canvas-wash: linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(8, 21, 36, 0.02));
|
|
113
|
+
--c-annotation: #081524;
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
:root[data-theme="high-contrast"] {
|
|
@@ -162,6 +164,7 @@
|
|
|
162
164
|
--c-accent-hover: #33ffff;
|
|
163
165
|
--c-warn-hover: #ffff33;
|
|
164
166
|
--c-canvas-wash: linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0));
|
|
167
|
+
--c-annotation: #ffff00;
|
|
165
168
|
}
|
|
166
169
|
|
|
167
170
|
* {
|
|
@@ -1471,6 +1474,28 @@ body,
|
|
|
1471
1474
|
z-index: 9998;
|
|
1472
1475
|
}
|
|
1473
1476
|
|
|
1477
|
+
.annotation-layer {
|
|
1478
|
+
position: absolute;
|
|
1479
|
+
inset: 0;
|
|
1480
|
+
width: 1px;
|
|
1481
|
+
height: 1px;
|
|
1482
|
+
overflow: visible;
|
|
1483
|
+
pointer-events: none;
|
|
1484
|
+
z-index: 45;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
.annotation-capture-layer {
|
|
1488
|
+
position: absolute;
|
|
1489
|
+
inset: 0;
|
|
1490
|
+
z-index: 9996;
|
|
1491
|
+
pointer-events: none;
|
|
1492
|
+
background: color-mix(in srgb, var(--c-accent) 5%, transparent);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
.annotation-capture-layer.erasing {
|
|
1496
|
+
background: color-mix(in srgb, var(--c-danger) 6%, transparent);
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1474
1499
|
/* ── Drop Zone (file drag-and-drop) ─────────────────────────── */
|
|
1475
1500
|
.drop-zone-overlay {
|
|
1476
1501
|
position: absolute;
|