pmx-canvas 0.1.26 → 0.1.27

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 (63) hide show
  1. package/.github/extensions/pmx-canvas/extension.mjs +191 -0
  2. package/CHANGELOG.md +74 -0
  3. package/Readme.md +74 -27
  4. package/dist/canvas/index.js +82 -82
  5. package/dist/json-render/index.css +1 -1
  6. package/dist/json-render/index.js +944 -164
  7. package/dist/types/json-render/catalog.d.ts +195 -20
  8. package/dist/types/json-render/charts/components.d.ts +7 -0
  9. package/dist/types/json-render/charts/definitions.d.ts +13 -1
  10. package/dist/types/json-render/charts/tufte-components.d.ts +65 -0
  11. package/dist/types/json-render/charts/tufte-definitions.d.ts +164 -0
  12. package/dist/types/json-render/directives.d.ts +23 -0
  13. package/dist/types/json-render/renderer/index.d.ts +1 -0
  14. package/dist/types/json-render/server.d.ts +32 -1
  15. package/dist/types/mcp/canvas-access.d.ts +62 -0
  16. package/dist/types/server/ax-state.d.ts +170 -0
  17. package/dist/types/server/canvas-db.d.ts +17 -1
  18. package/dist/types/server/canvas-operations.d.ts +45 -0
  19. package/dist/types/server/canvas-schema.d.ts +5 -1
  20. package/dist/types/server/canvas-state.d.ts +95 -4
  21. package/dist/types/server/index.d.ts +114 -2
  22. package/dist/types/server/mutation-history.d.ts +1 -1
  23. package/docs/cli.md +42 -0
  24. package/docs/http-api.md +64 -0
  25. package/docs/mcp.md +23 -5
  26. package/docs/node-types.md +1 -1
  27. package/docs/screenshots/codex-app.png +0 -0
  28. package/docs/screenshots/github-copilot-app.png +0 -0
  29. package/docs/sdk.md +19 -1
  30. package/package.json +10 -7
  31. package/skills/control-session-orchestrator/SKILL.md +359 -0
  32. package/skills/control-session-orchestrator/evals/evals.json +75 -0
  33. package/skills/data-analysis/SKILL.md +6 -0
  34. package/skills/pmx-canvas/SKILL.md +50 -4
  35. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +6 -0
  36. package/skills/tufte-viz/SKILL.md +157 -0
  37. package/skills/tufte-viz/references/analytical-design.md +217 -0
  38. package/skills/tufte-viz/references/tufte-principles.md +147 -0
  39. package/src/cli/agent.ts +280 -2
  40. package/src/cli/index.ts +2 -1
  41. package/src/client/nodes/ExtAppFrame.tsx +23 -1
  42. package/src/client/nodes/McpAppNode.tsx +6 -2
  43. package/src/json-render/catalog.ts +22 -1
  44. package/src/json-render/charts/components.tsx +97 -10
  45. package/src/json-render/charts/definitions.ts +19 -2
  46. package/src/json-render/charts/extra-components.tsx +5 -4
  47. package/src/json-render/charts/tufte-components.tsx +383 -0
  48. package/src/json-render/charts/tufte-definitions.ts +128 -0
  49. package/src/json-render/directives.ts +29 -0
  50. package/src/json-render/renderer/index.css +101 -0
  51. package/src/json-render/renderer/index.tsx +33 -0
  52. package/src/json-render/server.ts +257 -5
  53. package/src/mcp/canvas-access.ts +261 -0
  54. package/src/mcp/server.ts +496 -7
  55. package/src/server/ax-context.ts +8 -3
  56. package/src/server/ax-state.ts +447 -0
  57. package/src/server/canvas-db.ts +184 -1
  58. package/src/server/canvas-operations.ts +107 -0
  59. package/src/server/canvas-schema.ts +26 -3
  60. package/src/server/canvas-state.ts +349 -2
  61. package/src/server/index.ts +234 -2
  62. package/src/server/mutation-history.ts +6 -0
  63. package/src/server/server.ts +419 -2
@@ -8,6 +8,8 @@ type OpenMcpAppResult = Awaited<ReturnType<PmxCanvas['openMcpApp']>>;
8
8
  type AddDiagramInput = Parameters<PmxCanvas['addDiagram']>[0];
9
9
  type AddJsonRenderNodeInput = Parameters<PmxCanvas['addJsonRenderNode']>[0];
10
10
  type AddJsonRenderNodeResult = ReturnType<PmxCanvas['addJsonRenderNode']>;
11
+ type StreamJsonRenderNodeInput = Parameters<PmxCanvas['streamJsonRenderNode']>[0];
12
+ type StreamJsonRenderNodeResult = ReturnType<PmxCanvas['streamJsonRenderNode']>;
11
13
  type AddHtmlNodeInput = Parameters<PmxCanvas['addHtmlNode']>[0];
12
14
  type AddHtmlPrimitiveInput = Parameters<PmxCanvas['addHtmlPrimitive']>[0];
13
15
  type AddHtmlPrimitiveResult = ReturnType<PmxCanvas['addHtmlPrimitive']>;
@@ -24,6 +26,29 @@ type FitViewResult = ReturnType<PmxCanvas['fitView']>;
24
26
  type AxStateResult = ReturnType<PmxCanvas['getAxState']>;
25
27
  type AxContextResult = ReturnType<PmxCanvas['getAxContext']>;
26
28
  type SetAxFocusResult = ReturnType<PmxCanvas['setAxFocus']>;
29
+ type RecordAxEventInput = Parameters<PmxCanvas['recordAxEvent']>[0];
30
+ type RecordAxEventResult = ReturnType<PmxCanvas['recordAxEvent']>;
31
+ type SendSteeringResult = ReturnType<PmxCanvas['sendSteering']>;
32
+ type GetAxTimelineQuery = Parameters<PmxCanvas['getAxTimeline']>[0];
33
+ type GetAxTimelineResult = ReturnType<PmxCanvas['getAxTimeline']>;
34
+ type AddWorkItemInput = Parameters<PmxCanvas['addWorkItem']>[0];
35
+ type AddWorkItemResult = ReturnType<PmxCanvas['addWorkItem']>;
36
+ type UpdateWorkItemPatch = Parameters<PmxCanvas['updateWorkItem']>[1];
37
+ type UpdateWorkItemResult = ReturnType<PmxCanvas['updateWorkItem']>;
38
+ type ListWorkItemsResult = ReturnType<PmxCanvas['listWorkItems']>;
39
+ type RequestApprovalInput = Parameters<PmxCanvas['requestApproval']>[0];
40
+ type RequestApprovalResult = ReturnType<PmxCanvas['requestApproval']>;
41
+ type ResolveApprovalResult = ReturnType<PmxCanvas['resolveApproval']>;
42
+ type ListApprovalGatesResult = ReturnType<PmxCanvas['listApprovalGates']>;
43
+ type AddEvidenceInput = Parameters<PmxCanvas['addEvidence']>[0];
44
+ type AddEvidenceResult = ReturnType<PmxCanvas['addEvidence']>;
45
+ type AddReviewAnnotationInput = Parameters<PmxCanvas['addReviewAnnotation']>[0];
46
+ type AddReviewAnnotationResult = ReturnType<PmxCanvas['addReviewAnnotation']>;
47
+ type UpdateReviewAnnotationPatch = Parameters<PmxCanvas['updateReviewAnnotation']>[1];
48
+ type UpdateReviewAnnotationResult = ReturnType<PmxCanvas['updateReviewAnnotation']>;
49
+ type ListReviewAnnotationsResult = ReturnType<PmxCanvas['listReviewAnnotations']>;
50
+ type GetHostCapabilityResult = ReturnType<PmxCanvas['getHostCapability']>;
51
+ type ReportHostCapabilityResult = ReturnType<PmxCanvas['reportHostCapability']>;
27
52
  type SearchResult = ReturnType<PmxCanvas['search']>;
28
53
  type UndoRedoResult = Awaited<ReturnType<PmxCanvas['undo']>>;
29
54
  type HistoryResult = ReturnType<PmxCanvas['getHistory']>;
@@ -55,6 +80,7 @@ export interface CanvasAccess {
55
80
  openMcpApp(input: OpenMcpAppInput): Promise<OpenMcpAppResult>;
56
81
  addDiagram(input: AddDiagramInput): Promise<OpenMcpAppResult>;
57
82
  addJsonRenderNode(input: AddJsonRenderNodeInput): Promise<AddJsonRenderNodeResult>;
83
+ streamJsonRenderNode(input: StreamJsonRenderNodeInput): Promise<StreamJsonRenderNodeResult>;
58
84
  addHtmlNode(input: AddHtmlNodeInput): Promise<string>;
59
85
  addHtmlPrimitive(input: AddHtmlPrimitiveInput): Promise<AddHtmlPrimitiveResult>;
60
86
  addGraphNode(input: AddGraphNodeInput): Promise<AddGraphNodeResult>;
@@ -77,6 +103,42 @@ export interface CanvasAccess {
77
103
  setAxFocus(nodeIds: string[], options?: {
78
104
  source?: PmxAxSource;
79
105
  }): Promise<SetAxFocusResult>;
106
+ recordAxEvent(input: RecordAxEventInput, options?: {
107
+ source?: PmxAxSource;
108
+ }): Promise<RecordAxEventResult>;
109
+ sendSteering(message: string, options?: {
110
+ source?: PmxAxSource;
111
+ }): Promise<SendSteeringResult>;
112
+ getAxTimeline(query?: GetAxTimelineQuery): Promise<GetAxTimelineResult>;
113
+ addWorkItem(input: AddWorkItemInput, options?: {
114
+ source?: PmxAxSource;
115
+ }): Promise<AddWorkItemResult>;
116
+ updateWorkItem(id: string, patch: UpdateWorkItemPatch, options?: {
117
+ source?: PmxAxSource;
118
+ }): Promise<UpdateWorkItemResult>;
119
+ listWorkItems(): Promise<ListWorkItemsResult>;
120
+ requestApproval(input: RequestApprovalInput, options?: {
121
+ source?: PmxAxSource;
122
+ }): Promise<RequestApprovalResult>;
123
+ resolveApproval(id: string, decision: 'approved' | 'rejected', options?: {
124
+ resolution?: string;
125
+ source?: PmxAxSource;
126
+ }): Promise<ResolveApprovalResult>;
127
+ listApprovalGates(): Promise<ListApprovalGatesResult>;
128
+ addEvidence(input: AddEvidenceInput, options?: {
129
+ source?: PmxAxSource;
130
+ }): Promise<AddEvidenceResult>;
131
+ addReviewAnnotation(input: AddReviewAnnotationInput, options?: {
132
+ source?: PmxAxSource;
133
+ }): Promise<AddReviewAnnotationResult>;
134
+ updateReviewAnnotation(id: string, patch: UpdateReviewAnnotationPatch, options?: {
135
+ source?: PmxAxSource;
136
+ }): Promise<UpdateReviewAnnotationResult>;
137
+ listReviewAnnotations(): Promise<ListReviewAnnotationsResult>;
138
+ getHostCapability(): Promise<GetHostCapabilityResult>;
139
+ reportHostCapability(input: unknown, options?: {
140
+ source?: PmxAxSource;
141
+ }): Promise<ReportHostCapabilityResult>;
80
142
  clear(): Promise<void>;
81
143
  search(query: string): Promise<SearchResult>;
82
144
  undo(): Promise<UndoRedoResult>;
@@ -7,9 +7,121 @@ export interface PmxAxFocusState {
7
7
  updatedAt: string | null;
8
8
  source: PmxAxSource | null;
9
9
  }
10
+ export type PmxAxEventKind = 'prompt' | 'assistant-message' | 'tool-start' | 'tool-result' | 'failure' | 'approval' | 'steering';
11
+ export type PmxAxEvidenceKind = 'logs' | 'tool-result' | 'screenshot' | 'file' | 'diff' | 'test-output';
12
+ export type PmxAxWorkItemStatus = 'todo' | 'in-progress' | 'blocked' | 'done' | 'cancelled';
13
+ export type PmxAxApprovalStatus = 'pending' | 'approved' | 'rejected';
14
+ export type PmxAxReviewKind = 'comment' | 'finding';
15
+ export type PmxAxReviewSeverity = 'info' | 'warning' | 'error';
16
+ export type PmxAxReviewStatus = 'open' | 'resolved' | 'dismissed';
17
+ export type PmxAxReviewAnchorType = 'node' | 'file' | 'region';
18
+ export interface PmxAxWorkItem {
19
+ id: string;
20
+ title: string;
21
+ status: PmxAxWorkItemStatus;
22
+ detail: string | null;
23
+ nodeIds: string[];
24
+ createdAt: string;
25
+ updatedAt: string;
26
+ source: PmxAxSource | null;
27
+ }
28
+ export interface PmxAxApprovalGate {
29
+ id: string;
30
+ title: string;
31
+ detail: string | null;
32
+ action: string | null;
33
+ status: PmxAxApprovalStatus;
34
+ nodeIds: string[];
35
+ createdAt: string;
36
+ resolvedAt: string | null;
37
+ resolution: string | null;
38
+ source: PmxAxSource | null;
39
+ }
40
+ export interface PmxAxReviewRegion {
41
+ line?: number;
42
+ endLine?: number;
43
+ label?: string;
44
+ }
45
+ export interface PmxAxReviewAnnotation {
46
+ id: string;
47
+ kind: PmxAxReviewKind;
48
+ body: string;
49
+ severity: PmxAxReviewSeverity;
50
+ status: PmxAxReviewStatus;
51
+ anchorType: PmxAxReviewAnchorType;
52
+ nodeId: string | null;
53
+ file: string | null;
54
+ region: PmxAxReviewRegion | null;
55
+ author: string | null;
56
+ createdAt: string;
57
+ updatedAt: string;
58
+ source: PmxAxSource | null;
59
+ }
60
+ export interface PmxAxEvent {
61
+ id: string;
62
+ seq: number;
63
+ kind: PmxAxEventKind;
64
+ summary: string;
65
+ detail: string | null;
66
+ nodeIds: string[];
67
+ data: Record<string, unknown> | null;
68
+ createdAt: string;
69
+ source: PmxAxSource | null;
70
+ }
71
+ export interface PmxAxEvidence {
72
+ id: string;
73
+ seq: number;
74
+ kind: PmxAxEvidenceKind;
75
+ title: string;
76
+ body: string | null;
77
+ ref: string | null;
78
+ nodeIds: string[];
79
+ data: Record<string, unknown> | null;
80
+ createdAt: string;
81
+ source: PmxAxSource | null;
82
+ }
83
+ export interface PmxAxSteeringMessage {
84
+ id: string;
85
+ seq: number;
86
+ message: string;
87
+ delivered: boolean;
88
+ createdAt: string;
89
+ source: PmxAxSource | null;
90
+ }
91
+ export interface PmxAxHostCapability {
92
+ host: string | null;
93
+ canvas: boolean;
94
+ hooks: boolean;
95
+ tools: boolean;
96
+ sessionMessaging: boolean;
97
+ permissions: boolean;
98
+ files: boolean;
99
+ uiPrompts: boolean;
100
+ reportedAt: string | null;
101
+ raw: Record<string, unknown> | null;
102
+ }
103
+ export interface PmxAxTimelineSummary {
104
+ recentEvents: PmxAxEvent[];
105
+ recentEvidence: PmxAxEvidence[];
106
+ pendingSteering: PmxAxSteeringMessage[];
107
+ counts: {
108
+ events: number;
109
+ evidence: number;
110
+ steering: number;
111
+ };
112
+ }
113
+ export declare const AX_TIMELINE_RETENTION = 500;
114
+ export declare const AX_TIMELINE_DEFAULT_LIMIT = 50;
115
+ export declare const AX_TIMELINE_MAX_LIMIT = 200;
116
+ export declare const AX_CONTEXT_EVENT_LIMIT = 20;
117
+ export declare const AX_CONTEXT_EVIDENCE_LIMIT = 10;
118
+ export declare const AX_CONTEXT_STEERING_LIMIT = 10;
10
119
  export interface PmxAxState {
11
120
  version: 1;
12
121
  focus: PmxAxFocusState;
122
+ workItems: PmxAxWorkItem[];
123
+ approvalGates: PmxAxApprovalGate[];
124
+ reviewAnnotations: PmxAxReviewAnnotation[];
13
125
  }
14
126
  export interface PmxAxPinnedContext {
15
127
  preamble: string;
@@ -29,15 +141,73 @@ export interface PmxAxContext {
29
141
  };
30
142
  pinned: PmxAxPinnedContext;
31
143
  focus: PmxAxFocusContext;
144
+ workItems: PmxAxWorkItem[];
145
+ approvalGates: PmxAxApprovalGate[];
146
+ reviewAnnotations: PmxAxReviewAnnotation[];
147
+ timeline: PmxAxTimelineSummary;
148
+ host: PmxAxHostCapability | null;
32
149
  }
150
+ export declare function isAxEventKind(value: unknown): value is PmxAxEventKind;
151
+ export declare function isAxEvidenceKind(value: unknown): value is PmxAxEvidenceKind;
33
152
  export declare function createEmptyAxFocusState(): PmxAxFocusState;
34
153
  export declare function createEmptyAxState(): PmxAxState;
154
+ export declare function createEmptyAxHostCapability(): PmxAxHostCapability;
35
155
  export declare function normalizeAxFocusState(input: unknown, validNodeIds?: Set<string>): PmxAxFocusState;
156
+ export declare function normalizeAxWorkItem(input: unknown, validNodeIds?: Set<string>): PmxAxWorkItem | null;
157
+ export declare function normalizeAxApprovalGate(input: unknown, validNodeIds?: Set<string>): PmxAxApprovalGate | null;
158
+ export declare function normalizeAxReviewAnnotation(input: unknown, validNodeIds?: Set<string>): PmxAxReviewAnnotation | null;
159
+ export declare function normalizeAxHostCapability(input: unknown): PmxAxHostCapability | null;
160
+ export declare function normalizeAxEvent(input: unknown): PmxAxEvent | null;
161
+ export declare function normalizeAxEvidence(input: unknown): PmxAxEvidence | null;
162
+ export declare function normalizeAxSteeringMessage(input: unknown): PmxAxSteeringMessage | null;
163
+ export declare function createAxWorkItem(input: {
164
+ title: string;
165
+ status?: PmxAxWorkItemStatus;
166
+ detail?: string | null;
167
+ nodeIds?: string[];
168
+ }, source: PmxAxSource | null, validNodeIds?: Set<string>): PmxAxWorkItem;
169
+ export declare function createAxApprovalGate(input: {
170
+ title: string;
171
+ detail?: string | null;
172
+ action?: string | null;
173
+ nodeIds?: string[];
174
+ }, source: PmxAxSource | null, validNodeIds?: Set<string>): PmxAxApprovalGate;
175
+ export declare function createAxReviewAnnotation(input: {
176
+ body: string;
177
+ kind?: PmxAxReviewKind;
178
+ severity?: PmxAxReviewSeverity;
179
+ anchorType?: PmxAxReviewAnchorType;
180
+ nodeId?: string | null;
181
+ file?: string | null;
182
+ region?: PmxAxReviewRegion | null;
183
+ author?: string | null;
184
+ }, source: PmxAxSource | null): PmxAxReviewAnnotation;
185
+ export declare function createAxEvent(input: {
186
+ kind: PmxAxEventKind;
187
+ summary: string;
188
+ detail?: string | null;
189
+ nodeIds?: string[];
190
+ data?: Record<string, unknown> | null;
191
+ }, source: PmxAxSource | null): Omit<PmxAxEvent, 'seq'>;
192
+ export declare function createAxEvidence(input: {
193
+ kind: PmxAxEvidenceKind;
194
+ title: string;
195
+ body?: string | null;
196
+ ref?: string | null;
197
+ nodeIds?: string[];
198
+ data?: Record<string, unknown> | null;
199
+ }, source: PmxAxSource | null): Omit<PmxAxEvidence, 'seq'>;
200
+ export declare function createAxSteeringMessage(message: string, source: PmxAxSource | null): Omit<PmxAxSteeringMessage, 'seq'>;
36
201
  export declare function normalizeAxState(input: unknown, validNodeIds?: Set<string>): PmxAxState;
37
202
  export declare function buildAxContext(input: {
38
203
  layout: CanvasLayout;
39
204
  pinned: PmxAxPinnedContext;
40
205
  focus: PmxAxFocusState;
41
206
  focusNodes: AgentContextNode[];
207
+ workItems: PmxAxWorkItem[];
208
+ approvalGates: PmxAxApprovalGate[];
209
+ reviewAnnotations: PmxAxReviewAnnotation[];
210
+ timeline: PmxAxTimelineSummary;
211
+ host: PmxAxHostCapability | null;
42
212
  }): PmxAxContext;
43
213
  export declare function nodeSetFromLayout(nodes: CanvasNodeState[]): Set<string>;
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { Database } from 'bun:sqlite';
8
8
  import type { CanvasAnnotation, CanvasEdge, CanvasNodeState, CanvasSnapshot, CanvasSnapshotListOptions, ViewportState } from './canvas-state.js';
9
- import { type PmxAxState } from './ax-state.js';
9
+ import { type PmxAxState, type PmxAxEvent, type PmxAxEvidence, type PmxAxSteeringMessage, type PmxAxHostCapability, type PmxAxTimelineSummary } from './ax-state.js';
10
10
  export type CanvasTheme = 'dark' | 'light' | 'high-contrast';
11
11
  export declare function normalizeCanvasTheme(value: unknown, fallback?: CanvasTheme): CanvasTheme;
12
12
  export interface PersistedCanvasState {
@@ -36,3 +36,19 @@ export declare function deleteSnapshotFromDB(db: Database, id: string): boolean;
36
36
  export declare function writeBlobToDB(db: Database, sha256: string, jsonValue: string): number;
37
37
  export declare function readBlobFromDB(db: Database, sha256: string): string | null;
38
38
  export declare function hasBlobInDB(db: Database, sha256: string): boolean;
39
+ export interface AxTimelineQuery {
40
+ limit?: number;
41
+ sessionId?: string;
42
+ }
43
+ export declare function appendAxEventToDB(db: Database, ev: Omit<PmxAxEvent, 'seq'>): PmxAxEvent;
44
+ export declare function appendAxEvidenceToDB(db: Database, ev: Omit<PmxAxEvidence, 'seq'>): PmxAxEvidence;
45
+ export declare function appendAxSteeringToDB(db: Database, s: Omit<PmxAxSteeringMessage, 'seq'>): PmxAxSteeringMessage;
46
+ export declare function markAxSteeringDeliveredInDB(db: Database, id: string): boolean;
47
+ export declare function loadAxEventsFromDB(db: Database, q?: AxTimelineQuery): PmxAxEvent[];
48
+ export declare function loadAxEvidenceFromDB(db: Database, q?: AxTimelineQuery): PmxAxEvidence[];
49
+ export declare function loadAxSteeringFromDB(db: Database, q?: AxTimelineQuery & {
50
+ onlyPending?: boolean;
51
+ }): PmxAxSteeringMessage[];
52
+ export declare function loadAxTimelineSummaryFromDB(db: Database): PmxAxTimelineSummary;
53
+ export declare function upsertAxHostCapabilityToDB(db: Database, cap: PmxAxHostCapability): void;
54
+ export declare function loadAxHostCapabilityFromDB(db: Database): PmxAxHostCapability | null;
@@ -124,6 +124,18 @@ export declare function validateCanvasNodePatch(patch: {
124
124
  export declare function mergeTraceNodeDataFields(base: Record<string, unknown>, input: Record<string, unknown>): Record<string, unknown>;
125
125
  export declare function hasTraceNodeDataFields(input: Record<string, unknown>): boolean;
126
126
  export declare function scheduleCodeGraphRecompute(onComplete?: () => void): void;
127
+ /**
128
+ * Resolve an html-node `html` field that may be a path to a local .html/.htm file.
129
+ *
130
+ * If the string looks like a bare filesystem path to an existing HTML file
131
+ * (no markup, no newlines, short, ends in .html/.htm, exists on disk), read the
132
+ * file and return its contents. Otherwise return the string unchanged as raw HTML.
133
+ * On read failure, fall back to the raw string and warn — never throw.
134
+ *
135
+ * This is a local dev tool, so reading a user-pointed-at local file is acceptable;
136
+ * the markup/newline guards prevent misclassifying genuine HTML as a path.
137
+ */
138
+ export declare function resolveHtmlContent(html: string): string;
127
139
  export declare function addCanvasNode(input: CanvasAddNodeInput): {
128
140
  id: string;
129
141
  node: CanvasNodeState;
@@ -206,6 +218,39 @@ export declare function createCanvasJsonRenderNode(input: JsonRenderNodeInput):
206
218
  spec: JsonRenderSpec;
207
219
  node: CanvasNodeState;
208
220
  };
221
+ /**
222
+ * Create an empty streaming json-render node. Unlike createCanvasJsonRenderNode
223
+ * this does NOT validate a complete spec — the node starts blank and is filled
224
+ * in by appendCanvasJsonRenderStream as SpecStream patches arrive.
225
+ */
226
+ export declare function createCanvasStreamingJsonRenderNode(input: {
227
+ title?: string;
228
+ x?: number;
229
+ y?: number;
230
+ width?: number;
231
+ height?: number;
232
+ strictSize?: boolean;
233
+ }): {
234
+ id: string;
235
+ url: string;
236
+ spec: JsonRenderSpec;
237
+ node: CanvasNodeState;
238
+ };
239
+ /**
240
+ * Apply a batch of SpecStream patches to an existing json-render node, bumping
241
+ * its specVersion so the browser reloads the viewer with the accumulated spec.
242
+ */
243
+ export declare function appendCanvasJsonRenderStream(nodeId: string, patches: unknown[], done: boolean): {
244
+ ok: true;
245
+ applied: number;
246
+ skipped: number;
247
+ specVersion: number;
248
+ elementCount: number;
249
+ streamStatus: 'open' | 'closed';
250
+ } | {
251
+ ok: false;
252
+ error: string;
253
+ };
209
254
  export declare function createCanvasGraphNode(input: GraphNodeInput): {
210
255
  id: string;
211
256
  url: string;
@@ -33,7 +33,7 @@ export interface StructuredValidationResult {
33
33
  };
34
34
  summary: Record<string, unknown>;
35
35
  }
36
- declare const CANONICAL_GRAPH_TYPES: readonly ["line", "bar", "pie", "area", "scatter", "radar", "stacked-bar", "composed"];
36
+ declare const CANONICAL_GRAPH_TYPES: readonly ["line", "bar", "pie", "area", "scatter", "radar", "stacked-bar", "composed", "sparkline", "dot-plot", "bullet", "slopegraph"];
37
37
  type CanvasGraphType = typeof CANONICAL_GRAPH_TYPES[number];
38
38
  export declare function describeCanvasSchema(): {
39
39
  ok: true;
@@ -43,6 +43,10 @@ export declare function describeCanvasSchema(): {
43
43
  jsonRender: {
44
44
  rootShape: Record<string, string>;
45
45
  components: JsonRenderComponentDescriptor[];
46
+ directives: Array<{
47
+ name: string;
48
+ usage: string;
49
+ }>;
46
50
  };
47
51
  graph: {
48
52
  graphTypes: CanvasGraphType[];
@@ -9,8 +9,8 @@
9
9
  * in the workspace root on every mutation (debounced). Auto-loads on `loadFromDisk()`.
10
10
  * Legacy `.pmx-canvas/state.json` is auto-migrated on first boot.
11
11
  */
12
- import { type PersistedCanvasState, type CanvasTheme } from './canvas-db.js';
13
- import { type PmxAxFocusState, type PmxAxSource, type PmxAxState } from './ax-state.js';
12
+ import { type PersistedCanvasState, type CanvasTheme, type AxTimelineQuery } from './canvas-db.js';
13
+ import { type PmxAxFocusState, type PmxAxSource, type PmxAxState, type PmxAxWorkItem, type PmxAxWorkItemStatus, type PmxAxApprovalGate, type PmxAxReviewAnnotation, type PmxAxReviewKind, type PmxAxReviewSeverity, type PmxAxReviewStatus, type PmxAxReviewAnchorType, type PmxAxReviewRegion, type PmxAxEvent, type PmxAxEventKind, type PmxAxEvidence, type PmxAxEvidenceKind, type PmxAxSteeringMessage, type PmxAxHostCapability, type PmxAxTimelineSummary } from './ax-state.js';
14
14
  export declare const PMX_CANVAS_DIR = ".pmx-canvas";
15
15
  export interface PersistedBlobRef {
16
16
  __pmxCanvasBlob: 'v1';
@@ -120,9 +120,9 @@ export interface CanvasNodeUpdate {
120
120
  collapsed?: boolean;
121
121
  dockPosition?: 'left' | 'right' | null;
122
122
  }
123
- export type CanvasChangeType = 'pins' | 'nodes' | 'ax';
123
+ export type CanvasChangeType = 'pins' | 'nodes' | 'ax' | 'ax-timeline';
124
124
  export interface MutationRecordInfo {
125
- operationType: 'addNode' | 'updateNode' | 'removeNode' | 'addEdge' | 'removeEdge' | 'addAnnotation' | 'removeAnnotation' | 'clear' | 'restoreSnapshot' | 'setPins' | 'setAxFocus' | 'arrange' | 'batch' | 'groupNodes' | 'ungroupNodes' | 'viewport';
125
+ operationType: 'addNode' | 'updateNode' | 'removeNode' | 'addEdge' | 'removeEdge' | 'addAnnotation' | 'removeAnnotation' | 'clear' | 'restoreSnapshot' | 'setPins' | 'setAxFocus' | 'addWorkItem' | 'updateWorkItem' | 'requestApproval' | 'resolveApproval' | 'addReviewAnnotation' | 'updateReviewAnnotation' | 'arrange' | 'batch' | 'groupNodes' | 'ungroupNodes' | 'viewport';
126
126
  description: string;
127
127
  forward: () => void;
128
128
  inverse: () => void;
@@ -143,6 +143,7 @@ declare class CanvasStateManager {
143
143
  private _theme;
144
144
  private _contextPinnedNodeIds;
145
145
  private _axState;
146
+ private _axHostCapability;
146
147
  private _workspaceRoot;
147
148
  private _changeListeners;
148
149
  /** Register a listener for state changes. Used by MCP server to emit resource notifications. */
@@ -263,6 +264,96 @@ declare class CanvasStateManager {
263
264
  recordHistory?: boolean;
264
265
  }): PmxAxFocusState;
265
266
  clearAxFocus(): PmxAxFocusState;
267
+ getWorkItems(): PmxAxWorkItem[];
268
+ addWorkItem(input: {
269
+ title: string;
270
+ status?: PmxAxWorkItemStatus;
271
+ detail?: string | null;
272
+ nodeIds?: string[];
273
+ }, options?: {
274
+ source?: PmxAxSource;
275
+ }): PmxAxWorkItem;
276
+ updateWorkItem(id: string, patch: {
277
+ title?: string;
278
+ status?: PmxAxWorkItemStatus;
279
+ detail?: string | null;
280
+ nodeIds?: string[];
281
+ }, options?: {
282
+ source?: PmxAxSource;
283
+ }): PmxAxWorkItem | null;
284
+ getApprovalGates(): PmxAxApprovalGate[];
285
+ requestApproval(input: {
286
+ title: string;
287
+ detail?: string | null;
288
+ action?: string | null;
289
+ nodeIds?: string[];
290
+ }, options?: {
291
+ source?: PmxAxSource;
292
+ }): PmxAxApprovalGate;
293
+ resolveApproval(id: string, decision: 'approved' | 'rejected', options?: {
294
+ resolution?: string;
295
+ source?: PmxAxSource;
296
+ }): PmxAxApprovalGate | null;
297
+ getReviewAnnotations(): PmxAxReviewAnnotation[];
298
+ addReviewAnnotation(input: {
299
+ body: string;
300
+ kind?: PmxAxReviewKind;
301
+ severity?: PmxAxReviewSeverity;
302
+ anchorType?: PmxAxReviewAnchorType;
303
+ nodeId?: string | null;
304
+ file?: string | null;
305
+ region?: PmxAxReviewRegion | null;
306
+ author?: string | null;
307
+ }, options?: {
308
+ source?: PmxAxSource;
309
+ }): PmxAxReviewAnnotation | null;
310
+ updateReviewAnnotation(id: string, patch: {
311
+ body?: string;
312
+ status?: PmxAxReviewStatus;
313
+ severity?: PmxAxReviewSeverity;
314
+ kind?: PmxAxReviewKind;
315
+ }, options?: {
316
+ source?: PmxAxSource;
317
+ }): PmxAxReviewAnnotation | null;
318
+ getHostCapability(): PmxAxHostCapability | null;
319
+ setHostCapability(input: unknown, _options?: {
320
+ source?: PmxAxSource;
321
+ }): PmxAxHostCapability;
322
+ recordAxEvent(input: {
323
+ kind: PmxAxEventKind;
324
+ summary: string;
325
+ detail?: string | null;
326
+ nodeIds?: string[];
327
+ data?: Record<string, unknown> | null;
328
+ }, options?: {
329
+ source?: PmxAxSource;
330
+ }): PmxAxEvent;
331
+ addEvidence(input: {
332
+ kind: PmxAxEvidenceKind;
333
+ title: string;
334
+ body?: string | null;
335
+ ref?: string | null;
336
+ nodeIds?: string[];
337
+ data?: Record<string, unknown> | null;
338
+ }, options?: {
339
+ source?: PmxAxSource;
340
+ }): PmxAxEvidence;
341
+ recordSteeringMessage(message: string, options?: {
342
+ source?: PmxAxSource;
343
+ }): PmxAxSteeringMessage;
344
+ markSteeringDelivered(id: string): boolean;
345
+ getAxEvents(q?: AxTimelineQuery): PmxAxEvent[];
346
+ getAxEvidence(q?: AxTimelineQuery): PmxAxEvidence[];
347
+ getAxSteering(q?: AxTimelineQuery & {
348
+ onlyPending?: boolean;
349
+ }): PmxAxSteeringMessage[];
350
+ getAxTimelineSummary(): PmxAxTimelineSummary;
351
+ getAxTimeline(q?: AxTimelineQuery): {
352
+ events: PmxAxEvent[];
353
+ evidence: PmxAxEvidence[];
354
+ steering: PmxAxSteeringMessage[];
355
+ summary: PmxAxTimelineSummary;
356
+ };
266
357
  setContextPins(nodeIds: string[]): void;
267
358
  clearContextPins(): void;
268
359
  /** Move child nodes into a group. Sets data.parentGroup on children and data.children on the group. */
@@ -1,6 +1,8 @@
1
1
  import { EventEmitter } from 'node:events';
2
+ import { canvasState } from './canvas-state.js';
2
3
  import type { CanvasAnnotation, CanvasNodeState, CanvasEdge, CanvasLayout } from './canvas-state.js';
3
- import type { PmxAxContext, PmxAxFocusState, PmxAxSource, PmxAxState } from './ax-state.js';
4
+ import type { PmxAxApprovalGate, PmxAxContext, PmxAxEvent, PmxAxEvidence, PmxAxEvidenceKind, PmxAxFocusState, PmxAxHostCapability, PmxAxReviewAnchorType, PmxAxReviewAnnotation, PmxAxReviewKind, PmxAxReviewRegion, PmxAxReviewSeverity, PmxAxReviewStatus, PmxAxSource, PmxAxState, PmxAxSteeringMessage, PmxAxWorkItem, PmxAxWorkItemStatus } from './ax-state.js';
5
+ import type { AxTimelineQuery } from './canvas-db.js';
4
6
  import { searchNodes } from './spatial-analysis.js';
5
7
  import { diffLayouts } from './mutation-history.js';
6
8
  import { fitCanvasView, gcCanvasSnapshots, listCanvasSnapshots } from './canvas-operations.js';
@@ -114,6 +116,85 @@ export declare class PmxCanvas extends EventEmitter {
114
116
  setAxFocus(nodeIds: string[], options?: {
115
117
  source?: PmxAxSource;
116
118
  }): PmxAxFocusState;
119
+ recordAxEvent(input: {
120
+ kind: PmxAxEvent['kind'];
121
+ summary: string;
122
+ detail?: string | null;
123
+ nodeIds?: string[];
124
+ data?: Record<string, unknown> | null;
125
+ }, options?: {
126
+ source?: PmxAxSource;
127
+ }): PmxAxEvent;
128
+ sendSteering(message: string, options?: {
129
+ source?: PmxAxSource;
130
+ }): PmxAxSteeringMessage;
131
+ markSteeringDelivered(id: string): boolean;
132
+ getAxTimeline(query?: AxTimelineQuery): ReturnType<typeof canvasState.getAxTimeline>;
133
+ listWorkItems(): PmxAxWorkItem[];
134
+ addWorkItem(input: {
135
+ title: string;
136
+ status?: PmxAxWorkItemStatus;
137
+ detail?: string | null;
138
+ nodeIds?: string[];
139
+ }, options?: {
140
+ source?: PmxAxSource;
141
+ }): PmxAxWorkItem;
142
+ updateWorkItem(id: string, patch: {
143
+ title?: string;
144
+ status?: PmxAxWorkItemStatus;
145
+ detail?: string | null;
146
+ nodeIds?: string[];
147
+ }, options?: {
148
+ source?: PmxAxSource;
149
+ }): PmxAxWorkItem | null;
150
+ listApprovalGates(): PmxAxApprovalGate[];
151
+ requestApproval(input: {
152
+ title: string;
153
+ detail?: string | null;
154
+ action?: string | null;
155
+ nodeIds?: string[];
156
+ }, options?: {
157
+ source?: PmxAxSource;
158
+ }): PmxAxApprovalGate;
159
+ resolveApproval(id: string, decision: 'approved' | 'rejected', options?: {
160
+ resolution?: string;
161
+ source?: PmxAxSource;
162
+ }): PmxAxApprovalGate | null;
163
+ addEvidence(input: {
164
+ kind: PmxAxEvidenceKind;
165
+ title: string;
166
+ body?: string | null;
167
+ ref?: string | null;
168
+ nodeIds?: string[];
169
+ data?: Record<string, unknown> | null;
170
+ }, options?: {
171
+ source?: PmxAxSource;
172
+ }): PmxAxEvidence;
173
+ listReviewAnnotations(): PmxAxReviewAnnotation[];
174
+ addReviewAnnotation(input: {
175
+ body: string;
176
+ kind?: PmxAxReviewKind;
177
+ severity?: PmxAxReviewSeverity;
178
+ anchorType?: PmxAxReviewAnchorType;
179
+ nodeId?: string | null;
180
+ file?: string | null;
181
+ region?: PmxAxReviewRegion | null;
182
+ author?: string | null;
183
+ }, options?: {
184
+ source?: PmxAxSource;
185
+ }): PmxAxReviewAnnotation | null;
186
+ updateReviewAnnotation(id: string, patch: {
187
+ body?: string;
188
+ status?: PmxAxReviewStatus;
189
+ severity?: PmxAxReviewSeverity;
190
+ kind?: PmxAxReviewKind;
191
+ }, options?: {
192
+ source?: PmxAxSource;
193
+ }): PmxAxReviewAnnotation | null;
194
+ getHostCapability(): PmxAxHostCapability | null;
195
+ reportHostCapability(input: unknown, options?: {
196
+ source?: PmxAxSource;
197
+ }): PmxAxHostCapability;
117
198
  fitView(options?: {
118
199
  width?: number;
119
200
  height?: number;
@@ -188,9 +269,13 @@ export declare class PmxCanvas extends EventEmitter {
188
269
  jsonRender: {
189
270
  rootShape: Record<string, string>;
190
271
  components: import("../json-render/catalog.js").JsonRenderComponentDescriptor[];
272
+ directives: Array<{
273
+ name: string;
274
+ usage: string;
275
+ }>;
191
276
  };
192
277
  graph: {
193
- graphTypes: ("line" | "bar" | "pie" | "area" | "scatter" | "radar" | "composed" | "stacked-bar")[];
278
+ graphTypes: ("line" | "bar" | "pie" | "area" | "scatter" | "radar" | "composed" | "sparkline" | "bullet" | "slopegraph" | "stacked-bar" | "dot-plot")[];
194
279
  };
195
280
  htmlPrimitives: import("./html-primitives.js").HtmlPrimitiveDescriptor[];
196
281
  mcp: {
@@ -251,6 +336,31 @@ export declare class PmxCanvas extends EventEmitter {
251
336
  url: string;
252
337
  spec: JsonRenderSpec;
253
338
  };
339
+ /**
340
+ * Progressively build a json-render node from SpecStream patches. Omit nodeId
341
+ * to create a new streaming node; pass the same nodeId on later calls to
342
+ * append more patches. The server accumulates the spec and the browser
343
+ * reloads the viewer as the specVersion bumps.
344
+ */
345
+ streamJsonRenderNode(input: {
346
+ nodeId?: string;
347
+ title?: string;
348
+ patches?: unknown[];
349
+ done?: boolean;
350
+ x?: number;
351
+ y?: number;
352
+ width?: number;
353
+ height?: number;
354
+ strictSize?: boolean;
355
+ }): {
356
+ id: string;
357
+ url: string;
358
+ applied: number;
359
+ skipped: number;
360
+ specVersion: number;
361
+ elementCount: number;
362
+ streamStatus: 'open' | 'closed';
363
+ };
254
364
  addHtmlNode(input: {
255
365
  html: string;
256
366
  title?: string;
@@ -318,3 +428,5 @@ export type { WebArtifactBuildInput, WebArtifactBuildOutput, WebArtifactCanvasBu
318
428
  export type { GraphNodeInput, JsonRenderNodeInput, JsonRenderSpec } from '../json-render/server.js';
319
429
  export type { HtmlPrimitiveKind, HtmlPrimitiveDescriptor, HtmlPrimitiveInput, HtmlPrimitiveBuildResult } from './html-primitives.js';
320
430
  export { traceManager } from './trace-manager.js';
431
+ 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';
432
+ 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' | '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' | 'batch' | 'viewport' | 'groupNodes' | 'ungroupNodes';
16
16
  export interface MutationEntry {
17
17
  id: string;
18
18
  timestamp: string;