pmx-canvas 0.8.2 → 0.9.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/.github/extensions/pmx-canvas/runtime.json +1 -1
- package/.github/extensions/pmx-canvas/tools.json +601 -22
- package/CHANGELOG.md +49 -0
- package/Readme.md +131 -532
- package/dist/canvas/global.css +2724 -476
- package/dist/canvas/index.js +168 -107
- package/dist/canvas/mcp-app.html +2899 -596
- package/dist/json-render/index.js +20 -20
- package/dist/types/client/canvas/BarHint.d.ts +12 -2
- package/dist/types/client/canvas/BoardLinkDialog.d.ts +3 -1
- package/dist/types/client/canvas/BoardPinButton.d.ts +10 -0
- package/dist/types/client/canvas/BoardSwitcher.d.ts +1 -1
- package/dist/types/client/canvas/CanvasViewport.d.ts +1 -1
- package/dist/types/client/canvas/CommandBar.d.ts +3 -4
- package/dist/types/client/canvas/ConnectionBanner.d.ts +2 -1
- package/dist/types/client/canvas/ContextChip.d.ts +3 -0
- package/dist/types/client/canvas/CrossBoardReferences.d.ts +5 -0
- package/dist/types/client/canvas/EdgeLayer.d.ts +14 -3
- package/dist/types/client/canvas/EmptyState.d.ts +4 -4
- package/dist/types/client/canvas/HomeGraphView.d.ts +2 -0
- package/dist/types/client/canvas/HomeMapView.d.ts +1 -0
- package/dist/types/client/canvas/HomeReviewView.d.ts +6 -0
- package/dist/types/client/canvas/HomeView.d.ts +9 -7
- package/dist/types/client/canvas/KnowledgeDialog.d.ts +4 -0
- package/dist/types/client/canvas/LifecycleChrome.d.ts +5 -0
- package/dist/types/client/canvas/LifecycleFields.d.ts +7 -0
- package/dist/types/client/canvas/LifecyclePanel.d.ts +1 -0
- package/dist/types/client/canvas/MemoryInspector.d.ts +7 -0
- package/dist/types/client/canvas/NearPinLayer.d.ts +14 -0
- package/dist/types/client/canvas/NodeContextMark.d.ts +40 -7
- package/dist/types/client/canvas/RelationPresetsDialog.d.ts +4 -0
- package/dist/types/client/canvas/RelationsPanel.d.ts +4 -0
- package/dist/types/client/canvas/SessionPanel.d.ts +2 -0
- package/dist/types/client/canvas/canvas-area.d.ts +1 -1
- package/dist/types/client/canvas/graph-geometry.d.ts +27 -0
- package/dist/types/client/canvas/graph-model.d.ts +37 -0
- package/dist/types/client/canvas/memory-layout.d.ts +23 -0
- package/dist/types/client/canvas/use-chrome-height.d.ts +2 -0
- package/dist/types/client/canvas/use-focus-trap.d.ts +1 -0
- package/dist/types/client/canvas/use-memory-graph.d.ts +8 -0
- package/dist/types/client/canvas/use-pan-zoom.d.ts +4 -1
- package/dist/types/client/icons.d.ts +0 -10
- package/dist/types/client/nodes/AxStepControls.d.ts +1 -1
- package/dist/types/client/nodes/InlineMarkdownEditor.d.ts +4 -4
- package/dist/types/client/nodes/MarkdownNode.d.ts +5 -1
- package/dist/types/client/nodes/McpAppNode.d.ts +4 -4
- package/dist/types/client/nodes/viewer-runtime-state.d.ts +1 -1
- package/dist/types/client/state/boards-store.d.ts +81 -9
- package/dist/types/client/state/canvas-store.d.ts +14 -1
- package/dist/types/client/state/context-chip-store.d.ts +22 -0
- package/dist/types/client/state/context-status-store.d.ts +35 -0
- package/dist/types/client/state/intent-bridge.d.ts +11 -8
- package/dist/types/client/state/knowledge-store.d.ts +22 -0
- package/dist/types/client/state/near-pin-store.d.ts +44 -1
- package/dist/types/client/state/presence-store.d.ts +4 -4
- package/dist/types/client/state/presentation.d.ts +28 -0
- package/dist/types/client/state/relation-store.d.ts +10 -0
- package/dist/types/client/state/session-store.d.ts +41 -2
- package/dist/types/client/state/workspace-settings.d.ts +7 -0
- package/dist/types/client/types.d.ts +13 -1
- package/dist/types/client/utils/keyboard.d.ts +2 -0
- package/dist/types/client/utils/time-ago.d.ts +4 -0
- package/dist/types/mcp/context-uri-template.d.ts +3 -1
- package/dist/types/server/agent-presence.d.ts +10 -3
- package/dist/types/server/ax-context.d.ts +1 -1
- package/dist/types/server/canvas-db.d.ts +30 -7
- package/dist/types/server/canvas-operations.d.ts +24 -2
- package/dist/types/server/canvas-provenance.d.ts +22 -2
- package/dist/types/server/canvas-serialization.d.ts +2 -0
- package/dist/types/server/canvas-state.d.ts +93 -15
- package/dist/types/server/canvas-validation.d.ts +1 -1
- package/dist/types/server/context-brief.d.ts +94 -6
- package/dist/types/server/context-reads.d.ts +33 -7
- package/dist/types/server/edit-summary.d.ts +20 -0
- package/dist/types/server/index.d.ts +71 -10
- package/dist/types/server/knowledge-lifecycle.d.ts +221 -0
- package/dist/types/server/lifecycle-status.d.ts +10 -0
- package/dist/types/server/memory-graph.d.ts +9 -0
- package/dist/types/server/mutation-history.d.ts +2 -0
- package/dist/types/server/operations/ops/ax-shared.d.ts +1 -1
- package/dist/types/server/operations/ops/boards.d.ts +2 -1
- package/dist/types/server/operations/ops/lifecycle.d.ts +2 -0
- package/dist/types/server/operations/ops/memory-graph.d.ts +2 -0
- package/dist/types/server/operations/ops/nodes.d.ts +5 -0
- package/dist/types/server/operations/ops/query.d.ts +23 -0
- package/dist/types/server/operations/registry.d.ts +1 -0
- package/dist/types/server/placement.d.ts +7 -0
- package/dist/types/server/scope-fence.d.ts +2 -1
- package/dist/types/server/spatial-analysis.d.ts +6 -3
- package/dist/types/server/tour-control.d.ts +32 -0
- package/dist/types/server/wiki-links.d.ts +14 -0
- package/dist/types/server/workbench-auth.d.ts +2 -0
- package/dist/types/shared/agent-context.d.ts +2 -0
- package/dist/types/shared/agent-presence.d.ts +15 -12
- package/dist/types/shared/auto-arrange.d.ts +1 -0
- package/dist/types/shared/boards.d.ts +4 -4
- package/dist/types/shared/knowledge-lifecycle.d.ts +41 -0
- package/dist/types/shared/knowledge-presets.d.ts +6 -0
- package/dist/types/shared/lifecycle-status.d.ts +24 -0
- package/dist/types/shared/memory-graph.d.ts +53 -0
- package/dist/types/shared/relations.d.ts +68 -0
- package/dist/types/shared/semantic-attention.d.ts +2 -0
- package/dist/types/shared/tour.d.ts +38 -0
- package/dist/types/shared/workspace-settings.d.ts +11 -0
- package/docs/RELEASE.md +21 -3
- package/docs/adr-001-bun-only-runtime.md +7 -1
- package/docs/adr-002-shared-product-separate-runtimes.md +93 -0
- package/docs/api-reference.md +109 -0
- package/docs/ax-host-adapter-contract.md +1 -1
- package/docs/ax-state-contract.md +5 -4
- package/docs/cli.md +153 -15
- package/docs/demos/pmx-canvas-demo.mp4 +0 -0
- package/docs/design/AgentContext.dc.html +3 -3
- package/docs/design/BoardPins.dc.html +37 -22
- package/docs/design/Categories.dc.html +208 -0
- package/docs/design/CategoryEditor.dc.html +33 -0
- package/docs/design/Chrome.dc.html +52 -9
- package/docs/design/ContextChip.dc.html +224 -0
- package/docs/design/ContextChip600.dc.html +136 -0
- package/docs/design/EmptyState.dc.html +45 -0
- package/docs/design/Flows.dc.html +23 -1
- package/docs/design/HeaderMarks.dc.html +183 -0
- package/docs/design/Home.dc.html +19 -1
- package/docs/design/HomeGraph.dc.html +86 -202
- package/docs/design/HomeMap.dc.html +23 -1
- package/docs/design/HomeTeam.dc.html +32 -14
- package/docs/design/Lifecycle.dc.html +22 -0
- package/docs/design/Lifecycle600.dc.html +18 -0
- package/docs/design/LifecycleVariants.dc.html +157 -0
- package/docs/design/LinkAuthorship.dc.html +139 -0
- package/docs/design/LinksChanged.dc.html +203 -0
- package/docs/design/LinksOptions.dc.html +137 -0
- package/docs/design/LinksOptions600.dc.html +134 -0
- package/docs/design/NearPin.dc.html +9 -10
- package/docs/design/Pane600.dc.html +4 -3
- package/docs/design/Relations.dc.html +3 -2
- package/docs/design/Restore.dc.html +152 -0
- package/docs/design/SeeChange.dc.html +267 -0
- package/docs/design/Uses.dc.html +12 -6
- package/docs/design/canvas.json +146 -19
- package/docs/design.md +449 -16
- package/docs/environment.md +0 -1
- package/docs/evals/curation-effect.md +128 -0
- package/docs/http-api.md +459 -37
- package/docs/mcp.md +146 -18
- package/docs/node-types.md +58 -3
- package/docs/plans/design-gaps-2026-10-08.md +53 -0
- package/docs/plans/plan-009-tech-debt-backlog.md +379 -0
- package/docs/plans/plan-016-context-made-visible-wave-1.md +150 -5
- package/docs/plans/plan-017-knowledge-categories-and-lifecycle.md +175 -0
- package/docs/plans/plan-018-connected-memory-wave-2.md +594 -0
- package/docs/plans/plan-019-post-0.9-roadmap.md +198 -0
- package/docs/product-context-vision-2026-09.md +17 -1
- package/docs/product-vision-2026-09.md +1082 -43
- package/docs/product-vision-review-2026-09.md +13 -1
- package/docs/screenshots/workbench-live-dark.png +0 -0
- package/docs/screenshots/workbench-live-light.png +0 -0
- package/docs/sdk.md +62 -2
- package/package.json +1 -1
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
- package/plugins/pmx-canvas/plugin.json +1 -1
- package/plugins/pmx-canvas/runtime.json +1 -1
- package/plugins/pmx-canvas/tools.json +601 -22
- package/skills/pmx-canvas/SKILL.md +216 -42
- package/skills/pmx-canvas/references/full-reference.md +120 -21
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +2 -2
- package/skills/pmx-canvas/references/importing-context.md +132 -0
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
- package/skills/pmx-canvas/references/tours-and-recording.md +16 -1
- package/skills/pmx-canvas-testing/SKILL.md +20 -0
- package/src/cli/agent.ts +2 -0
- package/src/cli/commands/ax.ts +12 -0
- package/src/cli/commands/boards.ts +87 -11
- package/src/cli/commands/edges.ts +28 -0
- package/src/cli/commands/groups.ts +7 -0
- package/src/cli/commands/nodes.ts +1 -0
- package/src/cli/commands/query.ts +34 -2
- package/src/cli/commands/record.ts +199 -48
- package/src/cli/index.ts +6 -1
- package/src/client/App.tsx +177 -70
- package/src/client/canvas/AttentionHistory.tsx +0 -2
- package/src/client/canvas/BarHint.tsx +40 -2
- package/src/client/canvas/BoardCopyDialog.tsx +1 -1
- package/src/client/canvas/BoardFolderDialog.tsx +7 -7
- package/src/client/canvas/BoardLinkDialog.tsx +138 -33
- package/src/client/canvas/BoardPinButton.tsx +33 -0
- package/src/client/canvas/BoardSwitcher.tsx +26 -40
- package/src/client/canvas/CanvasNode.tsx +360 -237
- package/src/client/canvas/CanvasViewport.tsx +45 -7
- package/src/client/canvas/CommandBar.tsx +29 -23
- package/src/client/canvas/CommandPalette.tsx +5 -12
- package/src/client/canvas/ConnectionBanner.tsx +3 -3
- package/src/client/canvas/ContextChip.tsx +296 -0
- package/src/client/canvas/ContextMenu.tsx +63 -5
- package/src/client/canvas/CrossBoardReferences.tsx +60 -0
- package/src/client/canvas/EdgeLayer.tsx +339 -76
- package/src/client/canvas/EmptyState.tsx +33 -18
- package/src/client/canvas/ExpandedNodeOverlay.tsx +72 -40
- package/src/client/canvas/ExternalWriters.tsx +57 -42
- package/src/client/canvas/HomeGraphView.tsx +942 -0
- package/src/client/canvas/HomeMapView.tsx +641 -0
- package/src/client/canvas/HomeReviewView.tsx +167 -0
- package/src/client/canvas/HomeView.tsx +687 -160
- package/src/client/canvas/IntentLayer.tsx +19 -12
- package/src/client/canvas/KnowledgeDialog.tsx +488 -0
- package/src/client/canvas/LifecycleChrome.tsx +133 -0
- package/src/client/canvas/LifecycleFields.tsx +91 -0
- package/src/client/canvas/LifecyclePanel.tsx +533 -0
- package/src/client/canvas/MemoryInspector.tsx +104 -0
- package/src/client/canvas/Minimap.tsx +3 -3
- package/src/client/canvas/NearPinLayer.tsx +187 -0
- package/src/client/canvas/NodeContextMark.tsx +175 -97
- package/src/client/canvas/Presentation.tsx +23 -57
- package/src/client/canvas/RelationPresetsDialog.tsx +413 -0
- package/src/client/canvas/RelationsPanel.tsx +82 -0
- package/src/client/canvas/SelectionBar.tsx +3 -6
- package/src/client/canvas/SessionPanel.tsx +90 -50
- package/src/client/canvas/SessionReceipt.tsx +311 -39
- package/src/client/canvas/ShortcutOverlay.tsx +1 -1
- package/src/client/canvas/SnapshotPanel.tsx +27 -36
- package/src/client/canvas/ToolRail.tsx +367 -192
- package/src/client/canvas/TopBar.tsx +354 -124
- package/src/client/canvas/canvas-area.ts +10 -3
- package/src/client/canvas/graph-geometry.ts +195 -0
- package/src/client/canvas/graph-model.ts +254 -0
- package/src/client/canvas/memory-layout.ts +106 -0
- package/src/client/canvas/use-chrome-height.ts +20 -0
- package/src/client/canvas/use-focus-trap.ts +31 -5
- package/src/client/canvas/use-memory-graph.ts +58 -0
- package/src/client/canvas/use-node-drag.ts +2 -1
- package/src/client/canvas/use-pan-zoom.ts +64 -7
- package/src/client/icons.tsx +0 -63
- package/src/client/mcp-app/style.css +0 -6
- package/src/client/nodes/AxStepControls.tsx +74 -50
- package/src/client/nodes/BoardNode.tsx +5 -1
- package/src/client/nodes/ContextNode.tsx +18 -11
- package/src/client/nodes/ExtAppFrame.tsx +0 -1
- package/src/client/nodes/FileNode.tsx +46 -42
- package/src/client/nodes/HtmlNode.tsx +32 -0
- package/src/client/nodes/ImageNode.tsx +1 -1
- package/src/client/nodes/InlineFormatBar.tsx +6 -9
- package/src/client/nodes/InlineMarkdownEditor.tsx +56 -17
- package/src/client/nodes/MarkdownNode.tsx +377 -109
- package/src/client/nodes/McpAppNode.tsx +50 -20
- package/src/client/nodes/MdFormatBar.tsx +21 -18
- package/src/client/nodes/PromptNode.tsx +1 -1
- package/src/client/nodes/ResponseNode.tsx +1 -1
- package/src/client/nodes/viewer-runtime-state.ts +54 -22
- package/src/client/state/attention-bridge.ts +64 -15
- package/src/client/state/boards-store.ts +193 -39
- package/src/client/state/canvas-store.ts +99 -12
- package/src/client/state/context-chip-store.ts +70 -0
- package/src/client/state/context-status-store.ts +53 -0
- package/src/client/state/intent-bridge.ts +51 -30
- package/src/client/state/knowledge-store.ts +43 -0
- package/src/client/state/near-pin-store.ts +115 -6
- package/src/client/state/presence-store.ts +7 -10
- package/src/client/state/presentation.ts +91 -0
- package/src/client/state/relation-store.ts +81 -0
- package/src/client/state/session-store.ts +144 -18
- package/src/client/state/sse-bridge.ts +206 -29
- package/src/client/state/workspace-settings.ts +11 -0
- package/src/client/theme/global.css +2724 -476
- package/src/client/types.ts +12 -0
- package/src/client/utils/keyboard.ts +10 -0
- package/src/client/utils/time-ago.ts +14 -0
- package/src/json-render/renderer/index.tsx +31 -0
- package/src/mcp/canvas-app.ts +12 -2
- package/src/mcp/context-uri-template.ts +7 -4
- package/src/mcp/server.ts +63 -41
- package/src/mcp/workbench-app.ts +39 -6
- package/src/server/agent-presence.ts +128 -28
- package/src/server/ax-context.ts +27 -13
- package/src/server/board-export.ts +12 -1
- package/src/server/canvas-db.ts +331 -42
- package/src/server/canvas-operations.ts +195 -83
- package/src/server/canvas-provenance.ts +53 -22
- package/src/server/canvas-serialization.ts +2 -0
- package/src/server/canvas-state.ts +950 -122
- package/src/server/canvas-validation.ts +9 -2
- package/src/server/context-brief.ts +345 -38
- package/src/server/context-reads.ts +178 -30
- package/src/server/demo-state.json +355 -24
- package/src/server/edit-summary.ts +74 -0
- package/src/server/html-surface.ts +8 -1
- package/src/server/index.ts +181 -11
- package/src/server/knowledge-lifecycle.ts +304 -0
- package/src/server/lifecycle-status.ts +232 -0
- package/src/server/memory-graph.ts +166 -0
- package/src/server/mutation-history.ts +18 -6
- package/src/server/operations/composites.ts +32 -11
- package/src/server/operations/http.ts +7 -2
- package/src/server/operations/index.ts +4 -0
- package/src/server/operations/mcp.ts +26 -1
- package/src/server/operations/ops/ax-presence.ts +1 -1
- package/src/server/operations/ops/ax-read.ts +57 -6
- package/src/server/operations/ops/ax-timeline.ts +28 -2
- package/src/server/operations/ops/backup.ts +5 -3
- package/src/server/operations/ops/batch.ts +35 -4
- package/src/server/operations/ops/boards.ts +188 -47
- package/src/server/operations/ops/canvas-wire.ts +31 -1
- package/src/server/operations/ops/edges.ts +36 -2
- package/src/server/operations/ops/groups.ts +6 -1
- package/src/server/operations/ops/lifecycle.ts +262 -0
- package/src/server/operations/ops/memory-graph.ts +45 -0
- package/src/server/operations/ops/nodes.ts +107 -24
- package/src/server/operations/ops/query.ts +281 -68
- package/src/server/operations/ops/snapshots.ts +73 -1
- package/src/server/operations/ops/validate.ts +5 -1
- package/src/server/operations/ops/viewport.ts +97 -3
- package/src/server/operations/registry.ts +74 -25
- package/src/server/placement.ts +29 -0
- package/src/server/scope-fence.ts +78 -6
- package/src/server/server.ts +115 -16
- package/src/server/spatial-analysis.ts +48 -23
- package/src/server/tour-control.ts +82 -0
- package/src/server/wiki-links.ts +137 -0
- package/src/server/workbench-auth.ts +11 -0
- package/src/shared/agent-context.ts +3 -0
- package/src/shared/agent-presence.ts +15 -15
- package/src/shared/auto-arrange.ts +2 -0
- package/src/shared/boards.ts +4 -4
- package/src/shared/knowledge-lifecycle.ts +22 -0
- package/src/shared/knowledge-presets.ts +80 -0
- package/src/shared/lifecycle-status.ts +26 -0
- package/src/shared/memory-graph.ts +74 -0
- package/src/shared/relations.ts +98 -0
- package/src/shared/semantic-attention.ts +15 -1
- package/src/shared/tour.ts +23 -5
- package/src/shared/workspace-settings.ts +13 -0
- package/dist/types/client/canvas/ContextPinBar.d.ts +0 -1
- package/dist/types/client/canvas/FocusFieldLayer.d.ts +0 -1
- package/dist/types/client/canvas/kind-colors.d.ts +0 -3
- package/dist/types/server/agent-context.d.ts +0 -22
- package/src/client/canvas/ContextPinBar.tsx +0 -25
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { CanvasNodeState } from './canvas-state.js';
|
|
2
|
+
|
|
3
|
+
const ORDINALS = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth', 'ninth', 'tenth'];
|
|
4
|
+
/** "See change" shows this much of each side, centred on the first difference. */
|
|
5
|
+
export const CHANGE_EXCERPT = 1200;
|
|
6
|
+
|
|
7
|
+
export function cardText(node: CanvasNodeState): string {
|
|
8
|
+
const { content, text } = node.data;
|
|
9
|
+
return typeof content === 'string' ? content : typeof text === 'string' ? text : '';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function cardTitle(node: CanvasNodeState): string {
|
|
13
|
+
return typeof node.data.title === 'string' ? node.data.title : '';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const paragraphs = (text: string) =>
|
|
17
|
+
text
|
|
18
|
+
.split(/\n\s*\n/)
|
|
19
|
+
.map((paragraph) => paragraph.trim().replace(/\s+/g, ' '))
|
|
20
|
+
.filter(Boolean);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* What an agent's edit did to a card, in a few words, from the card before
|
|
24
|
+
* the session and now (AgentContext.dc.html: "rewrote the second paragraph").
|
|
25
|
+
* Paragraphs are aligned on their shared start and end, so a paragraph added
|
|
26
|
+
* at the top reads as added, not as everything rewritten.
|
|
27
|
+
*/
|
|
28
|
+
export function describeEdit(before: CanvasNodeState, after: CanvasNodeState): string {
|
|
29
|
+
const parts: string[] = [];
|
|
30
|
+
if (cardTitle(before) !== cardTitle(after)) parts.push(`renamed it “${cardTitle(after)}”`);
|
|
31
|
+
const was = cardText(before);
|
|
32
|
+
const now = cardText(after);
|
|
33
|
+
if (was !== now) {
|
|
34
|
+
const a = paragraphs(was);
|
|
35
|
+
const b = paragraphs(now);
|
|
36
|
+
let head = 0;
|
|
37
|
+
while (head < a.length && head < b.length && a[head] === b[head]) head += 1;
|
|
38
|
+
let tail = 0;
|
|
39
|
+
while (tail < a.length - head && tail < b.length - head && a[a.length - 1 - tail] === b[b.length - 1 - tail])
|
|
40
|
+
tail += 1;
|
|
41
|
+
const removed = a.length - head - tail;
|
|
42
|
+
const added = b.length - head - tail;
|
|
43
|
+
const count = (n: number) => `${n} paragraph${n === 1 ? '' : 's'}`;
|
|
44
|
+
if (removed === 0 && added === 0) parts.push('reformatted its text');
|
|
45
|
+
else if (a.length === 0) parts.push('wrote its text');
|
|
46
|
+
else if (b.length === 0) parts.push('cleared its text');
|
|
47
|
+
else if (removed === 0) parts.push(`added ${count(added)}`);
|
|
48
|
+
else if (added === 0) parts.push(`removed ${count(removed)}`);
|
|
49
|
+
else if (removed === 1 && added === 1) parts.push(`rewrote the ${ORDINALS[head] ?? `#${head + 1}`} paragraph`);
|
|
50
|
+
else if (Math.max(removed, added) > Math.max(a.length, b.length) / 2) parts.push('rewrote most of it');
|
|
51
|
+
else parts.push(`changed ${count(Math.max(removed, added))} of ${Math.max(a.length, b.length)}`);
|
|
52
|
+
}
|
|
53
|
+
return parts.join(' and ') || 'changed its settings';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Before and after for "See change": each side cut to CHANGE_EXCERPT around
|
|
58
|
+
* the first character that differs, with "…" where text was cut, so a change
|
|
59
|
+
* deep in a long card is what shows.
|
|
60
|
+
*/
|
|
61
|
+
export function changeExcerpts(was: string, now: string): { before: string; after: string } {
|
|
62
|
+
let at = 0;
|
|
63
|
+
while (at < was.length && at < now.length && was[at] === now[at]) at += 1;
|
|
64
|
+
const from = Math.max(0, at - Math.floor(CHANGE_EXCERPT / 4));
|
|
65
|
+
// Never cut between the two halves of a surrogate pair (an emoji).
|
|
66
|
+
const low = (text: string, index: number) => /[\uDC00-\uDFFF]/.test(text[index] ?? '');
|
|
67
|
+
const cut = (text: string) => {
|
|
68
|
+
const start = low(text, from) ? from - 1 : from;
|
|
69
|
+
let end = start + CHANGE_EXCERPT;
|
|
70
|
+
if (low(text, end)) end -= 1;
|
|
71
|
+
return `${start > 0 ? '…' : ''}${text.slice(start, end)}${end < text.length ? '…' : ''}`;
|
|
72
|
+
};
|
|
73
|
+
return { before: cut(was), after: cut(now) };
|
|
74
|
+
}
|
|
@@ -60,7 +60,14 @@ function buildThemeBridge(themeToken: string): string {
|
|
|
60
60
|
const PMX_CANVAS_THEME_TOKEN = ${token};
|
|
61
61
|
window.addEventListener('message', (event) => {
|
|
62
62
|
const message = event.data;
|
|
63
|
-
if (!message || message.source !== '${HTML_SURFACE_PUSH_SOURCE}' || message.
|
|
63
|
+
if (event.source !== window.parent || !message || message.source !== '${HTML_SURFACE_PUSH_SOURCE}' || message.token !== PMX_CANVAS_THEME_TOKEN) return;
|
|
64
|
+
if (message.type === 'check-ready') {
|
|
65
|
+
const reply = (type) => window.parent.postMessage({ source: '${HTML_SURFACE_PUSH_SOURCE}', type, token: PMX_CANVAS_THEME_TOKEN }, '*');
|
|
66
|
+
reply('mounted');
|
|
67
|
+
requestAnimationFrame(() => requestAnimationFrame(() => reply('ready')));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (message.type !== 'theme-update') return;
|
|
64
71
|
if (typeof message.theme !== 'string') return;
|
|
65
72
|
document.documentElement.setAttribute('data-pmx-canvas-theme', message.theme);
|
|
66
73
|
document.documentElement.setAttribute('data-theme', message.theme);
|
package/src/server/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
|
-
import { derivedTour, type Tour } from '../shared/tour.js';
|
|
2
|
+
import { derivedTour, type Camera, type Tour, type TourStop } from '../shared/tour.js';
|
|
3
|
+
import { exitTour, goToTourStop, moveCamera, type TourStep, type TourStepResult } from './tour-control.js';
|
|
3
4
|
export type { Tour, TourStop } from '../shared/tour.js';
|
|
5
|
+
export type { TourStep, TourStepResult } from './tour-control.js';
|
|
4
6
|
import { agentPresence } from './agent-presence.js';
|
|
5
7
|
import { checkFenceTarget, type FenceTarget } from './scope-fence.js';
|
|
6
8
|
import type { AgentPhase, AgentPresence, AgentPresenceSnapshot } from '../shared/agent-presence.js';
|
|
@@ -38,6 +40,7 @@ import type {
|
|
|
38
40
|
PmxAxWorkItemStatus,
|
|
39
41
|
} from './ax-state.js';
|
|
40
42
|
import type { AxTimelineQuery, CanvasBoard } from './canvas-db.js';
|
|
43
|
+
import type { MemoryGraph } from '../shared/memory-graph.js';
|
|
41
44
|
import type { Attachment, DocumentImport, ImportSection } from './document-import.js';
|
|
42
45
|
import { workbenchToken } from './workbench-auth.js';
|
|
43
46
|
import type { BackupFile, BackupStatus } from './backup.js';
|
|
@@ -45,7 +48,8 @@ import type { ExportManifest } from './board-export.js';
|
|
|
45
48
|
import { onFileNodeChanged } from './file-watcher.js';
|
|
46
49
|
import { findOpenCanvasPosition, computeGroupBounds } from './placement.js';
|
|
47
50
|
import { overlapsAny } from '../shared/placement.js';
|
|
48
|
-
import {
|
|
51
|
+
import { buildSpatialContext } from './spatial-analysis.js';
|
|
52
|
+
import { searchCanvasNodes } from './operations/ops/query.js';
|
|
49
53
|
import { mutationHistory, diffLayouts, formatDiff } from './mutation-history.js';
|
|
50
54
|
import { recomputeCodeGraph, buildCodeGraphSummary, formatCodeGraph } from './code-graph.js';
|
|
51
55
|
import {
|
|
@@ -75,10 +79,12 @@ import {
|
|
|
75
79
|
import {
|
|
76
80
|
buildNodePatch,
|
|
77
81
|
createBasicCanvasNode,
|
|
82
|
+
createDestinationNode,
|
|
78
83
|
removeNodeCore,
|
|
79
84
|
setGroupChildrenFromApi,
|
|
80
85
|
} from './operations/ops/nodes.js';
|
|
81
86
|
import { streamJsonRenderCore } from './operations/ops/json-render.js';
|
|
87
|
+
import { boardsPayload } from './operations/ops/boards.js';
|
|
82
88
|
import { executeOperation, runCanvasBatchOperation, type OpenMcpAppCoreResult } from './operations/index.js';
|
|
83
89
|
import { validateCanvasLayout } from './canvas-validation.js';
|
|
84
90
|
import { describeCanvasSchema, validateStructuredCanvasPayload } from './canvas-schema.js';
|
|
@@ -289,10 +295,14 @@ export class PmxCanvas extends EventEmitter {
|
|
|
289
295
|
* or keep the whole node — both work. (Previously returned a bare id string.)
|
|
290
296
|
*/
|
|
291
297
|
addNode(input: {
|
|
298
|
+
destinationBoardId?: string;
|
|
299
|
+
requestId?: string;
|
|
300
|
+
expectedBoardId?: string | null;
|
|
292
301
|
intentId?: string;
|
|
293
302
|
type: CanvasNodeState['type'];
|
|
294
303
|
title?: string;
|
|
295
304
|
content?: string;
|
|
305
|
+
data?: Record<string, unknown>;
|
|
296
306
|
children?: string[];
|
|
297
307
|
childIds?: string[];
|
|
298
308
|
childLayout?: 'grid' | 'column' | 'flow';
|
|
@@ -309,6 +319,19 @@ export class PmxCanvas extends EventEmitter {
|
|
|
309
319
|
height?: number;
|
|
310
320
|
strictSize?: boolean;
|
|
311
321
|
}): SdkCanvasNode {
|
|
322
|
+
if (input.expectedBoardId !== undefined && input.expectedBoardId !== canvasState.activeBoardId)
|
|
323
|
+
throw new Error('The active board changed. Refresh before retrying this action.');
|
|
324
|
+
if (input.destinationBoardId !== undefined || input.requestId !== undefined) {
|
|
325
|
+
const revision = canvasState.getContentRevision().revision;
|
|
326
|
+
const node = createDestinationNode(input);
|
|
327
|
+
if (
|
|
328
|
+
(input.destinationBoardId ?? canvasState.activeBoardId) === canvasState.activeBoardId ||
|
|
329
|
+
revision !== canvasState.getContentRevision().revision
|
|
330
|
+
)
|
|
331
|
+
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
332
|
+
emitPrimaryWorkbenchEvent('boards-changed', boardsPayload());
|
|
333
|
+
return toSdkNode(node);
|
|
334
|
+
}
|
|
312
335
|
assertInsideFence(
|
|
313
336
|
'node.add',
|
|
314
337
|
createTarget(input, input.type === 'group' ? (input.childIds ?? input.children ?? []) : []),
|
|
@@ -442,17 +465,41 @@ export class PmxCanvas extends EventEmitter {
|
|
|
442
465
|
}
|
|
443
466
|
|
|
444
467
|
addEdge(input: {
|
|
468
|
+
destinationBoardId?: string;
|
|
469
|
+
requestId?: string;
|
|
470
|
+
expectedBoardId?: string | null;
|
|
445
471
|
intentId?: string;
|
|
446
472
|
from?: string;
|
|
447
473
|
to?: string;
|
|
474
|
+
toBoardId?: string;
|
|
448
475
|
fromSearch?: string;
|
|
449
476
|
toSearch?: string;
|
|
450
477
|
type: CanvasEdge['type'];
|
|
478
|
+
kind?: string;
|
|
479
|
+
reason?: string;
|
|
451
480
|
label?: string;
|
|
452
481
|
style?: CanvasEdge['style'];
|
|
453
482
|
animated?: boolean;
|
|
454
483
|
}): string {
|
|
455
|
-
|
|
484
|
+
if (input.expectedBoardId !== undefined && input.expectedBoardId !== canvasState.activeBoardId)
|
|
485
|
+
throw new Error('The active board changed. Refresh before retrying this action.');
|
|
486
|
+
if (input.destinationBoardId !== undefined || input.requestId !== undefined) {
|
|
487
|
+
const revision = canvasState.getContentRevision().revision;
|
|
488
|
+
const edge = addCanvasEdge(input);
|
|
489
|
+
if (
|
|
490
|
+
(input.destinationBoardId ?? canvasState.activeBoardId) === canvasState.activeBoardId ||
|
|
491
|
+
revision !== canvasState.getContentRevision().revision
|
|
492
|
+
)
|
|
493
|
+
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
494
|
+
emitPrimaryWorkbenchEvent('boards-changed', boardsPayload());
|
|
495
|
+
return edge.id;
|
|
496
|
+
}
|
|
497
|
+
assertInsideFence('edge.add', {
|
|
498
|
+
nodeIds:
|
|
499
|
+
input.toBoardId && input.toBoardId !== canvasState.activeBoardId
|
|
500
|
+
? [input.from ?? '']
|
|
501
|
+
: [input.from ?? '', input.to ?? ''],
|
|
502
|
+
});
|
|
456
503
|
return this.runIntentCommit(
|
|
457
504
|
input.intentId,
|
|
458
505
|
['connect'],
|
|
@@ -465,6 +512,13 @@ export class PmxCanvas extends EventEmitter {
|
|
|
465
512
|
);
|
|
466
513
|
}
|
|
467
514
|
|
|
515
|
+
async updateEdge(
|
|
516
|
+
id: string,
|
|
517
|
+
patch: Partial<Pick<CanvasEdge, 'type' | 'kind' | 'reason' | 'label' | 'style' | 'animated'>>,
|
|
518
|
+
): Promise<CanvasEdge> {
|
|
519
|
+
return (await executeOperation('edge.update', { id, ...patch }, { source: 'sdk' })) as CanvasEdge;
|
|
520
|
+
}
|
|
521
|
+
|
|
468
522
|
addAnnotation(input: Omit<CanvasAnnotation, 'id' | 'createdAt'> & { id?: string; createdAt?: string }): string {
|
|
469
523
|
const id = input.id ?? `ann-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
470
524
|
canvasState.addAnnotation({
|
|
@@ -484,7 +538,8 @@ export class PmxCanvas extends EventEmitter {
|
|
|
484
538
|
|
|
485
539
|
removeEdge(id: string): void {
|
|
486
540
|
const edge = canvasState.getEdges().find((entry) => entry.id === id);
|
|
487
|
-
if (edge)
|
|
541
|
+
if (edge)
|
|
542
|
+
assertInsideFence('edge.remove', { nodeIds: edge.toBoardId !== undefined ? [edge.from] : [edge.from, edge.to] });
|
|
488
543
|
removeCanvasEdge(id);
|
|
489
544
|
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
490
545
|
}
|
|
@@ -494,6 +549,9 @@ export class PmxCanvas extends EventEmitter {
|
|
|
494
549
|
* If childIds are provided, the group auto-sizes to contain them with padding.
|
|
495
550
|
*/
|
|
496
551
|
createGroup(input: {
|
|
552
|
+
destinationBoardId?: string;
|
|
553
|
+
requestId?: string;
|
|
554
|
+
expectedBoardId?: string | null;
|
|
497
555
|
intentId?: string;
|
|
498
556
|
title?: string;
|
|
499
557
|
childIds?: string[];
|
|
@@ -504,6 +562,19 @@ export class PmxCanvas extends EventEmitter {
|
|
|
504
562
|
color?: string;
|
|
505
563
|
childLayout?: 'grid' | 'column' | 'flow';
|
|
506
564
|
}): string {
|
|
565
|
+
if (input.expectedBoardId !== undefined && input.expectedBoardId !== canvasState.activeBoardId)
|
|
566
|
+
throw new Error('The active board changed. Refresh before retrying this action.');
|
|
567
|
+
if (input.destinationBoardId !== undefined || input.requestId !== undefined) {
|
|
568
|
+
const revision = canvasState.getContentRevision().revision;
|
|
569
|
+
const { id } = createCanvasGroup(input);
|
|
570
|
+
if (
|
|
571
|
+
(input.destinationBoardId ?? canvasState.activeBoardId) === canvasState.activeBoardId ||
|
|
572
|
+
revision !== canvasState.getContentRevision().revision
|
|
573
|
+
)
|
|
574
|
+
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
575
|
+
emitPrimaryWorkbenchEvent('boards-changed', boardsPayload());
|
|
576
|
+
return id;
|
|
577
|
+
}
|
|
507
578
|
assertInsideFence('group.create', { nodeIds: input.childIds ?? [] });
|
|
508
579
|
return this.runIntentCommit(
|
|
509
580
|
input.intentId,
|
|
@@ -571,6 +642,26 @@ export class PmxCanvas extends EventEmitter {
|
|
|
571
642
|
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
572
643
|
}
|
|
573
644
|
|
|
645
|
+
/** Present a tour stop (index, `next` or `previous`) in the workbench. Not recorded in undo history. */
|
|
646
|
+
goToTourStop(step: TourStep, options?: { present?: boolean }): TourStepResult {
|
|
647
|
+
const result = goToTourStop(step);
|
|
648
|
+
emitPrimaryWorkbenchEvent('canvas-tour-step', { ...result, present: options?.present !== false });
|
|
649
|
+
return result;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/** Leave presentation in every viewer. */
|
|
653
|
+
exitTour(): void {
|
|
654
|
+
exitTour();
|
|
655
|
+
emitPrimaryWorkbenchEvent('canvas-tour-exit', {});
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/** Ease the camera to a node, world rect or viewport. Not recorded in undo history. */
|
|
659
|
+
moveCamera(stop: TourStop): { viewport: Camera } {
|
|
660
|
+
const result = moveCamera(stop);
|
|
661
|
+
emitPrimaryWorkbenchEvent('canvas-camera-move', result);
|
|
662
|
+
return { viewport: result.viewport };
|
|
663
|
+
}
|
|
664
|
+
|
|
574
665
|
clear(): void {
|
|
575
666
|
assertInsideFence('canvas.clear', { boardWide: true });
|
|
576
667
|
for (const node of canvasState.getLayout().nodes) {
|
|
@@ -805,10 +896,10 @@ export class PmxCanvas extends EventEmitter {
|
|
|
805
896
|
)) as { import: DocumentImport; nodeIds: string[] };
|
|
806
897
|
}
|
|
807
898
|
|
|
808
|
-
async createBoard(name: string,
|
|
899
|
+
async createBoard(name: string, folder?: string): Promise<CanvasBoard> {
|
|
809
900
|
const result = (await executeOperation(
|
|
810
901
|
'board.create',
|
|
811
|
-
{ name, ...(
|
|
902
|
+
{ name, ...(folder ? { folder } : {}) },
|
|
812
903
|
{ source: 'sdk' },
|
|
813
904
|
)) as {
|
|
814
905
|
board: CanvasBoard;
|
|
@@ -816,8 +907,27 @@ export class PmxCanvas extends EventEmitter {
|
|
|
816
907
|
return result.board;
|
|
817
908
|
}
|
|
818
909
|
|
|
819
|
-
/**
|
|
820
|
-
async
|
|
910
|
+
/** Workspace category and folder actions do not open a board. */
|
|
911
|
+
async knowledge<T extends import('./knowledge-lifecycle.js').KnowledgeInput>(
|
|
912
|
+
input: T,
|
|
913
|
+
): Promise<import('./knowledge-lifecycle.js').KnowledgeResults[T['action']]> {
|
|
914
|
+
const { action, ...payload } = input;
|
|
915
|
+
return (await executeOperation(`knowledge.${action}`, payload, {
|
|
916
|
+
source: 'sdk',
|
|
917
|
+
})) as import('./knowledge-lifecycle.js').KnowledgeResults[T['action']];
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
async lifecycle<T extends import('./knowledge-lifecycle.js').LifecycleInput>(
|
|
921
|
+
input: T,
|
|
922
|
+
): Promise<import('./knowledge-lifecycle.js').LifecycleResults[T['action']]> {
|
|
923
|
+
const { action, ...payload } = input;
|
|
924
|
+
return (await executeOperation(action === 'review' ? 'node.review' : `node.lifecycle-${action}`, payload, {
|
|
925
|
+
source: 'sdk',
|
|
926
|
+
})) as import('./knowledge-lifecycle.js').LifecycleResults[T['action']];
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
/** Rename a board and/or file it under a folder (`folder: null` unfiles it). */
|
|
930
|
+
async updateBoard(id: string, patch: Parameters<typeof canvasState.updateBoard>[1]): Promise<void> {
|
|
821
931
|
await executeOperation('board.update', { id, ...patch }, { source: 'sdk' });
|
|
822
932
|
}
|
|
823
933
|
|
|
@@ -825,10 +935,19 @@ export class PmxCanvas extends EventEmitter {
|
|
|
825
935
|
await executeOperation('board.update', { id, readmeNodeId }, { source: 'sdk' });
|
|
826
936
|
}
|
|
827
937
|
|
|
938
|
+
/** Pin a board into the agent's working set (its README and pinned cards reach every brief). */
|
|
939
|
+
async pinBoard(id: string, reason?: string): Promise<void> {
|
|
940
|
+
await executeOperation('board.pin', { id, ...(reason ? { reason } : {}) }, { source: 'sdk' });
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
async unpinBoard(id: string): Promise<void> {
|
|
944
|
+
await executeOperation('board.unpin', { id }, { source: 'sdk' });
|
|
945
|
+
}
|
|
946
|
+
|
|
828
947
|
async createBoardFrom(input: {
|
|
829
948
|
sourceBoardId: string;
|
|
830
949
|
name: string;
|
|
831
|
-
|
|
950
|
+
folder?: string;
|
|
832
951
|
nodeIds?: string[];
|
|
833
952
|
includeReadme?: boolean;
|
|
834
953
|
includeStructure?: boolean;
|
|
@@ -844,6 +963,13 @@ export class PmxCanvas extends EventEmitter {
|
|
|
844
963
|
>;
|
|
845
964
|
}
|
|
846
965
|
|
|
966
|
+
/** Same projection as Home Graph. Discovery summaries never count as full-content reads. */
|
|
967
|
+
async getMemoryGraph(
|
|
968
|
+
options: { focus?: string; depth?: number; projection?: 'full' | 'boards' } = {},
|
|
969
|
+
): Promise<MemoryGraph> {
|
|
970
|
+
return (await executeOperation('memory-graph.get', options, { source: 'sdk' })) as MemoryGraph;
|
|
971
|
+
}
|
|
972
|
+
|
|
847
973
|
/** Budgeted cross-board brief. Budget is measured in UTF-16 characters. */
|
|
848
974
|
async getContextBrief(
|
|
849
975
|
options: { consumer?: string; since?: number; budget?: number } = {},
|
|
@@ -912,6 +1038,11 @@ export class PmxCanvas extends EventEmitter {
|
|
|
912
1038
|
return canvasState.getNodeReadStatus(board ?? canvasState.activeBoardId);
|
|
913
1039
|
}
|
|
914
1040
|
|
|
1041
|
+
/** A board's latest agent read of any kind (a pinned board's map counts), or null. */
|
|
1042
|
+
getBoardLastRead(board?: string): ReturnType<typeof canvasState.getBoardLastRead> {
|
|
1043
|
+
return canvasState.getBoardLastRead(board ?? canvasState.activeBoardId);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
915
1046
|
listWorkItems(): PmxAxWorkItem[] {
|
|
916
1047
|
return canvasState.getWorkItems();
|
|
917
1048
|
}
|
|
@@ -1279,8 +1410,11 @@ export class PmxCanvas extends EventEmitter {
|
|
|
1279
1410
|
return result;
|
|
1280
1411
|
}
|
|
1281
1412
|
|
|
1282
|
-
search(
|
|
1283
|
-
|
|
1413
|
+
search(
|
|
1414
|
+
query: string,
|
|
1415
|
+
options: { scope?: 'active' | 'library'; boardId?: string; folder?: string; limit?: number } = {},
|
|
1416
|
+
) {
|
|
1417
|
+
return searchCanvasNodes(query, options).results;
|
|
1284
1418
|
}
|
|
1285
1419
|
|
|
1286
1420
|
getSpatialContext() {
|
|
@@ -1293,6 +1427,10 @@ export class PmxCanvas extends EventEmitter {
|
|
|
1293
1427
|
if (!entry) return { ok: false, description: 'Nothing to undo' };
|
|
1294
1428
|
await syncCanvasRuntimeBackends();
|
|
1295
1429
|
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
1430
|
+
emitPrimaryWorkbenchEvent('context-pins-changed', {
|
|
1431
|
+
count: canvasState.contextPinnedNodeIds.size,
|
|
1432
|
+
nodeIds: Array.from(canvasState.contextPinnedNodeIds),
|
|
1433
|
+
});
|
|
1296
1434
|
// Undo can reverse an AX mutation (work item, focus, …); nudge AX surfaces to
|
|
1297
1435
|
// re-fetch so a live board reflects the reversal (debounced client-side).
|
|
1298
1436
|
emitPrimaryWorkbenchEvent('ax-state-changed', {});
|
|
@@ -1304,6 +1442,10 @@ export class PmxCanvas extends EventEmitter {
|
|
|
1304
1442
|
if (!entry) return { ok: false, description: 'Nothing to redo' };
|
|
1305
1443
|
await syncCanvasRuntimeBackends();
|
|
1306
1444
|
emitPrimaryWorkbenchEvent('canvas-layout-update', { layout: canvasState.getLayout() });
|
|
1445
|
+
emitPrimaryWorkbenchEvent('context-pins-changed', {
|
|
1446
|
+
count: canvasState.contextPinnedNodeIds.size,
|
|
1447
|
+
nodeIds: Array.from(canvasState.contextPinnedNodeIds),
|
|
1448
|
+
});
|
|
1307
1449
|
emitPrimaryWorkbenchEvent('ax-state-changed', {});
|
|
1308
1450
|
return { ok: true, description: `Redid: ${entry.description}` };
|
|
1309
1451
|
}
|
|
@@ -1359,6 +1501,24 @@ export class PmxCanvas extends EventEmitter {
|
|
|
1359
1501
|
return result;
|
|
1360
1502
|
}
|
|
1361
1503
|
|
|
1504
|
+
/** Put one card back to its content in a snapshot (the receipt's Undo on an edit). */
|
|
1505
|
+
async restoreSnapshotNode(
|
|
1506
|
+
snapshotId: string,
|
|
1507
|
+
nodeId: string,
|
|
1508
|
+
options: { preserveHumanEdits?: boolean } = {},
|
|
1509
|
+
): Promise<{ ok: boolean; id: string; restored: boolean; skipped?: 'human-edit' }> {
|
|
1510
|
+
return (await executeOperation(
|
|
1511
|
+
'snapshot.restore-node',
|
|
1512
|
+
{ id: snapshotId, nodeId, ...options },
|
|
1513
|
+
{ source: 'sdk' },
|
|
1514
|
+
)) as {
|
|
1515
|
+
ok: boolean;
|
|
1516
|
+
id: string;
|
|
1517
|
+
restored: boolean;
|
|
1518
|
+
skipped?: 'human-edit';
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1362
1522
|
deleteSnapshot(id: string): { ok: boolean } {
|
|
1363
1523
|
return deleteCanvasSnapshot(id);
|
|
1364
1524
|
}
|
|
@@ -1779,3 +1939,13 @@ export type {
|
|
|
1779
1939
|
PmxAxWorkItemStatus,
|
|
1780
1940
|
} from './ax-state.js';
|
|
1781
1941
|
export type { AxTimelineQuery } from './canvas-db.js';
|
|
1942
|
+
export type {
|
|
1943
|
+
Lifecycle,
|
|
1944
|
+
KnowledgeCategory,
|
|
1945
|
+
FolderProperties,
|
|
1946
|
+
ReviewRecord,
|
|
1947
|
+
KnowledgeInput,
|
|
1948
|
+
KnowledgeResults,
|
|
1949
|
+
LifecycleInput,
|
|
1950
|
+
LifecycleResults,
|
|
1951
|
+
} from './knowledge-lifecycle.js';
|