pmx-canvas 0.1.18 → 0.1.19
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 +54 -0
- package/dist/types/server/canvas-state.d.ts +2 -0
- package/docs/RELEASE.md +153 -0
- package/docs/bun-webview-integration.md +296 -0
- package/docs/cli.md +140 -0
- package/docs/evals/e2e-cli-coverage.md +61 -0
- package/docs/http-api.md +191 -0
- package/docs/mcp.md +135 -0
- package/docs/node-types.md +244 -0
- package/docs/plans/.gitkeep +0 -0
- package/docs/plans/plan-001-semantic-watch-mvp.md +335 -0
- package/docs/plans/plan-002-human-attention-layer-design-spec.md +679 -0
- package/docs/plans/plan-003-human-attention-layer-implementation-plan.md +572 -0
- package/docs/reactive-canvas-proposal.md +578 -0
- package/docs/release-review-0.1.0.md +38 -0
- package/docs/screenshot.png +0 -0
- package/docs/screenshots/demo-workbench-dark.png +0 -0
- package/docs/screenshots/demo-workbench-light.png +0 -0
- package/docs/screenshots/welcome-dark.png +0 -0
- package/docs/screenshots/welcome-light.png +0 -0
- package/docs/sdk.md +92 -0
- package/package.json +2 -1
- package/src/cli/agent.ts +17 -0
- package/src/mcp/canvas-access.ts +2 -0
- package/src/mcp/server.ts +2 -0
- package/src/server/canvas-state.ts +18 -5
- package/src/server/server.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,59 @@
|
|
|
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.19] - 2026-05-05
|
|
7
|
+
|
|
8
|
+
Snapshot ergonomics and reference-doc distribution. Adds `before` /
|
|
9
|
+
`after` ISO timestamp filters on snapshot listing across CLI, HTTP,
|
|
10
|
+
and MCP, ships the `docs/` reference tree inside the npm tarball so
|
|
11
|
+
consumers see the same surface docs as the repo, and surfaces the
|
|
12
|
+
existing trace-field flags in `node update --help`. Also lands the
|
|
13
|
+
deflake of the MCP-app fullscreen reopen e2e (originally
|
|
14
|
+
`LRN-20260505-001`) — 9/20 → 50+/50 stability via a retry-on-stuck-
|
|
15
|
+
iframe helper.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **`pmx-canvas snapshot list --before / --after`.** Both flags
|
|
20
|
+
accept ISO 8601 timestamps and filter against `snapshot.createdAt`.
|
|
21
|
+
Same surface lands on `GET /api/canvas/snapshots?before=&after=`,
|
|
22
|
+
`RemoteCanvasAccess.listSnapshots()`, and the `canvas_list_snapshots`
|
|
23
|
+
MCP tool schema. The CLI help (`pmx-canvas snapshot list --help`)
|
|
24
|
+
now lists the new flags alongside `--limit`, `--query`, and
|
|
25
|
+
`--all`.
|
|
26
|
+
- **`docs/` shipped in the npm tarball.** The package `files`
|
|
27
|
+
allowlist now includes `docs/`, so consumers installing
|
|
28
|
+
`pmx-canvas` see the same `docs/cli.md`, `docs/http-api.md`,
|
|
29
|
+
`docs/mcp.md`, `docs/node-types.md`, and `docs/sdk.md` reference
|
|
30
|
+
files that ship in the repo.
|
|
31
|
+
- **`node update --help` advertises trace flags.** The CLI help now
|
|
32
|
+
documents `--tool-name` / `--toolName`, `--category`, `--status`,
|
|
33
|
+
`--duration`, `--result-summary` / `--resultSummary`, and `--error`
|
|
34
|
+
so agents discover trace-field updates without reading the source
|
|
35
|
+
or schema.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- **MCP-app fullscreen reopen e2e is no longer flaky.** The
|
|
40
|
+
visibility check for the fixture editor used to race the ext-app
|
|
41
|
+
bridge handshake — if the iframe started parsing before the
|
|
42
|
+
parent registered its postMessage listener, the iframe's
|
|
43
|
+
`ui/initialize` request was lost and `app.connect()` hung. The
|
|
44
|
+
test now wraps the assertion in a retry-on-stuck-iframe helper
|
|
45
|
+
that closes and reopens the fullscreen overlay (each remount is
|
|
46
|
+
independent of the prior failed handshake), with three 5s
|
|
47
|
+
attempts to match the original 15s budget. Pass rate moved from
|
|
48
|
+
9/20 to 50+/50 consecutive runs.
|
|
49
|
+
|
|
50
|
+
### Internal
|
|
51
|
+
|
|
52
|
+
- Regression coverage for: snapshot list before/after filtering at
|
|
53
|
+
the canvas-state layer and through the CLI, snapshot list help
|
|
54
|
+
advertising the new flags, `node update --help` advertising
|
|
55
|
+
trace flags, the `docs/` allowlist entry surviving in
|
|
56
|
+
`package.json` for npm consumers, and the existing arrange
|
|
57
|
+
operation recording as a single undoable history entry.
|
|
58
|
+
|
|
6
59
|
## [0.1.18] - 2026-05-05
|
|
7
60
|
|
|
8
61
|
Token-budget polish on top of 0.1.17. Full-mode MCP responses for
|
|
@@ -771,6 +824,7 @@ otherwise have to discover by trial and error.
|
|
|
771
824
|
- Regression coverage for snapshot flat-`id` aliases on both MCP and
|
|
772
825
|
HTTP surfaces, plus async / top-level-`await` WebView script bodies.
|
|
773
826
|
|
|
827
|
+
[0.1.19]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.19
|
|
774
828
|
[0.1.18]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.18
|
|
775
829
|
[0.1.17]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.17
|
|
776
830
|
[0.1.16]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.1.16
|
package/docs/RELEASE.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Release process
|
|
2
|
+
|
|
3
|
+
Internal recipe for cutting a new `pmx-canvas` release. Lives in `docs/`
|
|
4
|
+
rather than the README so end-user agents and humans driving the canvas
|
|
5
|
+
aren't distracted by maintainer-only flow. Agents working **on** this
|
|
6
|
+
repo (improving the canvas itself) should treat this file as the
|
|
7
|
+
single source of truth for the release dance — see also
|
|
8
|
+
[`AGENTS.md`](../AGENTS.md) and [`CLAUDE.md`](../CLAUDE.md).
|
|
9
|
+
|
|
10
|
+
## TL;DR
|
|
11
|
+
|
|
12
|
+
1. Land all the changes you want in the release on `main` with green CI.
|
|
13
|
+
2. Bump `package.json` `version`.
|
|
14
|
+
3. Add a `## [X.Y.Z]` block to `CHANGELOG.md`.
|
|
15
|
+
4. Commit, push, wait for `test.yml` green.
|
|
16
|
+
5. `git tag -a vX.Y.Z -m "..." && git push origin vX.Y.Z` →
|
|
17
|
+
`publish.yml` runs `npm publish --access public --provenance`.
|
|
18
|
+
6. `gh release create vX.Y.Z --notes-file <notes.md>`.
|
|
19
|
+
7. Smoke-test the published tarball: `bunx pmx-canvas@X.Y.Z --no-open`.
|
|
20
|
+
|
|
21
|
+
## Pre-flight gates
|
|
22
|
+
|
|
23
|
+
Run these locally before tagging. They mirror what `publish.yml`
|
|
24
|
+
re-runs in CI; a failure here means the publish workflow will also fail.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
bun install --frozen-lockfile
|
|
28
|
+
bun run typecheck
|
|
29
|
+
bun run build
|
|
30
|
+
bun test tests/unit # 200+ tests, all green
|
|
31
|
+
bun run test:web-canvas # Playwright E2E, all green
|
|
32
|
+
bun run test:e2e-cli # fresh-workspace CLI eval
|
|
33
|
+
bun run release:check # bundles + lints
|
|
34
|
+
bun run release:smoke # packs + boots from a clean dir
|
|
35
|
+
bun run pack:dry-run # confirms the tarball shape
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`bun run test:e2e-cli` starts a local server in a fresh temp workspace
|
|
39
|
+
and exercises the CLI flows from
|
|
40
|
+
[`docs/evals/e2e-cli-coverage.md`](evals/e2e-cli-coverage.md).
|
|
41
|
+
|
|
42
|
+
## Versioning
|
|
43
|
+
|
|
44
|
+
Semantic versioning. While we are still in `0.1.x`:
|
|
45
|
+
|
|
46
|
+
- Patch (`0.1.x → 0.1.x+1`): bug fixes, hardening, internal cleanups,
|
|
47
|
+
additive CLI flags / MCP fields with backwards-compat fallbacks.
|
|
48
|
+
- Minor (`0.1.x → 0.2.0`): documented breaking changes (e.g. dropping
|
|
49
|
+
the `hostMode + path` fallback in `getCanvasNodeKind`, removing legacy
|
|
50
|
+
`ext-app-ext-app-…` ID handling, JSON-shape changes that aren't
|
|
51
|
+
additive).
|
|
52
|
+
- Major (`0.x → 1.0`): production-stability commitment.
|
|
53
|
+
|
|
54
|
+
CLAUDE.md rule #5 (CanvasStateManager / PmxCanvas SDK / HTTP / MCP
|
|
55
|
+
four-layer parity) is the strongest hard rule for what counts as
|
|
56
|
+
non-breaking — a CLI/HTTP-only addition without MCP parity has
|
|
57
|
+
historically required a follow-up patch release to restore parity.
|
|
58
|
+
|
|
59
|
+
## CHANGELOG
|
|
60
|
+
|
|
61
|
+
`CHANGELOG.md` follows [Keep a Changelog](https://keepachangelog.com/).
|
|
62
|
+
Each release section uses these subheadings:
|
|
63
|
+
|
|
64
|
+
- **Added** — new public surface (HTTP endpoint, MCP tool/resource, CLI
|
|
65
|
+
command/flag, SDK export, JSON shape).
|
|
66
|
+
- **Changed** — behavior changes that aren't strictly bug fixes
|
|
67
|
+
(response shape additions, schema cleanups, stricter validation).
|
|
68
|
+
- **Fixed** — bug fixes.
|
|
69
|
+
- **Internal** — refactors, test additions, docs that don't affect
|
|
70
|
+
the public surface.
|
|
71
|
+
|
|
72
|
+
Don't ship a release without a CHANGELOG entry. The GitHub release
|
|
73
|
+
notes file (`/tmp/pmx-canvas-vX.Y.Z-release-notes.md` by convention)
|
|
74
|
+
expands on the CHANGELOG with examples and migration notes.
|
|
75
|
+
|
|
76
|
+
## Tag → publish
|
|
77
|
+
|
|
78
|
+
The publish workflow ([`/.github/workflows/publish.yml`](../.github/workflows/publish.yml))
|
|
79
|
+
triggers on tags matching `v*`:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git tag -a v0.1.6 -m "v0.1.6 — short summary"
|
|
83
|
+
git push origin v0.1.6
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
It will:
|
|
87
|
+
|
|
88
|
+
1. Verify the tag matches `package.json` version.
|
|
89
|
+
2. Re-run typecheck / build / unit / E2E / pack.
|
|
90
|
+
3. `npm publish --access public --provenance` using the `NPM_TOKEN`
|
|
91
|
+
secret. Provenance attestations are signed via sigstore and visible
|
|
92
|
+
on the npm package page.
|
|
93
|
+
|
|
94
|
+
Watch it complete:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
gh run watch
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If publish fails after npm has accepted the tarball, you cannot reuse
|
|
101
|
+
the same version number. Bump the patch and re-tag.
|
|
102
|
+
|
|
103
|
+
If this is the first release from your machine, run `bunx npm login`
|
|
104
|
+
once so Bun can reuse your npm credentials. CI does not need this —
|
|
105
|
+
it uses `NPM_TOKEN` directly.
|
|
106
|
+
|
|
107
|
+
## GitHub release
|
|
108
|
+
|
|
109
|
+
After `npm publish` succeeds:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
gh release create v0.1.6 \
|
|
113
|
+
--title "pmx-canvas 0.1.6 — short theme" \
|
|
114
|
+
--notes-file /tmp/pmx-canvas-v0.1.6-release-notes.md \
|
|
115
|
+
--verify-tag
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`--verify-tag` makes the command fail if the local tag drifted from
|
|
119
|
+
the remote — a small but useful guard.
|
|
120
|
+
|
|
121
|
+
## Smoke test from npm
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
cd /tmp && rm -rf smoke && mkdir smoke && cd smoke
|
|
125
|
+
bunx --bun pmx-canvas@<version> --no-open --port=4926 > smoke.log &
|
|
126
|
+
SP=$!
|
|
127
|
+
for i in 1 2 3 4 5 6 7 8 9 10; do
|
|
128
|
+
curl -sf http://localhost:4926/health >/dev/null 2>&1 && break
|
|
129
|
+
sleep 1
|
|
130
|
+
done
|
|
131
|
+
curl -s http://localhost:4926/health # → {"ok":true,"workspace":"…"}
|
|
132
|
+
bunx pmx-canvas@<version> --version # → <version>
|
|
133
|
+
kill $SP
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
If `bunx pmx-canvas@<version>` resolves and the health endpoint replies
|
|
137
|
+
with `ok: true`, the published tarball is intact end-to-end.
|
|
138
|
+
|
|
139
|
+
## Common gotchas
|
|
140
|
+
|
|
141
|
+
- **`/.pmx-canvas/artifacts/.web-artifacts/sdlc-control-room/.parcel-cache/`**
|
|
142
|
+
files always show as modified after running an artifact build. They
|
|
143
|
+
are workspace-local cache and must not be committed; they're gitignored
|
|
144
|
+
but still appear in `git status`. Use `git restore --staged` if they
|
|
145
|
+
sneak into a `git add -A`.
|
|
146
|
+
- **`docs/screenshot.png`** updates whenever the showcase E2E runs.
|
|
147
|
+
Don't bake those updates into a release commit unless the screenshot
|
|
148
|
+
in `Readme.md` actually needs the refresh.
|
|
149
|
+
- **CHANGELOG dates**: use the actual publish date in the
|
|
150
|
+
`## [version] - YYYY-MM-DD` header, not the day you wrote the entry.
|
|
151
|
+
- **Node 24 deprecation timeline**: GitHub Actions is migrating
|
|
152
|
+
`actions/checkout`, `setup-node`, `upload-artifact` to Node 24 by
|
|
153
|
+
June 2, 2026. The publish workflow already pins `@v5` of all three.
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# Bun.WebView Integration
|
|
2
|
+
|
|
3
|
+
PMX Canvas now uses Bun's built-in `Bun.WebView` API for **headless canvas automation**, while keeping the current external browser launcher for the normal interactive canvas window.
|
|
4
|
+
|
|
5
|
+
This document tracks:
|
|
6
|
+
|
|
7
|
+
- what is implemented today
|
|
8
|
+
- what was validated on stable Bun `v1.3.12`
|
|
9
|
+
- what still remains future work
|
|
10
|
+
|
|
11
|
+
## Current Status
|
|
12
|
+
|
|
13
|
+
**Implemented** for Phase 1.
|
|
14
|
+
|
|
15
|
+
The repo now targets Bun `>=1.3.12`, and PMX Canvas ships an opt-in, server-owned WebView automation session that can:
|
|
16
|
+
|
|
17
|
+
- start a headless browser session for `/workbench`
|
|
18
|
+
- report WebView runtime status
|
|
19
|
+
- evaluate JavaScript in the page
|
|
20
|
+
- resize the automation viewport
|
|
21
|
+
- capture screenshots
|
|
22
|
+
- stop and clean up the automation session explicitly
|
|
23
|
+
|
|
24
|
+
What is **not** implemented:
|
|
25
|
+
|
|
26
|
+
- replacing `openUrlInExternalBrowser()` for the visible user-facing canvas window
|
|
27
|
+
- headed Bun.WebView window support
|
|
28
|
+
- Chrome-only CDP tooling
|
|
29
|
+
|
|
30
|
+
## Why This Exists
|
|
31
|
+
|
|
32
|
+
The existing browser-launch path in [`src/server/server.ts`](../src/server/server.ts) still opens the interactive canvas with platform-specific shell behavior:
|
|
33
|
+
|
|
34
|
+
- macOS: AppleScript / `osascript`
|
|
35
|
+
- Windows: `cmd /c start` or a resolved browser executable
|
|
36
|
+
- Linux: `xdg-open`
|
|
37
|
+
|
|
38
|
+
That path is still appropriate for humans, but it provides no programmatic control once the browser is open.
|
|
39
|
+
|
|
40
|
+
`Bun.WebView` gives PMX Canvas a controlled browser session that the server can own directly. That unlocks:
|
|
41
|
+
|
|
42
|
+
- agent-visible screenshots
|
|
43
|
+
- browser-backed evaluation of rendered canvas state
|
|
44
|
+
- controlled viewport sizing
|
|
45
|
+
- future browser automation tools without depending on Playwright for the basic runtime
|
|
46
|
+
|
|
47
|
+
## Implemented Surface
|
|
48
|
+
|
|
49
|
+
### Server layer
|
|
50
|
+
|
|
51
|
+
Implemented in [`src/server/server.ts`](../src/server/server.ts):
|
|
52
|
+
|
|
53
|
+
- `getCanvasAutomationWebViewStatus()`
|
|
54
|
+
- `startCanvasAutomationWebView(url, options)`
|
|
55
|
+
- `stopCanvasAutomationWebView()`
|
|
56
|
+
- `evaluateCanvasAutomationWebView(expression)`
|
|
57
|
+
- `resizeCanvasAutomationWebView(width, height)`
|
|
58
|
+
- `screenshotCanvasAutomationWebView(options)`
|
|
59
|
+
|
|
60
|
+
Important behavior:
|
|
61
|
+
|
|
62
|
+
- runtime-gated: if `Bun.WebView` is unavailable, PMX Canvas returns a clear error
|
|
63
|
+
- headless-only: PMX Canvas does not rely on `headless: false`
|
|
64
|
+
- explicit lifecycle: start and stop are owned by the server
|
|
65
|
+
- screenshot normalization handles Bun return types correctly, including `Blob`
|
|
66
|
+
|
|
67
|
+
### HTTP API
|
|
68
|
+
|
|
69
|
+
Implemented in [`src/server/server.ts`](../src/server/server.ts):
|
|
70
|
+
|
|
71
|
+
- `GET /api/workbench/webview`
|
|
72
|
+
- `POST /api/workbench/webview/start`
|
|
73
|
+
- `POST /api/workbench/webview/evaluate`
|
|
74
|
+
- `POST /api/workbench/webview/resize`
|
|
75
|
+
- `POST /api/workbench/webview/screenshot`
|
|
76
|
+
- `DELETE /api/workbench/webview`
|
|
77
|
+
|
|
78
|
+
Current HTTP behavior:
|
|
79
|
+
|
|
80
|
+
- `GET` returns runtime support plus active-session status
|
|
81
|
+
- `POST` starts a new headless automation session for the current `/workbench`
|
|
82
|
+
- `POST /evaluate` runs JavaScript in the active automation session and returns JSON
|
|
83
|
+
- `POST /resize` updates the active automation viewport and returns JSON status
|
|
84
|
+
- `POST /screenshot` returns image bytes for the active automation session
|
|
85
|
+
- `DELETE` stops the current automation session
|
|
86
|
+
|
|
87
|
+
Current options accepted by `POST /api/workbench/webview/start`:
|
|
88
|
+
|
|
89
|
+
- `backend`: `"chrome"` or `"webkit"`
|
|
90
|
+
- `width`
|
|
91
|
+
- `height`
|
|
92
|
+
- `chromePath`
|
|
93
|
+
- `chromeArgv`
|
|
94
|
+
- `dataStoreDir`
|
|
95
|
+
|
|
96
|
+
### SDK
|
|
97
|
+
|
|
98
|
+
Implemented in [`src/server/index.ts`](../src/server/index.ts):
|
|
99
|
+
|
|
100
|
+
- `canvas.start({ automationWebView: ... })`
|
|
101
|
+
- `canvas.startAutomationWebView(options)`
|
|
102
|
+
- `canvas.stopAutomationWebView()`
|
|
103
|
+
- `canvas.getAutomationWebViewStatus()`
|
|
104
|
+
- `canvas.evaluateAutomationWebView(expression)`
|
|
105
|
+
- `canvas.resizeAutomationWebView(width, height)`
|
|
106
|
+
- `canvas.screenshotAutomationWebView(options)`
|
|
107
|
+
|
|
108
|
+
### CLI
|
|
109
|
+
|
|
110
|
+
Implemented in [`src/cli/index.ts`](../src/cli/index.ts):
|
|
111
|
+
|
|
112
|
+
- `--webview-automation`
|
|
113
|
+
- `--webview-backend`
|
|
114
|
+
- `--webview-width`
|
|
115
|
+
- `--webview-height`
|
|
116
|
+
- `--webview-chrome-path`
|
|
117
|
+
- `--webview-chrome-argv`
|
|
118
|
+
- `--webview-data-dir`
|
|
119
|
+
|
|
120
|
+
Implemented in [`src/cli/agent.ts`](../src/cli/agent.ts):
|
|
121
|
+
|
|
122
|
+
- `pmx-canvas webview status`
|
|
123
|
+
- `pmx-canvas webview start`
|
|
124
|
+
- `pmx-canvas webview evaluate`
|
|
125
|
+
- `pmx-canvas webview resize`
|
|
126
|
+
- `pmx-canvas webview screenshot`
|
|
127
|
+
- `pmx-canvas webview stop`
|
|
128
|
+
|
|
129
|
+
Example:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
pmx-canvas --no-open --webview-automation
|
|
133
|
+
pmx-canvas --webview-automation --webview-backend=chrome
|
|
134
|
+
pmx-canvas webview start --backend chrome --width 1440 --height 900
|
|
135
|
+
pmx-canvas webview evaluate --expression "document.title"
|
|
136
|
+
pmx-canvas webview resize --width 1280 --height 800
|
|
137
|
+
pmx-canvas webview screenshot --output ./canvas.png
|
|
138
|
+
pmx-canvas webview stop
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
These flags are intentionally automation-only. They do **not** imply a visible Bun-managed window.
|
|
142
|
+
|
|
143
|
+
### MCP
|
|
144
|
+
|
|
145
|
+
Implemented in [`src/mcp/server.ts`](../src/mcp/server.ts):
|
|
146
|
+
|
|
147
|
+
- `canvas_webview_status`
|
|
148
|
+
- `canvas_webview_start`
|
|
149
|
+
- `canvas_webview_stop`
|
|
150
|
+
- `canvas_evaluate`
|
|
151
|
+
- `canvas_resize`
|
|
152
|
+
- `canvas_screenshot`
|
|
153
|
+
|
|
154
|
+
Current MCP behavior:
|
|
155
|
+
|
|
156
|
+
- automation lifecycle is explicit rather than implicit
|
|
157
|
+
- screenshot returns an MCP image payload plus JSON metadata
|
|
158
|
+
- evaluate/resize/screenshot require an active automation session
|
|
159
|
+
- start accepts the same backend/viewport/data-store options as the server layer
|
|
160
|
+
|
|
161
|
+
## Backend Strategy
|
|
162
|
+
|
|
163
|
+
PMX Canvas follows Bun's current stable backend reality.
|
|
164
|
+
|
|
165
|
+
### WebKit backend
|
|
166
|
+
|
|
167
|
+
- macOS only
|
|
168
|
+
- good default on macOS when CDP is not required
|
|
169
|
+
- zero external Chrome dependency
|
|
170
|
+
|
|
171
|
+
### Chrome backend
|
|
172
|
+
|
|
173
|
+
- required on Linux and Windows
|
|
174
|
+
- also supported on macOS
|
|
175
|
+
- preferred when backend consistency or future CDP-based tooling matters
|
|
176
|
+
|
|
177
|
+
### Current default behavior
|
|
178
|
+
|
|
179
|
+
PMX Canvas defaults to:
|
|
180
|
+
|
|
181
|
+
- `webkit` on macOS
|
|
182
|
+
- `chrome` elsewhere
|
|
183
|
+
|
|
184
|
+
If `chromePath` or `chromeArgv` is provided, PMX Canvas forces a Chrome-backed session.
|
|
185
|
+
|
|
186
|
+
## Bun Runtime Requirements
|
|
187
|
+
|
|
188
|
+
The repo now requires:
|
|
189
|
+
|
|
190
|
+
- Bun `>=1.3.12`
|
|
191
|
+
|
|
192
|
+
That change is reflected in:
|
|
193
|
+
|
|
194
|
+
- [`package.json`](../package.json)
|
|
195
|
+
- [`.github/workflows/test.yml`](../.github/workflows/test.yml)
|
|
196
|
+
|
|
197
|
+
PMX Canvas still keeps a runtime guard because older local Bun versions can exist in user environments. If `Bun.WebView` is missing, startup fails cleanly for the automation path instead of partially starting.
|
|
198
|
+
|
|
199
|
+
## Validation Results
|
|
200
|
+
|
|
201
|
+
Validated on Bun `v1.3.12`.
|
|
202
|
+
|
|
203
|
+
### Unit coverage
|
|
204
|
+
|
|
205
|
+
Verified by tests in:
|
|
206
|
+
|
|
207
|
+
- [`tests/unit/server-api.test.ts`](../tests/unit/server-api.test.ts)
|
|
208
|
+
- [`tests/unit/cli-webview.test.ts`](../tests/unit/cli-webview.test.ts)
|
|
209
|
+
- [`tests/unit/webview-automation.test.ts`](../tests/unit/webview-automation.test.ts)
|
|
210
|
+
|
|
211
|
+
Covered behavior:
|
|
212
|
+
|
|
213
|
+
- WebView status over HTTP
|
|
214
|
+
- start/stop lifecycle over HTTP
|
|
215
|
+
- evaluate/resize/screenshot over HTTP
|
|
216
|
+
- CLI status/start/evaluate/resize/screenshot/stop commands
|
|
217
|
+
- graceful unsupported-runtime handling
|
|
218
|
+
- SDK start/evaluate/resize/screenshot flow
|
|
219
|
+
|
|
220
|
+
### Live runtime smoke
|
|
221
|
+
|
|
222
|
+
Validated manually after upgrading the local runtime to Bun `1.3.12`:
|
|
223
|
+
|
|
224
|
+
- `pmx-canvas --port=4529 --no-open --webview-automation --webview-backend=chrome`
|
|
225
|
+
- `GET /api/workbench/webview`
|
|
226
|
+
- `DELETE /api/workbench/webview`
|
|
227
|
+
- SDK smoke with:
|
|
228
|
+
- `startAutomationWebView`
|
|
229
|
+
- `evaluateAutomationWebView('document.title')`
|
|
230
|
+
- `resizeAutomationWebView(...)`
|
|
231
|
+
- `screenshotAutomationWebView(...)`
|
|
232
|
+
|
|
233
|
+
Observed results:
|
|
234
|
+
|
|
235
|
+
- automation session started successfully
|
|
236
|
+
- status endpoint reported `active: true`
|
|
237
|
+
- JS evaluation returned `"PMX Canvas"`
|
|
238
|
+
- viewport resize updated status correctly
|
|
239
|
+
- screenshots returned non-zero image bytes on both WebKit and Chrome backends during smoke testing
|
|
240
|
+
|
|
241
|
+
## Implementation Notes
|
|
242
|
+
|
|
243
|
+
### Screenshot normalization bug
|
|
244
|
+
|
|
245
|
+
During real runtime validation, a bug was found in the first implementation:
|
|
246
|
+
|
|
247
|
+
- PMX Canvas assumed `view.screenshot()` returned only `Uint8Array` or `ArrayBuffer`
|
|
248
|
+
- on this machine, Bun could also return a `Blob`
|
|
249
|
+
- that caused zero-byte screenshots in the wrapper even though Bun was returning valid image data
|
|
250
|
+
|
|
251
|
+
This was fixed in [`src/server/server.ts`](../src/server/server.ts) by normalizing:
|
|
252
|
+
|
|
253
|
+
- `Uint8Array`
|
|
254
|
+
- `ArrayBuffer`
|
|
255
|
+
- `Blob`
|
|
256
|
+
|
|
257
|
+
The regression is now covered by [`tests/unit/webview-automation.test.ts`](../tests/unit/webview-automation.test.ts).
|
|
258
|
+
|
|
259
|
+
### Why the interactive browser path still exists
|
|
260
|
+
|
|
261
|
+
Even with Bun `v1.3.12`, PMX Canvas should still keep `openUrlInExternalBrowser()` for the normal canvas window because Bun's current documented WebView surface is still effectively headless automation. There is no reason yet to promise a headed replacement window to users.
|
|
262
|
+
|
|
263
|
+
## Known Limits
|
|
264
|
+
|
|
265
|
+
These are current, accepted constraints:
|
|
266
|
+
|
|
267
|
+
- no visible Bun-managed canvas window
|
|
268
|
+
- no persistent automation-session orchestration beyond the single owned server session
|
|
269
|
+
- no Chrome-only CDP tool surface yet
|
|
270
|
+
|
|
271
|
+
## Future Work
|
|
272
|
+
|
|
273
|
+
### Near-term
|
|
274
|
+
|
|
275
|
+
The most obvious next steps are:
|
|
276
|
+
|
|
277
|
+
1. Add an optional `canvas_cdp` MCP tool for Chrome-backed sessions only
|
|
278
|
+
2. Decide whether the default macOS backend should stay `webkit` or move to `chrome` for stricter cross-platform parity
|
|
279
|
+
3. Add more backend-specific test coverage if Bun behavior diverges between WebKit and Chrome
|
|
280
|
+
|
|
281
|
+
### Later
|
|
282
|
+
|
|
283
|
+
Defer these until Bun's API justifies them:
|
|
284
|
+
|
|
285
|
+
1. Replace `openUrlInExternalBrowser()` with Bun.WebView for the normal interactive canvas window
|
|
286
|
+
2. Add headed window management semantics
|
|
287
|
+
3. Build user-facing browser controls around Bun.WebView if Bun documents those behaviors as stable
|
|
288
|
+
|
|
289
|
+
## Decision Summary
|
|
290
|
+
|
|
291
|
+
The project should continue with this split:
|
|
292
|
+
|
|
293
|
+
- **Interactive canvas for humans**: external browser
|
|
294
|
+
- **Programmatic canvas automation for agents/server workflows**: Bun.WebView
|
|
295
|
+
|
|
296
|
+
That keeps the current user-facing behavior stable while giving PMX Canvas a real browser automation surface that is built into the runtime.
|
package/docs/cli.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# CLI reference
|
|
2
|
+
|
|
3
|
+
The CLI is the shell-native way to run and control PMX Canvas. It targets
|
|
4
|
+
`http://localhost:4313` by default — override with `PMX_CANVAS_URL` or
|
|
5
|
+
`PMX_CANVAS_PORT` when the server runs elsewhere.
|
|
6
|
+
|
|
7
|
+
## Server lifecycle
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pmx-canvas # Start canvas, open browser
|
|
11
|
+
pmx-canvas --demo # Start with the project-tour demo board
|
|
12
|
+
pmx-canvas --port=8080 # Custom port
|
|
13
|
+
pmx-canvas --no-open # Headless (for agents/CI)
|
|
14
|
+
pmx-canvas --theme=light # dark | light | high-contrast
|
|
15
|
+
pmx-canvas --mcp # Run as MCP server (stdio)
|
|
16
|
+
pmx-canvas --webview-automation # Start headless Bun.WebView session
|
|
17
|
+
pmx-canvas open # Open the current workbench in a browser
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Daemon mode
|
|
21
|
+
|
|
22
|
+
Run detached with pid/log tracking instead of holding a terminal:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pmx-canvas serve --daemon --no-open --wait-ms=20000 # Start detached, wait for health
|
|
26
|
+
pmx-canvas serve status # Inspect daemon health + pid
|
|
27
|
+
pmx-canvas serve stop # Stop the daemon for this port
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Nodes and edges
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pmx-canvas node add --type webpage --url https://example.com/docs
|
|
34
|
+
pmx-canvas node add --type web-artifact --title "Dashboard" --app-file ./App.tsx
|
|
35
|
+
pmx-canvas node add --type graph --graph-type bar --data-file ./metrics.json --x-key label --y-key value
|
|
36
|
+
pmx-canvas node add --type graph --graph-type bar --data '[{"x":"a","y":1}]' --x-key x --y-key y
|
|
37
|
+
pmx-canvas graph add --graph-type bar --data '[{"x":"a","y":1}]' --x-key x --y-key y # Alias
|
|
38
|
+
pmx-canvas node add --help --type webpage --json # Schema for one type
|
|
39
|
+
|
|
40
|
+
pmx-canvas external-app add --kind excalidraw --title "Diagram"
|
|
41
|
+
|
|
42
|
+
pmx-canvas edge add --from-search "DVT O3 — GitOps" --to-search "deep work trend" --type relation
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`--from-search` / `--to-search` must each resolve to exactly one node — broad
|
|
46
|
+
queries fail rather than guess. Use the full visible title.
|
|
47
|
+
|
|
48
|
+
CLI create commands return the created node shape with normalized title,
|
|
49
|
+
content, and geometry, which makes scripting stacked layouts and batch
|
|
50
|
+
follow-ups easier.
|
|
51
|
+
|
|
52
|
+
### Graph height flags
|
|
53
|
+
|
|
54
|
+
Graph height flags split by target:
|
|
55
|
+
|
|
56
|
+
- `--node-height` / `--nodeHeight` — the canvas node frame
|
|
57
|
+
- `--chart-height` — the chart content inside the node
|
|
58
|
+
- `--height` — accepted as a frame-height compatibility alias
|
|
59
|
+
|
|
60
|
+
For MCP/HTTP payloads, use `nodeHeight` for the frame and `height` for chart
|
|
61
|
+
content.
|
|
62
|
+
|
|
63
|
+
## Discovery and validation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pmx-canvas node schema --type json-render --component Table --summary
|
|
67
|
+
pmx-canvas validate # Layout validation
|
|
68
|
+
pmx-canvas validate spec --type json-render --spec-file ./dashboard.json --summary
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The schema commands surface the running server's data, which is strictly
|
|
72
|
+
better than guessing flags or payloads.
|
|
73
|
+
|
|
74
|
+
## Batch and arrange
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pmx-canvas batch --file ./canvas-ops.json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
See [HTTP API → batch](http-api.md#batch-operations) for the operation
|
|
81
|
+
schema; the same JSON works for the CLI batch file.
|
|
82
|
+
|
|
83
|
+
## Web artifacts
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pmx-canvas web-artifact build --title "Dashboard" --app-file ./App.tsx --deps recharts --include-logs
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Failed or empty CLI bundles print `ok: false`, exit non-zero, and do not
|
|
90
|
+
create a canvas node.
|
|
91
|
+
|
|
92
|
+
## Watch (semantic deltas)
|
|
93
|
+
|
|
94
|
+
`pmx-canvas watch` consumes the SSE stream and emits compact semantic deltas
|
|
95
|
+
for agents that need low-token updates instead of full layout snapshots. It
|
|
96
|
+
filters noise from harmless moves and reports meaningful events such as pins,
|
|
97
|
+
node additions/removals, group changes, edge connections, and moves that
|
|
98
|
+
change spatial clustering.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pmx-canvas watch --events context-pin,move-end
|
|
102
|
+
pmx-canvas watch --json --events context-pin --max-events 1
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Focus
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pmx-canvas focus <node-id> # Pan viewport to a node
|
|
109
|
+
pmx-canvas focus <node-id> --no-pan # Select/raise without panning
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## WebView automation
|
|
113
|
+
|
|
114
|
+
Drive a headless Bun.WebView (Chromium or WebKit) pointed at the workbench:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pmx-canvas webview status
|
|
118
|
+
pmx-canvas webview start --backend chrome --width 1440 --height 900
|
|
119
|
+
pmx-canvas webview evaluate --expression "document.title"
|
|
120
|
+
pmx-canvas webview resize --width 1280 --height 800
|
|
121
|
+
pmx-canvas webview screenshot --output ./canvas.png
|
|
122
|
+
pmx-canvas webview stop
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Use WebView for visual annotation inspection. Agent-readable canvas context only
|
|
126
|
+
reports annotation targets and bounds; it does not describe whether the human
|
|
127
|
+
drew an arrow, line, circle, or other shape. Inspect `.annotation-layer path` or
|
|
128
|
+
take a screenshot when the drawn form matters.
|
|
129
|
+
|
|
130
|
+
Humans draw with the pen toolbar button and remove marks with the eraser button.
|
|
131
|
+
If an agent already knows the annotation ID from context, it can remove it through
|
|
132
|
+
MCP with `canvas_remove_annotation`.
|
|
133
|
+
|
|
134
|
+
## When to reach for the CLI
|
|
135
|
+
|
|
136
|
+
- Direct terminal control without MCP wiring
|
|
137
|
+
- Shell scripts and CI-friendly automation
|
|
138
|
+
- Schema-driven discovery from the running server
|
|
139
|
+
- Local debugging of canvas, webview, and screenshot flows
|
|
140
|
+
- A control surface that covers normal canvas work without MCP wiring
|