pmx-canvas 0.1.13 → 0.1.15
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 +163 -0
- package/Readme.md +108 -1058
- package/dist/canvas/global.css +141 -0
- package/dist/canvas/index.js +137 -87
- package/dist/json-render/index.css +1 -1
- package/dist/types/client/nodes/ExtAppFrame.d.ts +2 -3
- package/dist/types/client/nodes/HtmlNode.d.ts +5 -0
- package/dist/types/client/nodes/McpAppNode.d.ts +2 -1
- package/dist/types/client/state/canvas-store.d.ts +5 -1
- package/dist/types/client/state/intent-bridge.d.ts +3 -1
- package/dist/types/client/types.d.ts +2 -2
- package/dist/types/json-render/catalog.d.ts +1 -1
- package/dist/types/mcp/canvas-access.d.ts +7 -1
- package/dist/types/server/agent-context.d.ts +1 -0
- package/dist/types/server/canvas-operations.d.ts +12 -2
- package/dist/types/server/canvas-provenance.d.ts +1 -1
- package/dist/types/server/canvas-serialization.d.ts +3 -0
- package/dist/types/server/canvas-state.d.ts +51 -4
- package/dist/types/server/demo.d.ts +5 -0
- package/dist/types/server/diagram-presets.d.ts +4 -0
- package/dist/types/server/index.d.ts +21 -3
- package/dist/types/server/mcp-app-runtime.d.ts +1 -0
- package/dist/types/server/web-artifacts.d.ts +18 -0
- package/dist/types/shared/canvas-node-kind.d.ts +5 -0
- package/package.json +1 -1
- package/skills/pmx-canvas/SKILL.md +43 -0
- package/skills/pmx-canvas-testing/SKILL.md +17 -0
- package/src/cli/agent.ts +66 -5
- package/src/cli/index.ts +2 -23
- package/src/client/canvas/AttentionHistory.tsx +14 -1
- package/src/client/canvas/CanvasNode.tsx +1 -1
- package/src/client/canvas/CanvasViewport.tsx +3 -0
- package/src/client/canvas/DockedNode.tsx +110 -12
- package/src/client/canvas/ExpandedNodeOverlay.tsx +8 -3
- package/src/client/canvas/Minimap.tsx +1 -0
- package/src/client/icons.tsx +1 -0
- package/src/client/nodes/ExtAppFrame.tsx +10 -35
- package/src/client/nodes/HtmlNode.tsx +151 -0
- package/src/client/nodes/McpAppNode.tsx +2 -2
- package/src/client/state/canvas-store.ts +24 -2
- package/src/client/state/intent-bridge.ts +4 -3
- package/src/client/state/sse-bridge.ts +2 -0
- package/src/client/theme/global.css +141 -0
- package/src/client/types.ts +3 -0
- package/src/mcp/canvas-access.ts +34 -7
- package/src/mcp/server.ts +199 -26
- package/src/server/agent-context.ts +50 -3
- package/src/server/canvas-operations.ts +55 -3
- package/src/server/canvas-provenance.ts +2 -1
- package/src/server/canvas-serialization.ts +38 -13
- package/src/server/canvas-state.ts +305 -34
- package/src/server/demo.ts +792 -0
- package/src/server/diagram-presets.ts +45 -25
- package/src/server/index.ts +64 -7
- package/src/server/mcp-app-runtime.ts +15 -5
- package/src/server/server.ts +169 -63
- package/src/server/web-artifacts.ts +116 -3
- package/src/shared/canvas-node-kind.ts +14 -0
|
@@ -43,11 +43,13 @@ export const EXCALIDRAW_MCP_TRANSPORT: ExternalMcpTransportConfig = {
|
|
|
43
43
|
|
|
44
44
|
export interface DiagramPresetOpenInput {
|
|
45
45
|
elements: unknown;
|
|
46
|
+
nodeId?: string;
|
|
46
47
|
title?: string;
|
|
47
48
|
x?: number;
|
|
48
49
|
y?: number;
|
|
49
50
|
width?: number;
|
|
50
51
|
height?: number;
|
|
52
|
+
timeoutMs?: number;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
export interface ExcalidrawOpenMcpAppInput {
|
|
@@ -55,11 +57,13 @@ export interface ExcalidrawOpenMcpAppInput {
|
|
|
55
57
|
toolName: string;
|
|
56
58
|
serverName: string;
|
|
57
59
|
toolArguments: { elements: string };
|
|
60
|
+
nodeId?: string;
|
|
58
61
|
title?: string;
|
|
59
62
|
x?: number;
|
|
60
63
|
y?: number;
|
|
61
64
|
width?: number;
|
|
62
65
|
height?: number;
|
|
66
|
+
timeoutMs?: number;
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
@@ -111,6 +115,21 @@ function finiteNumber(value: unknown): number | null {
|
|
|
111
115
|
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
112
116
|
}
|
|
113
117
|
|
|
118
|
+
function positiveFiniteNumber(value: unknown): number | null {
|
|
119
|
+
const num = finiteNumber(value);
|
|
120
|
+
return num !== null && num > 0 ? num : null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function labelFromBoundText(element: Record<string, unknown>): Record<string, unknown> | null {
|
|
124
|
+
const text = typeof element.text === 'string' ? element.text : '';
|
|
125
|
+
if (text.trim().length === 0) return null;
|
|
126
|
+
const fontSize = positiveFiniteNumber(element.fontSize);
|
|
127
|
+
return {
|
|
128
|
+
text,
|
|
129
|
+
...(fontSize ? { fontSize } : {}),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
114
133
|
function elementHasCameraUpdate(elements: Array<Record<string, unknown>>): boolean {
|
|
115
134
|
return elements.some((element) => element.type === 'cameraUpdate');
|
|
116
135
|
}
|
|
@@ -134,39 +153,38 @@ function normalizeExcalidrawBoundText(elements: Array<Record<string, unknown>>):
|
|
|
134
153
|
}
|
|
135
154
|
|
|
136
155
|
let changed = false;
|
|
137
|
-
const
|
|
156
|
+
const labelsByContainer = new Map<string, Record<string, unknown>>();
|
|
138
157
|
|
|
139
158
|
for (const element of elements) {
|
|
140
159
|
if (element.type !== 'text' || typeof element.id !== 'string' || typeof element.containerId !== 'string') continue;
|
|
141
160
|
const container = elementsById.get(element.containerId);
|
|
142
|
-
if (!container) continue;
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
161
|
+
if (!container || (container.type !== 'rectangle' && container.type !== 'ellipse' && container.type !== 'diamond')) continue;
|
|
162
|
+
const label = labelFromBoundText(element);
|
|
163
|
+
if (!label) continue;
|
|
164
|
+
labelsByContainer.set(element.containerId, label);
|
|
146
165
|
}
|
|
147
166
|
|
|
148
|
-
const normalized
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const missing = [...boundTextIds].filter((id) => !existingTextIds.has(id));
|
|
162
|
-
if (missing.length === 0) return element;
|
|
167
|
+
const normalized: Array<Record<string, unknown>> = [];
|
|
168
|
+
for (const element of elements) {
|
|
169
|
+
if (element.type === 'text' && typeof element.containerId === 'string') {
|
|
170
|
+
if (labelsByContainer.has(element.containerId)) {
|
|
171
|
+
changed = true;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (typeof element.id !== 'string' || !labelsByContainer.has(element.id)) {
|
|
177
|
+
normalized.push(element);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
163
180
|
|
|
164
181
|
changed = true;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
182
|
+
const { boundElements: _boundElements, ...container } = element;
|
|
183
|
+
normalized.push({
|
|
184
|
+
...container,
|
|
185
|
+
label: labelsByContainer.get(element.id),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
170
188
|
|
|
171
189
|
return changed ? normalized : elements;
|
|
172
190
|
}
|
|
@@ -333,10 +351,12 @@ export function buildExcalidrawOpenMcpAppInput(input: DiagramPresetOpenInput): E
|
|
|
333
351
|
serverName: EXCALIDRAW_SERVER_NAME,
|
|
334
352
|
toolArguments: { elements },
|
|
335
353
|
};
|
|
354
|
+
if (typeof input.nodeId === 'string' && input.nodeId.trim().length > 0) out.nodeId = input.nodeId.trim();
|
|
336
355
|
if (typeof input.title === 'string' && input.title.trim().length > 0) out.title = input.title.trim();
|
|
337
356
|
if (typeof input.x === 'number' && Number.isFinite(input.x)) out.x = input.x;
|
|
338
357
|
if (typeof input.y === 'number' && Number.isFinite(input.y)) out.y = input.y;
|
|
339
358
|
if (typeof input.width === 'number' && Number.isFinite(input.width)) out.width = input.width;
|
|
340
359
|
if (typeof input.height === 'number' && Number.isFinite(input.height)) out.height = input.height;
|
|
360
|
+
if (typeof input.timeoutMs === 'number' && Number.isFinite(input.timeoutMs) && input.timeoutMs > 0) out.timeoutMs = input.timeoutMs;
|
|
341
361
|
return out;
|
|
342
362
|
}
|
package/src/server/index.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
fitCanvasView,
|
|
21
21
|
deleteCanvasSnapshot,
|
|
22
22
|
executeCanvasBatch,
|
|
23
|
+
gcCanvasSnapshots,
|
|
23
24
|
groupCanvasNodes,
|
|
24
25
|
listCanvasSnapshots,
|
|
25
26
|
refreshCanvasWebpageNode,
|
|
@@ -33,6 +34,8 @@ import {
|
|
|
33
34
|
ungroupCanvasNodes,
|
|
34
35
|
validateCanvasNodePatch,
|
|
35
36
|
hasStructuredNodeUpdateFields,
|
|
37
|
+
hasTraceNodeDataFields,
|
|
38
|
+
mergeTraceNodeDataFields,
|
|
36
39
|
} from './canvas-operations.js';
|
|
37
40
|
import { validateCanvasLayout } from './canvas-validation.js';
|
|
38
41
|
import { describeCanvasSchema, validateStructuredCanvasPayload } from './canvas-schema.js';
|
|
@@ -158,6 +161,12 @@ export class PmxCanvas extends EventEmitter {
|
|
|
158
161
|
type: CanvasNodeState['type'];
|
|
159
162
|
title?: string;
|
|
160
163
|
content?: string;
|
|
164
|
+
toolName?: string;
|
|
165
|
+
category?: string;
|
|
166
|
+
status?: string;
|
|
167
|
+
duration?: string;
|
|
168
|
+
resultSummary?: string;
|
|
169
|
+
error?: string;
|
|
161
170
|
x?: number;
|
|
162
171
|
y?: number;
|
|
163
172
|
width?: number;
|
|
@@ -243,9 +252,10 @@ export class PmxCanvas extends EventEmitter {
|
|
|
243
252
|
patch.title !== undefined ||
|
|
244
253
|
patch.content !== undefined ||
|
|
245
254
|
typeof patch.arrangeLocked === 'boolean' ||
|
|
246
|
-
typeof patch.strictSize === 'boolean'
|
|
255
|
+
typeof patch.strictSize === 'boolean' ||
|
|
256
|
+
(existing.type === 'trace' && hasTraceNodeDataFields(patch))
|
|
247
257
|
) {
|
|
248
|
-
|
|
258
|
+
const nextData = {
|
|
249
259
|
...existing.data,
|
|
250
260
|
...(patch.data && typeof patch.data === 'object' && !Array.isArray(patch.data) ? patch.data : {}),
|
|
251
261
|
...(typeof patch.title === 'string' ? { title: patch.title } : {}),
|
|
@@ -253,6 +263,9 @@ export class PmxCanvas extends EventEmitter {
|
|
|
253
263
|
...(typeof patch.arrangeLocked === 'boolean' ? { arrangeLocked: patch.arrangeLocked } : {}),
|
|
254
264
|
...(typeof patch.strictSize === 'boolean' ? { strictSize: patch.strictSize } : {}),
|
|
255
265
|
};
|
|
266
|
+
resolvedPatch.data = existing.type === 'trace'
|
|
267
|
+
? mergeTraceNodeDataFields(nextData, patch)
|
|
268
|
+
: nextData;
|
|
256
269
|
}
|
|
257
270
|
|
|
258
271
|
const error = validateCanvasNodePatch({
|
|
@@ -447,8 +460,8 @@ export class PmxCanvas extends EventEmitter {
|
|
|
447
460
|
return result;
|
|
448
461
|
}
|
|
449
462
|
|
|
450
|
-
listSnapshots() {
|
|
451
|
-
return listCanvasSnapshots();
|
|
463
|
+
listSnapshots(options?: Parameters<typeof listCanvasSnapshots>[0]) {
|
|
464
|
+
return listCanvasSnapshots(options);
|
|
452
465
|
}
|
|
453
466
|
|
|
454
467
|
saveSnapshot(name: string) {
|
|
@@ -467,6 +480,10 @@ export class PmxCanvas extends EventEmitter {
|
|
|
467
480
|
return deleteCanvasSnapshot(id);
|
|
468
481
|
}
|
|
469
482
|
|
|
483
|
+
gcSnapshots(options?: Parameters<typeof gcCanvasSnapshots>[0]): ReturnType<typeof gcCanvasSnapshots> {
|
|
484
|
+
return gcCanvasSnapshots(options);
|
|
485
|
+
}
|
|
486
|
+
|
|
470
487
|
diffSnapshot(idOrName: string): { ok: boolean; text?: string; diff?: ReturnType<typeof diffLayouts>; error?: string } {
|
|
471
488
|
const snapData = canvasState.getSnapshotData(idOrName);
|
|
472
489
|
if (!snapData) return { ok: false, error: `Snapshot "${idOrName}" not found` };
|
|
@@ -520,21 +537,36 @@ export class PmxCanvas extends EventEmitter {
|
|
|
520
537
|
transport: ExternalMcpTransportConfig;
|
|
521
538
|
toolName: string;
|
|
522
539
|
toolArguments?: Record<string, unknown>;
|
|
540
|
+
nodeId?: string;
|
|
523
541
|
serverName?: string;
|
|
524
542
|
title?: string;
|
|
525
543
|
x?: number;
|
|
526
544
|
y?: number;
|
|
527
545
|
width?: number;
|
|
528
546
|
height?: number;
|
|
547
|
+
timeoutMs?: number;
|
|
529
548
|
}): Promise<{ ok: true; id?: string; nodeId: string | null; toolCallId: string; sessionId: string; resourceUri: string }> {
|
|
549
|
+
const targetNode = input.nodeId ? canvasState.getNode(input.nodeId) : undefined;
|
|
550
|
+
if (input.nodeId && !targetNode) {
|
|
551
|
+
throw new Error(`Node "${input.nodeId}" not found.`);
|
|
552
|
+
}
|
|
553
|
+
if (targetNode && (targetNode.type !== 'mcp-app' || targetNode.data.mode !== 'ext-app')) {
|
|
554
|
+
throw new Error(`Node "${input.nodeId}" is not an external app node.`);
|
|
555
|
+
}
|
|
556
|
+
|
|
530
557
|
const opened = await openExternalMcpApp({
|
|
531
558
|
transport: input.transport,
|
|
532
559
|
toolName: input.toolName,
|
|
533
560
|
...(input.toolArguments ? { toolArguments: input.toolArguments } : {}),
|
|
534
561
|
...(input.serverName ? { serverName: input.serverName } : {}),
|
|
562
|
+
...(typeof input.timeoutMs === 'number' ? { timeoutMs: input.timeoutMs } : {}),
|
|
535
563
|
});
|
|
536
564
|
const toolCallId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
537
|
-
const
|
|
565
|
+
const previousSessionId = targetNode?.data.appSessionId;
|
|
566
|
+
if (typeof previousSessionId === 'string' && previousSessionId.trim().length > 0) {
|
|
567
|
+
closeMcpAppSession(previousSessionId);
|
|
568
|
+
}
|
|
569
|
+
const nodeIdSeed = input.nodeId ?? `ext-app-${toolCallId}`;
|
|
538
570
|
const toolResult = isExcalidrawCreateView(opened.serverName, opened.toolName)
|
|
539
571
|
? ensureExcalidrawCheckpointId(opened.toolResult, nodeIdSeed)
|
|
540
572
|
: opened.toolResult;
|
|
@@ -566,7 +598,7 @@ export class PmxCanvas extends EventEmitter {
|
|
|
566
598
|
success: toolResult.isError !== true,
|
|
567
599
|
result: toolResult,
|
|
568
600
|
});
|
|
569
|
-
const nodeId = this.findCanvasExtAppNodeId(toolCallId);
|
|
601
|
+
const nodeId = input.nodeId ?? this.findCanvasExtAppNodeId(toolCallId);
|
|
570
602
|
return {
|
|
571
603
|
ok: true,
|
|
572
604
|
...(nodeId ? { id: nodeId } : {}),
|
|
@@ -592,6 +624,31 @@ export class PmxCanvas extends EventEmitter {
|
|
|
592
624
|
return result;
|
|
593
625
|
}
|
|
594
626
|
|
|
627
|
+
addHtmlNode(input: {
|
|
628
|
+
html: string;
|
|
629
|
+
title?: string;
|
|
630
|
+
x?: number;
|
|
631
|
+
y?: number;
|
|
632
|
+
width?: number;
|
|
633
|
+
height?: number;
|
|
634
|
+
strictSize?: boolean;
|
|
635
|
+
}): string {
|
|
636
|
+
const { id } = addCanvasNode({
|
|
637
|
+
type: 'html',
|
|
638
|
+
...(typeof input.title === 'string' ? { title: input.title } : {}),
|
|
639
|
+
data: { html: input.html },
|
|
640
|
+
...(typeof input.x === 'number' ? { x: input.x } : {}),
|
|
641
|
+
...(typeof input.y === 'number' ? { y: input.y } : {}),
|
|
642
|
+
...(typeof input.width === 'number' ? { width: input.width } : {}),
|
|
643
|
+
...(typeof input.height === 'number' ? { height: input.height } : {}),
|
|
644
|
+
...(input.strictSize ? { strictSize: true } : {}),
|
|
645
|
+
defaultWidth: 720,
|
|
646
|
+
defaultHeight: 640,
|
|
647
|
+
});
|
|
648
|
+
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
649
|
+
return id;
|
|
650
|
+
}
|
|
651
|
+
|
|
595
652
|
addGraphNode(input: GraphNodeInput): { id: string; url: string; spec: JsonRenderSpec } {
|
|
596
653
|
const result = createCanvasGraphNode(input);
|
|
597
654
|
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
@@ -666,7 +723,7 @@ export {
|
|
|
666
723
|
screenshotCanvasAutomationWebView,
|
|
667
724
|
} from './server.js';
|
|
668
725
|
export { canvasState } from './canvas-state.js';
|
|
669
|
-
export type { CanvasSnapshot } from './canvas-state.js';
|
|
726
|
+
export type { CanvasSnapshot, CanvasSnapshotGcResult, CanvasSnapshotListOptions } from './canvas-state.js';
|
|
670
727
|
export { findOpenCanvasPosition } from './placement.js';
|
|
671
728
|
export { searchNodes, buildSpatialContext, detectClusters, findNeighborhoods } from './spatial-analysis.js';
|
|
672
729
|
export type { SpatialCluster, SpatialContext, SpatialNeighbor, NodeSpatialInfo } from './spatial-analysis.js';
|
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
TextResourceContents,
|
|
13
13
|
Tool,
|
|
14
14
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
15
|
+
import type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
15
16
|
import {
|
|
16
17
|
EXTENSION_ID,
|
|
17
18
|
RESOURCE_MIME_TYPE,
|
|
@@ -47,6 +48,7 @@ export interface OpenMcpAppInput {
|
|
|
47
48
|
toolName: string;
|
|
48
49
|
toolArguments?: Record<string, unknown>;
|
|
49
50
|
serverName?: string;
|
|
51
|
+
timeoutMs?: number;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
export interface OpenMcpAppResult {
|
|
@@ -184,6 +186,12 @@ function normalizeServerName(raw: string | undefined, transport: ExternalMcpTran
|
|
|
184
186
|
return trimmed.length > 0 ? trimmed : defaultServerName(transport);
|
|
185
187
|
}
|
|
186
188
|
|
|
189
|
+
function requestOptions(timeoutMs: number | undefined): RequestOptions | undefined {
|
|
190
|
+
return typeof timeoutMs === 'number' && Number.isFinite(timeoutMs) && timeoutMs > 0
|
|
191
|
+
? { timeout: timeoutMs }
|
|
192
|
+
: undefined;
|
|
193
|
+
}
|
|
194
|
+
|
|
187
195
|
function buildTransport(config: ExternalMcpTransportConfig): RuntimeTransport {
|
|
188
196
|
if (config.type === 'http') {
|
|
189
197
|
return new StreamableHTTPClientTransport(new URL(config.url), {
|
|
@@ -209,15 +217,16 @@ function buildTransport(config: ExternalMcpTransportConfig): RuntimeTransport {
|
|
|
209
217
|
async function createSession(
|
|
210
218
|
transportConfig: ExternalMcpTransportConfig,
|
|
211
219
|
serverName?: string,
|
|
220
|
+
timeoutMs?: number,
|
|
212
221
|
): Promise<McpAppSession> {
|
|
213
222
|
const transport = buildTransport(transportConfig);
|
|
214
223
|
const client = new Client(
|
|
215
224
|
{ name: 'pmx-canvas-app-host', version: '0.1.0' },
|
|
216
225
|
{ capabilities: clientCapabilities },
|
|
217
226
|
);
|
|
218
|
-
await client.connect(transport);
|
|
227
|
+
await client.connect(transport, requestOptions(timeoutMs));
|
|
219
228
|
|
|
220
|
-
const toolList = await client.listTools();
|
|
229
|
+
const toolList = await client.listTools(undefined, requestOptions(timeoutMs));
|
|
221
230
|
const session: McpAppSession = {
|
|
222
231
|
id: randomId('mcp-app-session'),
|
|
223
232
|
serverName: normalizeServerName(serverName, transportConfig),
|
|
@@ -350,7 +359,8 @@ function prepareResourceHtml(html: string, meta: McpUiResourceMeta | undefined):
|
|
|
350
359
|
}
|
|
351
360
|
|
|
352
361
|
export async function openMcpApp(input: OpenMcpAppInput): Promise<OpenMcpAppResult> {
|
|
353
|
-
const
|
|
362
|
+
const options = requestOptions(input.timeoutMs);
|
|
363
|
+
const session = await createSession(input.transport, input.serverName, input.timeoutMs);
|
|
354
364
|
try {
|
|
355
365
|
const tool = await findTool(session, input.toolName);
|
|
356
366
|
const resourceUri = getToolUiResourceUri(tool);
|
|
@@ -362,9 +372,9 @@ export async function openMcpApp(input: OpenMcpAppInput): Promise<OpenMcpAppResu
|
|
|
362
372
|
const rawToolResult = await session.client.callTool({
|
|
363
373
|
name: tool.name,
|
|
364
374
|
arguments: toolInput,
|
|
365
|
-
});
|
|
375
|
+
}, undefined, options);
|
|
366
376
|
const toolResult = normalizeExtAppToolResult({ result: rawToolResult });
|
|
367
|
-
const readResult = await session.client.readResource({ uri: resourceUri });
|
|
377
|
+
const readResult = await session.client.readResource({ uri: resourceUri }, options);
|
|
368
378
|
const resourceMeta = resourceMetaFromReadResult(readResult);
|
|
369
379
|
const html = prepareResourceHtml(htmlContentFromReadResult(readResult, resourceUri), resourceMeta);
|
|
370
380
|
|