pmx-canvas 0.1.11 → 0.1.13

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.
@@ -0,0 +1,9 @@
1
+ export interface TraceDisplayModel {
2
+ toolName: string;
3
+ category: string;
4
+ status: string;
5
+ duration: string;
6
+ resultSummary: string;
7
+ error: string;
8
+ }
9
+ export declare function buildTraceDisplayModel(data: Record<string, unknown>): TraceDisplayModel;
@@ -54,6 +54,8 @@ export declare function replaceViewport(next: ViewportState): void;
54
54
  export declare function commitViewport(next: ViewportState): void;
55
55
  export declare function applyServerCanvasLayout(layout: Pick<CanvasLayout, 'nodes' | 'edges'> & {
56
56
  viewport?: ViewportState;
57
+ }, options?: {
58
+ applyViewport?: boolean;
57
59
  }): void;
58
60
  /**
59
61
  * Smoothly animate the viewport to a target state.
@@ -0,0 +1,88 @@
1
+ import { type CanvasLayout, type CanvasNodeState, type CanvasSnapshot, type PmxCanvas } from '../server/index.js';
2
+ type AddNodeInput = Parameters<PmxCanvas['addNode']>[0];
3
+ type AddWebpageNodeInput = Parameters<PmxCanvas['addWebpageNode']>[0];
4
+ type RefreshWebpageNodeResult = Awaited<ReturnType<PmxCanvas['refreshWebpageNode']>>;
5
+ type OpenMcpAppInput = Parameters<PmxCanvas['openMcpApp']>[0];
6
+ type OpenMcpAppResult = Awaited<ReturnType<PmxCanvas['openMcpApp']>>;
7
+ type AddDiagramInput = Parameters<PmxCanvas['addDiagram']>[0];
8
+ type AddJsonRenderNodeInput = Parameters<PmxCanvas['addJsonRenderNode']>[0];
9
+ type AddJsonRenderNodeResult = ReturnType<PmxCanvas['addJsonRenderNode']>;
10
+ type AddGraphNodeInput = Parameters<PmxCanvas['addGraphNode']>[0];
11
+ type AddGraphNodeResult = ReturnType<PmxCanvas['addGraphNode']>;
12
+ type UpdateNodePatch = Parameters<PmxCanvas['updateNode']>[1];
13
+ type AddEdgeInput = Parameters<PmxCanvas['addEdge']>[0];
14
+ type CreateGroupInput = Parameters<PmxCanvas['createGroup']>[0];
15
+ type GroupNodesOptions = Parameters<PmxCanvas['groupNodes']>[2];
16
+ type ArrangeLayout = Parameters<PmxCanvas['arrange']>[0];
17
+ type FocusNodeResult = ReturnType<PmxCanvas['focusNode']>;
18
+ type FitViewOptions = Parameters<PmxCanvas['fitView']>[0];
19
+ type FitViewResult = ReturnType<PmxCanvas['fitView']>;
20
+ type SearchResult = ReturnType<PmxCanvas['search']>;
21
+ type UndoRedoResult = Awaited<ReturnType<PmxCanvas['undo']>>;
22
+ type HistoryResult = ReturnType<PmxCanvas['getHistory']>;
23
+ type SetContextPinsResult = ReturnType<PmxCanvas['setContextPins']>;
24
+ type RunBatchInput = Parameters<PmxCanvas['runBatch']>[0];
25
+ type RunBatchResult = Awaited<ReturnType<PmxCanvas['runBatch']>>;
26
+ type SnapshotList = ReturnType<PmxCanvas['listSnapshots']>;
27
+ type DeleteSnapshotResult = ReturnType<PmxCanvas['deleteSnapshot']>;
28
+ type DiffSnapshotResult = ReturnType<PmxCanvas['diffSnapshot']>;
29
+ type CodeGraphResult = ReturnType<PmxCanvas['getCodeGraph']>;
30
+ type ValidationResult = ReturnType<PmxCanvas['validate']>;
31
+ type WebArtifactInput = Parameters<PmxCanvas['buildWebArtifact']>[0];
32
+ type WebArtifactResult = Awaited<ReturnType<PmxCanvas['buildWebArtifact']>>;
33
+ type AutomationWebViewOptions = Parameters<PmxCanvas['startAutomationWebView']>[0];
34
+ type AutomationWebViewStatus = Awaited<ReturnType<PmxCanvas['startAutomationWebView']>>;
35
+ type AutomationEvaluateResult = Awaited<ReturnType<PmxCanvas['evaluateAutomationWebView']>>;
36
+ type AutomationScreenshotOptions = Parameters<PmxCanvas['screenshotAutomationWebView']>[0];
37
+ export interface CanvasAccess {
38
+ readonly port: number;
39
+ readonly remoteBaseUrl: string | null;
40
+ getLayout(): Promise<CanvasLayout>;
41
+ getNode(id: string): Promise<CanvasNodeState | undefined>;
42
+ addNode(input: AddNodeInput): Promise<string>;
43
+ addWebpageNode(input: AddWebpageNodeInput): Promise<Awaited<ReturnType<PmxCanvas['addWebpageNode']>>>;
44
+ refreshWebpageNode(id: string, url?: string): Promise<RefreshWebpageNodeResult>;
45
+ openMcpApp(input: OpenMcpAppInput): Promise<OpenMcpAppResult>;
46
+ addDiagram(input: AddDiagramInput): Promise<OpenMcpAppResult>;
47
+ addJsonRenderNode(input: AddJsonRenderNodeInput): Promise<AddJsonRenderNodeResult>;
48
+ addGraphNode(input: AddGraphNodeInput): Promise<AddGraphNodeResult>;
49
+ buildWebArtifact(input: WebArtifactInput): Promise<WebArtifactResult>;
50
+ updateNode(id: string, patch: UpdateNodePatch): Promise<void>;
51
+ removeNode(id: string): Promise<void>;
52
+ addEdge(input: AddEdgeInput): Promise<string>;
53
+ removeEdge(id: string): Promise<void>;
54
+ createGroup(input: CreateGroupInput): Promise<string>;
55
+ groupNodes(groupId: string, childIds: string[], options?: GroupNodesOptions): Promise<boolean>;
56
+ ungroupNodes(groupId: string): Promise<boolean>;
57
+ arrange(layout?: ArrangeLayout): Promise<void>;
58
+ focusNode(id: string, options?: {
59
+ noPan?: boolean;
60
+ }): Promise<FocusNodeResult>;
61
+ fitView(options?: FitViewOptions): Promise<FitViewResult>;
62
+ clear(): Promise<void>;
63
+ search(query: string): Promise<SearchResult>;
64
+ undo(): Promise<UndoRedoResult>;
65
+ redo(): Promise<UndoRedoResult>;
66
+ getHistory(): Promise<HistoryResult>;
67
+ setContextPins(nodeIds: string[], mode?: 'set' | 'add' | 'remove'): Promise<SetContextPinsResult>;
68
+ getPinnedNodeIds(): Promise<string[]>;
69
+ runBatch(operations: RunBatchInput): Promise<RunBatchResult>;
70
+ listSnapshots(): Promise<SnapshotList>;
71
+ saveSnapshot(name: string): Promise<CanvasSnapshot | null>;
72
+ restoreSnapshot(id: string): Promise<{
73
+ ok: boolean;
74
+ }>;
75
+ deleteSnapshot(id: string): Promise<DeleteSnapshotResult>;
76
+ diffSnapshot(idOrName: string): Promise<DiffSnapshotResult>;
77
+ getCodeGraph(): Promise<CodeGraphResult>;
78
+ validate(): Promise<ValidationResult>;
79
+ getAutomationWebViewStatus(): Promise<AutomationWebViewStatus>;
80
+ startAutomationWebView(options?: AutomationWebViewOptions): Promise<AutomationWebViewStatus>;
81
+ stopAutomationWebView(): Promise<boolean>;
82
+ evaluateAutomationWebView(expression: string): Promise<AutomationEvaluateResult>;
83
+ resizeAutomationWebView(width: number, height: number): Promise<AutomationWebViewStatus>;
84
+ screenshotAutomationWebView(options?: AutomationScreenshotOptions): Promise<Uint8Array>;
85
+ }
86
+ export declare function refreshCanvasAccess(access: CanvasAccess): Promise<CanvasAccess>;
87
+ export declare function createCanvasAccess(): Promise<CanvasAccess>;
88
+ export {};
@@ -96,6 +96,7 @@ export interface CanvasServerOptions {
96
96
  port?: number;
97
97
  workspaceRoot?: string;
98
98
  autoOpenBrowser?: boolean;
99
+ allowPortFallback?: boolean;
99
100
  }
100
101
  export declare function startCanvasServer(options?: CanvasServerOptions): string | null;
101
102
  export declare function stopCanvasServer(): void;
@@ -38,6 +38,7 @@ export interface WebArtifactCanvasBuildResult extends WebArtifactBuildOutput {
38
38
  openedInCanvas: boolean;
39
39
  nodeId?: string;
40
40
  url?: string;
41
+ completedAt: string;
41
42
  }
42
43
  export declare function resolveWorkspacePath(pathLike: string, cwd?: string): string;
43
44
  export declare function resolveWebArtifactScriptPath(kind: 'init' | 'bundle'): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmx-canvas",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Spatial canvas workbench for coding agents — infinite 2D canvas with agent-native CLI, MCP integration, nodes, edges, file watching, and snapshots",
5
5
  "type": "module",
6
6
  "main": "./src/server/index.ts",
@@ -115,12 +115,13 @@ else
115
115
  echo "✅ Using Vite $VITE_VERSION (Node 18 compatible)"
116
116
  fi
117
117
 
118
- # Detect OS and set sed syntax
119
- if [[ "$OSTYPE" == "darwin"* ]]; then
120
- SED_INPLACE="sed -i ''"
121
- else
122
- SED_INPLACE="sed -i"
123
- fi
118
+ function sed_in_place() {
119
+ if [[ "$OSTYPE" == "darwin"* ]]; then
120
+ sed -i '' "$@"
121
+ else
122
+ sed -i "$@"
123
+ fi
124
+ }
124
125
 
125
126
  declare -a PNPM_CMD
126
127
  configure_pnpm
@@ -158,8 +159,8 @@ fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
158
159
  "
159
160
 
160
161
  echo "🧹 Cleaning up Vite template..."
161
- $SED_INPLACE '/<link rel="icon".*/d' index.html
162
- $SED_INPLACE 's/<title>.*<\/title>/<title>'"$PROJECT_NAME"'<\/title>/' index.html
162
+ sed_in_place '/<link rel="icon".*/d' index.html
163
+ sed_in_place 's/<title>.*<\/title>/<title>'"$PROJECT_NAME"'<\/title>/' index.html
163
164
 
164
165
  echo "📦 Installing base dependencies..."
165
166
  run_pnpm_quiet install
@@ -1,4 +1,5 @@
1
1
  import type { CanvasNodeState } from '../types';
2
+ import { buildTraceDisplayModel } from './trace-model';
2
3
 
3
4
  const CATEGORY_COLORS: Record<string, string> = {
4
5
  mcp: 'var(--c-accent)',
@@ -20,12 +21,7 @@ const STATUS_COLORS: Record<string, string> = {
20
21
  };
21
22
 
22
23
  export function TraceNode({ node }: { node: CanvasNodeState }) {
23
- const toolName = (node.data.toolName as string) || 'unknown';
24
- const category = (node.data.category as string) || 'other';
25
- const status = (node.data.status as string) || 'running';
26
- const duration = (node.data.duration as string) || '';
27
- const resultSummary = (node.data.resultSummary as string) || '';
28
- const error = (node.data.error as string) || '';
24
+ const { toolName, category, status, duration, resultSummary, error } = buildTraceDisplayModel(node.data);
29
25
 
30
26
  const catColor = CATEGORY_COLORS[category] ?? CATEGORY_COLORS.other;
31
27
  const statusIcon = STATUS_ICONS[status] ?? '◌';
@@ -0,0 +1,19 @@
1
+ export interface TraceDisplayModel {
2
+ toolName: string;
3
+ category: string;
4
+ status: string;
5
+ duration: string;
6
+ resultSummary: string;
7
+ error: string;
8
+ }
9
+
10
+ export function buildTraceDisplayModel(data: Record<string, unknown>): TraceDisplayModel {
11
+ return {
12
+ toolName: (data.toolName as string) || (data.title as string) || 'unknown',
13
+ category: (data.category as string) || 'other',
14
+ status: (data.status as string) || 'running',
15
+ duration: (data.duration as string) || '',
16
+ resultSummary: (data.resultSummary as string) || (data.content as string) || '',
17
+ error: (data.error as string) || '',
18
+ };
19
+ }
@@ -313,7 +313,10 @@ export function commitViewport(next: ViewportState): void {
313
313
  void updateViewportFromClient(next);
314
314
  }
315
315
 
316
- export function applyServerCanvasLayout(layout: Pick<CanvasLayout, 'nodes' | 'edges'> & { viewport?: ViewportState }): void {
316
+ export function applyServerCanvasLayout(
317
+ layout: Pick<CanvasLayout, 'nodes' | 'edges'> & { viewport?: ViewportState },
318
+ options: { applyViewport?: boolean } = {},
319
+ ): void {
317
320
  const nextNodes = new Map<string, CanvasNodeState>();
318
321
  let nextMaxZ = 1;
319
322
  for (const node of layout.nodes) {
@@ -337,7 +340,7 @@ export function applyServerCanvasLayout(layout: Pick<CanvasLayout, 'nodes' | 'ed
337
340
  const nextContextPinnedNodeIds = filterNodeIdSet(contextPinnedNodeIds.value, nextNodes);
338
341
 
339
342
  batch(() => {
340
- if (layout.viewport) {
343
+ if (options.applyViewport === true && layout.viewport) {
341
344
  viewport.value = layout.viewport;
342
345
  }
343
346
  maxZ = nextMaxZ;
@@ -803,6 +803,7 @@ function handleCanvasLayoutUpdate(data: Record<string, unknown>): void {
803
803
  }
804
804
  | undefined;
805
805
  if (!layout?.nodes) return;
806
+ const shouldApplyViewport = !hasInitialServerLayout.value;
806
807
  hasInitialServerLayout.value = true;
807
808
 
808
809
  const serverNodes = layout.nodes
@@ -824,7 +825,7 @@ function handleCanvasLayoutUpdate(data: Record<string, unknown>): void {
824
825
  ...(nextViewport ? { viewport: nextViewport } : {}),
825
826
  nodes: serverNodes,
826
827
  edges: serverEdges,
827
- });
828
+ }, { applyViewport: shouldApplyViewport });
828
829
 
829
830
  syncAttentionFromSse({ event: 'canvas-layout-update', data });
830
831
  }