pmx-canvas 0.6.5 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/.github/extensions/pmx-canvas/extension.mjs +139 -14
  2. package/CHANGELOG.md +70 -0
  3. package/Readme.md +32 -6
  4. package/dist/canvas/global.css +510 -31
  5. package/dist/canvas/index.js +92 -77
  6. package/dist/types/cli/agent.d.ts +3 -0
  7. package/dist/types/cli/commands/backup.d.ts +1 -0
  8. package/dist/types/cli/commands/boards.d.ts +1 -0
  9. package/dist/types/cli/commands/export.d.ts +1 -0
  10. package/dist/types/cli/daemon.d.ts +5 -5
  11. package/dist/types/cli/shared.d.ts +3 -1
  12. package/dist/types/client/canvas/BoardCopyDialog.d.ts +5 -0
  13. package/dist/types/client/canvas/BoardFolderDialog.d.ts +7 -0
  14. package/dist/types/client/canvas/BoardLinkDialog.d.ts +3 -0
  15. package/dist/types/client/canvas/BoardSwitcher.d.ts +8 -0
  16. package/dist/types/client/canvas/ExportDialog.d.ts +7 -0
  17. package/dist/types/client/canvas/HomeView.d.ts +9 -0
  18. package/dist/types/client/nodes/AttachmentNode.d.ts +6 -0
  19. package/dist/types/client/nodes/BoardNode.d.ts +5 -0
  20. package/dist/types/client/state/boards-store.d.ts +79 -0
  21. package/dist/types/client/state/canvas-store.d.ts +2 -0
  22. package/dist/types/client/state/intent-bridge.d.ts +1 -0
  23. package/dist/types/client/state/session-store.d.ts +7 -0
  24. package/dist/types/client/types.d.ts +2 -2
  25. package/dist/types/json-render/catalog.d.ts +1 -1
  26. package/dist/types/json-render/charts/definitions.d.ts +1 -1
  27. package/dist/types/json-render/server.d.ts +6 -0
  28. package/dist/types/mcp/canvas-access.d.ts +10 -3
  29. package/dist/types/mcp/context-uri-template.d.ts +6 -0
  30. package/dist/types/server/agent-presence.d.ts +1 -1
  31. package/dist/types/server/attribution.d.ts +11 -0
  32. package/dist/types/server/ax-context.d.ts +3 -1
  33. package/dist/types/server/ax-interaction.d.ts +2 -2
  34. package/dist/types/server/ax-state.d.ts +13 -3
  35. package/dist/types/server/backup.d.ts +36 -0
  36. package/dist/types/server/board-export.d.ts +45 -0
  37. package/dist/types/server/canvas-db.d.ts +63 -9
  38. package/dist/types/server/canvas-operations.d.ts +23 -0
  39. package/dist/types/server/canvas-provenance.d.ts +1 -1
  40. package/dist/types/server/canvas-state.d.ts +140 -3
  41. package/dist/types/server/context-brief.d.ts +111 -0
  42. package/dist/types/server/context-reads.d.ts +55 -0
  43. package/dist/types/server/document-import.d.ts +66 -0
  44. package/dist/types/server/index.d.ts +103 -4
  45. package/dist/types/server/mutation-history.d.ts +1 -0
  46. package/dist/types/server/operations/invoker.d.ts +2 -0
  47. package/dist/types/server/operations/mcp.d.ts +7 -1
  48. package/dist/types/server/operations/ops/ax-shared.d.ts +2 -2
  49. package/dist/types/server/operations/ops/backup.d.ts +2 -0
  50. package/dist/types/server/operations/ops/boards.d.ts +10 -0
  51. package/dist/types/server/operations/ops/export.d.ts +2 -0
  52. package/dist/types/server/operations/ops/imports.d.ts +2 -0
  53. package/dist/types/server/operations/ops/nodes.d.ts +1 -1
  54. package/dist/types/server/operations/ops/query.d.ts +2 -0
  55. package/dist/types/server/operations/registry.d.ts +9 -1
  56. package/dist/types/server/operations/types.d.ts +1 -1
  57. package/dist/types/server/server.d.ts +1 -0
  58. package/dist/types/server/trace-manager.d.ts +7 -0
  59. package/dist/types/server/webpage-node.d.ts +22 -1
  60. package/dist/types/server/workbench-auth.d.ts +3 -0
  61. package/dist/types/shared/boards.d.ts +6 -0
  62. package/docs/RELEASE.md +5 -0
  63. package/docs/cli.md +73 -0
  64. package/docs/http-api.md +198 -2
  65. package/docs/mcp.md +71 -6
  66. package/docs/node-types.md +26 -0
  67. package/docs/plans/plan-010-attributed-ask-answers.md +39 -0
  68. package/docs/plans/plan-011-context-read-instrumentation.md +54 -0
  69. package/docs/plans/plan-012-many-boards-stage-1.md +98 -0
  70. package/docs/plans/plan-013-static-board-export.md +47 -0
  71. package/docs/plans/plan-014-connected-board-memory.md +140 -0
  72. package/docs/product-vision-2026-09.md +118 -18
  73. package/docs/sdk.md +50 -0
  74. package/package.json +1 -1
  75. package/skills/pmx-canvas/SKILL.md +68 -11
  76. package/skills/pmx-canvas/evals/evals.json +130 -0
  77. package/skills/pmx-canvas/references/full-reference.md +43 -7
  78. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +3 -0
  79. package/skills/pmx-canvas/references/installing-pmx-canvas.md +4 -4
  80. package/skills/pmx-canvas/references/tours-and-recording.md +69 -0
  81. package/skills/pmx-canvas-orchestration/SKILL.md +5 -0
  82. package/skills/pmx-canvas-testing/SKILL.md +11 -2
  83. package/src/cli/agent.ts +4 -0
  84. package/src/cli/commands/apps.ts +1 -1
  85. package/src/cli/commands/ax.ts +13 -0
  86. package/src/cli/commands/backup.ts +66 -0
  87. package/src/cli/commands/boards.ts +71 -0
  88. package/src/cli/commands/export.ts +37 -0
  89. package/src/cli/commands/nodes.ts +4 -1
  90. package/src/cli/commands/pins.ts +6 -2
  91. package/src/cli/commands/pump.ts +3 -0
  92. package/src/cli/commands/query.ts +33 -7
  93. package/src/cli/commands/view.ts +7 -5
  94. package/src/cli/daemon.ts +37 -7
  95. package/src/cli/index.ts +19 -9
  96. package/src/cli/shared.ts +11 -2
  97. package/src/client/App.tsx +21 -4
  98. package/src/client/canvas/AttentionToast.tsx +5 -3
  99. package/src/client/canvas/BoardCopyDialog.tsx +153 -0
  100. package/src/client/canvas/BoardFolderDialog.tsx +120 -0
  101. package/src/client/canvas/BoardLinkDialog.tsx +93 -0
  102. package/src/client/canvas/BoardSwitcher.tsx +149 -0
  103. package/src/client/canvas/CanvasNode.tsx +0 -1
  104. package/src/client/canvas/CanvasViewport.tsx +3 -0
  105. package/src/client/canvas/CommandPalette.tsx +107 -4
  106. package/src/client/canvas/ContextMenu.tsx +4 -1
  107. package/src/client/canvas/ExpandedNodeOverlay.tsx +3 -0
  108. package/src/client/canvas/ExportDialog.tsx +199 -0
  109. package/src/client/canvas/HomeView.tsx +277 -0
  110. package/src/client/canvas/Presentation.tsx +39 -9
  111. package/src/client/canvas/SelectionBar.tsx +0 -2
  112. package/src/client/canvas/SessionPanel.tsx +28 -1
  113. package/src/client/canvas/ToolRail.tsx +38 -3
  114. package/src/client/canvas/TopBar.tsx +34 -18
  115. package/src/client/canvas/import-files.ts +19 -1
  116. package/src/client/canvas/kind-colors.ts +1 -0
  117. package/src/client/icons.tsx +2 -0
  118. package/src/client/nodes/AttachmentNode.tsx +145 -0
  119. package/src/client/nodes/BoardNode.tsx +35 -0
  120. package/src/client/nodes/FileNode.tsx +6 -0
  121. package/src/client/nodes/MarkdownNode.tsx +47 -19
  122. package/src/client/nodes/ax-node-actions.ts +2 -5
  123. package/src/client/nodes/use-ax-surface-bridge.ts +1 -1
  124. package/src/client/state/attention-bridge.ts +3 -1
  125. package/src/client/state/boards-store.ts +167 -0
  126. package/src/client/state/canvas-store.ts +22 -0
  127. package/src/client/state/intent-bridge.ts +30 -2
  128. package/src/client/state/node-factory.ts +1 -0
  129. package/src/client/state/session-store.ts +5 -0
  130. package/src/client/state/sse-bridge.ts +52 -6
  131. package/src/client/theme/global.css +510 -31
  132. package/src/client/types.ts +2 -0
  133. package/src/json-render/server.ts +16 -9
  134. package/src/mcp/canvas-access.ts +59 -22
  135. package/src/mcp/context-uri-template.ts +28 -0
  136. package/src/mcp/server.ts +122 -15
  137. package/src/server/agent-context.ts +116 -29
  138. package/src/server/attribution.ts +29 -0
  139. package/src/server/ax-context.ts +4 -2
  140. package/src/server/ax-interaction.ts +1 -0
  141. package/src/server/ax-state-manager.ts +72 -3
  142. package/src/server/ax-state.ts +41 -0
  143. package/src/server/backup.ts +178 -0
  144. package/src/server/board-export.ts +686 -0
  145. package/src/server/canvas-db.ts +599 -107
  146. package/src/server/canvas-operations.ts +68 -9
  147. package/src/server/canvas-provenance.ts +1 -0
  148. package/src/server/canvas-schema.ts +12 -0
  149. package/src/server/canvas-state.ts +774 -45
  150. package/src/server/context-brief.ts +372 -0
  151. package/src/server/context-reads.ts +238 -0
  152. package/src/server/demo-state.json +659 -2
  153. package/src/server/document-import.ts +223 -0
  154. package/src/server/index.ts +231 -5
  155. package/src/server/mutation-history.ts +10 -13
  156. package/src/server/operations/composites.ts +26 -4
  157. package/src/server/operations/http.ts +9 -3
  158. package/src/server/operations/index.ts +8 -0
  159. package/src/server/operations/invoker.ts +14 -3
  160. package/src/server/operations/mcp.ts +50 -11
  161. package/src/server/operations/ops/app.ts +5 -0
  162. package/src/server/operations/ops/ax-read.ts +10 -6
  163. package/src/server/operations/ops/ax-timeline.ts +75 -0
  164. package/src/server/operations/ops/backup.ts +134 -0
  165. package/src/server/operations/ops/batch.ts +8 -1
  166. package/src/server/operations/ops/boards.ts +351 -0
  167. package/src/server/operations/ops/export.ts +74 -0
  168. package/src/server/operations/ops/ext-app.ts +4 -0
  169. package/src/server/operations/ops/imports.ts +236 -0
  170. package/src/server/operations/ops/nodes.ts +57 -5
  171. package/src/server/operations/ops/query.ts +206 -9
  172. package/src/server/operations/registry.ts +123 -31
  173. package/src/server/operations/types.ts +1 -1
  174. package/src/server/server.ts +146 -2
  175. package/src/server/spatial-analysis.ts +9 -17
  176. package/src/server/trace-manager.ts +19 -0
  177. package/src/server/web-artifacts.ts +2 -1
  178. package/src/server/webpage-node.ts +173 -13
  179. package/src/server/workbench-auth.ts +11 -0
  180. package/src/shared/boards.ts +18 -0
  181. package/src/shared/node-sizes.ts +1 -0
@@ -27,10 +27,13 @@ import {
27
27
  workbenchConnectionEpoch,
28
28
  reconnectAttempt,
29
29
  reconnectDelay,
30
+ resetCanvasInteractionState,
30
31
  } from './canvas-store';
32
+ import { applyBoards, loadBoards, setBoardSwitchHandler } from './boards-store';
31
33
  import {
32
34
  fetchAgentPresence,
33
35
  fetchAxSurfaceState,
36
+ fetchCanvasState,
34
37
  reportClientViewportSize,
35
38
  requestJson,
36
39
  tabAgentKey,
@@ -38,7 +41,7 @@ import {
38
41
  import { agentActivity, applyPresenceSnapshot, sessionActive } from './presence-store';
39
42
  import { applyHumanSnapshot, startHumanPresence } from './human-store';
40
43
  import type { HumanPresenceSnapshot } from '../../shared/human-presence.js';
41
- import { applySessionReceipt, refreshTimeline } from './session-store';
44
+ import { applySessionReceipt, dismissSessionReceipt, refreshTimeline } from './session-store';
42
45
  import { initSessionThemeOverride, themeOverrideActive } from './theme-override';
43
46
  import { DEFAULT_POSITIONS, makeNodeState } from './node-factory';
44
47
  import { invalidateTokenCache } from '../theme/tokens';
@@ -304,6 +307,7 @@ function isCanvasNodeType(value: unknown): value is CanvasNodeState['type'] {
304
307
  value === 'webpage' ||
305
308
  value === 'json-render' ||
306
309
  value === 'graph' ||
310
+ value === 'board' ||
307
311
  value === 'prompt' ||
308
312
  value === 'response' ||
309
313
  value === 'status' ||
@@ -456,14 +460,46 @@ function handleAgentSessionEnded(data: Record<string, unknown>): void {
456
460
  }
457
461
 
458
462
  let stopHumanPresence: (() => void) | null = null;
463
+ let boardResyncGeneration = 0;
464
+ let layoutRevision = 0;
465
+ let pinsRevision = 0;
459
466
 
460
467
  function handleHumanPresence(data: Record<string, unknown>): void {
461
468
  applyHumanSnapshot(data as Partial<HumanPresenceSnapshot>);
462
469
  }
463
470
 
471
+ /**
472
+ * The open board changed (this tab, another tab, or a restart): the canvas is
473
+ * a different board now, so take its layout like a fresh connection would —
474
+ * camera included — and drop what belonged to the old board.
475
+ */
476
+ function resyncForBoardSwitch(): void {
477
+ const generation = ++boardResyncGeneration;
478
+ savedLayout = null;
479
+ hasInitialServerLayout.value = false;
480
+ resetIntents();
481
+ resetCanvasInteractionState();
482
+ resetAttentionBridge();
483
+ dismissSessionReceipt();
484
+ axSurfaceState.value = null;
485
+ void refreshAxSurface();
486
+ const layoutAtRequest = layoutRevision;
487
+ const pinsAtRequest = pinsRevision;
488
+ void fetchCanvasState().then((layout) => {
489
+ if (generation === boardResyncGeneration && layoutAtRequest === layoutRevision)
490
+ handleCanvasLayoutUpdate({ layout });
491
+ });
492
+ void requestJson<{ nodeIds?: unknown }>('fetchPinnedContext', '/api/canvas/pinned-context', {}).then((data) => {
493
+ if (generation === boardResyncGeneration && pinsAtRequest === pinsRevision)
494
+ handleContextPinsChanged({ nodeIds: data.nodeIds });
495
+ });
496
+ }
497
+ setBoardSwitchHandler(resyncForBoardSwitch);
498
+
464
499
  function handleConnected(data: Record<string, unknown>): void {
465
500
  sessionId.value = (data.sessionId as string) || '';
466
501
  connectionStatus.value = 'connected';
502
+ void loadBoards();
467
503
  // Reconnect marker for holders of server-minted URLs (Finding S).
468
504
  workbenchConnectionEpoch.value += 1;
469
505
  reloadIfServerUpgraded(data.version, data.bundleStamp);
@@ -486,8 +522,7 @@ function handleConnected(data: Record<string, unknown>): void {
486
522
  // The AX surface snapshot (work items, gates) likewise — it used to arrive
487
523
  // only on the first ax-state-changed, so a fresh load showed an empty
488
524
  // session panel while persisted work items existed.
489
- void fetchAxSurfaceState().then((state) => {
490
- axSurfaceState.value = state;
525
+ void refreshAxSurface().then(() => {
491
526
  if (sessionActive.value) void refreshTimeline();
492
527
  });
493
528
  // A ?theme= session override (host-default theming) wins over the
@@ -903,6 +938,7 @@ function handleCanvasLayoutUpdate(data: Record<string, unknown>): void {
903
938
  }
904
939
  | undefined;
905
940
  if (!layout?.nodes) return;
941
+ layoutRevision += 1;
906
942
  const shouldApplyViewport = !hasInitialServerLayout.value;
907
943
  hasInitialServerLayout.value = true;
908
944
 
@@ -993,6 +1029,7 @@ function handleThemeChanged(data: Record<string, unknown>): void {
993
1029
  }
994
1030
 
995
1031
  function handleContextPinsChanged(data: Record<string, unknown>): void {
1032
+ pinsRevision += 1;
996
1033
  const nodeIds = Array.isArray(data.nodeIds) ? data.nodeIds.filter((id): id is string => typeof id === 'string') : [];
997
1034
  replaceContextPinsFromServer(nodeIds);
998
1035
  syncAttentionFromSse({ event: 'context-pins-changed', data });
@@ -1003,13 +1040,21 @@ function handleContextPinsChanged(data: Record<string, unknown>): void {
1003
1040
  // (debounced). The snapshot feeds AX-enabled surfaces (HtmlNode/McpAppNode push it
1004
1041
  // into their iframes), so authored boards reflect the live work queue / focus.
1005
1042
  let axRefreshTimer: ReturnType<typeof setTimeout> | null = null;
1043
+ let axRefreshSequence = 0;
1044
+ async function refreshAxSurface(): Promise<void> {
1045
+ const sequence = ++axRefreshSequence;
1046
+ const generation = boardResyncGeneration;
1047
+ const state = await fetchAxSurfaceState();
1048
+ if (sequence === axRefreshSequence && generation === boardResyncGeneration) axSurfaceState.value = state;
1049
+ }
1050
+
1006
1051
  function handleAxStateChanged(): void {
1007
1052
  if (axRefreshTimer) clearTimeout(axRefreshTimer);
1053
+ // Invalidate any in-flight read before the debounced replacement starts.
1054
+ axRefreshSequence += 1;
1008
1055
  axRefreshTimer = setTimeout(() => {
1009
1056
  axRefreshTimer = null;
1010
- void fetchAxSurfaceState().then((state) => {
1011
- axSurfaceState.value = state;
1012
- });
1057
+ void refreshAxSurface();
1013
1058
  // The session panel's timeline — only worth fetching while it is mounted.
1014
1059
  if (sessionActive.value) void refreshTimeline();
1015
1060
  }, 150);
@@ -1064,6 +1109,7 @@ export const EVENT_HANDLERS: Record<string, (data: Record<string, unknown>) => v
1064
1109
  'ext-app-update': handleExtAppUpdate,
1065
1110
  'ext-app-result': handleExtAppResult,
1066
1111
  'context-pins-changed': handleContextPinsChanged,
1112
+ 'boards-changed': applyBoards,
1067
1113
  'canvas-layout-update': handleCanvasLayoutUpdate,
1068
1114
  'canvas-focus-node': handleCanvasFocusNode,
1069
1115
  'canvas-viewport-update': handleCanvasViewportUpdate,