agentic-canvas 0.2.0 → 0.4.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/README.md +120 -10
- package/dist/{chunk-V477KSZQ.js → chunk-HPUYT5TC.js} +183 -8
- package/dist/{chunk-W7NRP3EX.js → chunk-J52RPFRP.js} +39 -8
- package/dist/{chunk-GGQPE65T.js → chunk-JZA525X5.js} +61 -2
- package/dist/{chunk-KEMOXKBY.js → chunk-TSWXD4YG.js} +15 -2
- package/dist/cli.js +13 -3
- package/dist/client.d.ts +119 -0
- package/dist/client.js +80 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -3
- package/dist/live-worker.d.ts +2 -1
- package/dist/live-worker.js +3 -3
- package/dist/live.d.ts +7 -1
- package/dist/live.js +12 -11
- package/dist/{service-CJTe-uBI.d.ts → read-Bdg1uiFC.d.ts} +11 -108
- package/dist/service-Cim7TWnJ.d.ts +128 -0
- package/dist/worker.d.ts +5 -2
- package/dist/worker.js +5 -3
- package/llms.txt +3 -1
- package/package.json +21 -6
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { S as ShapeType, c as Board, P as Principal, B as BoardData, a as Shape, C as Connector, d as CanvasElement } from './read-Bdg1uiFC.js';
|
|
2
|
+
import { Store } from 'agentic-identity';
|
|
3
|
+
|
|
4
|
+
declare const MAX_FLOW_NODES = 500;
|
|
5
|
+
declare const MAX_FLOW_EDGES = 2000;
|
|
6
|
+
interface FlowNode {
|
|
7
|
+
id: string;
|
|
8
|
+
text: string;
|
|
9
|
+
shape: Extract<ShapeType, "rect" | "ellipse" | "diamond">;
|
|
10
|
+
}
|
|
11
|
+
interface FlowEdge {
|
|
12
|
+
from: string;
|
|
13
|
+
to: string;
|
|
14
|
+
text: string;
|
|
15
|
+
}
|
|
16
|
+
interface FlowGraph {
|
|
17
|
+
direction: "TB" | "LR";
|
|
18
|
+
nodes: FlowNode[];
|
|
19
|
+
edges: FlowEdge[];
|
|
20
|
+
}
|
|
21
|
+
declare function parseFlow(source: string): FlowGraph;
|
|
22
|
+
interface Placement {
|
|
23
|
+
id: string;
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
w: number;
|
|
27
|
+
h: number;
|
|
28
|
+
}
|
|
29
|
+
/** Layered layout. The top-left of the result is (0, 0). The layout breaks cycles and handles self-loops. */
|
|
30
|
+
declare function layoutFlow(graph: FlowGraph): Placement[];
|
|
31
|
+
interface DrawOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Put in front of every id. Default: a new random prefix for each call, so two agents that draw at
|
|
34
|
+
* the same time never write the same id. A prefix you pass is used as given, and it makes ids
|
|
35
|
+
* repeatable. Up to 16 of A-Z, a-z, 0-9, _ and -.
|
|
36
|
+
*/
|
|
37
|
+
idPrefix?: string;
|
|
38
|
+
/** Top-left of the drawing. Default: below the shapes already on the board. */
|
|
39
|
+
origin?: {
|
|
40
|
+
x: number;
|
|
41
|
+
y: number;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Draw a flow on the board. All or nothing: on any error the board stays as it was. */
|
|
45
|
+
declare function drawFlow(board: Board, source: string, actor: Principal, options?: DrawOptions): {
|
|
46
|
+
nodes: string[];
|
|
47
|
+
edges: string[];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Who sent the Yjs item with this id, if the room knows. */
|
|
51
|
+
type Writer = (item: {
|
|
52
|
+
client: number;
|
|
53
|
+
clock: number;
|
|
54
|
+
}) => Principal | undefined;
|
|
55
|
+
/** One place for every board operation. The CLI, the MCP server, and the Worker call it. */
|
|
56
|
+
declare class CanvasService {
|
|
57
|
+
private readonly store;
|
|
58
|
+
constructor(store: Store);
|
|
59
|
+
create(actor: Principal, options?: {
|
|
60
|
+
id?: string;
|
|
61
|
+
title?: string;
|
|
62
|
+
}): Promise<{
|
|
63
|
+
id: string;
|
|
64
|
+
title: string;
|
|
65
|
+
}>;
|
|
66
|
+
/** The first 100 boards (the store sorts by id), with titles. A board whose stored bytes are damaged shows an empty title: it stays in the list so a person can find and repair it. */
|
|
67
|
+
list(): Promise<{
|
|
68
|
+
id: string;
|
|
69
|
+
title: string;
|
|
70
|
+
}[]>;
|
|
71
|
+
/** Throws NOT_FOUND unless the board exists. A live room opens only for a board that exists. */
|
|
72
|
+
assertExists(id: string): Promise<void>;
|
|
73
|
+
read(id: string): Promise<BoardData & {
|
|
74
|
+
id: string;
|
|
75
|
+
}>;
|
|
76
|
+
/** Run `change` on the board and save it, all inside one transaction. */
|
|
77
|
+
change<R>(id: string, change: (board: Board) => R): Promise<R>;
|
|
78
|
+
add(id: string, shape: unknown, actor: Principal): Promise<Shape>;
|
|
79
|
+
connect(id: string, connector: unknown, actor: Principal): Promise<Connector>;
|
|
80
|
+
/** Change fields of one shape or connector: position, size, text, colors. */
|
|
81
|
+
update(id: string, elementId: string, patch: unknown, actor: Principal): Promise<CanvasElement>;
|
|
82
|
+
move(id: string, elementId: string, dx: number, dy: number, actor: Principal): Promise<{
|
|
83
|
+
moved: string[];
|
|
84
|
+
}>;
|
|
85
|
+
remove(id: string, elementId: string): Promise<{
|
|
86
|
+
removed: string[];
|
|
87
|
+
}>;
|
|
88
|
+
flow(id: string, text: string, actor: Principal, options?: DrawOptions): Promise<{
|
|
89
|
+
nodes: string[];
|
|
90
|
+
edges: string[];
|
|
91
|
+
}>;
|
|
92
|
+
exportSvg(id: string): Promise<string>;
|
|
93
|
+
/** The stored board as a Yjs update. A client applies it to a room to seed it: the room does not read it. */
|
|
94
|
+
state(id: string): Promise<Uint8Array>;
|
|
95
|
+
/** What the stored board has that a room with state `room` lacks, as a Yjs update, or null when the room has all of it. */
|
|
96
|
+
missingFrom(id: string, room?: Uint8Array): Promise<Uint8Array | null>;
|
|
97
|
+
/**
|
|
98
|
+
* `writer` names who sent each Yjs item, from the room's log. It sets the stamps where it knows (see `Board.restamp`).
|
|
99
|
+
* Merge a live room's state into the stored board. `authors` are the principals the room saw send updates. A null
|
|
100
|
+
* `actor` trusts only them: the Worker saves a room that way, with nobody present to vouch.
|
|
101
|
+
* An element stamped by anyone else is deleted, and a changed author is put back (see `Board.restamp`),
|
|
102
|
+
* so a client that writes raw Yjs cannot put another author on its work. Broken entries are repaired and
|
|
103
|
+
* a board past the element cap is refused. Returns the ids the checks fixed.
|
|
104
|
+
*
|
|
105
|
+
* Limits: the save corrects the stored board only. The room keeps what its clients wrote, so a client that sees
|
|
106
|
+
* a non-empty `fixed` must join again, or its later edits are lost at the next save. The room remembers its
|
|
107
|
+
* authors for good, so an OLD item that the log does not name (a seeded one, or a range the log dropped) keeps the older rule: its
|
|
108
|
+
* stamp may name anyone who once sent an update in that room. A NEW item with no writer is deleted or undone.
|
|
109
|
+
* The log records who adds an item, not who deletes a key: a deleted optional key is credited to the writer of the editor
|
|
110
|
+
* stamp written in the same save, or undone if there is none.
|
|
111
|
+
* A client that adds a root type of its own makes every later save of that room fail, because the room keeps it.
|
|
112
|
+
*/
|
|
113
|
+
checkpoint(id: string, update: Uint8Array, actor: Principal | null, authors?: Principal[], writer?: Writer): Promise<{
|
|
114
|
+
elements: number;
|
|
115
|
+
fixed: string[];
|
|
116
|
+
}>;
|
|
117
|
+
/** Owner only. Repair a board and delete the named elements. Only a human actor may call it. */
|
|
118
|
+
repair(id: string, actor: Principal, drop?: string[]): Promise<{
|
|
119
|
+
id: string;
|
|
120
|
+
fixed: string[];
|
|
121
|
+
elements: number;
|
|
122
|
+
}>;
|
|
123
|
+
private load;
|
|
124
|
+
}
|
|
125
|
+
/** What the CLI and the MCP server need. `CanvasService` runs it on a store, and `LiveService` runs it in a live room. */
|
|
126
|
+
type BoardAccess = Pick<CanvasService, "create" | "list" | "read" | "update" | "add" | "connect" | "move" | "remove" | "flow" | "exportSvg">;
|
|
127
|
+
|
|
128
|
+
export { type BoardAccess as B, CanvasService as C, type DrawOptions as D, type FlowEdge as F, MAX_FLOW_EDGES as M, type Placement as P, type FlowGraph as a, type FlowNode as b, MAX_FLOW_NODES as c, drawFlow as d, layoutFlow as l, parseFlow as p };
|
package/dist/worker.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { Blobs } from 'agentic-identity';
|
|
|
2
2
|
import { Realtime } from 'agentic-realtime';
|
|
3
3
|
import { D1Like, R2Like } from 'agentic-identity/cloudflare';
|
|
4
4
|
import { Hono } from 'hono';
|
|
5
|
-
import { P as Principal
|
|
5
|
+
import { P as Principal } from './read-Bdg1uiFC.js';
|
|
6
|
+
import { C as CanvasService } from './service-Cim7TWnJ.js';
|
|
6
7
|
import 'yjs';
|
|
7
8
|
import 'zod';
|
|
8
9
|
|
|
@@ -39,6 +40,8 @@ interface AppOptions {
|
|
|
39
40
|
/** Makes the live-room server from the Worker bindings. Without it, the ws route answers 404. */
|
|
40
41
|
live?: (env: WorkerEnv) => Realtime;
|
|
41
42
|
}
|
|
43
|
+
/** A browser cannot set a header on a WebSocket. It offers the token as the sub-protocols `agentic-canvas.bearer` and the token in base64url. */
|
|
44
|
+
declare const WS_PROTOCOL = "agentic-canvas.bearer";
|
|
42
45
|
/** The principal and role for a bearer token, or null. The kind is never defaulted: a grant without a valid kind gets null. */
|
|
43
46
|
declare function authenticate(request: Request, env: WorkerEnv): {
|
|
44
47
|
actor: Principal;
|
|
@@ -51,4 +54,4 @@ declare const _default: {
|
|
|
51
54
|
fetch: (request: Request, env: WorkerEnv, ctx: unknown) => Response | Promise<Response>;
|
|
52
55
|
};
|
|
53
56
|
|
|
54
|
-
export { type AppOptions, type Role, type WorkerEnv, authenticate, createApp, _default as default, sniffImage };
|
|
57
|
+
export { type AppOptions, type Role, WS_PROTOCOL, type WorkerEnv, authenticate, createApp, _default as default, sniffImage };
|
package/dist/worker.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
+
WS_PROTOCOL,
|
|
2
3
|
authenticate,
|
|
3
4
|
createApp,
|
|
4
5
|
sniffImage,
|
|
5
6
|
worker_default
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-HPUYT5TC.js";
|
|
8
|
+
import "./chunk-J52RPFRP.js";
|
|
9
|
+
import "./chunk-JZA525X5.js";
|
|
9
10
|
import "./chunk-NWQED42L.js";
|
|
10
11
|
export {
|
|
12
|
+
WS_PROTOCOL,
|
|
11
13
|
authenticate,
|
|
12
14
|
createApp,
|
|
13
15
|
worker_default as default,
|
package/llms.txt
CHANGED
|
@@ -5,9 +5,11 @@ A shared whiteboard for diagrams, drawn by people and agents.
|
|
|
5
5
|
Keywords: whiteboard,canvas,diagrams,drawing,collaboration,agents,mcp,cli.
|
|
6
6
|
|
|
7
7
|
- SDK: import { Board, drawFlow, readBoard, toSvg } from "agentic-canvas".
|
|
8
|
-
- CLI: agentic-canvas new|read|add|connect|move|rm|flow|export.
|
|
8
|
+
- CLI: agentic-canvas new|list|read|add|connect|update|move|rm|flow|export.
|
|
9
|
+
- UI: the Worker serves a web UI at its root (run `npm run build`, then `wrangler dev`). A person signs in with a bearer token.
|
|
9
10
|
- Live: set CANVAS_SERVER and CANVAS_TOKEN, and the CLI and `agentic-canvas mcp` edit the board in its live room.
|
|
10
11
|
- SDK: import { LiveBoard, LiveService } from "agentic-canvas/live".
|
|
12
|
+
- SDK: import { createClient, CanvasApiError } from "agentic-canvas/client". It calls the Worker API with fetch. Methods: me, listBoards, createBoard, readBoard, exportSvg, addShape, addConnector, drawFlow, update, move, remove, uploadImage, getImage, state, checkpoint. A failure throws CanvasApiError with `code` and `status`. No retries.
|
|
11
13
|
|
|
12
14
|
## Docs
|
|
13
15
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-canvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A shared whiteboard for diagrams, drawn by people and agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"whiteboard",
|
|
@@ -51,6 +51,10 @@
|
|
|
51
51
|
"types": "./dist/live-worker.d.ts",
|
|
52
52
|
"import": "./dist/live-worker.js"
|
|
53
53
|
},
|
|
54
|
+
"./client": {
|
|
55
|
+
"types": "./dist/client.d.ts",
|
|
56
|
+
"import": "./dist/client.js"
|
|
57
|
+
},
|
|
54
58
|
"./file-store": {
|
|
55
59
|
"types": "./dist/store-file.d.ts",
|
|
56
60
|
"import": "./dist/store-file.js"
|
|
@@ -60,17 +64,19 @@
|
|
|
60
64
|
"agentic-canvas": "./dist/cli.js"
|
|
61
65
|
},
|
|
62
66
|
"scripts": {
|
|
63
|
-
"build": "tsup",
|
|
64
|
-
"typecheck": "tsc --noEmit",
|
|
67
|
+
"build": "tsup && vite build",
|
|
68
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p ui",
|
|
65
69
|
"test": "vitest run",
|
|
66
70
|
"clean": "rm -rf dist",
|
|
67
|
-
"ci:local": "npm run build && npm run typecheck && npm test"
|
|
71
|
+
"ci:local": "npm run build && npm run typecheck && npm test && npm run test:e2e",
|
|
72
|
+
"deploy:demo": "wrangler deploy -c wrangler.demo.jsonc",
|
|
73
|
+
"test:e2e": "playwright test -c e2e/playwright.config.ts"
|
|
68
74
|
},
|
|
69
75
|
"dependencies": {
|
|
70
76
|
"@dagrejs/dagre": "^3.1.3",
|
|
71
77
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
72
|
-
"agentic-identity": "^0.
|
|
73
|
-
"agentic-realtime": "^0.
|
|
78
|
+
"agentic-identity": "^0.5.0",
|
|
79
|
+
"agentic-realtime": "^0.3.0",
|
|
74
80
|
"yjs": "^13.6.0",
|
|
75
81
|
"zod": "^3.25.0"
|
|
76
82
|
},
|
|
@@ -83,12 +89,21 @@
|
|
|
83
89
|
}
|
|
84
90
|
},
|
|
85
91
|
"devDependencies": {
|
|
92
|
+
"@axe-core/playwright": "^4.14.0",
|
|
93
|
+
"@playwright/test": "^1.64.1",
|
|
86
94
|
"@types/node": "^22.0.0",
|
|
95
|
+
"@types/react": "^19.3.0",
|
|
96
|
+
"@types/react-dom": "^19.3.0",
|
|
97
|
+
"@vitejs/plugin-react": "^5.2.0",
|
|
98
|
+
"agentic-design": "^0.2.0",
|
|
87
99
|
"hono": "^4.13.14",
|
|
88
100
|
"miniflare": "^4.20260730.0",
|
|
89
101
|
"playwright-core": "^1.64.1",
|
|
102
|
+
"react": "^19.3.1",
|
|
103
|
+
"react-dom": "^19.3.1",
|
|
90
104
|
"tsup": "^8.0.0",
|
|
91
105
|
"typescript": "^5.6.0",
|
|
106
|
+
"vite": "^7.3.7",
|
|
92
107
|
"vitest": "^3.0.0",
|
|
93
108
|
"wrangler": "^4.155.0"
|
|
94
109
|
}
|