pmx-canvas 0.2.7 → 0.3.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 +148 -1
- package/Readme.md +13 -11
- package/dist/canvas/index.js +2 -2
- package/dist/json-render/index.css +1 -1
- package/dist/types/cli/daemon.d.ts +74 -0
- package/dist/types/cli/watch.d.ts +2 -2
- package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
- package/dist/types/client/canvas/CommandPalette.d.ts +1 -1
- package/dist/types/client/canvas/Minimap.d.ts +1 -1
- package/dist/types/client/nodes/FileNode.d.ts +1 -1
- package/dist/types/client/nodes/ImageNode.d.ts +1 -1
- package/dist/types/client/nodes/InlineFormatBar.d.ts +1 -1
- package/dist/types/client/nodes/MarkdownNode.d.ts +1 -1
- package/dist/types/client/nodes/PromptNode.d.ts +1 -1
- package/dist/types/client/nodes/ResponseNode.d.ts +1 -1
- package/dist/types/mcp/canvas-access.d.ts +0 -7
- package/dist/types/server/ax-state-manager.d.ts +3 -2
- package/dist/types/server/bundled-skills.d.ts +3 -3
- package/dist/types/server/canvas-schema.d.ts +1 -1
- package/dist/types/server/canvas-state.d.ts +2 -0
- package/dist/types/server/ext-app-lookup.d.ts +1 -3
- package/dist/types/server/html-primitives.d.ts +1 -1
- package/dist/types/server/index.d.ts +4 -4
- package/dist/types/server/operations/composites.d.ts +29 -23
- package/dist/types/server/operations/http.d.ts +2 -1
- package/dist/types/server/operations/index.d.ts +1 -1
- package/dist/types/server/operations/ops/ax-read.d.ts +2 -0
- package/dist/types/server/operations/ops/canvas-wire.d.ts +2 -0
- package/dist/types/server/operations/ops/ext-app.d.ts +2 -0
- package/dist/types/shared/ax-intent.d.ts +1 -1
- package/docs/RELEASE.md +23 -8
- package/docs/ax-host-adapter-contract.md +7 -7
- package/docs/ax-state-contract.md +7 -6
- package/docs/bun-webview-integration.md +5 -5
- package/docs/cli.md +1 -1
- package/docs/http-api.md +35 -3
- package/docs/mcp.md +121 -100
- package/docs/node-types.md +45 -35
- package/docs/plans/plan-006-mcp-tool-consolidation.md +3 -1
- package/docs/plans/plan-008-registry-finish.md +2 -0
- package/docs/plans/plan-009-tech-debt-backlog.md +51 -0
- package/docs/screenshot.png +0 -0
- package/docs/tech-debt-assessment-2026-06.md +1 -1
- package/docs/tech-debt-assessment-2026-07.md +135 -0
- package/package.json +5 -2
- package/skills/data-analysis/SKILL.md +3 -3
- package/skills/frontend-design/SKILL.md +3 -2
- package/skills/json-render-mcp/SKILL.md +4 -3
- package/skills/playwright-cli/SKILL.md +1 -1
- package/skills/pmx-canvas/SKILL.md +12 -7
- package/skills/pmx-canvas/evals/evals.json +2 -2
- package/skills/pmx-canvas/references/ax-html-control-surface.md +3 -1
- package/skills/pmx-canvas/references/excalidraw-diagram-authoring.md +2 -2
- package/skills/pmx-canvas/references/full-reference.md +58 -56
- package/skills/pmx-canvas/references/html-primitives.md +3 -3
- package/skills/tufte-viz/SKILL.md +5 -4
- package/skills/web-artifacts-builder/SKILL.md +4 -4
- package/src/cli/agent.ts +1861 -1548
- package/src/cli/daemon.ts +460 -0
- package/src/cli/index.ts +63 -326
- package/src/cli/watch.ts +2 -10
- package/src/client/App.tsx +48 -46
- package/src/client/canvas/AttentionHistory.tsx +11 -1
- package/src/client/canvas/CanvasNode.tsx +41 -29
- package/src/client/canvas/CanvasViewport.tsx +101 -66
- package/src/client/canvas/CommandPalette.tsx +61 -27
- package/src/client/canvas/ContextMenu.tsx +13 -20
- package/src/client/canvas/ContextPinBar.tsx +1 -5
- package/src/client/canvas/ContextPinHud.tsx +1 -6
- package/src/client/canvas/DockedNode.tsx +4 -4
- package/src/client/canvas/EdgeLayer.tsx +37 -36
- package/src/client/canvas/ExpandedNodeOverlay.tsx +69 -45
- package/src/client/canvas/FocusFieldLayer.tsx +20 -22
- package/src/client/canvas/IntentLayer.tsx +31 -14
- package/src/client/canvas/Minimap.tsx +11 -16
- package/src/client/canvas/SelectionBar.tsx +4 -11
- package/src/client/canvas/ShortcutOverlay.tsx +3 -1
- package/src/client/canvas/SnapshotPanel.tsx +77 -95
- package/src/client/canvas/auto-fit.ts +15 -14
- package/src/client/canvas/snap-guides.ts +12 -12
- package/src/client/canvas/use-node-resize.ts +1 -5
- package/src/client/canvas/use-pan-zoom.ts +25 -26
- package/src/client/ext-app/bridge.ts +3 -12
- package/src/client/icons.tsx +63 -20
- package/src/client/nodes/ContextNode.tsx +14 -25
- package/src/client/nodes/ExtAppFrame.tsx +60 -39
- package/src/client/nodes/FileNode.tsx +74 -62
- package/src/client/nodes/GroupNode.tsx +4 -6
- package/src/client/nodes/HtmlNode.tsx +76 -46
- package/src/client/nodes/ImageNode.tsx +18 -27
- package/src/client/nodes/InlineFormatBar.tsx +4 -21
- package/src/client/nodes/InlineMarkdownEditor.tsx +0 -1
- package/src/client/nodes/LedgerNode.tsx +10 -4
- package/src/client/nodes/MarkdownNode.tsx +3 -10
- package/src/client/nodes/McpAppNode.tsx +26 -22
- package/src/client/nodes/MdFormatBar.tsx +10 -7
- package/src/client/nodes/PromptNode.tsx +23 -51
- package/src/client/nodes/ResponseNode.tsx +3 -13
- package/src/client/nodes/StatusNode.tsx +5 -9
- package/src/client/nodes/StatusSummary.tsx +2 -8
- package/src/client/nodes/WebpageNode.tsx +20 -14
- package/src/client/nodes/iframe-document-url.ts +25 -16
- package/src/client/nodes/image-warnings.ts +1 -7
- package/src/client/nodes/md-format.ts +20 -5
- package/src/client/state/attention-bridge.ts +4 -9
- package/src/client/state/attention-store.ts +1 -7
- package/src/client/state/canvas-store.ts +52 -36
- package/src/client/state/intent-bridge.ts +176 -112
- package/src/client/state/intent-store.ts +4 -1
- package/src/client/state/sse-bridge.ts +53 -70
- package/src/json-render/catalog.ts +12 -16
- package/src/json-render/charts/components.tsx +16 -20
- package/src/json-render/charts/extra-components.tsx +8 -16
- package/src/json-render/charts/extra-definitions.ts +1 -2
- package/src/json-render/charts/tufte-components.tsx +37 -20
- package/src/json-render/charts/tufte-definitions.ts +8 -2
- package/src/json-render/renderer/index.tsx +42 -22
- package/src/json-render/schema.ts +6 -3
- package/src/json-render/server.ts +33 -39
- package/src/mcp/canvas-access.ts +40 -121
- package/src/mcp/server.ts +206 -271
- package/src/server/agent-context.ts +63 -36
- package/src/server/ax-context.ts +7 -5
- package/src/server/ax-interaction.ts +176 -43
- package/src/server/ax-state-manager.ts +185 -41
- package/src/server/ax-state.ts +142 -47
- package/src/server/bundled-skills.ts +3 -3
- package/src/server/canvas-db.ts +213 -95
- package/src/server/canvas-operations.ts +177 -120
- package/src/server/canvas-provenance.ts +1 -4
- package/src/server/canvas-schema.ts +500 -102
- package/src/server/canvas-serialization.ts +27 -35
- package/src/server/canvas-state.ts +155 -58
- package/src/server/chart-template.ts +4 -5
- package/src/server/code-graph.ts +20 -7
- package/src/server/diagram-presets.ts +28 -29
- package/src/server/ext-app-lookup.ts +4 -20
- package/src/server/html-node-summary.ts +19 -10
- package/src/server/html-primitives.ts +326 -97
- package/src/server/html-surface.ts +6 -9
- package/src/server/image-source.ts +6 -4
- package/src/server/index.ts +321 -218
- package/src/server/intent-registry.ts +3 -6
- package/src/server/mcp-app-candidate.ts +5 -10
- package/src/server/mcp-app-host.ts +14 -38
- package/src/server/mcp-app-runtime.ts +12 -20
- package/src/server/mutation-history.ts +15 -5
- package/src/server/operations/composites.ts +38 -40
- package/src/server/operations/http.ts +5 -5
- package/src/server/operations/index.ts +7 -1
- package/src/server/operations/invoker.ts +4 -3
- package/src/server/operations/mcp.ts +29 -36
- package/src/server/operations/ops/annotation.ts +122 -10
- package/src/server/operations/ops/app.ts +102 -77
- package/src/server/operations/ops/ax-await.ts +17 -10
- package/src/server/operations/ops/ax-read.ts +347 -0
- package/src/server/operations/ops/ax-shared.ts +2 -7
- package/src/server/operations/ops/ax-state.ts +32 -14
- package/src/server/operations/ops/ax-timeline.ts +32 -19
- package/src/server/operations/ops/ax-work.ts +54 -37
- package/src/server/operations/ops/batch.ts +39 -14
- package/src/server/operations/ops/canvas-wire.ts +91 -0
- package/src/server/operations/ops/edges.ts +37 -25
- package/src/server/operations/ops/ext-app.ts +346 -0
- package/src/server/operations/ops/groups.ts +49 -20
- package/src/server/operations/ops/intent.ts +18 -12
- package/src/server/operations/ops/json-render.ts +239 -98
- package/src/server/operations/ops/nodes.ts +300 -111
- package/src/server/operations/ops/query.ts +62 -33
- package/src/server/operations/ops/snapshots.ts +35 -26
- package/src/server/operations/ops/validate.ts +2 -1
- package/src/server/operations/ops/viewport.ts +60 -16
- package/src/server/operations/ops/webview.ts +44 -18
- package/src/server/operations/registry.ts +2 -3
- package/src/server/operations/types.ts +7 -5
- package/src/server/operations/webview-runner.ts +1 -3
- package/src/server/placement.ts +8 -18
- package/src/server/server.ts +121 -1012
- package/src/server/spatial-analysis.ts +39 -25
- package/src/server/trace-manager.ts +3 -8
- package/src/server/web-artifacts.ts +23 -27
- package/src/server/webpage-node.ts +5 -13
- package/src/shared/auto-arrange.ts +12 -5
- package/src/shared/ax-intent.ts +1 -1
- package/src/shared/content-height-reporter.ts +8 -6
- package/src/shared/ext-app-tool-result.ts +2 -6
- package/src/shared/placement.ts +1 -4
- package/src/shared/semantic-attention.ts +39 -37
- package/src/shared/surface.ts +8 -4
|
@@ -152,7 +152,8 @@ function boundTextRefId(value: unknown): string | null {
|
|
|
152
152
|
function hasRenderableExcalidrawElement(elements: Array<Record<string, unknown>>): boolean {
|
|
153
153
|
return elements.some((element) => {
|
|
154
154
|
if (element.isDeleted === true) return false;
|
|
155
|
-
if (element.type === 'cameraUpdate' || element.type === 'restoreCheckpoint' || element.type === 'delete')
|
|
155
|
+
if (element.type === 'cameraUpdate' || element.type === 'restoreCheckpoint' || element.type === 'delete')
|
|
156
|
+
return false;
|
|
156
157
|
if (typeof element.type !== 'string' || element.type.length === 0) return false;
|
|
157
158
|
if (element.type === 'text') {
|
|
158
159
|
return typeof element.text === 'string' && element.text.trim().length > 0;
|
|
@@ -173,7 +174,12 @@ function normalizeExcalidrawBoundText(elements: Array<Record<string, unknown>>):
|
|
|
173
174
|
const collapsedTextIds = new Set<string>();
|
|
174
175
|
|
|
175
176
|
for (const container of elements) {
|
|
176
|
-
if (
|
|
177
|
+
if (
|
|
178
|
+
!isTextBindableContainer(container) ||
|
|
179
|
+
typeof container.id !== 'string' ||
|
|
180
|
+
!Array.isArray(container.boundElements)
|
|
181
|
+
)
|
|
182
|
+
continue;
|
|
177
183
|
for (const rawBoundElement of container.boundElements) {
|
|
178
184
|
const textId = boundTextRefId(rawBoundElement);
|
|
179
185
|
if (!textId) continue;
|
|
@@ -187,9 +193,8 @@ function normalizeExcalidrawBoundText(elements: Array<Record<string, unknown>>):
|
|
|
187
193
|
|
|
188
194
|
for (const element of elements) {
|
|
189
195
|
if (element.type !== 'text' || typeof element.id !== 'string') continue;
|
|
190
|
-
const containerId =
|
|
191
|
-
? element.containerId
|
|
192
|
-
: containerIdByTextId.get(element.id);
|
|
196
|
+
const containerId =
|
|
197
|
+
typeof element.containerId === 'string' ? element.containerId : containerIdByTextId.get(element.id);
|
|
193
198
|
if (!containerId) continue;
|
|
194
199
|
const container = elementsById.get(containerId);
|
|
195
200
|
if (!container || !isTextBindableContainer(container)) continue;
|
|
@@ -227,9 +232,7 @@ function normalizeExcalidrawBoundText(elements: Array<Record<string, unknown>>):
|
|
|
227
232
|
function resolveExcalidrawCameraSize(width: number, height: number): { width: number; height: number } {
|
|
228
233
|
const requiredWidth = Math.max(EXCALIDRAW_MIN_CAMERA_WIDTH, width);
|
|
229
234
|
const requiredHeight = Math.max(EXCALIDRAW_MIN_CAMERA_HEIGHT, height);
|
|
230
|
-
const standard = EXCALIDRAW_CAMERA_SIZES.find(
|
|
231
|
-
(size) => size.width >= requiredWidth && size.height >= requiredHeight,
|
|
232
|
-
);
|
|
235
|
+
const standard = EXCALIDRAW_CAMERA_SIZES.find((size) => size.width >= requiredWidth && size.height >= requiredHeight);
|
|
233
236
|
if (standard) return standard;
|
|
234
237
|
|
|
235
238
|
const heightFromWidth = requiredWidth / EXCALIDRAW_CAMERA_ASPECT_RATIO;
|
|
@@ -241,9 +244,7 @@ function resolveExcalidrawCameraSize(width: number, height: number): { width: nu
|
|
|
241
244
|
};
|
|
242
245
|
}
|
|
243
246
|
|
|
244
|
-
export function inferExcalidrawCameraUpdate(
|
|
245
|
-
elements: Array<Record<string, unknown>>,
|
|
246
|
-
): Record<string, unknown> | null {
|
|
247
|
+
export function inferExcalidrawCameraUpdate(elements: Array<Record<string, unknown>>): Record<string, unknown> | null {
|
|
247
248
|
let minX = Number.POSITIVE_INFINITY;
|
|
248
249
|
let minY = Number.POSITIVE_INFINITY;
|
|
249
250
|
let maxX = Number.NEGATIVE_INFINITY;
|
|
@@ -257,7 +258,12 @@ export function inferExcalidrawCameraUpdate(
|
|
|
257
258
|
};
|
|
258
259
|
|
|
259
260
|
for (const element of elements) {
|
|
260
|
-
if (
|
|
261
|
+
if (
|
|
262
|
+
element.isDeleted === true ||
|
|
263
|
+
element.type === 'cameraUpdate' ||
|
|
264
|
+
element.type === 'restoreCheckpoint' ||
|
|
265
|
+
element.type === 'delete'
|
|
266
|
+
) {
|
|
261
267
|
continue;
|
|
262
268
|
}
|
|
263
269
|
|
|
@@ -287,10 +293,7 @@ export function inferExcalidrawCameraUpdate(
|
|
|
287
293
|
|
|
288
294
|
const contentWidth = Math.max(1, maxX - minX);
|
|
289
295
|
const contentHeight = Math.max(1, maxY - minY);
|
|
290
|
-
const padding = Math.max(
|
|
291
|
-
EXCALIDRAW_CAMERA_PADDING,
|
|
292
|
-
Math.round(Math.max(contentWidth, contentHeight) * 0.18),
|
|
293
|
-
);
|
|
296
|
+
const padding = Math.max(EXCALIDRAW_CAMERA_PADDING, Math.round(Math.max(contentWidth, contentHeight) * 0.18));
|
|
294
297
|
const camera = resolveExcalidrawCameraSize(contentWidth + padding * 2, contentHeight + padding * 2);
|
|
295
298
|
const centerX = minX + contentWidth / 2;
|
|
296
299
|
const centerY = minY + contentHeight / 2;
|
|
@@ -304,9 +307,7 @@ export function inferExcalidrawCameraUpdate(
|
|
|
304
307
|
};
|
|
305
308
|
}
|
|
306
309
|
|
|
307
|
-
function withInferredCameraUpdate(
|
|
308
|
-
elements: Array<Record<string, unknown>>,
|
|
309
|
-
): Array<Record<string, unknown>> {
|
|
310
|
+
function withInferredCameraUpdate(elements: Array<Record<string, unknown>>): Array<Record<string, unknown>> {
|
|
310
311
|
if (elementHasCameraUpdate(elements)) return elements;
|
|
311
312
|
const camera = inferExcalidrawCameraUpdate(elements);
|
|
312
313
|
return camera ? [camera, ...elements] : elements;
|
|
@@ -332,10 +333,7 @@ export function normalizeExcalidrawCheckpointDataForToolInput(data: unknown): st
|
|
|
332
333
|
export function buildExcalidrawRestoreCheckpointToolInput(checkpointId: string, data?: unknown): string {
|
|
333
334
|
const elements = parseExcalidrawCheckpointElements(data);
|
|
334
335
|
const camera = elements ? inferExcalidrawCameraUpdate(elements) : null;
|
|
335
|
-
return JSON.stringify([
|
|
336
|
-
{ type: 'restoreCheckpoint', id: checkpointId },
|
|
337
|
-
...(camera ? [camera] : []),
|
|
338
|
-
]);
|
|
336
|
+
return JSON.stringify([{ type: 'restoreCheckpoint', id: checkpointId }, ...(camera ? [camera] : [])]);
|
|
339
337
|
}
|
|
340
338
|
|
|
341
339
|
export function isExcalidrawCreateView(serverName: unknown, toolName: unknown): boolean {
|
|
@@ -343,7 +341,10 @@ export function isExcalidrawCreateView(serverName: unknown, toolName: unknown):
|
|
|
343
341
|
}
|
|
344
342
|
|
|
345
343
|
export function buildExcalidrawCheckpointId(seed: string): string {
|
|
346
|
-
const safe = seed
|
|
344
|
+
const safe = seed
|
|
345
|
+
.replace(/[^A-Za-z0-9_-]+/g, '-')
|
|
346
|
+
.replace(/^-+|-+$/g, '')
|
|
347
|
+
.slice(0, 96);
|
|
347
348
|
return `pmx-${safe || 'checkpoint'}`;
|
|
348
349
|
}
|
|
349
350
|
|
|
@@ -353,10 +354,7 @@ export function getExcalidrawCheckpointIdFromToolResult(result: unknown): string
|
|
|
353
354
|
return typeof checkpointId === 'string' && checkpointId.trim().length > 0 ? checkpointId.trim() : null;
|
|
354
355
|
}
|
|
355
356
|
|
|
356
|
-
export function withExcalidrawCheckpointId(
|
|
357
|
-
result: CallToolResult,
|
|
358
|
-
checkpointId: string,
|
|
359
|
-
): CallToolResult {
|
|
357
|
+
export function withExcalidrawCheckpointId(result: CallToolResult, checkpointId: string): CallToolResult {
|
|
360
358
|
const structuredContent = isRecord(result.structuredContent) ? result.structuredContent : {};
|
|
361
359
|
return {
|
|
362
360
|
...result,
|
|
@@ -392,6 +390,7 @@ export function buildExcalidrawOpenMcpAppInput(input: DiagramPresetOpenInput): E
|
|
|
392
390
|
if (typeof input.y === 'number' && Number.isFinite(input.y)) out.y = input.y;
|
|
393
391
|
if (typeof input.width === 'number' && Number.isFinite(input.width)) out.width = input.width;
|
|
394
392
|
if (typeof input.height === 'number' && Number.isFinite(input.height)) out.height = input.height;
|
|
395
|
-
if (typeof input.timeoutMs === 'number' && Number.isFinite(input.timeoutMs) && input.timeoutMs > 0)
|
|
393
|
+
if (typeof input.timeoutMs === 'number' && Number.isFinite(input.timeoutMs) && input.timeoutMs > 0)
|
|
394
|
+
out.timeoutMs = input.timeoutMs;
|
|
396
395
|
return out;
|
|
397
396
|
}
|
|
@@ -9,9 +9,7 @@
|
|
|
9
9
|
* Resolution order:
|
|
10
10
|
* 1. The direct prefixed form (`ext-app-<toolCallId>` if not already
|
|
11
11
|
* prefixed, otherwise `toolCallId` as-is).
|
|
12
|
-
* 2.
|
|
13
|
-
* v0.1.4 and still on disk. Remove this fallback in v0.2.x.
|
|
14
|
-
* 3. A scan of the layout for any `mcp-app` ext-app node carrying that
|
|
12
|
+
* 2. A scan of the layout for any `mcp-app` ext-app node carrying that
|
|
15
13
|
* `toolCallId` in its data.
|
|
16
14
|
*/
|
|
17
15
|
import type { CanvasNodeState } from './canvas-state.js';
|
|
@@ -21,26 +19,12 @@ export interface ExtAppLookupSource {
|
|
|
21
19
|
listNodes(): readonly CanvasNodeState[];
|
|
22
20
|
}
|
|
23
21
|
|
|
24
|
-
export function findCanvasExtAppNodeId(
|
|
25
|
-
toolCallId:
|
|
26
|
-
source: ExtAppLookupSource,
|
|
27
|
-
): string | null {
|
|
28
|
-
const directId = toolCallId.startsWith('ext-app-')
|
|
29
|
-
? toolCallId
|
|
30
|
-
: `ext-app-${toolCallId}`;
|
|
22
|
+
export function findCanvasExtAppNodeId(toolCallId: string, source: ExtAppLookupSource): string | null {
|
|
23
|
+
const directId = toolCallId.startsWith('ext-app-') ? toolCallId : `ext-app-${toolCallId}`;
|
|
31
24
|
if (source.getNode(directId)) return directId;
|
|
32
25
|
|
|
33
|
-
const legacyDirectId = `ext-app-${toolCallId}`;
|
|
34
|
-
if (legacyDirectId !== directId && source.getNode(legacyDirectId)) {
|
|
35
|
-
return legacyDirectId;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
26
|
for (const node of source.listNodes()) {
|
|
39
|
-
if (
|
|
40
|
-
node.type === 'mcp-app' &&
|
|
41
|
-
node.data.mode === 'ext-app' &&
|
|
42
|
-
node.data.toolCallId === toolCallId
|
|
43
|
-
) {
|
|
27
|
+
if (node.type === 'mcp-app' && node.data.mode === 'ext-app' && node.data.toolCallId === toolCallId) {
|
|
44
28
|
return node.id;
|
|
45
29
|
}
|
|
46
30
|
}
|
|
@@ -34,11 +34,15 @@ function decodeHtmlEntities(value: string): string {
|
|
|
34
34
|
const lower = entity.toLowerCase();
|
|
35
35
|
if (lower.startsWith('#x')) {
|
|
36
36
|
const codePoint = Number.parseInt(lower.slice(2), 16);
|
|
37
|
-
return Number.isInteger(codePoint) && codePoint >= 0 && codePoint <= 0x10ffff
|
|
37
|
+
return Number.isInteger(codePoint) && codePoint >= 0 && codePoint <= 0x10ffff
|
|
38
|
+
? String.fromCodePoint(codePoint)
|
|
39
|
+
: match;
|
|
38
40
|
}
|
|
39
41
|
if (lower.startsWith('#')) {
|
|
40
42
|
const codePoint = Number.parseInt(lower.slice(1), 10);
|
|
41
|
-
return Number.isInteger(codePoint) && codePoint >= 0 && codePoint <= 0x10ffff
|
|
43
|
+
return Number.isInteger(codePoint) && codePoint >= 0 && codePoint <= 0x10ffff
|
|
44
|
+
? String.fromCodePoint(codePoint)
|
|
45
|
+
: match;
|
|
42
46
|
}
|
|
43
47
|
return named[lower] ?? match;
|
|
44
48
|
});
|
|
@@ -51,7 +55,10 @@ export function summarizeHtmlText(html: string): string | null {
|
|
|
51
55
|
.replace(/<style\b[\s\S]*?<\/style>/gi, ' ')
|
|
52
56
|
.replace(/<noscript\b[\s\S]*?<\/noscript>/gi, ' ');
|
|
53
57
|
const text = withoutNoise
|
|
54
|
-
.replace(
|
|
58
|
+
.replace(
|
|
59
|
+
/<(?:h[1-6]|p|li|br|div|section|article|header|footer|main|aside|summary|figcaption|blockquote|tr|td|th)\b[^>]*>/gi,
|
|
60
|
+
'\n',
|
|
61
|
+
)
|
|
55
62
|
.replace(/<[^>]+>/g, ' ');
|
|
56
63
|
const normalized = normalizeWhitespace(decodeHtmlEntities(text));
|
|
57
64
|
return normalized.length > 0 ? truncateText(normalized, HTML_CONTENT_SUMMARY_MAX_LENGTH) : null;
|
|
@@ -123,13 +130,15 @@ export function normalizeHtmlNodeSemanticData<T extends Record<string, unknown>>
|
|
|
123
130
|
].filter((value): value is string => value !== null);
|
|
124
131
|
const embeddedNodeIds = uniqueLimited([...explicitNodeIds, ...(html ? extractHtmlNodeIds(html) : [])]);
|
|
125
132
|
const embeddedUrls = uniqueLimited([...strings(data.embeddedUrls), ...(html ? extractHtmlUrls(html) : [])]);
|
|
126
|
-
const agentSummary =
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
const agentSummary =
|
|
134
|
+
pickString(data.agentSummary) ??
|
|
135
|
+
joinSummaryParts([
|
|
136
|
+
primitive ? `HTML primitive: ${primitive}` : '',
|
|
137
|
+
explicitSummary ?? '',
|
|
138
|
+
contentSummary ?? '',
|
|
139
|
+
embeddedNodeIds.length > 0 ? `Embedded canvas nodes: ${embeddedNodeIds.join(', ')}` : '',
|
|
140
|
+
embeddedUrls.length > 0 ? `Embedded URLs: ${embeddedUrls.join(', ')}` : '',
|
|
141
|
+
]);
|
|
133
142
|
|
|
134
143
|
return {
|
|
135
144
|
...base,
|