pmx-canvas 0.1.18 → 0.1.20

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 (70) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/Readme.md +19 -6
  3. package/dist/canvas/global.css +35 -2
  4. package/dist/canvas/index.js +70 -69
  5. package/dist/json-render/index.js +109 -109
  6. package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
  7. package/dist/types/client/icons.d.ts +2 -0
  8. package/dist/types/client/state/canvas-store.d.ts +2 -0
  9. package/dist/types/client/types.d.ts +2 -1
  10. package/dist/types/json-render/charts/components.d.ts +5 -1
  11. package/dist/types/json-render/renderer/index.d.ts +1 -0
  12. package/dist/types/json-render/server.d.ts +1 -0
  13. package/dist/types/mcp/canvas-access.d.ts +3 -0
  14. package/dist/types/server/canvas-operations.d.ts +4 -0
  15. package/dist/types/server/canvas-schema.d.ts +19 -3
  16. package/dist/types/server/canvas-serialization.d.ts +1 -0
  17. package/dist/types/server/canvas-state.d.ts +8 -2
  18. package/dist/types/server/html-primitives.d.ts +34 -0
  19. package/dist/types/server/index.d.ts +19 -0
  20. package/docs/RELEASE.md +153 -0
  21. package/docs/bun-webview-integration.md +296 -0
  22. package/docs/cli.md +143 -0
  23. package/docs/evals/e2e-cli-coverage.md +61 -0
  24. package/docs/http-api.md +201 -0
  25. package/docs/mcp.md +137 -0
  26. package/docs/node-types.md +272 -0
  27. package/docs/plans/.gitkeep +0 -0
  28. package/docs/plans/plan-001-semantic-watch-mvp.md +335 -0
  29. package/docs/plans/plan-002-human-attention-layer-design-spec.md +679 -0
  30. package/docs/plans/plan-003-human-attention-layer-implementation-plan.md +572 -0
  31. package/docs/reactive-canvas-proposal.md +578 -0
  32. package/docs/release-review-0.1.0.md +38 -0
  33. package/docs/screenshot.png +0 -0
  34. package/docs/screenshots/demo-workbench-dark.png +0 -0
  35. package/docs/screenshots/demo-workbench-light.png +0 -0
  36. package/docs/screenshots/welcome-dark.png +0 -0
  37. package/docs/screenshots/welcome-light.png +0 -0
  38. package/docs/sdk.md +103 -0
  39. package/package.json +2 -1
  40. package/skills/pmx-canvas/SKILL.md +8 -0
  41. package/src/cli/agent.ts +167 -5
  42. package/src/client/App.tsx +20 -1
  43. package/src/client/canvas/AnnotationLayer.tsx +33 -12
  44. package/src/client/canvas/CanvasViewport.tsx +88 -7
  45. package/src/client/canvas/CommandPalette.tsx +1 -1
  46. package/src/client/canvas/ContextMenu.tsx +2 -2
  47. package/src/client/canvas/ExpandedNodeOverlay.tsx +7 -1
  48. package/src/client/icons.tsx +13 -0
  49. package/src/client/nodes/McpAppNode.tsx +12 -4
  50. package/src/client/state/canvas-store.ts +15 -5
  51. package/src/client/state/sse-bridge.ts +4 -3
  52. package/src/client/theme/global.css +35 -2
  53. package/src/client/types.ts +2 -1
  54. package/src/json-render/charts/components.tsx +41 -7
  55. package/src/json-render/charts/extra-components.tsx +13 -12
  56. package/src/json-render/renderer/index.tsx +1 -0
  57. package/src/json-render/server.ts +3 -1
  58. package/src/mcp/canvas-access.ts +25 -0
  59. package/src/mcp/server.ts +85 -27
  60. package/src/server/agent-context.ts +17 -0
  61. package/src/server/canvas-operations.ts +91 -38
  62. package/src/server/canvas-schema.ts +83 -3
  63. package/src/server/canvas-serialization.ts +9 -2
  64. package/src/server/canvas-state.ts +27 -9
  65. package/src/server/demo-state.json +1143 -0
  66. package/src/server/demo.ts +25 -777
  67. package/src/server/html-primitives.ts +990 -0
  68. package/src/server/index.ts +43 -2
  69. package/src/server/server.ts +140 -14
  70. package/src/server/spatial-analysis.ts +3 -3
@@ -32,6 +32,12 @@ function normalizePositiveInteger(value: number | undefined): number | undefined
32
32
  return Math.floor(value);
33
33
  }
34
34
 
35
+ function normalizeSnapshotTimestamp(value: string | undefined): string | undefined {
36
+ if (!value) return undefined;
37
+ const parsed = Date.parse(value);
38
+ return Number.isFinite(parsed) ? new Date(parsed).toISOString() : undefined;
39
+ }
40
+
35
41
  export const PMX_CANVAS_DIR = '.pmx-canvas';
36
42
  const STATE_FILENAME = 'state.json';
37
43
  const SNAPSHOTS_SUBDIR = 'snapshots';
@@ -89,6 +95,8 @@ export interface CanvasSnapshot {
89
95
  export interface CanvasSnapshotListOptions {
90
96
  limit?: number;
91
97
  query?: string;
98
+ before?: string;
99
+ after?: string;
92
100
  all?: boolean;
93
101
  }
94
102
 
@@ -154,11 +162,12 @@ export interface CanvasAnnotationPoint {
154
162
 
155
163
  export interface CanvasAnnotation {
156
164
  id: string;
157
- type: 'freehand';
165
+ type: 'freehand' | 'text';
158
166
  points: CanvasAnnotationPoint[];
159
167
  bounds: { x: number; y: number; width: number; height: number };
160
168
  color: string;
161
169
  width: number;
170
+ text?: string;
162
171
  label?: string;
163
172
  createdAt: string;
164
173
  }
@@ -193,6 +202,10 @@ interface GroupNodesOptions {
193
202
  keepGroupFrame?: boolean;
194
203
  }
195
204
 
205
+ interface ApplyUpdatesOptions {
206
+ skipGroupChildTranslation?: boolean;
207
+ }
208
+
196
209
  function formatBatchUpdateDescription(updates: CanvasNodeUpdate[]): string {
197
210
  let moved = 0;
198
211
  let resized = 0;
@@ -856,11 +869,16 @@ class CanvasStateManager {
856
869
  }
857
870
  }
858
871
  const query = options.query?.trim().toLowerCase();
859
- const filtered = query
860
- ? snapshots.filter((snapshot) =>
861
- snapshot.id.toLowerCase().includes(query) || snapshot.name.toLowerCase().includes(query),
862
- )
863
- : snapshots;
872
+ const before = normalizeSnapshotTimestamp(options.before);
873
+ const after = normalizeSnapshotTimestamp(options.after);
874
+ const filtered = snapshots.filter((snapshot) => {
875
+ if (query && !snapshot.id.toLowerCase().includes(query) && !snapshot.name.toLowerCase().includes(query)) {
876
+ return false;
877
+ }
878
+ if (before && snapshot.createdAt > before) return false;
879
+ if (after && snapshot.createdAt < after) return false;
880
+ return true;
881
+ });
864
882
  const sorted = filtered.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
865
883
  const limit = options.all ? undefined : (normalizePositiveInteger(options.limit) ?? 20);
866
884
  return limit === undefined ? sorted : sorted.slice(0, limit);
@@ -1203,7 +1221,7 @@ class CanvasStateManager {
1203
1221
  };
1204
1222
  }
1205
1223
 
1206
- applyUpdates(updates: CanvasNodeUpdate[]): { applied: number; skipped: number } {
1224
+ applyUpdates(updates: CanvasNodeUpdate[], options: ApplyUpdatesOptions = {}): { applied: number; skipped: number } {
1207
1225
  let applied = 0;
1208
1226
  let skipped = 0;
1209
1227
  const touchedParentGroups = new Map<string, { compact: boolean }>();
@@ -1246,7 +1264,7 @@ class CanvasStateManager {
1246
1264
  }
1247
1265
  oldSnapshots.set(update.id, structuredClone(existing));
1248
1266
  appliedUpdates.push({ id: update.id, ...structuredClone(nextPatch) });
1249
- if (existing.type === 'group' && nextPatch.position) {
1267
+ if (existing.type === 'group' && nextPatch.position && options.skipGroupChildTranslation !== true) {
1250
1268
  this.translateGroupChildren(
1251
1269
  update.id,
1252
1270
  nextPatch.position.x - existing.position.x,
@@ -1284,7 +1302,7 @@ class CanvasStateManager {
1284
1302
  operationType: 'batch',
1285
1303
  description: formatBatchUpdateDescription(appliedUpdates),
1286
1304
  forward: this.suppressed(() => {
1287
- this.applyUpdates(appliedUpdates.map((update) => structuredClone(update)));
1305
+ this.applyUpdates(appliedUpdates.map((update) => structuredClone(update)), options);
1288
1306
  }),
1289
1307
  inverse: this.suppressed(() => {
1290
1308
  for (const snapshot of inverseSnapshots) {