agentic-canvas 0.1.0 → 0.2.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.
@@ -0,0 +1,164 @@
1
+ import {
2
+ Board,
3
+ CanvasError,
4
+ drawFlow,
5
+ principalSchema,
6
+ readBoard,
7
+ toSvg
8
+ } from "./chunk-GGQPE65T.js";
9
+ import {
10
+ FileStoreError
11
+ } from "./chunk-NWQED42L.js";
12
+
13
+ // src/service.ts
14
+ import * as Y from "yjs";
15
+ import { assertId, StoreConflictError } from "agentic-identity";
16
+ var COLLECTION = "boards";
17
+ var MAX_LIVE_BYTES = 1572864;
18
+ var BOARD_ID = /^[A-Za-z0-9_-]{1,64}$/;
19
+ function toBase64(bytes) {
20
+ let text = "";
21
+ for (let i = 0; i < bytes.length; i += 8192) text += String.fromCharCode(...bytes.subarray(i, i + 8192));
22
+ return btoa(text);
23
+ }
24
+ var fromBase64 = (text) => Uint8Array.from(atob(text), (c) => c.charCodeAt(0));
25
+ function boardKey(id) {
26
+ try {
27
+ if (!BOARD_ID.test(id)) throw new Error();
28
+ assertId(id);
29
+ } catch {
30
+ throw new CanvasError("INVALID", "board id must be 1 to 64 of A-Z, a-z, 0-9, _ and -, and not like __x__");
31
+ }
32
+ return id;
33
+ }
34
+ function storeFailure(error) {
35
+ if (error instanceof StoreConflictError) throw new CanvasError("UNAVAILABLE", "the board changed at the same time. Try again");
36
+ if (error instanceof FileStoreError) throw new CanvasError(error.code === "LOCKED" ? "UNAVAILABLE" : "INVALID", error.message);
37
+ throw error;
38
+ }
39
+ var CanvasService = class {
40
+ store;
41
+ constructor(store) {
42
+ this.store = { ...store, transaction: (fn) => store.transaction(fn).catch(storeFailure) };
43
+ }
44
+ async create(actor, options = {}) {
45
+ const id = boardKey(options.id ?? crypto.randomUUID());
46
+ const board = new Board();
47
+ if (options.title !== void 0) board.setTitle(options.title, actor);
48
+ return this.store.transaction(async (tx) => {
49
+ if (await tx.get(COLLECTION, id)) throw new CanvasError("DUPLICATE_ID", `board "${id}" already exists`);
50
+ await tx.put(COLLECTION, id, { update: toBase64(board.encode()) });
51
+ return { id, title: board.title };
52
+ });
53
+ }
54
+ /** Throws NOT_FOUND unless the board exists. A live room opens only for a board that exists. */
55
+ async assertExists(id) {
56
+ boardKey(id);
57
+ if (!await this.store.transaction((tx) => tx.get(COLLECTION, id))) throw new CanvasError("NOT_FOUND", `no board "${id}"`);
58
+ }
59
+ async read(id) {
60
+ boardKey(id);
61
+ return this.store.transaction(async (tx) => ({ id, ...readBoard(await this.load(tx.get(COLLECTION, id), id)) }));
62
+ }
63
+ /** Run `change` on the board and save it, all inside one transaction. */
64
+ async change(id, change) {
65
+ boardKey(id);
66
+ return this.store.transaction(async (tx) => {
67
+ const board = await this.load(tx.get(COLLECTION, id), id);
68
+ const result = change(board);
69
+ await tx.put(COLLECTION, id, { update: toBase64(board.encode()) });
70
+ return result;
71
+ });
72
+ }
73
+ add(id, shape, actor) {
74
+ return this.change(id, (b) => b.addShape(shape, actor));
75
+ }
76
+ connect(id, connector, actor) {
77
+ return this.change(id, (b) => b.addConnector(connector, actor));
78
+ }
79
+ move(id, elementId, dx, dy, actor) {
80
+ return this.change(id, (b) => ({ moved: b.move(elementId, dx, dy, actor) }));
81
+ }
82
+ remove(id, elementId) {
83
+ return this.change(id, (b) => ({ removed: b.remove(elementId) }));
84
+ }
85
+ flow(id, text, actor, options) {
86
+ return this.change(id, (b) => drawFlow(b, text, actor, options));
87
+ }
88
+ async exportSvg(id) {
89
+ boardKey(id);
90
+ return this.store.transaction(async (tx) => toSvg(await this.load(tx.get(COLLECTION, id), id)));
91
+ }
92
+ /** The stored board as a Yjs update. A client applies it to a room to seed it: the room does not read it. */
93
+ async state(id) {
94
+ boardKey(id);
95
+ return this.store.transaction(async (tx) => (await this.load(tx.get(COLLECTION, id), id)).encode());
96
+ }
97
+ /**
98
+ * Merge a live room's state into the stored board. `authors` are the principals the room saw send updates.
99
+ * An element stamped by anyone else is deleted, and a changed author is put back (see `Board.restamp`),
100
+ * so a client that writes raw Yjs cannot put another author on its work. Broken entries are repaired and
101
+ * a board past the element cap is refused. Returns the ids the checks fixed.
102
+ *
103
+ * Limits: the save corrects the stored board only. The room keeps what its clients wrote, so a client that sees
104
+ * a non-empty `fixed` must join again, or its later edits are lost at the next save. The room remembers its
105
+ * authors for good, so a client may stamp an element with the name of anyone who once sent an update in that room.
106
+ * A client that adds a root type of its own makes every later save of that room fail, because the room keeps it.
107
+ */
108
+ async checkpoint(id, update, actor, authors = []) {
109
+ boardKey(id);
110
+ const by = principalSchema.safeParse(actor);
111
+ if (!by.success) throw new CanvasError("INVALID", "the actor must be a valid principal");
112
+ const trusted = (who) => [by.data, ...authors].some((a) => a.kind === who.kind && a.id === who.id);
113
+ return this.store.transaction(async (tx) => {
114
+ const prior = await this.load(tx.get(COLLECTION, id), id);
115
+ const next = prior.clone();
116
+ try {
117
+ Y.applyUpdate(next.doc, update);
118
+ } catch {
119
+ throw new CanvasError("INVALID", "the update is not a Yjs update");
120
+ }
121
+ if (next.doc.store.pendingStructs || next.doc.store.pendingDs) throw new CanvasError("INVALID", "the update is not complete: it needs changes that the board does not have");
122
+ const strange = [...next.doc.share.keys()].filter((key) => key !== "elements" && key !== "meta");
123
+ if (strange.length > 0) throw new CanvasError("INVALID", "the update holds data that is not part of a board");
124
+ const fixed = /* @__PURE__ */ new Set([...next.restamp(prior, trusted), ...next.repair()]);
125
+ const saved = next.encode();
126
+ if (saved.length > MAX_LIVE_BYTES) throw new CanvasError("LIMIT", `the board would hold over ${MAX_LIVE_BYTES} bytes`);
127
+ await tx.put(COLLECTION, id, { update: toBase64(saved) });
128
+ return { elements: next.list().length, fixed: [...fixed].sort() };
129
+ });
130
+ }
131
+ /** Owner only. Repair a board and delete the named elements. Only a human actor may call it. */
132
+ async repair(id, actor, drop = []) {
133
+ const by = principalSchema.safeParse(actor);
134
+ if (!by.success) throw new CanvasError("INVALID", "the actor must be a valid principal");
135
+ if (by.data.kind !== "human") throw new CanvasError("FORBIDDEN", "only a human owner can repair a board");
136
+ boardKey(id);
137
+ return this.store.transaction(async (tx) => {
138
+ const doc = await tx.get(COLLECTION, id);
139
+ if (!doc) throw new CanvasError("NOT_FOUND", `no board "${id}"`);
140
+ const board = decodeStored(doc, id, Board.open);
141
+ const fixed = board.repair(drop);
142
+ await tx.put(COLLECTION, id, { update: toBase64(board.encode()) });
143
+ return { id, fixed, elements: board.list().length };
144
+ });
145
+ }
146
+ async load(read, id) {
147
+ const doc = await read;
148
+ if (!doc) throw new CanvasError("NOT_FOUND", `no board "${id}"`);
149
+ return decodeStored(doc, id, Board.decode);
150
+ }
151
+ };
152
+ function decodeStored(doc, id, decode) {
153
+ try {
154
+ return decode(fromBase64(String(doc.update)));
155
+ } catch (error) {
156
+ if (error instanceof CanvasError) throw error;
157
+ throw new CanvasError("INVALID", `stored board "${id}" is damaged`);
158
+ }
159
+ }
160
+
161
+ export {
162
+ MAX_LIVE_BYTES,
163
+ CanvasService
164
+ };
package/dist/cli.js CHANGED
@@ -2,14 +2,20 @@
2
2
  import {
3
3
  ActorConfigError,
4
4
  BRAND,
5
- CanvasError,
6
- CanvasService,
7
5
  operatorActor,
8
- runMcp
9
- } from "./chunk-NSZ2AC5O.js";
6
+ runMcp,
7
+ svgToPng
8
+ } from "./chunk-KEMOXKBY.js";
10
9
  import {
11
10
  openLocalStore
12
- } from "./chunk-I3EJ5JB7.js";
11
+ } from "./chunk-UKST5A57.js";
12
+ import {
13
+ CanvasService
14
+ } from "./chunk-W7NRP3EX.js";
15
+ import {
16
+ CanvasError
17
+ } from "./chunk-GGQPE65T.js";
18
+ import "./chunk-NWQED42L.js";
13
19
 
14
20
  // src/cli.ts
15
21
  import { readFileSync, writeFileSync } from "fs";
@@ -33,6 +39,10 @@ Commands:
33
39
  repair <board> [--drop <element>]... Owner only: fix a broken or over-cap board. Needs CANVAS_ACTOR=human:<id>.
34
40
  mcp Serve these as MCP tools on stdio. Needs CANVAS_ACTOR.
35
41
 
42
+ Live mode: set CANVAS_SERVER=<worker url> and CANVAS_TOKEN=<bearer token>. Every command then runs in the live room of
43
+ the board on that server, so a person and an agent can edit one board at once. The token sets the actor, the kind,
44
+ and the role, so CANVAS_ACTOR is not needed. If it is set, it must match the token. --dir, CANVAS_DIR, and repair are local only.
45
+
36
46
  Write commands need an actor in CANVAS_ACTOR as <kind>:<id>, such as "agent:helper".
37
47
  The operator sets it. A caller cannot pick its own kind: there is no --actor flag.
38
48
  Kinds: human, agent_of_human, agent_of_agent, agent, user_token.
@@ -78,7 +88,24 @@ async function run(argv) {
78
88
  const need = (count, shape) => {
79
89
  if (positionals.length !== count + 1) throw new UsageError(`usage: ${BRAND.command} ${command} ${shape}`);
80
90
  };
91
+ const server = process.env.CANVAS_SERVER;
92
+ let live;
93
+ let service;
94
+ if (server) {
95
+ if (v.dir !== void 0 || process.env.CANVAS_DIR) throw new UsageError("--dir and CANVAS_DIR are local only: CANVAS_SERVER is set, so the board lives on the server");
96
+ const token = process.env.CANVAS_TOKEN;
97
+ if (!token) throw new UsageError("CANVAS_SERVER needs CANVAS_TOKEN");
98
+ if (command === "repair") throw new UsageError("repair runs on the local store only. Unset CANVAS_SERVER.");
99
+ const { LiveService, whoAmI } = await import("./live.js");
100
+ service = new LiveService({ server, token });
101
+ const claimed = process.env.CANVAS_ACTOR;
102
+ if (claimed || command !== "read" && command !== "export") live = (await whoAmI(server, token)).actor;
103
+ if (live && claimed && claimed !== `${live.kind}:${live.id}`) throw new UsageError(`CANVAS_ACTOR "${claimed}" does not match the token (${live.kind}:${live.id}). Unset CANVAS_ACTOR.`);
104
+ } else {
105
+ service = new CanvasService(openLocalStore(v.dir ?? process.env.CANVAS_DIR ?? ".agentic-canvas"));
106
+ }
81
107
  const actor = () => {
108
+ if (live) return live;
82
109
  try {
83
110
  return operatorActor();
84
111
  } catch (error) {
@@ -86,7 +113,6 @@ async function run(argv) {
86
113
  throw error;
87
114
  }
88
115
  };
89
- const service = new CanvasService(openLocalStore(v.dir ?? process.env.CANVAS_DIR ?? ".agentic-canvas"));
90
116
  const print = (value) => console.log(JSON.stringify(value));
91
117
  switch (command) {
92
118
  case "new":
@@ -118,7 +144,7 @@ async function run(argv) {
118
144
  const format = v.format ?? "svg";
119
145
  if (format !== "svg" && format !== "png") throw new UsageError(`format must be svg or png, got "${format}"`);
120
146
  if (format === "png" && !v.out) throw new UsageError("png is binary: pass --out <path>");
121
- const data = format === "svg" ? await service.exportSvg(board) : await service.exportPng(board);
147
+ const data = format === "svg" ? await service.exportSvg(board) : await svgToPng(await service.exportSvg(board));
122
148
  if (!v.out) return void process.stdout.write(`${data}
123
149
  `);
124
150
  writeFileSync(v.out, data);
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import * as Y from 'yjs';
2
- import { z } from 'zod';
1
+ import { B as Board, P as Principal, a as BoardAccess } from './service-CJTe-uBI.js';
2
+ export { b as BoardData, d as CanvasElement, e as CanvasError, c as CanvasService, C as Connector, D as DrawOptions, E as EdgeData, f as Endpoint, g as ErrorCode, F as FlowEdge, h as FlowGraph, i as FlowNode, G as Group, M as MAX_ELEMENTS, j as MAX_FLOW_EDGES, k as MAX_FLOW_NODES, l as MAX_TEXT, N as NodeData, m as Placement, n as SHAPE_TYPES, S as Shape, o as ShapeType, p as drawFlow, q as layoutFlow, r as parseFlow, s as principalSchema, t as readBoard } from './service-CJTe-uBI.js';
3
3
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
- import { Store } from 'agentic-identity';
5
- export { PRINCIPAL_KINDS, PrincipalKind, isMachineMade } from 'agentic-identity';
6
4
  export { FileStoreOptions, createFileStore, openLocalStore } from './store-file.js';
5
+ export { PRINCIPAL_KINDS, PrincipalKind, isMachineMade } from 'agentic-identity';
6
+ import 'yjs';
7
+ import 'zod';
7
8
 
8
9
  declare const VERSION: string;
9
10
 
@@ -13,207 +14,6 @@ declare const BRAND: {
13
14
  readonly version: string;
14
15
  };
15
16
 
16
- declare const principalSchema: z.ZodObject<{
17
- kind: z.ZodEnum<["human", "agent_of_human", "agent_of_agent", "agent", "user_token"]>;
18
- id: z.ZodString;
19
- }, "strict", z.ZodTypeAny, {
20
- id: string;
21
- kind: "human" | "agent_of_human" | "agent_of_agent" | "agent" | "user_token";
22
- }, {
23
- id: string;
24
- kind: "human" | "agent_of_human" | "agent_of_agent" | "agent" | "user_token";
25
- }>;
26
- type Principal = z.infer<typeof principalSchema>;
27
-
28
- type ErrorCode = "INVALID" | "DUPLICATE_ID" | "NOT_FOUND" | "BAD_REFERENCE" | "LIMIT" | "UNAVAILABLE" | "FORBIDDEN";
29
- declare class CanvasError extends Error {
30
- readonly code: ErrorCode;
31
- constructor(code: ErrorCode, message: string);
32
- }
33
- declare const SHAPE_TYPES: readonly ["rect", "ellipse", "diamond", "text", "sticky", "frame", "image"];
34
- type ShapeType = (typeof SHAPE_TYPES)[number];
35
- declare const MAX_ELEMENTS = 10000;
36
- declare const MAX_TEXT = 10000;
37
- type Endpoint = {
38
- id: string;
39
- } | {
40
- x: number;
41
- y: number;
42
- };
43
- interface Stamp {
44
- id: string;
45
- z: number;
46
- groupId?: string;
47
- /** Who made the element. Never changes. */
48
- author: Principal;
49
- /** Who made the last edit. */
50
- editedBy: Principal;
51
- }
52
- interface Shape extends Stamp {
53
- type: ShapeType;
54
- x: number;
55
- y: number;
56
- w: number;
57
- h: number;
58
- text: string;
59
- fill?: string;
60
- stroke?: string;
61
- src?: string;
62
- }
63
- interface Connector extends Stamp {
64
- type: "connector";
65
- from: Endpoint;
66
- to: Endpoint;
67
- text: string;
68
- startArrow: boolean;
69
- endArrow: boolean;
70
- stroke?: string;
71
- }
72
- interface Group extends Stamp {
73
- type: "group";
74
- }
75
- type CanvasElement = Shape | Connector | Group;
76
- /**
77
- * A whiteboard on a Yjs doc. Headless: no UI code. Every write names its actor.
78
- *
79
- * A synced Yjs update is untrusted input. Every read checks each stored element against the same
80
- * rules the write methods enforce, and returns only the checked fields. An entry that fails is
81
- * hidden at once. `repair()` deletes it, and `Board.decode` runs `repair()`. This holds even
82
- * when a caller writes to `doc` directly.
83
- */
84
- declare class Board {
85
- readonly doc: Y.Doc;
86
- private readonly elements;
87
- private readonly meta;
88
- private maxElements;
89
- constructor(doc?: Y.Doc, options?: {
90
- maxElements?: number;
91
- });
92
- /** Load a saved board with no element checks. Only the owner repair path uses it. */
93
- static open(update: Uint8Array): Board;
94
- /**
95
- * Load a saved board. Refuses a doc past the element cap. Then it deletes every entry that fails
96
- * the element checks, and repairs what concurrent writers left broken.
97
- */
98
- static decode(update: Uint8Array): Board;
99
- encode(): Uint8Array;
100
- /** An independent copy. Edits to it leave this board alone. */
101
- clone(): Board;
102
- get title(): string;
103
- get titleBy(): Principal | undefined;
104
- setTitle(title: string, actor: Principal): void;
105
- /** One element. An invalid entry, or a connector with a missing bound end, is hidden. */
106
- get(elementId: string): CanvasElement | undefined;
107
- /** All visible elements from back to front. */
108
- list(): CanvasElement[];
109
- /**
110
- * Delete what peers can leave broken: entries that fail the element checks, connectors whose
111
- * bound end is gone, and members that name a deleted group. Idempotent, so every peer may run it.
112
- * `drop` names elements the owner removes too, with what they hold: a shape takes its connectors,
113
- * a group takes its members. Refuses a result still past the cap, and then changes nothing.
114
- * Returns the ids fixed.
115
- */
116
- repair(drop?: string[]): string[];
117
- addShape(input: unknown, actor: Principal): Shape;
118
- addConnector(input: unknown, actor: Principal): Connector;
119
- update(elementId: string, patch: unknown, actor: Principal): CanvasElement;
120
- /** Shift an element, or a whole group. Returns the ids that moved. Bound connector ends follow their shapes. */
121
- move(elementId: string, dx: number, dy: number, actor: Principal): string[];
122
- /** Delete an element. A shape takes its connectors and a group takes its members. Returns the ids removed. */
123
- remove(elementId: string): string[];
124
- group(ids: string[], actor: Principal, groupId?: string): Group;
125
- /** Remove a group and hand its members to the parent group. */
126
- ungroup(groupId: string, actor: Principal): void;
127
- /** Put an element, or a group with its inner order kept, in front of or behind every other element. */
128
- reorder(elementId: string, to: "front" | "back", actor: Principal): void;
129
- /** One stored element that passes the checks and whose id matches its key, or undefined. */
130
- private stored;
131
- /** Every stored element that passes the checks, from back to front. Refuses a doc past the cap. */
132
- private storedList;
133
- /** Like storedList, with no cap check. Repair needs every entry, even on a board past the cap. */
134
- private allStored;
135
- /** A connector is detached when a bound end does not name a stored shape. */
136
- private isDetached;
137
- private require;
138
- private checkEnd;
139
- /** The z value just past the top or the bottom. Not clamped: the caller checks the range. */
140
- private edgeZ;
141
- /** The element and, for a group, everything below it. Cycle-safe. */
142
- private subtree;
143
- private subtreeIn;
144
- private create;
145
- /** Apply field changes and stamp the editor, all in one transaction. An undefined value clears the field. */
146
- private write;
147
- }
148
-
149
- declare const MAX_FLOW_NODES = 500;
150
- declare const MAX_FLOW_EDGES = 2000;
151
- interface FlowNode {
152
- id: string;
153
- text: string;
154
- shape: Extract<ShapeType, "rect" | "ellipse" | "diamond">;
155
- }
156
- interface FlowEdge {
157
- from: string;
158
- to: string;
159
- text: string;
160
- }
161
- interface FlowGraph {
162
- direction: "TB" | "LR";
163
- nodes: FlowNode[];
164
- edges: FlowEdge[];
165
- }
166
- declare function parseFlow(source: string): FlowGraph;
167
- interface Placement {
168
- id: string;
169
- x: number;
170
- y: number;
171
- w: number;
172
- h: number;
173
- }
174
- /** Layered layout. The top-left of the result is (0, 0). The layout breaks cycles and handles self-loops. */
175
- declare function layoutFlow(graph: FlowGraph): Placement[];
176
- interface DrawOptions {
177
- /**
178
- * Put in front of every id. Default: a new random prefix for each call, so two agents that draw at
179
- * the same time never write the same id. A prefix you pass is used as given, and it makes ids
180
- * repeatable. Up to 16 of A-Z, a-z, 0-9, _ and -.
181
- */
182
- idPrefix?: string;
183
- /** Top-left of the drawing. Default: below the shapes already on the board. */
184
- origin?: {
185
- x: number;
186
- y: number;
187
- };
188
- }
189
- /** Draw a flow on the board. All or nothing: on any error the board stays as it was. */
190
- declare function drawFlow(board: Board, source: string, actor: Principal, options?: DrawOptions): {
191
- nodes: string[];
192
- edges: string[];
193
- };
194
-
195
- interface Labels {
196
- /** The author is an agent or acts for one. */
197
- machineMade: boolean;
198
- /** The last edit came from an agent or one acting for one. */
199
- lastEditMachineMade: boolean;
200
- }
201
- type NodeData = Shape & Labels;
202
- type EdgeData = Connector & Labels;
203
- interface BoardData {
204
- title: string;
205
- nodes: NodeData[];
206
- edges: EdgeData[];
207
- groups: {
208
- id: string;
209
- members: string[];
210
- }[];
211
- /** Every non-empty text, back to front. */
212
- texts: string[];
213
- }
214
- /** The board as plain data for an agent. Reads only. Embedded image bytes are left out. */
215
- declare function readBoard(board: Board): BoardData;
216
-
217
17
  /** Draw the board, back to front, on a white background. */
218
18
  declare function toSvg(board: Board): string;
219
19
 
@@ -235,51 +35,12 @@ declare class ActorConfigError extends Error {
235
35
  */
236
36
  declare function operatorActor(env?: Record<string, string | undefined>): Principal;
237
37
 
238
- /** One place for every board operation. The CLI, the MCP server, and the Worker call it. */
239
- declare class CanvasService {
240
- private readonly store;
241
- constructor(store: Store);
242
- create(actor: Principal, options?: {
243
- id?: string;
244
- title?: string;
245
- }): Promise<{
246
- id: string;
247
- title: string;
248
- }>;
249
- read(id: string): Promise<BoardData & {
250
- id: string;
251
- }>;
252
- /** Run `change` on the board and save it, all inside one transaction. */
253
- change<R>(id: string, change: (board: Board) => R): Promise<R>;
254
- add(id: string, shape: unknown, actor: Principal): Promise<Shape>;
255
- connect(id: string, connector: unknown, actor: Principal): Promise<Connector>;
256
- move(id: string, elementId: string, dx: number, dy: number, actor: Principal): Promise<{
257
- moved: string[];
258
- }>;
259
- remove(id: string, elementId: string): Promise<{
260
- removed: string[];
261
- }>;
262
- flow(id: string, text: string, actor: Principal, options?: DrawOptions): Promise<{
263
- nodes: string[];
264
- edges: string[];
265
- }>;
266
- exportSvg(id: string): Promise<string>;
267
- exportPng(id: string): Promise<Uint8Array>;
268
- /** Owner only. Repair a board and delete the named elements. Only a human actor may call it. */
269
- repair(id: string, actor: Principal, drop?: string[]): Promise<{
270
- id: string;
271
- fixed: string[];
272
- elements: number;
273
- }>;
274
- private load;
275
- }
276
-
277
38
  /**
278
39
  * The tools mirror the CLI. The actor is fixed here by the operator. No tool takes an actor,
279
40
  * author, or kind, so a caller cannot choose who it writes as.
280
41
  */
281
- declare function createMcpServer(service: CanvasService, actor: Principal): McpServer;
42
+ declare function createMcpServer(service: BoardAccess, actor: Principal): McpServer;
282
43
  /** Serve the tools on stdin and stdout. Stdout carries protocol frames only. */
283
- declare function runMcp(service: CanvasService, actor: Principal): Promise<void>;
44
+ declare function runMcp(service: BoardAccess, actor: Principal): Promise<void>;
284
45
 
285
- export { ActorConfigError, BRAND, Board, type BoardData, type CanvasElement, CanvasError, CanvasService, type Connector, type DrawOptions, type EdgeData, type Endpoint, type ErrorCode, type FlowEdge, type FlowGraph, type FlowNode, type Group, MAX_ELEMENTS, MAX_FLOW_EDGES, MAX_FLOW_NODES, MAX_TEXT, type NodeData, type Placement, type Principal, SHAPE_TYPES, type Shape, type ShapeType, VERSION, createMcpServer, drawFlow, layoutFlow, operatorActor, parseFlow, principalSchema, readBoard, runMcp, svgToPng, toSvg };
46
+ export { ActorConfigError, BRAND, Board, Principal, VERSION, createMcpServer, operatorActor, runMcp, svgToPng, toSvg };
package/dist/index.js CHANGED
@@ -1,32 +1,37 @@
1
1
  import {
2
2
  ActorConfigError,
3
3
  BRAND,
4
+ VERSION,
5
+ createMcpServer,
6
+ operatorActor,
7
+ runMcp,
8
+ svgToPng
9
+ } from "./chunk-KEMOXKBY.js";
10
+ import {
11
+ createFileStore,
12
+ openLocalStore
13
+ } from "./chunk-UKST5A57.js";
14
+ import {
15
+ CanvasService
16
+ } from "./chunk-W7NRP3EX.js";
17
+ import {
4
18
  Board,
5
19
  CanvasError,
6
- CanvasService,
7
20
  MAX_ELEMENTS,
8
21
  MAX_FLOW_EDGES,
9
22
  MAX_FLOW_NODES,
10
23
  MAX_TEXT,
11
24
  PRINCIPAL_KINDS,
12
25
  SHAPE_TYPES,
13
- VERSION,
14
- createMcpServer,
15
26
  drawFlow,
16
27
  isMachineMade,
17
28
  layoutFlow,
18
- operatorActor,
19
29
  parseFlow,
20
30
  principalSchema,
21
31
  readBoard,
22
- runMcp,
23
- svgToPng,
24
32
  toSvg
25
- } from "./chunk-NSZ2AC5O.js";
26
- import {
27
- createFileStore,
28
- openLocalStore
29
- } from "./chunk-I3EJ5JB7.js";
33
+ } from "./chunk-GGQPE65T.js";
34
+ import "./chunk-NWQED42L.js";
30
35
  export {
31
36
  ActorConfigError,
32
37
  BRAND,
@@ -0,0 +1,21 @@
1
+ import { createDurableObjectRealtime } from 'agentic-realtime/worker';
2
+ export { SyncRoom } from 'agentic-realtime/worker';
3
+ import { WorkerEnv } from './worker.js';
4
+ import 'agentic-identity';
5
+ import 'agentic-realtime';
6
+ import 'agentic-identity/cloudflare';
7
+ import 'hono';
8
+ import './service-CJTe-uBI.js';
9
+ import 'yjs';
10
+ import 'zod';
11
+
12
+ type Namespace = Parameters<typeof createDurableObjectRealtime>[0];
13
+ interface LiveEnv extends WorkerEnv {
14
+ /** Durable Object namespace of the live rooms. Bind `SyncRoom` to it. */
15
+ SYNC_ROOM?: Namespace;
16
+ }
17
+ declare const _default: {
18
+ fetch: (request: Request, env: LiveEnv, ctx: unknown) => Response | Promise<Response>;
19
+ };
20
+
21
+ export { type LiveEnv, _default as default };
@@ -0,0 +1,25 @@
1
+ import {
2
+ createApp
3
+ } from "./chunk-V477KSZQ.js";
4
+ import "./chunk-W7NRP3EX.js";
5
+ import {
6
+ CanvasError
7
+ } from "./chunk-GGQPE65T.js";
8
+ import "./chunk-NWQED42L.js";
9
+
10
+ // src/live-worker.ts
11
+ import { parseRegion } from "agentic-identity";
12
+ import { createDurableObjectRealtime } from "agentic-realtime/worker";
13
+ import { SyncRoom } from "agentic-realtime/worker";
14
+ var app = createApp({
15
+ live: (env) => {
16
+ const rooms = env.SYNC_ROOM;
17
+ if (!rooms) throw new CanvasError("UNAVAILABLE", "bind a Durable Object namespace as SYNC_ROOM");
18
+ return createDurableObjectRealtime(rooms, parseRegion(env.CANVAS_REGION ?? "") === "eu" ? "eu" : void 0);
19
+ }
20
+ });
21
+ var live_worker_default = { fetch: (request, env, ctx) => app.fetch(request, env, ctx) };
22
+ export {
23
+ SyncRoom,
24
+ live_worker_default as default
25
+ };