pmx-canvas 0.4.7 → 0.5.0

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 (212) hide show
  1. package/.github/extensions/pmx-canvas/extension.mjs +154 -5
  2. package/.github/extensions/pmx-canvas/steering-delivery.mjs +79 -0
  3. package/CHANGELOG.md +156 -0
  4. package/Readme.md +72 -23
  5. package/dist/canvas/global.css +3069 -796
  6. package/dist/canvas/index.js +104 -104
  7. package/dist/json-render/index.css +1 -1
  8. package/dist/types/cli/agent.d.ts +1 -0
  9. package/dist/types/cli/commands/pump.d.ts +9 -0
  10. package/dist/types/client/App.d.ts +1 -1
  11. package/dist/types/client/canvas/AgentPresenceLayer.d.ts +11 -0
  12. package/dist/types/client/canvas/BarHint.d.ts +22 -0
  13. package/dist/types/client/canvas/CanvasNode.d.ts +5 -0
  14. package/dist/types/client/canvas/CanvasViewport.d.ts +4 -4
  15. package/dist/types/client/canvas/CommandBar.d.ts +10 -0
  16. package/dist/types/client/canvas/ConnectionBanner.d.ts +13 -0
  17. package/dist/types/client/canvas/ContextMenu.d.ts +6 -0
  18. package/dist/types/client/canvas/EdgeLayer.d.ts +2 -1
  19. package/dist/types/client/canvas/EmptyState.d.ts +11 -0
  20. package/dist/types/client/canvas/ExternalWriters.d.ts +5 -0
  21. package/dist/types/client/canvas/HumanPresenceLayer.d.ts +8 -0
  22. package/dist/types/client/canvas/Minimap.d.ts +12 -1
  23. package/dist/types/client/canvas/ScopeFenceLayer.d.ts +8 -0
  24. package/dist/types/client/canvas/SelectionBar.d.ts +6 -0
  25. package/dist/types/client/canvas/SessionPanel.d.ts +1 -0
  26. package/dist/types/client/canvas/SessionReceipt.d.ts +17 -0
  27. package/dist/types/client/canvas/TextPrompt.d.ts +25 -0
  28. package/dist/types/client/canvas/ToolRail.d.ts +21 -0
  29. package/dist/types/client/canvas/TopBar.d.ts +7 -0
  30. package/dist/types/client/canvas/canvas-area.d.ts +25 -0
  31. package/dist/types/client/canvas/create-in-view.d.ts +18 -0
  32. package/dist/types/client/canvas/import-files.d.ts +8 -0
  33. package/dist/types/client/canvas/kind-colors.d.ts +3 -0
  34. package/dist/types/client/canvas/use-focus-trap.d.ts +14 -0
  35. package/dist/types/client/canvas/use-now.d.ts +6 -0
  36. package/dist/types/client/icons.d.ts +11 -4
  37. package/dist/types/client/nodes/ExtAppFrame.d.ts +32 -0
  38. package/dist/types/client/nodes/GroupNode.d.ts +6 -1
  39. package/dist/types/client/nodes/MarkdownNode.d.ts +2 -0
  40. package/dist/types/client/nodes/inline-editor-commands.d.ts +3 -4
  41. package/dist/types/client/state/canvas-store.d.ts +49 -5
  42. package/dist/types/client/state/human-store.d.ts +26 -0
  43. package/dist/types/client/state/iframe-mode.d.ts +1 -0
  44. package/dist/types/client/state/intent-bridge.d.ts +37 -5
  45. package/dist/types/client/state/node-factory.d.ts +0 -1
  46. package/dist/types/client/state/presence-store.d.ts +78 -0
  47. package/dist/types/client/state/session-store.d.ts +176 -0
  48. package/dist/types/client/types.d.ts +2 -1
  49. package/dist/types/client/utils/platform.d.ts +2 -0
  50. package/dist/types/server/agent-presence.d.ts +192 -0
  51. package/dist/types/server/ax-gate-ttl.d.ts +6 -0
  52. package/dist/types/server/ax-interaction.d.ts +4 -10
  53. package/dist/types/server/ax-state-manager.d.ts +21 -2
  54. package/dist/types/server/ax-state.d.ts +49 -3
  55. package/dist/types/server/ax-wait.d.ts +13 -0
  56. package/dist/types/server/canvas-db.d.ts +23 -1
  57. package/dist/types/server/canvas-operations.d.ts +1 -0
  58. package/dist/types/server/canvas-state.d.ts +27 -13
  59. package/dist/types/server/canvas-validation.d.ts +0 -14
  60. package/dist/types/server/html-surface.d.ts +1 -1
  61. package/dist/types/server/human-presence.d.ts +40 -0
  62. package/dist/types/server/index.d.ts +29 -3
  63. package/dist/types/server/intent-registry.d.ts +7 -0
  64. package/dist/types/server/mutation-history.d.ts +15 -2
  65. package/dist/types/server/operations/invoker.d.ts +13 -2
  66. package/dist/types/server/operations/ops/ax-presence.d.ts +2 -0
  67. package/dist/types/server/operations/ops/human-presence.d.ts +3 -0
  68. package/dist/types/server/operations/registry.d.ts +11 -0
  69. package/dist/types/server/operations/types.d.ts +1 -1
  70. package/dist/types/server/scope-fence.d.ts +62 -0
  71. package/dist/types/server/server.d.ts +0 -12
  72. package/dist/types/shared/agent-presence.d.ts +130 -0
  73. package/dist/types/shared/approval-gates.d.ts +19 -0
  74. package/dist/types/shared/auto-arrange.d.ts +0 -1
  75. package/dist/types/shared/ax-kinds.d.ts +11 -0
  76. package/dist/types/shared/human-presence.d.ts +31 -0
  77. package/dist/types/shared/iframe-probe.d.ts +8 -0
  78. package/dist/types/shared/scope-fence.d.ts +21 -0
  79. package/docs/RELEASE.md +54 -0
  80. package/docs/ax-host-adapter-contract.md +30 -14
  81. package/docs/cli.md +37 -1
  82. package/docs/environment.md +3 -0
  83. package/docs/http-api.md +222 -5
  84. package/docs/mcp.md +6 -5
  85. package/docs/node-types.md +3 -1
  86. package/docs/plans/plan-009-tech-debt-backlog.md +13 -0
  87. package/docs/screenshot.png +0 -0
  88. package/docs/screenshots/multi-agent-live.png +0 -0
  89. package/docs/screenshots/workbench-live-dark.png +0 -0
  90. package/docs/screenshots/workbench-live-light.png +0 -0
  91. package/docs/sdk.md +1 -1
  92. package/package.json +1 -1
  93. package/skills/pmx-canvas/SKILL.md +109 -18
  94. package/skills/pmx-canvas/references/codex-app-adapter.md +28 -0
  95. package/skills/pmx-canvas/references/full-reference.md +55 -16
  96. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +41 -24
  97. package/skills/pmx-canvas-orchestration/SKILL.md +56 -2
  98. package/skills/pmx-canvas-testing/SKILL.md +57 -0
  99. package/src/cli/agent.ts +1 -0
  100. package/src/cli/commands/copilot.ts +15 -8
  101. package/src/cli/commands/nodes.ts +1 -19
  102. package/src/cli/commands/pump.ts +252 -0
  103. package/src/cli/index.ts +1 -5
  104. package/src/cli/shared.ts +1 -1
  105. package/src/client/App.tsx +209 -585
  106. package/src/client/canvas/AgentPresenceLayer.tsx +74 -0
  107. package/src/client/canvas/AttentionHistory.tsx +0 -10
  108. package/src/client/canvas/BarHint.tsx +49 -0
  109. package/src/client/canvas/CanvasNode.tsx +488 -136
  110. package/src/client/canvas/CanvasViewport.tsx +190 -94
  111. package/src/client/canvas/CommandBar.tsx +140 -0
  112. package/src/client/canvas/CommandPalette.tsx +133 -58
  113. package/src/client/canvas/ConnectionBanner.tsx +65 -0
  114. package/src/client/canvas/ContextMenu.tsx +88 -27
  115. package/src/client/canvas/ContextPinBar.tsx +2 -2
  116. package/src/client/canvas/EdgeLayer.tsx +121 -38
  117. package/src/client/canvas/EmptyState.tsx +93 -0
  118. package/src/client/canvas/ExpandedNodeOverlay.tsx +64 -118
  119. package/src/client/canvas/ExternalWriters.tsx +308 -0
  120. package/src/client/canvas/FocusFieldLayer.tsx +12 -1
  121. package/src/client/canvas/HumanPresenceLayer.tsx +45 -0
  122. package/src/client/canvas/IntentLayer.tsx +1 -1
  123. package/src/client/canvas/Minimap.tsx +117 -190
  124. package/src/client/canvas/ScopeFenceLayer.tsx +38 -0
  125. package/src/client/canvas/SelectionBar.tsx +175 -23
  126. package/src/client/canvas/SessionPanel.tsx +481 -0
  127. package/src/client/canvas/SessionReceipt.tsx +141 -0
  128. package/src/client/canvas/ShortcutOverlay.tsx +21 -6
  129. package/src/client/canvas/SnapshotPanel.tsx +166 -80
  130. package/src/client/canvas/TextPrompt.tsx +128 -0
  131. package/src/client/canvas/ToolRail.tsx +447 -0
  132. package/src/client/canvas/TopBar.tsx +308 -0
  133. package/src/client/canvas/auto-fit.ts +1 -5
  134. package/src/client/canvas/canvas-area.ts +41 -0
  135. package/src/client/canvas/create-in-view.ts +48 -0
  136. package/src/client/canvas/import-files.ts +64 -0
  137. package/src/client/canvas/kind-colors.ts +22 -0
  138. package/src/client/canvas/snap-guides.ts +1 -1
  139. package/src/client/canvas/use-focus-trap.ts +54 -0
  140. package/src/client/canvas/use-now.ts +17 -0
  141. package/src/client/canvas/use-pan-zoom.ts +13 -2
  142. package/src/client/icons.tsx +57 -18
  143. package/src/client/nodes/ExtAppFrame.tsx +79 -2
  144. package/src/client/nodes/GroupNode.tsx +9 -28
  145. package/src/client/nodes/InlineFormatBar.tsx +4 -3
  146. package/src/client/nodes/InlineMarkdownEditor.tsx +27 -0
  147. package/src/client/nodes/MarkdownNode.tsx +59 -24
  148. package/src/client/nodes/MdFormatBar.tsx +2 -4
  149. package/src/client/nodes/inline-editor-commands.ts +17 -6
  150. package/src/client/nodes/use-surface-frame.ts +3 -1
  151. package/src/client/state/attention-bridge.ts +3 -0
  152. package/src/client/state/canvas-store.ts +273 -84
  153. package/src/client/state/human-store.ts +175 -0
  154. package/src/client/state/iframe-mode.ts +33 -9
  155. package/src/client/state/intent-bridge.ts +75 -13
  156. package/src/client/state/node-factory.ts +2 -8
  157. package/src/client/state/presence-store.ts +168 -0
  158. package/src/client/state/session-store.ts +419 -0
  159. package/src/client/state/sse-bridge.ts +93 -30
  160. package/src/client/theme/global.css +3069 -796
  161. package/src/client/types.ts +3 -1
  162. package/src/client/utils/platform.ts +6 -1
  163. package/src/mcp/canvas-access.ts +2 -2
  164. package/src/server/agent-presence.ts +755 -0
  165. package/src/server/ax-context.ts +45 -0
  166. package/src/server/ax-gate-ttl.ts +61 -0
  167. package/src/server/ax-interaction.ts +29 -1
  168. package/src/server/ax-state-manager.ts +78 -6
  169. package/src/server/ax-state.ts +82 -15
  170. package/src/server/ax-wait.ts +33 -0
  171. package/src/server/canvas-db.ts +237 -61
  172. package/src/server/canvas-operations.ts +17 -8
  173. package/src/server/canvas-state.ts +131 -58
  174. package/src/server/canvas-validation.ts +3 -53
  175. package/src/server/demo-state.json +2 -70
  176. package/src/server/html-surface.ts +11 -2
  177. package/src/server/human-presence.ts +160 -0
  178. package/src/server/index.ts +107 -4
  179. package/src/server/intent-registry.ts +13 -0
  180. package/src/server/mutation-history.ts +47 -2
  181. package/src/server/operations/composites.ts +6 -3
  182. package/src/server/operations/http.ts +10 -1
  183. package/src/server/operations/index.ts +4 -0
  184. package/src/server/operations/invoker.ts +33 -6
  185. package/src/server/operations/ops/ax-presence.ts +62 -0
  186. package/src/server/operations/ops/ax-read.ts +8 -0
  187. package/src/server/operations/ops/ax-state.ts +106 -1
  188. package/src/server/operations/ops/ax-timeline.ts +54 -5
  189. package/src/server/operations/ops/ax-work.ts +46 -0
  190. package/src/server/operations/ops/batch.ts +3 -1
  191. package/src/server/operations/ops/edges.ts +88 -2
  192. package/src/server/operations/ops/groups.ts +4 -3
  193. package/src/server/operations/ops/human-presence.ts +35 -0
  194. package/src/server/operations/ops/json-render.ts +11 -1
  195. package/src/server/operations/ops/nodes.ts +65 -16
  196. package/src/server/operations/ops/query.ts +1 -0
  197. package/src/server/operations/ops/snapshots.ts +16 -0
  198. package/src/server/operations/registry.ts +196 -1
  199. package/src/server/operations/types.ts +1 -1
  200. package/src/server/scope-fence.ts +207 -0
  201. package/src/server/server.ts +177 -79
  202. package/src/server/trace-manager.ts +0 -2
  203. package/src/server/web-artifacts.ts +0 -1
  204. package/src/shared/agent-presence.ts +162 -0
  205. package/src/shared/approval-gates.ts +35 -0
  206. package/src/shared/auto-arrange.ts +121 -13
  207. package/src/shared/ax-kinds.ts +23 -0
  208. package/src/shared/human-presence.ts +30 -0
  209. package/src/shared/iframe-probe.ts +8 -0
  210. package/src/shared/scope-fence.ts +31 -0
  211. package/dist/types/client/canvas/DockedNode.d.ts +0 -4
  212. package/src/client/canvas/DockedNode.tsx +0 -165
@@ -0,0 +1,74 @@
1
+ import { useRef } from 'preact/hooks';
2
+ import { agentIdentityHue, agentPhaseLabel, type AgentPresence } from '../../shared/agent-presence.js';
3
+ import { nodes, viewport } from '../state/canvas-store';
4
+ import { agentPresences, presenceWorldPosition } from '../state/presence-store';
5
+
6
+ /**
7
+ * Agent presence layer (rail-chrome-v2 phase 3): one cursor + phase chip per
8
+ * live writer — attached sessions and external (unattached) writers alike. Lives inside the
9
+ * world layer (like IntentLayer) so it pans and zooms with the board; the
10
+ * glyph itself is counter-scaled so it stays a constant screen size. Moves
11
+ * glide (220ms) — pans and zooms do not, because those move the world layer.
12
+ *
13
+ * Sibling of IntentLayer by design: ghosts show WHAT is about to change and
14
+ * carry the veto; this layer shows WHERE the agent is and WHAT PHASE it is in.
15
+ */
16
+ export function AgentPresenceLayer() {
17
+ // Remember the last resolved position per writer so a cursor parked on a
18
+ // node that was just removed stays where it was instead of vanishing.
19
+ const lastPositions = useRef(new Map<string, { x: number; y: number }>());
20
+
21
+ const scale = viewport.value.scale;
22
+ const nodeMap = nodes.value;
23
+ const counterScale = 1 / Math.max(0.05, scale);
24
+
25
+ // Every live writer paints a cursor, attached session or not — an external
26
+ // writer editing a quiet board is exactly when the human needs to see WHERE
27
+ // it is working (user call, 2026-08-24). Unattached writers get the
28
+ // `is-external` style; a board with no writers renders nothing. Attached
29
+ // twins never double-paint (twin-merge folds an agent's channels into one
30
+ // session), and an external writer's channels appear exactly as the
31
+ // External-activity panel counts them.
32
+ const cursors = agentPresences.value
33
+ .map((presence) => {
34
+ const resolved = presenceWorldPosition(presence, (id) => nodeMap.get(id));
35
+ if (resolved) lastPositions.current.set(presence.sessionId, resolved);
36
+ const position = resolved ?? lastPositions.current.get(presence.sessionId) ?? null;
37
+ return position ? { presence, position } : null;
38
+ })
39
+ .filter((entry): entry is { presence: AgentPresence; position: { x: number; y: number } } => entry !== null);
40
+
41
+ if (cursors.length === 0) return null;
42
+
43
+ return (
44
+ <div class="agent-presence-layer" aria-hidden="true">
45
+ {cursors.map(({ presence, position }) => (
46
+ <div
47
+ key={presence.sessionId}
48
+ class={`agent-cursor phase-${presence.phase}${presence.attached ? '' : ' is-external'}${presence.parentAgentId ? ' is-worker' : ''}`}
49
+ data-session-id={presence.sessionId}
50
+ style={{
51
+ transform: `translate(${position.x}px, ${position.y}px)`,
52
+ '--identity-color': `hsl(${agentIdentityHue(presence.sessionId)} 65% 62%)`,
53
+ }}
54
+ >
55
+ <div class="agent-cursor-inner" style={{ transform: `scale(${counterScale})` }}>
56
+ <svg class="agent-cursor-glyph" width="16" height="18" viewBox="0 0 16 18" aria-hidden="true">
57
+ <path
58
+ d="M1.5 1.5L14.5 9.2 8.3 10.6 5.2 16.5z"
59
+ fill="currentColor"
60
+ stroke="var(--c-bg)"
61
+ stroke-width="1.2"
62
+ />
63
+ </svg>
64
+ <span class="agent-cursor-chip">
65
+ <span class="agent-cursor-dot" />
66
+ <span class="agent-cursor-label">{agentPhaseLabel(presence)}</span>
67
+ <span class="agent-cursor-who">{presence.label}</span>
68
+ </span>
69
+ </div>
70
+ </div>
71
+ ))}
72
+ </div>
73
+ );
74
+ }
@@ -5,7 +5,6 @@ import {
5
5
  closeAttentionHistory,
6
6
  openAttentionHistory,
7
7
  } from '../state/attention-store';
8
- import { collapseDockedContextNodes, hasOpenDockedContextPanel } from '../state/canvas-store';
9
8
 
10
9
  function formatTimestamp(timestamp: number): string {
11
10
  return new Date(timestamp).toLocaleTimeString([], {
@@ -15,9 +14,6 @@ function formatTimestamp(timestamp: number): string {
15
14
  }
16
15
 
17
16
  function handleOpenUpdates(): void {
18
- // Mutual exclusion with the Context panel — only one side panel open at a
19
- // time (they share the same right-edge anchor).
20
- collapseDockedContextNodes();
21
17
  openAttentionHistory();
22
18
  }
23
19
 
@@ -27,12 +23,6 @@ export function AttentionHistory() {
27
23
 
28
24
  const isOpen = attentionHistoryOpen.value;
29
25
  const unread = attentionHistoryUnread.value;
30
- // Hide the collapsed Updates pill while the Context side panel is open —
31
- // the panel sits at the same right-edge and would visually cover the pill.
32
- // Mutual exclusion guarantees both can't be expanded simultaneously, so the
33
- // pill only needs to hide while context is expanded.
34
- if (!isOpen && hasOpenDockedContextPanel.value) return null;
35
-
36
26
  if (!isOpen) {
37
27
  return (
38
28
  <button
@@ -0,0 +1,49 @@
1
+ import type { ComponentChildren } from 'preact';
2
+
3
+ /**
4
+ * Styled hover/focus tooltip for bar controls — the replacement for native
5
+ * `title` hints, which are delay-gated and never render in embedded panes.
6
+ */
7
+ export function BarHint({
8
+ label,
9
+ shortcut,
10
+ body,
11
+ align = 'center',
12
+ side = 'down',
13
+ tapToOpen = false,
14
+ children,
15
+ }: {
16
+ label: string;
17
+ shortcut?: string;
18
+ /** One or two plain sentences under the label — the explanation a native `title` used to hide. */
19
+ body?: string;
20
+ align?: 'start' | 'center' | 'end';
21
+ /** Which way the tooltip opens. Bars at the bottom of the region open 'up'. */
22
+ side?: 'down' | 'up';
23
+ /**
24
+ * Informational (non-button) content: a click/focus opens the tooltip, so
25
+ * surfaces that do not forward hover (embedded panes, touch) still reach
26
+ * the explanation. Never for action buttons — their tooltips must dismiss
27
+ * after the click, not linger on focus.
28
+ */
29
+ tapToOpen?: boolean;
30
+ children: ComponentChildren;
31
+ }) {
32
+ return (
33
+ <span
34
+ class={`toolbar-tooltip-anchor toolbar-tooltip-anchor-${align}${side === 'up' ? ' toolbar-tooltip-anchor-up' : ''}${tapToOpen ? ' toolbar-tooltip-anchor-tap' : ''}`}
35
+ tabIndex={tapToOpen ? -1 : undefined}
36
+ >
37
+ {children}
38
+ <span class="toolbar-tooltip" role="tooltip">
39
+ <span class="toolbar-tooltip-label">{label}</span>
40
+ {body && <span class="toolbar-tooltip-body">{body}</span>}
41
+ {shortcut && (
42
+ <span class="toolbar-tooltip-meta">
43
+ <kbd class="toolbar-tooltip-shortcut">{shortcut}</kbd>
44
+ </span>
45
+ )}
46
+ </span>
47
+ </span>
48
+ );
49
+ }