agentic-canvas 0.9.0 → 0.11.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/dist/embed.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import {
2
- PRINCIPAL_KINDS
3
- } from "./chunk-JOBTIAFJ.js";
2
+ Board,
3
+ PRINCIPAL_KINDS,
4
+ principalSchema,
5
+ readBoard
6
+ } from "./chunk-MVWUIBGV.js";
4
7
 
5
8
  // ui/embed.tsx
6
9
  import { ToastProvider, TooltipProvider } from "agentic-design/react";
@@ -9,7 +12,7 @@ import { createRoot } from "react-dom/client";
9
12
 
10
13
  // ui/BoardView.tsx
11
14
  import { Button as Button2, EmptyState, Input, PresenceChip, PresenceStack, Select, Textarea, Toolbar, ToolbarButton, ToolbarSeparator, useToast } from "agentic-design/react";
12
- import { useCallback, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
15
+ import { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
13
16
 
14
17
  // ui/errors.ts
15
18
  var isApiError = (error) => typeof error === "object" && error !== null && error.name === "CanvasApiError" && typeof error.code === "string" && typeof error.status === "number";
@@ -226,6 +229,29 @@ function Failure({ message, retry }) {
226
229
  ] });
227
230
  }
228
231
 
232
+ // ui/host.ts
233
+ import * as Y from "yjs";
234
+ function checkHost(host) {
235
+ if (!host || !(host.doc instanceof Y.Doc)) throw new TypeError("a host board needs a Yjs document in `doc`");
236
+ const presence = host.presence;
237
+ if (presence !== void 0 && (!Array.isArray(presence?.peers) || typeof presence.onPeers !== "function")) {
238
+ throw new TypeError("a host presence needs peers and onPeers, as a SyncClient has");
239
+ }
240
+ if (host.status !== void 0 && typeof host.status !== "function" || host.onStatus !== void 0 && typeof host.onStatus !== "function") {
241
+ throw new TypeError("a host status and onStatus must be functions");
242
+ }
243
+ }
244
+ function boardCalls(board, who) {
245
+ return {
246
+ readBoard: async (id) => ({ id, ...readBoard(board) }),
247
+ addShape: async (_id, shape) => board.addShape(shape, who()),
248
+ addConnector: async (_id, connector) => board.addConnector(connector, who()),
249
+ update: async (_id, element, patch) => board.update(element, patch, who()),
250
+ move: async (_id, element, dx, dy) => ({ moved: board.move(element, dx, dy, who()) }),
251
+ remove: async (_id, element) => ({ removed: board.remove(element) })
252
+ };
253
+ }
254
+
229
255
  // ui/presence.ts
230
256
  import { SyncClient } from "agentic-realtime/client";
231
257
  var WS_PROTOCOL = "agentic-canvas";
@@ -288,7 +314,7 @@ var TOOLS = [
288
314
  var POLL_MS = 5e3;
289
315
  var DEFAULT_SIZE = { rect: [140, 70], ellipse: [140, 70], diamond: [140, 90], text: [140, 40], sticky: [150, 120] };
290
316
  var DEFAULT_TEXT = { rect: "Rectangle", ellipse: "Ellipse", diamond: "Decision", text: "Text", sticky: "Note" };
291
- function BoardView({ id, client, room: roomOptions, me, backHref }) {
317
+ function BoardView({ id, client: remote, host, room: roomOptions, me, backHref }) {
292
318
  const roomUrl2 = roomOptions?.baseUrl;
293
319
  const roomToken = roomOptions?.token;
294
320
  const toast = useToast();
@@ -302,6 +328,17 @@ function BoardView({ id, client, room: roomOptions, me, backHref }) {
302
328
  const queue = useRef2(Promise.resolve());
303
329
  const canvasBox = useRef2(null);
304
330
  const editable = me.role === "editor";
331
+ const hostDoc = host?.doc;
332
+ const hostPresence = host?.presence;
333
+ const hostRef = useRef2(host);
334
+ hostRef.current = host;
335
+ const who = useRef2({ kind: me.kind, id: me.id ?? me.actor });
336
+ who.current = { kind: me.kind, id: me.id ?? me.actor };
337
+ const client = useMemo(() => {
338
+ if (hostDoc) return boardCalls(new Board(hostDoc), () => who.current);
339
+ if (!remote) throw new TypeError("the board needs a client or a host board");
340
+ return remote;
341
+ }, [remote, hostDoc]);
305
342
  const [saving, setSaving] = useState2(0);
306
343
  const pending = useRef2(0);
307
344
  const generation = useRef2(0);
@@ -319,7 +356,7 @@ function BoardView({ id, client, room: roomOptions, me, backHref }) {
319
356
  }, [client, id]);
320
357
  const load = useCallback(async () => {
321
358
  if (pending.current > 0) return;
322
- const wait = lastRead.current + 1e3 - Date.now();
359
+ const wait = hostDoc ? 0 : lastRead.current + 1e3 - Date.now();
323
360
  if (wait > 0) {
324
361
  clearTimeout(timer.current);
325
362
  timer.current = setTimeout(() => void load(), wait);
@@ -327,7 +364,7 @@ function BoardView({ id, client, room: roomOptions, me, backHref }) {
327
364
  }
328
365
  lastRead.current = Date.now();
329
366
  await read();
330
- }, [read]);
367
+ }, [read, hostDoc]);
331
368
  useEffect2(() => {
332
369
  setBoard({ state: "loading" });
333
370
  lastRead.current = 0;
@@ -341,15 +378,45 @@ function BoardView({ id, client, room: roomOptions, me, backHref }) {
341
378
  return () => window.removeEventListener("beforeunload", guard);
342
379
  }, [saving]);
343
380
  useEffect2(() => {
344
- if (roomUrl2 === void 0 || roomToken === void 0) return;
345
- const joined = joinRoom({ board: id, baseUrl: roomUrl2, token: roomToken, name: me.actor, onPeers: setPeers, onChange: () => void load(), onStatus: setLive });
381
+ if (!hostDoc) return;
382
+ let queued = false;
383
+ const changed = () => {
384
+ if (queued) return;
385
+ queued = true;
386
+ queueMicrotask(() => (queued = false, void load()));
387
+ };
388
+ const elements = hostDoc.getMap("elements");
389
+ const meta = hostDoc.getMap("meta");
390
+ elements.observeDeep(changed);
391
+ meta.observe(changed);
392
+ return () => (elements.unobserveDeep(changed), meta.unobserve(changed));
393
+ }, [hostDoc, load]);
394
+ useEffect2(() => {
395
+ if (!hostPresence) return;
396
+ setPeers(hostPresence.peers.map(toEntry));
397
+ const off = hostPresence.onPeers((list) => setPeers(list.map(toEntry)));
398
+ return () => (off(), setPeers([]));
399
+ }, [hostPresence]);
400
+ useEffect2(() => {
401
+ if (!hostDoc) return;
402
+ const reset = () => setLive(false);
403
+ const { status: ask, onStatus: listen } = hostRef.current ?? {};
404
+ setLive(ask ? ask() === "connected" : !listen);
405
+ const stop = listen?.((next) => setLive(next === "connected"));
406
+ return () => (stop?.(), reset());
407
+ }, [hostDoc]);
408
+ useEffect2(() => {
409
+ if (hostDoc || roomUrl2 === void 0 || roomToken === void 0) return;
410
+ let left = false;
411
+ const joined = joinRoom({ board: id, baseUrl: roomUrl2, token: roomToken, name: me.actor, onPeers: (list) => !left && setPeers(list), onChange: () => !left && void load(), onStatus: (up) => !left && setLive(up) });
346
412
  room.current = joined;
347
- return () => (joined.leave(), room.current = void 0);
348
- }, [id, roomUrl2, roomToken, me.actor, load]);
413
+ return () => (left = true, joined.leave(), setPeers([]), room.current = void 0);
414
+ }, [id, hostDoc, roomUrl2, roomToken, me.actor, load]);
349
415
  useEffect2(() => {
416
+ if (hostDoc) return;
350
417
  const timer2 = setInterval(() => void load(), POLL_MS);
351
418
  return () => clearInterval(timer2);
352
- }, [load]);
419
+ }, [load, hostDoc]);
353
420
  const write = useCallback(
354
421
  (change, failure, select) => {
355
422
  pending.current++;
@@ -425,7 +492,7 @@ function BoardView({ id, client, room: roomOptions, me, backHref }) {
425
492
  /* @__PURE__ */ jsx3(ToolbarButton, { label: "Reset view", icon: icon(/* @__PURE__ */ jsx3("path", { d: "M4 4h5M4 4v5M16 16h-5M16 16v-5" })), onClick: () => setView(HOME) })
426
493
  ] }),
427
494
  /* @__PURE__ */ jsx3("p", { className: "note", role: "status", children: editable ? status : "" }),
428
- !editable && /* @__PURE__ */ jsx3("p", { className: "note", children: "This token can read the board but not change it." }),
495
+ !editable && /* @__PURE__ */ jsx3("p", { className: "note", children: host ? "This board is read only." : "This token can read the board but not change it." }),
429
496
  /* @__PURE__ */ jsxs3("div", { className: "stage", ref: canvasBox, children: [
430
497
  /* @__PURE__ */ jsx3(Canvas, { data: d, selected, editable, view, onView: setView, onSelect: setSelected, onMove: move, onResize: resize, onDelete: remove }),
431
498
  empty && /* @__PURE__ */ jsx3("div", { className: "empty-overlay", children: /* @__PURE__ */ jsx3(EmptyState, { title: "This board is empty", description: editable ? "Add a shape or a note with the tools above." : "Nothing has been drawn yet." }) }),
@@ -487,10 +554,18 @@ function Inspector({ item, nodes, editable, onText, onPlace, onDelete, onConnect
487
554
 
488
555
  // ui/embed.tsx
489
556
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
490
- function checkPrincipal(principal) {
557
+ function checkPrincipal(principal, options) {
491
558
  if (!principal || !PRINCIPAL_KINDS.includes(principal.kind) || typeof principal.name !== "string" || principal.name.trim() === "") {
492
559
  throw new TypeError(`the board needs a principal with a kind (${PRINCIPAL_KINDS.join(", ")}) and a name`);
493
560
  }
561
+ if (!options) return;
562
+ if (options.host) {
563
+ checkHost(options.host);
564
+ if (options.client) throw new TypeError("a host board writes to its own document, not through a `client`: give one of them");
565
+ const stamp = principalSchema.safeParse({ kind: options.principal.kind, id: options.principal.id ?? options.principal.name });
566
+ if (!stamp.success) throw new TypeError(`the principal needs an \`id\` of letters, digits, ".", "_" and "-" to stamp its writes: ${stamp.error.issues[0]?.message}`);
567
+ if (options.room) throw new TypeError("a host board has no live room of its own: give its presence in `host.presence`, not `room`");
568
+ } else if (!options.client) throw new TypeError("the board needs a `client`, or a `host` board");
494
569
  }
495
570
  var Boundary = class extends Component {
496
571
  state = { failed: false };
@@ -504,16 +579,16 @@ var Boundary = class extends Component {
504
579
  ] }) }) : this.props.children;
505
580
  }
506
581
  };
507
- function Board({ boardId, client, principal, readOnly, room, backHref }) {
508
- checkPrincipal(principal);
582
+ function Board2({ boardId, client, host, principal, readOnly, room, backHref }) {
583
+ checkPrincipal(principal, { boardId, client, host, principal, room });
509
584
  const role = principal.role === "editor" && !readOnly ? "editor" : "viewer";
510
- return /* @__PURE__ */ jsx4(BoardView, { id: boardId, client, room, backHref, me: { actor: principal.name, kind: principal.kind, role } }, boardId);
585
+ return /* @__PURE__ */ jsx4(BoardView, { id: boardId, client, host, room, backHref, me: { actor: principal.name, id: principal.id, kind: principal.kind, role } }, boardId);
511
586
  }
512
587
  function BoardEditor(options) {
513
- return /* @__PURE__ */ jsx4("div", { className: "cv-root", children: /* @__PURE__ */ jsx4(Boundary, { children: /* @__PURE__ */ jsx4(Board, { ...options }) }) });
588
+ return /* @__PURE__ */ jsx4("div", { className: "cv-root", children: /* @__PURE__ */ jsx4(Boundary, { children: /* @__PURE__ */ jsx4(Board2, { ...options }) }) });
514
589
  }
515
590
  function mount(element, options) {
516
- checkPrincipal(options.principal);
591
+ checkPrincipal(options.principal, options);
517
592
  const root = createRoot(element);
518
593
  const render = (next) => root.render(
519
594
  /* @__PURE__ */ jsx4(TooltipProvider, { children: /* @__PURE__ */ jsx4(ToastProvider, { children: /* @__PURE__ */ jsx4(BoardEditor, { ...next }) }) })
@@ -521,7 +596,7 @@ function mount(element, options) {
521
596
  render(options);
522
597
  let open = true;
523
598
  return {
524
- update: (next) => (checkPrincipal(next.principal), open && render(next)),
599
+ update: (next) => (checkPrincipal(next.principal, next), open && render(next)),
525
600
  unmount: () => {
526
601
  if (!open) return;
527
602
  open = false;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { B as Board, P as Principal } from './read--Jd3kE13.js';
2
- export { a as BoardData, b as CanvasElement, e as CanvasError, C as Connector, f as EdgeData, d as Endpoint, E as ErrorCode, G as Group, M as MAX_ELEMENTS, g as MAX_TEXT, N as NodeData, h as SHAPE_TYPES, S as Shape, c as ShapeType, p as principalSchema, r as readBoard } from './read--Jd3kE13.js';
3
- import { B as BoardAccess } from './service-OiTtNadu.js';
4
- export { C as CanvasService, D as DrawOptions, F as FlowEdge, a as FlowGraph, b as FlowNode, M as MAX_FLOW_EDGES, c as MAX_FLOW_NODES, P as Placement, d as drawFlow, l as layoutFlow, p as parseFlow } from './service-OiTtNadu.js';
1
+ import { B as Board, P as Principal } from './read-UIJlrkwx.js';
2
+ export { a as BoardData, b as CanvasElement, d as CanvasError, C as Connector, e as EdgeData, E as Endpoint, f as ErrorCode, G as Group, M as MAX_ELEMENTS, g as MAX_TEXT, N as NodeData, h as SHAPE_TYPES, S as Shape, c as ShapeType, p as principalSchema, r as readBoard } from './read-UIJlrkwx.js';
3
+ import { B as BoardAccess } from './service-ojpxVNVl.js';
4
+ export { C as CanvasService, D as DrawOptions, F as FlowEdge, a as FlowGraph, b as FlowNode, M as MAX_FLOW_EDGES, c as MAX_FLOW_NODES, P as Placement, d as drawFlow, l as layoutFlow, p as parseFlow } from './service-ojpxVNVl.js';
5
5
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
+ import { B as BoardSharing } from './client-Dyd30StF.js';
6
7
  export { FileStoreOptions, createFileStore, openLocalStore } from './store-file.js';
7
8
  export { PRINCIPAL_KINDS, PrincipalKind, isMachineMade } from 'agentic-identity';
8
9
  import 'yjs';
@@ -39,10 +40,11 @@ declare function operatorActor(env?: Record<string, string | undefined>): Princi
39
40
 
40
41
  /**
41
42
  * The tools mirror the CLI. The actor is fixed here by the operator. No tool takes an actor,
42
- * author, or kind, so a caller cannot choose who it writes as.
43
+ * author, or kind, so a caller cannot choose who it writes as. The sharing tools run on a server, as the owner of its token:
44
+ * with no `sharing` client they fail with UNAVAILABLE.
43
45
  */
44
- declare function createMcpServer(service: BoardAccess, actor: Principal): McpServer;
46
+ declare function createMcpServer(service: BoardAccess, actor: Principal, sharing?: BoardSharing): McpServer;
45
47
  /** Serve the tools on stdin and stdout. Stdout carries protocol frames only. */
46
- declare function runMcp(service: BoardAccess, actor: Principal): Promise<void>;
48
+ declare function runMcp(service: BoardAccess, actor: Principal, sharing?: BoardSharing): Promise<void>;
47
49
 
48
50
  export { ActorConfigError, BRAND, Board, Principal, VERSION, createMcpServer, operatorActor, runMcp, svgToPng, toSvg };
package/dist/index.js CHANGED
@@ -6,34 +6,34 @@ import {
6
6
  operatorActor,
7
7
  runMcp,
8
8
  svgToPng
9
- } from "./chunk-33ANMQEY.js";
9
+ } from "./chunk-EE725BJ3.js";
10
10
  import {
11
11
  createFileStore,
12
12
  openLocalStore
13
13
  } from "./chunk-NRLF6MGR.js";
14
14
  import {
15
15
  CanvasService
16
- } from "./chunk-M74ENUWR.js";
16
+ } from "./chunk-Z6KLGAFP.js";
17
17
  import "./chunk-NWQED42L.js";
18
18
  import {
19
- Board,
20
- CanvasError,
21
- MAX_ELEMENTS,
22
19
  MAX_FLOW_EDGES,
23
20
  MAX_FLOW_NODES,
24
- MAX_TEXT,
25
- SHAPE_TYPES,
26
21
  drawFlow,
27
22
  layoutFlow,
28
23
  parseFlow,
29
- readBoard,
30
24
  toSvg
31
- } from "./chunk-ZSPZMGHG.js";
25
+ } from "./chunk-EDQNA2SU.js";
32
26
  import {
27
+ Board,
28
+ CanvasError,
29
+ MAX_ELEMENTS,
30
+ MAX_TEXT,
33
31
  PRINCIPAL_KINDS,
32
+ SHAPE_TYPES,
34
33
  isMachineMade,
35
- principalSchema
36
- } from "./chunk-JOBTIAFJ.js";
34
+ principalSchema,
35
+ readBoard
36
+ } from "./chunk-MVWUIBGV.js";
37
37
  export {
38
38
  ActorConfigError,
39
39
  BRAND,
@@ -5,10 +5,10 @@ import 'agentic-identity';
5
5
  import 'agentic-realtime';
6
6
  import 'agentic-identity/cloudflare';
7
7
  import 'hono';
8
- import './read--Jd3kE13.js';
8
+ import './read-UIJlrkwx.js';
9
9
  import 'yjs';
10
10
  import 'zod';
11
- import './service-OiTtNadu.js';
11
+ import './service-ojpxVNVl.js';
12
12
 
13
13
  type Namespace = Parameters<typeof createDurableObjectRealtime>[0];
14
14
  interface LiveEnv extends WorkerEnv {
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  createApp
3
- } from "./chunk-JQCUVXXD.js";
4
- import "./chunk-M74ENUWR.js";
3
+ } from "./chunk-5II2WZIL.js";
4
+ import "./chunk-Z6KLGAFP.js";
5
5
  import "./chunk-NWQED42L.js";
6
+ import "./chunk-EDQNA2SU.js";
6
7
  import {
7
8
  CanvasError
8
- } from "./chunk-ZSPZMGHG.js";
9
- import "./chunk-JOBTIAFJ.js";
9
+ } from "./chunk-MVWUIBGV.js";
10
10
 
11
11
  // src/live-worker.ts
12
12
  import { parseRegion } from "agentic-identity";
package/dist/live.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { B as Board, P as Principal, a as BoardData, S as Shape, C as Connector, b as CanvasElement } from './read--Jd3kE13.js';
1
+ import { B as Board, P as Principal, a as BoardData, S as Shape, C as Connector, b as CanvasElement } from './read-UIJlrkwx.js';
2
2
  import { Peer } from 'agentic-realtime/client';
3
- import { B as BoardAccess, D as DrawOptions } from './service-OiTtNadu.js';
3
+ import { B as BoardAccess, D as DrawOptions } from './service-ojpxVNVl.js';
4
4
  import 'yjs';
5
5
  import 'agentic-identity';
6
6
  import 'zod';
package/dist/live.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import {
2
- Board,
3
- CanvasError,
4
2
  drawFlow,
5
- readBoard,
6
3
  toSvg
7
- } from "./chunk-ZSPZMGHG.js";
8
- import "./chunk-JOBTIAFJ.js";
4
+ } from "./chunk-EDQNA2SU.js";
5
+ import {
6
+ Board,
7
+ CanvasError,
8
+ readBoard
9
+ } from "./chunk-MVWUIBGV.js";
9
10
 
10
11
  // src/live.ts
11
12
  import { parsePrincipal } from "agentic-identity";
@@ -181,4 +181,4 @@ interface BoardData {
181
181
  /** The board as plain data for an agent. Reads only. Embedded image bytes are left out. */
182
182
  declare function readBoard(board: Board): BoardData;
183
183
 
184
- 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 };
184
+ export { Board as B, type Connector as C, type Endpoint 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, CanvasError as d, type EdgeData as e, type ErrorCode as f, MAX_TEXT as g, SHAPE_TYPES as h, principalSchema as p, readBoard as r };
@@ -1,4 +1,4 @@
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--Jd3kE13.js';
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-UIJlrkwx.js';
2
2
  import { Store } from 'agentic-identity';
3
3
 
4
4
  declare const MAX_FLOW_NODES = 500;
package/dist/worker.d.ts CHANGED
@@ -2,8 +2,8 @@ import { Store, PrincipalContext, Action, Grant, InviteSummary, Blobs } from 'ag
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--Jd3kE13.js';
6
- import { C as CanvasService } from './service-OiTtNadu.js';
5
+ import { P as Principal } from './read-UIJlrkwx.js';
6
+ import { C as CanvasService } from './service-ojpxVNVl.js';
7
7
  import 'yjs';
8
8
  import 'zod';
9
9
 
package/dist/worker.js CHANGED
@@ -5,11 +5,11 @@ import {
5
5
  identify,
6
6
  sniffImage,
7
7
  worker_default
8
- } from "./chunk-JQCUVXXD.js";
9
- import "./chunk-M74ENUWR.js";
8
+ } from "./chunk-5II2WZIL.js";
9
+ import "./chunk-Z6KLGAFP.js";
10
10
  import "./chunk-NWQED42L.js";
11
- import "./chunk-ZSPZMGHG.js";
12
- import "./chunk-JOBTIAFJ.js";
11
+ import "./chunk-EDQNA2SU.js";
12
+ import "./chunk-MVWUIBGV.js";
13
13
  export {
14
14
  WS_PROTOCOL,
15
15
  authenticate,
package/llms.txt CHANGED
@@ -6,12 +6,12 @@ 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|delete|flow|export.
9
+ - CLI: agentic-canvas new|list|read|add|connect|update|move|rm|delete|flow|export, and with CANVAS_SERVER: access|grant|revoke|invite. MCP tools for sharing: list_access, grant_access, revoke_access, create_invite.
10
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: an agentic-identity credential (scope canvas:write or canvas:read). A static CANVAS_API_TOKENS list works only with CANVAS_UNSAFE_STATIC_TOKENS=1 (dev).
11
11
  - Live: set CANVAS_SERVER and CANVAS_TOKEN, and the CLI and `agentic-canvas mcp` edit the board in its live room.
12
12
  - SDK: import { LiveBoard, LiveService } from "agentic-canvas/live".
13
- - SDK: import { createClient, CanvasApiError } from "agentic-canvas/client". It calls the Worker API with fetch. Methods: me, listBoards, createBoard, readBoard, deleteBoard, 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.
13
+ - SDK: import { createClient, CanvasApiError } from "agentic-canvas/client". It calls the Worker API with fetch. Methods: me, listBoards, createBoard, readBoard, deleteBoard, exportSvg, addShape, addConnector, drawFlow, update, move, remove, access, grant, revoke, invite, 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, id? }, readOnly?, room?: { baseUrl, token } }) (or host: { doc, presence?, status?, onStatus? } instead of client and room; in host mode id (default name) must be letters, digits, . _ -, to edit the app's own Yjs document with no HTTP call) renders the board and returns { update(options), unmount() }. BoardEditor is the same as a React component. React 19 is a peer dependency.
15
15
 
16
16
  ## Docs
17
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-canvas",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "A shared whiteboard for diagrams, drawn by people and agents.",
5
5
  "keywords": [
6
6
  "whiteboard",
@@ -70,7 +70,7 @@
70
70
  "agentic-canvas": "./dist/cli.js"
71
71
  },
72
72
  "scripts": {
73
- "build": "tsup && vite build && node ui/build-css.mjs",
73
+ "build": "rm -rf dist && tsup && vite build && node ui/build-css.mjs",
74
74
  "typecheck": "tsc --noEmit && tsc --noEmit -p ui",
75
75
  "test": "vitest run",
76
76
  "clean": "rm -rf dist",
@@ -82,7 +82,7 @@
82
82
  "@dagrejs/dagre": "^3.1.3",
83
83
  "@modelcontextprotocol/sdk": "^1.12.0",
84
84
  "agentic-design": "^0.4.0",
85
- "agentic-identity": "^0.7.0",
85
+ "agentic-identity": "^0.8.0",
86
86
  "agentic-realtime": "^0.4.2",
87
87
  "yjs": "^13.6.0",
88
88
  "zod": "^4.6.7"
@@ -1,19 +0,0 @@
1
- // src/core/principal.ts
2
- import { PRINCIPAL_KINDS, isMachineMade, parsePrincipal } from "agentic-identity";
3
- import { z } from "zod";
4
- var principalSchema = z.object({ kind: z.string(), id: z.string() }).strict().transform((value, ctx) => {
5
- try {
6
- return parsePrincipal(value);
7
- } catch (error) {
8
- ctx.addIssue({ code: "custom", message: error instanceof Error ? error.message : "invalid principal" });
9
- return z.NEVER;
10
- }
11
- });
12
- var storedPrincipalSchema = z.object({ kind: z.enum(PRINCIPAL_KINDS), id: z.string().min(1).max(200) }).strict();
13
-
14
- export {
15
- PRINCIPAL_KINDS,
16
- isMachineMade,
17
- principalSchema,
18
- storedPrincipalSchema
19
- };