pmx-canvas 0.9.2 → 0.10.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/extension.mjs +9 -3
- package/.github/extensions/pmx-canvas/runtime.json +1 -1
- package/.github/extensions/pmx-canvas/tools.json +9278 -2014
- package/CHANGELOG.md +34 -1
- package/dist/canvas/global.css +12 -17
- package/dist/canvas/index.js +58 -58
- package/dist/canvas/mcp-app.html +75 -80
- package/dist/types/client/canvas/submit-without-navigation.d.ts +3 -0
- package/dist/types/client/state/intent-bridge.d.ts +0 -3
- package/dist/types/client/state/presence-store.d.ts +3 -3
- package/dist/types/client/types.d.ts +1 -1
- package/dist/types/mcp/canvas-access.d.ts +1 -12
- package/dist/types/mcp/resource-subscriptions.d.ts +7 -0
- package/dist/types/mcp/server.d.ts +2 -0
- package/dist/types/server/ax-wait.d.ts +1 -0
- package/dist/types/server/canvas-operations.d.ts +1 -0
- package/dist/types/server/canvas-state.d.ts +2 -0
- package/dist/types/server/index.d.ts +5 -5
- package/dist/types/server/knowledge-lifecycle.d.ts +11 -2
- package/dist/types/server/lifecycle-status.d.ts +3 -1
- package/dist/types/server/operations/http.d.ts +10 -0
- package/dist/types/server/operations/index.d.ts +2 -2
- package/dist/types/server/operations/invoker.d.ts +4 -3
- package/dist/types/server/operations/mcp-contracts.d.ts +20 -0
- package/dist/types/server/operations/mcp.d.ts +2 -0
- package/dist/types/server/operations/ops/batch.d.ts +1 -0
- package/dist/types/server/operations/registry.d.ts +2 -2
- package/dist/types/server/operations/types.d.ts +12 -2
- package/dist/types/server/server.d.ts +2 -0
- package/dist/types/server/tour-control.d.ts +6 -3
- package/dist/types/server/webpage-node.d.ts +1 -0
- package/docs/api-reference.md +2 -2
- package/docs/cli.md +10 -1
- package/docs/design/Chrome.dc.html +1 -0
- package/docs/design.md +3 -1
- package/docs/http-api.md +31 -0
- package/docs/mcp.md +98 -22
- package/docs/node-types.md +3 -0
- package/docs/plans/plan-019-post-0.9-roadmap.md +187 -11
- package/docs/sdk.md +10 -0
- package/package.json +1 -1
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/extension.mjs +9 -3
- 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 +9278 -2014
- package/skills/pmx-canvas/SKILL.md +12 -7
- package/skills/pmx-canvas/references/full-reference.md +35 -2
- package/skills/pmx-canvas/references/github-copilot-app-adapter.md +2 -2
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +7 -7
- package/src/client/canvas/BoardCopyDialog.tsx +2 -1
- package/src/client/canvas/KnowledgeDialog.tsx +3 -0
- package/src/client/canvas/LifecyclePanel.tsx +4 -0
- package/src/client/canvas/RelationPresetsDialog.tsx +2 -0
- package/src/client/canvas/ToolRail.tsx +2 -0
- package/src/client/canvas/submit-without-navigation.ts +14 -0
- package/src/client/state/canvas-store.ts +12 -24
- package/src/client/state/intent-bridge.ts +0 -6
- package/src/client/state/presence-store.ts +3 -3
- package/src/client/state/sse-bridge.ts +11 -6
- package/src/client/theme/global.css +12 -17
- package/src/mcp/canvas-access.ts +6 -47
- package/src/mcp/resource-subscriptions.ts +181 -0
- package/src/mcp/server.ts +185 -219
- package/src/server/ax-wait.ts +21 -6
- package/src/server/canvas-operations.ts +6 -2
- package/src/server/canvas-state.ts +10 -0
- package/src/server/index.ts +20 -32
- package/src/server/knowledge-lifecycle.ts +66 -0
- package/src/server/lifecycle-status.ts +79 -7
- package/src/server/operations/http.ts +69 -21
- package/src/server/operations/index.ts +8 -1
- package/src/server/operations/invoker.ts +53 -5
- package/src/server/operations/mcp-contracts.ts +339 -0
- package/src/server/operations/mcp.ts +153 -18
- package/src/server/operations/ops/ax-await.ts +18 -10
- package/src/server/operations/ops/ax-read.ts +2 -0
- package/src/server/operations/ops/ax-timeline.ts +2 -2
- package/src/server/operations/ops/batch.ts +27 -8
- package/src/server/operations/ops/lifecycle.ts +3 -7
- package/src/server/operations/ops/nodes.ts +20 -8
- package/src/server/operations/ops/viewport.ts +3 -7
- package/src/server/operations/registry.ts +24 -4
- package/src/server/operations/types.ts +16 -2
- package/src/server/server.ts +23 -10
- package/src/server/tour-control.ts +17 -8
- package/src/server/webpage-node.ts +9 -4
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { AgentPresenceSnapshot } from '../../shared/agent-presence.js';
|
|
2
1
|
import type { CanvasNodeState } from '../types';
|
|
3
2
|
/**
|
|
4
3
|
* Per-tab identity: an AGENT driving the workbench UI from its own pane opens
|
|
@@ -156,8 +155,6 @@ export interface AxInteractionResponse {
|
|
|
156
155
|
}
|
|
157
156
|
/** Fetch the compact AX state snapshot pushed into AX-enabled surfaces. */
|
|
158
157
|
export declare function fetchAxSurfaceState(): Promise<unknown>;
|
|
159
|
-
/** Connect-time agent-presence read; live updates arrive as `agent-presence` SSE frames. */
|
|
160
|
-
export declare function fetchAgentPresence(): Promise<Partial<AgentPresenceSnapshot> | null>;
|
|
161
158
|
/** Ask the server to open a node's surface in the system browser. */
|
|
162
159
|
export declare function openNodeInSystemBrowserRequest(nodeId: string, url?: string): Promise<{
|
|
163
160
|
ok: boolean;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { PmxAxIntent } from '../../shared/ax-intent.js';
|
|
2
2
|
import { type AgentActivityEntry, type AgentPresence, type AgentPresenceSnapshot } from '../../shared/agent-presence.js';
|
|
3
3
|
/**
|
|
4
|
-
* Agent presence (rail-chrome-v2 phase 2). Fed by the server's
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Agent presence (rail-chrome-v2 phase 2). Fed by the server's ordered
|
|
5
|
+
* `agent-presence` frames: a connect snapshot and every change, including TTL
|
|
6
|
+
* expiry, over SSE or polling. This store never runs its own expiry ticker.
|
|
7
7
|
*
|
|
8
8
|
* `sessionActive` is the ONE selector every agent surface reads — the session
|
|
9
9
|
* panel, command bar, presence layer, and top-bar chip all mount on it.
|
|
@@ -75,7 +75,7 @@ export type AnnotationTool = 'pen' | 'eraser' | 'text' | null;
|
|
|
75
75
|
export type ConnectionStatus = 'connecting' | 'connected' | 'disconnected';
|
|
76
76
|
export declare const TYPE_LABELS: Record<CanvasNodeState['type'], string>;
|
|
77
77
|
/** Node types that support the full-viewport expand/focus overlay. */
|
|
78
|
-
export declare const EXPANDABLE_TYPES: Set<"
|
|
78
|
+
export declare const EXPANDABLE_TYPES: Set<"board" | "image" | "file" | "markdown" | "mcp-app" | "webpage" | "json-render" | "graph" | "prompt" | "response" | "status" | "context" | "ledger" | "trace" | "diff" | "mermaid" | "html" | "group">;
|
|
79
79
|
export declare const EXCALIDRAW_SERVER_NAME = "Excalidraw";
|
|
80
80
|
export declare const EXCALIDRAW_CREATE_VIEW_TOOL = "create_view";
|
|
81
81
|
export declare function isExcalidrawNode(node: CanvasNodeState): boolean;
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import { type CanvasLayout, type CanvasNodeState, type PmxCanvas } from '../server/index.js';
|
|
2
|
-
import type { PmxAxSource } from '../server/ax-state.js';
|
|
3
2
|
import type { ContextReadInput } from '../server/context-reads.js';
|
|
4
3
|
import { type OperationInvoker } from '../server/operations/index.js';
|
|
5
4
|
type AxStateResult = ReturnType<PmxCanvas['getAxState']>;
|
|
6
5
|
type AxContextResult = ReturnType<PmxCanvas['getAxContext']>;
|
|
7
|
-
type SubmitAxInteractionInput = Parameters<PmxCanvas['submitAxInteraction']>[0];
|
|
8
|
-
type SubmitAxInteractionResult = ReturnType<PmxCanvas['submitAxInteraction']>;
|
|
9
6
|
type GetPendingSteeringResult = ReturnType<PmxCanvas['getPendingSteering']>;
|
|
10
7
|
type ListElicitationsResult = ReturnType<PmxCanvas['listElicitations']>;
|
|
11
8
|
type ListModeRequestsResult = ReturnType<PmxCanvas['listModeRequests']>;
|
|
12
|
-
type IngestActivityInput = Parameters<PmxCanvas['ingestActivity']>[0];
|
|
13
|
-
type IngestActivityResult = ReturnType<PmxCanvas['ingestActivity']>;
|
|
14
9
|
type GetPolicyResult = ReturnType<PmxCanvas['getPolicy']>;
|
|
15
10
|
type GetAxTimelineQuery = Parameters<PmxCanvas['getAxTimeline']>[0];
|
|
16
11
|
type GetAxTimelineResult = ReturnType<PmxCanvas['getAxTimeline']>;
|
|
@@ -38,18 +33,12 @@ export interface CanvasAccess {
|
|
|
38
33
|
listWorkItems(): Promise<ListWorkItemsResult>;
|
|
39
34
|
listApprovalGates(): Promise<ListApprovalGatesResult>;
|
|
40
35
|
listReviewAnnotations(): Promise<ListReviewAnnotationsResult>;
|
|
41
|
-
submitAxInteraction(input: SubmitAxInteractionInput, options?: {
|
|
42
|
-
source?: PmxAxSource;
|
|
43
|
-
}): Promise<SubmitAxInteractionResult>;
|
|
44
36
|
getPendingSteering(options?: {
|
|
45
37
|
consumer?: string;
|
|
46
38
|
limit?: number;
|
|
47
39
|
}): Promise<GetPendingSteeringResult>;
|
|
48
40
|
listElicitations(): Promise<ListElicitationsResult>;
|
|
49
41
|
listModeRequests(): Promise<ListModeRequestsResult>;
|
|
50
|
-
ingestActivity(input: IngestActivityInput, options?: {
|
|
51
|
-
source?: PmxAxSource;
|
|
52
|
-
}): Promise<IngestActivityResult>;
|
|
53
42
|
getPolicy(): Promise<GetPolicyResult>;
|
|
54
43
|
getHistory(): Promise<HistoryResult>;
|
|
55
44
|
getPinnedNodeIds(board?: string): Promise<string[]>;
|
|
@@ -62,7 +51,7 @@ export interface CanvasAccess {
|
|
|
62
51
|
runBatch(operations: RunBatchInput): Promise<RunBatchResult>;
|
|
63
52
|
getCodeGraph(): Promise<CodeGraphResult>;
|
|
64
53
|
getAutomationWebViewStatus(): Promise<AutomationWebViewStatus>;
|
|
65
|
-
screenshotAutomationWebView(options?: AutomationScreenshotOptions): Promise<Uint8Array>;
|
|
54
|
+
screenshotAutomationWebView(options?: AutomationScreenshotOptions, signal?: AbortSignal): Promise<Uint8Array>;
|
|
66
55
|
}
|
|
67
56
|
export declare function refreshCanvasAccess(access: CanvasAccess): Promise<CanvasAccess>;
|
|
68
57
|
/**
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { CanvasAccess } from './canvas-access.js';
|
|
3
|
+
/** One subscription set and event source per MCP connection. Notifications are not reads. */
|
|
4
|
+
export declare function registerResourceSubscriptions(server: McpServer, getCanvas: () => Promise<CanvasAccess>): {
|
|
5
|
+
attach: (canvas: CanvasAccess) => void;
|
|
6
|
+
dispose: () => void;
|
|
7
|
+
};
|
|
@@ -168,6 +168,7 @@ export declare function resolveCanvasNode(nodeRef: CanvasNodeLookupInput): {
|
|
|
168
168
|
};
|
|
169
169
|
export declare function refreshCanvasWebpageNode(id: string, options?: {
|
|
170
170
|
url?: string;
|
|
171
|
+
signal?: AbortSignal;
|
|
171
172
|
}): Promise<{
|
|
172
173
|
ok: boolean;
|
|
173
174
|
id: string;
|
|
@@ -432,6 +432,8 @@ declare class CanvasStateManager {
|
|
|
432
432
|
updateNode(id: string, patch: Partial<CanvasNodeState>, savedWikiLinks?: WikiLink[] | null): void;
|
|
433
433
|
removeNode(id: string): void;
|
|
434
434
|
getNode(id: string): CanvasNodeState | undefined;
|
|
435
|
+
/** Camera targets need geometry, not hydrated documents, frames or image blobs. */
|
|
436
|
+
nodeGeometry(): Array<Pick<CanvasNodeState, 'id' | 'type' | 'position' | 'size'>>;
|
|
435
437
|
/** Who made and last edited each card, and its content revision — no content, no copies. */
|
|
436
438
|
nodeStamps(): Array<Pick<CanvasNodeState, 'id' | 'createdBy' | 'lastEditedBy' | 'contentRevision'>>;
|
|
437
439
|
getNodeForPersistence(id: string): CanvasNodeState | undefined;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
|
-
import {
|
|
3
|
-
import { type TourStep, type TourStepResult } from './tour-control.js';
|
|
2
|
+
import type { Camera, Tour, TourStop } from '../shared/tour.js';
|
|
3
|
+
import { type TourState, type TourStep, type TourStepResult } from './tour-control.js';
|
|
4
4
|
export type { Tour, TourStop } from '../shared/tour.js';
|
|
5
|
-
export type { TourStep, TourStepResult } from './tour-control.js';
|
|
5
|
+
export type { TourState, TourStep, TourStepResult } from './tour-control.js';
|
|
6
6
|
import type { AgentPhase, AgentPresence, AgentPresenceSnapshot } from '../shared/agent-presence.js';
|
|
7
7
|
import { canvasState } from './canvas-state.js';
|
|
8
8
|
import type { CanvasAnnotation, CanvasNodeState, CanvasEdge, CanvasLayout } from './canvas-state.js';
|
|
@@ -22,7 +22,7 @@ import type { HtmlPrimitiveKind } from './html-primitives.js';
|
|
|
22
22
|
import { type WebArtifactBuildInput, type WebArtifactCanvasBuildResult } from './web-artifacts.js';
|
|
23
23
|
import { type ExternalMcpTransportConfig } from './mcp-app-runtime.js';
|
|
24
24
|
import type { DiagramPresetOpenInput } from './diagram-presets.js';
|
|
25
|
-
import {
|
|
25
|
+
import type { GraphNodeInput, JsonRenderNodeInput, JsonRenderSpec } from '../json-render/server.js';
|
|
26
26
|
import type { CanvasAutomationWebViewOptions, CanvasAutomationWebViewStatus } from './server.js';
|
|
27
27
|
/**
|
|
28
28
|
* Node object returned by the SDK's create/get methods. It is the fully
|
|
@@ -163,7 +163,7 @@ export declare class PmxCanvas extends EventEmitter {
|
|
|
163
163
|
ungroupNodes(groupId: string, options?: {
|
|
164
164
|
intentId?: string;
|
|
165
165
|
}): boolean;
|
|
166
|
-
getTour():
|
|
166
|
+
getTour(): TourState;
|
|
167
167
|
setTour(tour: Tour | null): void;
|
|
168
168
|
/** Present a tour stop (index, `next` or `previous`) in the workbench. Not recorded in undo history. */
|
|
169
169
|
goToTourStop(step: TourStep, options?: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Database } from 'bun:sqlite';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { type MemoryTarget } from '../shared/memory-graph.js';
|
|
3
4
|
import { type ActorAttribution } from './attribution.js';
|
|
4
5
|
import type { LifecycleQualification } from '../shared/lifecycle-status.js';
|
|
5
6
|
import type { CanvasNodeState } from './canvas-state.js';
|
|
@@ -182,7 +183,7 @@ export declare class KnowledgeLifecycle {
|
|
|
182
183
|
cadenceDays?: number | undefined;
|
|
183
184
|
} | null;
|
|
184
185
|
lifecycleSourceFolder: string | null;
|
|
185
|
-
lifecycleSource: "
|
|
186
|
+
lifecycleSource: "card" | "unknown" | "folder";
|
|
186
187
|
};
|
|
187
188
|
resolveCard(folderPath: string | null, node: Pick<CanvasNodeState, 'type' | 'data'>, catalog?: {
|
|
188
189
|
categories: KnowledgeCategory[];
|
|
@@ -208,8 +209,16 @@ export declare class KnowledgeLifecycle {
|
|
|
208
209
|
cadenceDays?: number | undefined;
|
|
209
210
|
} | null;
|
|
210
211
|
lifecycleSourceFolder: string | null;
|
|
211
|
-
lifecycleSource: "
|
|
212
|
+
lifecycleSource: "card" | "unknown" | "folder";
|
|
212
213
|
};
|
|
214
|
+
private indexedDb;
|
|
215
|
+
/** Stored owners of semantic sources; the caller overlays the active board's unsaved edges. */
|
|
216
|
+
incomingSourceBoards(target: MemoryTarget, activeBoardId: string | null): string[];
|
|
217
|
+
/** One indexed latest validation and retirement per card, never its full audit history. */
|
|
218
|
+
reviewSummaries(targets: MemoryTarget[]): Map<string, {
|
|
219
|
+
lastValidation: ReviewRecord | null;
|
|
220
|
+
retired: boolean;
|
|
221
|
+
}>;
|
|
213
222
|
reviews(boardId: string, nodeId: string): {
|
|
214
223
|
records: ReviewRecord[];
|
|
215
224
|
retired: boolean;
|
|
@@ -3,8 +3,10 @@ import type { LifecycleQualification } from '../shared/lifecycle-status.js';
|
|
|
3
3
|
import type { ReviewCardSummary } from './knowledge-lifecycle.js';
|
|
4
4
|
/** A read-only qualification, shared by briefs, search, Home and card review. No clock is renewed. */
|
|
5
5
|
export declare function lifecycleQualifications(now?: number, atUse?: MemoryTarget[]): Record<string, LifecycleQualification>;
|
|
6
|
+
/** A card being inspected is in use, including its transitive sources and portal contents. */
|
|
7
|
+
export declare function lifecycleQualification(target: MemoryTarget, now?: number): LifecycleQualification | undefined;
|
|
6
8
|
/** Compact queue metadata and qualifications come from the same authoritative read. */
|
|
7
|
-
export declare function lifecycleSnapshot(now?: number, atUse?: MemoryTarget[]): {
|
|
9
|
+
export declare function lifecycleSnapshot(now?: number, atUse?: MemoryTarget[], only?: MemoryTarget): {
|
|
8
10
|
cards: Record<string, LifecycleQualification>;
|
|
9
11
|
reviewCards: ReviewCardSummary[];
|
|
10
12
|
};
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import { type OperationProgress } from './types.js';
|
|
2
|
+
/** Opt-in NDJSON; the terminal frame retains the ordinary HTTP status/body. */
|
|
3
|
+
export type OperationStreamFrame = {
|
|
4
|
+
type: 'progress';
|
|
5
|
+
progress: OperationProgress;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'result';
|
|
8
|
+
status: number;
|
|
9
|
+
body: unknown;
|
|
10
|
+
};
|
|
1
11
|
export declare function matchOperationPath(template: string, pathname: string): Record<string, string> | null;
|
|
2
12
|
/**
|
|
3
13
|
* Shared body reader: preserves the parsed JSON value as-is (object, array,
|
|
@@ -3,6 +3,6 @@ export { dispatchOperationRoute } from './http.js';
|
|
|
3
3
|
export { runCanvasBatchOperation, type BatchEnvelope } from './ops/batch.js';
|
|
4
4
|
export type { OpenMcpAppCoreResult } from './ops/app.js';
|
|
5
5
|
export { LocalOperationInvoker, HttpOperationInvoker, type OperationInvoker } from './invoker.js';
|
|
6
|
-
export { registerOperationTools, registerCompositeTools, type OperationToolHost } from './mcp.js';
|
|
6
|
+
export { registerOperationTools, registerCompositeTools, registerOperationHelpTool, type OperationToolHost, } from './mcp.js';
|
|
7
7
|
export { compositeToolDefinitions, type CompositeToolDefinition } from './composites.js';
|
|
8
|
-
export { OperationError, defineOperation, type Operation, type OperationContext, type OperationDefinition, type OperationErrorStatus, } from './types.js';
|
|
8
|
+
export { OperationError, defineOperation, type Operation, type OperationContext, type OperationDefinition, type OperationExecutionOptions, type OperationErrorStatus, type OperationProgress, } from './types.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { type OperationExecutionOptions } from './types.js';
|
|
1
2
|
export interface OperationInvoker {
|
|
2
|
-
invoke(name: string, input: Record<string, unknown
|
|
3
|
+
invoke(name: string, input: Record<string, unknown>, options?: OperationExecutionOptions): Promise<unknown>;
|
|
3
4
|
}
|
|
4
5
|
/**
|
|
5
6
|
* The agent-presence label for a transport: `PMX_CANVAS_AGENT_SOURCE` lets a
|
|
@@ -14,7 +15,7 @@ export declare class LocalOperationInvoker implements OperationInvoker {
|
|
|
14
15
|
private readonly proxiedRead;
|
|
15
16
|
/** `source` labels this caller's agent presence ('mcp', 'sdk', …). */
|
|
16
17
|
constructor(source?: string, allowExternalMcp?: boolean);
|
|
17
|
-
invoke(name: string, input: Record<string, unknown
|
|
18
|
+
invoke(name: string, input: Record<string, unknown>, options?: OperationExecutionOptions): Promise<unknown>;
|
|
18
19
|
}
|
|
19
20
|
/** Builds the HTTP request from the op's route template (`:id` from input, GET flags to query). */
|
|
20
21
|
export declare class HttpOperationInvoker implements OperationInvoker {
|
|
@@ -24,5 +25,5 @@ export declare class HttpOperationInvoker implements OperationInvoker {
|
|
|
24
25
|
private readonly proxiedRead;
|
|
25
26
|
/** `source` labels this caller's agent presence on the server ('cli', 'mcp', …). */
|
|
26
27
|
constructor(baseUrl: string, source?: string, allowExternalMcp?: boolean);
|
|
27
|
-
invoke(name: string, rawInput: Record<string, unknown
|
|
28
|
+
invoke(name: string, rawInput: Record<string, unknown>, options?: OperationExecutionOptions): Promise<unknown>;
|
|
28
29
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP's output is the FORMATTER projection, never the larger HTTP payload.
|
|
3
|
+
* `result` wraps prose/arrays without pretending they are JSON objects. Each
|
|
4
|
+
* operation validates its stable fields; loose payloads preserve full:true and
|
|
5
|
+
* extensible node/app data. No schema advertises an unconstrained root record.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { CallToolResult, ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
export declare function operationOutputSchema(operations: string[]): z.ZodObject<{
|
|
10
|
+
result: z.ZodUnion<readonly [...z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>[], z.ZodObject<{
|
|
11
|
+
operation: z.ZodNull;
|
|
12
|
+
outcome: z.ZodLiteral<"error">;
|
|
13
|
+
data: z.ZodObject<{
|
|
14
|
+
message: z.ZodString;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
}, z.core.$strict>]>;
|
|
17
|
+
}, z.core.$strict>;
|
|
18
|
+
export declare function structuredOperationResult(operation: string, formatted: CallToolResult): CallToolResult;
|
|
19
|
+
export declare function operationToolError(error: unknown): CallToolResult;
|
|
20
|
+
export declare function operationToolAnnotations(toolName: string): ToolAnnotations;
|
|
@@ -12,6 +12,8 @@ export interface OperationToolHost extends OperationMcpToolHost {
|
|
|
12
12
|
recordContextRead(read: ContextReadInput): Promise<void>;
|
|
13
13
|
}
|
|
14
14
|
export declare function registerOperationTools(server: McpServer, getHost: () => Promise<OperationToolHost>): void;
|
|
15
|
+
/** Registry metadata only: never boots a canvas or records a content read. */
|
|
16
|
+
export declare function registerOperationHelpTool(server: McpServer): void;
|
|
15
17
|
/**
|
|
16
18
|
* Register composite (action-discriminated) MCP tools (plan-006). Each action
|
|
17
19
|
* dispatches to a registered operation, reusing that op's `mcp.buildInput` and
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Operation } from './types.js';
|
|
1
|
+
import { type Operation, type OperationExecutionOptions } from './types.js';
|
|
2
2
|
export declare function registerOperation(op: Operation): void;
|
|
3
3
|
export declare function getOperation(name: string): Operation;
|
|
4
4
|
export declare function listOperations(): Operation[];
|
|
@@ -12,7 +12,7 @@ export declare function getOperationEventEmitter(): OperationEventEmitter | null
|
|
|
12
12
|
export declare function isEmitSuppressed(): boolean;
|
|
13
13
|
/** Suppress this call chain's per-entry frames; the batch emits its final frame afterward. */
|
|
14
14
|
export declare function runWithSuppressedEmits<T>(fn: () => Promise<T>): Promise<T>;
|
|
15
|
-
export interface ExecuteOperationMeta {
|
|
15
|
+
export interface ExecuteOperationMeta extends OperationExecutionOptions {
|
|
16
16
|
/**
|
|
17
17
|
* Skip the synthesized auto-ghost: set by the workbench's own HTTP calls
|
|
18
18
|
* (a human dragging a node is not agent activity) and by canvas.batch for
|
|
@@ -20,7 +20,17 @@ export declare class OperationError extends Error {
|
|
|
20
20
|
readonly details?: Record<string, unknown>;
|
|
21
21
|
constructor(message: string, status?: OperationErrorStatus, details?: Record<string, unknown>);
|
|
22
22
|
}
|
|
23
|
-
export interface
|
|
23
|
+
export interface OperationProgress {
|
|
24
|
+
progress: number;
|
|
25
|
+
total?: number;
|
|
26
|
+
message?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Cooperative cancellation: completed writes are never rolled back. */
|
|
29
|
+
export interface OperationExecutionOptions {
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
onProgress?: (progress: OperationProgress) => void | Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export interface OperationContext extends OperationExecutionOptions {
|
|
24
34
|
/** Emit a workbench SSE event (e.g. extra `canvas-layout-update` frames, focus, viewport). */
|
|
25
35
|
emit(event: string, payload?: Record<string, unknown>): void;
|
|
26
36
|
}
|
|
@@ -53,7 +63,7 @@ export interface OperationMcpToolHost {
|
|
|
53
63
|
* restore summary).
|
|
54
64
|
*/
|
|
55
65
|
invoker(): {
|
|
56
|
-
invoke(name: string, input: Record<string, unknown
|
|
66
|
+
invoke(name: string, input: Record<string, unknown>, options?: OperationExecutionOptions): Promise<unknown>;
|
|
57
67
|
};
|
|
58
68
|
}
|
|
59
69
|
export interface OperationMcpTool {
|
|
@@ -80,6 +80,8 @@ export interface PrimaryWorkbenchCanvasPromptRequest {
|
|
|
80
80
|
contextNodeIds: string[];
|
|
81
81
|
}
|
|
82
82
|
type PrimaryWorkbenchCanvasPromptHandler = (request: PrimaryWorkbenchCanvasPromptRequest) => Promise<void>;
|
|
83
|
+
/** In-process invalidation observers share the same events as daemon SSE clients. */
|
|
84
|
+
export declare function onWorkbenchEvent(listener: (event: string) => void): () => void;
|
|
83
85
|
export declare function setPrimaryWorkbenchAutoOpenEnabled(enabled: boolean): void;
|
|
84
86
|
export declare function isPrimaryWorkbenchAutoOpenEnabled(): boolean;
|
|
85
87
|
export declare function hasWorkbenchSubscribers(): boolean;
|
|
@@ -15,9 +15,12 @@ export interface TourStepResult {
|
|
|
15
15
|
total: number;
|
|
16
16
|
stop: TourStop;
|
|
17
17
|
}
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
export interface TourState {
|
|
19
|
+
tour: Tour;
|
|
20
|
+
derived: boolean;
|
|
21
|
+
position: number | null;
|
|
22
|
+
}
|
|
23
|
+
export declare function currentTour(): TourState;
|
|
21
24
|
/** Move the shared cursor. `next`/`previous` clamp at the ends; an explicit index must exist. */
|
|
22
25
|
export declare function goToTourStop(step: TourStep): TourStepResult;
|
|
23
26
|
export declare function exitTour(): void;
|
|
@@ -37,6 +37,7 @@ export declare function checkWebpageHop(originScope: AddressScope, hopScope: Add
|
|
|
37
37
|
export declare function fetchWebpageSnapshot(inputUrl: string, options?: {
|
|
38
38
|
resolveHost?: ResolveHost;
|
|
39
39
|
timeoutMs?: number;
|
|
40
|
+
signal?: AbortSignal;
|
|
40
41
|
}): Promise<WebpageSnapshot>;
|
|
41
42
|
export declare function getWebpageFetchErrorDetails(error: unknown): {
|
|
42
43
|
message: string;
|
package/docs/api-reference.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## MCP Server
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
25 tools: 18 action-discriminated composites (`canvas_import`, `canvas_board`, `canvas_node`, `canvas_render`, `canvas_edge`, `canvas_group`, `canvas_history`, `canvas_view`, `canvas_query`, `canvas_webview`, `canvas_app`, `canvas_snapshot`, `canvas_ax_state`, `canvas_ax_work`, `canvas_ax_gate`, `canvas_ax_timeline`, `canvas_ax_delivery`, `canvas_intent`) plus 7 standalone tools (`canvas_help`, `canvas_batch`, `canvas_pin_nodes`, `canvas_invoke_command`, `canvas_ax_interaction`, `canvas_ingest_activity`, `canvas_screenshot`). `canvas_help { op }` returns one MCP registry operation's public arguments and guidance without accessing the canvas; omit `op` to list names. `canvas_import` is the agent half of the human-consented attachment workflow: agents list/read requested imports, submit reviewable Markdown, or report unavailable; they cannot request, cancel, or commit. The 57 legacy single-purpose tools the composites replaced were removed in v0.3.0; v0.4.0 shipped the `canvas_snapshot` composite and removed the 6 deprecated snapshot standalones. Prefer composites for new MCP calls; see `docs/mcp.md` for the authoritative tool list and the legacy-to-composite migration reference.
|
|
10
10
|
|
|
11
11
|
### Agent-assisted document imports
|
|
12
12
|
|
|
@@ -18,7 +18,7 @@ The `diagram` action of `canvas_app` is a thin preset in `src/server/diagram-pre
|
|
|
18
18
|
|
|
19
19
|
15 static canvas resources: `canvas://boards`, `canvas://pinned-context`, `canvas://schema`, `canvas://layout`, `canvas://summary`, `canvas://spatial-context`, `canvas://history`, `canvas://code-graph`, `canvas://ax`, `canvas://ax-context`, `canvas://ax-timeline`, `canvas://ax-work`, `canvas://ax-pending-steering`, `canvas://ax-delivery`, `canvas://skills`; two canvas resource templates: `canvas://context{?budget,consumer,since}` and `canvas://graph{?focus,depth}`. Bundled skills additionally register per-skill `canvas://skills/<name>` resources and the `skill://{name}/{+path}` file template.
|
|
20
20
|
|
|
21
|
-
Resource change notifications:
|
|
21
|
+
Resource change notifications: subscribe to each live URI to receive `notifications/resources/updated` when canvas state or knowledge policies change. Notifications invalidate cached data without reading it. Subscriptions belong to the connection; subscribe again after reconnecting. See [Resource subscriptions](mcp.md#resource-subscriptions-010).
|
|
22
22
|
|
|
23
23
|
### AX Primitives (host-agnostic)
|
|
24
24
|
|
package/docs/cli.md
CHANGED
|
@@ -99,7 +99,8 @@ offset mid-move without changing endpoints. Tours allow at most 1000 stops.
|
|
|
99
99
|
Tours persist with the board and snapshots, participate in undo, and clear with
|
|
100
100
|
the board. A file containing `null` resets the tour: when none is saved, groups
|
|
101
101
|
are sorted by y, then x, then ID. A saved empty `stops` array deliberately has no
|
|
102
|
-
stops. SDK: `canvas.setTour(tourOrNull)` / `canvas.getTour()
|
|
102
|
+
stops. SDK: `canvas.setTour(tourOrNull)` / `canvas.getTour()`, which returns
|
|
103
|
+
`{ tour, derived, position }` as of 0.10; read stops from `.tour.stops`.
|
|
103
104
|
|
|
104
105
|
### Driving a tour (agents)
|
|
105
106
|
|
|
@@ -593,6 +594,14 @@ pmx-canvas copilot install-extension --dry-run # Preview target, writes nothin
|
|
|
593
594
|
pmx-canvas copilot install-extension --yes # Install/overwrite into .github/extensions/pmx-canvas/
|
|
594
595
|
```
|
|
595
596
|
|
|
597
|
+
After updating the adapter, start a new Copilot project session to load it.
|
|
598
|
+
Panel instructions, `send_instruction` and canvas steering request the SDK's
|
|
599
|
+
`immediate` mode: during an active turn, Copilot receives them before its next
|
|
600
|
+
model call, without aborting an executing tool. If the turn has already ended,
|
|
601
|
+
the SDK queues the instruction instead. A successful send means the host accepted
|
|
602
|
+
the instruction, not that the model has consumed it. Failed sends are not marked
|
|
603
|
+
delivered; the delivery pump retries them.
|
|
604
|
+
|
|
596
605
|
## Skill sync
|
|
597
606
|
|
|
598
607
|
Refresh the pmx-canvas skill copies **already installed** in this workspace.
|
|
@@ -125,6 +125,7 @@ body{margin:0}
|
|
|
125
125
|
<div style="height: 350px; display: flex; flex-direction: column; border: 1px solid #1b2c44; border-radius: 14px; overflow: hidden; background: #0f1d31">
|
|
126
126
|
<div style="flex-shrink: 0; height: 46px; display: flex; align-items: center; gap: 10px; padding: 0 16px; border-bottom: 1px solid #1b2c44; font-size: 13px; font-weight: 600">Research index <span style="margin-left: auto; font-size: 12px; font-weight: 400">Relations</span><span style="margin-left: 12px">×</span></div>
|
|
127
127
|
<div style="flex: 1; min-height: 0; overflow: auto; padding: 16px; font-size: 13px; color: #b9c6d6">Read and edit the source here. Actual edits finish saving before a reference opens; a refused save keeps this reader and its draft.</div>
|
|
128
|
+
<button style="flex-shrink: 0; align-self: flex-end; margin: 16px; padding: 8px 18px; border: 1px solid #1b2c44; border-radius: 6px; font: 600 13px 'IBM Plex Sans', sans-serif; background: #13243b; color: #8ea3bd"></> Source</button>
|
|
128
129
|
<div role="region" aria-label="Cross-board references" tabindex="0" style="flex-shrink: 0; max-height: min(40%, 132px); overflow: auto; overscroll-behavior: contain">
|
|
129
130
|
<div style="padding: 6px 12px; border-top: 1px solid #1b2c44; font-size: 12px; color: #b9c6d6">↗ references: Research / Interview notes</div>
|
|
130
131
|
<div style="padding: 6px 12px; border-top: 1px solid #1b2c44; font-size: 12px; color: #b9c6d6">↗ references: Research / Findings</div>
|
package/docs/design.md
CHANGED
|
@@ -504,7 +504,9 @@ retain their hit targets. Grab areas yield to every card, including neighboring
|
|
|
504
504
|
but outrank connection labels and lines. Group interiors still select and open their menus,
|
|
505
505
|
below child ports and labels; the frames and labels keep their existing visual stacking.
|
|
506
506
|
Expanded flow documents put Source in a separate row above the reader, clear of the
|
|
507
|
-
bottom dock's action hints
|
|
507
|
+
bottom dock's action hints. Ordinary documents keep Source at the bottom right in a
|
|
508
|
+
reserved row below the scroll viewport, so it cannot cover text at narrow widths
|
|
509
|
+
or intermediate scroll positions (0.9.2 review follow-up, 2026-10-24).
|
|
508
510
|
Hovering a flow action temporarily
|
|
509
511
|
hides another action's keyboard hint without moving focus; leaving restores the focused hint.
|
|
510
512
|
Card checkbox clicks address parsed Markdown tasks, not fenced/indented examples or raw
|
package/docs/http-api.md
CHANGED
|
@@ -3,6 +3,37 @@
|
|
|
3
3
|
REST endpoints for all canvas operations + an SSE event stream. Works from
|
|
4
4
|
any language. Default base URL: `http://localhost:4313`.
|
|
5
5
|
|
|
6
|
+
## Operation cancellation and progress (0.10)
|
|
7
|
+
|
|
8
|
+
Registry-backed operation routes use the request's abort signal. Disconnecting
|
|
9
|
+
stops supported AX waits, cancels webpage fetching and prevents later batch
|
|
10
|
+
operations from starting. Completed writes remain. Cancellation is cooperative:
|
|
11
|
+
external app builds/runtime calls and local WebView captures cannot be interrupted
|
|
12
|
+
mid-call. A standalone cancelled operation returns HTTP 499 with
|
|
13
|
+
`{ "ok": false, "cancelled": true, "error": "Operation cancelled." }` when the
|
|
14
|
+
connection still permits a response. An interrupted batch retains completed
|
|
15
|
+
`results` and `refs` in its partial-failure body and adds `cancelled: true`.
|
|
16
|
+
Disconnected clients must inspect state before retrying; they may never receive
|
|
17
|
+
that body. Cancellation is not rollback.
|
|
18
|
+
|
|
19
|
+
Send `Accept: application/x-ndjson` to opt into batch and supported AX wait progress
|
|
20
|
+
over the operation response stream. Each newline-delimited JSON frame is one of:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{"type":"progress","progress":{"progress":1,"total":3,"message":"node.add"}}
|
|
24
|
+
{"type":"result","status":200,"body":{"ok":true,"results":[],"refs":{}}}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The examples show frame shapes, not one complete batch. The terminal `result`
|
|
28
|
+
frame carries the ordinary operation status and body; the stream's HTTP 200 does
|
|
29
|
+
not establish operation success. Without this header, routes keep their ordinary
|
|
30
|
+
JSON status/body. Early validation errors may still be ordinary JSON. The
|
|
31
|
+
in-process and HTTP operation invokers accept optional `{ signal, onProgress }`;
|
|
32
|
+
the HTTP invoker negotiates this stream only when given a progress callback.
|
|
33
|
+
|
|
34
|
+
AX wait routes accept `timeoutMs` as well as the direct-HTTP `waitMs` parameter;
|
|
35
|
+
`timeoutMs` takes precedence when both are supplied.
|
|
36
|
+
|
|
6
37
|
## Knowledge lifecycle data (plan 017 slice 1)
|
|
7
38
|
|
|
8
39
|
The slice-1 data contract now also drives the workbench, due engine and qualified agent context.
|