pmx-canvas 0.1.35 → 0.2.0
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 +461 -0
- package/Readme.md +14 -2
- package/dist/canvas/index.js +82 -41
- package/dist/json-render/index.js +89 -334
- package/dist/types/client/nodes/ExtAppFrame.d.ts +2 -0
- package/dist/types/mcp/canvas-access.d.ts +12 -159
- package/dist/types/server/ax-context.d.ts +1 -1
- package/dist/types/server/ax-state-manager.d.ts +256 -0
- package/dist/types/server/ax-state.d.ts +29 -1
- package/dist/types/server/ax-wait.d.ts +23 -0
- package/dist/types/server/canvas-operations.d.ts +1 -12
- package/dist/types/server/canvas-state.d.ts +46 -14
- package/dist/types/server/html-surface.d.ts +7 -0
- package/dist/types/server/index.d.ts +66 -26
- 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 +65 -0
- package/docs/ax-state-contract.md +72 -0
- package/docs/http-api.md +34 -2
- package/docs/mcp.md +64 -11
- 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/screenshot.png +0 -0
- package/docs/tech-debt-assessment-2026-06.md +90 -0
- package/package.json +3 -3
- package/skills/pmx-canvas/SKILL.md +233 -185
- package/skills/pmx-canvas/evals/evals.json +3 -3
- package/skills/pmx-canvas/references/codex-app-adapter.md +24 -11
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +31 -1
- package/src/cli/agent.ts +52 -31
- package/src/client/nodes/ExtAppFrame.tsx +73 -5
- package/src/client/nodes/HtmlNode.tsx +12 -3
- package/src/client/nodes/McpAppNode.tsx +12 -3
- package/src/json-render/renderer/index.tsx +3 -0
- package/src/mcp/canvas-access.ts +43 -774
- package/src/mcp/server.ts +190 -2001
- package/src/server/ax-context.ts +7 -1
- package/src/server/ax-state-manager.ts +808 -0
- package/src/server/ax-state.ts +89 -2
- package/src/server/ax-wait.ts +56 -0
- package/src/server/canvas-operations.ts +2 -328
- package/src/server/canvas-schema.ts +2 -2
- package/src/server/canvas-state.ts +140 -382
- package/src/server/html-surface.ts +49 -11
- package/src/server/index.ts +136 -192
- 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 +253 -2170
- package/src/server/web-artifacts.ts +6 -2
package/src/mcp/canvas-access.ts
CHANGED
|
@@ -6,95 +6,48 @@ import {
|
|
|
6
6
|
type CanvasEdge,
|
|
7
7
|
type CanvasLayout,
|
|
8
8
|
type CanvasNodeState,
|
|
9
|
-
type CanvasSnapshot,
|
|
10
9
|
type PmxCanvas,
|
|
11
10
|
} from '../server/index.js';
|
|
12
11
|
import type { PmxAxSource } from '../server/ax-state.js';
|
|
12
|
+
import {
|
|
13
|
+
HttpOperationInvoker,
|
|
14
|
+
LocalOperationInvoker,
|
|
15
|
+
type OperationInvoker,
|
|
16
|
+
} from '../server/operations/index.js';
|
|
13
17
|
|
|
14
|
-
type AddNodeInput = Parameters<PmxCanvas['addNode']>[0];
|
|
15
|
-
type AddWebpageNodeInput = Parameters<PmxCanvas['addWebpageNode']>[0];
|
|
16
18
|
type RefreshWebpageNodeResult = Awaited<ReturnType<PmxCanvas['refreshWebpageNode']>>;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type StreamJsonRenderNodeInput = Parameters<PmxCanvas['streamJsonRenderNode']>[0];
|
|
23
|
-
type StreamJsonRenderNodeResult = ReturnType<PmxCanvas['streamJsonRenderNode']>;
|
|
19
|
+
// openMcpApp / addDiagram / buildWebArtifact CanvasAccess methods + their type
|
|
20
|
+
// aliases removed with the standalone MCP tools (plan-008 Wave 4): those tools
|
|
21
|
+
// migrated to the operation registry (mcpapp.open / diagram.open /
|
|
22
|
+
// webartifact.build) and the composite/registry tools dispatch via the invoker,
|
|
23
|
+
// not CanvasAccess. The public SDK PmxCanvas methods are unchanged.
|
|
24
24
|
type AddHtmlNodeInput = Parameters<PmxCanvas['addHtmlNode']>[0];
|
|
25
25
|
type AddHtmlPrimitiveInput = Parameters<PmxCanvas['addHtmlPrimitive']>[0];
|
|
26
26
|
type AddHtmlPrimitiveResult = ReturnType<PmxCanvas['addHtmlPrimitive']>;
|
|
27
|
-
type AddGraphNodeInput = Parameters<PmxCanvas['addGraphNode']>[0];
|
|
28
|
-
type AddGraphNodeResult = ReturnType<PmxCanvas['addGraphNode']>;
|
|
29
|
-
type UpdateNodePatch = Parameters<PmxCanvas['updateNode']>[1];
|
|
30
|
-
type AddEdgeInput = Parameters<PmxCanvas['addEdge']>[0];
|
|
31
|
-
type CreateGroupInput = Parameters<PmxCanvas['createGroup']>[0];
|
|
32
|
-
type GroupNodesOptions = Parameters<PmxCanvas['groupNodes']>[2];
|
|
33
|
-
type ArrangeLayout = Parameters<PmxCanvas['arrange']>[0];
|
|
34
|
-
type FocusNodeResult = ReturnType<PmxCanvas['focusNode']>;
|
|
35
|
-
type FitViewOptions = Parameters<PmxCanvas['fitView']>[0];
|
|
36
|
-
type FitViewResult = ReturnType<PmxCanvas['fitView']>;
|
|
37
27
|
type AxStateResult = ReturnType<PmxCanvas['getAxState']>;
|
|
38
28
|
type AxContextResult = ReturnType<PmxCanvas['getAxContext']>;
|
|
39
|
-
type SetAxFocusResult = ReturnType<PmxCanvas['setAxFocus']>;
|
|
40
|
-
type RecordAxEventInput = Parameters<PmxCanvas['recordAxEvent']>[0];
|
|
41
|
-
type RecordAxEventResult = ReturnType<PmxCanvas['recordAxEvent']>;
|
|
42
|
-
type SendSteeringResult = ReturnType<PmxCanvas['sendSteering']>;
|
|
43
29
|
type SubmitAxInteractionInput = Parameters<PmxCanvas['submitAxInteraction']>[0];
|
|
44
30
|
type SubmitAxInteractionResult = ReturnType<PmxCanvas['submitAxInteraction']>;
|
|
45
31
|
type GetPendingSteeringResult = ReturnType<PmxCanvas['getPendingSteering']>;
|
|
46
32
|
type ListElicitationsResult = ReturnType<PmxCanvas['listElicitations']>;
|
|
47
|
-
type RequestElicitationInput = Parameters<PmxCanvas['requestElicitation']>[0];
|
|
48
|
-
type RequestElicitationResult = ReturnType<PmxCanvas['requestElicitation']>;
|
|
49
|
-
type RespondElicitationResult = ReturnType<PmxCanvas['respondElicitation']>;
|
|
50
33
|
type ListModeRequestsResult = ReturnType<PmxCanvas['listModeRequests']>;
|
|
51
|
-
type
|
|
52
|
-
type
|
|
53
|
-
type ResolveModeRequestResult = ReturnType<PmxCanvas['resolveModeRequest']>;
|
|
54
|
-
type GetCommandRegistryResult = ReturnType<PmxCanvas['getCommandRegistry']>;
|
|
55
|
-
type InvokeCommandResult = ReturnType<PmxCanvas['invokeCommand']>;
|
|
34
|
+
type IngestActivityInput = Parameters<PmxCanvas['ingestActivity']>[0];
|
|
35
|
+
type IngestActivityResult = ReturnType<PmxCanvas['ingestActivity']>;
|
|
56
36
|
type GetPolicyResult = ReturnType<PmxCanvas['getPolicy']>;
|
|
57
|
-
type SetPolicyInput = Parameters<PmxCanvas['setPolicy']>[0];
|
|
58
|
-
type SetPolicyResult = ReturnType<PmxCanvas['setPolicy']>;
|
|
59
37
|
type GetAxTimelineQuery = Parameters<PmxCanvas['getAxTimeline']>[0];
|
|
60
38
|
type GetAxTimelineResult = ReturnType<PmxCanvas['getAxTimeline']>;
|
|
61
|
-
type AddWorkItemInput = Parameters<PmxCanvas['addWorkItem']>[0];
|
|
62
|
-
type AddWorkItemResult = ReturnType<PmxCanvas['addWorkItem']>;
|
|
63
|
-
type UpdateWorkItemPatch = Parameters<PmxCanvas['updateWorkItem']>[1];
|
|
64
|
-
type UpdateWorkItemResult = ReturnType<PmxCanvas['updateWorkItem']>;
|
|
65
39
|
type ListWorkItemsResult = ReturnType<PmxCanvas['listWorkItems']>;
|
|
66
|
-
type RequestApprovalInput = Parameters<PmxCanvas['requestApproval']>[0];
|
|
67
|
-
type RequestApprovalResult = ReturnType<PmxCanvas['requestApproval']>;
|
|
68
|
-
type ResolveApprovalResult = ReturnType<PmxCanvas['resolveApproval']>;
|
|
69
40
|
type ListApprovalGatesResult = ReturnType<PmxCanvas['listApprovalGates']>;
|
|
70
|
-
type AddEvidenceInput = Parameters<PmxCanvas['addEvidence']>[0];
|
|
71
|
-
type AddEvidenceResult = ReturnType<PmxCanvas['addEvidence']>;
|
|
72
|
-
type AddReviewAnnotationInput = Parameters<PmxCanvas['addReviewAnnotation']>[0];
|
|
73
|
-
type AddReviewAnnotationResult = ReturnType<PmxCanvas['addReviewAnnotation']>;
|
|
74
|
-
type UpdateReviewAnnotationPatch = Parameters<PmxCanvas['updateReviewAnnotation']>[1];
|
|
75
|
-
type UpdateReviewAnnotationResult = ReturnType<PmxCanvas['updateReviewAnnotation']>;
|
|
76
41
|
type ListReviewAnnotationsResult = ReturnType<PmxCanvas['listReviewAnnotations']>;
|
|
77
|
-
type GetHostCapabilityResult = ReturnType<PmxCanvas['getHostCapability']>;
|
|
78
|
-
type ReportHostCapabilityResult = ReturnType<PmxCanvas['reportHostCapability']>;
|
|
79
|
-
type SearchResult = ReturnType<PmxCanvas['search']>;
|
|
80
|
-
type UndoRedoResult = Awaited<ReturnType<PmxCanvas['undo']>>;
|
|
81
42
|
type HistoryResult = ReturnType<PmxCanvas['getHistory']>;
|
|
82
|
-
type SetContextPinsResult = ReturnType<PmxCanvas['setContextPins']>;
|
|
83
43
|
type RunBatchInput = Parameters<PmxCanvas['runBatch']>[0];
|
|
84
44
|
type RunBatchResult = Awaited<ReturnType<PmxCanvas['runBatch']>>;
|
|
85
|
-
type SnapshotListOptions = Parameters<PmxCanvas['listSnapshots']>[0];
|
|
86
|
-
type SnapshotList = ReturnType<PmxCanvas['listSnapshots']>;
|
|
87
|
-
type DeleteSnapshotResult = ReturnType<PmxCanvas['deleteSnapshot']>;
|
|
88
|
-
type GcSnapshotsOptions = Parameters<PmxCanvas['gcSnapshots']>[0];
|
|
89
|
-
type GcSnapshotsResult = ReturnType<PmxCanvas['gcSnapshots']>;
|
|
90
|
-
type DiffSnapshotResult = ReturnType<PmxCanvas['diffSnapshot']>;
|
|
91
45
|
type CodeGraphResult = ReturnType<PmxCanvas['getCodeGraph']>;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
type AutomationWebViewStatus = Awaited<ReturnType<PmxCanvas['
|
|
97
|
-
type AutomationEvaluateResult = Awaited<ReturnType<PmxCanvas['evaluateAutomationWebView']>>;
|
|
46
|
+
// canvas_screenshot (the only webview tool still hand-written) needs the status
|
|
47
|
+
// + screenshot accessors; the other four webview methods (start/stop/evaluate/
|
|
48
|
+
// resize) migrated to the operation registry (plan-008 Wave 3) and were removed
|
|
49
|
+
// from CanvasAccess.
|
|
50
|
+
type AutomationWebViewStatus = Awaited<ReturnType<PmxCanvas['getAutomationWebViewStatus']>>;
|
|
98
51
|
type AutomationScreenshotOptions = Parameters<PmxCanvas['screenshotAutomationWebView']>[0];
|
|
99
52
|
|
|
100
53
|
interface HealthResponse {
|
|
@@ -107,120 +60,41 @@ interface NodeResponse {
|
|
|
107
60
|
node?: { id?: string };
|
|
108
61
|
}
|
|
109
62
|
|
|
110
|
-
interface JsonRenderNodeResponse extends NodeResponse {
|
|
111
|
-
url: string;
|
|
112
|
-
spec: AddJsonRenderNodeResult['spec'];
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
interface GraphNodeResponse extends NodeResponse {
|
|
116
|
-
url: string;
|
|
117
|
-
spec: AddGraphNodeResult['spec'];
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
interface SearchResponse {
|
|
121
|
-
results?: SearchResult;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
interface SnapshotSaveResponse {
|
|
125
|
-
snapshot?: CanvasSnapshot;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
interface WebViewEnvelope {
|
|
129
|
-
webview?: AutomationWebViewStatus;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
interface WebViewStopEnvelope extends WebViewEnvelope {
|
|
133
|
-
stopped?: boolean;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
interface WebViewEvaluateEnvelope {
|
|
137
|
-
value?: AutomationEvaluateResult;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
63
|
export interface CanvasAccess {
|
|
141
64
|
readonly port: number;
|
|
142
65
|
readonly remoteBaseUrl: string | null;
|
|
66
|
+
/** Operation-registry invoker (plan-005): local in-process or HTTP, matching the access mode. */
|
|
67
|
+
invoker(): OperationInvoker;
|
|
143
68
|
getLayout(): Promise<CanvasLayout>;
|
|
144
69
|
getNode(id: string): Promise<CanvasNodeState | undefined>;
|
|
145
|
-
addNode(input: AddNodeInput): Promise<string>;
|
|
146
|
-
addWebpageNode(input: AddWebpageNodeInput): Promise<Awaited<ReturnType<PmxCanvas['addWebpageNode']>>>;
|
|
147
70
|
refreshWebpageNode(id: string, url?: string): Promise<RefreshWebpageNodeResult>;
|
|
148
|
-
openMcpApp(input: OpenMcpAppInput): Promise<OpenMcpAppResult>;
|
|
149
|
-
addDiagram(input: AddDiagramInput): Promise<OpenMcpAppResult>;
|
|
150
|
-
addJsonRenderNode(input: AddJsonRenderNodeInput): Promise<AddJsonRenderNodeResult>;
|
|
151
|
-
streamJsonRenderNode(input: StreamJsonRenderNodeInput): Promise<StreamJsonRenderNodeResult>;
|
|
152
71
|
addHtmlNode(input: AddHtmlNodeInput): Promise<string>;
|
|
153
72
|
addHtmlPrimitive(input: AddHtmlPrimitiveInput): Promise<AddHtmlPrimitiveResult>;
|
|
154
|
-
addGraphNode(input: AddGraphNodeInput): Promise<AddGraphNodeResult>;
|
|
155
|
-
buildWebArtifact(input: WebArtifactInput): Promise<WebArtifactResult>;
|
|
156
|
-
updateNode(id: string, patch: UpdateNodePatch): Promise<void>;
|
|
157
|
-
removeNode(id: string): Promise<void>;
|
|
158
|
-
removeAnnotation(id: string): Promise<boolean>;
|
|
159
|
-
addEdge(input: AddEdgeInput): Promise<string>;
|
|
160
|
-
removeEdge(id: string): Promise<void>;
|
|
161
|
-
createGroup(input: CreateGroupInput): Promise<string>;
|
|
162
|
-
groupNodes(groupId: string, childIds: string[], options?: GroupNodesOptions): Promise<boolean>;
|
|
163
|
-
ungroupNodes(groupId: string): Promise<boolean>;
|
|
164
|
-
arrange(layout?: ArrangeLayout): Promise<void>;
|
|
165
|
-
focusNode(id: string, options?: { noPan?: boolean }): Promise<FocusNodeResult>;
|
|
166
|
-
fitView(options?: FitViewOptions): Promise<FitViewResult>;
|
|
167
73
|
getAxState(): Promise<AxStateResult>;
|
|
168
|
-
getAxContext(): Promise<AxContextResult>;
|
|
169
|
-
setAxFocus(nodeIds: string[], options?: { source?: PmxAxSource }): Promise<SetAxFocusResult>;
|
|
170
|
-
recordAxEvent(input: RecordAxEventInput, options?: { source?: PmxAxSource }): Promise<RecordAxEventResult>;
|
|
171
|
-
sendSteering(message: string, options?: { source?: PmxAxSource }): Promise<SendSteeringResult>;
|
|
74
|
+
getAxContext(options?: { consumer?: string }): Promise<AxContextResult>;
|
|
172
75
|
getAxTimeline(query?: GetAxTimelineQuery): Promise<GetAxTimelineResult>;
|
|
173
|
-
addWorkItem(input: AddWorkItemInput, options?: { source?: PmxAxSource }): Promise<AddWorkItemResult>;
|
|
174
|
-
updateWorkItem(id: string, patch: UpdateWorkItemPatch, options?: { source?: PmxAxSource }): Promise<UpdateWorkItemResult>;
|
|
175
76
|
listWorkItems(): Promise<ListWorkItemsResult>;
|
|
176
|
-
requestApproval(input: RequestApprovalInput, options?: { source?: PmxAxSource }): Promise<RequestApprovalResult>;
|
|
177
|
-
resolveApproval(id: string, decision: 'approved' | 'rejected', options?: { resolution?: string; source?: PmxAxSource }): Promise<ResolveApprovalResult>;
|
|
178
77
|
listApprovalGates(): Promise<ListApprovalGatesResult>;
|
|
179
|
-
addEvidence(input: AddEvidenceInput, options?: { source?: PmxAxSource }): Promise<AddEvidenceResult>;
|
|
180
|
-
addReviewAnnotation(input: AddReviewAnnotationInput, options?: { source?: PmxAxSource }): Promise<AddReviewAnnotationResult>;
|
|
181
|
-
updateReviewAnnotation(id: string, patch: UpdateReviewAnnotationPatch, options?: { source?: PmxAxSource }): Promise<UpdateReviewAnnotationResult>;
|
|
182
78
|
listReviewAnnotations(): Promise<ListReviewAnnotationsResult>;
|
|
183
|
-
getHostCapability(): Promise<GetHostCapabilityResult>;
|
|
184
|
-
reportHostCapability(input: unknown, options?: { source?: PmxAxSource }): Promise<ReportHostCapabilityResult>;
|
|
185
79
|
submitAxInteraction(input: SubmitAxInteractionInput, options?: { source?: PmxAxSource }): Promise<SubmitAxInteractionResult>;
|
|
186
80
|
getPendingSteering(options?: { consumer?: string; limit?: number }): Promise<GetPendingSteeringResult>;
|
|
187
|
-
markSteeringDelivered(id: string): Promise<boolean>;
|
|
188
81
|
listElicitations(): Promise<ListElicitationsResult>;
|
|
189
|
-
requestElicitation(input: RequestElicitationInput, options?: { source?: PmxAxSource }): Promise<RequestElicitationResult>;
|
|
190
|
-
respondElicitation(id: string, response: Record<string, unknown>, options?: { source?: PmxAxSource }): Promise<RespondElicitationResult>;
|
|
191
82
|
listModeRequests(): Promise<ListModeRequestsResult>;
|
|
192
|
-
|
|
193
|
-
resolveModeRequest(id: string, decision: 'approved' | 'rejected', options?: { resolution?: string; source?: PmxAxSource }): Promise<ResolveModeRequestResult>;
|
|
194
|
-
getCommandRegistry(): Promise<GetCommandRegistryResult>;
|
|
195
|
-
invokeCommand(name: string, args?: Record<string, unknown> | null, options?: { source?: PmxAxSource }): Promise<InvokeCommandResult>;
|
|
83
|
+
ingestActivity(input: IngestActivityInput, options?: { source?: PmxAxSource }): Promise<IngestActivityResult>;
|
|
196
84
|
getPolicy(): Promise<GetPolicyResult>;
|
|
197
|
-
setPolicy(patch: SetPolicyInput, options?: { source?: PmxAxSource }): Promise<SetPolicyResult>;
|
|
198
|
-
clear(): Promise<void>;
|
|
199
|
-
search(query: string): Promise<SearchResult>;
|
|
200
|
-
undo(): Promise<UndoRedoResult>;
|
|
201
|
-
redo(): Promise<UndoRedoResult>;
|
|
202
85
|
getHistory(): Promise<HistoryResult>;
|
|
203
|
-
setContextPins(nodeIds: string[], mode?: 'set' | 'add' | 'remove'): Promise<SetContextPinsResult>;
|
|
204
86
|
getPinnedNodeIds(): Promise<string[]>;
|
|
205
87
|
runBatch(operations: RunBatchInput): Promise<RunBatchResult>;
|
|
206
|
-
listSnapshots(options?: SnapshotListOptions): Promise<SnapshotList>;
|
|
207
|
-
saveSnapshot(name: string): Promise<CanvasSnapshot | null>;
|
|
208
|
-
restoreSnapshot(id: string): Promise<{ ok: boolean }>;
|
|
209
|
-
deleteSnapshot(id: string): Promise<DeleteSnapshotResult>;
|
|
210
|
-
gcSnapshots(options?: GcSnapshotsOptions): Promise<GcSnapshotsResult>;
|
|
211
|
-
diffSnapshot(idOrName: string): Promise<DiffSnapshotResult>;
|
|
212
88
|
getCodeGraph(): Promise<CodeGraphResult>;
|
|
213
|
-
|
|
89
|
+
// canvas_screenshot (still hand-written — binary payload) is the only webview
|
|
90
|
+
// tool left on CanvasAccess; it needs the status + screenshot accessors.
|
|
214
91
|
getAutomationWebViewStatus(): Promise<AutomationWebViewStatus>;
|
|
215
|
-
startAutomationWebView(options?: AutomationWebViewOptions): Promise<AutomationWebViewStatus>;
|
|
216
|
-
stopAutomationWebView(): Promise<boolean>;
|
|
217
|
-
evaluateAutomationWebView(expression: string): Promise<AutomationEvaluateResult>;
|
|
218
|
-
resizeAutomationWebView(width: number, height: number): Promise<AutomationWebViewStatus>;
|
|
219
92
|
screenshotAutomationWebView(options?: AutomationScreenshotOptions): Promise<Uint8Array>;
|
|
220
93
|
}
|
|
221
94
|
|
|
222
95
|
class LocalCanvasAccess implements CanvasAccess {
|
|
223
96
|
readonly remoteBaseUrl = null;
|
|
97
|
+
private readonly operationInvoker = new LocalOperationInvoker();
|
|
224
98
|
|
|
225
99
|
constructor(
|
|
226
100
|
private readonly canvas: PmxCanvas,
|
|
@@ -232,6 +106,10 @@ class LocalCanvasAccess implements CanvasAccess {
|
|
|
232
106
|
return this.canvas.port;
|
|
233
107
|
}
|
|
234
108
|
|
|
109
|
+
invoker(): OperationInvoker {
|
|
110
|
+
return this.operationInvoker;
|
|
111
|
+
}
|
|
112
|
+
|
|
235
113
|
async getLayout(): Promise<CanvasLayout> {
|
|
236
114
|
return this.canvas.getLayout();
|
|
237
115
|
}
|
|
@@ -240,36 +118,10 @@ class LocalCanvasAccess implements CanvasAccess {
|
|
|
240
118
|
return this.canvas.getNode(id);
|
|
241
119
|
}
|
|
242
120
|
|
|
243
|
-
async addNode(input: AddNodeInput): Promise<string> {
|
|
244
|
-
// PmxCanvas.addNode returns the created node; the CanvasAccess contract
|
|
245
|
-
// (shared with the remote proxy + MCP) stays id-only.
|
|
246
|
-
return this.canvas.addNode(input).id;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
async addWebpageNode(input: AddWebpageNodeInput): Promise<Awaited<ReturnType<PmxCanvas['addWebpageNode']>>> {
|
|
250
|
-
return await this.canvas.addWebpageNode(input);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
121
|
async refreshWebpageNode(id: string, url?: string): Promise<RefreshWebpageNodeResult> {
|
|
254
122
|
return await this.canvas.refreshWebpageNode(id, url);
|
|
255
123
|
}
|
|
256
124
|
|
|
257
|
-
async openMcpApp(input: OpenMcpAppInput): Promise<OpenMcpAppResult> {
|
|
258
|
-
return await this.canvas.openMcpApp(input);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
async addDiagram(input: AddDiagramInput): Promise<OpenMcpAppResult> {
|
|
262
|
-
return await this.canvas.addDiagram(input);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
async addJsonRenderNode(input: AddJsonRenderNodeInput): Promise<AddJsonRenderNodeResult> {
|
|
266
|
-
return this.canvas.addJsonRenderNode(input);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
async streamJsonRenderNode(input: StreamJsonRenderNodeInput): Promise<StreamJsonRenderNodeResult> {
|
|
270
|
-
return this.canvas.streamJsonRenderNode(input);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
125
|
async addHtmlNode(input: AddHtmlNodeInput): Promise<string> {
|
|
274
126
|
// PmxCanvas.addHtmlNode returns the created node; the CanvasAccess contract
|
|
275
127
|
// is a bare id string, so extract it (mirrors addNode above).
|
|
@@ -280,86 +132,18 @@ class LocalCanvasAccess implements CanvasAccess {
|
|
|
280
132
|
return this.canvas.addHtmlPrimitive(input);
|
|
281
133
|
}
|
|
282
134
|
|
|
283
|
-
async addGraphNode(input: AddGraphNodeInput): Promise<AddGraphNodeResult> {
|
|
284
|
-
return this.canvas.addGraphNode(input);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
async buildWebArtifact(input: WebArtifactInput): Promise<WebArtifactResult> {
|
|
288
|
-
return await this.canvas.buildWebArtifact(input);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
async updateNode(id: string, patch: UpdateNodePatch): Promise<void> {
|
|
292
|
-
this.canvas.updateNode(id, patch);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
async removeNode(id: string): Promise<void> {
|
|
296
|
-
this.canvas.removeNode(id);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
async removeAnnotation(id: string): Promise<boolean> {
|
|
300
|
-
return this.canvas.removeAnnotation(id);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
async addEdge(input: AddEdgeInput): Promise<string> {
|
|
304
|
-
return this.canvas.addEdge(input);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
async removeEdge(id: string): Promise<void> {
|
|
308
|
-
this.canvas.removeEdge(id);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
async createGroup(input: CreateGroupInput): Promise<string> {
|
|
312
|
-
return this.canvas.createGroup(input);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
async groupNodes(groupId: string, childIds: string[], options?: GroupNodesOptions): Promise<boolean> {
|
|
316
|
-
return this.canvas.groupNodes(groupId, childIds, options);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
async ungroupNodes(groupId: string): Promise<boolean> {
|
|
320
|
-
return this.canvas.ungroupNodes(groupId);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
async arrange(layout?: ArrangeLayout): Promise<void> {
|
|
324
|
-
this.canvas.arrange(layout);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
async focusNode(id: string, options?: { noPan?: boolean }): Promise<FocusNodeResult> {
|
|
328
|
-
return this.canvas.focusNode(id, options);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
async fitView(options?: FitViewOptions): Promise<FitViewResult> {
|
|
332
|
-
return this.canvas.fitView(options);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
135
|
async getAxState(): Promise<AxStateResult> {
|
|
336
136
|
return this.canvas.getAxState();
|
|
337
137
|
}
|
|
338
138
|
|
|
339
|
-
async getAxContext(): Promise<AxContextResult> {
|
|
340
|
-
return this.canvas.getAxContext();
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
async setAxFocus(nodeIds: string[], options?: { source?: PmxAxSource }): Promise<SetAxFocusResult> {
|
|
344
|
-
return this.canvas.setAxFocus(nodeIds, { source: options?.source ?? 'mcp' });
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
async recordAxEvent(input: RecordAxEventInput, options?: { source?: PmxAxSource }): Promise<RecordAxEventResult> {
|
|
348
|
-
return this.canvas.recordAxEvent(input, { source: options?.source ?? 'mcp' });
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
async sendSteering(message: string, options?: { source?: PmxAxSource }): Promise<SendSteeringResult> {
|
|
352
|
-
return this.canvas.sendSteering(message, { source: options?.source ?? 'mcp' });
|
|
139
|
+
async getAxContext(options?: { consumer?: string }): Promise<AxContextResult> {
|
|
140
|
+
return this.canvas.getAxContext(options);
|
|
353
141
|
}
|
|
354
142
|
|
|
355
143
|
async getAxTimeline(query?: GetAxTimelineQuery): Promise<GetAxTimelineResult> {
|
|
356
144
|
return this.canvas.getAxTimeline(query);
|
|
357
145
|
}
|
|
358
146
|
|
|
359
|
-
async addWorkItem(input: AddWorkItemInput, options?: { source?: PmxAxSource }): Promise<AddWorkItemResult> {
|
|
360
|
-
return this.canvas.addWorkItem(input, { source: options?.source ?? 'mcp' });
|
|
361
|
-
}
|
|
362
|
-
|
|
363
147
|
async submitAxInteraction(input: SubmitAxInteractionInput, options?: { source?: PmxAxSource }): Promise<SubmitAxInteractionResult> {
|
|
364
148
|
return this.canvas.submitAxInteraction(input, { source: options?.source ?? 'mcp' });
|
|
365
149
|
}
|
|
@@ -368,121 +152,38 @@ class LocalCanvasAccess implements CanvasAccess {
|
|
|
368
152
|
return this.canvas.getPendingSteering(options);
|
|
369
153
|
}
|
|
370
154
|
|
|
371
|
-
async markSteeringDelivered(id: string): Promise<boolean> {
|
|
372
|
-
return this.canvas.markSteeringDelivered(id);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
155
|
async listElicitations(): Promise<ListElicitationsResult> {
|
|
376
156
|
return this.canvas.listElicitations();
|
|
377
157
|
}
|
|
378
158
|
|
|
379
|
-
async requestElicitation(input: RequestElicitationInput, options?: { source?: PmxAxSource }): Promise<RequestElicitationResult> {
|
|
380
|
-
return this.canvas.requestElicitation(input, { source: options?.source ?? 'mcp' });
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
async respondElicitation(id: string, response: Record<string, unknown>, options?: { source?: PmxAxSource }): Promise<RespondElicitationResult> {
|
|
384
|
-
return this.canvas.respondElicitation(id, response, { source: options?.source ?? 'mcp' });
|
|
385
|
-
}
|
|
386
|
-
|
|
387
159
|
async listModeRequests(): Promise<ListModeRequestsResult> {
|
|
388
160
|
return this.canvas.listModeRequests();
|
|
389
161
|
}
|
|
390
162
|
|
|
391
|
-
async
|
|
392
|
-
return this.canvas.
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
async resolveModeRequest(id: string, decision: 'approved' | 'rejected', options?: { resolution?: string; source?: PmxAxSource }): Promise<ResolveModeRequestResult> {
|
|
396
|
-
return this.canvas.resolveModeRequest(id, decision, { ...(options ?? {}), source: options?.source ?? 'mcp' });
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
async getCommandRegistry(): Promise<GetCommandRegistryResult> {
|
|
400
|
-
return this.canvas.getCommandRegistry();
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
async invokeCommand(name: string, args?: Record<string, unknown> | null, options?: { source?: PmxAxSource }): Promise<InvokeCommandResult> {
|
|
404
|
-
return this.canvas.invokeCommand(name, args ?? null, { source: options?.source ?? 'mcp' });
|
|
163
|
+
async ingestActivity(input: IngestActivityInput, options?: { source?: PmxAxSource }): Promise<IngestActivityResult> {
|
|
164
|
+
return this.canvas.ingestActivity(input, { source: options?.source ?? 'mcp' });
|
|
405
165
|
}
|
|
406
166
|
|
|
407
167
|
async getPolicy(): Promise<GetPolicyResult> {
|
|
408
168
|
return this.canvas.getPolicy();
|
|
409
169
|
}
|
|
410
170
|
|
|
411
|
-
async setPolicy(patch: SetPolicyInput, options?: { source?: PmxAxSource }): Promise<SetPolicyResult> {
|
|
412
|
-
return this.canvas.setPolicy(patch, { source: options?.source ?? 'mcp' });
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
async updateWorkItem(id: string, patch: UpdateWorkItemPatch, options?: { source?: PmxAxSource }): Promise<UpdateWorkItemResult> {
|
|
416
|
-
return this.canvas.updateWorkItem(id, patch, { source: options?.source ?? 'mcp' });
|
|
417
|
-
}
|
|
418
|
-
|
|
419
171
|
async listWorkItems(): Promise<ListWorkItemsResult> {
|
|
420
172
|
return this.canvas.listWorkItems();
|
|
421
173
|
}
|
|
422
174
|
|
|
423
|
-
async requestApproval(input: RequestApprovalInput, options?: { source?: PmxAxSource }): Promise<RequestApprovalResult> {
|
|
424
|
-
return this.canvas.requestApproval(input, { source: options?.source ?? 'mcp' });
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
async resolveApproval(id: string, decision: 'approved' | 'rejected', options?: { resolution?: string; source?: PmxAxSource }): Promise<ResolveApprovalResult> {
|
|
428
|
-
return this.canvas.resolveApproval(id, decision, {
|
|
429
|
-
...(options?.resolution !== undefined ? { resolution: options.resolution } : {}),
|
|
430
|
-
source: options?.source ?? 'mcp',
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
|
|
434
175
|
async listApprovalGates(): Promise<ListApprovalGatesResult> {
|
|
435
176
|
return this.canvas.listApprovalGates();
|
|
436
177
|
}
|
|
437
178
|
|
|
438
|
-
async addEvidence(input: AddEvidenceInput, options?: { source?: PmxAxSource }): Promise<AddEvidenceResult> {
|
|
439
|
-
return this.canvas.addEvidence(input, { source: options?.source ?? 'mcp' });
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
async addReviewAnnotation(input: AddReviewAnnotationInput, options?: { source?: PmxAxSource }): Promise<AddReviewAnnotationResult> {
|
|
443
|
-
return this.canvas.addReviewAnnotation(input, { source: options?.source ?? 'mcp' });
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
async updateReviewAnnotation(id: string, patch: UpdateReviewAnnotationPatch, options?: { source?: PmxAxSource }): Promise<UpdateReviewAnnotationResult> {
|
|
447
|
-
return this.canvas.updateReviewAnnotation(id, patch, { source: options?.source ?? 'mcp' });
|
|
448
|
-
}
|
|
449
|
-
|
|
450
179
|
async listReviewAnnotations(): Promise<ListReviewAnnotationsResult> {
|
|
451
180
|
return this.canvas.listReviewAnnotations();
|
|
452
181
|
}
|
|
453
182
|
|
|
454
|
-
async getHostCapability(): Promise<GetHostCapabilityResult> {
|
|
455
|
-
return this.canvas.getHostCapability();
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
async reportHostCapability(input: unknown, options?: { source?: PmxAxSource }): Promise<ReportHostCapabilityResult> {
|
|
459
|
-
return this.canvas.reportHostCapability(input, { source: options?.source ?? 'mcp' });
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
async clear(): Promise<void> {
|
|
463
|
-
this.canvas.clear();
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
async search(query: string): Promise<SearchResult> {
|
|
467
|
-
return this.canvas.search(query);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
async undo(): Promise<UndoRedoResult> {
|
|
471
|
-
return await this.canvas.undo();
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
async redo(): Promise<UndoRedoResult> {
|
|
475
|
-
return await this.canvas.redo();
|
|
476
|
-
}
|
|
477
|
-
|
|
478
183
|
async getHistory(): Promise<HistoryResult> {
|
|
479
184
|
return this.canvas.getHistory();
|
|
480
185
|
}
|
|
481
186
|
|
|
482
|
-
async setContextPins(nodeIds: string[], mode: 'set' | 'add' | 'remove' = 'set'): Promise<SetContextPinsResult> {
|
|
483
|
-
return this.canvas.setContextPins(nodeIds, mode);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
187
|
async getPinnedNodeIds(): Promise<string[]> {
|
|
487
188
|
return Array.from(canvasState.contextPinnedNodeIds);
|
|
488
189
|
}
|
|
@@ -491,58 +192,14 @@ class LocalCanvasAccess implements CanvasAccess {
|
|
|
491
192
|
return await this.canvas.runBatch(operations);
|
|
492
193
|
}
|
|
493
194
|
|
|
494
|
-
async listSnapshots(options?: SnapshotListOptions): Promise<SnapshotList> {
|
|
495
|
-
return this.canvas.listSnapshots(options);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
async saveSnapshot(name: string): Promise<CanvasSnapshot | null> {
|
|
499
|
-
return this.canvas.saveSnapshot(name);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
async restoreSnapshot(id: string): Promise<{ ok: boolean }> {
|
|
503
|
-
return await this.canvas.restoreSnapshot(id);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
async deleteSnapshot(id: string): Promise<DeleteSnapshotResult> {
|
|
507
|
-
return this.canvas.deleteSnapshot(id);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
async gcSnapshots(options?: GcSnapshotsOptions): Promise<GcSnapshotsResult> {
|
|
511
|
-
return this.canvas.gcSnapshots(options);
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
async diffSnapshot(idOrName: string): Promise<DiffSnapshotResult> {
|
|
515
|
-
return this.canvas.diffSnapshot(idOrName);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
195
|
async getCodeGraph(): Promise<CodeGraphResult> {
|
|
519
196
|
return this.canvas.getCodeGraph();
|
|
520
197
|
}
|
|
521
198
|
|
|
522
|
-
async validate(): Promise<ValidationResult> {
|
|
523
|
-
return this.canvas.validate();
|
|
524
|
-
}
|
|
525
|
-
|
|
526
199
|
async getAutomationWebViewStatus(): Promise<AutomationWebViewStatus> {
|
|
527
200
|
return this.canvas.getAutomationWebViewStatus();
|
|
528
201
|
}
|
|
529
202
|
|
|
530
|
-
async startAutomationWebView(options: AutomationWebViewOptions = {}): Promise<AutomationWebViewStatus> {
|
|
531
|
-
return await this.canvas.startAutomationWebView(options);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
async stopAutomationWebView(): Promise<boolean> {
|
|
535
|
-
return await this.canvas.stopAutomationWebView();
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
async evaluateAutomationWebView(expression: string): Promise<AutomationEvaluateResult> {
|
|
539
|
-
return await this.canvas.evaluateAutomationWebView(expression);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
async resizeAutomationWebView(width: number, height: number): Promise<AutomationWebViewStatus> {
|
|
543
|
-
return await this.canvas.resizeAutomationWebView(width, height);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
203
|
async screenshotAutomationWebView(options: AutomationScreenshotOptions = {}): Promise<Uint8Array> {
|
|
547
204
|
return await this.canvas.screenshotAutomationWebView(options);
|
|
548
205
|
}
|
|
@@ -551,11 +208,17 @@ class LocalCanvasAccess implements CanvasAccess {
|
|
|
551
208
|
class RemoteCanvasAccess implements CanvasAccess {
|
|
552
209
|
readonly remoteBaseUrl: string;
|
|
553
210
|
readonly port: number;
|
|
211
|
+
private readonly operationInvoker: HttpOperationInvoker;
|
|
554
212
|
|
|
555
213
|
constructor(baseUrl: string) {
|
|
556
214
|
this.remoteBaseUrl = baseUrl.replace(/\/$/, '');
|
|
557
215
|
const parsed = new URL(this.remoteBaseUrl);
|
|
558
216
|
this.port = Number(parsed.port || '80');
|
|
217
|
+
this.operationInvoker = new HttpOperationInvoker(this.remoteBaseUrl);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
invoker(): OperationInvoker {
|
|
221
|
+
return this.operationInvoker;
|
|
559
222
|
}
|
|
560
223
|
|
|
561
224
|
private async requestJson<T>(method: string, path: string, body?: unknown): Promise<T> {
|
|
@@ -621,61 +284,12 @@ class RemoteCanvasAccess implements CanvasAccess {
|
|
|
621
284
|
return parsed as CanvasNodeState;
|
|
622
285
|
}
|
|
623
286
|
|
|
624
|
-
async addNode(input: AddNodeInput): Promise<string> {
|
|
625
|
-
return await this.requestNodeId('POST', '/api/canvas/node', input);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
async addWebpageNode(input: AddWebpageNodeInput): Promise<Awaited<ReturnType<PmxCanvas['addWebpageNode']>>> {
|
|
629
|
-
return await this.requestJson<Awaited<ReturnType<PmxCanvas['addWebpageNode']>>>('POST', '/api/canvas/node', {
|
|
630
|
-
type: 'webpage',
|
|
631
|
-
...input,
|
|
632
|
-
});
|
|
633
|
-
}
|
|
634
|
-
|
|
635
287
|
async refreshWebpageNode(id: string, url?: string): Promise<RefreshWebpageNodeResult> {
|
|
636
288
|
return await this.requestJson<RefreshWebpageNodeResult>('POST', `/api/canvas/node/${encodeURIComponent(id)}/refresh`, {
|
|
637
289
|
...(url ? { url } : {}),
|
|
638
290
|
});
|
|
639
291
|
}
|
|
640
292
|
|
|
641
|
-
async openMcpApp(input: OpenMcpAppInput): Promise<OpenMcpAppResult> {
|
|
642
|
-
return await this.requestJson<OpenMcpAppResult>('POST', '/api/canvas/mcp-app/open', input);
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
async addDiagram(input: AddDiagramInput): Promise<OpenMcpAppResult> {
|
|
646
|
-
return await this.requestJson<OpenMcpAppResult>('POST', '/api/canvas/diagram', input);
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
async addJsonRenderNode(input: AddJsonRenderNodeInput): Promise<AddJsonRenderNodeResult> {
|
|
650
|
-
const response = await this.requestJson<JsonRenderNodeResponse>('POST', '/api/canvas/json-render', input);
|
|
651
|
-
const id = typeof response.id === 'string' ? response.id : response.node?.id;
|
|
652
|
-
if (!id) throw new Error('json-render response did not include a node id.');
|
|
653
|
-
return { id, url: response.url, spec: response.spec };
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
async streamJsonRenderNode(input: StreamJsonRenderNodeInput): Promise<StreamJsonRenderNodeResult> {
|
|
657
|
-
const response = await this.requestJson<{
|
|
658
|
-
id?: string;
|
|
659
|
-
url?: string;
|
|
660
|
-
applied?: number;
|
|
661
|
-
skipped?: number;
|
|
662
|
-
specVersion?: number;
|
|
663
|
-
elementCount?: number;
|
|
664
|
-
streamStatus?: 'open' | 'closed';
|
|
665
|
-
}>('POST', '/api/canvas/json-render/stream', input);
|
|
666
|
-
const id = typeof response.id === 'string' ? response.id : undefined;
|
|
667
|
-
if (!id) throw new Error('json-render stream response did not include a node id.');
|
|
668
|
-
return {
|
|
669
|
-
id,
|
|
670
|
-
url: response.url ?? '',
|
|
671
|
-
applied: response.applied ?? 0,
|
|
672
|
-
skipped: response.skipped ?? 0,
|
|
673
|
-
specVersion: response.specVersion ?? 0,
|
|
674
|
-
elementCount: response.elementCount ?? 0,
|
|
675
|
-
streamStatus: response.streamStatus ?? 'open',
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
|
|
679
293
|
async addHtmlNode(input: AddHtmlNodeInput): Promise<string> {
|
|
680
294
|
const {
|
|
681
295
|
summary,
|
|
@@ -729,98 +343,6 @@ class RemoteCanvasAccess implements CanvasAccess {
|
|
|
729
343
|
};
|
|
730
344
|
}
|
|
731
345
|
|
|
732
|
-
async addGraphNode(input: AddGraphNodeInput): Promise<AddGraphNodeResult> {
|
|
733
|
-
const response = await this.requestJson<GraphNodeResponse>('POST', '/api/canvas/graph', {
|
|
734
|
-
...input,
|
|
735
|
-
...(typeof input.heightPx === 'number' ? { nodeHeight: input.heightPx } : {}),
|
|
736
|
-
});
|
|
737
|
-
const id = typeof response.id === 'string' ? response.id : response.node?.id;
|
|
738
|
-
if (!id) throw new Error('graph response did not include a node id.');
|
|
739
|
-
return { id, url: response.url, spec: response.spec };
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
async buildWebArtifact(input: WebArtifactInput): Promise<WebArtifactResult> {
|
|
743
|
-
return await this.requestJson<WebArtifactResult>('POST', '/api/canvas/web-artifact', input);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
async updateNode(id: string, patch: UpdateNodePatch): Promise<void> {
|
|
747
|
-
await this.requestJson<unknown>('PATCH', `/api/canvas/node/${encodeURIComponent(id)}`, patch);
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
async removeNode(id: string): Promise<void> {
|
|
751
|
-
await this.requestJson<unknown>('DELETE', `/api/canvas/node/${encodeURIComponent(id)}`);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
async removeAnnotation(id: string): Promise<boolean> {
|
|
755
|
-
const response = await this.requestJson<{ ok?: boolean }>('DELETE', `/api/canvas/annotation/${encodeURIComponent(id)}`);
|
|
756
|
-
return response.ok === true;
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
async addEdge(input: AddEdgeInput): Promise<string> {
|
|
760
|
-
const response = await this.requestJson<{ id?: string }>('POST', '/api/canvas/edge', input);
|
|
761
|
-
if (!response.id) throw new Error('Canvas edge response did not include an edge id.');
|
|
762
|
-
return response.id;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
async removeEdge(id: string): Promise<void> {
|
|
766
|
-
await this.requestJson<unknown>('DELETE', '/api/canvas/edge', { edge_id: id });
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
async createGroup(input: CreateGroupInput): Promise<string> {
|
|
770
|
-
return await this.requestNodeId('POST', '/api/canvas/group', input);
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
async groupNodes(groupId: string, childIds: string[], options?: GroupNodesOptions): Promise<boolean> {
|
|
774
|
-
const response = await this.requestJson<{ ok?: boolean }>('POST', '/api/canvas/group/add', {
|
|
775
|
-
groupId,
|
|
776
|
-
childIds,
|
|
777
|
-
...(options?.childLayout ? { childLayout: options.childLayout } : {}),
|
|
778
|
-
});
|
|
779
|
-
return response.ok === true;
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
async ungroupNodes(groupId: string): Promise<boolean> {
|
|
783
|
-
const response = await this.requestJson<{ ok?: boolean }>('POST', '/api/canvas/group/ungroup', { groupId });
|
|
784
|
-
return response.ok === true;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
async arrange(layout?: ArrangeLayout): Promise<void> {
|
|
788
|
-
await this.requestJson<unknown>('POST', '/api/canvas/arrange', { ...(layout ? { layout } : {}) });
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
async focusNode(id: string, options?: { noPan?: boolean }): Promise<FocusNodeResult> {
|
|
792
|
-
const response = await fetch(`${this.remoteBaseUrl}/api/canvas/focus`, {
|
|
793
|
-
method: 'POST',
|
|
794
|
-
headers: { 'Content-Type': 'application/json' },
|
|
795
|
-
body: JSON.stringify({ id, ...(options?.noPan === true ? { noPan: true } : {}) }),
|
|
796
|
-
});
|
|
797
|
-
if (response.status === 404) return null;
|
|
798
|
-
const parsed = await response.json() as { focused?: string; panned?: boolean };
|
|
799
|
-
if (!response.ok || typeof parsed.focused !== 'string' || typeof parsed.panned !== 'boolean') return null;
|
|
800
|
-
return { focused: parsed.focused, panned: parsed.panned };
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
async fitView(options?: FitViewOptions): Promise<FitViewResult> {
|
|
804
|
-
return await this.requestJson<FitViewResult>('POST', '/api/canvas/fit', options ?? {});
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
async clear(): Promise<void> {
|
|
808
|
-
await this.requestJson<unknown>('POST', '/api/canvas/clear', {});
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
async search(query: string): Promise<SearchResult> {
|
|
812
|
-
const response = await this.requestJson<SearchResponse>('GET', `/api/canvas/search?q=${encodeURIComponent(query)}`);
|
|
813
|
-
return response.results ?? [];
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
async undo(): Promise<UndoRedoResult> {
|
|
817
|
-
return await this.requestJson<UndoRedoResult>('POST', '/api/canvas/undo', {});
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
async redo(): Promise<UndoRedoResult> {
|
|
821
|
-
return await this.requestJson<UndoRedoResult>('POST', '/api/canvas/redo', {});
|
|
822
|
-
}
|
|
823
|
-
|
|
824
346
|
async getHistory(): Promise<HistoryResult> {
|
|
825
347
|
return await this.requestJson<HistoryResult>('GET', '/api/canvas/history');
|
|
826
348
|
}
|
|
@@ -831,35 +353,9 @@ class RemoteCanvasAccess implements CanvasAccess {
|
|
|
831
353
|
return response.state;
|
|
832
354
|
}
|
|
833
355
|
|
|
834
|
-
async getAxContext(): Promise<AxContextResult> {
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
async setAxFocus(nodeIds: string[], options?: { source?: PmxAxSource }): Promise<SetAxFocusResult> {
|
|
839
|
-
const response = await this.requestJson<{ focus?: SetAxFocusResult }>('POST', '/api/canvas/ax/focus', {
|
|
840
|
-
nodeIds,
|
|
841
|
-
source: options?.source ?? 'mcp',
|
|
842
|
-
});
|
|
843
|
-
if (!response.focus) throw new Error('Remote canvas did not return AX focus.');
|
|
844
|
-
return response.focus;
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
async recordAxEvent(input: RecordAxEventInput, options?: { source?: PmxAxSource }): Promise<RecordAxEventResult> {
|
|
848
|
-
const response = await this.requestJson<{ event?: RecordAxEventResult }>('POST', '/api/canvas/ax/event', {
|
|
849
|
-
...input,
|
|
850
|
-
source: options?.source ?? 'mcp',
|
|
851
|
-
});
|
|
852
|
-
if (!response.event) throw new Error('Remote canvas did not return an AX event.');
|
|
853
|
-
return response.event;
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
async sendSteering(message: string, options?: { source?: PmxAxSource }): Promise<SendSteeringResult> {
|
|
857
|
-
const response = await this.requestJson<{ steering?: SendSteeringResult }>('POST', '/api/canvas/ax/steer', {
|
|
858
|
-
message,
|
|
859
|
-
source: options?.source ?? 'mcp',
|
|
860
|
-
});
|
|
861
|
-
if (!response.steering) throw new Error('Remote canvas did not return a steering message.');
|
|
862
|
-
return response.steering;
|
|
356
|
+
async getAxContext(options?: { consumer?: string }): Promise<AxContextResult> {
|
|
357
|
+
const qs = options?.consumer ? `?consumer=${encodeURIComponent(options.consumer)}` : '';
|
|
358
|
+
return await this.requestJson<AxContextResult>('GET', `/api/canvas/ax/context${qs}`);
|
|
863
359
|
}
|
|
864
360
|
|
|
865
361
|
async getAxTimeline(query?: GetAxTimelineQuery): Promise<GetAxTimelineResult> {
|
|
@@ -867,15 +363,6 @@ class RemoteCanvasAccess implements CanvasAccess {
|
|
|
867
363
|
return await this.requestJson<GetAxTimelineResult>('GET', `/api/canvas/ax/timeline${qs}`);
|
|
868
364
|
}
|
|
869
365
|
|
|
870
|
-
async addWorkItem(input: AddWorkItemInput, options?: { source?: PmxAxSource }): Promise<AddWorkItemResult> {
|
|
871
|
-
const response = await this.requestJson<{ workItem?: AddWorkItemResult }>('POST', '/api/canvas/ax/work', {
|
|
872
|
-
...input,
|
|
873
|
-
source: options?.source ?? 'mcp',
|
|
874
|
-
});
|
|
875
|
-
if (!response.workItem) throw new Error('Remote canvas did not return a work item.');
|
|
876
|
-
return response.workItem;
|
|
877
|
-
}
|
|
878
|
-
|
|
879
366
|
async submitAxInteraction(input: SubmitAxInteractionInput, options?: { source?: PmxAxSource }): Promise<SubmitAxInteractionResult> {
|
|
880
367
|
// The interaction endpoint returns its structured outcome (ok/code/error) in
|
|
881
368
|
// the body for both accepted and rejected interactions, so read the body
|
|
@@ -902,77 +389,21 @@ class RemoteCanvasAccess implements CanvasAccess {
|
|
|
902
389
|
return response.pending ?? [];
|
|
903
390
|
}
|
|
904
391
|
|
|
905
|
-
async markSteeringDelivered(id: string): Promise<boolean> {
|
|
906
|
-
const response = await this.requestJson<{ delivered?: boolean }>(
|
|
907
|
-
'POST',
|
|
908
|
-
`/api/canvas/ax/delivery/${encodeURIComponent(id)}/mark`,
|
|
909
|
-
{},
|
|
910
|
-
);
|
|
911
|
-
return response.delivered ?? false;
|
|
912
|
-
}
|
|
913
|
-
|
|
914
392
|
async listElicitations(): Promise<ListElicitationsResult> {
|
|
915
393
|
const r = await this.requestJson<{ elicitations?: ListElicitationsResult }>('GET', '/api/canvas/ax/elicitation');
|
|
916
394
|
return r.elicitations ?? [];
|
|
917
395
|
}
|
|
918
396
|
|
|
919
|
-
async requestElicitation(input: RequestElicitationInput, options?: { source?: PmxAxSource }): Promise<RequestElicitationResult> {
|
|
920
|
-
const r = await this.requestJson<{ elicitation?: RequestElicitationResult }>('POST', '/api/canvas/ax/elicitation', {
|
|
921
|
-
...input,
|
|
922
|
-
source: options?.source ?? 'mcp',
|
|
923
|
-
});
|
|
924
|
-
if (!r.elicitation) throw new Error('Remote canvas did not return an elicitation.');
|
|
925
|
-
return r.elicitation;
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
async respondElicitation(id: string, response: Record<string, unknown>, options?: { source?: PmxAxSource }): Promise<RespondElicitationResult> {
|
|
929
|
-
const res = await fetch(`${this.remoteBaseUrl}/api/canvas/ax/elicitation/${encodeURIComponent(id)}/respond`, {
|
|
930
|
-
method: 'POST',
|
|
931
|
-
headers: { 'Content-Type': 'application/json' },
|
|
932
|
-
body: JSON.stringify({ response, source: options?.source ?? 'mcp' }),
|
|
933
|
-
});
|
|
934
|
-
if (res.status === 404) return null;
|
|
935
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
936
|
-
return (await res.json() as { elicitation?: RespondElicitationResult }).elicitation ?? null;
|
|
937
|
-
}
|
|
938
|
-
|
|
939
397
|
async listModeRequests(): Promise<ListModeRequestsResult> {
|
|
940
398
|
const r = await this.requestJson<{ modeRequests?: ListModeRequestsResult }>('GET', '/api/canvas/ax/mode');
|
|
941
399
|
return r.modeRequests ?? [];
|
|
942
400
|
}
|
|
943
401
|
|
|
944
|
-
async
|
|
945
|
-
|
|
402
|
+
async ingestActivity(input: IngestActivityInput, options?: { source?: PmxAxSource }): Promise<IngestActivityResult> {
|
|
403
|
+
return await this.requestJson<IngestActivityResult>('POST', '/api/canvas/ax/activity', {
|
|
946
404
|
...input,
|
|
947
405
|
source: options?.source ?? 'mcp',
|
|
948
406
|
});
|
|
949
|
-
if (!r.modeRequest) throw new Error('Remote canvas did not return a mode request.');
|
|
950
|
-
return r.modeRequest;
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
async resolveModeRequest(id: string, decision: 'approved' | 'rejected', options?: { resolution?: string; source?: PmxAxSource }): Promise<ResolveModeRequestResult> {
|
|
954
|
-
const res = await fetch(`${this.remoteBaseUrl}/api/canvas/ax/mode/${encodeURIComponent(id)}/resolve`, {
|
|
955
|
-
method: 'POST',
|
|
956
|
-
headers: { 'Content-Type': 'application/json' },
|
|
957
|
-
body: JSON.stringify({ decision, ...(options?.resolution ? { resolution: options.resolution } : {}), source: options?.source ?? 'mcp' }),
|
|
958
|
-
});
|
|
959
|
-
if (res.status === 404) return null;
|
|
960
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
961
|
-
return (await res.json() as { modeRequest?: ResolveModeRequestResult }).modeRequest ?? null;
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
async getCommandRegistry(): Promise<GetCommandRegistryResult> {
|
|
965
|
-
const r = await this.requestJson<{ commands?: GetCommandRegistryResult }>('GET', '/api/canvas/ax/command');
|
|
966
|
-
return r.commands ?? [];
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
async invokeCommand(name: string, args?: Record<string, unknown> | null, options?: { source?: PmxAxSource }): Promise<InvokeCommandResult> {
|
|
970
|
-
const r = await this.requestJson<{ event?: InvokeCommandResult }>('POST', '/api/canvas/ax/command', {
|
|
971
|
-
name,
|
|
972
|
-
...(args ? { args } : {}),
|
|
973
|
-
source: options?.source ?? 'mcp',
|
|
974
|
-
});
|
|
975
|
-
return r.event ?? null;
|
|
976
407
|
}
|
|
977
408
|
|
|
978
409
|
async getPolicy(): Promise<GetPolicyResult> {
|
|
@@ -981,125 +412,21 @@ class RemoteCanvasAccess implements CanvasAccess {
|
|
|
981
412
|
return r.policy;
|
|
982
413
|
}
|
|
983
414
|
|
|
984
|
-
async setPolicy(patch: SetPolicyInput, options?: { source?: PmxAxSource }): Promise<SetPolicyResult> {
|
|
985
|
-
const r = await this.requestJson<{ policy?: SetPolicyResult }>('POST', '/api/canvas/ax/policy', {
|
|
986
|
-
...patch,
|
|
987
|
-
source: options?.source ?? 'mcp',
|
|
988
|
-
});
|
|
989
|
-
if (!r.policy) throw new Error('Remote canvas did not return a policy.');
|
|
990
|
-
return r.policy;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
async updateWorkItem(id: string, patch: UpdateWorkItemPatch, options?: { source?: PmxAxSource }): Promise<UpdateWorkItemResult> {
|
|
994
|
-
const response = await fetch(`${this.remoteBaseUrl}/api/canvas/ax/work/${encodeURIComponent(id)}`, {
|
|
995
|
-
method: 'PATCH',
|
|
996
|
-
headers: { 'Content-Type': 'application/json' },
|
|
997
|
-
body: JSON.stringify({ ...patch, source: options?.source ?? 'mcp' }),
|
|
998
|
-
});
|
|
999
|
-
if (response.status === 404) return null;
|
|
1000
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
1001
|
-
return (await response.json() as { workItem?: AddWorkItemResult }).workItem ?? null;
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
415
|
async listWorkItems(): Promise<ListWorkItemsResult> {
|
|
1005
416
|
const response = await this.requestJson<{ workItems?: ListWorkItemsResult }>('GET', '/api/canvas/ax/work');
|
|
1006
417
|
return response.workItems ?? [];
|
|
1007
418
|
}
|
|
1008
419
|
|
|
1009
|
-
async requestApproval(input: RequestApprovalInput, options?: { source?: PmxAxSource }): Promise<RequestApprovalResult> {
|
|
1010
|
-
const response = await this.requestJson<{ approvalGate?: RequestApprovalResult }>('POST', '/api/canvas/ax/approval', {
|
|
1011
|
-
...input,
|
|
1012
|
-
source: options?.source ?? 'mcp',
|
|
1013
|
-
});
|
|
1014
|
-
if (!response.approvalGate) throw new Error('Remote canvas did not return an approval gate.');
|
|
1015
|
-
return response.approvalGate;
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
async resolveApproval(id: string, decision: 'approved' | 'rejected', options?: { resolution?: string; source?: PmxAxSource }): Promise<ResolveApprovalResult> {
|
|
1019
|
-
const response = await fetch(`${this.remoteBaseUrl}/api/canvas/ax/approval/${encodeURIComponent(id)}/resolve`, {
|
|
1020
|
-
method: 'POST',
|
|
1021
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1022
|
-
body: JSON.stringify({
|
|
1023
|
-
decision,
|
|
1024
|
-
...(options?.resolution !== undefined ? { resolution: options.resolution } : {}),
|
|
1025
|
-
source: options?.source ?? 'mcp',
|
|
1026
|
-
}),
|
|
1027
|
-
});
|
|
1028
|
-
if (response.status === 404) return null;
|
|
1029
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
1030
|
-
return (await response.json() as { approvalGate?: RequestApprovalResult }).approvalGate ?? null;
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
420
|
async listApprovalGates(): Promise<ListApprovalGatesResult> {
|
|
1034
421
|
const response = await this.requestJson<{ approvalGates?: ListApprovalGatesResult }>('GET', '/api/canvas/ax/approval');
|
|
1035
422
|
return response.approvalGates ?? [];
|
|
1036
423
|
}
|
|
1037
424
|
|
|
1038
|
-
async addEvidence(input: AddEvidenceInput, options?: { source?: PmxAxSource }): Promise<AddEvidenceResult> {
|
|
1039
|
-
const response = await this.requestJson<{ evidence?: AddEvidenceResult }>('POST', '/api/canvas/ax/evidence', {
|
|
1040
|
-
...input,
|
|
1041
|
-
source: options?.source ?? 'mcp',
|
|
1042
|
-
});
|
|
1043
|
-
if (!response.evidence) throw new Error('Remote canvas did not return an evidence item.');
|
|
1044
|
-
return response.evidence;
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
async addReviewAnnotation(input: AddReviewAnnotationInput, options?: { source?: PmxAxSource }): Promise<AddReviewAnnotationResult> {
|
|
1048
|
-
const response = await fetch(`${this.remoteBaseUrl}/api/canvas/ax/review`, {
|
|
1049
|
-
method: 'POST',
|
|
1050
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1051
|
-
body: JSON.stringify({ ...input, source: options?.source ?? 'mcp' }),
|
|
1052
|
-
});
|
|
1053
|
-
// 400 = validation rejection (e.g. node-anchored review with an unknown
|
|
1054
|
-
// nodeId); mirror the local path and return null rather than throwing.
|
|
1055
|
-
if (response.status === 400) return null;
|
|
1056
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
1057
|
-
return (await response.json() as { reviewAnnotation?: AddReviewAnnotationResult }).reviewAnnotation ?? null;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
async updateReviewAnnotation(id: string, patch: UpdateReviewAnnotationPatch, options?: { source?: PmxAxSource }): Promise<UpdateReviewAnnotationResult> {
|
|
1061
|
-
const response = await fetch(`${this.remoteBaseUrl}/api/canvas/ax/review/${encodeURIComponent(id)}`, {
|
|
1062
|
-
method: 'PATCH',
|
|
1063
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1064
|
-
body: JSON.stringify({ ...patch, source: options?.source ?? 'mcp' }),
|
|
1065
|
-
});
|
|
1066
|
-
if (response.status === 404) return null;
|
|
1067
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
1068
|
-
return (await response.json() as { reviewAnnotation?: AddReviewAnnotationResult }).reviewAnnotation ?? null;
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
425
|
async listReviewAnnotations(): Promise<ListReviewAnnotationsResult> {
|
|
1072
426
|
const response = await this.requestJson<{ reviewAnnotations?: ListReviewAnnotationsResult }>('GET', '/api/canvas/ax/review');
|
|
1073
427
|
return response.reviewAnnotations ?? [];
|
|
1074
428
|
}
|
|
1075
429
|
|
|
1076
|
-
async getHostCapability(): Promise<GetHostCapabilityResult> {
|
|
1077
|
-
const response = await this.requestJson<{ host?: GetHostCapabilityResult }>('GET', '/api/canvas/ax/host-capability');
|
|
1078
|
-
return response.host ?? null;
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
async reportHostCapability(input: unknown, options?: { source?: PmxAxSource }): Promise<ReportHostCapabilityResult> {
|
|
1082
|
-
const body = input !== null && typeof input === 'object' && !Array.isArray(input) ? { ...input } : {};
|
|
1083
|
-
const response = await this.requestJson<{ host?: ReportHostCapabilityResult }>('PUT', '/api/canvas/ax/host-capability', {
|
|
1084
|
-
...body,
|
|
1085
|
-
source: options?.source ?? 'mcp',
|
|
1086
|
-
});
|
|
1087
|
-
if (!response.host) throw new Error('Remote canvas did not return host capability.');
|
|
1088
|
-
return response.host;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
async setContextPins(nodeIds: string[], mode: 'set' | 'add' | 'remove' = 'set'): Promise<SetContextPinsResult> {
|
|
1092
|
-
const existing = mode === 'set' ? [] : await this.getPinnedNodeIds();
|
|
1093
|
-
const requested = new Set(nodeIds);
|
|
1094
|
-
const next = mode === 'set'
|
|
1095
|
-
? nodeIds
|
|
1096
|
-
: mode === 'add'
|
|
1097
|
-
? [...new Set([...existing, ...nodeIds])]
|
|
1098
|
-
: existing.filter((id) => !requested.has(id));
|
|
1099
|
-
const response = await this.requestJson<{ count?: number }>('POST', '/api/canvas/context-pins', { nodeIds: next });
|
|
1100
|
-
return { count: response.count ?? next.length, nodeIds: next };
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
430
|
async getPinnedNodeIds(): Promise<string[]> {
|
|
1104
431
|
const response = await this.requestJson<{ nodeIds?: string[] }>('GET', '/api/canvas/pinned-context');
|
|
1105
432
|
return Array.isArray(response.nodeIds) ? response.nodeIds : [];
|
|
@@ -1109,73 +436,15 @@ class RemoteCanvasAccess implements CanvasAccess {
|
|
|
1109
436
|
return await this.requestJson<RunBatchResult>('POST', '/api/canvas/batch', { operations });
|
|
1110
437
|
}
|
|
1111
438
|
|
|
1112
|
-
async listSnapshots(options?: SnapshotListOptions): Promise<SnapshotList> {
|
|
1113
|
-
const params = new URLSearchParams();
|
|
1114
|
-
if (typeof options?.limit === 'number') params.set('limit', String(options.limit));
|
|
1115
|
-
if (options?.query) params.set('q', options.query);
|
|
1116
|
-
if (options?.before) params.set('before', options.before);
|
|
1117
|
-
if (options?.after) params.set('after', options.after);
|
|
1118
|
-
if (options?.all) params.set('all', 'true');
|
|
1119
|
-
const query = params.size > 0 ? `?${params.toString()}` : '';
|
|
1120
|
-
return await this.requestJson<SnapshotList>('GET', `/api/canvas/snapshots${query}`);
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
async saveSnapshot(name: string): Promise<CanvasSnapshot | null> {
|
|
1124
|
-
const response = await this.requestJson<SnapshotSaveResponse>('POST', '/api/canvas/snapshots', { name });
|
|
1125
|
-
return response.snapshot ?? null;
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
async restoreSnapshot(id: string): Promise<{ ok: boolean }> {
|
|
1129
|
-
return await this.requestJson<{ ok: boolean }>('POST', `/api/canvas/snapshots/${encodeURIComponent(id)}`, {});
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
async deleteSnapshot(id: string): Promise<DeleteSnapshotResult> {
|
|
1133
|
-
return await this.requestJson<DeleteSnapshotResult>('DELETE', `/api/canvas/snapshots/${encodeURIComponent(id)}`);
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
async gcSnapshots(options?: GcSnapshotsOptions): Promise<GcSnapshotsResult> {
|
|
1137
|
-
return await this.requestJson<GcSnapshotsResult>('POST', '/api/canvas/snapshots/gc', options ?? {});
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
async diffSnapshot(idOrName: string): Promise<DiffSnapshotResult> {
|
|
1141
|
-
return await this.requestJson<DiffSnapshotResult>('GET', `/api/canvas/snapshots/${encodeURIComponent(idOrName)}/diff`);
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
439
|
async getCodeGraph(): Promise<CodeGraphResult> {
|
|
1145
440
|
const summary = await this.requestJson<CodeGraphResult['summary']>('GET', '/api/canvas/code-graph');
|
|
1146
441
|
return { text: JSON.stringify(summary, null, 2), summary };
|
|
1147
442
|
}
|
|
1148
443
|
|
|
1149
|
-
async validate(): Promise<ValidationResult> {
|
|
1150
|
-
return await this.requestJson<ValidationResult>('GET', '/api/canvas/validate');
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
444
|
async getAutomationWebViewStatus(): Promise<AutomationWebViewStatus> {
|
|
1154
445
|
return await this.requestJson<AutomationWebViewStatus>('GET', '/api/workbench/webview');
|
|
1155
446
|
}
|
|
1156
447
|
|
|
1157
|
-
async startAutomationWebView(options: AutomationWebViewOptions = {}): Promise<AutomationWebViewStatus> {
|
|
1158
|
-
const response = await this.requestJson<WebViewEnvelope>('POST', '/api/workbench/webview/start', options);
|
|
1159
|
-
if (!response.webview) throw new Error('WebView start response did not include status.');
|
|
1160
|
-
return response.webview;
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
async stopAutomationWebView(): Promise<boolean> {
|
|
1164
|
-
const response = await this.requestJson<WebViewStopEnvelope>('DELETE', '/api/workbench/webview');
|
|
1165
|
-
return response.stopped === true;
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
async evaluateAutomationWebView(expression: string): Promise<AutomationEvaluateResult> {
|
|
1169
|
-
const response = await this.requestJson<WebViewEvaluateEnvelope>('POST', '/api/workbench/webview/evaluate', { expression });
|
|
1170
|
-
return response.value as AutomationEvaluateResult;
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
async resizeAutomationWebView(width: number, height: number): Promise<AutomationWebViewStatus> {
|
|
1174
|
-
const response = await this.requestJson<WebViewEnvelope>('POST', '/api/workbench/webview/resize', { width, height });
|
|
1175
|
-
if (!response.webview) throw new Error('WebView resize response did not include status.');
|
|
1176
|
-
return response.webview;
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
448
|
async screenshotAutomationWebView(options: AutomationScreenshotOptions = {}): Promise<Uint8Array> {
|
|
1180
449
|
const response = await fetch(`${this.remoteBaseUrl}/api/workbench/webview/screenshot`, {
|
|
1181
450
|
method: 'POST',
|