pmx-canvas 0.1.29 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +161 -0
- package/Readme.md +20 -10
- package/dist/canvas/global.css +13 -0
- package/dist/canvas/index.js +80 -163
- package/dist/canvas/surface-theme.css +142 -0
- package/dist/json-render/index.js +103 -103
- package/dist/types/client/nodes/HtmlNode.d.ts +0 -7
- package/dist/types/client/nodes/ax-node-actions.d.ts +18 -0
- package/dist/types/client/nodes/surface-url.d.ts +22 -0
- package/dist/types/client/state/attention-bridge.d.ts +3 -0
- package/dist/types/client/state/intent-bridge.d.ts +17 -0
- package/dist/types/json-render/renderer/index.d.ts +2 -0
- package/dist/types/json-render/schema.d.ts +2 -0
- package/dist/types/json-render/server.d.ts +2 -0
- package/dist/types/mcp/canvas-access.d.ts +47 -0
- package/dist/types/server/ax-interaction.d.ts +210 -0
- package/dist/types/server/ax-state.d.ts +67 -1
- package/dist/types/server/canvas-db.d.ts +4 -0
- package/dist/types/server/canvas-serialization.d.ts +2 -0
- package/dist/types/server/canvas-state.d.ts +47 -2
- package/dist/types/server/html-surface.d.ts +40 -0
- package/dist/types/server/index.d.ts +50 -2
- package/dist/types/server/mutation-history.d.ts +1 -1
- package/dist/types/server/placement.d.ts +1 -1
- package/dist/types/shared/surface.d.ts +19 -0
- package/docs/cli.md +30 -0
- package/docs/http-api.md +55 -0
- package/docs/mcp.md +40 -2
- package/docs/node-types.md +26 -0
- package/docs/plans/plan-004-pmx-ax-primitives.md +623 -394
- package/docs/sdk.md +20 -0
- package/package.json +2 -2
- package/skills/pmx-canvas/SKILL.md +107 -9
- package/src/cli/agent.ts +177 -0
- package/src/client/canvas/CanvasNode.tsx +8 -4
- package/src/client/canvas/ExpandedNodeOverlay.tsx +12 -0
- package/src/client/nodes/ContextNode.tsx +17 -0
- package/src/client/nodes/ExtAppFrame.tsx +40 -3
- package/src/client/nodes/FileNode.tsx +26 -0
- package/src/client/nodes/HtmlNode.tsx +60 -188
- package/src/client/nodes/McpAppNode.tsx +47 -2
- package/src/client/nodes/StatusNode.tsx +20 -0
- package/src/client/nodes/ax-node-actions.ts +39 -0
- package/src/client/nodes/surface-url.ts +48 -0
- package/src/client/state/attention-bridge.ts +5 -0
- package/src/client/state/intent-bridge.ts +33 -0
- package/src/client/theme/global.css +13 -0
- package/src/client/theme/surface-theme.css +142 -0
- package/src/json-render/renderer/index.tsx +31 -0
- package/src/json-render/schema.ts +4 -0
- package/src/json-render/server.ts +13 -0
- package/src/mcp/canvas-access.ts +195 -0
- package/src/mcp/server.ts +232 -2
- package/src/server/ax-context.ts +3 -0
- package/src/server/ax-interaction.ts +549 -0
- package/src/server/ax-state.ts +188 -2
- package/src/server/canvas-db.ts +20 -0
- package/src/server/canvas-operations.ts +11 -0
- package/src/server/canvas-serialization.ts +9 -0
- package/src/server/canvas-state.ts +177 -16
- package/src/server/html-surface.ts +170 -0
- package/src/server/index.ts +98 -0
- package/src/server/mutation-history.ts +5 -0
- package/src/server/placement.ts +5 -1
- package/src/server/server.ts +305 -0
- package/src/shared/surface.ts +38 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
import { canvasState } from './canvas-state.js';
|
|
3
3
|
import type { CanvasAnnotation, CanvasNodeState, CanvasEdge, CanvasLayout } from './canvas-state.js';
|
|
4
|
-
import
|
|
4
|
+
import { type AxInteractionInput, type AxInteractionPublicResult } from './ax-interaction.js';
|
|
5
|
+
import type { PmxAxApprovalGate, PmxAxCommandDescriptor, PmxAxContext, PmxAxElicitation, PmxAxEvent, PmxAxEvidence, PmxAxEvidenceKind, PmxAxFocusState, PmxAxHostCapability, PmxAxMode, PmxAxModeRequest, PmxAxPolicy, PmxAxReviewAnchorType, PmxAxReviewAnnotation, PmxAxReviewKind, PmxAxReviewRegion, PmxAxReviewSeverity, PmxAxReviewStatus, PmxAxSource, PmxAxState, PmxAxSteeringMessage, PmxAxWorkItem, PmxAxWorkItemStatus } from './ax-state.js';
|
|
5
6
|
import type { AxTimelineQuery } from './canvas-db.js';
|
|
6
7
|
import { searchNodes } from './spatial-analysis.js';
|
|
7
8
|
import { diffLayouts } from './mutation-history.js';
|
|
@@ -140,6 +141,19 @@ export declare class PmxCanvas extends EventEmitter {
|
|
|
140
141
|
source?: PmxAxSource;
|
|
141
142
|
}): PmxAxSteeringMessage;
|
|
142
143
|
markSteeringDelivered(id: string): boolean;
|
|
144
|
+
/** Undelivered steering for a consumer (loop-safe; excludes consumer-originated). */
|
|
145
|
+
getPendingSteering(options?: {
|
|
146
|
+
consumer?: string;
|
|
147
|
+
limit?: number;
|
|
148
|
+
}): PmxAxSteeringMessage[];
|
|
149
|
+
/**
|
|
150
|
+
* Submit a node-originated AX interaction (plan-004 Phase 1). Validates the
|
|
151
|
+
* envelope + node capabilities, maps the interaction onto the matching AX
|
|
152
|
+
* operation, and emits the outcome + state SSE events.
|
|
153
|
+
*/
|
|
154
|
+
submitAxInteraction(input: AxInteractionInput, options?: {
|
|
155
|
+
source?: PmxAxSource;
|
|
156
|
+
}): AxInteractionPublicResult;
|
|
143
157
|
getAxTimeline(query?: AxTimelineQuery): ReturnType<typeof canvasState.getAxTimeline>;
|
|
144
158
|
listWorkItems(): PmxAxWorkItem[];
|
|
145
159
|
addWorkItem(input: {
|
|
@@ -206,6 +220,40 @@ export declare class PmxCanvas extends EventEmitter {
|
|
|
206
220
|
reportHostCapability(input: unknown, options?: {
|
|
207
221
|
source?: PmxAxSource;
|
|
208
222
|
}): PmxAxHostCapability;
|
|
223
|
+
listElicitations(): PmxAxElicitation[];
|
|
224
|
+
requestElicitation(input: {
|
|
225
|
+
prompt: string;
|
|
226
|
+
fields?: string[];
|
|
227
|
+
nodeIds?: string[];
|
|
228
|
+
}, options?: {
|
|
229
|
+
source?: PmxAxSource;
|
|
230
|
+
}): PmxAxElicitation;
|
|
231
|
+
respondElicitation(id: string, response: Record<string, unknown>, options?: {
|
|
232
|
+
source?: PmxAxSource;
|
|
233
|
+
}): PmxAxElicitation | null;
|
|
234
|
+
listModeRequests(): PmxAxModeRequest[];
|
|
235
|
+
requestMode(input: {
|
|
236
|
+
mode: PmxAxMode;
|
|
237
|
+
reason?: string | null;
|
|
238
|
+
nodeIds?: string[];
|
|
239
|
+
}, options?: {
|
|
240
|
+
source?: PmxAxSource;
|
|
241
|
+
}): PmxAxModeRequest;
|
|
242
|
+
resolveModeRequest(id: string, decision: 'approved' | 'rejected', options?: {
|
|
243
|
+
resolution?: string;
|
|
244
|
+
source?: PmxAxSource;
|
|
245
|
+
}): PmxAxModeRequest | null;
|
|
246
|
+
getCommandRegistry(): PmxAxCommandDescriptor[];
|
|
247
|
+
invokeCommand(name: string, args?: Record<string, unknown> | null, options?: {
|
|
248
|
+
source?: PmxAxSource;
|
|
249
|
+
}): PmxAxEvent | null;
|
|
250
|
+
getPolicy(): PmxAxPolicy;
|
|
251
|
+
setPolicy(patch: {
|
|
252
|
+
tools?: Partial<PmxAxPolicy['tools']>;
|
|
253
|
+
prompt?: Partial<PmxAxPolicy['prompt']>;
|
|
254
|
+
}, options?: {
|
|
255
|
+
source?: PmxAxSource;
|
|
256
|
+
}): PmxAxPolicy;
|
|
209
257
|
fitView(options?: {
|
|
210
258
|
width?: number;
|
|
211
259
|
height?: number;
|
|
@@ -439,5 +487,5 @@ export type { WebArtifactBuildInput, WebArtifactBuildOutput, WebArtifactCanvasBu
|
|
|
439
487
|
export type { GraphNodeInput, JsonRenderNodeInput, JsonRenderSpec } from '../json-render/server.js';
|
|
440
488
|
export type { HtmlPrimitiveKind, HtmlPrimitiveDescriptor, HtmlPrimitiveInput, HtmlPrimitiveBuildResult } from './html-primitives.js';
|
|
441
489
|
export { traceManager } from './trace-manager.js';
|
|
442
|
-
export type { PmxAxApprovalGate, PmxAxApprovalStatus, PmxAxContext, PmxAxEvent, PmxAxEventKind, PmxAxEvidence, PmxAxEvidenceKind, PmxAxFocusState, PmxAxHostCapability, PmxAxReviewAnchorType, PmxAxReviewAnnotation, PmxAxReviewKind, PmxAxReviewRegion, PmxAxReviewSeverity, PmxAxReviewStatus, PmxAxSource, PmxAxState, PmxAxSteeringMessage, PmxAxTimelineSummary, PmxAxWorkItem, PmxAxWorkItemStatus, } from './ax-state.js';
|
|
490
|
+
export type { PmxAxApprovalGate, PmxAxApprovalStatus, PmxAxCommandDescriptor, PmxAxContext, PmxAxEvent, PmxAxElicitation, PmxAxElicitationStatus, PmxAxEventKind, PmxAxEvidence, PmxAxEvidenceKind, PmxAxFocusState, PmxAxHostCapability, PmxAxMode, PmxAxModeRequest, PmxAxModeRequestStatus, PmxAxPolicy, PmxAxReviewAnchorType, PmxAxReviewAnnotation, PmxAxReviewKind, PmxAxReviewRegion, PmxAxReviewSeverity, PmxAxReviewStatus, PmxAxSource, PmxAxState, PmxAxSteeringMessage, PmxAxTimelineSummary, PmxAxWorkItem, PmxAxWorkItemStatus, } from './ax-state.js';
|
|
443
491
|
export type { AxTimelineQuery } from './canvas-db.js';
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* - _replaying flag prevents undo/redo from recording new entries
|
|
13
13
|
*/
|
|
14
14
|
import type { CanvasNodeState, CanvasEdge } from './canvas-state.js';
|
|
15
|
-
export type MutationOp = 'addNode' | 'updateNode' | 'removeNode' | 'addEdge' | 'removeEdge' | 'addAnnotation' | 'removeAnnotation' | 'clear' | 'arrange' | 'restoreSnapshot' | 'setPins' | 'setAxFocus' | 'addWorkItem' | 'updateWorkItem' | 'requestApproval' | 'resolveApproval' | 'addReviewAnnotation' | 'updateReviewAnnotation' | 'batch' | 'viewport' | 'groupNodes' | 'ungroupNodes';
|
|
15
|
+
export type MutationOp = 'addNode' | 'updateNode' | 'removeNode' | 'addEdge' | 'removeEdge' | 'addAnnotation' | 'removeAnnotation' | 'clear' | 'arrange' | 'restoreSnapshot' | 'setPins' | 'setAxFocus' | 'addWorkItem' | 'updateWorkItem' | 'requestApproval' | 'resolveApproval' | 'addReviewAnnotation' | 'updateReviewAnnotation' | 'requestElicitation' | 'respondElicitation' | 'requestMode' | 'resolveModeRequest' | 'setPolicy' | 'batch' | 'viewport' | 'groupNodes' | 'ungroupNodes';
|
|
16
16
|
export interface MutationEntry {
|
|
17
17
|
id: string;
|
|
18
18
|
timestamp: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type CanvasPlacementRect } from '../shared/placement.js';
|
|
2
2
|
export { findOpenCanvasPosition, type CanvasPlacementRect } from '../shared/placement.js';
|
|
3
|
-
export declare const GROUP_PAD =
|
|
3
|
+
export declare const GROUP_PAD = 56;
|
|
4
4
|
export declare const GROUP_TITLEBAR_HEIGHT = 32;
|
|
5
5
|
/**
|
|
6
6
|
* Compute bounding box for a group that should contain the given child rects.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-cutting helpers for node "surfaces" — the standalone documents served at
|
|
3
|
+
* /api/canvas/surface/:nodeId. Shared by the server route, the server-side node
|
|
4
|
+
* serialization, and the client so the openability rule lives in exactly one
|
|
5
|
+
* place. The authoritative dispatch (serve vs redirect) lives in the server's
|
|
6
|
+
* handleNodeSurface; this predicate mirrors which node types it can open.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Whether a node has an "Open as site" surface. Coarse by design (presence of the
|
|
10
|
+
* minimal field) — the route itself decides what to actually serve.
|
|
11
|
+
*/
|
|
12
|
+
export declare function canOpenNodeAsSurface(type: string, data: Record<string, unknown>): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* CSP sandbox tokens for a hosted ext-app surface, used both as the in-canvas
|
|
15
|
+
* iframe `sandbox` attribute and as the `Content-Security-Policy: sandbox` value
|
|
16
|
+
* when the surface route serves an ext-app standalone. All tokens are in the
|
|
17
|
+
* server's safe-sandbox allowlist; notably NOT allow-same-origin.
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEFAULT_EXT_APP_SANDBOX = "allow-scripts allow-popups allow-popups-to-escape-sandbox";
|
package/docs/cli.md
CHANGED
|
@@ -157,6 +157,36 @@ pmx-canvas ax host report --host copilot --canvas --session-messaging
|
|
|
157
157
|
pmx-canvas ax host status
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
+
### AX interactions, delivery, elicitation, mode, commands & policy
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Node interaction — one capability-gated envelope (server re-validates + scopes)
|
|
164
|
+
pmx-canvas ax interaction --type ax.work.create --node node-1 --payload '{"title":"Wire auth"}'
|
|
165
|
+
|
|
166
|
+
# Delivery — claim pending steering for a consumer (loop-safe), then acknowledge
|
|
167
|
+
pmx-canvas ax delivery list --consumer copilot --limit 20
|
|
168
|
+
pmx-canvas ax delivery mark <steering-id>
|
|
169
|
+
|
|
170
|
+
# Elicitation — request structured human input, then answer
|
|
171
|
+
pmx-canvas ax elicitation request --prompt "Who owns this migration?" --fields owner
|
|
172
|
+
pmx-canvas ax elicitation respond <id> --response '{"owner":"alice"}'
|
|
173
|
+
pmx-canvas ax elicitation list
|
|
174
|
+
|
|
175
|
+
# Mode — request a plan/execute/autonomous transition, then resolve
|
|
176
|
+
pmx-canvas ax mode request --mode execute --reason "plan approved"
|
|
177
|
+
pmx-canvas ax mode resolve <id> --decision approved
|
|
178
|
+
pmx-canvas ax mode list
|
|
179
|
+
|
|
180
|
+
# Commands — list the registry, invoke a registry-gated command
|
|
181
|
+
pmx-canvas ax command list
|
|
182
|
+
pmx-canvas ax command invoke pmx.plan
|
|
183
|
+
pmx-canvas ax command invoke pmx.promote-context --args '{"nodeIds":["n1"]}'
|
|
184
|
+
|
|
185
|
+
# Policy — read / patch the tool/prompt policy (stored by PMX, enforced by adapters)
|
|
186
|
+
pmx-canvas ax policy get
|
|
187
|
+
pmx-canvas ax policy set --excluded-tools shell,write --mode concise
|
|
188
|
+
```
|
|
189
|
+
|
|
160
190
|
## Copilot adapter
|
|
161
191
|
|
|
162
192
|
Install the bundled GitHub Copilot extension adapter into a repo. The adapter
|
package/docs/http-api.md
CHANGED
|
@@ -181,6 +181,61 @@ Validation: `/ax/event` requires a valid `kind` + `summary` (400 otherwise);
|
|
|
181
181
|
and `PATCH /ax/review/:id` return 404 for unknown IDs; approval resolve returns
|
|
182
182
|
404 if the gate is missing or already resolved.
|
|
183
183
|
|
|
184
|
+
## AX interactions, delivery, elicitation, mode, commands & policy
|
|
185
|
+
|
|
186
|
+
Node interactions are one normalized, capability-gated envelope that maps onto an
|
|
187
|
+
AX operation. The server re-validates every interaction against the source node's
|
|
188
|
+
effective capabilities and clamps sandboxed surfaces (`html-node`, `mcp-app`,
|
|
189
|
+
`json-render`) to their own node.
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# Node interaction — one envelope, validated + mapped to the matching AX op
|
|
193
|
+
curl -X POST http://localhost:4313/api/canvas/ax/interaction \
|
|
194
|
+
-H "Content-Type: application/json" \
|
|
195
|
+
-d '{"type":"ax.work.create","sourceNodeId":"node-1","payload":{"title":"Wire auth"}}'
|
|
196
|
+
|
|
197
|
+
# Delivery — claim pending steering for a consumer (loop-safe), then mark delivered
|
|
198
|
+
curl "http://localhost:4313/api/canvas/ax/delivery/pending?consumer=copilot&limit=20"
|
|
199
|
+
curl -X POST http://localhost:4313/api/canvas/ax/delivery/<steering-id>/mark \
|
|
200
|
+
-H "Content-Type: application/json" \
|
|
201
|
+
-d '{"consumer":"copilot"}'
|
|
202
|
+
|
|
203
|
+
# Elicitation — request structured human input, then respond
|
|
204
|
+
curl -X POST http://localhost:4313/api/canvas/ax/elicitation \
|
|
205
|
+
-H "Content-Type: application/json" \
|
|
206
|
+
-d '{"prompt":"Who owns this migration?","fields":["owner"],"source":"api"}'
|
|
207
|
+
curl -X POST http://localhost:4313/api/canvas/ax/elicitation/<id>/respond \
|
|
208
|
+
-H "Content-Type: application/json" \
|
|
209
|
+
-d '{"response":{"owner":"alice"}}'
|
|
210
|
+
curl http://localhost:4313/api/canvas/ax/elicitation
|
|
211
|
+
|
|
212
|
+
# Mode — request a plan/execute/autonomous transition, then resolve
|
|
213
|
+
curl -X POST http://localhost:4313/api/canvas/ax/mode \
|
|
214
|
+
-H "Content-Type: application/json" \
|
|
215
|
+
-d '{"mode":"plan","reason":"scope the change first","source":"api"}'
|
|
216
|
+
curl -X POST http://localhost:4313/api/canvas/ax/mode/<id>/resolve \
|
|
217
|
+
-H "Content-Type: application/json" \
|
|
218
|
+
-d '{"decision":"approved"}'
|
|
219
|
+
curl http://localhost:4313/api/canvas/ax/mode
|
|
220
|
+
|
|
221
|
+
# Commands — list the registry, invoke a command (records a `command` agent-event)
|
|
222
|
+
curl http://localhost:4313/api/canvas/ax/command
|
|
223
|
+
curl -X POST http://localhost:4313/api/canvas/ax/command \
|
|
224
|
+
-H "Content-Type: application/json" \
|
|
225
|
+
-d '{"name":"pmx.plan","args":{"note":"draft a plan"},"source":"api"}'
|
|
226
|
+
|
|
227
|
+
# Policy — read / patch the canvas-bound tool/prompt policy (patches merge)
|
|
228
|
+
curl http://localhost:4313/api/canvas/ax/policy
|
|
229
|
+
curl -X POST http://localhost:4313/api/canvas/ax/policy \
|
|
230
|
+
-H "Content-Type: application/json" \
|
|
231
|
+
-d '{"tools":{"excluded":["shell"]},"prompt":{"mode":"concise"},"source":"api"}'
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Validation: `/ax/interaction` returns `{ ok: false, code }` (403 `ax-disabled` /
|
|
235
|
+
`not-allowed`, 400 `invalid-payload` / `unknown-command`, 404 `unknown-node`);
|
|
236
|
+
`/ax/command` rejects an unknown command name with 400; `/ax/elicitation/:id/respond`
|
|
237
|
+
and `/ax/mode/:id/resolve` return 404 for unknown IDs.
|
|
238
|
+
|
|
184
239
|
## Diagrams (Excalidraw preset)
|
|
185
240
|
|
|
186
241
|
```bash
|
package/docs/mcp.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MCP reference
|
|
2
2
|
|
|
3
|
-
PMX Canvas ships an MCP stdio server with **
|
|
3
|
+
PMX Canvas ships an MCP stdio server with **65 tools** + **14 core resources**,
|
|
4
4
|
plus per-skill resources at `canvas://skills/<name>`. The server emits
|
|
5
5
|
`notifications/resources/updated` when canvas state changes — humans pin
|
|
6
6
|
nodes in the browser, agents are notified immediately.
|
|
@@ -65,6 +65,15 @@ searchable and readable in pinned/spatial context.
|
|
|
65
65
|
| `canvas_add_evidence` | Record an `evidence-item` on the timeline (logs/tool-result/screenshot/file/diff/test-output) |
|
|
66
66
|
| `canvas_add_review_annotation` | Add a canvas-bound `review-annotation` (comment/finding) anchored to a node, file, or region |
|
|
67
67
|
| `canvas_report_host_capability` | Report a host/session `host-capability` for diagnostics |
|
|
68
|
+
| `canvas_ax_interaction` | Submit one capability-gated AX interaction envelope (`{ type, sourceNodeId, payload }`) that maps onto an AX operation; the server re-validates and clamps sandboxed surfaces to their own node |
|
|
69
|
+
| `canvas_claim_ax_delivery` | Claim undelivered steering messages for an adapterless consumer (loop-safe — never returns steering the consumer originated) |
|
|
70
|
+
| `canvas_mark_ax_delivery` | Mark a steering message delivered for a consumer |
|
|
71
|
+
| `canvas_request_elicitation` | Request structured human input via a canvas-bound `elicitation` (pending) |
|
|
72
|
+
| `canvas_respond_elicitation` | Respond to / resolve a pending elicitation |
|
|
73
|
+
| `canvas_request_mode` | Request a workflow `mode-request` transition (plan/execute/autonomous) |
|
|
74
|
+
| `canvas_resolve_mode` | Resolve a pending mode request |
|
|
75
|
+
| `canvas_invoke_command` | Invoke a registry command (`pmx.plan`, `pmx.execute`, `pmx.promote-context`, `pmx.summarize`, `pmx.review`); records a `command` agent-event, unknown names rejected |
|
|
76
|
+
| `canvas_set_ax_policy` | Patch the canvas-bound tool/prompt policy (`tools.allowed\|excluded\|approvalRequired`, `prompt.systemAppend\|mode`); patches merge and are normalized |
|
|
68
77
|
| `canvas_pin_nodes` | Pin nodes to include in agent context |
|
|
69
78
|
| `canvas_clear` | Clear all nodes and edges |
|
|
70
79
|
| `canvas_snapshot` | Save current canvas as a named snapshot |
|
|
@@ -96,8 +105,10 @@ Individual bundled skills are also readable at `canvas://skills/<name>`.
|
|
|
96
105
|
| `canvas://pinned-context` | Content of pinned nodes + nearby unpinned neighbors |
|
|
97
106
|
| `canvas://ax` | PMX AX state: focus, work items, approval gates, review annotations |
|
|
98
107
|
| `canvas://ax-context` | Agent-readable pinned and focused AX context, plus timeline summary and host capability |
|
|
99
|
-
| `canvas://ax-work` | Canvas-bound AX work: work items, approval gates, review annotations |
|
|
108
|
+
| `canvas://ax-work` | Canvas-bound AX work: work items, approval gates, review annotations, elicitations, mode requests, and tool/prompt policy |
|
|
100
109
|
| `canvas://ax-timeline` | Bounded AX timeline: recent agent-events, evidence, and steering messages |
|
|
110
|
+
| `canvas://ax-pending-steering` | Undelivered steering an adapterless MCP client can claim, act on, and mark delivered |
|
|
111
|
+
| `canvas://ax-delivery` | Steering delivery state (delivered flag) for diagnostics |
|
|
101
112
|
| `canvas://schema` | Running-server create schemas and json-render catalog metadata |
|
|
102
113
|
| `canvas://layout` | Full canvas state (all nodes, edges, viewport) |
|
|
103
114
|
| `canvas://summary` | Compact overview: counts, pinned titles, viewport |
|
|
@@ -106,6 +117,33 @@ Individual bundled skills are also readable at `canvas://skills/<name>`.
|
|
|
106
117
|
| `canvas://code-graph` | Auto-detected file dependency graph (JS/TS, Python, Go, Rust) |
|
|
107
118
|
| `canvas://skills` | Index of bundled agent skills + per-skill content at `canvas://skills/<name>` |
|
|
108
119
|
|
|
120
|
+
## Node interactions (capability-gated)
|
|
121
|
+
|
|
122
|
+
Eligible nodes emit one normalized, validated interaction envelope
|
|
123
|
+
(`{ type, sourceNodeId, payload, sourceSurface }`) via `canvas_ax_interaction`
|
|
124
|
+
(HTTP `POST /api/canvas/ax/interaction`) that maps onto an AX operation — work
|
|
125
|
+
item, evidence, approval, review, focus, steering, event, elicitation, mode, or
|
|
126
|
+
command. The server is the single trust boundary and re-validates every
|
|
127
|
+
interaction against the node's effective capabilities.
|
|
128
|
+
|
|
129
|
+
- **Capabilities:** each node type has a default capability set (a ceiling). A
|
|
130
|
+
node may opt in or narrow via `data.axCapabilities` (`{ enabled, allowed }`),
|
|
131
|
+
clamped to the ceiling — a node can never escalate beyond its type's ceiling.
|
|
132
|
+
`html` / `html-primitive`, `mcp-app`, and internal `prompt` / `response` are
|
|
133
|
+
disabled by default.
|
|
134
|
+
- **Scoping:** sandboxed/opaque-origin iframe surfaces (`html-node`, `mcp-app`,
|
|
135
|
+
`json-render`) are clamped to their own node — caller-supplied `nodeIds` are
|
|
136
|
+
forced to the source node. Trusted surfaces (`native-node`, `adapter`) may
|
|
137
|
+
target explicit nodeIds.
|
|
138
|
+
- **Transports:** native node controls call the endpoint directly; sandboxed
|
|
139
|
+
`html` / `mcp-app` nodes call `window.PMX_AX.emit(type, payload)`; the
|
|
140
|
+
`json-render` / `graph` viewer forwards a spec action named after an AX type
|
|
141
|
+
(e.g. `on.press → { action: "ax.work.create", params }`). All postMessage
|
|
142
|
+
transports are nonce-validated by the parent canvas before submission.
|
|
143
|
+
- **Commands:** `canvas_invoke_command` runs a registry command (`pmx.plan`,
|
|
144
|
+
`pmx.execute`, `pmx.promote-context`, `pmx.summarize`, `pmx.review`); unknown
|
|
145
|
+
names are rejected and a successful call records a `command` agent-event.
|
|
146
|
+
|
|
109
147
|
## Change notifications
|
|
110
148
|
|
|
111
149
|
The MCP server emits `notifications/resources/updated` whenever canvas state
|
package/docs/node-types.md
CHANGED
|
@@ -138,6 +138,32 @@ canvas_add_json_render_node({
|
|
|
138
138
|
`outline`. Older saved specs using `label` or status variants such as
|
|
139
139
|
`success`/`warning` are normalized during validation.
|
|
140
140
|
|
|
141
|
+
Elements may carry an `on` map (`on.press`, `on.change`, …) binding events to
|
|
142
|
+
actions (`{ action, params }`) — built-in actions (`setState`, `pushState`, …) or
|
|
143
|
+
host-provided handlers. PMX wires AX handlers named after interaction types, so a
|
|
144
|
+
spec action named `ax.*` becomes a capability-gated AX interaction:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
canvas_add_json_render_node({
|
|
148
|
+
title: 'Approve plan',
|
|
149
|
+
spec: {
|
|
150
|
+
root: 'btn',
|
|
151
|
+
elements: {
|
|
152
|
+
btn: {
|
|
153
|
+
type: 'Button',
|
|
154
|
+
props: { label: 'Track as work', variant: 'primary' },
|
|
155
|
+
on: { press: { action: 'ax.work.create', params: { title: 'Ship the plan' } } },
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The viewer forwards the emit to the parent canvas, which validates it (iframe
|
|
163
|
+
source + per-viewer nonce + node id) and submits it server-side; `json-render` /
|
|
164
|
+
`graph` viewers are sandboxed surfaces, so caller-supplied `nodeIds` are clamped
|
|
165
|
+
to the node's own id. See the [MCP reference](mcp.md#node-interactions-capability-gated).
|
|
166
|
+
|
|
141
167
|
Use `canvas_describe_schema` / `canvas_validate_spec` to introspect the
|
|
142
168
|
component catalog before building a spec.
|
|
143
169
|
|