@particle-academy/agent-integrations 0.2.4
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 +131 -0
- package/dist/bridges/flow.d.cts +72 -0
- package/dist/bridges/flow.d.ts +72 -0
- package/dist/bridges/whiteboard.d.cts +40 -0
- package/dist/bridges/whiteboard.d.ts +40 -0
- package/dist/bridges-flow.cjs +330 -0
- package/dist/bridges-flow.cjs.map +1 -0
- package/dist/bridges-flow.js +4 -0
- package/dist/bridges-flow.js.map +1 -0
- package/dist/bridges-whiteboard.cjs +409 -0
- package/dist/bridges-whiteboard.cjs.map +1 -0
- package/dist/bridges-whiteboard.js +4 -0
- package/dist/bridges-whiteboard.js.map +1 -0
- package/dist/chunk-2VOQJKSU.js +320 -0
- package/dist/chunk-2VOQJKSU.js.map +1 -0
- package/dist/chunk-5ZUHNNLR.js +398 -0
- package/dist/chunk-5ZUHNNLR.js.map +1 -0
- package/dist/chunk-6LTKCNLF.js +68 -0
- package/dist/chunk-6LTKCNLF.js.map +1 -0
- package/dist/chunk-FLEOQUKF.js +157 -0
- package/dist/chunk-FLEOQUKF.js.map +1 -0
- package/dist/chunk-QGCF7YKW.js +130 -0
- package/dist/chunk-QGCF7YKW.js.map +1 -0
- package/dist/index.cjs +1632 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +155 -0
- package/dist/index.d.ts +155 -0
- package/dist/index.js +567 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.cts +73 -0
- package/dist/mcp/index.d.ts +73 -0
- package/dist/mcp.cjs +210 -0
- package/dist/mcp.cjs.map +1 -0
- package/dist/mcp.js +4 -0
- package/dist/mcp.js.map +1 -0
- package/dist/server-Bv985us3.d.cts +173 -0
- package/dist/server-Bv985us3.d.ts +173 -0
- package/dist/sharing/index.d.cts +89 -0
- package/dist/sharing/index.d.ts +89 -0
- package/dist/sharing.cjs +166 -0
- package/dist/sharing.cjs.map +1 -0
- package/dist/sharing.js +3 -0
- package/dist/sharing.js.map +1 -0
- package/dist/styles.css +331 -0
- package/dist/styles.css.map +1 -0
- package/dist/types-CRPA_D0z.d.ts +18 -0
- package/dist/types-DR5AS6Rd.d.cts +18 -0
- package/docs/relay-protocol.md +57 -0
- package/package.json +61 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { errorResult, textResult } from './chunk-QGCF7YKW.js';
|
|
2
|
+
|
|
3
|
+
// src/bridges/whiteboard.ts
|
|
4
|
+
var DEFAULT_AGENT = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
5
|
+
var VALID_SHAPES = ["rect", "rounded-rect", "ellipse", "diamond", "triangle", "line", "arrow", "text"];
|
|
6
|
+
var num = (v, fallback) => typeof v === "number" && Number.isFinite(v) ? v : fallback ?? 0;
|
|
7
|
+
var str = (v, fallback = "") => typeof v === "string" ? v : fallback;
|
|
8
|
+
var bool = (v, fallback = false) => typeof v === "boolean" ? v : fallback;
|
|
9
|
+
var newId = (prefix) => `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;
|
|
10
|
+
function registerWhiteboardBridge(server, options) {
|
|
11
|
+
const { adapter } = options;
|
|
12
|
+
const agent = { ...DEFAULT_AGENT, ...options.agent ?? {} };
|
|
13
|
+
const disposers = [];
|
|
14
|
+
const reg = (name, description, inputProperties, required, handler) => {
|
|
15
|
+
disposers.push(
|
|
16
|
+
server.registerTool(
|
|
17
|
+
{
|
|
18
|
+
name,
|
|
19
|
+
description,
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: inputProperties,
|
|
23
|
+
required,
|
|
24
|
+
additionalProperties: false
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
async (args) => {
|
|
28
|
+
try {
|
|
29
|
+
return await handler(args);
|
|
30
|
+
} catch (e) {
|
|
31
|
+
return errorResult(e instanceof Error ? e.message : String(e));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
reg("whiteboard_get_state", "Get the full board state: viewport, all items, strokes.", {}, [], () => {
|
|
38
|
+
const state = {
|
|
39
|
+
viewport: adapter.getViewport(),
|
|
40
|
+
notes: adapter.getNotes(),
|
|
41
|
+
shapes: adapter.getShapes(),
|
|
42
|
+
connectors: adapter.getConnectors(),
|
|
43
|
+
strokes: adapter.getStrokes()
|
|
44
|
+
};
|
|
45
|
+
return textResult(JSON.stringify(state, null, 2), state);
|
|
46
|
+
});
|
|
47
|
+
reg("whiteboard_list_items", "List notes, shapes, and connectors with id, kind, and bounds.", {}, [], () => {
|
|
48
|
+
const items = [];
|
|
49
|
+
for (const n of adapter.getNotes()) {
|
|
50
|
+
items.push({
|
|
51
|
+
id: n.id,
|
|
52
|
+
kind: "sticky",
|
|
53
|
+
summary: `"${(n.text ?? "").slice(0, 40)}" @(${Math.round(n.x)},${Math.round(n.y)}) ${n.width}\xD7${n.height}`
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
for (const s of adapter.getShapes()) {
|
|
57
|
+
items.push({
|
|
58
|
+
id: s.id,
|
|
59
|
+
kind: `shape:${s.shape}`,
|
|
60
|
+
summary: `${s.text ? `"${s.text}" ` : ""}@(${Math.round(s.x)},${Math.round(s.y)}) ${s.width}\xD7${s.height}`
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
for (const c of adapter.getConnectors()) {
|
|
64
|
+
items.push({ id: c.id, kind: "connector", summary: `from=${JSON.stringify(c.from)} to=${JSON.stringify(c.to)}` });
|
|
65
|
+
}
|
|
66
|
+
return textResult(items.map((i) => `${i.kind} ${i.id}: ${i.summary}`).join("\n") || "(empty board)", items);
|
|
67
|
+
});
|
|
68
|
+
reg(
|
|
69
|
+
"whiteboard_get_item",
|
|
70
|
+
"Get a single item (sticky / shape / connector) by id.",
|
|
71
|
+
{ id: { type: "string" } },
|
|
72
|
+
["id"],
|
|
73
|
+
(args) => {
|
|
74
|
+
const id = str(args.id);
|
|
75
|
+
const all = [...adapter.getNotes(), ...adapter.getShapes(), ...adapter.getConnectors()];
|
|
76
|
+
const found = all.find((x) => x.id === id);
|
|
77
|
+
if (!found) return errorResult(`No item with id ${id}`);
|
|
78
|
+
return textResult(JSON.stringify(found, null, 2), found);
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
reg(
|
|
82
|
+
"whiteboard_add_sticky",
|
|
83
|
+
"Add a sticky note. Position is in world coordinates.",
|
|
84
|
+
{
|
|
85
|
+
x: { type: "number" },
|
|
86
|
+
y: { type: "number" },
|
|
87
|
+
text: { type: "string" },
|
|
88
|
+
width: { type: "number" },
|
|
89
|
+
height: { type: "number" },
|
|
90
|
+
color: { type: "string", description: "CSS color, e.g. #fde68a" }
|
|
91
|
+
},
|
|
92
|
+
["x", "y"],
|
|
93
|
+
async (args) => {
|
|
94
|
+
const x = num(args.x);
|
|
95
|
+
const y = num(args.y);
|
|
96
|
+
const width = num(args.width, 180);
|
|
97
|
+
const height = num(args.height, 140);
|
|
98
|
+
const note = {
|
|
99
|
+
id: newId("n"),
|
|
100
|
+
kind: "sticky",
|
|
101
|
+
x,
|
|
102
|
+
y,
|
|
103
|
+
width,
|
|
104
|
+
height,
|
|
105
|
+
text: str(args.text),
|
|
106
|
+
color: typeof args.color === "string" ? args.color : "#fde68a",
|
|
107
|
+
authorId: agent.id
|
|
108
|
+
};
|
|
109
|
+
adapter.setNotes((all) => [...all, note]);
|
|
110
|
+
return textResult(`Added sticky ${note.id}`, note);
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
reg(
|
|
114
|
+
"whiteboard_stream_text",
|
|
115
|
+
"Type text into a sticky note character-by-character so the human can read it forming. The tool returns once streaming finishes.",
|
|
116
|
+
{
|
|
117
|
+
id: { type: "string" },
|
|
118
|
+
text: { type: "string" },
|
|
119
|
+
cps: { type: "number", description: "Characters per second. Default 25." },
|
|
120
|
+
append: { type: "boolean", description: "Append to existing text instead of replacing. Default false." }
|
|
121
|
+
},
|
|
122
|
+
["id", "text"],
|
|
123
|
+
async (args) => {
|
|
124
|
+
const id = str(args.id);
|
|
125
|
+
const target = str(args.text);
|
|
126
|
+
const cps = Math.max(1, num(args.cps, 25));
|
|
127
|
+
const append = bool(args.append);
|
|
128
|
+
const startNote = adapter.getNotes().find((n) => n.id === id);
|
|
129
|
+
if (!startNote) return errorResult(`No sticky with id ${id}`);
|
|
130
|
+
const base = append ? startNote.text ?? "" : "";
|
|
131
|
+
const interval = Math.max(8, Math.round(1e3 / cps));
|
|
132
|
+
for (let i = 0; i <= target.length; i++) {
|
|
133
|
+
const nextText = base + target.slice(0, i);
|
|
134
|
+
adapter.setNotes((all) => all.map((n) => n.id === id ? { ...n, text: nextText } : n));
|
|
135
|
+
if (i < target.length) await new Promise((r) => setTimeout(r, interval));
|
|
136
|
+
}
|
|
137
|
+
return textResult(`Streamed ${target.length} chars to ${id}`, { id, text: base + target });
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
reg(
|
|
141
|
+
"whiteboard_update_sticky",
|
|
142
|
+
"Update fields on a sticky note. Only provided fields are changed.",
|
|
143
|
+
{
|
|
144
|
+
id: { type: "string" },
|
|
145
|
+
x: { type: "number" },
|
|
146
|
+
y: { type: "number" },
|
|
147
|
+
width: { type: "number" },
|
|
148
|
+
height: { type: "number" },
|
|
149
|
+
text: { type: "string" },
|
|
150
|
+
color: { type: "string" }
|
|
151
|
+
},
|
|
152
|
+
["id"],
|
|
153
|
+
async (args) => {
|
|
154
|
+
const id = str(args.id);
|
|
155
|
+
const existing = adapter.getNotes().find((n) => n.id === id);
|
|
156
|
+
if (!existing) return errorResult(`No sticky with id ${id}`);
|
|
157
|
+
const nextX = args.x !== void 0 ? num(args.x) : existing.x;
|
|
158
|
+
const nextY = args.y !== void 0 ? num(args.y) : existing.y;
|
|
159
|
+
const nextW = args.width !== void 0 ? num(args.width) : existing.width;
|
|
160
|
+
const nextH = args.height !== void 0 ? num(args.height) : existing.height;
|
|
161
|
+
let updated = null;
|
|
162
|
+
adapter.setNotes(
|
|
163
|
+
(all) => all.map((n) => {
|
|
164
|
+
if (n.id !== id) return n;
|
|
165
|
+
updated = {
|
|
166
|
+
...n,
|
|
167
|
+
x: nextX,
|
|
168
|
+
y: nextY,
|
|
169
|
+
width: nextW,
|
|
170
|
+
height: nextH,
|
|
171
|
+
...args.text !== void 0 ? { text: str(args.text) } : {},
|
|
172
|
+
...args.color !== void 0 ? { color: str(args.color) } : {}
|
|
173
|
+
};
|
|
174
|
+
return updated;
|
|
175
|
+
})
|
|
176
|
+
);
|
|
177
|
+
return textResult(`Updated sticky ${id}`, updated);
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
reg(
|
|
181
|
+
"whiteboard_add_shape",
|
|
182
|
+
`Add a shape. Kind must be one of: ${VALID_SHAPES.join(", ")}.`,
|
|
183
|
+
{
|
|
184
|
+
shape: { type: "string", enum: VALID_SHAPES },
|
|
185
|
+
x: { type: "number" },
|
|
186
|
+
y: { type: "number" },
|
|
187
|
+
width: { type: "number" },
|
|
188
|
+
height: { type: "number" },
|
|
189
|
+
text: { type: "string" },
|
|
190
|
+
fill: { type: "string" },
|
|
191
|
+
stroke: { type: "string" },
|
|
192
|
+
flipX: { type: "boolean" },
|
|
193
|
+
flipY: { type: "boolean" }
|
|
194
|
+
},
|
|
195
|
+
["shape", "x", "y", "width", "height"],
|
|
196
|
+
async (args) => {
|
|
197
|
+
const kind = str(args.shape);
|
|
198
|
+
if (!VALID_SHAPES.includes(kind)) return errorResult(`Invalid shape kind: ${kind}`);
|
|
199
|
+
const x = num(args.x);
|
|
200
|
+
const y = num(args.y);
|
|
201
|
+
const width = num(args.width);
|
|
202
|
+
const height = num(args.height);
|
|
203
|
+
const shape = {
|
|
204
|
+
id: newId("s"),
|
|
205
|
+
kind: "shape",
|
|
206
|
+
shape: kind,
|
|
207
|
+
x,
|
|
208
|
+
y,
|
|
209
|
+
width,
|
|
210
|
+
height,
|
|
211
|
+
...args.text !== void 0 ? { text: str(args.text) } : {},
|
|
212
|
+
...args.fill !== void 0 ? { fill: str(args.fill) } : {},
|
|
213
|
+
...args.stroke !== void 0 ? { stroke: str(args.stroke) } : {},
|
|
214
|
+
...args.flipX !== void 0 ? { flipX: bool(args.flipX) } : {},
|
|
215
|
+
...args.flipY !== void 0 ? { flipY: bool(args.flipY) } : {}
|
|
216
|
+
};
|
|
217
|
+
adapter.setShapes((all) => [...all, shape]);
|
|
218
|
+
return textResult(`Added ${kind} ${shape.id}`, shape);
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
reg(
|
|
222
|
+
"whiteboard_update_shape",
|
|
223
|
+
"Update fields on a shape.",
|
|
224
|
+
{
|
|
225
|
+
id: { type: "string" },
|
|
226
|
+
x: { type: "number" },
|
|
227
|
+
y: { type: "number" },
|
|
228
|
+
width: { type: "number" },
|
|
229
|
+
height: { type: "number" },
|
|
230
|
+
text: { type: "string" },
|
|
231
|
+
fill: { type: "string" },
|
|
232
|
+
stroke: { type: "string" }
|
|
233
|
+
},
|
|
234
|
+
["id"],
|
|
235
|
+
async (args) => {
|
|
236
|
+
const id = str(args.id);
|
|
237
|
+
const existing = adapter.getShapes().find((s) => s.id === id);
|
|
238
|
+
if (!existing) return errorResult(`No shape with id ${id}`);
|
|
239
|
+
const nextX = args.x !== void 0 ? num(args.x) : existing.x;
|
|
240
|
+
const nextY = args.y !== void 0 ? num(args.y) : existing.y;
|
|
241
|
+
const nextW = args.width !== void 0 ? num(args.width) : existing.width;
|
|
242
|
+
const nextH = args.height !== void 0 ? num(args.height) : existing.height;
|
|
243
|
+
let updated = null;
|
|
244
|
+
adapter.setShapes(
|
|
245
|
+
(all) => all.map((s) => {
|
|
246
|
+
if (s.id !== id) return s;
|
|
247
|
+
updated = {
|
|
248
|
+
...s,
|
|
249
|
+
x: nextX,
|
|
250
|
+
y: nextY,
|
|
251
|
+
width: nextW,
|
|
252
|
+
height: nextH,
|
|
253
|
+
...args.text !== void 0 ? { text: str(args.text) } : {},
|
|
254
|
+
...args.fill !== void 0 ? { fill: str(args.fill) } : {},
|
|
255
|
+
...args.stroke !== void 0 ? { stroke: str(args.stroke) } : {}
|
|
256
|
+
};
|
|
257
|
+
return updated;
|
|
258
|
+
})
|
|
259
|
+
);
|
|
260
|
+
return textResult(`Updated shape ${id}`, updated);
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
reg(
|
|
264
|
+
"whiteboard_add_connector",
|
|
265
|
+
"Connect two items by id, or specify explicit world-space points.",
|
|
266
|
+
{
|
|
267
|
+
from: { description: "Item id (string) or {x,y}" },
|
|
268
|
+
to: { description: "Item id (string) or {x,y}" },
|
|
269
|
+
color: { type: "string" }
|
|
270
|
+
},
|
|
271
|
+
["from", "to"],
|
|
272
|
+
(args) => {
|
|
273
|
+
const c = {
|
|
274
|
+
id: newId("c"),
|
|
275
|
+
kind: "connector",
|
|
276
|
+
from: args.from,
|
|
277
|
+
to: args.to,
|
|
278
|
+
...args.color !== void 0 ? { color: str(args.color) } : {}
|
|
279
|
+
};
|
|
280
|
+
adapter.setConnectors((all) => [...all, c]);
|
|
281
|
+
return textResult(`Added connector ${c.id}`, c);
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
reg(
|
|
285
|
+
"whiteboard_add_stroke",
|
|
286
|
+
"Add a freeform pen stroke. Points are absolute screen coords (matching the Drawing layer).",
|
|
287
|
+
{
|
|
288
|
+
points: {
|
|
289
|
+
type: "array",
|
|
290
|
+
description: "Array of {x,y} points"
|
|
291
|
+
},
|
|
292
|
+
color: { type: "string" },
|
|
293
|
+
size: { type: "number" }
|
|
294
|
+
},
|
|
295
|
+
["points"],
|
|
296
|
+
(args) => {
|
|
297
|
+
const points = (Array.isArray(args.points) ? args.points : []).map((p) => ({
|
|
298
|
+
x: num(p?.x),
|
|
299
|
+
y: num(p?.y)
|
|
300
|
+
}));
|
|
301
|
+
if (!points.length) return errorResult("Stroke requires at least one point");
|
|
302
|
+
const stroke = {
|
|
303
|
+
id: newId("st"),
|
|
304
|
+
points,
|
|
305
|
+
color: typeof args.color === "string" ? args.color : "#0f172a",
|
|
306
|
+
size: typeof args.size === "number" ? args.size : 2,
|
|
307
|
+
authorId: agent.id
|
|
308
|
+
};
|
|
309
|
+
adapter.setStrokes((all) => [...all, stroke]);
|
|
310
|
+
return textResult(`Added stroke ${stroke.id} (${points.length} points)`, stroke);
|
|
311
|
+
}
|
|
312
|
+
);
|
|
313
|
+
reg(
|
|
314
|
+
"whiteboard_delete_item",
|
|
315
|
+
"Remove any item by id (sticky / shape / connector / stroke).",
|
|
316
|
+
{ id: { type: "string" } },
|
|
317
|
+
["id"],
|
|
318
|
+
(args) => {
|
|
319
|
+
const id = str(args.id);
|
|
320
|
+
let removed = false;
|
|
321
|
+
adapter.setNotes((all) => {
|
|
322
|
+
const next = all.filter((x) => x.id !== id);
|
|
323
|
+
if (next.length !== all.length) removed = true;
|
|
324
|
+
return next;
|
|
325
|
+
});
|
|
326
|
+
adapter.setShapes((all) => {
|
|
327
|
+
const next = all.filter((x) => x.id !== id);
|
|
328
|
+
if (next.length !== all.length) removed = true;
|
|
329
|
+
return next;
|
|
330
|
+
});
|
|
331
|
+
adapter.setConnectors((all) => {
|
|
332
|
+
const next = all.filter((x) => x.id !== id);
|
|
333
|
+
if (next.length !== all.length) removed = true;
|
|
334
|
+
return next;
|
|
335
|
+
});
|
|
336
|
+
adapter.setStrokes((all) => {
|
|
337
|
+
const next = all.filter((x) => x.id !== id);
|
|
338
|
+
if (next.length !== all.length) removed = true;
|
|
339
|
+
return next;
|
|
340
|
+
});
|
|
341
|
+
return removed ? textResult(`Deleted ${id}`) : errorResult(`No item with id ${id}`);
|
|
342
|
+
}
|
|
343
|
+
);
|
|
344
|
+
reg(
|
|
345
|
+
"whiteboard_set_viewport",
|
|
346
|
+
"Pan / zoom the viewport.",
|
|
347
|
+
{ x: { type: "number" }, y: { type: "number" }, zoom: { type: "number" } },
|
|
348
|
+
[],
|
|
349
|
+
(args) => {
|
|
350
|
+
const v = adapter.getViewport();
|
|
351
|
+
const next = {
|
|
352
|
+
x: args.x !== void 0 ? num(args.x) : v.x,
|
|
353
|
+
y: args.y !== void 0 ? num(args.y) : v.y,
|
|
354
|
+
zoom: args.zoom !== void 0 ? num(args.zoom) : v.zoom
|
|
355
|
+
};
|
|
356
|
+
adapter.setViewport(next);
|
|
357
|
+
return textResult(`Viewport \u2192 ${JSON.stringify(next)}`, next);
|
|
358
|
+
}
|
|
359
|
+
);
|
|
360
|
+
reg(
|
|
361
|
+
"whiteboard_set_agent_cursor",
|
|
362
|
+
"Move the agent's presence cursor (or pass null to hide it).",
|
|
363
|
+
{
|
|
364
|
+
x: { type: "number" },
|
|
365
|
+
y: { type: "number" },
|
|
366
|
+
hide: { type: "boolean" }
|
|
367
|
+
},
|
|
368
|
+
[],
|
|
369
|
+
(args) => {
|
|
370
|
+
if (!adapter.setAgentCursor) return errorResult("Host did not provide setAgentCursor");
|
|
371
|
+
if (bool(args.hide)) {
|
|
372
|
+
adapter.setAgentCursor(null);
|
|
373
|
+
return textResult("Agent cursor hidden");
|
|
374
|
+
}
|
|
375
|
+
const cursor = {
|
|
376
|
+
userId: agent.id,
|
|
377
|
+
name: agent.name,
|
|
378
|
+
color: agent.color,
|
|
379
|
+
x: num(args.x),
|
|
380
|
+
y: num(args.y)
|
|
381
|
+
};
|
|
382
|
+
adapter.setAgentCursor(cursor);
|
|
383
|
+
return textResult(`Cursor \u2192 (${cursor.x}, ${cursor.y})`, cursor);
|
|
384
|
+
}
|
|
385
|
+
);
|
|
386
|
+
return {
|
|
387
|
+
id: "whiteboard",
|
|
388
|
+
title: "Whiteboard",
|
|
389
|
+
dispose: () => {
|
|
390
|
+
for (const d of disposers) d();
|
|
391
|
+
adapter.setAgentCursor?.(null);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export { registerWhiteboardBridge };
|
|
397
|
+
//# sourceMappingURL=chunk-5ZUHNNLR.js.map
|
|
398
|
+
//# sourceMappingURL=chunk-5ZUHNNLR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bridges/whiteboard.ts"],"names":[],"mappings":"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","file":"chunk-5ZUHNNLR.js","sourcesContent":["import type {\n BoardItem,\n ConnectorItem,\n RemoteCursor,\n ShapeItem,\n ShapeKind,\n StickyNoteItem,\n Stroke,\n Viewport,\n} from \"@particle-academy/fancy-whiteboard\";\nimport { textResult, errorResult } from \"../mcp/server\";\nimport type { MicroMcpServer } from \"../mcp/server\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\n\n/**\n * State accessors / mutators the bridge needs from the host. The host owns\n * whiteboard state (controlled props on fancy-whiteboard components); the\n * bridge calls into these to read or change it.\n */\nexport type WhiteboardBridgeAdapter = {\n getNotes: () => StickyNoteItem[];\n setNotes: (next: StickyNoteItem[] | ((prev: StickyNoteItem[]) => StickyNoteItem[])) => void;\n getShapes: () => ShapeItem[];\n setShapes: (next: ShapeItem[] | ((prev: ShapeItem[]) => ShapeItem[])) => void;\n getConnectors: () => ConnectorItem[];\n setConnectors: (next: ConnectorItem[] | ((prev: ConnectorItem[]) => ConnectorItem[])) => void;\n getStrokes: () => Stroke[];\n setStrokes: (next: Stroke[] | ((prev: Stroke[]) => Stroke[])) => void;\n getViewport: () => Viewport;\n setViewport: (next: Viewport) => void;\n /** Optional: agent presence cursor (for the visualizer). */\n setAgentCursor?: (cursor: RemoteCursor | null) => void;\n};\n\nexport type WhiteboardBridgeOptions = {\n adapter: WhiteboardBridgeAdapter;\n /** Identity used when the agent stamps authorId on items / cursor. */\n agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\nconst VALID_SHAPES: ShapeKind[] = [\"rect\", \"rounded-rect\", \"ellipse\", \"diamond\", \"triangle\", \"line\", \"arrow\", \"text\"];\n\nconst num = (v: unknown, fallback?: number): number =>\n typeof v === \"number\" && Number.isFinite(v) ? v : fallback ?? 0;\nconst str = (v: unknown, fallback = \"\"): string => (typeof v === \"string\" ? v : fallback);\nconst bool = (v: unknown, fallback = false): boolean => (typeof v === \"boolean\" ? v : fallback);\n\nconst newId = (prefix: string) =>\n `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;\n\n/**\n * registerWhiteboardBridge — wires a full MCP tool set against a fancy-\n * whiteboard session controlled by the host. Returns a Bridge handle the\n * host can dispose to tear everything down.\n */\nexport function registerWhiteboardBridge(\n server: MicroMcpServer,\n options: WhiteboardBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const disposers: Array<() => void> = [];\n\n // Cursor narration is the agent's responsibility — call\n // whiteboard_set_agent_cursor as a separate prerequisite before any\n // mutation. This keeps the protocol honest: each tool does one thing.\n\n\n const reg = (\n name: string,\n description: string,\n inputProperties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n ) => {\n disposers.push(\n server.registerTool(\n {\n name,\n description,\n inputSchema: {\n type: \"object\",\n properties: inputProperties as any,\n required,\n additionalProperties: false,\n },\n },\n async (args) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n },\n ),\n );\n };\n\n // ───────────── Read tools ─────────────\n\n reg(\"whiteboard_get_state\", \"Get the full board state: viewport, all items, strokes.\", {}, [], () => {\n const state = {\n viewport: adapter.getViewport(),\n notes: adapter.getNotes(),\n shapes: adapter.getShapes(),\n connectors: adapter.getConnectors(),\n strokes: adapter.getStrokes(),\n };\n return textResult(JSON.stringify(state, null, 2), state);\n });\n\n reg(\"whiteboard_list_items\", \"List notes, shapes, and connectors with id, kind, and bounds.\", {}, [], () => {\n const items: Array<{ id: string; kind: string; summary: string }> = [];\n for (const n of adapter.getNotes()) {\n items.push({\n id: n.id,\n kind: \"sticky\",\n summary: `\"${(n.text ?? \"\").slice(0, 40)}\" @(${Math.round(n.x)},${Math.round(n.y)}) ${n.width}×${n.height}`,\n });\n }\n for (const s of adapter.getShapes()) {\n items.push({\n id: s.id,\n kind: `shape:${s.shape}`,\n summary: `${s.text ? `\"${s.text}\" ` : \"\"}@(${Math.round(s.x)},${Math.round(s.y)}) ${s.width}×${s.height}`,\n });\n }\n for (const c of adapter.getConnectors()) {\n items.push({ id: c.id, kind: \"connector\", summary: `from=${JSON.stringify(c.from)} to=${JSON.stringify(c.to)}` });\n }\n return textResult(items.map((i) => `${i.kind} ${i.id}: ${i.summary}`).join(\"\\n\") || \"(empty board)\", items);\n });\n\n reg(\n \"whiteboard_get_item\",\n \"Get a single item (sticky / shape / connector) by id.\",\n { id: { type: \"string\" } },\n [\"id\"],\n (args) => {\n const id = str(args.id);\n const all: BoardItem[] = [...adapter.getNotes(), ...adapter.getShapes(), ...adapter.getConnectors()];\n const found = all.find((x) => x.id === id);\n if (!found) return errorResult(`No item with id ${id}`);\n return textResult(JSON.stringify(found, null, 2), found);\n },\n );\n\n // ───────────── Sticky CRUD ─────────────\n\n reg(\n \"whiteboard_add_sticky\",\n \"Add a sticky note. Position is in world coordinates.\",\n {\n x: { type: \"number\" },\n y: { type: \"number\" },\n text: { type: \"string\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n color: { type: \"string\", description: \"CSS color, e.g. #fde68a\" },\n },\n [\"x\", \"y\"],\n async (args) => {\n const x = num(args.x);\n const y = num(args.y);\n const width = num(args.width, 180);\n const height = num(args.height, 140);\n// (cursor narration is now an explicit separate tool call)\n const note: StickyNoteItem = {\n id: newId(\"n\"),\n kind: \"sticky\",\n x, y, width, height,\n text: str(args.text),\n color: typeof args.color === \"string\" ? args.color : \"#fde68a\",\n authorId: agent.id,\n };\n adapter.setNotes((all) => [...all, note]);\n return textResult(`Added sticky ${note.id}`, note);\n },\n );\n\n reg(\n \"whiteboard_stream_text\",\n \"Type text into a sticky note character-by-character so the human can read it forming. The tool returns once streaming finishes.\",\n {\n id: { type: \"string\" },\n text: { type: \"string\" },\n cps: { type: \"number\", description: \"Characters per second. Default 25.\" },\n append: { type: \"boolean\", description: \"Append to existing text instead of replacing. Default false.\" },\n },\n [\"id\", \"text\"],\n async (args) => {\n const id = str(args.id);\n const target = str(args.text);\n const cps = Math.max(1, num(args.cps, 25));\n const append = bool(args.append);\n const startNote = adapter.getNotes().find((n) => n.id === id);\n if (!startNote) return errorResult(`No sticky with id ${id}`);\n const base = append ? (startNote.text ?? \"\") : \"\";\n const interval = Math.max(8, Math.round(1000 / cps));\n for (let i = 0; i <= target.length; i++) {\n const nextText = base + target.slice(0, i);\n adapter.setNotes((all) => all.map((n) => (n.id === id ? { ...n, text: nextText } : n)));\n if (i < target.length) await new Promise((r) => setTimeout(r, interval));\n }\n return textResult(`Streamed ${target.length} chars to ${id}`, { id, text: base + target });\n },\n );\n\n reg(\n \"whiteboard_update_sticky\",\n \"Update fields on a sticky note. Only provided fields are changed.\",\n {\n id: { type: \"string\" },\n x: { type: \"number\" },\n y: { type: \"number\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n text: { type: \"string\" },\n color: { type: \"string\" },\n },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n const existing = adapter.getNotes().find((n) => n.id === id);\n if (!existing) return errorResult(`No sticky with id ${id}`);\n const nextX = args.x !== undefined ? num(args.x) : existing.x;\n const nextY = args.y !== undefined ? num(args.y) : existing.y;\n const nextW = args.width !== undefined ? num(args.width) : existing.width;\n const nextH = args.height !== undefined ? num(args.height) : existing.height;\n// (cursor narration is now an explicit separate tool call)\n let updated: StickyNoteItem | null = null;\n adapter.setNotes((all) =>\n all.map((n) => {\n if (n.id !== id) return n;\n updated = {\n ...n,\n x: nextX, y: nextY, width: nextW, height: nextH,\n ...(args.text !== undefined ? { text: str(args.text) } : {}),\n ...(args.color !== undefined ? { color: str(args.color) } : {}),\n };\n return updated;\n }),\n );\n return textResult(`Updated sticky ${id}`, updated);\n },\n );\n\n // ───────────── Shape CRUD ─────────────\n\n reg(\n \"whiteboard_add_shape\",\n `Add a shape. Kind must be one of: ${VALID_SHAPES.join(\", \")}.`,\n {\n shape: { type: \"string\", enum: VALID_SHAPES },\n x: { type: \"number\" },\n y: { type: \"number\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n text: { type: \"string\" },\n fill: { type: \"string\" },\n stroke: { type: \"string\" },\n flipX: { type: \"boolean\" },\n flipY: { type: \"boolean\" },\n },\n [\"shape\", \"x\", \"y\", \"width\", \"height\"],\n async (args) => {\n const kind = str(args.shape) as ShapeKind;\n if (!VALID_SHAPES.includes(kind)) return errorResult(`Invalid shape kind: ${kind}`);\n const x = num(args.x);\n const y = num(args.y);\n const width = num(args.width);\n const height = num(args.height);\n// (cursor narration is now an explicit separate tool call)\n const shape: ShapeItem = {\n id: newId(\"s\"),\n kind: \"shape\",\n shape: kind,\n x, y, width, height,\n ...(args.text !== undefined ? { text: str(args.text) } : {}),\n ...(args.fill !== undefined ? { fill: str(args.fill) } : {}),\n ...(args.stroke !== undefined ? { stroke: str(args.stroke) } : {}),\n ...(args.flipX !== undefined ? { flipX: bool(args.flipX) } : {}),\n ...(args.flipY !== undefined ? { flipY: bool(args.flipY) } : {}),\n };\n adapter.setShapes((all) => [...all, shape]);\n return textResult(`Added ${kind} ${shape.id}`, shape);\n },\n );\n\n reg(\n \"whiteboard_update_shape\",\n \"Update fields on a shape.\",\n {\n id: { type: \"string\" },\n x: { type: \"number\" },\n y: { type: \"number\" },\n width: { type: \"number\" },\n height: { type: \"number\" },\n text: { type: \"string\" },\n fill: { type: \"string\" },\n stroke: { type: \"string\" },\n },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n const existing = adapter.getShapes().find((s) => s.id === id);\n if (!existing) return errorResult(`No shape with id ${id}`);\n const nextX = args.x !== undefined ? num(args.x) : existing.x;\n const nextY = args.y !== undefined ? num(args.y) : existing.y;\n const nextW = args.width !== undefined ? num(args.width) : existing.width;\n const nextH = args.height !== undefined ? num(args.height) : existing.height;\n// (cursor narration is now an explicit separate tool call)\n let updated: ShapeItem | null = null;\n adapter.setShapes((all) =>\n all.map((s) => {\n if (s.id !== id) return s;\n updated = {\n ...s,\n x: nextX, y: nextY, width: nextW, height: nextH,\n ...(args.text !== undefined ? { text: str(args.text) } : {}),\n ...(args.fill !== undefined ? { fill: str(args.fill) } : {}),\n ...(args.stroke !== undefined ? { stroke: str(args.stroke) } : {}),\n };\n return updated;\n }),\n );\n return textResult(`Updated shape ${id}`, updated);\n },\n );\n\n // ───────────── Connectors ─────────────\n\n reg(\n \"whiteboard_add_connector\",\n \"Connect two items by id, or specify explicit world-space points.\",\n {\n from: { description: \"Item id (string) or {x,y}\" },\n to: { description: \"Item id (string) or {x,y}\" },\n color: { type: \"string\" },\n },\n [\"from\", \"to\"],\n (args) => {\n const c: ConnectorItem = {\n id: newId(\"c\"),\n kind: \"connector\",\n from: args.from as any,\n to: args.to as any,\n ...(args.color !== undefined ? { color: str(args.color) } : {}),\n };\n adapter.setConnectors((all) => [...all, c]);\n return textResult(`Added connector ${c.id}`, c);\n },\n );\n\n // ───────────── Drawing ─────────────\n\n reg(\n \"whiteboard_add_stroke\",\n \"Add a freeform pen stroke. Points are absolute screen coords (matching the Drawing layer).\",\n {\n points: {\n type: \"array\",\n description: \"Array of {x,y} points\",\n },\n color: { type: \"string\" },\n size: { type: \"number\" },\n },\n [\"points\"],\n (args) => {\n const points = (Array.isArray(args.points) ? args.points : []).map((p: any) => ({\n x: num(p?.x),\n y: num(p?.y),\n }));\n if (!points.length) return errorResult(\"Stroke requires at least one point\");\n const stroke: Stroke = {\n id: newId(\"st\"),\n points,\n color: typeof args.color === \"string\" ? args.color : \"#0f172a\",\n size: typeof args.size === \"number\" ? args.size : 2,\n authorId: agent.id,\n };\n adapter.setStrokes((all) => [...all, stroke]);\n return textResult(`Added stroke ${stroke.id} (${points.length} points)`, stroke);\n },\n );\n\n // ───────────── Generic delete ─────────────\n\n reg(\n \"whiteboard_delete_item\",\n \"Remove any item by id (sticky / shape / connector / stroke).\",\n { id: { type: \"string\" } },\n [\"id\"],\n (args) => {\n const id = str(args.id);\n let removed = false;\n adapter.setNotes((all) => {\n const next = all.filter((x) => x.id !== id);\n if (next.length !== all.length) removed = true;\n return next;\n });\n adapter.setShapes((all) => {\n const next = all.filter((x) => x.id !== id);\n if (next.length !== all.length) removed = true;\n return next;\n });\n adapter.setConnectors((all) => {\n const next = all.filter((x) => x.id !== id);\n if (next.length !== all.length) removed = true;\n return next;\n });\n adapter.setStrokes((all) => {\n const next = all.filter((x) => x.id !== id);\n if (next.length !== all.length) removed = true;\n return next;\n });\n return removed ? textResult(`Deleted ${id}`) : errorResult(`No item with id ${id}`);\n },\n );\n\n // ───────────── Viewport / agent presence ─────────────\n\n reg(\n \"whiteboard_set_viewport\",\n \"Pan / zoom the viewport.\",\n { x: { type: \"number\" }, y: { type: \"number\" }, zoom: { type: \"number\" } },\n [],\n (args) => {\n const v = adapter.getViewport();\n const next: Viewport = {\n x: args.x !== undefined ? num(args.x) : v.x,\n y: args.y !== undefined ? num(args.y) : v.y,\n zoom: args.zoom !== undefined ? num(args.zoom) : v.zoom,\n };\n adapter.setViewport(next);\n return textResult(`Viewport → ${JSON.stringify(next)}`, next);\n },\n );\n\n reg(\n \"whiteboard_set_agent_cursor\",\n \"Move the agent's presence cursor (or pass null to hide it).\",\n {\n x: { type: \"number\" },\n y: { type: \"number\" },\n hide: { type: \"boolean\" },\n },\n [],\n (args) => {\n if (!adapter.setAgentCursor) return errorResult(\"Host did not provide setAgentCursor\");\n if (bool(args.hide)) {\n adapter.setAgentCursor(null);\n return textResult(\"Agent cursor hidden\");\n }\n const cursor: RemoteCursor = {\n userId: agent.id,\n name: agent.name,\n color: agent.color,\n x: num(args.x),\n y: num(args.y),\n };\n adapter.setAgentCursor(cursor);\n return textResult(`Cursor → (${cursor.x}, ${cursor.y})`, cursor);\n },\n );\n\n return {\n id: \"whiteboard\",\n title: \"Whiteboard\",\n dispose: () => {\n for (const d of disposers) d();\n adapter.setAgentCursor?.(null);\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/mcp/transports/in-process.ts
|
|
2
|
+
var InProcessTransport = class {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
5
|
+
}
|
|
6
|
+
/** Bind to a server. Called from the client's setup, not directly. */
|
|
7
|
+
bindServer(server) {
|
|
8
|
+
this.server = server;
|
|
9
|
+
}
|
|
10
|
+
/** Server → client (delivered to subscribed listeners). */
|
|
11
|
+
send(message) {
|
|
12
|
+
for (const l of this.listeners) l(message);
|
|
13
|
+
}
|
|
14
|
+
/** Client → server. Awaitable so callers can flush. */
|
|
15
|
+
async deliver(message) {
|
|
16
|
+
if (!this.server) throw new Error("InProcessTransport has no bound server");
|
|
17
|
+
await this.server.receive(this, message);
|
|
18
|
+
}
|
|
19
|
+
/** Subscribe to messages the server pushes to this client. */
|
|
20
|
+
onServerMessage(listener) {
|
|
21
|
+
this.listeners.add(listener);
|
|
22
|
+
return () => this.listeners.delete(listener);
|
|
23
|
+
}
|
|
24
|
+
close() {
|
|
25
|
+
this.listeners.clear();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
function attachInProcess(server) {
|
|
29
|
+
const transport = new InProcessTransport();
|
|
30
|
+
transport.bindServer(server);
|
|
31
|
+
server.attach(transport);
|
|
32
|
+
return transport;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/mcp/transports/relay.ts
|
|
36
|
+
var RelayTransport = class {
|
|
37
|
+
constructor(channel) {
|
|
38
|
+
this.channel = channel;
|
|
39
|
+
}
|
|
40
|
+
bindServer(server) {
|
|
41
|
+
this.server = server;
|
|
42
|
+
}
|
|
43
|
+
send(message) {
|
|
44
|
+
this.channel.sendToRemote(message);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Host calls this with each frame received from the remote agent. Accepts
|
|
48
|
+
* either a parsed object or a raw JSON string.
|
|
49
|
+
*/
|
|
50
|
+
async deliverFromRemote(payload) {
|
|
51
|
+
if (!this.server) throw new Error("RelayTransport has no bound server");
|
|
52
|
+
const message = typeof payload === "string" ? JSON.parse(payload) : payload;
|
|
53
|
+
await this.server.receive(this, message);
|
|
54
|
+
}
|
|
55
|
+
close() {
|
|
56
|
+
this.channel.onClose?.();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
function attachRelay(server, channel) {
|
|
60
|
+
const transport = new RelayTransport(channel);
|
|
61
|
+
transport.bindServer(server);
|
|
62
|
+
server.attach(transport);
|
|
63
|
+
return transport;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { InProcessTransport, RelayTransport, attachInProcess, attachRelay };
|
|
67
|
+
//# sourceMappingURL=chunk-6LTKCNLF.js.map
|
|
68
|
+
//# sourceMappingURL=chunk-6LTKCNLF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/transports/in-process.ts","../src/mcp/transports/relay.ts"],"names":[],"mappings":";AAeO,IAAM,qBAAN,MAA8C;AAAA,EAA9C,WAAA,GAAA;AAEL,IAAA,IAAA,CAAQ,SAAA,uBAAgB,GAAA,EAAmC;AAAA,EAAA;AAAA;AAAA,EAG3D,WAAW,MAAA,EAA8B;AACvC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA,EAGA,KAAK,OAAA,EAA+B;AAClC,IAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,SAAA,EAAW,CAAA,CAAE,OAAO,CAAA;AAAA,EAC3C;AAAA;AAAA,EAGA,MAAM,QAAQ,OAAA,EAAwC;AACpD,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,EAAQ,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAC1E,IAAA,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AAAA,EACzC;AAAA;AAAA,EAGA,gBAAgB,QAAA,EAAqD;AACnE,IAAA,IAAA,CAAK,SAAA,CAAU,IAAI,QAAQ,CAAA;AAC3B,IAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,QAAQ,CAAA;AAAA,EAC7C;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,EACvB;AACF;AAKO,SAAS,gBAAgB,MAAA,EAA4C;AAC1E,EAAA,MAAM,SAAA,GAAY,IAAI,kBAAA,EAAmB;AACzC,EAAA,SAAA,CAAU,WAAW,MAAM,CAAA;AAC3B,EAAA,MAAA,CAAO,OAAO,SAAS,CAAA;AACvB,EAAA,OAAO,SAAA;AACT;;;AC7BO,IAAM,iBAAN,MAA0C;AAAA,EAE/C,YAAoB,OAAA,EAAuB;AAAvB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAAwB;AAAA,EAE5C,WAAW,MAAA,EAA8B;AACvC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,KAAK,OAAA,EAA+B;AAClC,IAAA,IAAA,CAAK,OAAA,CAAQ,aAAa,OAAO,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,kBAAkB,OAAA,EAAiD;AACvE,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,EAAQ,MAAM,IAAI,MAAM,oCAAoC,CAAA;AACtE,IAAA,MAAM,UAAU,OAAO,OAAA,KAAY,WAC9B,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,GACnB,OAAA;AACJ,IAAA,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AAAA,EACzC;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,QAAQ,OAAA,IAAU;AAAA,EACzB;AACF;AAKO,SAAS,WAAA,CAAY,QAAwB,OAAA,EAAuC;AACzF,EAAA,MAAM,SAAA,GAAY,IAAI,cAAA,CAAe,OAAO,CAAA;AAC5C,EAAA,SAAA,CAAU,WAAW,MAAM,CAAA;AAC3B,EAAA,MAAA,CAAO,OAAO,SAAS,CAAA;AACvB,EAAA,OAAO,SAAA;AACT","file":"chunk-6LTKCNLF.js","sourcesContent":["import type { JsonRpcMessage } from \"../types\";\nimport type { MicroMcpServer, Transport } from \"../server\";\n\n/**\n * InProcessTransport — direct function-call wiring between an in-page MCP\n * client (e.g. an embedded chat agent) and a MicroMcpServer running in\n * the same JS context. No serialization, no network.\n *\n * Usage:\n *\n * const t = new InProcessTransport();\n * server.attach(t);\n * t.onServerMessage((msg) => { ... }); // client subscribes\n * t.send({ jsonrpc: \"2.0\", id: 1, method: \"tools/list\" }); // client → server\n */\nexport class InProcessTransport implements Transport {\n private server?: MicroMcpServer;\n private listeners = new Set<(msg: JsonRpcMessage) => void>();\n\n /** Bind to a server. Called from the client's setup, not directly. */\n bindServer(server: MicroMcpServer): void {\n this.server = server;\n }\n\n /** Server → client (delivered to subscribed listeners). */\n send(message: JsonRpcMessage): void {\n for (const l of this.listeners) l(message);\n }\n\n /** Client → server. Awaitable so callers can flush. */\n async deliver(message: JsonRpcMessage): Promise<void> {\n if (!this.server) throw new Error(\"InProcessTransport has no bound server\");\n await this.server.receive(this, message);\n }\n\n /** Subscribe to messages the server pushes to this client. */\n onServerMessage(listener: (msg: JsonRpcMessage) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n close(): void {\n this.listeners.clear();\n }\n}\n\n/**\n * Convenience: create a server-attached in-process transport in one call.\n */\nexport function attachInProcess(server: MicroMcpServer): InProcessTransport {\n const transport = new InProcessTransport();\n transport.bindServer(server);\n server.attach(transport);\n return transport;\n}\n","import type { JsonRpcMessage } from \"../types\";\nimport type { MicroMcpServer, Transport } from \"../server\";\n\n/**\n * RelayTransport — wraps any duplex JSON-frame channel (e.g. a Reverb\n * websocket private channel, a WebRTC data channel) so external agents\n * can talk to a browser-side MicroMcpServer.\n *\n * The host app owns the actual channel. This class only handles framing\n * (JSON.stringify / JSON.parse) and the server contract.\n *\n * Channel contract:\n * - host calls `transport.deliverFromRemote(payload)` with each frame\n * it receives from the remote agent\n * - host implements `sendToRemote(frame)` so the transport can deliver\n * server → client frames outward\n *\n * See docs/relay-protocol.md for the wire format.\n */\nexport type RelayChannel = {\n sendToRemote: (frame: JsonRpcMessage) => void;\n /** Optional: notify the channel that the server is gone. */\n onClose?: () => void;\n};\n\nexport class RelayTransport implements Transport {\n private server?: MicroMcpServer;\n constructor(private channel: RelayChannel) {}\n\n bindServer(server: MicroMcpServer): void {\n this.server = server;\n }\n\n send(message: JsonRpcMessage): void {\n this.channel.sendToRemote(message);\n }\n\n /**\n * Host calls this with each frame received from the remote agent. Accepts\n * either a parsed object or a raw JSON string.\n */\n async deliverFromRemote(payload: JsonRpcMessage | string): Promise<void> {\n if (!this.server) throw new Error(\"RelayTransport has no bound server\");\n const message = typeof payload === \"string\"\n ? (JSON.parse(payload) as JsonRpcMessage)\n : payload;\n await this.server.receive(this, message);\n }\n\n close(): void {\n this.channel.onClose?.();\n }\n}\n\n/**\n * Convenience wiring. Returns the bound transport.\n */\nexport function attachRelay(server: MicroMcpServer, channel: RelayChannel): RelayTransport {\n const transport = new RelayTransport(channel);\n transport.bindServer(server);\n server.attach(transport);\n return transport;\n}\n"]}
|