pmx-canvas 0.7.3 → 0.8.2
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/.github/extensions/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
- package/.github/extensions/pmx-canvas/extension.mjs +25 -172
- package/.github/extensions/pmx-canvas/mcp-bootstrap.ts +198 -0
- package/.github/extensions/pmx-canvas/runtime.d.mts +41 -0
- package/.github/extensions/pmx-canvas/runtime.json +3 -0
- package/.github/extensions/pmx-canvas/runtime.mjs +194 -0
- package/.github/extensions/pmx-canvas/start-mcp.mjs +51 -0
- package/.github/extensions/pmx-canvas/tools.json +2560 -0
- package/CHANGELOG.md +64 -0
- package/Readme.md +21 -7
- package/dist/canvas/fonts/OFL.txt +93 -0
- package/dist/canvas/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-ext-400-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-ext-500-normal.woff2 +0 -0
- package/dist/canvas/fonts/ibm-plex-sans-latin-ext-600-normal.woff2 +0 -0
- package/dist/canvas/global.css +726 -674
- package/dist/canvas/index.js +90 -88
- package/dist/canvas/mcp-app.html +7879 -0
- package/dist/canvas/mermaid-entry.js +1 -1
- package/dist/canvas/surface-theme.css +151 -46
- package/dist/json-render/index.css +81 -1
- package/dist/json-render/index.js +1 -1
- package/dist/types/cli/commands/record.d.ts +1 -1
- package/dist/types/client/canvas/NodeContextMark.d.ts +24 -0
- package/dist/types/client/canvas/SessionReceipt.d.ts +3 -1
- package/dist/types/client/icons.d.ts +1 -2
- package/dist/types/client/mcp-app/index.d.ts +1 -0
- package/dist/types/client/nodes/HtmlNode.d.ts +1 -0
- package/dist/types/client/nodes/ax-node-actions.d.ts +2 -2
- package/dist/types/client/nodes/markdown-sanitize.d.ts +2 -0
- package/dist/types/client/nodes/use-workbench-asset.d.ts +2 -0
- package/dist/types/client/state/attention-store.d.ts +0 -5
- package/dist/types/client/state/context-status-store.d.ts +53 -0
- package/dist/types/client/state/intent-bridge.d.ts +3 -0
- package/dist/types/client/state/near-pin-store.d.ts +16 -0
- package/dist/types/client/state/presence-store.d.ts +5 -0
- package/dist/types/client/state/session-store.d.ts +33 -3
- package/dist/types/client/state/workbench-transport.d.ts +16 -0
- package/dist/types/client/theme/tokens.d.ts +1 -3
- package/dist/types/client/types.d.ts +9 -0
- package/dist/types/json-render/server.d.ts +1 -1
- package/dist/types/mcp/app-server.d.ts +3 -0
- package/dist/types/mcp/canvas-access.d.ts +1 -1
- package/dist/types/mcp/canvas-app.d.ts +4 -0
- package/dist/types/mcp/workbench-app.d.ts +4 -0
- package/dist/types/server/agent-presence.d.ts +1 -1
- package/dist/types/server/ax-state.d.ts +1 -1
- package/dist/types/server/canvas-db.d.ts +8 -0
- package/dist/types/server/canvas-geometry.d.ts +25 -0
- package/dist/types/server/canvas-operations.d.ts +1 -11
- package/dist/types/server/canvas-state.d.ts +25 -3
- package/dist/types/server/context-brief.d.ts +8 -1
- package/dist/types/server/context-reads.d.ts +30 -7
- package/dist/types/server/index.d.ts +6 -1
- package/dist/types/server/mcp-app-runtime.d.ts +1 -0
- package/dist/types/server/operations/http.d.ts +2 -0
- package/dist/types/server/operations/invoker.d.ts +4 -2
- package/dist/types/server/operations/ops/nodes.d.ts +0 -6
- package/dist/types/server/server.d.ts +1 -0
- package/dist/types/server/spatial-analysis.d.ts +2 -0
- package/dist/types/shared/agent-context.d.ts +22 -0
- package/dist/types/shared/agent-presence.d.ts +3 -10
- package/dist/types/shared/canvas-app.d.ts +54 -0
- package/dist/types/shared/themes.d.ts +1 -1
- package/docs/RELEASE.md +7 -3
- package/docs/agent-plugin.md +123 -0
- package/docs/ax-state-contract.md +40 -0
- package/docs/cli.md +7 -2
- package/docs/design/AgentContext.dc.html +186 -0
- package/docs/design/Before.dc.html +208 -0
- package/docs/design/BoardPins.dc.html +151 -0
- package/docs/design/Chrome.dc.html +211 -0
- package/docs/design/Context.dc.html +239 -0
- package/docs/design/Flows.dc.html +181 -0
- package/docs/design/Home.dc.html +209 -0
- package/docs/design/HomeGraph.dc.html +211 -0
- package/docs/design/HomeMap.dc.html +117 -0
- package/docs/design/HomeTeam.dc.html +176 -0
- package/docs/design/Light.dc.html +28 -0
- package/docs/design/Main.dc.html +280 -0
- package/docs/design/NearPin.dc.html +260 -0
- package/docs/design/Pane600.dc.html +120 -0
- package/docs/design/Relations.dc.html +297 -0
- package/docs/design/Themes.dc.html +121 -0
- package/docs/design/TokenSystem.dc.html +136 -0
- package/docs/design/Tokens.dc.html +163 -0
- package/docs/design/Types1.dc.html +177 -0
- package/docs/design/Types2.dc.html +226 -0
- package/docs/design/Types3.dc.html +195 -0
- package/docs/design/Uses.dc.html +152 -0
- package/docs/design/Vision.dc.html +116 -0
- package/docs/design/Zoom.dc.html +82 -0
- package/docs/design/canvas.json +274 -0
- package/docs/design.md +217 -0
- package/docs/environment.md +1 -1
- package/docs/http-api.md +86 -16
- package/docs/mcp.md +202 -4
- package/docs/node-types.md +34 -10
- package/docs/plans/plan-009-tech-debt-backlog.md +1 -1
- package/docs/plans/plan-015-design-foundation-wave-0.md +177 -0
- package/docs/plans/plan-016-context-made-visible-wave-1.md +148 -0
- package/docs/product-vision-2026-09.md +47 -7
- package/docs/screenshot.png +0 -0
- package/docs/sdk.md +1 -0
- package/package.json +10 -4
- package/plugins/pmx-canvas/LICENSE +21 -0
- package/plugins/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
- package/plugins/pmx-canvas/assets/preview.png +0 -0
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/extension.mjs +930 -0
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +3 -0
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.mjs +194 -0
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/steering-delivery.mjs +79 -0
- package/plugins/pmx-canvas/mcp.json +12 -0
- package/plugins/pmx-canvas/plugin.json +24 -0
- package/plugins/pmx-canvas/runtime.json +3 -0
- package/plugins/pmx-canvas/runtime.mjs +194 -0
- package/plugins/pmx-canvas/start-mcp.mjs +51 -0
- package/plugins/pmx-canvas/tools.json +2560 -0
- package/skills/pmx-canvas/SKILL.md +29 -9
- package/skills/pmx-canvas/evals/evals.json +62 -0
- package/skills/pmx-canvas/references/ax-html-control-surface.md +6 -0
- package/skills/pmx-canvas/references/full-reference.md +11 -7
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +20 -8
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
- package/skills/pmx-canvas-testing/SKILL.md +5 -4
- package/src/cli/commands/copilot.ts +5 -0
- package/src/cli/commands/nodes.ts +3 -2
- package/src/cli/commands/view.ts +1 -1
- package/src/cli/index.ts +10 -4
- package/src/client/App.tsx +6 -1
- package/src/client/canvas/AgentPresenceLayer.tsx +3 -3
- package/src/client/canvas/AnnotationLayer.tsx +1 -1
- package/src/client/canvas/CanvasNode.tsx +32 -49
- package/src/client/canvas/CanvasViewport.tsx +0 -2
- package/src/client/canvas/CommandPalette.tsx +3 -2
- package/src/client/canvas/ContextMenu.tsx +11 -0
- package/src/client/canvas/EdgeLayer.tsx +1 -1
- package/src/client/canvas/ExportDialog.tsx +33 -6
- package/src/client/canvas/IntentLayer.tsx +2 -2
- package/src/client/canvas/Minimap.tsx +12 -7
- package/src/client/canvas/NodeContextMark.tsx +156 -0
- package/src/client/canvas/SessionPanel.tsx +4 -7
- package/src/client/canvas/SessionReceipt.tsx +114 -17
- package/src/client/canvas/ShortcutOverlay.tsx +6 -1
- package/src/client/canvas/SnapshotPanel.tsx +11 -2
- package/src/client/canvas/ToolRail.tsx +12 -9
- package/src/client/canvas/TopBar.tsx +16 -11
- package/src/client/icons.tsx +2 -12
- package/src/client/mcp-app/index.tsx +137 -0
- package/src/client/mcp-app/style.css +10 -0
- package/src/client/nodes/AttachmentNode.tsx +8 -1
- package/src/client/nodes/AxStepControls.tsx +1 -1
- package/src/client/nodes/ContextNode.tsx +9 -9
- package/src/client/nodes/ExtAppFrame.tsx +13 -8
- package/src/client/nodes/FileNode.tsx +8 -5
- package/src/client/nodes/HtmlNode.tsx +12 -2
- package/src/client/nodes/ImageNode.tsx +4 -2
- package/src/client/nodes/InlineMarkdownEditor.tsx +2 -1
- package/src/client/nodes/LedgerNode.tsx +2 -2
- package/src/client/nodes/MarkdownNode.tsx +44 -9
- package/src/client/nodes/McpAppNode.tsx +6 -4
- package/src/client/nodes/PromptNode.tsx +5 -17
- package/src/client/nodes/ResponseNode.tsx +3 -15
- package/src/client/nodes/StatusNode.tsx +2 -2
- package/src/client/nodes/StatusSummary.tsx +3 -1
- package/src/client/nodes/TraceNode.tsx +6 -4
- package/src/client/nodes/WebpageNode.tsx +1 -1
- package/src/client/nodes/ax-node-actions.ts +2 -2
- package/src/client/nodes/iframe-document-url.ts +3 -2
- package/src/client/nodes/markdown-sanitize.ts +10 -0
- package/src/client/nodes/surface-url.ts +10 -0
- package/src/client/nodes/use-surface-frame.ts +3 -1
- package/src/client/nodes/use-workbench-asset.ts +26 -0
- package/src/client/state/attention-bridge.ts +0 -8
- package/src/client/state/attention-store.ts +0 -17
- package/src/client/state/canvas-store.ts +4 -2
- package/src/client/state/context-status-store.ts +66 -0
- package/src/client/state/human-store.ts +2 -0
- package/src/client/state/iframe-mode.ts +5 -0
- package/src/client/state/intent-bridge.ts +10 -4
- package/src/client/state/near-pin-store.ts +53 -0
- package/src/client/state/presence-store.ts +5 -10
- package/src/client/state/session-store.ts +106 -9
- package/src/client/state/sse-bridge.ts +26 -7
- package/src/client/state/theme-override.ts +1 -1
- package/src/client/state/workbench-transport.ts +36 -0
- package/src/client/theme/global.css +726 -674
- package/src/client/theme/surface-theme.css +151 -46
- package/src/client/theme/tokens.ts +7 -11
- package/src/client/types.ts +10 -0
- package/src/json-render/renderer/index.css +6 -1
- package/src/json-render/renderer/index.tsx +0 -1
- package/src/json-render/server.ts +71 -14
- package/src/mcp/app-server.ts +64 -0
- package/src/mcp/canvas-access.ts +14 -11
- package/src/mcp/canvas-app.ts +318 -0
- package/src/mcp/server.ts +1 -1
- package/src/mcp/workbench-app.ts +211 -0
- package/src/server/agent-presence.ts +45 -6
- package/src/server/ax-context.ts +1 -1
- package/src/server/ax-state.ts +1 -1
- package/src/server/board-export.ts +5 -2
- package/src/server/canvas-db.ts +46 -12
- package/src/server/canvas-geometry.ts +64 -0
- package/src/server/canvas-operations.ts +7 -25
- package/src/server/canvas-state.ts +105 -15
- package/src/server/canvas-validation.ts +19 -4
- package/src/server/context-brief.ts +39 -2
- package/src/server/context-reads.ts +87 -15
- package/src/server/demo-state.json +31 -31
- package/src/server/html-surface.ts +4 -5
- package/src/server/index.ts +41 -5
- package/src/server/mcp-app-runtime.ts +11 -0
- package/src/server/operations/composites.ts +4 -3
- package/src/server/operations/http.ts +4 -4
- package/src/server/operations/invoker.ts +13 -4
- package/src/server/operations/mcp.ts +6 -0
- package/src/server/operations/ops/ax-read.ts +1 -1
- package/src/server/operations/ops/ax-timeline.ts +37 -0
- package/src/server/operations/ops/boards.ts +1 -1
- package/src/server/operations/ops/canvas-wire.ts +3 -6
- package/src/server/operations/ops/intent.ts +31 -2
- package/src/server/operations/ops/json-render.ts +6 -2
- package/src/server/operations/ops/nodes.ts +8 -76
- package/src/server/operations/ops/query.ts +8 -2
- package/src/server/operations/ops/snapshots.ts +4 -1
- package/src/server/operations/ops/viewport.ts +29 -5
- package/src/server/operations/registry.ts +41 -5
- package/src/server/scope-fence.ts +55 -10
- package/src/server/server.ts +83 -5
- package/src/server/spatial-analysis.ts +2 -2
- package/src/server/workboard.ts +6 -1
- package/src/{server → shared}/agent-context.ts +2 -2
- package/src/shared/agent-presence.ts +3 -15
- package/src/shared/canvas-app.ts +62 -0
- package/src/shared/themes.ts +5 -5
- package/src/client/canvas/FocusFieldLayer.tsx +0 -116
- package/src/client/canvas/kind-colors.ts +0 -23
|
@@ -20,8 +20,20 @@ At the start of board work, read `canvas://context?consumer=<stable-unique-id>`
|
|
|
20
20
|
(or `canvas_query { action: "context", consumer: "<stable-unique-id>" }`) before
|
|
21
21
|
falling back to broader resources. The budget is UTF-16 code units, not tokens.
|
|
22
22
|
Use one stable consumer ID per agent/adapter only when durable deltas are wanted;
|
|
23
|
-
omit it for a fresh read. Pins are highest priority
|
|
24
|
-
|
|
23
|
+
omit it for a fresh read. Pins are highest priority, then the cards near each pin
|
|
24
|
+
(reason `near`, title + short summary only). If a source card is clipped or near,
|
|
25
|
+
pull that card explicitly with `canvas_node { action: "get", board, id, full: true }`.
|
|
26
|
+
|
|
27
|
+
**Read → check → refresh:** after reading context, inspect `canvas_ax_timeline {
|
|
28
|
+
action: "read-status", board }`. No entry means no recorded content delivery;
|
|
29
|
+
`readRevision < contentRevision` on the current card means changed since read.
|
|
30
|
+
Re-read that card with `full: true`, then check status again before acting on it.
|
|
31
|
+
Full HTTP/CLI node reads and SDK `getNode` also record the delivered revision;
|
|
32
|
+
compact MCP metadata, CLI `--summary`/`--field`, and workbench reads do not.
|
|
33
|
+
Compact MCP responses that contain text (such as Markdown) do count as delivery.
|
|
34
|
+
In 0.8.0, direct node gets were untracked; use a context read on that version.
|
|
35
|
+
A read mark proves delivery, not understanding or approval. Agent attribution
|
|
36
|
+
describes who acted; it never grants permission or wakes an idle agent.
|
|
25
37
|
|
|
26
38
|
When authoring a board, establish its README without waiting for the human to
|
|
27
39
|
click a button. Read `canvas_board { action: "get" }`; if `readmeNodeId` is null,
|
|
@@ -43,7 +55,7 @@ for the authoritative stop, viewport, persistence, reset, group-order, and captu
|
|
|
43
55
|
|
|
44
56
|
## Runtime prerequisites
|
|
45
57
|
|
|
46
|
-
PMX Canvas 0.
|
|
58
|
+
PMX Canvas 0.8.2 requires **Bun >=1.4.2**, including when installed through npm.
|
|
47
59
|
Check `bun --version` and ensure Bun is on the MCP host's PATH, not just your shell's;
|
|
48
60
|
use an absolute executable path if needed. Install/configure only when requested.
|
|
49
61
|
For pinned installation, MCP configuration, managed services, and disposable verification,
|
|
@@ -116,7 +128,8 @@ the served catalog is a startup snapshot. Local mirrors still use `skills sync`
|
|
|
116
128
|
`canvas_view { action: "fit", nodeIds: [...] }` with exactly the new ids. See
|
|
117
129
|
**In-View Placement & Sizing** below — auto-placement is board-relative, not camera-relative.
|
|
118
130
|
8. **Verify context pins.** Pin with `canvas_pin_nodes` or the browser's **Pin as context**, then
|
|
119
|
-
read `canvas://pinned-context`.
|
|
131
|
+
read `canvas://pinned-context`. When you pin, pass a short `reason` — the human sees who pinned a
|
|
132
|
+
node and why.
|
|
120
133
|
9. **Clean up temporary nodes.** Remove retry/test fixtures and restore the baseline snapshot when
|
|
121
134
|
the task requires leaving the board unchanged.
|
|
122
135
|
|
|
@@ -219,7 +232,7 @@ always authoritative, independent of the installed release version.
|
|
|
219
232
|
| `canvas_ax_state` | `get`, `set-focus`, `set-policy`, `report-capability`, `presence`, `set-presence` |
|
|
220
233
|
| `canvas_ax_work` | `add`, `update`, `annotate` |
|
|
221
234
|
| `canvas_ax_gate` | `request`, `resolve`, `await` with `approval`, `elicitation`, or `mode` |
|
|
222
|
-
| `canvas_ax_timeline` | `read`, `record-event`, `add-evidence`, `send-steering`, `reads` |
|
|
235
|
+
| `canvas_ax_timeline` | `read`, `record-event`, `add-evidence`, `send-steering`, `reads`, `read-status` |
|
|
223
236
|
| `canvas_ax_delivery` | `claim`, `mark` |
|
|
224
237
|
| `canvas_board` | `list`, `get`, `create`, `create-from`, `open`, `update` |
|
|
225
238
|
| `canvas_snapshot` | `save`, `list`, `restore`, `delete`, `gc`, `diff` |
|
|
@@ -303,8 +316,9 @@ reports any node below its floor as an advisory `sizeWarnings` entry — treat a
|
|
|
303
316
|
as layout work left to do.
|
|
304
317
|
Creation responses may include `sizeAdjustment` (`defaulted`, `clamped-to-minimum`, or
|
|
305
318
|
`fit-to-children`); use its `applied` geometry rather than assuming the request won. Json-render
|
|
306
|
-
validation/creation
|
|
307
|
-
|
|
319
|
+
validation/creation binds a literal form-control `value` to `state.form` automatically; it still
|
|
320
|
+
warns for `$state` expressions, controls inside a repeat, or a non-object `state.form`, which render
|
|
321
|
+
but do not update runtime state until bound with `$bindState`/`$bindItem`.
|
|
308
322
|
Bound JSON input and dynamic lists are local UI state, not saved canvas data. Focus-mode
|
|
309
323
|
expand/close preserves that state for the same spec in the current tab; an authored spec update,
|
|
310
324
|
board switch or page reload resets it. Persist important edits explicitly through the app's
|
|
@@ -379,6 +393,12 @@ What the session asks of you:
|
|
|
379
393
|
`agentId` values are for actual independent subagents, not steps in one chat. Attaching over a
|
|
380
394
|
non-empty board saved a `Before session · …` snapshot; detaching emits the receipt (items
|
|
381
395
|
done / vetoed, a diff against that snapshot, one-click restore) — an idle timeout delays it.
|
|
396
|
+
- **Inspect receipt touch rows:** Read lists delivered content, Pinned lists pins, and
|
|
397
|
+
Created/Edited come from the session snapshot diff. Creating then editing one card puts
|
|
398
|
+
it in Created, not both rows. A stale warning means the pin changed after its read.
|
|
399
|
+
For example, after reading A, editing existing B and creating C, use **Dim untouched
|
|
400
|
+
nodes** to fade an untouched D to 0.35 opacity; A/B/C remain visible. The lens changes
|
|
401
|
+
presentation, not content, pin membership, approval or delivery.
|
|
382
402
|
- **403 = outside the scope fence.** The human may fence you to a region (`policy.scope`): writes
|
|
383
403
|
outside it are refused with a reason naming the node or position (a fenced group frame
|
|
384
404
|
grants its members too). Read `policy.scope` in `canvas://ax-context`, ask the human to widen
|
|
@@ -440,7 +460,7 @@ Use the visible workbench when the human is actively curating layout:
|
|
|
440
460
|
carries the tools (Select V, Pan Space, Connect C), Markdown note M, Attach files, webpage W,
|
|
441
461
|
group G, and separate Draw A, Text note and Eraser buttons for board feedback,
|
|
442
462
|
and utilities: search & commands (Cmd+K — actions with shortcuts, then jump-to-node), arrange,
|
|
443
|
-
trace, minimap, history, the theme picker (nine themes:
|
|
463
|
+
trace, minimap, history, the theme picker (nine themes: harbor, daylight, high-contrast, midnight,
|
|
444
464
|
sepia, arctic, ember, forest, volt), and shortcuts (?). The top bar holds the connection dot,
|
|
445
465
|
workspace title, the session chip / gate badge / context meter while a session is attached
|
|
446
466
|
(or the external-writers indicator and *Start agent session* otherwise), and the zoom cluster
|
|
@@ -456,7 +476,7 @@ Use the visible workbench when the human is actively curating layout:
|
|
|
456
476
|
- Embedding hosts can open `/workbench?theme=<name>` (or `?theme=auto` to follow the host's
|
|
457
477
|
light/dark appearance) for a session-local default theme that never changes the server-global
|
|
458
478
|
theme other clients see; an explicit pick from the theme menu ends the override. The bundled
|
|
459
|
-
Copilot extension opens its panel with `?theme=
|
|
479
|
+
Copilot extension opens its panel with `?theme=daylight`.
|
|
460
480
|
|
|
461
481
|
After changing files under `src/client/`, rebuild with `bun run build` before manual browser
|
|
462
482
|
verification.
|
|
@@ -772,6 +772,68 @@
|
|
|
772
772
|
"type": "output_check"
|
|
773
773
|
}
|
|
774
774
|
]
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
"id": 32,
|
|
778
|
+
"name": "read-refresh-and-receipt-loop",
|
|
779
|
+
"prompt": "On a disposable board, pin A and B. Read A, then let the human edit it. Refresh only A before acting. Read nearby card C's source too. End your self-owned session after editing existing D and creating then editing E. Explain the receipt and dim untouched F. Does a read badge mean you understood or approved the content?",
|
|
780
|
+
"expected_output": "Uses a stable consumer for context and checks read-status. Fetches stale A and nearby C with canvas_node get full:true; compares recorded and current content revisions, leaving B unread unless actually delivered. Explains compact metadata/CLI projections do not record full delivery and 0.8.0 direct gets were untracked. Receipt Read/Pinned are descriptive, D is Edited, E is Created only; untouched F dims. Does not equate attribution or delivery with approval, understanding or idle wakeup.",
|
|
781
|
+
"assertions": [
|
|
782
|
+
{
|
|
783
|
+
"name": "refreshes-exact-stale-source",
|
|
784
|
+
"description": "Checks revisions, fetches full A/C by board and node ID, verifies refreshed status, and does not falsely claim unrelated B was read",
|
|
785
|
+
"type": "output_check"
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
"name": "explains-receipt-without-authority",
|
|
789
|
+
"description": "Distinguishes Created from Edited, verifies an untouched lens control, and calls reads delivery evidence rather than understanding, approval or wakeup",
|
|
790
|
+
"type": "output_check"
|
|
791
|
+
}
|
|
792
|
+
]
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
"id": 33,
|
|
796
|
+
"name": "first-entry-header-targets",
|
|
797
|
+
"prompt": "Verify Expand and Add to context on a disposable card by moving directly from outside to each at-rest button coordinate. A prior release shifted controls on hover and sometimes deleted cards. Is a successful keyboard Enter enough to close this bug?",
|
|
798
|
+
"expected_output": "Measures at-rest targets before hover, clicks those original coordinates on first entry, and checks expansion/pin state plus retained node identity. Includes keyboard activation only as a control, not pointer proof. Uses Undo if a test-owned card is accidentally deleted and retains failure evidence.",
|
|
799
|
+
"assertions": [
|
|
800
|
+
{
|
|
801
|
+
"name": "tests-real-first-entry-pointer",
|
|
802
|
+
"description": "Uses original at-rest coordinates, confirms intended action and no deletion, and does not substitute pre-hover or keyboard-only success",
|
|
803
|
+
"type": "output_check"
|
|
804
|
+
}
|
|
805
|
+
]
|
|
806
|
+
},
|
|
807
|
+
{
|
|
808
|
+
"id": 34,
|
|
809
|
+
"name": "spec-only-title-preservation",
|
|
810
|
+
"prompt": "Create a JSON card titled Protected custom title whose spec heading is Different heading. Replace only its spec with a New heading, then explicitly rename it. What should happen to its title and local form draft?",
|
|
811
|
+
"expected_output": "Verifies spec-only replacement preserves Protected custom title, explicit rename changes it, and authored spec replacement resets local runtime state. On old 0.8.0, includes the existing title as a workaround rather than silently accepting inferred renaming.",
|
|
812
|
+
"assertions": [
|
|
813
|
+
{
|
|
814
|
+
"name": "checks-independent-title-and-spec",
|
|
815
|
+
"description": "Uses distinct custom/inferred names, checks spec-only preservation and explicit rename, and distinguishes runtime reset from title loss",
|
|
816
|
+
"type": "output_check"
|
|
817
|
+
}
|
|
818
|
+
]
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
"id": 35,
|
|
822
|
+
"name": "late-html-ax-enable",
|
|
823
|
+
"prompt": "Mount an HTML form with AX disabled, then enable ax.work.create without changing its HTML. Exercise enable, disable, re-enable and allowed-action changes in src and srcdoc. Can we preserve unsaved iframe drafts or claim that a queued steer wakes an idle agent?",
|
|
824
|
+
"expected_output": "Saves important local data before capability changes, which reload the HTML document. Waits for bridge bootstrap, exercises the action and verifies acknowledgement plus persisted work, and checks denial while disabled or not allowed. Tests both modes rather than using focus-mode remount as proof. Describes 0.8.0's workaround separately; no idle-wakeup claim.",
|
|
825
|
+
"assertions": [
|
|
826
|
+
{
|
|
827
|
+
"name": "verifies-mounted-capability-lifecycle",
|
|
828
|
+
"description": "Tests both embed modes on the mounted card, checks permitted and forbidden effects, and verifies real persistence rather than just bridge presence",
|
|
829
|
+
"type": "output_check"
|
|
830
|
+
},
|
|
831
|
+
{
|
|
832
|
+
"name": "respects-draft-and-delivery-boundaries",
|
|
833
|
+
"description": "Warns capability changes reload local drafts, preserves important data beforehand, and distinguishes queued steering from host delivery",
|
|
834
|
+
"type": "output_check"
|
|
835
|
+
}
|
|
836
|
+
]
|
|
775
837
|
}
|
|
776
838
|
]
|
|
777
839
|
}
|
|
@@ -24,6 +24,12 @@ Without `axCapabilities.enabled = true`, `window.PMX_AX` is **not** injected —
|
|
|
24
24
|
renders but can't emit. `allowed` narrows what it may emit (never escalates the type's
|
|
25
25
|
ceiling). Flip an existing node on with `canvas_node({ action: "update", id, axCapabilities: { enabled: true, allowed: [...] } })`.
|
|
26
26
|
|
|
27
|
+
Changing effective capabilities reloads the mounted HTML document in both `src` and
|
|
28
|
+
`srcdoc` modes, including disable/re-enable and allowed-action changes. Unsaved iframe-local
|
|
29
|
+
drafts reset: save important state through durable AX primitives before changing capabilities.
|
|
30
|
+
Wait for the new document, invoke the action, and verify both its acknowledgement and persisted
|
|
31
|
+
result. On 0.8.0, late enabling required a deliberate remount; upgrading fixes that missing bridge.
|
|
32
|
+
|
|
27
33
|
## Three footguns (this is why a hand-rolled node looks "inert")
|
|
28
34
|
|
|
29
35
|
1. **The iframe is sandboxed opaque-origin** (no `allow-same-origin`). `localStorage`,
|
|
@@ -128,11 +128,11 @@ pmx-canvas # Start and open browser (port 4313)
|
|
|
128
128
|
pmx-canvas --no-open # Start without opening browser (for agents)
|
|
129
129
|
pmx-canvas --port=8080 # Custom port
|
|
130
130
|
pmx-canvas --demo # Start with sample content
|
|
131
|
-
pmx-canvas --theme=
|
|
131
|
+
pmx-canvas --theme=daylight # Daylight theme
|
|
132
132
|
pmx-canvas --version # Print installed version and exit
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
`--theme` accepts `
|
|
135
|
+
`--theme` accepts `harbor` (default), `daylight`, `high-contrast`, `midnight`, `sepia`, `arctic`, `ember`, `forest`, or `volt` (0.4.x; the rail's theme picker lists the same nine). Same value can be set via
|
|
136
136
|
the `PMX_CANVAS_THEME` environment variable, or picked live from the left tool rail.
|
|
137
137
|
|
|
138
138
|
Start the canvas once per session, then reuse it. Use `--no-open` when running as an agent — the
|
|
@@ -452,7 +452,7 @@ single-purpose tools behind an `action` (and, for `canvas_ax_gate`, a `kind`) di
|
|
|
452
452
|
| `canvas_ax_state` | `get` · `set-focus` · `set-policy` · `report-capability` · `presence` · `set-presence` | Read AX state; set AX focus; patch tool/prompt policy (the scope fence is human-set, read-only here); report host capability; read / set agent presence (phase, cursor, focus, attached session) |
|
|
453
453
|
| `canvas_ax_work` | `add` · `update` · `annotate` | Canvas-bound work items + review annotations |
|
|
454
454
|
| `canvas_ax_gate` | `request` · `resolve` · `await` × `kind` `approval` \| `elicitation` \| `mode` | Attributed gate lifecycle (request → await → resolve); attribution does not itself grant authority |
|
|
455
|
-
| `canvas_ax_timeline` | `read` · `record-event` · `add-evidence` · `send-steering` · `reads` | The bounded AX diagnostics timeline, and the context read log (`reads`) |
|
|
455
|
+
| `canvas_ax_timeline` | `read` · `record-event` · `add-evidence` · `send-steering` · `reads` · `read-status` | The bounded AX diagnostics timeline, and the context read log (`reads`) |
|
|
456
456
|
| `canvas_ax_delivery` | `claim` · `mark` | Adapterless steering delivery (claim → act → mark) |
|
|
457
457
|
| `canvas_intent` | `signal` · `update` · `clear` | Ghost Cursor of Intent — announce a move before making it |
|
|
458
458
|
|
|
@@ -508,7 +508,7 @@ coming and can veto it mid-thought. Intents are ephemeral presence: never
|
|
|
508
508
|
persisted, auto-expiring (~8s), never in `canvas_query layout`.
|
|
509
509
|
|
|
510
510
|
Narrate → linked mutation → automatic settle:
|
|
511
|
-
1. `canvas_intent { action: "signal", kind: "create",
|
|
511
|
+
1. `canvas_intent { action: "signal", kind: "create", nodeType: "markdown", label: "Add evidence", reason: "capturing the failing test", confidence: 0.8 }` → returns `intent.id` and the `position` the canvas chose.
|
|
512
512
|
2. Make the real move and pass that id: `canvas_node { action: "add", intentId: <intent.id>, ... }`.
|
|
513
513
|
3. PMX rejects the mutation if the intent was vetoed or expired; otherwise the
|
|
514
514
|
successful mutation settles the ghost into the resulting node automatically.
|
|
@@ -522,9 +522,13 @@ mcp-app) and `canvas_webview` do **not** accept an `intentId` and reject it with
|
|
|
522
522
|
400 — to telegraph one of those, signal a ghost, then `clear` it (or let it
|
|
523
523
|
expire) and run the open *without* an `intentId`.
|
|
524
524
|
|
|
525
|
-
Per kind, pass the anchor it renders against: `position` for `
|
|
526
|
-
`nodeId` for `move`/`edit`/`remove`, `edge: { from, to, type }` for
|
|
527
|
-
|
|
525
|
+
Per kind, pass the anchor it renders against: `position` for `move` (optional for
|
|
526
|
+
`create`), `nodeId` for `move`/`edit`/`remove`, `edge: { from, to, type }` for
|
|
527
|
+
`connect`. **Omit `position` on a create unless you know where the node goes:** the
|
|
528
|
+
canvas then forms the ghost where it will auto-place the node, keeps staged ghosts
|
|
529
|
+
from stacking, and lands the linked create on its ghost. Never pass a placeholder
|
|
530
|
+
such as `{ x: 0, y: 0 }`. The payoff is **legibility** — `reason` is shown beneath
|
|
531
|
+
the ghost.
|
|
528
532
|
|
|
529
533
|
**When to use vs skip.** Signal for adds, removes, and moves of visible nodes;
|
|
530
534
|
connecting nodes; creating groups; layout reorganizations; meaningful title/content
|
|
@@ -4,6 +4,10 @@ Use this reference when PMX Canvas is running inside the GitHub Copilot app as a
|
|
|
4
4
|
extension. The adapter is intentionally thin: PMX Canvas remains the state owner, and the extension
|
|
5
5
|
maps Copilot SDK features onto PMX AX primitives.
|
|
6
6
|
|
|
7
|
+
The [standalone agent plugin](../../../docs/agent-plugin.md) bundles this adapter and PMX's
|
|
8
|
+
MCP launcher. Its native canvas is Copilot-only; other Agent Plugins-compatible clients use
|
|
9
|
+
the portable MCP tools and browser workbench.
|
|
10
|
+
|
|
7
11
|
## Adapter Identity
|
|
8
12
|
|
|
9
13
|
- Extension path: `.github/extensions/pmx-canvas/extension.mjs`
|
|
@@ -17,9 +21,9 @@ maps Copilot SDK features onto PMX AX primitives.
|
|
|
17
21
|
packaged extension directory into the repository:
|
|
18
22
|
`mkdir -p .github/extensions && cp -R node_modules/pmx-canvas/.github/extensions/pmx-canvas .github/extensions/`
|
|
19
23
|
2. Reload Copilot app extensions with `extensions_reload` so `project:pmx-canvas` is registered.
|
|
20
|
-
3.
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
3. The adapter discovers a matching workspace daemon or starts the pinned package version
|
|
25
|
+
in `runtime.json` with Bun. It needs Bun on `PATH`, not a global `pmx-canvas` executable.
|
|
26
|
+
The shared daemon stays running when the extension exits.
|
|
23
27
|
4. Open the canvas with `extensionId: "project:pmx-canvas"`, `canvasId: "pmx-canvas"`, and a stable
|
|
24
28
|
`instanceId`.
|
|
25
29
|
5. If the first `invoke_canvas_action` immediately after `open_canvas` returns
|
|
@@ -66,6 +70,8 @@ end it after each task. Explicit agent IDs are reserved for genuinely independen
|
|
|
66
70
|
The Copilot app webview can leave nested `srcdoc` and `blob:` iframes blank, so PMX should route
|
|
67
71
|
generated frame HTML through `/api/canvas/frame-documents/...` instead.
|
|
68
72
|
- Connects to a matching local PMX server for the current workspace, or starts one when needed.
|
|
73
|
+
- Uses the session's working directory for startup, context, presence, and steering; Copilot's
|
|
74
|
+
`workspacePath` points to session artifacts and is not the project root.
|
|
69
75
|
- Reads `/api/canvas/ax/context` and injects pinned/focused context from
|
|
70
76
|
`onUserPromptSubmitted`.
|
|
71
77
|
- Exposes adapter actions for status, AX context refresh, AX focus, and explicit session steering.
|
|
@@ -137,16 +143,22 @@ All fields are optional:
|
|
|
137
143
|
}
|
|
138
144
|
```
|
|
139
145
|
|
|
140
|
-
Default discovery
|
|
146
|
+
Default discovery:
|
|
141
147
|
|
|
142
|
-
1. `serverUrl` input.
|
|
143
|
-
2. `
|
|
144
|
-
|
|
145
|
-
|
|
148
|
+
1. An explicit `serverUrl` input or `PMX_CANVAS_URL`, without silently choosing another target.
|
|
149
|
+
2. Workspace daemon pid-file ports, the preferred `PMX_CANVAS_PORT` / `PMX_WEB_CANVAS_PORT`,
|
|
150
|
+
and the normal MCP fallback ports, verified against the workspace's real path.
|
|
151
|
+
3. Serialized daemon startup for the session working directory when `autoStart` is not `false`.
|
|
146
152
|
|
|
147
153
|
The adapter rejects an unrelated running PMX server unless `allowWorkspaceMismatch` is true,
|
|
148
154
|
including when `serverUrl` is explicit.
|
|
149
155
|
|
|
156
|
+
To package this adapter in another plugin, copy `extension.mjs`, `steering-delivery.mjs`,
|
|
157
|
+
`runtime.mjs`, and `runtime.json`. For the portable MCP connector, also copy `start-mcp.mjs`,
|
|
158
|
+
`tools.json`, and `THIRD_PARTY_LICENSES.txt`, and invoke `start-mcp.mjs` with Bun. The agent calls
|
|
159
|
+
`canvas_connect_workspace` with its absolute project directory before using board tools;
|
|
160
|
+
plugin initialization must never adopt the installation directory as a project.
|
|
161
|
+
|
|
150
162
|
If discovery fails, the panel shows a connection page, not a partial workbench. It checks the
|
|
151
163
|
original target automatically; **Check connection** retries immediately and **Start server**
|
|
152
164
|
explicitly allows local startup even if `autoStart` was disabled. After recovery it navigates
|
|
@@ -4,7 +4,7 @@ Use this reference when the `pmx-canvas` skill is installed but the `pmx-canvas`
|
|
|
4
4
|
|
|
5
5
|
## Prerequisites and version
|
|
6
6
|
|
|
7
|
-
The examples pin **PMX Canvas 0.
|
|
7
|
+
The examples pin **PMX Canvas 0.8.2**, which requires **Bun >=1.4.2** even when
|
|
8
8
|
installed through npm: the CLI runs through Bun, not Node. Check `bun --version`
|
|
9
9
|
first. If missing or older, follow the [Bun installation instructions](https://bun.sh/docs/installation)
|
|
10
10
|
with the user's authorization. Ensure Bun is on the MCP host's PATH as well as the
|
|
@@ -17,11 +17,11 @@ in `SKILL.md`. Do not pair newer checkout guidance with an older runtime unknowi
|
|
|
17
17
|
## Install from npm
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
npm install -g pmx-canvas@0.
|
|
20
|
+
npm install -g pmx-canvas@0.8.2
|
|
21
21
|
pmx-canvas --version
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
Without a global install, use `bunx pmx-canvas@0.
|
|
24
|
+
Without a global install, use `bunx pmx-canvas@0.8.2` in place of `pmx-canvas` in
|
|
25
25
|
the commands below. Do not use unpinned `bunx pmx-canvas` for a version-specific check.
|
|
26
26
|
|
|
27
27
|
## Choose the workspace and target
|
|
@@ -91,7 +91,7 @@ discards empty env values, remove `PMX_CANVAS_URL` from its launch environment i
|
|
|
91
91
|
"mcpServers": {
|
|
92
92
|
"canvas": {
|
|
93
93
|
"command": "bunx",
|
|
94
|
-
"args": ["pmx-canvas@0.
|
|
94
|
+
"args": ["pmx-canvas@0.8.2", "--mcp"],
|
|
95
95
|
"env": {
|
|
96
96
|
"PMX_CANVAS_WORKSPACE_ROOT": "/absolute/path/to/project",
|
|
97
97
|
"PMX_CANVAS_PORT": "14313",
|
|
@@ -135,7 +135,7 @@ Amp executes, not only on the user's laptop. Merge this into that workspace's
|
|
|
135
135
|
"amp.mcpServers": {
|
|
136
136
|
"canvas": {
|
|
137
137
|
"command": "bunx",
|
|
138
|
-
"args": ["pmx-canvas@0.
|
|
138
|
+
"args": ["pmx-canvas@0.8.2", "--mcp"],
|
|
139
139
|
"includeTools": ["canvas_*"],
|
|
140
140
|
"env": {
|
|
141
141
|
"PMX_CANVAS_WORKSPACE_ROOT": "/absolute/path/to/project",
|
|
@@ -169,7 +169,7 @@ The agent must not run this approval itself or move the command to global settin
|
|
|
169
169
|
`--mcp-config` to bypass workspace trust. Approval authorizes execution of this MCP
|
|
170
170
|
command; it is not a new Canvas import consent or permission to mutate arbitrary boards.
|
|
171
171
|
After approval, reload MCP connections (`reload_mcp` in Amp) and require `connected`.
|
|
172
|
-
Discover `canvas` tools with `tool_search`; for the full unfiltered 0.
|
|
172
|
+
Discover `canvas` tools with `tool_search`; for the full unfiltered 0.8.2 server there
|
|
173
173
|
are 24 tools. If still absent, inspect the server status, command/PATH and target instead
|
|
174
174
|
of reinstalling blindly. See [Amp MCP documentation](https://ampcode.com/docs/customize/mcp).
|
|
175
175
|
|
|
@@ -68,10 +68,11 @@ and check `$?`, then read the file.
|
|
|
68
68
|
|
|
69
69
|
- In the product source checkout, Bun tests live under `tests/unit/`.
|
|
70
70
|
- In the product source checkout, Playwright browser smoke lives under `tests/e2e/`.
|
|
71
|
-
- Playwright runs
|
|
72
|
-
`tests/e2e/reference-pane.pw.ts
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
- Playwright runs `desktop` (1440×900, the whole suite except the reference cases) and three
|
|
72
|
+
reference projects for `tests/e2e/reference-pane.pw.ts`: `narrow-600`, `middle-1024` and
|
|
73
|
+
`wide-1920`. The workbench lives anywhere from a narrow side pane to a full window, so every
|
|
74
|
+
node type must paint at all three. A new node type fails its coverage test until it gets a
|
|
75
|
+
reference case. Run one width alone with `bash scripts/run-playwright.sh --project=narrow-600`.
|
|
75
76
|
- Product CI runs those checkout suites: Bun coverage plus the browser smoke flow.
|
|
76
77
|
- An isolated installed consumer instead tests the package's public transports and host behavior;
|
|
77
78
|
it does not run or depend on the product checkout's source suites.
|
|
@@ -20,6 +20,11 @@ cmd(
|
|
|
20
20
|
const sourcePaths = [
|
|
21
21
|
fileURLToPath(new URL('../../../.github/extensions/pmx-canvas/extension.mjs', import.meta.url)),
|
|
22
22
|
fileURLToPath(new URL('../../../.github/extensions/pmx-canvas/steering-delivery.mjs', import.meta.url)),
|
|
23
|
+
fileURLToPath(new URL('../../../.github/extensions/pmx-canvas/runtime.mjs', import.meta.url)),
|
|
24
|
+
fileURLToPath(new URL('../../../.github/extensions/pmx-canvas/runtime.json', import.meta.url)),
|
|
25
|
+
fileURLToPath(new URL('../../../.github/extensions/pmx-canvas/start-mcp.mjs', import.meta.url)),
|
|
26
|
+
fileURLToPath(new URL('../../../.github/extensions/pmx-canvas/tools.json', import.meta.url)),
|
|
27
|
+
fileURLToPath(new URL('../../../.github/extensions/pmx-canvas/THIRD_PARTY_LICENSES.txt', import.meta.url)),
|
|
23
28
|
];
|
|
24
29
|
const missingSource = sourcePaths.find((sourcePath) => !existsSync(sourcePath));
|
|
25
30
|
if (missingSource) {
|
|
@@ -796,11 +796,12 @@ cmd(
|
|
|
796
796
|
const id = positional[0];
|
|
797
797
|
if (!id) die('Missing node ID', 'pmx-canvas node get <node-id>');
|
|
798
798
|
|
|
799
|
+
const requestedFields = collectRequestedFields(args, flags);
|
|
799
800
|
const result = (await invokeOperation('node.get', {
|
|
800
801
|
id,
|
|
801
802
|
board: typeof flags.board === 'string' ? flags.board : undefined,
|
|
803
|
+
contextDelivery: !flags.summary && !flags.compact && requestedFields.length === 0,
|
|
802
804
|
})) as Record<string, unknown>;
|
|
803
|
-
const requestedFields = collectRequestedFields(args, flags);
|
|
804
805
|
if (requestedFields.length > 0) {
|
|
805
806
|
const picked = Object.fromEntries(requestedFields.map((field) => [field, resolveNodeFieldValue(result, field)]));
|
|
806
807
|
const missing = requestedFields.filter((field) => picked[field] === undefined);
|
|
@@ -893,7 +894,7 @@ cmd(
|
|
|
893
894
|
frameHeight !== undefined ||
|
|
894
895
|
arrangeLocked !== undefined
|
|
895
896
|
) {
|
|
896
|
-
const existing = (await invokeOperation('node.get', { id })) as {
|
|
897
|
+
const existing = (await invokeOperation('node.get', { id, contextDelivery: false })) as {
|
|
897
898
|
position: { x: number; y: number };
|
|
898
899
|
size: { width: number; height: number };
|
|
899
900
|
data: Record<string, unknown>;
|
package/src/cli/commands/view.ts
CHANGED
|
@@ -179,7 +179,7 @@ cmd(
|
|
|
179
179
|
[
|
|
180
180
|
'pmx-canvas serve',
|
|
181
181
|
'pmx-canvas serve --port=8080 --no-open',
|
|
182
|
-
'pmx-canvas serve --demo --theme=
|
|
182
|
+
'pmx-canvas serve --demo --theme=daylight',
|
|
183
183
|
'pmx-canvas --no-open --webview-automation',
|
|
184
184
|
],
|
|
185
185
|
async (_args) => {
|
package/src/cli/index.ts
CHANGED
|
@@ -149,9 +149,10 @@ function commandAfterGlobalTargetFlags(argv: string[]): string {
|
|
|
149
149
|
return '';
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
function runMcpServerProcess(): Promise<void> {
|
|
152
|
+
function runMcpServerProcess(app = false): Promise<void> {
|
|
153
153
|
return new Promise((resolvePromise, rejectPromise) => {
|
|
154
|
-
const
|
|
154
|
+
const entry = app ? resolve(cliDir, '..', 'mcp', 'app-server.ts') : mcpServerEntry;
|
|
155
|
+
const child = spawn(process.execPath, ['run', entry], {
|
|
155
156
|
stdio: 'inherit',
|
|
156
157
|
env: process.env,
|
|
157
158
|
});
|
|
@@ -222,6 +223,9 @@ if (firstArg === 'serve') {
|
|
|
222
223
|
const routedCommand = commandAfterGlobalTargetFlags(args);
|
|
223
224
|
if (AGENT_COMMANDS.has(routedCommand) && routedCommand !== 'serve') {
|
|
224
225
|
await runAgentCli(args);
|
|
226
|
+
} else if (args.includes('--mcp-app')) {
|
|
227
|
+
// Private MCP Apps profile: focused tools and a self-contained UI resource.
|
|
228
|
+
await runMcpServerProcess(true);
|
|
225
229
|
} else if (args.includes('--mcp')) {
|
|
226
230
|
// MCP server mode: stdio transport, auto-starts canvas on first tool call
|
|
227
231
|
await runMcpServerProcess();
|
|
@@ -274,7 +278,7 @@ Server options:
|
|
|
274
278
|
--log-file=PATH Daemon log file (default: ./.pmx-canvas/daemon-${port}.log)
|
|
275
279
|
--pid-file=PATH Optional daemon PID file (default: ./.pmx-canvas/daemon-${port}.pid)
|
|
276
280
|
--wait-ms=MS Health-check wait budget for daemon mode (default: 10000)
|
|
277
|
-
--theme=THEME Theme:
|
|
281
|
+
--theme=THEME Theme: harbor (default), daylight, high-contrast, midnight, sepia, arctic, ember, forest, volt
|
|
278
282
|
--webview-automation Start a headless Bun.WebView automation session for /workbench
|
|
279
283
|
--webview-backend=BACKEND Bun.WebView backend: chrome or webkit
|
|
280
284
|
--webview-width=PX Automation WebView width (default: 1280)
|
|
@@ -283,6 +287,7 @@ Server options:
|
|
|
283
287
|
--webview-chrome-argv=CSV Extra Chrome args for Bun.WebView, comma-separated
|
|
284
288
|
--webview-data-dir=PATH Persist automation browser storage in PATH
|
|
285
289
|
--mcp Run as MCP server (stdio transport)
|
|
290
|
+
--mcp-app Run the private MCP App profile (stdio; shared active board)
|
|
286
291
|
--help, -h Show this help
|
|
287
292
|
|
|
288
293
|
Agent CLI (works against running server):
|
|
@@ -311,7 +316,8 @@ Agent CLI (works against running server):
|
|
|
311
316
|
diagram add Add an Excalidraw diagram node
|
|
312
317
|
html primitive add|schema Add or inspect HTML communication primitives
|
|
313
318
|
pin <ids...> | --list | --clear Manage context pins
|
|
314
|
-
board list|create|rename|category
|
|
319
|
+
board list|create|open|rename|category
|
|
320
|
+
Manage boards and open the target before writing
|
|
315
321
|
backup [status|schedule] Back up every board, now or on a schedule
|
|
316
322
|
restore <backup-file> Replace every board with a backup
|
|
317
323
|
export [--board id] [--out file] Export a board as one HTML file anyone can open
|
package/src/client/App.tsx
CHANGED
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
import { connectSSE } from './state/sse-bridge';
|
|
55
55
|
import { intents } from './state/intent-store';
|
|
56
56
|
import { sessionActive } from './state/presence-store';
|
|
57
|
+
import { isHostedWorkbench } from './state/workbench-transport';
|
|
57
58
|
import {
|
|
58
59
|
createGroupFromClient,
|
|
59
60
|
removeEdgeFromClient,
|
|
@@ -376,7 +377,11 @@ export function App() {
|
|
|
376
377
|
intents.value.size === 0 && <EmptyState onOpenPalette={() => setPaletteOpen(true)} />
|
|
377
378
|
)}
|
|
378
379
|
{selectedNodeIds.value.size > 0 && <SelectionBar />}
|
|
379
|
-
{sessionIsActive
|
|
380
|
+
{sessionIsActive && !isHostedWorkbench() ? (
|
|
381
|
+
<CommandBar />
|
|
382
|
+
) : (
|
|
383
|
+
contextPinnedNodeIds.value.size > 0 && <ContextPinBar />
|
|
384
|
+
)}
|
|
380
385
|
<SessionReceipt onOpenSnapshots={() => setSnapshotOpen(true)} />
|
|
381
386
|
<TextPrompt />
|
|
382
387
|
<ExportDialog />
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useRef } from 'preact/hooks';
|
|
2
|
-
import {
|
|
2
|
+
import { agentPhaseLabel, type AgentPresence } from '../../shared/agent-presence.js';
|
|
3
3
|
import { nodes, viewport } from '../state/canvas-store';
|
|
4
|
-
import { agentPresences, presenceWorldPosition } from '../state/presence-store';
|
|
4
|
+
import { agentPresences, presenceWorldPosition, writerColor } from '../state/presence-store';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Agent presence layer (rail-chrome-v2 phase 3): one cursor + phase chip per
|
|
@@ -49,7 +49,7 @@ export function AgentPresenceLayer() {
|
|
|
49
49
|
data-session-id={presence.sessionId}
|
|
50
50
|
style={{
|
|
51
51
|
transform: `translate(${position.x}px, ${position.y}px)`,
|
|
52
|
-
'--identity-color':
|
|
52
|
+
'--identity-color': writerColor(presence.sessionId),
|
|
53
53
|
}}
|
|
54
54
|
>
|
|
55
55
|
<div class="agent-cursor-inner" style={{ transform: `scale(${counterScale})` }}>
|