pmx-canvas 0.4.2 → 0.4.3
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/extension.mjs +5 -2
- package/CHANGELOG.md +33 -0
- package/Readme.md +34 -12
- package/dist/canvas/global.css +37 -28
- package/dist/canvas/index.js +62 -62
- package/dist/canvas/surface-theme.css +20 -20
- package/dist/types/client/state/theme-override.d.ts +27 -0
- package/docs/http-api.md +8 -0
- package/docs/plans/plan-009-tech-debt-backlog.md +3 -1
- package/docs/screenshot.png +0 -0
- package/package.json +3 -3
- package/skills/pmx-canvas/SKILL.md +4 -0
- package/src/client/App.tsx +85 -78
- package/src/client/canvas/CommandPalette.tsx +4 -0
- package/src/client/nodes/ExtAppFrame.tsx +15 -4
- package/src/client/nodes/McpAppNode.tsx +6 -1
- package/src/client/state/sse-bridge.ts +8 -2
- package/src/client/state/theme-override.ts +83 -0
- package/src/client/theme/global.css +37 -28
- package/src/client/theme/surface-theme.css +20 -20
- package/src/server/operations/ops/canvas-wire.ts +9 -1
- package/src/shared/themes.ts +1 -1
|
@@ -252,7 +252,10 @@ function escapeHtml(value) {
|
|
|
252
252
|
|
|
253
253
|
function renderShell(instanceId, entry) {
|
|
254
254
|
const status = entry.pmx?.ok ? "Connected" : "Not connected";
|
|
255
|
-
|
|
255
|
+
// theme=light is a client-local session default matching the Copilot app's
|
|
256
|
+
// light chrome — it never changes the server-global theme other clients
|
|
257
|
+
// see, and the in-panel theme picker still overrides it.
|
|
258
|
+
const frameSrc = entry.pmx?.baseUrl ? `${entry.pmx.baseUrl}/workbench?theme=light` : "about:blank";
|
|
256
259
|
const error = entry.pmx?.error ? `<p class="error">${escapeHtml(entry.pmx.error)}</p>` : "";
|
|
257
260
|
return `<!doctype html>
|
|
258
261
|
<html>
|
|
@@ -731,7 +734,7 @@ const pmxCanvas = createCanvas({
|
|
|
731
734
|
return {
|
|
732
735
|
title: "PMX Canvas",
|
|
733
736
|
status: "Connected",
|
|
734
|
-
url: `${pmx.baseUrl}/workbench`,
|
|
737
|
+
url: `${pmx.baseUrl}/workbench?theme=light`,
|
|
735
738
|
};
|
|
736
739
|
}
|
|
737
740
|
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,38 @@
|
|
|
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.4.3] - 2026-08-05
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- Host-default theming: open the workbench with `?theme=<name>` (or
|
|
11
|
+
`?theme=auto` to follow the host's light/dark appearance) and that panel
|
|
12
|
+
gets its own session-local theme without changing the server-global theme
|
|
13
|
+
other clients see. Picking a theme from the toolbar ends the override. The
|
|
14
|
+
bundled GitHub Copilot extension now opens its panel with `?theme=light`.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- The `ember` theme was retuned to its intended look: neutral charcoal
|
|
19
|
+
surfaces, warm off-white text, and a vivid orange-red accent.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- The theme picker and More menus now open anchored to their buttons instead
|
|
24
|
+
of at the toolbar's right edge (0.4.2 report Finding T).
|
|
25
|
+
- `POST /api/canvas/theme` now rejects unknown theme names with a 400 error
|
|
26
|
+
instead of silently keeping the previous theme.
|
|
27
|
+
- An app node whose live session errors after a stressed reconnect (0.4.2
|
|
28
|
+
report Finding U, e.g. "MCP error -32001") now shows a soft
|
|
29
|
+
degraded-interactivity notice over its still-rendered saved content instead
|
|
30
|
+
of a red error banner.
|
|
31
|
+
- Graph, json-render, and app nodes no longer stay blank after a refresh in
|
|
32
|
+
srcdoc mode until scrolled or expanded — inline documents now load eagerly
|
|
33
|
+
(lazy loading only applies in `src` mode, where it defers a real HTTP
|
|
34
|
+
request).
|
|
35
|
+
- The npm package's `test` scripts now explain that the test suite is not
|
|
36
|
+
shipped instead of failing with a confusing "no test files" error.
|
|
37
|
+
|
|
6
38
|
## [0.4.2] - 2026-08-04
|
|
7
39
|
|
|
8
40
|
### Added
|
|
@@ -2880,6 +2912,7 @@ otherwise have to discover by trial and error.
|
|
|
2880
2912
|
- Regression coverage for snapshot flat-`id` aliases on both MCP and
|
|
2881
2913
|
HTTP surfaces, plus async / top-level-`await` WebView script bodies.
|
|
2882
2914
|
|
|
2915
|
+
[0.4.3]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.4.3
|
|
2883
2916
|
[0.4.2]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.4.2
|
|
2884
2917
|
[0.4.1]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.4.1
|
|
2885
2918
|
[0.4.0]: https://github.com/pskoett/pmx-canvas/releases/tag/v0.4.0
|
package/Readme.md
CHANGED
|
@@ -130,7 +130,8 @@ surfaces (the core never imports a host SDK).
|
|
|
130
130
|
|
|
131
131
|
- **GitHub Copilot app** — a committed project canvas extension
|
|
132
132
|
(`.github/extensions/pmx-canvas/`) opens the live PMX workbench in a native
|
|
133
|
-
Copilot panel
|
|
133
|
+
Copilot panel (light-themed by default to match the app, via the `?theme=`
|
|
134
|
+
session override), injects pinned/focused AX context on prompt submission, and
|
|
134
135
|
exposes actions for focus, session steering, work items, approval gates,
|
|
135
136
|
review annotations, the AX timeline, and host-capability reporting. Install it
|
|
136
137
|
into any repo with `pmx-canvas copilot install-extension` (`--dry-run` to
|
|
@@ -142,17 +143,25 @@ surfaces (the core never imports a host SDK).
|
|
|
142
143
|
(MCP + in-app Browser) are exactly what the canvas requires.
|
|
143
144
|
- **Claude Code desktop app** — the workbench runs in the desktop app's
|
|
144
145
|
built-in browser pane alongside the PMX MCP server, same zero-adapter recipe
|
|
145
|
-
as Codex: open `http://localhost:4313/workbench`
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
146
|
+
as Codex: open `http://localhost:4313/workbench?theme=light` (or
|
|
147
|
+
`?theme=auto` to follow the app's appearance) in the app's browser and the
|
|
148
|
+
live board, pins, and Ghost Cursor all work in-panel — themed to match the
|
|
149
|
+
pane without changing what other clients see.
|
|
150
|
+
- **AMPCode orbs + portal** — run the canvas as an orb service and view the
|
|
151
|
+
live workbench through the Amp portal (the `*.onamp.dev` URL ampcode.com
|
|
152
|
+
embeds for the thread). Zero configuration: orbs set `AMP_ORB` in the
|
|
153
|
+
service environment, and the canvas auto-adapts to the portal's constraints
|
|
154
|
+
— it switches to a polling transport when the portal proxy buffers the live
|
|
155
|
+
event stream, and renders HTML, graph, json-render, and app surfaces inline
|
|
156
|
+
via `srcdoc` because the nested-iframe embed blocks `src`-URL child iframes
|
|
157
|
+
(`/workbench?transport=poll` and `?iframe-mode=srcdoc` force either behavior
|
|
158
|
+
when diagnosing). The same detection helps other buffering proxies and
|
|
159
|
+
nested-iframe embeds.
|
|
160
|
+
<!-- screenshot: docs/screenshots/amp-orb-portal.png — PMX Canvas live inside the Amp portal (to be added) -->
|
|
161
|
+
|
|
162
|
+
Any other app browser (the ChatGPT desktop app, an IDE webview, …) works the
|
|
163
|
+
same zero-adapter way: open the workbench URL, and add `?theme=<name|auto>` to
|
|
164
|
+
give that panel its own session-local default theme.
|
|
156
165
|
|
|
157
166
|
The contract is host-agnostic, so a new host plugs in the same way: map its
|
|
158
167
|
hooks, canvas, and session APIs onto PMX's AX primitives — no core changes.
|
|
@@ -239,6 +248,19 @@ Agents read pinned/focused context from `canvas://ax-context` /
|
|
|
239
248
|
[`codex-app-adapter.md`](skills/pmx-canvas/references/codex-app-adapter.md) for
|
|
240
249
|
the full workflow and live-test checklist.
|
|
241
250
|
|
|
251
|
+
### Use inside AMPCode orbs and the Amp portal
|
|
252
|
+
|
|
253
|
+
Amp needs no adapter either. Run `pmx-canvas` as an orb service (the orb sets
|
|
254
|
+
`AMP_ORB` in the environment automatically) and open the workbench through the
|
|
255
|
+
thread's portal URL. The canvas detects the orb and the portal's nested-iframe
|
|
256
|
+
embed on its own: live updates arrive over the proxy-safe polling transport,
|
|
257
|
+
and iframe-backed nodes (HTML, graph, json-render, web artifacts) render
|
|
258
|
+
inline via `srcdoc` with their theme styling included. Cross-origin hosted
|
|
259
|
+
apps (e.g. the hosted Excalidraw MCP app) cannot be inlined and may stay
|
|
260
|
+
blocked by the portal embed — everything served from the canvas itself works.
|
|
261
|
+
Debug overrides: `/workbench?transport=poll|sse` and
|
|
262
|
+
`?iframe-mode=srcdoc|src`.
|
|
263
|
+
|
|
242
264
|
### Install the agent skill (recommended)
|
|
243
265
|
|
|
244
266
|
The fastest way to get a working canvas is to install the `pmx-canvas` agent
|
package/dist/canvas/global.css
CHANGED
|
@@ -337,16 +337,16 @@
|
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
:root[data-theme="ember"] {
|
|
340
|
-
/* ── Core palette (ember · charcoal + vivid
|
|
341
|
-
--c-bg: #
|
|
342
|
-
--c-panel: #
|
|
343
|
-
--c-panel-soft: #
|
|
344
|
-
--c-line: #
|
|
345
|
-
--c-text: #
|
|
346
|
-
--c-text-soft: #
|
|
347
|
-
--c-muted: #
|
|
348
|
-
--c-dim: #
|
|
349
|
-
--c-accent: #
|
|
340
|
+
/* ── Core palette (ember · neutral charcoal + vivid orange-red) ─── */
|
|
341
|
+
--c-bg: #0B0B0C;
|
|
342
|
+
--c-panel: #161618;
|
|
343
|
+
--c-panel-soft: #101012;
|
|
344
|
+
--c-line: #29292C;
|
|
345
|
+
--c-text: #EDEBE6;
|
|
346
|
+
--c-text-soft: #CBC9C2;
|
|
347
|
+
--c-muted: #96948D;
|
|
348
|
+
--c-dim: #66655F;
|
|
349
|
+
--c-accent: #F34E1C;
|
|
350
350
|
--c-ok: #4CC38A;
|
|
351
351
|
--c-warn: #F5B944;
|
|
352
352
|
--c-warn-alt: #FFB300;
|
|
@@ -354,23 +354,23 @@
|
|
|
354
354
|
--c-purple: #A78BFA;
|
|
355
355
|
--c-thinking: #A78BFA;
|
|
356
356
|
--c-subagent: #38BDF8;
|
|
357
|
-
--c-input-bg: #
|
|
358
|
-
--c-dot-grid: rgba(
|
|
359
|
-
--c-panel-overlay: rgba(
|
|
360
|
-
--c-panel-glass: rgba(
|
|
357
|
+
--c-input-bg: #101012;
|
|
358
|
+
--c-dot-grid: rgba(243, 78, 28, 0.08);
|
|
359
|
+
--c-panel-overlay: rgba(11, 11, 12, 0.6);
|
|
360
|
+
--c-panel-glass: rgba(22, 22, 24, 0.92);
|
|
361
361
|
--c-shadow: rgba(0, 0, 0, 0.3);
|
|
362
362
|
--c-shadow-heavy: rgba(0, 0, 0, 0.5);
|
|
363
|
-
--c-glow-accent: rgba(
|
|
363
|
+
--c-glow-accent: rgba(243, 78, 28, 0.15);
|
|
364
364
|
--c-surface-hover: rgba(255, 255, 255, 0.06);
|
|
365
365
|
--c-surface-subtle: rgba(255, 255, 255, 0.03);
|
|
366
366
|
--c-surface-th: rgba(255, 255, 255, 0.04);
|
|
367
|
-
--c-accent-8: rgba(
|
|
368
|
-
--c-accent-10: rgba(
|
|
369
|
-
--c-accent-12: rgba(
|
|
370
|
-
--c-accent-15: rgba(
|
|
371
|
-
--c-accent-25: rgba(
|
|
372
|
-
--c-accent-30: rgba(
|
|
373
|
-
--c-accent-40: rgba(
|
|
367
|
+
--c-accent-8: rgba(243, 78, 28, 0.08);
|
|
368
|
+
--c-accent-10: rgba(243, 78, 28, 0.1);
|
|
369
|
+
--c-accent-12: rgba(243, 78, 28, 0.12);
|
|
370
|
+
--c-accent-15: rgba(243, 78, 28, 0.15);
|
|
371
|
+
--c-accent-25: rgba(243, 78, 28, 0.25);
|
|
372
|
+
--c-accent-30: rgba(243, 78, 28, 0.3);
|
|
373
|
+
--c-accent-40: rgba(243, 78, 28, 0.4);
|
|
374
374
|
--c-ok-10: rgba(76, 195, 138, 0.1);
|
|
375
375
|
--c-ok-12: rgba(76, 195, 138, 0.12);
|
|
376
376
|
--c-ok-20: rgba(76, 195, 138, 0.2);
|
|
@@ -383,12 +383,12 @@
|
|
|
383
383
|
--c-warn-30: rgba(245, 185, 68, 0.3);
|
|
384
384
|
--c-warn-60: rgba(245, 185, 68, 0.6);
|
|
385
385
|
--c-danger-12: rgba(240, 86, 106, 0.12);
|
|
386
|
-
--c-line-30: rgba(
|
|
387
|
-
--c-contrast-fg: #
|
|
388
|
-
--c-accent-hover: #
|
|
386
|
+
--c-line-30: rgba(41, 41, 44, 0.3);
|
|
387
|
+
--c-contrast-fg: #0B0B0C;
|
|
388
|
+
--c-accent-hover: #FF6B3A;
|
|
389
389
|
--c-warn-hover: #F7C868;
|
|
390
390
|
--c-canvas-wash: linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(0, 0, 0, 0));
|
|
391
|
-
--c-annotation: #
|
|
391
|
+
--c-annotation: #F2F0EB;
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
:root[data-theme="forest"] {
|
|
@@ -944,7 +944,6 @@ body,
|
|
|
944
944
|
}
|
|
945
945
|
|
|
946
946
|
.toolbar-group {
|
|
947
|
-
position: relative;
|
|
948
947
|
display: flex;
|
|
949
948
|
flex-wrap: wrap;
|
|
950
949
|
align-items: center;
|
|
@@ -953,6 +952,14 @@ body,
|
|
|
953
952
|
max-width: 100%;
|
|
954
953
|
}
|
|
955
954
|
|
|
955
|
+
/* Positioning parent for a toolbar popover menu. Every menu MUST live inside
|
|
956
|
+
one of these wrapped around its trigger — anchoring to a wider ancestor
|
|
957
|
+
opens the menu far from the button (0.4.2 report Finding T). */
|
|
958
|
+
.toolbar-menu-anchor {
|
|
959
|
+
position: relative;
|
|
960
|
+
display: inline-flex;
|
|
961
|
+
}
|
|
962
|
+
|
|
956
963
|
.canvas-toolbar button svg {
|
|
957
964
|
display: block;
|
|
958
965
|
}
|
|
@@ -1074,7 +1081,9 @@ body,
|
|
|
1074
1081
|
}
|
|
1075
1082
|
|
|
1076
1083
|
.toolbar-more {
|
|
1077
|
-
|
|
1084
|
+
/* inline-flex (NOT contents): this span is also the positioning anchor
|
|
1085
|
+
for the More menu — display:contents cannot anchor absolute children. */
|
|
1086
|
+
display: inline-flex;
|
|
1078
1087
|
}
|
|
1079
1088
|
}
|
|
1080
1089
|
|