pmx-canvas 0.1.36 → 0.2.1
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 +447 -0
- package/Readme.md +2 -2
- package/dist/json-render/index.js +89 -334
- package/dist/types/mcp/canvas-access.d.ts +5 -171
- package/dist/types/server/ax-state-manager.d.ts +267 -0
- package/dist/types/server/ax-state.d.ts +3 -1
- package/dist/types/server/canvas-db.d.ts +13 -0
- package/dist/types/server/canvas-operations.d.ts +1 -12
- package/dist/types/server/canvas-state.d.ts +8 -23
- package/dist/types/server/index.d.ts +6 -24
- package/dist/types/server/operations/composites.d.ts +121 -0
- package/dist/types/server/operations/http.d.ts +7 -0
- package/dist/types/server/operations/index.d.ts +8 -0
- package/dist/types/server/operations/invoker.d.ts +13 -0
- package/dist/types/server/operations/mcp.d.ts +15 -0
- package/dist/types/server/operations/ops/annotation.d.ts +2 -0
- package/dist/types/server/operations/ops/app.d.ts +33 -0
- package/dist/types/server/operations/ops/ax-await.d.ts +2 -0
- package/dist/types/server/operations/ops/ax-shared.d.ts +31 -0
- package/dist/types/server/operations/ops/ax-state.d.ts +2 -0
- package/dist/types/server/operations/ops/ax-timeline.d.ts +2 -0
- package/dist/types/server/operations/ops/ax-work.d.ts +2 -0
- package/dist/types/server/operations/ops/batch.d.ts +19 -0
- package/dist/types/server/operations/ops/edges.d.ts +2 -0
- package/dist/types/server/operations/ops/groups.d.ts +2 -0
- package/dist/types/server/operations/ops/json-render.d.ts +31 -0
- package/dist/types/server/operations/ops/nodes.d.ts +62 -0
- package/dist/types/server/operations/ops/query.d.ts +2 -0
- package/dist/types/server/operations/ops/snapshots.d.ts +2 -0
- package/dist/types/server/operations/ops/validate.d.ts +2 -0
- package/dist/types/server/operations/ops/viewport.d.ts +2 -0
- package/dist/types/server/operations/ops/webview.d.ts +2 -0
- package/dist/types/server/operations/registry.d.ts +15 -0
- package/dist/types/server/operations/types.d.ts +116 -0
- package/dist/types/server/operations/webview-runner.d.ts +69 -0
- package/docs/RELEASE.md +5 -0
- package/docs/adr-001-bun-only-runtime.md +46 -0
- package/docs/api-stability.md +57 -0
- package/docs/ax-host-adapter-contract.md +19 -1
- package/docs/ax-state-contract.md +72 -0
- package/docs/http-api.md +4 -0
- package/docs/mcp.md +61 -12
- package/docs/plans/plan-005-operation-registry.md +84 -0
- package/docs/plans/plan-006-mcp-tool-consolidation.md +109 -0
- package/docs/plans/plan-007-ax-domain.md +99 -0
- package/docs/plans/plan-008-registry-finish.md +91 -0
- package/docs/tech-debt-assessment-2026-06.md +90 -0
- package/package.json +3 -3
- package/skills/pmx-canvas/SKILL.md +221 -193
- package/skills/pmx-canvas/evals/evals.json +3 -3
- package/skills/pmx-canvas/references/ax-html-control-surface.md +93 -0
- package/skills/pmx-canvas/references/codex-app-adapter.md +13 -14
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +26 -11
- package/src/cli/agent.ts +52 -31
- package/src/mcp/canvas-access.ts +30 -830
- package/src/mcp/server.ts +162 -2014
- package/src/server/ax-context.ts +8 -1
- package/src/server/ax-state-manager.ts +826 -0
- package/src/server/ax-state.ts +10 -2
- package/src/server/canvas-db.ts +35 -0
- package/src/server/canvas-operations.ts +2 -328
- package/src/server/canvas-schema.ts +2 -2
- package/src/server/canvas-state.ts +103 -465
- package/src/server/index.ts +54 -190
- package/src/server/operations/composites.ts +355 -0
- package/src/server/operations/http.ts +103 -0
- package/src/server/operations/index.ts +65 -0
- package/src/server/operations/invoker.ts +87 -0
- package/src/server/operations/mcp.ts +221 -0
- package/src/server/operations/ops/annotation.ts +60 -0
- package/src/server/operations/ops/app.ts +447 -0
- package/src/server/operations/ops/ax-await.ts +216 -0
- package/src/server/operations/ops/ax-shared.ts +38 -0
- package/src/server/operations/ops/ax-state.ts +249 -0
- package/src/server/operations/ops/ax-timeline.ts +381 -0
- package/src/server/operations/ops/ax-work.ts +635 -0
- package/src/server/operations/ops/batch.ts +365 -0
- package/src/server/operations/ops/edges.ts +166 -0
- package/src/server/operations/ops/groups.ts +176 -0
- package/src/server/operations/ops/json-render.ts +691 -0
- package/src/server/operations/ops/nodes.ts +1047 -0
- package/src/server/operations/ops/query.ts +281 -0
- package/src/server/operations/ops/snapshots.ts +366 -0
- package/src/server/operations/ops/validate.ts +37 -0
- package/src/server/operations/ops/viewport.ts +219 -0
- package/src/server/operations/ops/webview.ts +339 -0
- package/src/server/operations/registry.ts +79 -0
- package/src/server/operations/types.ts +150 -0
- package/src/server/operations/webview-runner.ts +77 -0
- package/src/server/server.ts +158 -2255
- package/src/server/web-artifacts.ts +6 -2
package/src/server/index.ts
CHANGED
|
@@ -31,7 +31,6 @@ import type {
|
|
|
31
31
|
PmxAxWorkItemStatus,
|
|
32
32
|
} from './ax-state.js';
|
|
33
33
|
import type { AxTimelineQuery } from './canvas-db.js';
|
|
34
|
-
import { findCanvasExtAppNodeId } from './ext-app-lookup.js';
|
|
35
34
|
import { onFileNodeChanged } from './file-watcher.js';
|
|
36
35
|
import { findOpenCanvasPosition, computeGroupBounds } from './placement.js';
|
|
37
36
|
import { searchNodes, buildSpatialContext } from './spatial-analysis.js';
|
|
@@ -40,27 +39,18 @@ import { recomputeCodeGraph, buildCodeGraphSummary, formatCodeGraph } from './co
|
|
|
40
39
|
import {
|
|
41
40
|
addCanvasNode,
|
|
42
41
|
addCanvasEdge,
|
|
43
|
-
appendCanvasJsonRenderStream,
|
|
44
|
-
createCanvasStreamingJsonRenderNode,
|
|
45
|
-
MARKDOWN_NODE_DEFAULT_SIZE,
|
|
46
|
-
MCP_APP_NODE_DEFAULT_SIZE,
|
|
47
|
-
IMAGE_NODE_DEFAULT_SIZE,
|
|
48
|
-
LEDGER_NODE_DEFAULT_SIZE,
|
|
49
42
|
applyCanvasNodeUpdates,
|
|
50
43
|
arrangeCanvasNodes,
|
|
51
44
|
clearCanvas,
|
|
52
45
|
createCanvasGraphNode,
|
|
53
46
|
createCanvasGroup,
|
|
54
47
|
createCanvasJsonRenderNode,
|
|
55
|
-
buildStructuredNodeUpdate,
|
|
56
48
|
fitCanvasView,
|
|
57
49
|
deleteCanvasSnapshot,
|
|
58
|
-
executeCanvasBatch,
|
|
59
50
|
gcCanvasSnapshots,
|
|
60
51
|
groupCanvasNodes,
|
|
61
52
|
listCanvasSnapshots,
|
|
62
53
|
refreshCanvasWebpageNode,
|
|
63
|
-
removeCanvasNode,
|
|
64
54
|
removeCanvasEdge,
|
|
65
55
|
resolveHtmlContent,
|
|
66
56
|
restoreCanvasSnapshot,
|
|
@@ -69,11 +59,19 @@ import {
|
|
|
69
59
|
syncCanvasRuntimeBackends,
|
|
70
60
|
setCanvasContextPins,
|
|
71
61
|
ungroupCanvasNodes,
|
|
72
|
-
validateCanvasNodePatch,
|
|
73
|
-
hasStructuredNodeUpdateFields,
|
|
74
|
-
hasTraceNodeDataFields,
|
|
75
|
-
mergeTraceNodeDataFields,
|
|
76
62
|
} from './canvas-operations.js';
|
|
63
|
+
import {
|
|
64
|
+
buildNodePatch,
|
|
65
|
+
createBasicCanvasNode,
|
|
66
|
+
removeNodeCore,
|
|
67
|
+
setGroupChildrenFromApi,
|
|
68
|
+
} from './operations/ops/nodes.js';
|
|
69
|
+
import { streamJsonRenderCore } from './operations/ops/json-render.js';
|
|
70
|
+
import {
|
|
71
|
+
executeOperation,
|
|
72
|
+
runCanvasBatchOperation,
|
|
73
|
+
type OpenMcpAppCoreResult,
|
|
74
|
+
} from './operations/index.js';
|
|
77
75
|
import { validateCanvasLayout } from './canvas-validation.js';
|
|
78
76
|
import { describeCanvasSchema, validateStructuredCanvasPayload } from './canvas-schema.js';
|
|
79
77
|
import { serializeCanvasNode, type SerializedCanvasNode } from './canvas-serialization.js';
|
|
@@ -86,13 +84,9 @@ import {
|
|
|
86
84
|
} from './web-artifacts.js';
|
|
87
85
|
import {
|
|
88
86
|
closeMcpAppSession,
|
|
89
|
-
openMcpApp as openExternalMcpApp,
|
|
90
87
|
type ExternalMcpTransportConfig,
|
|
91
88
|
} from './mcp-app-runtime.js';
|
|
92
89
|
import {
|
|
93
|
-
buildExcalidrawOpenMcpAppInput,
|
|
94
|
-
ensureExcalidrawCheckpointId,
|
|
95
|
-
isExcalidrawCreateView,
|
|
96
90
|
type DiagramPresetOpenInput,
|
|
97
91
|
} from './diagram-presets.js';
|
|
98
92
|
import {
|
|
@@ -259,29 +253,9 @@ export class PmxCanvas extends EventEmitter {
|
|
|
259
253
|
if (!groupNode) throw new Error(`Group node "${groupId}" was not created.`);
|
|
260
254
|
return toSdkNode(groupNode);
|
|
261
255
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
? MARKDOWN_NODE_DEFAULT_SIZE.width
|
|
266
|
-
: input.type === 'mcp-app'
|
|
267
|
-
? MCP_APP_NODE_DEFAULT_SIZE.width
|
|
268
|
-
: input.type === 'image'
|
|
269
|
-
? IMAGE_NODE_DEFAULT_SIZE.width
|
|
270
|
-
: input.type === 'ledger'
|
|
271
|
-
? LEDGER_NODE_DEFAULT_SIZE.width
|
|
272
|
-
: 360,
|
|
273
|
-
defaultHeight: input.type === 'markdown'
|
|
274
|
-
? MARKDOWN_NODE_DEFAULT_SIZE.height
|
|
275
|
-
: input.type === 'mcp-app'
|
|
276
|
-
? MCP_APP_NODE_DEFAULT_SIZE.height
|
|
277
|
-
: input.type === 'image'
|
|
278
|
-
? IMAGE_NODE_DEFAULT_SIZE.height
|
|
279
|
-
: input.type === 'ledger'
|
|
280
|
-
? LEDGER_NODE_DEFAULT_SIZE.height
|
|
281
|
-
: 200,
|
|
282
|
-
fileMode: 'path',
|
|
283
|
-
...(input.strictSize ? { strictSize: true } : {}),
|
|
284
|
-
});
|
|
256
|
+
// Thin wrapper over the shared operation core (plan-005); the SDK keeps
|
|
257
|
+
// fileMode 'path' as an explicit visible parameter instead of forked code.
|
|
258
|
+
const { node, needsCodeGraphRecompute } = createBasicCanvasNode(input, { fileMode: 'path' });
|
|
285
259
|
|
|
286
260
|
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
287
261
|
|
|
@@ -291,8 +265,6 @@ export class PmxCanvas extends EventEmitter {
|
|
|
291
265
|
});
|
|
292
266
|
}
|
|
293
267
|
|
|
294
|
-
const node = canvasState.getNode(id);
|
|
295
|
-
if (!node) throw new Error(`Node "${id}" was not created.`);
|
|
296
268
|
return toSdkNode(node);
|
|
297
269
|
}
|
|
298
270
|
|
|
@@ -339,58 +311,18 @@ export class PmxCanvas extends EventEmitter {
|
|
|
339
311
|
updateNode(id: string, patch: Partial<CanvasNodeState> & Record<string, unknown>): void {
|
|
340
312
|
const existing = canvasState.getNode(id);
|
|
341
313
|
if (!existing) return;
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (patch.pinned !== undefined) resolvedPatch.pinned = patch.pinned;
|
|
347
|
-
if (patch.dockPosition !== undefined) resolvedPatch.dockPosition = patch.dockPosition;
|
|
348
|
-
|
|
349
|
-
if (hasStructuredNodeUpdateFields(patch)) {
|
|
350
|
-
resolvedPatch.data = buildStructuredNodeUpdate(existing, patch).data;
|
|
351
|
-
} else if (
|
|
352
|
-
patch.data !== undefined ||
|
|
353
|
-
patch.title !== undefined ||
|
|
354
|
-
patch.content !== undefined ||
|
|
355
|
-
typeof patch.arrangeLocked === 'boolean' ||
|
|
356
|
-
typeof patch.strictSize === 'boolean' ||
|
|
357
|
-
(existing.type === 'trace' && hasTraceNodeDataFields(patch))
|
|
358
|
-
) {
|
|
359
|
-
const nextData = {
|
|
360
|
-
...existing.data,
|
|
361
|
-
...(patch.data && typeof patch.data === 'object' && !Array.isArray(patch.data) ? patch.data : {}),
|
|
362
|
-
...(typeof patch.title === 'string' ? { title: patch.title } : {}),
|
|
363
|
-
...(typeof patch.content === 'string' ? { content: patch.content } : {}),
|
|
364
|
-
...(typeof patch.arrangeLocked === 'boolean' ? { arrangeLocked: patch.arrangeLocked } : {}),
|
|
365
|
-
...(typeof patch.strictSize === 'boolean' ? { strictSize: patch.strictSize } : {}),
|
|
366
|
-
};
|
|
367
|
-
resolvedPatch.data = existing.type === 'trace'
|
|
368
|
-
? mergeTraceNodeDataFields(nextData, patch)
|
|
369
|
-
: nextData;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
const error = validateCanvasNodePatch({
|
|
373
|
-
...(resolvedPatch.position ? { position: resolvedPatch.position } : {}),
|
|
374
|
-
...(resolvedPatch.size ? { size: resolvedPatch.size } : {}),
|
|
375
|
-
});
|
|
376
|
-
if (error) {
|
|
377
|
-
throw new Error(error);
|
|
378
|
-
}
|
|
314
|
+
// Thin wrapper over the shared patch core (plan-005): the SDK now carries
|
|
315
|
+
// the same superset semantics as HTTP/MCP (webpage titleSource/url, html
|
|
316
|
+
// top-level fields, axCapabilities merge, group children).
|
|
317
|
+
const { patch: resolvedPatch, groupChildIds } = buildNodePatch(existing, patch);
|
|
379
318
|
canvasState.updateNode(id, resolvedPatch);
|
|
319
|
+
if (groupChildIds !== undefined) setGroupChildrenFromApi(id, groupChildIds);
|
|
380
320
|
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
381
321
|
}
|
|
382
322
|
|
|
323
|
+
/** Remove a node. Missing id throws (plan-005 unifies this across surfaces). */
|
|
383
324
|
removeNode(id: string): void {
|
|
384
|
-
const
|
|
385
|
-
const appSessionId =
|
|
386
|
-
existing?.type === 'mcp-app' && typeof existing.data.appSessionId === 'string'
|
|
387
|
-
? existing.data.appSessionId
|
|
388
|
-
: null;
|
|
389
|
-
if (appSessionId) {
|
|
390
|
-
closeMcpAppSession(appSessionId);
|
|
391
|
-
}
|
|
392
|
-
const { removed, needsCodeGraphRecompute } = removeCanvasNode(id);
|
|
393
|
-
if (!removed) return;
|
|
325
|
+
const { needsCodeGraphRecompute } = removeNodeCore(id);
|
|
394
326
|
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
395
327
|
|
|
396
328
|
if (needsCodeGraphRecompute) {
|
|
@@ -930,13 +862,6 @@ export class PmxCanvas extends EventEmitter {
|
|
|
930
862
|
return validateCanvasLayout(canvasState.getLayout());
|
|
931
863
|
}
|
|
932
864
|
|
|
933
|
-
private findCanvasExtAppNodeId(toolCallId: string): string | null {
|
|
934
|
-
return findCanvasExtAppNodeId(toolCallId, {
|
|
935
|
-
getNode: (id) => canvasState.getNode(id),
|
|
936
|
-
listNodes: () => canvasState.getLayout().nodes,
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
|
|
940
865
|
describeSchema() {
|
|
941
866
|
return describeCanvasSchema();
|
|
942
867
|
}
|
|
@@ -950,14 +875,22 @@ export class PmxCanvas extends EventEmitter {
|
|
|
950
875
|
}
|
|
951
876
|
|
|
952
877
|
async runBatch(operations: Array<{ op: string; assign?: string; args?: Record<string, unknown> }>) {
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
878
|
+
// Delegates to the canvas.batch registry meta-op (plan-008 Wave 2). The op
|
|
879
|
+
// emits the single final canvas-layout-update itself (via the registry
|
|
880
|
+
// emitter, which server.ts wires to emitPrimaryWorkbenchEvent) — do NOT
|
|
881
|
+
// emit again here or the frame would fire twice.
|
|
882
|
+
return await runCanvasBatchOperation(operations);
|
|
956
883
|
}
|
|
957
884
|
|
|
958
885
|
async buildWebArtifact(
|
|
959
|
-
input: WebArtifactBuildInput & { openInCanvas?: boolean },
|
|
886
|
+
input: WebArtifactBuildInput & { openInCanvas?: boolean; includeLogs?: boolean },
|
|
960
887
|
): Promise<WebArtifactCanvasBuildResult> {
|
|
888
|
+
// The registry's webartifact.build op wraps buildWebArtifactOnCanvas and
|
|
889
|
+
// returns a wire ENVELOPE (path/bytes/…); the SDK's documented return is the
|
|
890
|
+
// full WebArtifactCanvasBuildResult, so the SDK calls the build runtime
|
|
891
|
+
// directly here (the op core is the same buildWebArtifactOnCanvas; the node
|
|
892
|
+
// creation emits its own canvas-layout-update). The op and the SDK share the
|
|
893
|
+
// single build runtime — no behavior divergence.
|
|
961
894
|
return buildWebArtifactOnCanvas(input);
|
|
962
895
|
}
|
|
963
896
|
|
|
@@ -973,75 +906,21 @@ export class PmxCanvas extends EventEmitter {
|
|
|
973
906
|
width?: number;
|
|
974
907
|
height?: number;
|
|
975
908
|
timeoutMs?: number;
|
|
976
|
-
}): Promise<
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
const opened = await openExternalMcpApp({
|
|
986
|
-
transport: input.transport,
|
|
987
|
-
toolName: input.toolName,
|
|
988
|
-
...(input.toolArguments ? { toolArguments: input.toolArguments } : {}),
|
|
989
|
-
...(input.serverName ? { serverName: input.serverName } : {}),
|
|
990
|
-
...(typeof input.timeoutMs === 'number' ? { timeoutMs: input.timeoutMs } : {}),
|
|
991
|
-
});
|
|
992
|
-
const toolCallId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
993
|
-
const previousSessionId = targetNode?.data.appSessionId;
|
|
994
|
-
if (typeof previousSessionId === 'string' && previousSessionId.trim().length > 0) {
|
|
995
|
-
closeMcpAppSession(previousSessionId);
|
|
996
|
-
}
|
|
997
|
-
const nodeIdSeed = input.nodeId ?? `ext-app-${toolCallId}`;
|
|
998
|
-
const toolResult = isExcalidrawCreateView(opened.serverName, opened.toolName)
|
|
999
|
-
? ensureExcalidrawCheckpointId(opened.toolResult, nodeIdSeed)
|
|
1000
|
-
: opened.toolResult;
|
|
1001
|
-
emitPrimaryWorkbenchEvent('ext-app-open', {
|
|
1002
|
-
toolCallId,
|
|
1003
|
-
nodeId: nodeIdSeed,
|
|
1004
|
-
title: input.title ?? opened.tool.title ?? opened.tool.name,
|
|
1005
|
-
html: opened.html,
|
|
1006
|
-
toolInput: opened.toolInput,
|
|
1007
|
-
serverName: opened.serverName,
|
|
1008
|
-
toolName: opened.toolName,
|
|
1009
|
-
appSessionId: opened.sessionId,
|
|
1010
|
-
transportConfig: input.transport,
|
|
1011
|
-
resourceUri: opened.resourceUri,
|
|
1012
|
-
toolDefinition: opened.tool,
|
|
1013
|
-
sessionStatus: 'ready',
|
|
1014
|
-
sessionError: null,
|
|
1015
|
-
...(opened.resourceMeta ? { resourceMeta: opened.resourceMeta } : {}),
|
|
1016
|
-
...(typeof input.x === 'number' ? { x: input.x } : {}),
|
|
1017
|
-
...(typeof input.y === 'number' ? { y: input.y } : {}),
|
|
1018
|
-
...(typeof input.width === 'number' ? { width: input.width } : {}),
|
|
1019
|
-
...(typeof input.height === 'number' ? { height: input.height } : {}),
|
|
1020
|
-
});
|
|
1021
|
-
emitPrimaryWorkbenchEvent('ext-app-result', {
|
|
1022
|
-
toolCallId,
|
|
1023
|
-
nodeId: nodeIdSeed,
|
|
1024
|
-
serverName: opened.serverName,
|
|
1025
|
-
toolName: opened.toolName,
|
|
1026
|
-
success: toolResult.isError !== true,
|
|
1027
|
-
result: toolResult,
|
|
1028
|
-
});
|
|
1029
|
-
const nodeId = input.nodeId ?? this.findCanvasExtAppNodeId(toolCallId);
|
|
1030
|
-
return {
|
|
1031
|
-
ok: true,
|
|
1032
|
-
...(nodeId ? { id: nodeId } : {}),
|
|
1033
|
-
nodeId,
|
|
1034
|
-
toolCallId,
|
|
1035
|
-
sessionId: opened.sessionId,
|
|
1036
|
-
resourceUri: opened.resourceUri,
|
|
1037
|
-
};
|
|
909
|
+
}): Promise<OpenMcpAppCoreResult> {
|
|
910
|
+
// Delegate to the mcpapp.open registry op (plan-008 Wave 4). The op handler
|
|
911
|
+
// is the relocated legacy body (toolCallId, openExternalMcpApp, prior-session
|
|
912
|
+
// close, ext-app-open + ext-app-result via ctx.emit → the registry emitter
|
|
913
|
+
// wired to emitPrimaryWorkbenchEvent). mutates:false, so the registry adds no
|
|
914
|
+
// canvas-layout-update; the two ext-app-* frames fire exactly once.
|
|
915
|
+
return await executeOperation('mcpapp.open', input) as OpenMcpAppCoreResult;
|
|
1038
916
|
}
|
|
1039
917
|
|
|
1040
918
|
async addDiagram(
|
|
1041
919
|
input: DiagramPresetOpenInput,
|
|
1042
|
-
): Promise<
|
|
1043
|
-
|
|
1044
|
-
|
|
920
|
+
): Promise<OpenMcpAppCoreResult> {
|
|
921
|
+
// Delegate to the diagram.open registry op, which builds the Excalidraw
|
|
922
|
+
// OpenMcpApp input and dispatches to the shared open core (one ext-app-* pair).
|
|
923
|
+
return await executeOperation('diagram.open', input) as OpenMcpAppCoreResult;
|
|
1045
924
|
}
|
|
1046
925
|
|
|
1047
926
|
addJsonRenderNode(
|
|
@@ -1077,32 +956,17 @@ export class PmxCanvas extends EventEmitter {
|
|
|
1077
956
|
elementCount: number;
|
|
1078
957
|
streamStatus: 'open' | 'closed';
|
|
1079
958
|
} {
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
...(input.width !== undefined ? { width: input.width } : {}),
|
|
1088
|
-
...(input.height !== undefined ? { height: input.height } : {}),
|
|
1089
|
-
...(input.strictSize ? { strictSize: true } : {}),
|
|
1090
|
-
});
|
|
1091
|
-
nodeId = created.id;
|
|
1092
|
-
url = created.url;
|
|
1093
|
-
} else {
|
|
1094
|
-
url = String(canvasState.getNode(nodeId)?.data.url ?? '');
|
|
1095
|
-
}
|
|
1096
|
-
const result = appendCanvasJsonRenderStream(
|
|
1097
|
-
nodeId,
|
|
1098
|
-
Array.isArray(input.patches) ? input.patches : [],
|
|
1099
|
-
input.done === true,
|
|
1100
|
-
);
|
|
1101
|
-
if (!result.ok) throw new Error(result.error);
|
|
959
|
+
// Thin wrapper over the shared create-or-append core (plan-005). The op
|
|
960
|
+
// handler and this SDK method now share one implementation; the SDK emits
|
|
961
|
+
// the layout update itself (it does not flow through the registry's
|
|
962
|
+
// `mutates` path). `streamJsonRenderCore` throws OperationError (an Error
|
|
963
|
+
// subclass with the same message) on a bad append target. The core's
|
|
964
|
+
// result carries an extra `ok: true`; the SDK's wire shape omits it.
|
|
965
|
+
const result = streamJsonRenderCore(input);
|
|
1102
966
|
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
1103
967
|
return {
|
|
1104
|
-
id:
|
|
1105
|
-
url,
|
|
968
|
+
id: result.id,
|
|
969
|
+
url: result.url,
|
|
1106
970
|
applied: result.applied,
|
|
1107
971
|
skipped: result.skipped,
|
|
1108
972
|
specVersion: result.specVersion,
|