agentic-canvas 0.3.0 → 0.5.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 +206 -12
- package/dist/{chunk-W7NRP3EX.js → chunk-G4YTESPS.js} +44 -11
- package/dist/{chunk-GGQPE65T.js → chunk-JCYNPYYJ.js} +96 -40
- package/dist/chunk-SPP6PINW.js +10 -0
- package/dist/{chunk-V477KSZQ.js → chunk-V74PWJKY.js} +186 -9
- package/dist/{chunk-AGODNBN7.js → chunk-VHHJIBAB.js} +33 -18
- package/dist/cli.js +15 -4
- package/dist/client.d.ts +13 -2
- package/dist/client.js +2 -0
- package/dist/embed.d.ts +46 -0
- package/dist/embed.js +535 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +9 -7
- package/dist/live-worker.d.ts +2 -2
- package/dist/live-worker.js +5 -4
- package/dist/live.d.ts +7 -2
- package/dist/live.js +15 -12
- package/dist/{read-BY6f-mmy.d.ts → read-BupIJSPJ.d.ts} +13 -4
- package/dist/{service-Cpl6wKeY.d.ts → service-CR4-r1yx.d.ts} +24 -5
- package/dist/ui.css +38 -0
- package/dist/worker.d.ts +5 -3
- package/dist/worker.js +6 -3
- package/llms.txt +5 -2
- package/package.json +34 -8
package/dist/live.js
CHANGED
|
@@ -2,14 +2,15 @@ import {
|
|
|
2
2
|
Board,
|
|
3
3
|
CanvasError,
|
|
4
4
|
drawFlow,
|
|
5
|
-
principalSchema,
|
|
6
5
|
readBoard,
|
|
7
6
|
toSvg
|
|
8
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JCYNPYYJ.js";
|
|
8
|
+
import {
|
|
9
|
+
principalSchema
|
|
10
|
+
} from "./chunk-SPP6PINW.js";
|
|
9
11
|
|
|
10
12
|
// src/live.ts
|
|
11
13
|
import { SyncClient } from "agentic-realtime/client";
|
|
12
|
-
import * as Y from "yjs";
|
|
13
14
|
var CODES = ["INVALID", "DUPLICATE_ID", "NOT_FOUND", "BAD_REFERENCE", "LIMIT", "UNAVAILABLE", "FORBIDDEN"];
|
|
14
15
|
var base = (server) => server.replace(/\/$/, "") + "/api/v1/canvas";
|
|
15
16
|
async function refusal(response, fallback) {
|
|
@@ -61,7 +62,7 @@ var LiveBoard = class _LiveBoard {
|
|
|
61
62
|
const id = encodeURIComponent(options.board);
|
|
62
63
|
const stored = await call(options.server, options.token, `/boards/${id}/state`);
|
|
63
64
|
if (!stored.ok) throw await refusal(stored, "could not read the stored board");
|
|
64
|
-
|
|
65
|
+
await stored.body?.cancel();
|
|
65
66
|
const url = new URL(`${base(options.server)}/boards/${id}/ws`);
|
|
66
67
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
67
68
|
let client;
|
|
@@ -70,14 +71,6 @@ var LiveBoard = class _LiveBoard {
|
|
|
70
71
|
} catch (error) {
|
|
71
72
|
throw unreachable(error);
|
|
72
73
|
}
|
|
73
|
-
try {
|
|
74
|
-
Y.applyUpdate(client.doc, state);
|
|
75
|
-
await client.flush();
|
|
76
|
-
if (me.role === "editor" && client.denied.length > 0) throw new CanvasError("FORBIDDEN", `the room refused the stored board: ${client.denied[0]}`);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
await client.disconnect();
|
|
79
|
-
throw unreachable(error);
|
|
80
|
-
}
|
|
81
74
|
return new _LiveBoard(new Board(client.doc), me, client, options.board, options, client.denied.length);
|
|
82
75
|
}
|
|
83
76
|
/** The other people and agents in the room. `machine` is true for an agent. */
|
|
@@ -142,6 +135,13 @@ var LiveService = class {
|
|
|
142
135
|
if (typeof id !== "string" || typeof title !== "string") throw new CanvasError("INVALID", "the server sent a board this client does not know");
|
|
143
136
|
return { id, title };
|
|
144
137
|
}
|
|
138
|
+
async list() {
|
|
139
|
+
const response = await call(this.options.server, this.options.token, "/boards");
|
|
140
|
+
if (!response.ok) throw await refusal(response, "the server refused the request");
|
|
141
|
+
const { boards } = await json(response);
|
|
142
|
+
if (!Array.isArray(boards) || !boards.every((b) => typeof b?.id === "string" && typeof b?.title === "string")) throw new CanvasError("INVALID", "the server sent a board list this client does not know");
|
|
143
|
+
return boards;
|
|
144
|
+
}
|
|
145
145
|
async read(id) {
|
|
146
146
|
return this.use(id, async (live) => ({ id, ...readBoard(live.board) }));
|
|
147
147
|
}
|
|
@@ -154,6 +154,9 @@ var LiveService = class {
|
|
|
154
154
|
connect(id, connector, _actor) {
|
|
155
155
|
return this.write(id, (board, actor) => board.addConnector(connector, actor));
|
|
156
156
|
}
|
|
157
|
+
update(id, element, patch, _actor) {
|
|
158
|
+
return this.write(id, (board, actor) => board.update(element, patch, actor));
|
|
159
|
+
}
|
|
157
160
|
move(id, element, dx, dy, _actor) {
|
|
158
161
|
return this.write(id, (board, actor) => ({ moved: board.move(element, dx, dy, actor) }));
|
|
159
162
|
}
|
|
@@ -5,11 +5,11 @@ declare const principalSchema: z.ZodObject<{
|
|
|
5
5
|
kind: z.ZodEnum<["human", "agent_of_human", "agent_of_agent", "agent", "user_token"]>;
|
|
6
6
|
id: z.ZodString;
|
|
7
7
|
}, "strict", z.ZodTypeAny, {
|
|
8
|
-
id: string;
|
|
9
8
|
kind: "human" | "agent_of_human" | "agent_of_agent" | "agent" | "user_token";
|
|
10
|
-
}, {
|
|
11
9
|
id: string;
|
|
10
|
+
}, {
|
|
12
11
|
kind: "human" | "agent_of_human" | "agent_of_agent" | "agent" | "user_token";
|
|
12
|
+
id: string;
|
|
13
13
|
}>;
|
|
14
14
|
type Principal = z.infer<typeof principalSchema>;
|
|
15
15
|
|
|
@@ -108,8 +108,17 @@ declare class Board {
|
|
|
108
108
|
* author, and a changed one needs a trusted editor or it goes back to its prior state. An editor stamp changed alone
|
|
109
109
|
* to an untrusted principal is put back. Unknown keys, nested Yjs types, and bad or foreign title values are deleted
|
|
110
110
|
* or undone. Returns the ids it deleted or restored.
|
|
111
|
+
*
|
|
112
|
+
* `writer` says who sent the update that holds a Yjs item, or undefined when it does not know. Where it knows, it
|
|
113
|
+
* decides: a new element gets its creator as author and editor, and an old one gets the sender of its changes as editor.
|
|
114
|
+
* A client cannot claim another principal, and an agent cannot pass as a person. A new item that the log lacks has no
|
|
115
|
+
* sender: it is deleted or undone. Only an old item falls back to `trusted`. A hand save names its poster as the sender
|
|
116
|
+
* of every item that the room does not hold, in `writer`.
|
|
111
117
|
*/
|
|
112
|
-
restamp(prior: Board, trusted: (who: Principal) => boolean
|
|
118
|
+
restamp(prior: Board, trusted: (who: Principal) => boolean, writer?: (item: {
|
|
119
|
+
client: number;
|
|
120
|
+
clock: number;
|
|
121
|
+
}) => Principal | undefined): string[];
|
|
113
122
|
addShape(input: unknown, actor: Principal): Shape;
|
|
114
123
|
addConnector(input: unknown, actor: Principal): Connector;
|
|
115
124
|
update(elementId: string, patch: unknown, actor: Principal): CanvasElement;
|
|
@@ -164,4 +173,4 @@ interface BoardData {
|
|
|
164
173
|
/** The board as plain data for an agent. Reads only. Embedded image bytes are left out. */
|
|
165
174
|
declare function readBoard(board: Board): BoardData;
|
|
166
175
|
|
|
167
|
-
export {
|
|
176
|
+
export { Board as B, type Connector as C, type ErrorCode as E, type Group as G, MAX_ELEMENTS as M, type NodeData as N, type Principal as P, type Shape as S, type BoardData as a, type CanvasElement as b, type ShapeType as c, type Endpoint as d, CanvasError as e, type EdgeData as f, MAX_TEXT as g, SHAPE_TYPES as h, principalSchema as p, readBoard as r };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as ShapeType, B as Board, P as Principal, a as BoardData, S as Shape, C as Connector, b as CanvasElement } from './read-BupIJSPJ.js';
|
|
2
2
|
import { Store } from 'agentic-identity';
|
|
3
3
|
|
|
4
4
|
declare const MAX_FLOW_NODES = 500;
|
|
@@ -47,6 +47,11 @@ declare function drawFlow(board: Board, source: string, actor: Principal, option
|
|
|
47
47
|
edges: string[];
|
|
48
48
|
};
|
|
49
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;
|
|
50
55
|
/** One place for every board operation. The CLI, the MCP server, and the Worker call it. */
|
|
51
56
|
declare class CanvasService {
|
|
52
57
|
private readonly store;
|
|
@@ -58,6 +63,11 @@ declare class CanvasService {
|
|
|
58
63
|
id: string;
|
|
59
64
|
title: string;
|
|
60
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
|
+
}[]>;
|
|
61
71
|
/** Throws NOT_FOUND unless the board exists. A live room opens only for a board that exists. */
|
|
62
72
|
assertExists(id: string): Promise<void>;
|
|
63
73
|
read(id: string): Promise<BoardData & {
|
|
@@ -67,6 +77,8 @@ declare class CanvasService {
|
|
|
67
77
|
change<R>(id: string, change: (board: Board) => R): Promise<R>;
|
|
68
78
|
add(id: string, shape: unknown, actor: Principal): Promise<Shape>;
|
|
69
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>;
|
|
70
82
|
move(id: string, elementId: string, dx: number, dy: number, actor: Principal): Promise<{
|
|
71
83
|
moved: string[];
|
|
72
84
|
}>;
|
|
@@ -80,18 +92,25 @@ declare class CanvasService {
|
|
|
80
92
|
exportSvg(id: string): Promise<string>;
|
|
81
93
|
/** The stored board as a Yjs update. A client applies it to a room to seed it: the room does not read it. */
|
|
82
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>;
|
|
83
97
|
/**
|
|
84
|
-
*
|
|
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.
|
|
85
101
|
* An element stamped by anyone else is deleted, and a changed author is put back (see `Board.restamp`),
|
|
86
102
|
* so a client that writes raw Yjs cannot put another author on its work. Broken entries are repaired and
|
|
87
103
|
* a board past the element cap is refused. Returns the ids the checks fixed.
|
|
88
104
|
*
|
|
89
105
|
* Limits: the save corrects the stored board only. The room keeps what its clients wrote, so a client that sees
|
|
90
106
|
* a non-empty `fixed` must join again, or its later edits are lost at the next save. The room remembers its
|
|
91
|
-
* authors for good, so
|
|
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.
|
|
92
111
|
* A client that adds a root type of its own makes every later save of that room fail, because the room keeps it.
|
|
93
112
|
*/
|
|
94
|
-
checkpoint(id: string, update: Uint8Array, actor: Principal, authors?: Principal[]): Promise<{
|
|
113
|
+
checkpoint(id: string, update: Uint8Array, actor: Principal | null, authors?: Principal[], writer?: Writer): Promise<{
|
|
95
114
|
elements: number;
|
|
96
115
|
fixed: string[];
|
|
97
116
|
}>;
|
|
@@ -104,6 +123,6 @@ declare class CanvasService {
|
|
|
104
123
|
private load;
|
|
105
124
|
}
|
|
106
125
|
/** What the CLI and the MCP server need. `CanvasService` runs it on a store, and `LiveService` runs it in a live room. */
|
|
107
|
-
type BoardAccess = Pick<CanvasService, "create" | "read" | "add" | "connect" | "move" | "remove" | "flow" | "exportSvg">;
|
|
126
|
+
type BoardAccess = Pick<CanvasService, "create" | "list" | "read" | "update" | "add" | "connect" | "move" | "remove" | "flow" | "exportSvg">;
|
|
108
127
|
|
|
109
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/ui.css
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* Every rule is nested under .cv-root, so the styles do not reach the host page. */
|
|
2
|
+
.cv-root {
|
|
3
|
+
.row { display: flex; align-items: center; justify-content: space-between; gap: var(--ad-space-4); flex-wrap: wrap; }
|
|
4
|
+
.failure { border: 1px solid var(--ad-color-danger); border-radius: var(--ad-radius-md); padding: var(--ad-space-4); color: var(--ad-color-danger-text); background: var(--ad-color-danger-subtle); display: grid; gap: var(--ad-space-3); justify-items: start; }
|
|
5
|
+
.note { color: var(--ad-color-text-muted); }
|
|
6
|
+
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
7
|
+
|
|
8
|
+
.board { display: grid; gap: var(--ad-space-3); }
|
|
9
|
+
.stage { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 16rem; gap: var(--ad-space-3); height: 65vh; min-height: 22rem; }
|
|
10
|
+
@media (max-width: 48rem) { .stage { grid-template-columns: 1fr; height: auto; } .canvas { height: 55vh; } }
|
|
11
|
+
.canvas { background: var(--ad-color-surface-sunken); border: 1px solid var(--ad-color-border); border-radius: var(--ad-radius-md); overflow: hidden; touch-action: none; min-height: 18rem; }
|
|
12
|
+
.canvas:focus-visible { outline: 3px solid var(--ad-color-focus); outline-offset: 2px; }
|
|
13
|
+
.canvas svg { display: block; cursor: grab; font-family: var(--ad-font-family-sans); font-size: 14px; }
|
|
14
|
+
.item { outline: none; cursor: pointer; }
|
|
15
|
+
.shape { fill: var(--ad-color-surface-raised); stroke: var(--ad-color-border-strong); stroke-width: 1.5; }
|
|
16
|
+
.shape.text { fill: transparent; stroke: none; }
|
|
17
|
+
.shape.frame, .shape.image { fill: none; stroke-dasharray: 6 4; pointer-events: visiblePainted; }
|
|
18
|
+
.shape.sticky { fill: #ffe08a; stroke: #7a5b00; }
|
|
19
|
+
.label { fill: var(--ad-color-text); pointer-events: none; }
|
|
20
|
+
.sticky-label { fill: #1b1b1b; }
|
|
21
|
+
.edge { stroke: var(--ad-color-text-muted); stroke-width: 2; fill: none; pointer-events: none; }
|
|
22
|
+
.hit { stroke: transparent; stroke-width: 14; }
|
|
23
|
+
.arrowhead { fill: var(--ad-color-text-muted); }
|
|
24
|
+
.edge-text { fill: var(--ad-color-text); paint-order: stroke; stroke: var(--ad-color-surface-sunken); stroke-width: 4px; pointer-events: none; }
|
|
25
|
+
.ring, .ring-line { fill: none; stroke: none; stroke-width: 3; pointer-events: none; }
|
|
26
|
+
.item.selected .ring, .item.selected .ring-line, .item:focus-visible .ring, .item:focus-visible .ring-line { stroke: var(--ad-color-focus); }
|
|
27
|
+
.item:focus-visible .ring, .item:focus-visible .ring-line { stroke-width: 4; }
|
|
28
|
+
.handle { fill: var(--ad-color-focus); stroke: var(--ad-color-bg); stroke-width: 2; cursor: nwse-resize; }
|
|
29
|
+
.agent-badge rect { fill: var(--ad-color-agent-subtle); stroke: var(--ad-color-agent); }
|
|
30
|
+
.agent-badge text { fill: var(--ad-color-agent-text); font-size: 11px; font-weight: 600; pointer-events: none; }
|
|
31
|
+
.empty-overlay { position: absolute; inset: 0 16rem 0 0; display: grid; place-items: center; pointer-events: none; }
|
|
32
|
+
@media (max-width: 48rem) { .empty-overlay { inset: 0; bottom: auto; height: 55vh; } }
|
|
33
|
+
.inspector { border: 1px solid var(--ad-color-border); border-radius: var(--ad-radius-md); padding: var(--ad-space-3); background: var(--ad-color-surface); display: grid; gap: var(--ad-space-3); align-content: start; overflow: auto; }
|
|
34
|
+
.inspector h2 { margin: 0; font-size: var(--ad-font-size-lg); }
|
|
35
|
+
.inspector form { display: grid; gap: var(--ad-space-3); }
|
|
36
|
+
.inspector .by { margin: 0; color: var(--ad-color-text-muted); font-size: var(--ad-font-size-sm); }
|
|
37
|
+
.sizes { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ad-space-2); }
|
|
38
|
+
}
|
package/dist/worker.d.ts
CHANGED
|
@@ -2,8 +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 } from './read-
|
|
6
|
-
import { C as CanvasService } from './service-
|
|
5
|
+
import { P as Principal } from './read-BupIJSPJ.js';
|
|
6
|
+
import { C as CanvasService } from './service-CR4-r1yx.js';
|
|
7
7
|
import 'yjs';
|
|
8
8
|
import 'zod';
|
|
9
9
|
|
|
@@ -40,6 +40,8 @@ interface AppOptions {
|
|
|
40
40
|
/** Makes the live-room server from the Worker bindings. Without it, the ws route answers 404. */
|
|
41
41
|
live?: (env: WorkerEnv) => Realtime;
|
|
42
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";
|
|
43
45
|
/** The principal and role for a bearer token, or null. The kind is never defaulted: a grant without a valid kind gets null. */
|
|
44
46
|
declare function authenticate(request: Request, env: WorkerEnv): {
|
|
45
47
|
actor: Principal;
|
|
@@ -52,4 +54,4 @@ declare const _default: {
|
|
|
52
54
|
fetch: (request: Request, env: WorkerEnv, ctx: unknown) => Response | Promise<Response>;
|
|
53
55
|
};
|
|
54
56
|
|
|
55
|
-
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,16 @@
|
|
|
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-GGQPE65T.js";
|
|
7
|
+
} from "./chunk-V74PWJKY.js";
|
|
8
|
+
import "./chunk-G4YTESPS.js";
|
|
9
9
|
import "./chunk-NWQED42L.js";
|
|
10
|
+
import "./chunk-JCYNPYYJ.js";
|
|
11
|
+
import "./chunk-SPP6PINW.js";
|
|
10
12
|
export {
|
|
13
|
+
WS_PROTOCOL,
|
|
11
14
|
authenticate,
|
|
12
15
|
createApp,
|
|
13
16
|
worker_default as default,
|
package/llms.txt
CHANGED
|
@@ -5,10 +5,13 @@ 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
|
-
-
|
|
8
|
+
- Exports: the README "Exports" section lists every name of each entry point: agentic-canvas, /client, /file-store, /live, /worker and /live-worker.
|
|
9
|
+
- CLI: agentic-canvas new|list|read|add|connect|update|move|rm|flow|export.
|
|
10
|
+
- 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
11
|
- Live: set CANVAS_SERVER and CANVAS_TOKEN, and the CLI and `agentic-canvas mcp` edit the board in its live room.
|
|
10
12
|
- SDK: import { LiveBoard, LiveService } from "agentic-canvas/live".
|
|
11
|
-
- SDK: import { createClient, CanvasApiError } from "agentic-canvas/client". It calls the Worker API with fetch. Methods: me, createBoard, readBoard, exportSvg, addShape, addConnector, drawFlow, move, remove, uploadImage, getImage, state, checkpoint. A failure throws CanvasApiError with `code` and `status`. No retries.
|
|
13
|
+
- 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.
|
|
14
|
+
- UI: import { mount } from "agentic-canvas/ui"; import "agentic-canvas/ui.css" (with agentic-design/styles.css). mount(element, { boardId, client, principal: { kind, name, role }, readOnly?, room?: { baseUrl, token } }) renders the board and returns { update(options), unmount() }. BoardEditor is the same as a React component. React 19 is a peer dependency.
|
|
12
15
|
|
|
13
16
|
## Docs
|
|
14
17
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-canvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A shared whiteboard for diagrams, drawn by people and agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"whiteboard",
|
|
@@ -58,41 +58,67 @@
|
|
|
58
58
|
"./file-store": {
|
|
59
59
|
"types": "./dist/store-file.d.ts",
|
|
60
60
|
"import": "./dist/store-file.js"
|
|
61
|
-
}
|
|
61
|
+
},
|
|
62
|
+
"./ui": {
|
|
63
|
+
"types": "./dist/embed.d.ts",
|
|
64
|
+
"import": "./dist/embed.js"
|
|
65
|
+
},
|
|
66
|
+
"./ui.css": "./dist/ui.css"
|
|
62
67
|
},
|
|
63
68
|
"bin": {
|
|
64
69
|
"agentic-canvas": "./dist/cli.js"
|
|
65
70
|
},
|
|
66
71
|
"scripts": {
|
|
67
|
-
"build": "tsup",
|
|
68
|
-
"typecheck": "tsc --noEmit",
|
|
72
|
+
"build": "tsup && vite build && node ui/build-css.mjs",
|
|
73
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p ui",
|
|
69
74
|
"test": "vitest run",
|
|
70
75
|
"clean": "rm -rf dist",
|
|
71
|
-
"ci:local": "npm run build && npm run typecheck && npm test"
|
|
76
|
+
"ci:local": "npm run build && npm run typecheck && npm test && npm run test:e2e",
|
|
77
|
+
"deploy:demo": "wrangler deploy -c wrangler.demo.jsonc",
|
|
78
|
+
"test:e2e": "playwright test -c e2e/playwright.config.ts"
|
|
72
79
|
},
|
|
73
80
|
"dependencies": {
|
|
74
81
|
"@dagrejs/dagre": "^3.1.3",
|
|
75
82
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
76
|
-
"agentic-
|
|
77
|
-
"agentic-
|
|
83
|
+
"agentic-design": "^0.2.0",
|
|
84
|
+
"agentic-identity": "^0.5.0",
|
|
85
|
+
"agentic-realtime": "^0.3.0",
|
|
78
86
|
"yjs": "^13.6.0",
|
|
79
87
|
"zod": "^3.25.0"
|
|
80
88
|
},
|
|
81
89
|
"peerDependencies": {
|
|
82
|
-
"playwright-core": ">=1.40.0"
|
|
90
|
+
"playwright-core": ">=1.40.0",
|
|
91
|
+
"react": ">=19",
|
|
92
|
+
"react-dom": ">=19"
|
|
83
93
|
},
|
|
84
94
|
"peerDependenciesMeta": {
|
|
85
95
|
"playwright-core": {
|
|
86
96
|
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"react": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"react-dom": {
|
|
102
|
+
"optional": true
|
|
87
103
|
}
|
|
88
104
|
},
|
|
89
105
|
"devDependencies": {
|
|
106
|
+
"@axe-core/playwright": "^4.14.0",
|
|
107
|
+
"@playwright/test": "^1.64.1",
|
|
108
|
+
"@types/jsdom": "^21.1.7",
|
|
90
109
|
"@types/node": "^22.0.0",
|
|
110
|
+
"@types/react": "^19.3.0",
|
|
111
|
+
"@types/react-dom": "^19.3.0",
|
|
112
|
+
"@vitejs/plugin-react": "^5.2.0",
|
|
91
113
|
"hono": "^4.13.14",
|
|
114
|
+
"jsdom": "^26.0.0",
|
|
92
115
|
"miniflare": "^4.20260730.0",
|
|
93
116
|
"playwright-core": "^1.64.1",
|
|
117
|
+
"react": "^19.3.1",
|
|
118
|
+
"react-dom": "^19.3.1",
|
|
94
119
|
"tsup": "^8.0.0",
|
|
95
120
|
"typescript": "^5.6.0",
|
|
121
|
+
"vite": "^7.3.7",
|
|
96
122
|
"vitest": "^3.0.0",
|
|
97
123
|
"wrangler": "^4.155.0"
|
|
98
124
|
}
|