pmx-canvas 0.1.22 → 0.1.24

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 (53) hide show
  1. package/.github/extensions/pmx-canvas/extension.mjs +591 -0
  2. package/CHANGELOG.md +140 -0
  3. package/Readme.md +40 -8
  4. package/dist/canvas/global.css +36 -3
  5. package/dist/canvas/index.js +54 -54
  6. package/dist/types/client/nodes/ExtAppFrame.d.ts +1 -0
  7. package/dist/types/client/nodes/iframe-document-url.d.ts +8 -0
  8. package/dist/types/client/state/intent-bridge.d.ts +4 -0
  9. package/dist/types/client/types.d.ts +1 -0
  10. package/dist/types/json-render/catalog.d.ts +1 -1
  11. package/dist/types/mcp/canvas-access.d.ts +9 -0
  12. package/dist/types/server/ax-context.d.ts +3 -0
  13. package/dist/types/server/ax-state.d.ts +43 -0
  14. package/dist/types/server/canvas-db.d.ts +38 -0
  15. package/dist/types/server/canvas-state.d.ts +36 -16
  16. package/dist/types/server/index.d.ts +6 -0
  17. package/dist/types/server/mutation-history.d.ts +1 -1
  18. package/docs/cli.md +13 -0
  19. package/docs/http-api.md +24 -0
  20. package/docs/mcp.md +20 -2
  21. package/docs/plans/plan-004-pmx-ax-primitives.md +463 -0
  22. package/docs/screenshot.png +0 -0
  23. package/docs/sdk.md +5 -0
  24. package/package.json +3 -2
  25. package/skills/pmx-canvas/SKILL.md +22 -4
  26. package/skills/pmx-canvas/references/codex-app-adapter.md +107 -0
  27. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +111 -0
  28. package/src/cli/agent.ts +34 -0
  29. package/src/cli/index.ts +2 -1
  30. package/src/client/App.tsx +2 -0
  31. package/src/client/canvas/CanvasNode.tsx +7 -0
  32. package/src/client/canvas/CommandPalette.tsx +2 -1
  33. package/src/client/canvas/use-node-drag.ts +29 -7
  34. package/src/client/canvas/use-node-resize.ts +27 -7
  35. package/src/client/nodes/ExtAppFrame.tsx +51 -10
  36. package/src/client/nodes/HtmlNode.tsx +5 -2
  37. package/src/client/nodes/iframe-document-url.ts +58 -0
  38. package/src/client/state/intent-bridge.ts +8 -0
  39. package/src/client/state/sse-bridge.ts +2 -2
  40. package/src/client/theme/global.css +36 -3
  41. package/src/client/types.ts +1 -0
  42. package/src/mcp/canvas-access.ts +38 -0
  43. package/src/mcp/server.ts +113 -4
  44. package/src/server/ax-context.ts +38 -0
  45. package/src/server/ax-state.ts +130 -0
  46. package/src/server/canvas-db.ts +745 -0
  47. package/src/server/canvas-operations.ts +80 -1
  48. package/src/server/canvas-schema.ts +3 -3
  49. package/src/server/canvas-state.ts +390 -50
  50. package/src/server/canvas-validation.ts +6 -0
  51. package/src/server/index.ts +18 -0
  52. package/src/server/mutation-history.ts +1 -0
  53. package/src/server/server.ts +197 -11
package/CHANGELOG.md CHANGED
@@ -3,6 +3,144 @@
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.24] - 2026-06-03
7
+
8
+ Host-adapter and agent-experience (AX) release. Adds host-agnostic AX
9
+ focus/context primitives across every layer, ships GitHub Copilot and
10
+ Codex canvas adapters, moves embedded HTML/MCP-app iframes onto a
11
+ same-origin frame-document transport (still strictly sandboxed via a
12
+ CSP `sandbox` response header), and fixes a batch of iframe-backed
13
+ node drag/resize/fullscreen interaction glitches.
14
+
15
+ ### Added
16
+
17
+ - **PMX AX focus + context primitives.** A new host-agnostic
18
+ "agent experience" focus field lets any surface mark which nodes
19
+ an agent is attending to without moving the viewport. Implemented
20
+ end to end with full parity:
21
+ - State: `CanvasStateManager.getAxFocus()` / `setAxFocus()` /
22
+ `getAxState()`, recorded as a `setAxFocus` mutation-history op
23
+ (undo/redo) and persisted in a new SQLite `ax_state` table.
24
+ - SDK: `PmxCanvas.getAxState()`, `getAxContext()`, `setAxFocus()`.
25
+ - HTTP: `GET`/`PATCH /api/canvas/ax`, `GET /api/canvas/ax/context`,
26
+ `POST /api/canvas/ax/focus`.
27
+ - MCP: `canvas_get_ax`, `canvas_set_ax_focus` (45 tools total),
28
+ plus `canvas://ax` and `canvas://ax-context` resources that emit
29
+ `notifications/resources/updated` on change.
30
+ - CLI: `pmx-canvas ax focus <node-id...>` / `--clear`.
31
+ Focus state carries a `source` tag (`agent`/`api`/`browser`/`cli`/
32
+ `codex`/`copilot`/`mcp`/`sdk`/`system`) and node IDs are validated
33
+ against the live layout.
34
+ - **GitHub Copilot canvas adapter.** A new
35
+ `.github/extensions/pmx-canvas/extension.mjs` (591 lines) plus
36
+ `skills/pmx-canvas/references/github-copilot-app-adapter.md`
37
+ document and implement driving the canvas from GitHub Copilot.
38
+ - **Codex canvas adapter coverage.**
39
+ `skills/pmx-canvas/references/codex-app-adapter.md` documents the
40
+ Codex host integration, with browser regression coverage.
41
+ - **Same-origin frame-document transport for embedded apps.**
42
+ Embedded HTML and MCP-app iframes now load their document from
43
+ `POST /api/canvas/frame-documents` → `GET /api/canvas/frame-
44
+ documents/<id>` instead of an inline `srcdoc`. The served document
45
+ carries `Content-Security-Policy: sandbox <tokens>`,
46
+ `Referrer-Policy: no-referrer`, and `X-Content-Type-Options:
47
+ nosniff`. The sandbox-token allowlist deliberately excludes
48
+ `allow-same-origin` and top-navigation tokens, so frame content
49
+ stays in an opaque origin and cannot reach the canvas host. The
50
+ document store is in-memory, capped at 128 entries (LRU eviction)
51
+ and 5 MB per document.
52
+
53
+ ### Changed
54
+
55
+ - **Iframe-backed node drag is flicker-free.** Node drag now
56
+ rAF-throttles pointer moves, clears the browser text selection,
57
+ and toggles an `is-node-dragging` document class to suppress
58
+ selection and attention-field repaint artifacts. Inline app
59
+ iframes are kept pointer-inert near the resize handle so resize
60
+ starts reliably.
61
+ - **Docs tool/resource references updated.** `docs/mcp.md` and the
62
+ README now read 45 tools + 9 core resources; the `AGENTS.md` and
63
+ `CLAUDE.md` MCP tool enumerations were corrected to the full
64
+ 45-tool list (they had drifted to 42 and 39 respectively and were
65
+ missing `canvas_fit_view` and the new AX tools).
66
+
67
+ ### Internal
68
+
69
+ - Regression coverage for: AX focus set/clear/persistence through
70
+ state, HTTP, MCP, SDK, and CLI; AX focus round-tripping through
71
+ SQLite; arrange-lock interactions; iframe-backed node
72
+ drag/resize/fullscreen behavior (large browser e2e additions); and
73
+ the Copilot/Codex adapter surfaces.
74
+
75
+ ## [0.1.23] - 2026-05-12
76
+
77
+ Persistence overhaul. Canvas state, snapshots, context pins, and the
78
+ large-payload blob store all move from filesystem JSON files into a
79
+ single SQLite database at `.pmx-canvas/canvas.db` (WAL mode). The
80
+ old `state.json`, `snapshots/`, and per-blob files are auto-imported
81
+ on first boot and renamed to `.bak`. Adds dock-aware validation and
82
+ arrange behavior, accepts the documented `?type=` query string on
83
+ node creation, and grows the schema-metadata kebab-case aliases to
84
+ include both singular and plural variants.
85
+
86
+ ### Added
87
+
88
+ - **SQLite persistence (`src/server/canvas-db.ts`, 710 lines).**
89
+ Canvas state, snapshots, context pins, and the blob sidecar
90
+ store now live in `.pmx-canvas/canvas.db` (Bun SQLite in WAL
91
+ mode). Shape preserved across the migration: nodes, edges,
92
+ annotations, viewport, context pins, history, snapshots, and
93
+ blob payloads with checksum validation.
94
+ - Override DB path: `PMX_CANVAS_DB_PATH` env var.
95
+ - Backward-compatible legacy path: `PMX_CANVAS_STATE_FILE` (if
96
+ you set a `.db` path there, it's used as the DB; if not, it's
97
+ treated as a legacy JSON path for migration).
98
+ - `stopCanvasServer()` now calls `canvasState.close()` which
99
+ checkpoints WAL data into the DB file — stop the server (or
100
+ flush/close the SDK) before committing `canvas.db`.
101
+ - SQLite WAL/SHM files (`*.db-wal`, `*.db-shm`) are gitignored;
102
+ `canvas.db` itself is git-committable.
103
+ - **Legacy migration on first boot.** Existing
104
+ `.pmx-canvas/state.json`, root `.pmx-canvas.json`,
105
+ `.pmx-canvas/snapshots/`, `.pmx-canvas-snapshots/`, and blob
106
+ files are imported into the SQLite database and renamed to
107
+ `.bak` on first start. The migration is idempotent and only
108
+ runs when the DB is empty.
109
+ - **HTTP node create accepts `?type=` query string.** `POST
110
+ /api/canvas/node?type=html-primitive` with the body's `data`
111
+ fields is accepted as an alternative to passing `type` in the
112
+ body — handy for `curl` and shell-based agents. The body form
113
+ still wins when both are present.
114
+
115
+ ### Changed
116
+
117
+ - **Docked nodes are excluded from layout collision validation.**
118
+ `validateCanvasLayout` no longer flags `dockPosition !== null`
119
+ nodes as overlap or containment violations. Docked HUD-style
120
+ nodes intentionally sit on top of canvas content; the validator
121
+ now models that.
122
+ - **Docked nodes are treated as arrange-locked.** `arrange()`
123
+ now skips translating nodes with `dockPosition !== null` along
124
+ with pinned and explicitly arrange-locked nodes. Dock geometry
125
+ is anchored to the HUD layer, not the world grid.
126
+ - **Schema kebab-case aliases include plural forms.** `--embedded-
127
+ node-ids`, `--embedded-urls`, and `--slide-titles` are now
128
+ documented aliases for the array-shaped HTML sidecar fields,
129
+ alongside the existing singular `--embedded-node-id`,
130
+ `--embedded-url`, and `--slide-title`.
131
+ - **Bun engine bumped to `>=1.3.14`.** `package.json#engines.bun`
132
+ raised from `>=1.3.12` to `>=1.3.14` to pick up the
133
+ `bun:sqlite` improvements the new persistence layer depends on.
134
+
135
+ ### Internal
136
+
137
+ - Regression coverage for: `validateCanvasLayout` ignoring docked
138
+ nodes as collision candidates, html primitive node creation
139
+ accepting the documented query-string `?type=` form, and the
140
+ existing canvas-state and operations suites continuing to pass
141
+ against the SQLite-backed persistence (including snapshot
142
+ save/restore, blob round-trip, and undo/redo history).
143
+
6
144
  ## [0.1.22] - 2026-05-12
7
145
 
8
146
  CLI ergonomics and response-size polish on top of 0.1.21. Adds a
@@ -1045,6 +1183,8 @@ otherwise have to discover by trial and error.
1045
1183
  - Regression coverage for snapshot flat-`id` aliases on both MCP and
1046
1184
  HTTP surfaces, plus async / top-level-`await` WebView script bodies.
1047
1185
 
1186
+ [0.1.24]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.24
1187
+ [0.1.23]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.23
1048
1188
  [0.1.22]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.22
1049
1189
  [0.1.21]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.21
1050
1190
  [0.1.20]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.20
package/Readme.md CHANGED
@@ -55,22 +55,40 @@ prompt engineering, no copy-paste — pin a node in the browser and the MCP
55
55
  server fires a `notifications/resources/updated` event the agent's harness
56
56
  picks up immediately.
57
57
 
58
+ AX context adds a host-agnostic focus layer on top of pins. Core PMX exposes
59
+ `/api/canvas/ax/context`, `canvas://ax-context`, SDK methods, and
60
+ `pmx-canvas ax context|focus`; adapters can map that same primitive to their
61
+ native hook systems without making PMX Canvas GitHub-specific.
62
+
58
63
  ### 05 / Save
59
64
 
60
- Spatial state auto-saves to `.pmx-canvas/state.json` (debounced ~500 ms) —
65
+ Spatial state auto-saves to `.pmx-canvas/canvas.db` (debounced ~500 ms) —
61
66
  git-committable, shareable across machines, and survives both browser
62
67
  refresh and server restart. Named [snapshots](docs/mcp.md#tools), full
63
68
  undo/redo, and an auto-detected code graph (JS/TS, Python, Go, Rust) make
64
- the canvas durable rather than throwaway.
69
+ the canvas durable rather than throwaway. Stop the server before committing
70
+ the DB so SQLite WAL data is checkpointed into the file.
65
71
 
66
72
  ### 06 / Any agent
67
73
 
68
- Harness-agnostic. Drive the canvas from [MCP](docs/mcp.md) (42 tools,
69
- 8 resources, change notifications), the [CLI](docs/cli.md), the
74
+ Harness-agnostic. Drive the canvas from [MCP](docs/mcp.md) (45 tools,
75
+ 9 resources, change notifications), the [CLI](docs/cli.md), the
70
76
  [HTTP API](docs/http-api.md), or the [Bun SDK](docs/sdk.md). Works with
71
77
  Claude Code, GitHub Copilot CLI, Codex, Cursor, Windsurf, or any agent
72
78
  that can spawn an MCP stdio server, call a CLI, or hit an HTTP endpoint.
73
79
 
80
+ The repo also ships a GitHub Copilot app adapter at
81
+ `.github/extensions/pmx-canvas/`. It opens the live PMX workbench in a native
82
+ Copilot canvas panel, injects AX pinned/focused context on prompt submission,
83
+ and exposes adapter actions for status, AX focus, context refresh, and explicit
84
+ session steering.
85
+
86
+ In the Codex app, PMX Canvas is MCP-first plus the Codex in-app Browser: agents
87
+ read `canvas://ax-context` / `canvas_get_ax`, humans use the live `/workbench`
88
+ view, and Codex-originated focus can be labeled with `source: "codex"` through
89
+ `canvas_set_ax_focus`. The CLI remains a fallback for scripts and manual
90
+ debugging, not the native Codex adapter path.
91
+
74
92
  ## Prerequisites
75
93
 
76
94
  - [Bun](https://bun.sh) >= 1.3.12
@@ -125,6 +143,20 @@ Add to your agent's MCP config:
125
143
 
126
144
  The canvas auto-starts on first tool call.
127
145
 
146
+ ### Use inside the GitHub Copilot app
147
+
148
+ This repository includes a project canvas extension:
149
+
150
+ ```text
151
+ .github/extensions/pmx-canvas/extension.mjs
152
+ ```
153
+
154
+ When loaded by the Copilot app, it opens the PMX workbench natively, starts a
155
+ matching local PMX server when needed, and injects `AX` pinned/focused context
156
+ as hidden per-turn context. The adapter is thin: PMX state still lives in
157
+ `.pmx-canvas/canvas.db`, and the same HTTP, MCP, CLI, and SDK surfaces remain
158
+ available to non-GitHub agents.
159
+
128
160
  ### Install the agent skill (recommended)
129
161
 
130
162
  The fastest way to get a working canvas is to install the `pmx-canvas` agent
@@ -147,8 +179,8 @@ Common harness skill directories: `.claude/skills/` (Claude Code),
147
179
  `.github/skills/` or `.copilot/skills/` (Copilot CLI),
148
180
  `.agents/skills/` (cross-harness convention). Once the canvas is running,
149
181
  the agent can read `canvas://skills` and pull in companion skills
150
- (`web-artifacts-builder`, `json-render-*`, `pmx-canvas-testing`,
151
- `playwright-cli`, etc.) as the work demands.
182
+ (`control-session-orchestrator`, `web-artifacts-builder`, `json-render-*`,
183
+ `pmx-canvas-testing`, `playwright-cli`, etc.) as the work demands.
152
184
 
153
185
  ## Documentation
154
186
 
@@ -156,7 +188,7 @@ the agent can read `canvas://skills` and pull in companion skills
156
188
  the three-tier visual matrix (json-render → html → web-artifact)
157
189
  - **[CLI reference](docs/cli.md)** — full command surface, daemon mode,
158
190
  watch streams, WebView automation
159
- - **[MCP reference](docs/mcp.md)** — 42 tools, 8 resources, change
191
+ - **[MCP reference](docs/mcp.md)** — 45 tools, 9 resources, change
160
192
  notifications, node-type routing
161
193
  - **[HTTP API](docs/http-api.md)** — REST endpoints, SSE, batch operations
162
194
  - **[Bun SDK](docs/sdk.md)** — `createCanvas()` for TypeScript on Bun
@@ -168,7 +200,7 @@ the agent can read `canvas://skills` and pull in companion skills
168
200
  one machine. No built-in multi-user auth or presence — collaboration means
169
201
  human ↔ agent on the same machine, plus any other browser tab/agent
170
202
  pointed at the same `localhost:4313`. To share across machines, commit
171
- `.pmx-canvas/state.json`.
203
+ `.pmx-canvas/canvas.db`.
172
204
  - **What leaves your machine.** The core canvas runs entirely on
173
205
  `localhost`. Network egress only happens for explicit, opt-in flows:
174
206
  `webpage` nodes fetch the URL you give them; `mcp-app` /
@@ -1107,10 +1107,13 @@ body,
1107
1107
  position: absolute;
1108
1108
  bottom: 0;
1109
1109
  right: 0;
1110
- width: 16px;
1111
- height: 16px;
1110
+ width: 32px;
1111
+ height: 32px;
1112
+ background: rgba(0, 0, 0, 0.001);
1112
1113
  cursor: nwse-resize;
1113
- z-index: 2;
1114
+ z-index: 30;
1115
+ pointer-events: auto;
1116
+ touch-action: none;
1114
1117
  }
1115
1118
 
1116
1119
  .canvas-node .node-resize-handle::after {
@@ -1130,6 +1133,36 @@ body,
1130
1133
  opacity: 1;
1131
1134
  }
1132
1135
 
1136
+ html.is-node-resizing,
1137
+ html.is-node-resizing * {
1138
+ cursor: nwse-resize !important;
1139
+ }
1140
+
1141
+ html.is-node-resizing .canvas-node {
1142
+ transition: box-shadow 0.15s ease !important;
1143
+ }
1144
+
1145
+ html.is-node-dragging .attention-field-layer {
1146
+ visibility: hidden;
1147
+ }
1148
+
1149
+ html.is-node-dragging,
1150
+ html.is-node-dragging * {
1151
+ cursor: grabbing !important;
1152
+ user-select: none !important;
1153
+ -webkit-user-select: none !important;
1154
+ }
1155
+
1156
+ html.is-node-dragging iframe,
1157
+ html.is-node-dragging .ext-app-preview-catcher {
1158
+ pointer-events: none !important;
1159
+ }
1160
+
1161
+ html.is-node-resizing iframe,
1162
+ html.is-node-resizing .ext-app-preview-catcher {
1163
+ pointer-events: none !important;
1164
+ }
1165
+
1133
1166
  /* Pinned node indicator */
1134
1167
  .canvas-node.pinned {
1135
1168
  border-style: dashed;