@particle-academy/agent-integrations 0.2.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/bridges/charts.d.cts +39 -0
- package/dist/bridges/charts.d.ts +39 -0
- package/dist/bridges/code.d.cts +47 -0
- package/dist/bridges/code.d.ts +47 -0
- package/dist/bridges/flow.d.cts +4 -3
- package/dist/bridges/flow.d.ts +4 -3
- package/dist/bridges/forms.d.cts +76 -0
- package/dist/bridges/forms.d.ts +76 -0
- package/dist/bridges/scene.d.cts +54 -0
- package/dist/bridges/scene.d.ts +54 -0
- package/dist/bridges/screens.d.cts +78 -0
- package/dist/bridges/screens.d.ts +78 -0
- package/dist/bridges/sheets.d.cts +62 -0
- package/dist/bridges/sheets.d.ts +62 -0
- package/dist/bridges/whiteboard.d.cts +4 -3
- package/dist/bridges/whiteboard.d.ts +4 -3
- package/dist/bridges-charts.cjs +167 -0
- package/dist/bridges-charts.cjs.map +1 -0
- package/dist/bridges-charts.js +6 -0
- package/dist/bridges-charts.js.map +1 -0
- package/dist/bridges-code.cjs +219 -0
- package/dist/bridges-code.cjs.map +1 -0
- package/dist/bridges-code.js +6 -0
- package/dist/bridges-code.js.map +1 -0
- package/dist/bridges-flow.cjs +78 -19
- package/dist/bridges-flow.cjs.map +1 -1
- package/dist/bridges-flow.js +4 -2
- package/dist/bridges-forms.cjs +205 -0
- package/dist/bridges-forms.cjs.map +1 -0
- package/dist/bridges-forms.js +6 -0
- package/dist/bridges-forms.js.map +1 -0
- package/dist/bridges-scene.cjs +250 -0
- package/dist/bridges-scene.cjs.map +1 -0
- package/dist/bridges-scene.js +6 -0
- package/dist/bridges-scene.js.map +1 -0
- package/dist/bridges-screens.cjs +227 -0
- package/dist/bridges-screens.cjs.map +1 -0
- package/dist/bridges-screens.js +6 -0
- package/dist/bridges-screens.js.map +1 -0
- package/dist/bridges-sheets.cjs +327 -0
- package/dist/bridges-sheets.cjs.map +1 -0
- package/dist/bridges-sheets.js +6 -0
- package/dist/bridges-sheets.js.map +1 -0
- package/dist/bridges-whiteboard.cjs +226 -40
- package/dist/bridges-whiteboard.cjs.map +1 -1
- package/dist/bridges-whiteboard.js +5 -2
- package/dist/{chunk-5ZUHNNLR.js → chunk-3KSZNGNW.js} +81 -43
- package/dist/chunk-3KSZNGNW.js.map +1 -0
- package/dist/chunk-4BL5M3U3.js +158 -0
- package/dist/chunk-4BL5M3U3.js.map +1 -0
- package/dist/{chunk-QGCF7YKW.js → chunk-4KAIV6OD.js} +40 -12
- package/dist/chunk-4KAIV6OD.js.map +1 -0
- package/dist/chunk-52S7XYZK.js +38 -0
- package/dist/chunk-52S7XYZK.js.map +1 -0
- package/dist/chunk-57ZDHD53.js +180 -0
- package/dist/chunk-57ZDHD53.js.map +1 -0
- package/dist/chunk-E4AICMFZ.js +83 -0
- package/dist/chunk-E4AICMFZ.js.map +1 -0
- package/dist/chunk-GQ7XXK7G.js +124 -0
- package/dist/chunk-GQ7XXK7G.js.map +1 -0
- package/dist/chunk-HSTW7ZNO.js +172 -0
- package/dist/chunk-HSTW7ZNO.js.map +1 -0
- package/dist/chunk-IANI25IT.js +280 -0
- package/dist/chunk-IANI25IT.js.map +1 -0
- package/dist/{chunk-FLEOQUKF.js → chunk-JMYPUAFH.js} +17 -2
- package/dist/chunk-JMYPUAFH.js.map +1 -0
- package/dist/chunk-JU2N4KK6.js +34 -0
- package/dist/chunk-JU2N4KK6.js.map +1 -0
- package/dist/{chunk-2VOQJKSU.js → chunk-N3H4DXY5.js} +44 -22
- package/dist/chunk-N3H4DXY5.js.map +1 -0
- package/dist/chunk-NTDZWGYB.js +120 -0
- package/dist/chunk-NTDZWGYB.js.map +1 -0
- package/dist/chunk-RGO42EQ6.js +25 -0
- package/dist/chunk-RGO42EQ6.js.map +1 -0
- package/dist/chunk-X66JWQBB.js +37 -0
- package/dist/chunk-X66JWQBB.js.map +1 -0
- package/dist/chunk-XRAJSOPS.js +203 -0
- package/dist/chunk-XRAJSOPS.js.map +1 -0
- package/dist/index.cjs +1766 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -3
- package/dist/index.d.ts +99 -3
- package/dist/index.js +115 -9
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.cts +5 -2
- package/dist/mcp/index.d.ts +5 -2
- package/dist/mcp.cjs +37 -9
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.js +1 -1
- package/dist/presence/index.d.cts +136 -0
- package/dist/presence/index.d.ts +136 -0
- package/dist/presence.cjs +107 -0
- package/dist/presence.cjs.map +1 -0
- package/dist/presence.js +5 -0
- package/dist/presence.js.map +1 -0
- package/dist/registry-2DRURS6U.js +3 -0
- package/dist/registry-2DRURS6U.js.map +1 -0
- package/dist/server-BsSwfemr.d.cts +63 -0
- package/dist/server-Du3-IGqM.d.ts +63 -0
- package/dist/sharing/index.d.cts +3 -1
- package/dist/sharing/index.d.ts +3 -1
- package/dist/sharing.cjs +68 -0
- package/dist/sharing.cjs.map +1 -1
- package/dist/sharing.js +1 -1
- package/dist/sheets-adapter.cjs +96 -0
- package/dist/sheets-adapter.cjs.map +1 -0
- package/dist/sheets-adapter.d.cts +115 -0
- package/dist/sheets-adapter.d.ts +115 -0
- package/dist/sheets-adapter.js +4 -0
- package/dist/sheets-adapter.js.map +1 -0
- package/dist/styles.css +57 -0
- package/dist/styles.css.map +1 -1
- package/dist/tool-host-BQuUygLF.d.cts +60 -0
- package/dist/tool-host-C8JMMGYq.d.ts +60 -0
- package/dist/{types-CRPA_D0z.d.ts → types-CCSBGW9T.d.cts} +2 -2
- package/dist/{types-DR5AS6Rd.d.cts → types-DIVNcIQO.d.ts} +2 -2
- package/dist/types-aOQLTW0E.d.cts +112 -0
- package/dist/types-aOQLTW0E.d.ts +112 -0
- package/dist/undo/index.d.cts +69 -0
- package/dist/undo/index.d.ts +69 -0
- package/dist/undo.cjs +163 -0
- package/dist/undo.cjs.map +1 -0
- package/dist/undo.js +5 -0
- package/dist/undo.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-2VOQJKSU.js.map +0 -1
- package/dist/chunk-5ZUHNNLR.js.map +0 -1
- package/dist/chunk-FLEOQUKF.js.map +0 -1
- package/dist/chunk-QGCF7YKW.js.map +0 -1
- package/dist/server-Bv985us3.d.cts +0 -173
- package/dist/server-Bv985us3.d.ts +0 -173
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { wrapToolWithActivity } from './chunk-52S7XYZK.js';
|
|
2
|
+
import { textResult, errorResult } from './chunk-4KAIV6OD.js';
|
|
3
|
+
|
|
4
|
+
// src/bridges/sheets.ts
|
|
5
|
+
var DEFAULT_AGENT = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
6
|
+
function registerSheetsBridge(host, options) {
|
|
7
|
+
const { adapter } = options;
|
|
8
|
+
const agent = { ...DEFAULT_AGENT, ...options.agent ?? {} };
|
|
9
|
+
const disposers = [];
|
|
10
|
+
const target = (sheetId, address) => ({
|
|
11
|
+
kind: "sheet",
|
|
12
|
+
screenId: adapter.screenId,
|
|
13
|
+
elementId: address ? `${sheetId}!${address}` : sheetId,
|
|
14
|
+
label: address ? `${sheetId}!${address}` : sheetId
|
|
15
|
+
});
|
|
16
|
+
const reg = (name, description, properties, required, handler, isMutation, resolveTarget) => {
|
|
17
|
+
const wrapped = async (args) => {
|
|
18
|
+
try {
|
|
19
|
+
return await handler(args);
|
|
20
|
+
} catch (e) {
|
|
21
|
+
return errorResult(e instanceof Error ? e.message : String(e));
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const final = isMutation ? wrapToolWithActivity(wrapped, {
|
|
25
|
+
toolName: name,
|
|
26
|
+
agent,
|
|
27
|
+
kind: "sheet",
|
|
28
|
+
screenId: adapter.screenId,
|
|
29
|
+
resolveTarget: ({ args, result }) => resolveTarget?.(args, result) ?? target(getSheetId(args))
|
|
30
|
+
}) : wrapped;
|
|
31
|
+
disposers.push(
|
|
32
|
+
host.registerTool(
|
|
33
|
+
{
|
|
34
|
+
name,
|
|
35
|
+
description,
|
|
36
|
+
inputSchema: { type: "object", properties, required, additionalProperties: false }
|
|
37
|
+
},
|
|
38
|
+
final
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
function activeSheetId() {
|
|
43
|
+
return adapter.getWorkbook().activeSheetId;
|
|
44
|
+
}
|
|
45
|
+
function getSheetId(args) {
|
|
46
|
+
return typeof args.sheet === "string" ? args.sheet : activeSheetId();
|
|
47
|
+
}
|
|
48
|
+
function getSheet(workbook, sheetId) {
|
|
49
|
+
return workbook.sheets.find((s) => s.id === sheetId);
|
|
50
|
+
}
|
|
51
|
+
reg(
|
|
52
|
+
"sheet_describe",
|
|
53
|
+
"Describe the workbook: every sheet's id, name, dimensions, cell count, active sheet. Call before reading or writing.",
|
|
54
|
+
{},
|
|
55
|
+
[],
|
|
56
|
+
() => {
|
|
57
|
+
const wb = adapter.getWorkbook();
|
|
58
|
+
const summary = {
|
|
59
|
+
activeSheetId: wb.activeSheetId,
|
|
60
|
+
sheets: wb.sheets.map((s) => ({
|
|
61
|
+
id: s.id,
|
|
62
|
+
name: s.name,
|
|
63
|
+
cellCount: Object.keys(s.cells).length,
|
|
64
|
+
columnCount: Object.keys(s.columnWidths).length,
|
|
65
|
+
frozenRows: s.frozenRows,
|
|
66
|
+
frozenCols: s.frozenCols
|
|
67
|
+
}))
|
|
68
|
+
};
|
|
69
|
+
const text = `Active: ${summary.activeSheetId}
|
|
70
|
+
` + summary.sheets.map((s) => `${s.id} "${s.name}" \u2014 ${s.cellCount} cells`).join("\n");
|
|
71
|
+
return textResult(text, summary);
|
|
72
|
+
},
|
|
73
|
+
false
|
|
74
|
+
);
|
|
75
|
+
reg(
|
|
76
|
+
"sheet_get_cell",
|
|
77
|
+
"Read a single cell's raw + computed value.",
|
|
78
|
+
{
|
|
79
|
+
sheet: { type: "string", description: "Sheet id (defaults to active)." },
|
|
80
|
+
address: { type: "string", description: 'A1-style address, e.g. "B12".' }
|
|
81
|
+
},
|
|
82
|
+
["address"],
|
|
83
|
+
(args) => {
|
|
84
|
+
const sheetId = getSheetId(args);
|
|
85
|
+
const address = String(args.address);
|
|
86
|
+
const sheet = getSheet(adapter.getWorkbook(), sheetId);
|
|
87
|
+
if (!sheet) return errorResult(`No sheet ${sheetId}`);
|
|
88
|
+
const cell = sheet.cells[address];
|
|
89
|
+
if (!cell) {
|
|
90
|
+
return textResult(`(empty)`, { sheet: sheetId, address, value: null });
|
|
91
|
+
}
|
|
92
|
+
return textResult(`${address} = ${JSON.stringify(cell.computedValue ?? cell.value)}`, { ...cell, sheet: sheetId, address });
|
|
93
|
+
},
|
|
94
|
+
false
|
|
95
|
+
);
|
|
96
|
+
reg(
|
|
97
|
+
"sheet_get_range",
|
|
98
|
+
"Read a rectangular range as a 2D array of values.",
|
|
99
|
+
{
|
|
100
|
+
sheet: { type: "string" },
|
|
101
|
+
start: { type: "string", description: "Top-left A1 address." },
|
|
102
|
+
end: { type: "string", description: "Bottom-right A1 address." }
|
|
103
|
+
},
|
|
104
|
+
["start", "end"],
|
|
105
|
+
(args) => {
|
|
106
|
+
const sheetId = getSheetId(args);
|
|
107
|
+
const sheet = getSheet(adapter.getWorkbook(), sheetId);
|
|
108
|
+
if (!sheet) return errorResult(`No sheet ${sheetId}`);
|
|
109
|
+
const grid = readRange(sheet, String(args.start), String(args.end));
|
|
110
|
+
return textResult(JSON.stringify(grid), { sheet: sheetId, start: args.start, end: args.end, values: grid });
|
|
111
|
+
},
|
|
112
|
+
false
|
|
113
|
+
);
|
|
114
|
+
reg(
|
|
115
|
+
"sheet_set_cell",
|
|
116
|
+
"Set a single cell's value. To set a formula, pass a string starting with '='.",
|
|
117
|
+
{
|
|
118
|
+
sheet: { type: "string" },
|
|
119
|
+
address: { type: "string" },
|
|
120
|
+
value: { description: "string | number | boolean | null. Strings starting with '=' are stored as formulas." }
|
|
121
|
+
},
|
|
122
|
+
["address", "value"],
|
|
123
|
+
(args) => {
|
|
124
|
+
const sheetId = getSheetId(args);
|
|
125
|
+
const address = String(args.address);
|
|
126
|
+
const value = args.value;
|
|
127
|
+
const wb = adapter.getWorkbook();
|
|
128
|
+
const sheet = getSheet(wb, sheetId);
|
|
129
|
+
if (!sheet) return errorResult(`No sheet ${sheetId}`);
|
|
130
|
+
const next = mergeCells(wb, sheetId, { [address]: cellOf(address, value) });
|
|
131
|
+
adapter.setWorkbook(next);
|
|
132
|
+
return textResult(`${sheetId}!${address} \u2190 ${JSON.stringify(value)}`, { sheet: sheetId, address, value });
|
|
133
|
+
},
|
|
134
|
+
true,
|
|
135
|
+
(args) => target(getSheetId(args), String(args.address ?? ""))
|
|
136
|
+
);
|
|
137
|
+
reg(
|
|
138
|
+
"sheet_set_range",
|
|
139
|
+
'Set many cells atomically. `cells` is an object map of { "A1": value, "B2": value, ... }.',
|
|
140
|
+
{
|
|
141
|
+
sheet: { type: "string" },
|
|
142
|
+
cells: { type: "object" }
|
|
143
|
+
},
|
|
144
|
+
["cells"],
|
|
145
|
+
(args) => {
|
|
146
|
+
const sheetId = getSheetId(args);
|
|
147
|
+
const wb = adapter.getWorkbook();
|
|
148
|
+
const sheet = getSheet(wb, sheetId);
|
|
149
|
+
if (!sheet) return errorResult(`No sheet ${sheetId}`);
|
|
150
|
+
const cells = args.cells && typeof args.cells === "object" ? args.cells : {};
|
|
151
|
+
const updates = {};
|
|
152
|
+
for (const [addr, v] of Object.entries(cells)) updates[addr] = cellOf(addr, v);
|
|
153
|
+
const next = mergeCells(wb, sheetId, updates);
|
|
154
|
+
adapter.setWorkbook(next);
|
|
155
|
+
return textResult(`Set ${Object.keys(cells).length} cells in ${sheetId}`, { sheet: sheetId, count: Object.keys(cells).length });
|
|
156
|
+
},
|
|
157
|
+
true
|
|
158
|
+
);
|
|
159
|
+
reg(
|
|
160
|
+
"sheet_add_sheet",
|
|
161
|
+
"Add a new sheet (tab) to the workbook.",
|
|
162
|
+
{ id: { type: "string" }, name: { type: "string" } },
|
|
163
|
+
["id", "name"],
|
|
164
|
+
(args) => {
|
|
165
|
+
const wb = adapter.getWorkbook();
|
|
166
|
+
const id = String(args.id);
|
|
167
|
+
const name = String(args.name);
|
|
168
|
+
if (wb.sheets.find((s) => s.id === id)) return errorResult(`Sheet ${id} already exists`);
|
|
169
|
+
const next = {
|
|
170
|
+
...wb,
|
|
171
|
+
sheets: [
|
|
172
|
+
...wb.sheets,
|
|
173
|
+
{
|
|
174
|
+
id,
|
|
175
|
+
name,
|
|
176
|
+
cells: {},
|
|
177
|
+
columnWidths: {},
|
|
178
|
+
mergedRegions: [],
|
|
179
|
+
columnFilters: {},
|
|
180
|
+
frozenRows: 0,
|
|
181
|
+
frozenCols: 0
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
};
|
|
185
|
+
adapter.setWorkbook(next);
|
|
186
|
+
return textResult(`Added sheet ${id} ("${name}")`, { id, name });
|
|
187
|
+
},
|
|
188
|
+
true,
|
|
189
|
+
(args) => target(String(args.id ?? ""))
|
|
190
|
+
);
|
|
191
|
+
reg(
|
|
192
|
+
"sheet_set_active",
|
|
193
|
+
"Switch to a different sheet tab.",
|
|
194
|
+
{ sheet: { type: "string" } },
|
|
195
|
+
["sheet"],
|
|
196
|
+
(args) => {
|
|
197
|
+
const sheetId = String(args.sheet);
|
|
198
|
+
const wb = adapter.getWorkbook();
|
|
199
|
+
if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);
|
|
200
|
+
adapter.setWorkbook({ ...wb, activeSheetId: sheetId });
|
|
201
|
+
return textResult(`Active sheet \u2192 ${sheetId}`, { sheet: sheetId });
|
|
202
|
+
},
|
|
203
|
+
true
|
|
204
|
+
);
|
|
205
|
+
reg(
|
|
206
|
+
"sheet_set_active_cell",
|
|
207
|
+
"Move the active cell selection (host implements DOM focus + scroll).",
|
|
208
|
+
{ sheet: { type: "string" }, address: { type: "string" } },
|
|
209
|
+
["address"],
|
|
210
|
+
(args) => {
|
|
211
|
+
if (!adapter.setActiveCell) return errorResult("Host did not provide setActiveCell.");
|
|
212
|
+
const sheetId = getSheetId(args);
|
|
213
|
+
adapter.setActiveCell(sheetId, String(args.address));
|
|
214
|
+
return textResult(`Active cell \u2192 ${sheetId}!${args.address}`, { sheet: sheetId, address: args.address });
|
|
215
|
+
},
|
|
216
|
+
true,
|
|
217
|
+
(args) => target(getSheetId(args), String(args.address ?? ""))
|
|
218
|
+
);
|
|
219
|
+
return {
|
|
220
|
+
id: "sheets",
|
|
221
|
+
title: "Sheets",
|
|
222
|
+
dispose: () => {
|
|
223
|
+
for (const d of disposers) d();
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function cellOf(address, value) {
|
|
228
|
+
return { address, value };
|
|
229
|
+
}
|
|
230
|
+
function mergeCells(wb, sheetId, updates) {
|
|
231
|
+
return {
|
|
232
|
+
...wb,
|
|
233
|
+
sheets: wb.sheets.map(
|
|
234
|
+
(s) => s.id !== sheetId ? s : { ...s, cells: { ...s.cells, ...updates } }
|
|
235
|
+
)
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function parseAddress(addr) {
|
|
239
|
+
const m = /^([A-Za-z]+)(\d+)$/.exec(addr.trim());
|
|
240
|
+
if (!m) throw new Error(`Bad address: ${addr}`);
|
|
241
|
+
const letters = m[1].toUpperCase();
|
|
242
|
+
let col = 0;
|
|
243
|
+
for (let i = 0; i < letters.length; i++) {
|
|
244
|
+
col = col * 26 + (letters.charCodeAt(i) - 64);
|
|
245
|
+
}
|
|
246
|
+
return { col: col - 1, row: parseInt(m[2], 10) - 1 };
|
|
247
|
+
}
|
|
248
|
+
function colToLetter(col) {
|
|
249
|
+
let s = "";
|
|
250
|
+
let n = col + 1;
|
|
251
|
+
while (n > 0) {
|
|
252
|
+
const r = (n - 1) % 26;
|
|
253
|
+
s = String.fromCharCode(65 + r) + s;
|
|
254
|
+
n = Math.floor((n - 1) / 26);
|
|
255
|
+
}
|
|
256
|
+
return s;
|
|
257
|
+
}
|
|
258
|
+
function readRange(sheet, startAddr, endAddr) {
|
|
259
|
+
const start = parseAddress(startAddr);
|
|
260
|
+
const end = parseAddress(endAddr);
|
|
261
|
+
const r0 = Math.min(start.row, end.row);
|
|
262
|
+
const r1 = Math.max(start.row, end.row);
|
|
263
|
+
const c0 = Math.min(start.col, end.col);
|
|
264
|
+
const c1 = Math.max(start.col, end.col);
|
|
265
|
+
const grid = [];
|
|
266
|
+
for (let r = r0; r <= r1; r++) {
|
|
267
|
+
const row = [];
|
|
268
|
+
for (let c = c0; c <= c1; c++) {
|
|
269
|
+
const addr = `${colToLetter(c)}${r + 1}`;
|
|
270
|
+
const cell = sheet.cells[addr];
|
|
271
|
+
row.push(cell?.computedValue ?? cell?.value ?? null);
|
|
272
|
+
}
|
|
273
|
+
grid.push(row);
|
|
274
|
+
}
|
|
275
|
+
return grid;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export { registerSheetsBridge };
|
|
279
|
+
//# sourceMappingURL=chunk-IANI25IT.js.map
|
|
280
|
+
//# sourceMappingURL=chunk-IANI25IT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bridges/sheets.ts"],"names":[],"mappings":";;;;AA4CA,IAAM,gBAAgB,EAAE,EAAA,EAAI,SAAS,IAAA,EAAM,OAAA,EAAS,OAAO,SAAA,EAAU;AAO9D,SAAS,oBAAA,CACd,MACA,OAAA,EACQ;AACR,EAAA,MAAM,EAAE,SAAQ,GAAI,OAAA;AACpB,EAAA,MAAM,KAAA,GAAQ,EAAE,GAAG,aAAA,EAAe,GAAI,OAAA,CAAQ,KAAA,IAAS,EAAC,EAAG;AAC3D,EAAA,MAAM,YAA+B,EAAC;AAEtC,EAAA,MAAM,MAAA,GAAS,CAAC,OAAA,EAAiB,OAAA,MAAmC;AAAA,IAClE,IAAA,EAAM,OAAA;AAAA,IACN,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,WAAW,OAAA,GAAU,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,GAAK,OAAA;AAAA,IAC/C,OAAO,OAAA,GAAU,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,GAAK;AAAA,GAC7C,CAAA;AAEA,EAAA,MAAM,GAAA,GAAM,CACV,IAAA,EACA,WAAA,EACA,YACA,QAAA,EACA,OAAA,EACA,YACA,aAAA,KACG;AACH,IAAA,MAAM,OAAA,GAAU,OAAO,IAAA,KAAqB;AAC1C,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,QAAQ,IAAI,CAAA;AAAA,MAC3B,SAAS,CAAA,EAAG;AACV,QAAA,OAAO,YAAY,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MAC/D;AAAA,IACF,CAAA;AACA,IAAA,MAAM,KAAA,GAAQ,UAAA,GACV,oBAAA,CAAqB,OAAA,EAAS;AAAA,MAC5B,QAAA,EAAU,IAAA;AAAA,MACV,KAAA;AAAA,MACA,IAAA,EAAM,OAAA;AAAA,MACN,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,aAAA,EAAe,CAAC,EAAE,IAAA,EAAM,MAAA,EAAO,KAC7B,aAAA,GAAgB,IAAA,EAAM,MAAM,CAAA,IAAK,MAAA,CAAO,UAAA,CAAW,IAAI,CAAC;AAAA,KAC3D,CAAA,GACD,OAAA;AACJ,IAAA,SAAA,CAAU,IAAA;AAAA,MACR,IAAA,CAAK,YAAA;AAAA,QACH;AAAA,UACE,IAAA;AAAA,UACA,WAAA;AAAA,UACA,aAAa,EAAE,IAAA,EAAM,UAAU,UAAA,EAA+B,QAAA,EAAU,sBAAsB,KAAA;AAAM,SACtG;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF,CAAA;AAEA,EAAA,SAAS,aAAA,GAAwB;AAC/B,IAAA,OAAO,OAAA,CAAQ,aAAY,CAAE,aAAA;AAAA,EAC/B;AACA,EAAA,SAAS,WAAW,IAAA,EAA0B;AAC5C,IAAA,OAAO,OAAO,IAAA,CAAK,KAAA,KAAU,QAAA,GAAW,IAAA,CAAK,QAAQ,aAAA,EAAc;AAAA,EACrE;AACA,EAAA,SAAS,QAAA,CAAS,UAAwB,OAAA,EAAwC;AAChF,IAAA,OAAO,SAAS,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,OAAO,CAAA;AAAA,EACrD;AAIA,EAAA,GAAA;AAAA,IACE,gBAAA;AAAA,IACA,sHAAA;AAAA,IACA,EAAC;AAAA,IACD,EAAC;AAAA,IACD,MAAM;AACJ,MAAA,MAAM,EAAA,GAAK,QAAQ,WAAA,EAAY;AAC/B,MAAA,MAAM,OAAA,GAAU;AAAA,QACd,eAAe,EAAA,CAAG,aAAA;AAAA,QAClB,MAAA,EAAQ,EAAA,CAAG,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,UAC5B,IAAI,CAAA,CAAE,EAAA;AAAA,UACN,MAAM,CAAA,CAAE,IAAA;AAAA,UACR,SAAA,EAAW,MAAA,CAAO,IAAA,CAAK,CAAA,CAAE,KAAK,CAAA,CAAE,MAAA;AAAA,UAChC,WAAA,EAAa,MAAA,CAAO,IAAA,CAAK,CAAA,CAAE,YAAY,CAAA,CAAE,MAAA;AAAA,UACzC,YAAY,CAAA,CAAE,UAAA;AAAA,UACd,YAAY,CAAA,CAAE;AAAA,SAChB,CAAE;AAAA,OACJ;AACA,MAAA,MAAM,IAAA,GAAO,CAAA,QAAA,EAAW,OAAA,CAAQ,aAAa;AAAA,CAAA,GAAO,QAAQ,MAAA,CACzD,GAAA,CAAI,CAAC,CAAA,KAAM,GAAG,CAAA,CAAE,EAAE,CAAA,EAAA,EAAK,CAAA,CAAE,IAAI,CAAA,SAAA,EAAO,CAAA,CAAE,SAAS,CAAA,MAAA,CAAQ,CAAA,CACvD,KAAK,IAAI,CAAA;AACZ,MAAA,OAAO,UAAA,CAAW,MAAM,OAAO,CAAA;AAAA,IACjC,CAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,GAAA;AAAA,IACE,gBAAA;AAAA,IACA,4CAAA;AAAA,IACA;AAAA,MACE,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA,EAAiC;AAAA,MACvE,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,+BAAA;AAAkC,KAC5E;AAAA,IACA,CAAC,SAAS,CAAA;AAAA,IACV,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,OAAA,GAAU,WAAW,IAAI,CAAA;AAC/B,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AACnC,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,OAAA,CAAQ,WAAA,IAAe,OAAO,CAAA;AACrD,MAAA,IAAI,CAAC,KAAA,EAAO,OAAO,WAAA,CAAY,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AACpD,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA;AAChC,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,OAAO,UAAA,CAAW,WAAW,EAAE,KAAA,EAAO,SAAS,OAAA,EAAS,KAAA,EAAO,MAAM,CAAA;AAAA,MACvE;AACA,MAAA,OAAO,WAAW,CAAA,EAAG,OAAO,MAAM,IAAA,CAAK,SAAA,CAAU,KAAK,aAAA,IAAiB,IAAA,CAAK,KAAK,CAAC,IAAI,EAAE,GAAG,MAAM,KAAA,EAAO,OAAA,EAAS,SAAS,CAAA;AAAA,IAC5H,CAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,GAAA;AAAA,IACE,iBAAA;AAAA,IACA,mDAAA;AAAA,IACA;AAAA,MACE,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACxB,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,sBAAA,EAAuB;AAAA,MAC7D,GAAA,EAAK,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,0BAAA;AAA2B,KACjE;AAAA,IACA,CAAC,SAAS,KAAK,CAAA;AAAA,IACf,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,OAAA,GAAU,WAAW,IAAI,CAAA;AAC/B,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,OAAA,CAAQ,WAAA,IAAe,OAAO,CAAA;AACrD,MAAA,IAAI,CAAC,KAAA,EAAO,OAAO,WAAA,CAAY,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AACpD,MAAA,MAAM,IAAA,GAAO,SAAA,CAAU,KAAA,EAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,GAAG,CAAC,CAAA;AAClE,MAAA,OAAO,WAAW,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG,EAAE,KAAA,EAAO,OAAA,EAAS,KAAA,EAAO,IAAA,CAAK,OAAO,GAAA,EAAK,IAAA,CAAK,GAAA,EAAK,MAAA,EAAQ,MAAM,CAAA;AAAA,IAC5G,CAAA;AAAA,IACA;AAAA,GACF;AAIA,EAAA,GAAA;AAAA,IACE,gBAAA;AAAA,IACA,+EAAA;AAAA,IACA;AAAA,MACE,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACxB,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MAC1B,KAAA,EAAO,EAAE,WAAA,EAAa,qFAAA;AAAsF,KAC9G;AAAA,IACA,CAAC,WAAW,OAAO,CAAA;AAAA,IACnB,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,OAAA,GAAU,WAAW,IAAI,CAAA;AAC/B,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AACnC,MAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AACnB,MAAA,MAAM,EAAA,GAAK,QAAQ,WAAA,EAAY;AAC/B,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,EAAA,EAAI,OAAO,CAAA;AAClC,MAAA,IAAI,CAAC,KAAA,EAAO,OAAO,WAAA,CAAY,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AACpD,MAAA,MAAM,IAAA,GAAO,UAAA,CAAW,EAAA,EAAI,OAAA,EAAS,EAAE,CAAC,OAAO,GAAG,MAAA,CAAO,OAAA,EAAS,KAAK,CAAA,EAAG,CAAA;AAC1E,MAAA,OAAA,CAAQ,YAAY,IAAI,CAAA;AACxB,MAAA,OAAO,WAAW,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,OAAO,WAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,IAAI,EAAE,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,OAAO,CAAA;AAAA,IAC1G,CAAA;AAAA,IACA,IAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,UAAA,CAAW,IAAI,GAAG,MAAA,CAAO,IAAA,CAAK,OAAA,IAAW,EAAE,CAAC;AAAA,GAC/D;AAEA,EAAA,GAAA;AAAA,IACE,iBAAA;AAAA,IACA,2FAAA;AAAA,IACA;AAAA,MACE,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACxB,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA;AAAS,KAC1B;AAAA,IACA,CAAC,OAAO,CAAA;AAAA,IACR,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,OAAA,GAAU,WAAW,IAAI,CAAA;AAC/B,MAAA,MAAM,EAAA,GAAK,QAAQ,WAAA,EAAY;AAC/B,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,EAAA,EAAI,OAAO,CAAA;AAClC,MAAA,IAAI,CAAC,KAAA,EAAO,OAAO,WAAA,CAAY,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AACpD,MAAA,MAAM,KAAA,GAAS,KAAK,KAAA,IAAS,OAAO,KAAK,KAAA,KAAU,QAAA,GAAY,IAAA,CAAK,KAAA,GAAqC,EAAC;AAC1G,MAAA,MAAM,UAAoC,EAAC;AAC3C,MAAA,KAAA,MAAW,CAAC,IAAA,EAAM,CAAC,CAAA,IAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,GAAI,MAAA,CAAO,MAAM,CAAC,CAAA;AAC7E,MAAA,MAAM,IAAA,GAAO,UAAA,CAAW,EAAA,EAAI,OAAA,EAAS,OAAO,CAAA;AAC5C,MAAA,OAAA,CAAQ,YAAY,IAAI,CAAA;AACxB,MAAA,OAAO,WAAW,CAAA,IAAA,EAAO,MAAA,CAAO,KAAK,KAAK,CAAA,CAAE,MAAM,CAAA,UAAA,EAAa,OAAO,IAAI,EAAE,KAAA,EAAO,SAAS,KAAA,EAAO,MAAA,CAAO,KAAK,KAAK,CAAA,CAAE,QAAQ,CAAA;AAAA,IAChI,CAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,GAAA;AAAA,IACE,iBAAA;AAAA,IACA,wCAAA;AAAA,IACA,EAAE,EAAA,EAAI,EAAE,IAAA,EAAM,QAAA,IAAY,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAS,EAAE;AAAA,IACnD,CAAC,MAAM,MAAM,CAAA;AAAA,IACb,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,EAAA,GAAK,QAAQ,WAAA,EAAY;AAC/B,MAAA,MAAM,EAAA,GAAK,MAAA,CAAO,IAAA,CAAK,EAAE,CAAA;AACzB,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAC7B,MAAA,IAAI,EAAA,CAAG,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,EAAG,OAAO,WAAA,CAAY,CAAA,MAAA,EAAS,EAAE,CAAA,eAAA,CAAiB,CAAA;AACvF,MAAA,MAAM,IAAA,GAAqB;AAAA,QACzB,GAAG,EAAA;AAAA,QACH,MAAA,EAAQ;AAAA,UACN,GAAG,EAAA,CAAG,MAAA;AAAA,UACN;AAAA,YACE,EAAA;AAAA,YAAI,IAAA;AAAA,YAAM,OAAO,EAAC;AAAA,YAAG,cAAc,EAAC;AAAA,YAAG,eAAe,EAAC;AAAA,YACvD,eAAe,EAAC;AAAA,YAAG,UAAA,EAAY,CAAA;AAAA,YAAG,UAAA,EAAY;AAAA;AAChD;AACF,OACF;AACA,MAAA,OAAA,CAAQ,YAAY,IAAI,CAAA;AACxB,MAAA,OAAO,UAAA,CAAW,eAAe,EAAE,CAAA,GAAA,EAAM,IAAI,CAAA,EAAA,CAAA,EAAM,EAAE,EAAA,EAAI,IAAA,EAAM,CAAA;AAAA,IACjE,CAAA;AAAA,IACA,IAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,OAAO,IAAA,CAAK,EAAA,IAAM,EAAE,CAAC;AAAA,GACxC;AAEA,EAAA,GAAA;AAAA,IACE,kBAAA;AAAA,IACA,kCAAA;AAAA,IACA,EAAE,KAAA,EAAO,EAAE,IAAA,EAAM,UAAS,EAAE;AAAA,IAC5B,CAAC,OAAO,CAAA;AAAA,IACR,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AACjC,MAAA,MAAM,EAAA,GAAK,QAAQ,WAAA,EAAY;AAC/B,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI,OAAO,GAAG,OAAO,WAAA,CAAY,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AACpE,MAAA,OAAA,CAAQ,YAAY,EAAE,GAAG,EAAA,EAAI,aAAA,EAAe,SAAS,CAAA;AACrD,MAAA,OAAO,WAAW,CAAA,oBAAA,EAAkB,OAAO,IAAI,EAAE,KAAA,EAAO,SAAS,CAAA;AAAA,IACnE,CAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,GAAA;AAAA,IACE,uBAAA;AAAA,IACA,sEAAA;AAAA,IACA,EAAE,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,IAAY,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAS,EAAE;AAAA,IACzD,CAAC,SAAS,CAAA;AAAA,IACV,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,CAAC,OAAA,CAAQ,aAAA,EAAe,OAAO,YAAY,qCAAqC,CAAA;AACpF,MAAA,MAAM,OAAA,GAAU,WAAW,IAAI,CAAA;AAC/B,MAAA,OAAA,CAAQ,aAAA,CAAc,OAAA,EAAS,MAAA,CAAO,IAAA,CAAK,OAAO,CAAC,CAAA;AACnD,MAAA,OAAO,UAAA,CAAW,CAAA,mBAAA,EAAiB,OAAO,CAAA,CAAA,EAAI,IAAA,CAAK,OAAO,CAAA,CAAA,EAAI,EAAE,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,IAAA,CAAK,SAAS,CAAA;AAAA,IACzG,CAAA;AAAA,IACA,IAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,UAAA,CAAW,IAAI,GAAG,MAAA,CAAO,IAAA,CAAK,OAAA,IAAW,EAAE,CAAC;AAAA,GAC/D;AAEA,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,QAAA;AAAA,IACJ,KAAA,EAAO,QAAA;AAAA,IACP,SAAS,MAAM;AACb,MAAA,KAAA,MAAW,CAAA,IAAK,WAAW,CAAA,EAAE;AAAA,IAC/B;AAAA,GACF;AACF;AAIA,SAAS,MAAA,CAAO,SAAiB,KAAA,EAA4B;AAC3D,EAAA,OAAO,EAAE,SAAS,KAAA,EAAM;AAC1B;AAEA,SAAS,UAAA,CAAW,EAAA,EAAkB,OAAA,EAAiB,OAAA,EAAiD;AACtG,EAAA,OAAO;AAAA,IACL,GAAG,EAAA;AAAA,IACH,MAAA,EAAQ,GAAG,MAAA,CAAO,GAAA;AAAA,MAAI,CAAC,CAAA,KACrB,CAAA,CAAE,EAAA,KAAO,OAAA,GAAU,IAAI,EAAE,GAAG,CAAA,EAAG,KAAA,EAAO,EAAE,GAAG,CAAA,CAAE,KAAA,EAAO,GAAG,SAAQ;AAAE;AACnE,GACF;AACF;AAGA,SAAS,aAAa,IAAA,EAA4C;AAChE,EAAA,MAAM,CAAA,GAAI,oBAAA,CAAqB,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA;AAC/C,EAAA,IAAI,CAAC,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,CAAA,aAAA,EAAgB,IAAI,CAAA,CAAE,CAAA;AAC9C,EAAA,MAAM,OAAA,GAAU,CAAA,CAAE,CAAC,CAAA,CAAE,WAAA,EAAY;AACjC,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,QAAQ,CAAA,EAAA,EAAK;AACvC,IAAA,GAAA,GAAM,GAAA,GAAM,EAAA,IAAM,OAAA,CAAQ,UAAA,CAAW,CAAC,CAAA,GAAI,EAAA,CAAA;AAAA,EAC5C;AACA,EAAA,OAAO,EAAE,GAAA,EAAK,GAAA,GAAM,CAAA,EAAG,GAAA,EAAK,QAAA,CAAS,CAAA,CAAE,CAAC,CAAA,EAAG,EAAE,CAAA,GAAI,CAAA,EAAE;AACrD;AAEA,SAAS,YAAY,GAAA,EAAqB;AACxC,EAAA,IAAI,CAAA,GAAI,EAAA;AACR,EAAA,IAAI,IAAI,GAAA,GAAM,CAAA;AACd,EAAA,OAAO,IAAI,CAAA,EAAG;AACZ,IAAA,MAAM,CAAA,GAAA,CAAK,IAAI,CAAA,IAAK,EAAA;AACpB,IAAA,CAAA,GAAI,MAAA,CAAO,YAAA,CAAa,EAAA,GAAK,CAAC,CAAA,GAAI,CAAA;AAClC,IAAA,CAAA,GAAI,IAAA,CAAK,KAAA,CAAA,CAAO,CAAA,GAAI,CAAA,IAAK,EAAE,CAAA;AAAA,EAC7B;AACA,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,SAAA,CAAU,KAAA,EAAkB,SAAA,EAAmB,OAAA,EAAgC;AACtF,EAAA,MAAM,KAAA,GAAQ,aAAa,SAAS,CAAA;AACpC,EAAA,MAAM,GAAA,GAAM,aAAa,OAAO,CAAA;AAChC,EAAA,MAAM,KAAK,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,GAAA,EAAK,IAAI,GAAG,CAAA;AACtC,EAAA,MAAM,KAAK,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,GAAA,EAAK,IAAI,GAAG,CAAA;AACtC,EAAA,MAAM,KAAK,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,GAAA,EAAK,IAAI,GAAG,CAAA;AACtC,EAAA,MAAM,KAAK,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,GAAA,EAAK,IAAI,GAAG,CAAA;AACtC,EAAA,MAAM,OAAsB,EAAC;AAC7B,EAAA,KAAA,IAAS,CAAA,GAAI,EAAA,EAAI,CAAA,IAAK,EAAA,EAAI,CAAA,EAAA,EAAK;AAC7B,IAAA,MAAM,MAAmB,EAAC;AAC1B,IAAA,KAAA,IAAS,CAAA,GAAI,EAAA,EAAI,CAAA,IAAK,EAAA,EAAI,CAAA,EAAA,EAAK;AAC7B,MAAA,MAAM,OAAO,CAAA,EAAG,WAAA,CAAY,CAAC,CAAC,CAAA,EAAG,IAAI,CAAC,CAAA,CAAA;AACtC,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AAC7B,MAAA,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM,aAAA,IAAiB,IAAA,EAAM,SAAS,IAAI,CAAA;AAAA,IACrD;AACA,IAAA,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,EACf;AACA,EAAA,OAAO,IAAA;AACT","file":"chunk-IANI25IT.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport type { AgentTarget } from \"../presence/types\";\n\n/**\n * Loose types — kept here so the bridge builds without a hard dep on\n * @particle-academy/fancy-sheets. They mirror the public surface of\n * `WorkbookData` / `SheetData` / `CellData` from that package.\n */\ntype CellValue = string | number | boolean | null;\ntype CellData = { address: string; value: CellValue; format?: unknown; comment?: unknown; computedValue?: CellValue };\ntype SheetData = {\n id: string;\n name: string;\n cells: Record<string, CellData>;\n columnWidths: Record<number, number>;\n mergedRegions: Array<{ start: string; end: string }>;\n columnFilters: Record<number, string>;\n sortColumn?: number;\n sortDirection?: \"asc\" | \"desc\";\n frozenRows: number;\n frozenCols: number;\n};\ntype WorkbookData = { sheets: SheetData[]; activeSheetId: string };\n\nexport type SheetsBridgeAdapter = {\n /** fancy-screens screen id (optional) so activity events know which screen the sheet lives in. */\n screenId?: string;\n /** Read the current workbook. */\n getWorkbook: () => WorkbookData;\n /** Replace the workbook. Host wires this to its onChange. */\n setWorkbook: (next: WorkbookData) => void;\n /** Optional: programmatically change the active cell. */\n setActiveCell?: (sheetId: string, address: string) => void;\n};\n\nexport type SheetsBridgeOptions = {\n adapter: SheetsBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * registerSheetsBridge — schema-aware MCP access to a fancy-sheets workbook.\n * Tools are sheet-aware (every mutator takes an explicit `sheet` id, defaulting\n * to the active sheet when omitted) so an agent can author multi-sheet docs.\n */\nexport function registerSheetsBridge(\n host: ToolHost,\n options: SheetsBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const disposers: Array<() => void> = [];\n\n const target = (sheetId: string, address?: string): AgentTarget => ({\n kind: \"sheet\",\n screenId: adapter.screenId,\n elementId: address ? `${sheetId}!${address}` : sheetId,\n label: address ? `${sheetId}!${address}` : sheetId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n isMutation: boolean,\n resolveTarget?: (args: JsonObject, result: any) => AgentTarget | null,\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = isMutation\n ? wrapToolWithActivity(wrapped, {\n toolName: name,\n agent,\n kind: \"sheet\",\n screenId: adapter.screenId,\n resolveTarget: ({ args, result }) =>\n resolveTarget?.(args, result) ?? target(getSheetId(args)),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false },\n },\n final as any,\n ),\n );\n };\n\n function activeSheetId(): string {\n return adapter.getWorkbook().activeSheetId;\n }\n function getSheetId(args: JsonObject): string {\n return typeof args.sheet === \"string\" ? args.sheet : activeSheetId();\n }\n function getSheet(workbook: WorkbookData, sheetId: string): SheetData | undefined {\n return workbook.sheets.find((s) => s.id === sheetId);\n }\n\n // ───────────── Read tools ─────────────\n\n reg(\n \"sheet_describe\",\n \"Describe the workbook: every sheet's id, name, dimensions, cell count, active sheet. Call before reading or writing.\",\n {},\n [],\n () => {\n const wb = adapter.getWorkbook();\n const summary = {\n activeSheetId: wb.activeSheetId,\n sheets: wb.sheets.map((s) => ({\n id: s.id,\n name: s.name,\n cellCount: Object.keys(s.cells).length,\n columnCount: Object.keys(s.columnWidths).length,\n frozenRows: s.frozenRows,\n frozenCols: s.frozenCols,\n })),\n };\n const text = `Active: ${summary.activeSheetId}\\n` + summary.sheets\n .map((s) => `${s.id} \"${s.name}\" — ${s.cellCount} cells`)\n .join(\"\\n\");\n return textResult(text, summary);\n },\n false,\n );\n\n reg(\n \"sheet_get_cell\",\n \"Read a single cell's raw + computed value.\",\n {\n sheet: { type: \"string\", description: \"Sheet id (defaults to active).\" },\n address: { type: \"string\", description: \"A1-style address, e.g. \\\"B12\\\".\" },\n },\n [\"address\"],\n (args) => {\n const sheetId = getSheetId(args);\n const address = String(args.address);\n const sheet = getSheet(adapter.getWorkbook(), sheetId);\n if (!sheet) return errorResult(`No sheet ${sheetId}`);\n const cell = sheet.cells[address];\n if (!cell) {\n return textResult(`(empty)`, { sheet: sheetId, address, value: null });\n }\n return textResult(`${address} = ${JSON.stringify(cell.computedValue ?? cell.value)}`, { ...cell, sheet: sheetId, address });\n },\n false,\n );\n\n reg(\n \"sheet_get_range\",\n \"Read a rectangular range as a 2D array of values.\",\n {\n sheet: { type: \"string\" },\n start: { type: \"string\", description: \"Top-left A1 address.\" },\n end: { type: \"string\", description: \"Bottom-right A1 address.\" },\n },\n [\"start\", \"end\"],\n (args) => {\n const sheetId = getSheetId(args);\n const sheet = getSheet(adapter.getWorkbook(), sheetId);\n if (!sheet) return errorResult(`No sheet ${sheetId}`);\n const grid = readRange(sheet, String(args.start), String(args.end));\n return textResult(JSON.stringify(grid), { sheet: sheetId, start: args.start, end: args.end, values: grid });\n },\n false,\n );\n\n // ───────────── Mutation tools ─────────────\n\n reg(\n \"sheet_set_cell\",\n \"Set a single cell's value. To set a formula, pass a string starting with '='.\",\n {\n sheet: { type: \"string\" },\n address: { type: \"string\" },\n value: { description: \"string | number | boolean | null. Strings starting with '=' are stored as formulas.\" },\n },\n [\"address\", \"value\"],\n (args) => {\n const sheetId = getSheetId(args);\n const address = String(args.address);\n const value = args.value as CellValue;\n const wb = adapter.getWorkbook();\n const sheet = getSheet(wb, sheetId);\n if (!sheet) return errorResult(`No sheet ${sheetId}`);\n const next = mergeCells(wb, sheetId, { [address]: cellOf(address, value) });\n adapter.setWorkbook(next);\n return textResult(`${sheetId}!${address} ← ${JSON.stringify(value)}`, { sheet: sheetId, address, value });\n },\n true,\n (args) => target(getSheetId(args), String(args.address ?? \"\")),\n );\n\n reg(\n \"sheet_set_range\",\n \"Set many cells atomically. `cells` is an object map of { \\\"A1\\\": value, \\\"B2\\\": value, ... }.\",\n {\n sheet: { type: \"string\" },\n cells: { type: \"object\" },\n },\n [\"cells\"],\n (args) => {\n const sheetId = getSheetId(args);\n const wb = adapter.getWorkbook();\n const sheet = getSheet(wb, sheetId);\n if (!sheet) return errorResult(`No sheet ${sheetId}`);\n const cells = (args.cells && typeof args.cells === \"object\") ? args.cells as Record<string, CellValue> : {};\n const updates: Record<string, CellData> = {};\n for (const [addr, v] of Object.entries(cells)) updates[addr] = cellOf(addr, v);\n const next = mergeCells(wb, sheetId, updates);\n adapter.setWorkbook(next);\n return textResult(`Set ${Object.keys(cells).length} cells in ${sheetId}`, { sheet: sheetId, count: Object.keys(cells).length });\n },\n true,\n );\n\n reg(\n \"sheet_add_sheet\",\n \"Add a new sheet (tab) to the workbook.\",\n { id: { type: \"string\" }, name: { type: \"string\" } },\n [\"id\", \"name\"],\n (args) => {\n const wb = adapter.getWorkbook();\n const id = String(args.id);\n const name = String(args.name);\n if (wb.sheets.find((s) => s.id === id)) return errorResult(`Sheet ${id} already exists`);\n const next: WorkbookData = {\n ...wb,\n sheets: [\n ...wb.sheets,\n {\n id, name, cells: {}, columnWidths: {}, mergedRegions: [],\n columnFilters: {}, frozenRows: 0, frozenCols: 0,\n },\n ],\n };\n adapter.setWorkbook(next);\n return textResult(`Added sheet ${id} (\"${name}\")`, { id, name });\n },\n true,\n (args) => target(String(args.id ?? \"\")),\n );\n\n reg(\n \"sheet_set_active\",\n \"Switch to a different sheet tab.\",\n { sheet: { type: \"string\" } },\n [\"sheet\"],\n (args) => {\n const sheetId = String(args.sheet);\n const wb = adapter.getWorkbook();\n if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n adapter.setWorkbook({ ...wb, activeSheetId: sheetId });\n return textResult(`Active sheet → ${sheetId}`, { sheet: sheetId });\n },\n true,\n );\n\n reg(\n \"sheet_set_active_cell\",\n \"Move the active cell selection (host implements DOM focus + scroll).\",\n { sheet: { type: \"string\" }, address: { type: \"string\" } },\n [\"address\"],\n (args) => {\n if (!adapter.setActiveCell) return errorResult(\"Host did not provide setActiveCell.\");\n const sheetId = getSheetId(args);\n adapter.setActiveCell(sheetId, String(args.address));\n return textResult(`Active cell → ${sheetId}!${args.address}`, { sheet: sheetId, address: args.address });\n },\n true,\n (args) => target(getSheetId(args), String(args.address ?? \"\")),\n );\n\n return {\n id: \"sheets\",\n title: \"Sheets\",\n dispose: () => {\n for (const d of disposers) d();\n },\n };\n}\n\n// ───────────── helpers ─────────────\n\nfunction cellOf(address: string, value: CellValue): CellData {\n return { address, value };\n}\n\nfunction mergeCells(wb: WorkbookData, sheetId: string, updates: Record<string, CellData>): WorkbookData {\n return {\n ...wb,\n sheets: wb.sheets.map((s) =>\n s.id !== sheetId ? s : { ...s, cells: { ...s.cells, ...updates } },\n ),\n };\n}\n\n/** Parse \"B12\" → { col: 1, row: 11 }. Letters are 1-based, rows 1-based. */\nfunction parseAddress(addr: string): { col: number; row: number } {\n const m = /^([A-Za-z]+)(\\d+)$/.exec(addr.trim());\n if (!m) throw new Error(`Bad address: ${addr}`);\n const letters = m[1].toUpperCase();\n let col = 0;\n for (let i = 0; i < letters.length; i++) {\n col = col * 26 + (letters.charCodeAt(i) - 64);\n }\n return { col: col - 1, row: parseInt(m[2], 10) - 1 };\n}\n\nfunction colToLetter(col: number): string {\n let s = \"\";\n let n = col + 1;\n while (n > 0) {\n const r = (n - 1) % 26;\n s = String.fromCharCode(65 + r) + s;\n n = Math.floor((n - 1) / 26);\n }\n return s;\n}\n\nfunction readRange(sheet: SheetData, startAddr: string, endAddr: string): CellValue[][] {\n const start = parseAddress(startAddr);\n const end = parseAddress(endAddr);\n const r0 = Math.min(start.row, end.row);\n const r1 = Math.max(start.row, end.row);\n const c0 = Math.min(start.col, end.col);\n const c1 = Math.max(start.col, end.col);\n const grid: CellValue[][] = [];\n for (let r = r0; r <= r1; r++) {\n const row: CellValue[] = [];\n for (let c = c0; c <= c1; c++) {\n const addr = `${colToLetter(c)}${r + 1}`;\n const cell = sheet.cells[addr];\n row.push(cell?.computedValue ?? cell?.value ?? null);\n }\n grid.push(row);\n }\n return grid;\n}\n"]}
|
|
@@ -149,9 +149,24 @@ function attachSseRelay(server, options) {
|
|
|
149
149
|
transport.bindServer(server);
|
|
150
150
|
server.attach(transport);
|
|
151
151
|
transport.start();
|
|
152
|
+
import('./registry-2DRURS6U.js').then(({ onActivity }) => {
|
|
153
|
+
const off = onActivity((event) => {
|
|
154
|
+
transport.send({
|
|
155
|
+
jsonrpc: "2.0",
|
|
156
|
+
method: "notifications/agent_activity",
|
|
157
|
+
params: event
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
const origClose = transport.close.bind(transport);
|
|
161
|
+
transport.close = () => {
|
|
162
|
+
off();
|
|
163
|
+
origClose();
|
|
164
|
+
};
|
|
165
|
+
}).catch(() => {
|
|
166
|
+
});
|
|
152
167
|
return transport;
|
|
153
168
|
}
|
|
154
169
|
|
|
155
170
|
export { SseRelayTransport, attachSseRelay, buildShareConfig, buildShareUrl, constantTimeEqual, createSessionDescriptor, describeSession, readSessionFromUrl };
|
|
156
|
-
//# sourceMappingURL=chunk-
|
|
157
|
-
//# sourceMappingURL=chunk-
|
|
171
|
+
//# sourceMappingURL=chunk-JMYPUAFH.js.map
|
|
172
|
+
//# sourceMappingURL=chunk-JMYPUAFH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sharing/token.ts","../src/sharing/sse-relay.ts"],"names":[],"mappings":"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","file":"chunk-JMYPUAFH.js","sourcesContent":["/**\n * Session-token utilities. The token is a high-entropy secret; possession\n * grants read/write on the session. We don't HMAC frames — frames carry\n * the token directly (which is fine for in-process / same-origin / TLS\n * transports). For lower-trust transports, host apps can layer signing\n * on top of the BroadcastChannelTransport.\n */\n\nconst TOKEN_BYTES = 24; // 192 bits, base64url-encoded → 32 chars\n\nexport type SessionDescriptor = {\n /** Stable session identifier. Channel name = `fai:share:${id}`. */\n id: string;\n /** Secret token. Treat as a password — anyone with it can read/write. */\n token: string;\n /** Pretty hash for display (first 8 chars of token). */\n display: string;\n};\n\nexport function createSessionDescriptor(): SessionDescriptor {\n const id = randomId(8);\n const token = randomToken();\n return { id, token, display: token.slice(0, 8) };\n}\n\nexport function describeSession(id: string, token: string): SessionDescriptor {\n return { id, token, display: token.slice(0, 8) };\n}\n\n/** Build the shareable URL for the current page (preserves path, adds session+token). */\nexport function buildShareUrl(\n descriptor: SessionDescriptor,\n baseUrl: string = typeof window !== \"undefined\" ? window.location.href.split(\"?\")[0] : \"\",\n): string {\n const u = new URL(baseUrl);\n u.searchParams.set(\"session\", descriptor.id);\n u.searchParams.set(\"token\", descriptor.token);\n return u.toString();\n}\n\n/** Build the JSON config form (suitable for Claude Desktop / Cline / etc.). */\nexport function buildShareConfig(descriptor: SessionDescriptor, transport = \"broadcast-channel\") {\n return {\n name: `whiteboard-${descriptor.id}`,\n transport,\n session: descriptor.id,\n token: descriptor.token,\n channel: `fai:share:${descriptor.id}`,\n protocol_version: \"2025-06-18\",\n };\n}\n\n/** Read session descriptor from current URL, or null if not a shared link. */\nexport function readSessionFromUrl(): SessionDescriptor | null {\n if (typeof window === \"undefined\") return null;\n const params = new URL(window.location.href).searchParams;\n const id = params.get(\"session\");\n const token = params.get(\"token\");\n if (!id || !token) return null;\n return describeSession(id, token);\n}\n\nfunction randomToken(): string {\n const bytes = new Uint8Array(TOKEN_BYTES);\n crypto.getRandomValues(bytes);\n return base64Url(bytes);\n}\n\nfunction randomId(len: number): string {\n const bytes = new Uint8Array(Math.ceil((len * 3) / 4));\n crypto.getRandomValues(bytes);\n return base64Url(bytes).slice(0, len);\n}\n\nfunction base64Url(bytes: Uint8Array): string {\n let s = \"\";\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** Constant-time string compare so a mismatched token leaks no timing info. */\nexport function constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return diff === 0;\n}\n","import type { JsonRpcMessage } from \"../mcp/types\";\nimport type { Transport } from \"../mcp/server\";\nimport type { MicroMcpServer } from \"../mcp/server\";\nimport { constantTimeEqual } from \"./token\";\n\n/**\n * SseRelayTransport — bridges the in-page MicroMcpServer to a host-app\n * relay broker over Server-Sent Events (inbound) + POST (outbound).\n *\n * Wire model:\n * - Browser opens an EventSource at `${baseUrl}/${sessionId}/events?token=…`.\n * Each `event: mcp` carries one JSON-RPC frame from a remote client.\n * - Browser POSTs JSON-RPC frames to `${baseUrl}/${sessionId}/outbox?token=…`\n * when the local server has a response/notification to send.\n *\n * The host provides the relay endpoint (any HTTP server). See the demo\n * `WhiteboardShareController` for the reference implementation.\n *\n * Token authentication is the host's job — this transport just carries the\n * token in the query string. For lower-trust deployments, layer signing on\n * top by wrapping `send` / `deliverFromRemote`.\n */\nexport type SseRelayOptions = {\n baseUrl: string;\n sessionId: string;\n token: string;\n /** Override fetch (testing / non-browser). Defaults to global fetch. */\n fetch?: typeof fetch;\n};\n\nexport class SseRelayTransport implements Transport {\n private server?: MicroMcpServer;\n private es?: EventSource;\n private opts: SseRelayOptions;\n private sendQueue: JsonRpcMessage[] = [];\n private connected = false;\n private listeners = new Set<(state: RelayState) => void>();\n private state: RelayState = \"idle\";\n private expectedToken: string;\n\n constructor(options: SseRelayOptions) {\n this.opts = options;\n this.expectedToken = options.token;\n }\n\n bindServer(server: MicroMcpServer): void {\n this.server = server;\n }\n\n /** Open the SSE channel. Idempotent. */\n start(): void {\n if (this.connected || typeof window === \"undefined\") return;\n const url = `${this.opts.baseUrl}/${encodeURIComponent(this.opts.sessionId)}/events?token=${encodeURIComponent(this.opts.token)}`;\n this.setState(\"connecting\");\n const es = new EventSource(url, { withCredentials: false });\n this.es = es;\n\n es.addEventListener(\"open\", () => {\n this.connected = true;\n this.setState(\"open\");\n // Flush queued outbound frames (tool list_changed notifications, etc.)\n const queued = this.sendQueue.splice(0);\n for (const msg of queued) this.postOut(msg);\n });\n\n es.addEventListener(\"mcp\", (ev: MessageEvent) => {\n const raw = ev.data;\n this.handleInbound(raw);\n });\n\n es.addEventListener(\"error\", () => {\n this.setState(\"error\");\n // EventSource auto-reconnects; no need to dispose.\n });\n }\n\n send(message: JsonRpcMessage): void {\n if (!this.connected) {\n this.sendQueue.push(message);\n return;\n }\n this.postOut(message);\n }\n\n close(): void {\n this.es?.close();\n this.es = undefined;\n this.connected = false;\n this.setState(\"closed\");\n }\n\n onStateChange(listener: (state: RelayState) => void): () => void {\n this.listeners.add(listener);\n listener(this.state);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * For relays that wrap each frame with auth metadata: hosts can call this\n * directly when a frame arrives via a non-SSE path. The transport will\n * dispatch it to the bound server.\n */\n async deliverFromRemote(payload: JsonRpcMessage | string, token?: string): Promise<void> {\n if (token !== undefined && !constantTimeEqual(token, this.expectedToken)) return;\n if (!this.server) throw new Error(\"SseRelayTransport has no bound server\");\n const message: JsonRpcMessage = typeof payload === \"string\" ? JSON.parse(payload) : payload;\n await this.server.receive(this, message);\n }\n\n private async postOut(message: JsonRpcMessage): Promise<void> {\n const url = `${this.opts.baseUrl}/${encodeURIComponent(this.opts.sessionId)}/outbox?token=${encodeURIComponent(this.opts.token)}`;\n const f = this.opts.fetch ?? fetch;\n try {\n await f(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"accept\": \"application/json\" },\n body: JSON.stringify(message),\n });\n } catch {\n // Drop — relay errors are surfaced via state change separately.\n }\n }\n\n private async handleInbound(raw: string): Promise<void> {\n if (!this.server) return;\n let message: JsonRpcMessage;\n try {\n message = JSON.parse(raw);\n } catch {\n return;\n }\n await this.server.receive(this, message);\n }\n\n private setState(state: RelayState): void {\n this.state = state;\n for (const l of this.listeners) l(state);\n }\n}\n\nexport type RelayState = \"idle\" | \"connecting\" | \"open\" | \"closed\" | \"error\";\n\nexport function attachSseRelay(server: MicroMcpServer, options: SseRelayOptions): SseRelayTransport {\n const transport = new SseRelayTransport(options);\n transport.bindServer(server);\n server.attach(transport);\n transport.start();\n\n // Forward in-process agent activity events out over the relay so external\n // subscribers can render presence indicators in real time. Uses a dynamic\n // import so the relay doesn't hard-depend on the presence module if it's\n // tree-shaken out.\n import(\"../presence/registry\").then(({ onActivity }) => {\n const off = onActivity((event) => {\n transport.send({\n jsonrpc: \"2.0\",\n method: \"notifications/agent_activity\",\n params: event as any,\n });\n });\n // Tear down the subscription when the transport closes.\n const origClose = transport.close.bind(transport);\n transport.close = () => {\n off();\n origClose();\n };\n }).catch(() => {\n // Presence module unavailable — silently no-op (relay still works).\n });\n\n return transport;\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/presence/registry.ts
|
|
2
|
+
var HISTORY_CAP = 200;
|
|
3
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
4
|
+
var history = [];
|
|
5
|
+
function emitActivity(event) {
|
|
6
|
+
history.push(event);
|
|
7
|
+
if (history.length > HISTORY_CAP) history.splice(0, history.length - HISTORY_CAP);
|
|
8
|
+
for (const l of listeners) l(event);
|
|
9
|
+
}
|
|
10
|
+
function onActivity(listener, filter) {
|
|
11
|
+
const wrapped = filter ? (e) => {
|
|
12
|
+
if (matches(e, filter)) listener(e);
|
|
13
|
+
} : listener;
|
|
14
|
+
listeners.add(wrapped);
|
|
15
|
+
return () => listeners.delete(wrapped);
|
|
16
|
+
}
|
|
17
|
+
function readActivityHistory(filter) {
|
|
18
|
+
if (!filter) return history.slice();
|
|
19
|
+
return history.filter((e) => matches(e, filter));
|
|
20
|
+
}
|
|
21
|
+
function resetActivityRegistry() {
|
|
22
|
+
listeners.clear();
|
|
23
|
+
history.length = 0;
|
|
24
|
+
}
|
|
25
|
+
function matches(e, f) {
|
|
26
|
+
if (f.agentId !== void 0 && e.agentId !== f.agentId) return false;
|
|
27
|
+
if (f.screenId !== void 0 && e.target.screenId !== f.screenId) return false;
|
|
28
|
+
if (f.kind !== void 0 && e.target.kind !== f.kind) return false;
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { emitActivity, onActivity, readActivityHistory, resetActivityRegistry };
|
|
33
|
+
//# sourceMappingURL=chunk-JU2N4KK6.js.map
|
|
34
|
+
//# sourceMappingURL=chunk-JU2N4KK6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/presence/registry.ts"],"names":[],"mappings":";AAYA,IAAM,WAAA,GAAc,GAAA;AAEpB,IAAM,SAAA,uBAAgB,GAAA,EAA2B;AACjD,IAAM,UAAgC,EAAC;AAGhC,SAAS,aAAa,KAAA,EAAiC;AAC5D,EAAA,OAAA,CAAQ,KAAK,KAAK,CAAA;AAClB,EAAA,IAAI,OAAA,CAAQ,SAAS,WAAA,EAAa,OAAA,CAAQ,OAAO,CAAA,EAAG,OAAA,CAAQ,SAAS,WAAW,CAAA;AAChF,EAAA,KAAA,MAAW,CAAA,IAAK,SAAA,EAAW,CAAA,CAAE,KAAK,CAAA;AACpC;AAOO,SAAS,UAAA,CAAW,UAAiC,MAAA,EAAqC;AAC/F,EAAA,MAAM,OAAA,GAAiC,MAAA,GACnC,CAAC,CAAA,KAAM;AAAE,IAAA,IAAI,OAAA,CAAQ,CAAA,EAAG,MAAM,CAAA,WAAY,CAAC,CAAA;AAAA,EAAG,CAAA,GAC9C,QAAA;AACJ,EAAA,SAAA,CAAU,IAAI,OAAO,CAAA;AACrB,EAAA,OAAO,MAAM,SAAA,CAAU,MAAA,CAAO,OAAO,CAAA;AACvC;AAGO,SAAS,oBAAoB,MAAA,EAA+C;AACjF,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,OAAA,CAAQ,KAAA,EAAM;AAClC,EAAA,OAAO,QAAQ,MAAA,CAAO,CAAC,MAAM,OAAA,CAAQ,CAAA,EAAG,MAAM,CAAC,CAAA;AACjD;AAGO,SAAS,qBAAA,GAA8B;AAC5C,EAAA,SAAA,CAAU,KAAA,EAAM;AAChB,EAAA,OAAA,CAAQ,MAAA,GAAS,CAAA;AACnB;AAEA,SAAS,OAAA,CAAQ,GAAuB,CAAA,EAA4B;AAClE,EAAA,IAAI,EAAE,OAAA,KAAY,MAAA,IAAa,EAAE,OAAA,KAAY,CAAA,CAAE,SAAS,OAAO,KAAA;AAC/D,EAAA,IAAI,CAAA,CAAE,aAAa,MAAA,IAAa,CAAA,CAAE,OAAO,QAAA,KAAa,CAAA,CAAE,UAAU,OAAO,KAAA;AACzE,EAAA,IAAI,CAAA,CAAE,SAAS,MAAA,IAAa,CAAA,CAAE,OAAO,IAAA,KAAS,CAAA,CAAE,MAAM,OAAO,KAAA;AAC7D,EAAA,OAAO,IAAA;AACT","file":"chunk-JU2N4KK6.js","sourcesContent":["import type { ActivityFilter, AgentActivityEvent, AgentActivityListener } from \"./types\";\n\n/**\n * In-process registry of agent activity events. Bridges call `emitActivity`\n * after a tool runs; React hooks + the SSE relay subscribe via\n * `onActivity()`.\n *\n * Holds a short scrollback of recent events (default 200) so newly-mounted\n * subscribers can render the recent past — useful for activity-log UIs\n * that rejoin a session mid-stream.\n */\n\nconst HISTORY_CAP = 200;\n\nconst listeners = new Set<AgentActivityListener>();\nconst history: AgentActivityEvent[] = [];\n\n/** Emit an activity event. All current listeners receive it synchronously. */\nexport function emitActivity(event: AgentActivityEvent): void {\n history.push(event);\n if (history.length > HISTORY_CAP) history.splice(0, history.length - HISTORY_CAP);\n for (const l of listeners) l(event);\n}\n\n/**\n * Subscribe to all events (or a filtered subset). Returns an unsubscribe\n * function. Filter checks all provided keys with strict equality; omit a\n * key to ignore it.\n */\nexport function onActivity(listener: AgentActivityListener, filter?: ActivityFilter): () => void {\n const wrapped: AgentActivityListener = filter\n ? (e) => { if (matches(e, filter)) listener(e); }\n : listener;\n listeners.add(wrapped);\n return () => listeners.delete(wrapped);\n}\n\n/** Read the recent history (newest last). Optional filter. */\nexport function readActivityHistory(filter?: ActivityFilter): AgentActivityEvent[] {\n if (!filter) return history.slice();\n return history.filter((e) => matches(e, filter));\n}\n\n/** Wipe history + clear listeners. Test/teardown helper. */\nexport function resetActivityRegistry(): void {\n listeners.clear();\n history.length = 0;\n}\n\nfunction matches(e: AgentActivityEvent, f: ActivityFilter): boolean {\n if (f.agentId !== undefined && e.agentId !== f.agentId) return false;\n if (f.screenId !== undefined && e.target.screenId !== f.screenId) return false;\n if (f.kind !== undefined && e.target.kind !== f.kind) return false;\n return true;\n}\n"]}
|
|
@@ -1,27 +1,41 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { wrapToolWithActivity } from './chunk-52S7XYZK.js';
|
|
2
|
+
import { errorResult, textResult } from './chunk-4KAIV6OD.js';
|
|
2
3
|
|
|
4
|
+
// src/bridges/flow.ts
|
|
5
|
+
var DEFAULT_AGENT = { id: "agent", name: "Agent", color: "#a855f7" };
|
|
3
6
|
var num = (v, fallback) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
4
7
|
var str = (v, fallback = "") => typeof v === "string" ? v : fallback;
|
|
5
8
|
var newId = (prefix) => `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;
|
|
6
|
-
function registerFlowBridge(
|
|
9
|
+
function registerFlowBridge(host, options) {
|
|
7
10
|
const { adapter } = options;
|
|
8
|
-
|
|
11
|
+
const agent = { ...DEFAULT_AGENT, ...options.agent ?? {} };
|
|
9
12
|
const disposers = [];
|
|
10
|
-
const
|
|
13
|
+
const flTarget = (args, result) => ({
|
|
14
|
+
kind: "flow",
|
|
15
|
+
elementId: result?.structuredContent?.id ?? args?.id
|
|
16
|
+
});
|
|
17
|
+
const reg = (name, description, properties, required, handler, resolveTarget) => {
|
|
18
|
+
const wrapped = async (args) => {
|
|
19
|
+
try {
|
|
20
|
+
return await handler(args);
|
|
21
|
+
} catch (e) {
|
|
22
|
+
return errorResult(e instanceof Error ? e.message : String(e));
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const final = resolveTarget ? wrapToolWithActivity(wrapped, {
|
|
26
|
+
toolName: name,
|
|
27
|
+
agent: { id: agent.id, name: agent.name, color: agent.color },
|
|
28
|
+
kind: "flow",
|
|
29
|
+
resolveTarget: ({ args, result }) => resolveTarget(args, result)
|
|
30
|
+
}) : wrapped;
|
|
11
31
|
disposers.push(
|
|
12
|
-
|
|
32
|
+
host.registerTool(
|
|
13
33
|
{
|
|
14
34
|
name,
|
|
15
35
|
description,
|
|
16
36
|
inputSchema: { type: "object", properties, required, additionalProperties: false }
|
|
17
37
|
},
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
return await handler(args);
|
|
21
|
-
} catch (e) {
|
|
22
|
-
return errorResult(e instanceof Error ? e.message : String(e));
|
|
23
|
-
}
|
|
24
|
-
}
|
|
38
|
+
final
|
|
25
39
|
)
|
|
26
40
|
);
|
|
27
41
|
};
|
|
@@ -157,7 +171,8 @@ function registerFlowBridge(server, options) {
|
|
|
157
171
|
};
|
|
158
172
|
adapter.setNodes((all) => [...all, node]);
|
|
159
173
|
return textResult(`Added ${kindName} ${id} ("${str(args.label)}")`, node);
|
|
160
|
-
}
|
|
174
|
+
},
|
|
175
|
+
flTarget
|
|
161
176
|
);
|
|
162
177
|
reg(
|
|
163
178
|
"flow_update_node",
|
|
@@ -195,7 +210,8 @@ function registerFlowBridge(server, options) {
|
|
|
195
210
|
);
|
|
196
211
|
if (!updated) return errorResult(`No node with id ${id}`);
|
|
197
212
|
return textResult(`Updated node ${id}`, updated);
|
|
198
|
-
}
|
|
213
|
+
},
|
|
214
|
+
flTarget
|
|
199
215
|
);
|
|
200
216
|
reg(
|
|
201
217
|
"flow_delete_node",
|
|
@@ -210,7 +226,8 @@ function registerFlowBridge(server, options) {
|
|
|
210
226
|
adapter.setNodes((all) => all.filter((n) => n.id !== id));
|
|
211
227
|
adapter.setEdges((all) => all.filter((e) => e.source !== id && e.target !== id));
|
|
212
228
|
return textResult(`Deleted node ${id}`);
|
|
213
|
-
}
|
|
229
|
+
},
|
|
230
|
+
flTarget
|
|
214
231
|
);
|
|
215
232
|
reg(
|
|
216
233
|
"flow_connect",
|
|
@@ -239,7 +256,8 @@ function registerFlowBridge(server, options) {
|
|
|
239
256
|
};
|
|
240
257
|
adapter.setEdges((existing) => [...existing, edge]);
|
|
241
258
|
return textResult(`Connected ${source}${edge.sourceHandle ? `:${edge.sourceHandle}` : ""} \u2192 ${target}${edge.targetHandle ? `:${edge.targetHandle}` : ""}`, edge);
|
|
242
|
-
}
|
|
259
|
+
},
|
|
260
|
+
flTarget
|
|
243
261
|
);
|
|
244
262
|
reg(
|
|
245
263
|
"flow_disconnect",
|
|
@@ -253,7 +271,8 @@ function registerFlowBridge(server, options) {
|
|
|
253
271
|
}
|
|
254
272
|
adapter.setEdges((all) => all.filter((e) => e.id !== id));
|
|
255
273
|
return textResult(`Disconnected ${id}`);
|
|
256
|
-
}
|
|
274
|
+
},
|
|
275
|
+
flTarget
|
|
257
276
|
);
|
|
258
277
|
reg(
|
|
259
278
|
"flow_set_node_status",
|
|
@@ -282,7 +301,8 @@ function registerFlowBridge(server, options) {
|
|
|
282
301
|
if (!found) return errorResult(`No node with id ${id}`);
|
|
283
302
|
}
|
|
284
303
|
return textResult(`${id} \u2192 ${status}${text ? ` (${text})` : ""}`);
|
|
285
|
-
}
|
|
304
|
+
},
|
|
305
|
+
flTarget
|
|
286
306
|
);
|
|
287
307
|
reg(
|
|
288
308
|
"flow_run",
|
|
@@ -293,7 +313,8 @@ function registerFlowBridge(server, options) {
|
|
|
293
313
|
if (!adapter.run) return errorResult("Host did not provide a run handler.");
|
|
294
314
|
const result = await adapter.run();
|
|
295
315
|
return textResult(result.ok ? "Run complete" : `Run failed: ${result.error ?? "unknown"}`, result);
|
|
296
|
-
}
|
|
316
|
+
},
|
|
317
|
+
flTarget
|
|
297
318
|
);
|
|
298
319
|
reg(
|
|
299
320
|
"flow_cancel",
|
|
@@ -304,7 +325,8 @@ function registerFlowBridge(server, options) {
|
|
|
304
325
|
if (!adapter.cancel) return errorResult("Host did not provide a cancel handler.");
|
|
305
326
|
adapter.cancel();
|
|
306
327
|
return textResult("Run cancelled");
|
|
307
|
-
}
|
|
328
|
+
},
|
|
329
|
+
flTarget
|
|
308
330
|
);
|
|
309
331
|
return {
|
|
310
332
|
id: "flow",
|
|
@@ -316,5 +338,5 @@ function registerFlowBridge(server, options) {
|
|
|
316
338
|
}
|
|
317
339
|
|
|
318
340
|
export { registerFlowBridge };
|
|
319
|
-
//# sourceMappingURL=chunk-
|
|
320
|
-
//# sourceMappingURL=chunk-
|
|
341
|
+
//# sourceMappingURL=chunk-N3H4DXY5.js.map
|
|
342
|
+
//# sourceMappingURL=chunk-N3H4DXY5.js.map
|