bytespost-canvas 0.1.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/LICENSE +21 -0
- package/README.md +102 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.js +747 -0
- package/dist/commandRegistry.d.ts +44 -0
- package/dist/commandRegistry.js +301 -0
- package/dist/daemon.d.ts +22 -0
- package/dist/daemon.js +475 -0
- package/dist/mcp.d.ts +1 -0
- package/dist/mcp.js +143 -0
- package/dist/protocol.d.ts +212 -0
- package/dist/protocol.js +9 -0
- package/package.json +58 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-bridge wire protocol (v1).
|
|
3
|
+
*
|
|
4
|
+
* The daemon relays each HTTP/CLI/MCP request to one browser tab over WebSocket
|
|
5
|
+
* as a `BridgeCommand`, and the tab answers with a `BridgeReply` carrying the
|
|
6
|
+
* same `id`. Browser tabs first announce themselves with a `hello` message so
|
|
7
|
+
* local agents can list and target every open canvas.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PROTOCOL_VERSION: "1";
|
|
10
|
+
/** Command kinds the daemon can ask the canvas to perform. */
|
|
11
|
+
export type BridgeCommandType = 'health' | 'screenshot' | 'draw' | 'document_get' | 'document_nodes' | 'node_get' | 'node_update' | 'node_delete' | 'select_set' | 'select_clear' | 'viewport_fit' | 'viewport_zoom' | 'building_create';
|
|
12
|
+
export interface CanvasTabInfo {
|
|
13
|
+
id: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
app?: string;
|
|
16
|
+
url?: string;
|
|
17
|
+
canvasType?: string;
|
|
18
|
+
ready?: boolean;
|
|
19
|
+
document?: {
|
|
20
|
+
id?: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
nodeCount?: number;
|
|
23
|
+
};
|
|
24
|
+
capabilities?: string[];
|
|
25
|
+
connectedAt?: string;
|
|
26
|
+
lastSeenAt?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface BrowserHello {
|
|
29
|
+
type: 'hello';
|
|
30
|
+
tab: CanvasTabInfo;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A minimal, renderer-agnostic node spec the external agent sends. Coordinates
|
|
34
|
+
* are in canvas/WORLD space (the same units the editor's pointer tools use).
|
|
35
|
+
* `fill`/`stroke`/`color` accept a `#rrggbb` hex string; the browser converts
|
|
36
|
+
* it into the IR's {r,g,b,a} 0..1 color before constructing the NodeIR.
|
|
37
|
+
*/
|
|
38
|
+
export type DrawNodeSpec = {
|
|
39
|
+
type: 'rect';
|
|
40
|
+
x: number;
|
|
41
|
+
y: number;
|
|
42
|
+
w: number;
|
|
43
|
+
h: number;
|
|
44
|
+
/** Hex fill, e.g. '#3b82f6'. Omit for the editor default. */
|
|
45
|
+
fill?: string;
|
|
46
|
+
/** Hex stroke colour; when set a 1px (or `strokeWidth`) stroke is added. */
|
|
47
|
+
stroke?: string;
|
|
48
|
+
strokeWidth?: number;
|
|
49
|
+
/** Uniform corner radius in px. */
|
|
50
|
+
radius?: number;
|
|
51
|
+
name?: string;
|
|
52
|
+
} | {
|
|
53
|
+
type: 'text';
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
text: string;
|
|
57
|
+
fontSize?: number;
|
|
58
|
+
/** Hex text colour, e.g. '#ffffff'. */
|
|
59
|
+
color?: string;
|
|
60
|
+
/** Optional fixed box width; height auto-grows. */
|
|
61
|
+
w?: number;
|
|
62
|
+
name?: string;
|
|
63
|
+
} | {
|
|
64
|
+
type: 'frame';
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
w: number;
|
|
68
|
+
h: number;
|
|
69
|
+
fill?: string;
|
|
70
|
+
name?: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'line';
|
|
73
|
+
x1: number;
|
|
74
|
+
y1: number;
|
|
75
|
+
x2: number;
|
|
76
|
+
y2: number;
|
|
77
|
+
stroke?: string;
|
|
78
|
+
width?: number;
|
|
79
|
+
name?: string;
|
|
80
|
+
};
|
|
81
|
+
/** HTTP /v1/draw request body. */
|
|
82
|
+
export interface DrawRequest {
|
|
83
|
+
nodes: DrawNodeSpec[];
|
|
84
|
+
}
|
|
85
|
+
/** A command the daemon sends to the canvas over WS. */
|
|
86
|
+
export interface BridgeCommand {
|
|
87
|
+
/** Correlation id; the reply MUST echo this. */
|
|
88
|
+
id: string;
|
|
89
|
+
type: BridgeCommandType;
|
|
90
|
+
/** Present only for `draw` commands. */
|
|
91
|
+
nodes?: DrawNodeSpec[];
|
|
92
|
+
/** Present for node commands. */
|
|
93
|
+
nodeId?: string;
|
|
94
|
+
/** Present for `node_update`; shallow patch applied by the browser. */
|
|
95
|
+
patch?: Record<string, unknown>;
|
|
96
|
+
/** Present for selection commands. */
|
|
97
|
+
nodeIds?: string[];
|
|
98
|
+
/** Present for viewport zoom commands. */
|
|
99
|
+
zoom?: number;
|
|
100
|
+
/** Present for `building_create`. */
|
|
101
|
+
buildingType?: string;
|
|
102
|
+
/** Domain-specific tool payload, including building operations. */
|
|
103
|
+
input?: Record<string, unknown>;
|
|
104
|
+
}
|
|
105
|
+
/** Health reply payload. */
|
|
106
|
+
export interface HealthReplyData {
|
|
107
|
+
ok: true;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Screenshot reply payload. The PNG is carried as a base64 string so the
|
|
111
|
+
* whole reply fits in one JSON text frame (SLICE 1 — simple over fast).
|
|
112
|
+
*/
|
|
113
|
+
export interface ScreenshotReplyData {
|
|
114
|
+
/** base64-encoded PNG bytes (no data: prefix). */
|
|
115
|
+
pngBase64: string;
|
|
116
|
+
width: number;
|
|
117
|
+
height: number;
|
|
118
|
+
}
|
|
119
|
+
/** Draw reply payload: the ids of the nodes that were created, in input order. */
|
|
120
|
+
export interface DrawReplyData {
|
|
121
|
+
nodeIds: string[];
|
|
122
|
+
}
|
|
123
|
+
export interface DocumentNodesReplyData {
|
|
124
|
+
nodes: Array<{
|
|
125
|
+
id: string;
|
|
126
|
+
type?: string;
|
|
127
|
+
name?: string;
|
|
128
|
+
parentId?: string;
|
|
129
|
+
pageId?: string;
|
|
130
|
+
depth?: number;
|
|
131
|
+
}>;
|
|
132
|
+
}
|
|
133
|
+
export interface CommandReplyData {
|
|
134
|
+
[key: string]: unknown;
|
|
135
|
+
}
|
|
136
|
+
/** A reply the canvas sends back to the daemon. */
|
|
137
|
+
export type BridgeReply = {
|
|
138
|
+
id: string;
|
|
139
|
+
ok: true;
|
|
140
|
+
type: 'health';
|
|
141
|
+
data: HealthReplyData;
|
|
142
|
+
} | {
|
|
143
|
+
id: string;
|
|
144
|
+
ok: true;
|
|
145
|
+
type: 'screenshot';
|
|
146
|
+
data: ScreenshotReplyData;
|
|
147
|
+
} | {
|
|
148
|
+
id: string;
|
|
149
|
+
ok: true;
|
|
150
|
+
type: 'draw';
|
|
151
|
+
data: DrawReplyData;
|
|
152
|
+
} | {
|
|
153
|
+
id: string;
|
|
154
|
+
ok: true;
|
|
155
|
+
type: 'document_get';
|
|
156
|
+
data: CommandReplyData;
|
|
157
|
+
} | {
|
|
158
|
+
id: string;
|
|
159
|
+
ok: true;
|
|
160
|
+
type: 'document_nodes';
|
|
161
|
+
data: DocumentNodesReplyData;
|
|
162
|
+
} | {
|
|
163
|
+
id: string;
|
|
164
|
+
ok: true;
|
|
165
|
+
type: 'node_get';
|
|
166
|
+
data: CommandReplyData;
|
|
167
|
+
} | {
|
|
168
|
+
id: string;
|
|
169
|
+
ok: true;
|
|
170
|
+
type: 'node_update';
|
|
171
|
+
data: CommandReplyData;
|
|
172
|
+
} | {
|
|
173
|
+
id: string;
|
|
174
|
+
ok: true;
|
|
175
|
+
type: 'node_delete';
|
|
176
|
+
data: CommandReplyData;
|
|
177
|
+
} | {
|
|
178
|
+
id: string;
|
|
179
|
+
ok: true;
|
|
180
|
+
type: 'select_set';
|
|
181
|
+
data: CommandReplyData;
|
|
182
|
+
} | {
|
|
183
|
+
id: string;
|
|
184
|
+
ok: true;
|
|
185
|
+
type: 'select_clear';
|
|
186
|
+
data: CommandReplyData;
|
|
187
|
+
} | {
|
|
188
|
+
id: string;
|
|
189
|
+
ok: true;
|
|
190
|
+
type: 'viewport_fit';
|
|
191
|
+
data: CommandReplyData;
|
|
192
|
+
} | {
|
|
193
|
+
id: string;
|
|
194
|
+
ok: true;
|
|
195
|
+
type: 'viewport_zoom';
|
|
196
|
+
data: CommandReplyData;
|
|
197
|
+
} | {
|
|
198
|
+
id: string;
|
|
199
|
+
ok: true;
|
|
200
|
+
type: 'building_create';
|
|
201
|
+
data: CommandReplyData;
|
|
202
|
+
} | {
|
|
203
|
+
id: string;
|
|
204
|
+
ok: false;
|
|
205
|
+
error: string;
|
|
206
|
+
};
|
|
207
|
+
/** HTTP /v1/health JSON shape. */
|
|
208
|
+
export interface HealthResponse {
|
|
209
|
+
canvasConnected: boolean;
|
|
210
|
+
tabCount: number;
|
|
211
|
+
version: typeof PROTOCOL_VERSION;
|
|
212
|
+
}
|
package/dist/protocol.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent-bridge wire protocol (v1).
|
|
3
|
+
*
|
|
4
|
+
* The daemon relays each HTTP/CLI/MCP request to one browser tab over WebSocket
|
|
5
|
+
* as a `BridgeCommand`, and the tab answers with a `BridgeReply` carrying the
|
|
6
|
+
* same `id`. Browser tabs first announce themselves with a `hello` message so
|
|
7
|
+
* local agents can list and target every open canvas.
|
|
8
|
+
*/
|
|
9
|
+
export const PROTOCOL_VERSION = '1';
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bytespost-canvas",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Local CLI + MCP server for the bytespost canvas — drive a running canvas tab from the terminal or any AI agent.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"bytespost",
|
|
7
|
+
"canvas",
|
|
8
|
+
"cli",
|
|
9
|
+
"mcp",
|
|
10
|
+
"ai",
|
|
11
|
+
"claude",
|
|
12
|
+
"agent",
|
|
13
|
+
"design",
|
|
14
|
+
"figma-like"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://app.bytespost.com",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/yunfengsay/canvas-three-gpu.git",
|
|
20
|
+
"directory": "packages/agent-bridge"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "bytespost",
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"bin": {
|
|
28
|
+
"canvas-bridge": "./dist/cli.js",
|
|
29
|
+
"canvas": "./dist/cli.js",
|
|
30
|
+
"canvasd": "./dist/cli.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -p tsconfig.build.json && chmod +x dist/cli.js",
|
|
42
|
+
"prepublishOnly": "npm run build",
|
|
43
|
+
"serve": "tsx src/cli.ts serve",
|
|
44
|
+
"cli": "tsx src/cli.ts",
|
|
45
|
+
"test": "node --import tsx --test test/**/*.test.mjs"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
49
|
+
"ws": "^8.18.0",
|
|
50
|
+
"zod": "^4.4.3"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^20.19.39",
|
|
54
|
+
"@types/ws": "^8.5.12",
|
|
55
|
+
"tsx": "^4.19.2",
|
|
56
|
+
"typescript": "^5.8.3"
|
|
57
|
+
}
|
|
58
|
+
}
|