@nimblebrain/synapse 0.15.0 → 0.17.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 +61 -111
- package/dist/{chunk-SN7YXLAV.cjs → chunk-EHLQWCYV.cjs} +6 -6
- package/dist/{chunk-SN7YXLAV.cjs.map → chunk-EHLQWCYV.cjs.map} +1 -1
- package/dist/{chunk-ZMNYUGSF.cjs → chunk-FDMRJZKT.cjs} +576 -662
- package/dist/chunk-FDMRJZKT.cjs.map +1 -0
- package/dist/{chunk-E7OOOYVR.js → chunk-SRQNQ26I.js} +3 -3
- package/dist/{chunk-E7OOOYVR.js.map → chunk-SRQNQ26I.js.map} +1 -1
- package/dist/{chunk-RYWW6EHB.cjs → chunk-TXJMGQYF.cjs} +3 -5
- package/dist/chunk-TXJMGQYF.cjs.map +1 -0
- package/dist/{chunk-J5ICAHK2.js → chunk-UPDBDXQB.js} +4 -5
- package/dist/chunk-UPDBDXQB.js.map +1 -0
- package/dist/{chunk-GNTQJSQX.js → chunk-VYR6V47N.js} +573 -663
- package/dist/chunk-VYR6V47N.js.map +1 -0
- package/dist/codegen/cli.cjs +1 -1
- package/dist/codegen/cli.js +1 -1
- package/dist/codegen/index.d.cts +1 -1
- package/dist/codegen/index.d.ts +1 -1
- package/dist/connect.iife.global.js +28 -28
- package/dist/{detect-C_qmYsh9.d.cts → detect-BHYg26_d.d.cts} +1 -1
- package/dist/{detect-Dfd0upoz.d.ts → detect-Bf8Q_0dK.d.ts} +1 -1
- package/dist/host/index.cjs +14 -14
- package/dist/host/index.d.cts +3 -3
- package/dist/host/index.d.ts +3 -3
- package/dist/host/index.js +2 -2
- package/dist/index.cjs +28 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -26
- package/dist/index.d.ts +58 -26
- package/dist/index.js +3 -81
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +81 -140
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +66 -82
- package/dist/react/index.d.ts +66 -82
- package/dist/react/index.js +82 -136
- package/dist/react/index.js.map +1 -1
- package/dist/{server-ERRDGEZ7.js → server-5N76YCWC.js} +3 -3
- package/dist/{server-ERRDGEZ7.js.map → server-5N76YCWC.js.map} +1 -1
- package/dist/{server-P54IYX2G.cjs → server-QIYIJHD5.cjs} +3 -3
- package/dist/{server-P54IYX2G.cjs.map → server-QIYIJHD5.cjs.map} +1 -1
- package/dist/synapse-runtime.iife.global.js +28 -28
- package/dist/synapse-ui.iife.global.js +2 -2
- package/dist/{types-BSZasM8q.d.cts → types-uEO4VFJ2.d.cts} +87 -166
- package/dist/{types-BSZasM8q.d.ts → types-uEO4VFJ2.d.ts} +87 -166
- package/dist/ui/index.cjs +403 -91
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.cts +115 -3
- package/dist/ui/index.d.ts +115 -3
- package/dist/ui/index.js +401 -93
- package/dist/ui/index.js.map +1 -1
- package/dist/vite/index.cjs +1 -1
- package/dist/vite/index.cjs.map +1 -1
- package/dist/vite/index.js +1 -1
- package/dist/vite/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-GNTQJSQX.js.map +0 -1
- package/dist/chunk-J5ICAHK2.js.map +0 -1
- package/dist/chunk-RYWW6EHB.cjs.map +0 -1
- package/dist/chunk-ZMNYUGSF.cjs.map +0 -1
|
@@ -1,448 +1,68 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkTXJMGQYF_cjs = require('./chunk-TXJMGQYF.cjs');
|
|
4
4
|
var extApps = require('@modelcontextprotocol/ext-apps');
|
|
5
5
|
|
|
6
|
-
// src/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
).map((block) => block.text);
|
|
18
|
-
if (texts.length > 0) {
|
|
19
|
-
const joined = texts.join("");
|
|
20
|
-
try {
|
|
21
|
-
return { content: JSON.parse(joined), structuredContent: null, raw };
|
|
22
|
-
} catch {
|
|
23
|
-
return { content: joined, structuredContent: null, raw };
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return { content: rawContent, structuredContent: null, raw };
|
|
27
|
-
}
|
|
28
|
-
if (typeof rawContent === "string") {
|
|
29
|
-
try {
|
|
30
|
-
return { content: JSON.parse(rawContent), structuredContent: null, raw };
|
|
31
|
-
} catch {
|
|
32
|
-
return { content: rawContent, structuredContent: null, raw };
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return { content: rawContent ?? null, structuredContent: null, raw };
|
|
36
|
-
}
|
|
37
|
-
var EVENT_MAP = {
|
|
38
|
-
"tool-result": extApps.TOOL_RESULT_METHOD,
|
|
39
|
-
"tool-input": extApps.TOOL_INPUT_METHOD,
|
|
40
|
-
"tool-input-partial": extApps.TOOL_INPUT_PARTIAL_METHOD,
|
|
41
|
-
"tool-cancelled": extApps.TOOL_CANCELLED_METHOD,
|
|
42
|
-
"theme-changed": extApps.HOST_CONTEXT_CHANGED_METHOD,
|
|
43
|
-
teardown: extApps.RESOURCE_TEARDOWN_METHOD
|
|
44
|
-
};
|
|
45
|
-
function resolveEventMethod(name) {
|
|
46
|
-
return EVENT_MAP[name] ?? name;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// src/resize.ts
|
|
50
|
-
function createResizer(send, autoResize) {
|
|
51
|
-
let destroyed = false;
|
|
52
|
-
let observer = null;
|
|
53
|
-
let rafId = null;
|
|
54
|
-
function measureAndSend() {
|
|
55
|
-
if (destroyed) return;
|
|
56
|
-
const width = document.body.scrollWidth;
|
|
57
|
-
const height = document.body.scrollHeight;
|
|
58
|
-
send("ui/notifications/size-changed", { width, height });
|
|
59
|
-
}
|
|
60
|
-
function resize(width, height) {
|
|
61
|
-
if (destroyed) return;
|
|
62
|
-
if (width !== void 0 && height !== void 0) {
|
|
63
|
-
send("ui/notifications/size-changed", { width, height });
|
|
64
|
-
} else {
|
|
65
|
-
measureAndSend();
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (autoResize && typeof ResizeObserver !== "undefined") {
|
|
69
|
-
observer = new ResizeObserver(() => {
|
|
70
|
-
if (destroyed) return;
|
|
71
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
72
|
-
rafId = requestAnimationFrame(() => {
|
|
73
|
-
rafId = null;
|
|
74
|
-
measureAndSend();
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
observer.observe(document.body);
|
|
78
|
-
}
|
|
79
|
-
function destroy() {
|
|
80
|
-
if (destroyed) return;
|
|
81
|
-
destroyed = true;
|
|
82
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
83
|
-
observer?.disconnect();
|
|
84
|
-
observer = null;
|
|
85
|
-
}
|
|
86
|
-
return { resize, measureAndSend, destroy };
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// src/result-parser.ts
|
|
90
|
-
function parseToolResult(raw) {
|
|
91
|
-
if (raw == null) {
|
|
92
|
-
return { data: null, isError: false };
|
|
93
|
-
}
|
|
94
|
-
if (isCallToolResult(raw)) {
|
|
95
|
-
return parseCallToolResult(raw);
|
|
96
|
-
}
|
|
97
|
-
return { data: raw, isError: false };
|
|
98
|
-
}
|
|
99
|
-
function isCallToolResult(value) {
|
|
100
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
return Array.isArray(value.content);
|
|
104
|
-
}
|
|
105
|
-
function isTextBlock(block) {
|
|
106
|
-
if (block === null || typeof block !== "object" || Array.isArray(block)) {
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
const obj = block;
|
|
110
|
-
return obj.type === "text" && typeof obj.text === "string";
|
|
111
|
-
}
|
|
112
|
-
function extractMeta(result) {
|
|
113
|
-
const meta = result._meta;
|
|
114
|
-
if (!meta || typeof meta !== "object" || Array.isArray(meta)) return void 0;
|
|
115
|
-
return { ...meta };
|
|
116
|
-
}
|
|
117
|
-
function parseCallToolResult(result) {
|
|
118
|
-
const isError = result.isError === true;
|
|
119
|
-
const content = result.content;
|
|
120
|
-
const meta = extractMeta(result);
|
|
121
|
-
if (content.length === 0) {
|
|
122
|
-
return { data: null, isError, content, ...meta && { _meta: meta } };
|
|
123
|
-
}
|
|
124
|
-
const firstText = content.find(isTextBlock);
|
|
125
|
-
if (!firstText) {
|
|
126
|
-
return { data: content, isError, content, ...meta && { _meta: meta } };
|
|
127
|
-
}
|
|
128
|
-
try {
|
|
129
|
-
return { data: JSON.parse(firstText.text), isError, content, ...meta && { _meta: meta } };
|
|
130
|
-
} catch {
|
|
131
|
-
return { data: firstText.text, isError, content, ...meta && { _meta: meta } };
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// src/transport.ts
|
|
136
|
-
var SynapseTransport = class {
|
|
137
|
-
counter = 0;
|
|
138
|
-
destroyed = false;
|
|
139
|
-
pending = /* @__PURE__ */ new Map();
|
|
140
|
-
handlers = /* @__PURE__ */ new Map();
|
|
141
|
-
listener;
|
|
142
|
-
constructor() {
|
|
143
|
-
this.listener = (event) => this.handleMessage(event);
|
|
144
|
-
window.addEventListener("message", this.listener);
|
|
145
|
-
}
|
|
146
|
-
send(method, params) {
|
|
147
|
-
if (this.destroyed) return;
|
|
148
|
-
const msg = {
|
|
149
|
-
jsonrpc: "2.0",
|
|
150
|
-
method,
|
|
151
|
-
...params !== void 0 && { params }
|
|
152
|
-
};
|
|
153
|
-
window.parent.postMessage(msg, "*");
|
|
154
|
-
}
|
|
155
|
-
request(method, params) {
|
|
156
|
-
if (this.destroyed) {
|
|
157
|
-
return Promise.reject(new Error("Transport destroyed"));
|
|
158
|
-
}
|
|
159
|
-
const id = `syn-${++this.counter}`;
|
|
160
|
-
const msg = {
|
|
161
|
-
jsonrpc: "2.0",
|
|
162
|
-
method,
|
|
163
|
-
id,
|
|
164
|
-
...params !== void 0 && { params }
|
|
165
|
-
};
|
|
166
|
-
return new Promise((resolve, reject) => {
|
|
167
|
-
this.pending.set(id, { resolve, reject });
|
|
168
|
-
window.parent.postMessage(msg, "*");
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
onMessage(method, callback) {
|
|
172
|
-
if (!this.handlers.has(method)) {
|
|
173
|
-
this.handlers.set(method, /* @__PURE__ */ new Set());
|
|
174
|
-
}
|
|
175
|
-
this.handlers.get(method)?.add(callback);
|
|
176
|
-
return () => {
|
|
177
|
-
const set = this.handlers.get(method);
|
|
178
|
-
if (set) {
|
|
179
|
-
set.delete(callback);
|
|
180
|
-
if (set.size === 0) {
|
|
181
|
-
this.handlers.delete(method);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
destroy() {
|
|
187
|
-
if (this.destroyed) return;
|
|
188
|
-
this.destroyed = true;
|
|
189
|
-
window.removeEventListener("message", this.listener);
|
|
190
|
-
const error = new Error("Transport destroyed");
|
|
191
|
-
for (const entry of this.pending.values()) {
|
|
192
|
-
entry.reject(error);
|
|
193
|
-
}
|
|
194
|
-
this.pending.clear();
|
|
195
|
-
this.handlers.clear();
|
|
196
|
-
}
|
|
197
|
-
handleMessage(event) {
|
|
198
|
-
if (this.destroyed) return;
|
|
199
|
-
const data = event.data;
|
|
200
|
-
if (!data || data.jsonrpc !== "2.0") return;
|
|
201
|
-
if ("id" in data && data.id && !("method" in data)) {
|
|
202
|
-
const response = data;
|
|
203
|
-
const entry = this.pending.get(response.id);
|
|
204
|
-
if (!entry) return;
|
|
205
|
-
this.pending.delete(response.id);
|
|
206
|
-
if (response.error) {
|
|
207
|
-
const err = new Error(response.error.message);
|
|
208
|
-
err.code = response.error.code;
|
|
209
|
-
err.data = response.error.data;
|
|
210
|
-
entry.reject(err);
|
|
211
|
-
} else {
|
|
212
|
-
entry.resolve(response.result);
|
|
213
|
-
}
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if ("method" in data && !("id" in data && data.id)) {
|
|
217
|
-
const notification = data;
|
|
218
|
-
const set = this.handlers.get(notification.method);
|
|
219
|
-
if (set) {
|
|
220
|
-
for (const handler of set) {
|
|
221
|
-
handler(notification.params);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
// src/connect.ts
|
|
229
|
-
var READ_RESOURCE_METHOD = "resources/read";
|
|
230
|
-
async function connect(options) {
|
|
231
|
-
const { name, version, autoResize = false } = options;
|
|
232
|
-
const transport = new SynapseTransport();
|
|
233
|
-
let destroyed = false;
|
|
234
|
-
let currentTheme = { mode: "light", tokens: {} };
|
|
235
|
-
let hostInfo = { name: "unknown", version: "unknown" };
|
|
236
|
-
let toolInfo = null;
|
|
237
|
-
let containerDimensions = null;
|
|
238
|
-
const handlers = /* @__PURE__ */ new Map();
|
|
239
|
-
const resizer = createResizer((method, params) => transport.send(method, params), autoResize);
|
|
240
|
-
resizer.measureAndSend();
|
|
241
|
-
const initParams = {
|
|
242
|
-
protocolVersion: extApps.LATEST_PROTOCOL_VERSION,
|
|
243
|
-
appInfo: { name, version },
|
|
244
|
-
appCapabilities: {}
|
|
245
|
-
};
|
|
246
|
-
const result = await transport.request(
|
|
247
|
-
extApps.INITIALIZE_METHOD,
|
|
248
|
-
initParams
|
|
249
|
-
);
|
|
250
|
-
if (result) {
|
|
251
|
-
hostInfo = {
|
|
252
|
-
name: result.hostInfo?.name ?? "unknown",
|
|
253
|
-
version: result.hostInfo?.version ?? "unknown"
|
|
254
|
-
};
|
|
255
|
-
const ctx = result.hostContext;
|
|
256
|
-
if (ctx) {
|
|
257
|
-
const initialFontFaces = chunkRYWW6EHB_cjs.extractFontFaces(ctx);
|
|
258
|
-
currentTheme = {
|
|
259
|
-
mode: ctx.theme === "dark" ? "dark" : "light",
|
|
260
|
-
tokens: ctx.styles?.variables && typeof ctx.styles.variables === "object" ? ctx.styles.variables : {},
|
|
261
|
-
...initialFontFaces ? { fontFaces: initialFontFaces } : {}
|
|
262
|
-
};
|
|
263
|
-
if (ctx.toolInfo && typeof ctx.toolInfo === "object") {
|
|
264
|
-
toolInfo = { tool: ctx.toolInfo.tool ?? {} };
|
|
265
|
-
}
|
|
266
|
-
if (ctx.containerDimensions && typeof ctx.containerDimensions === "object") {
|
|
267
|
-
containerDimensions = ctx.containerDimensions;
|
|
268
|
-
}
|
|
269
|
-
chunkRYWW6EHB_cjs.applyTheme(currentTheme.mode, currentTheme.tokens, currentTheme.fontFaces);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
transport.onMessage(extApps.HOST_CONTEXT_CHANGED_METHOD, (params) => {
|
|
273
|
-
if (destroyed || !params) return;
|
|
274
|
-
const ctx = params;
|
|
275
|
-
const mode = ctx.theme === "dark" ? "dark" : "light";
|
|
276
|
-
const variables = ctx.styles?.variables;
|
|
277
|
-
const tokens = variables && typeof variables === "object" ? variables : currentTheme.tokens;
|
|
278
|
-
const fontFaces = chunkRYWW6EHB_cjs.foldFontFaces(currentTheme.fontFaces, ctx);
|
|
279
|
-
currentTheme = { mode, tokens, ...fontFaces ? { fontFaces } : {} };
|
|
280
|
-
chunkRYWW6EHB_cjs.applyTheme(mode, tokens, fontFaces);
|
|
281
|
-
const set = handlers.get(extApps.HOST_CONTEXT_CHANGED_METHOD);
|
|
282
|
-
if (set) {
|
|
283
|
-
for (const handler of set) handler(currentTheme);
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
const subscribedMethods = /* @__PURE__ */ new Set([extApps.HOST_CONTEXT_CHANGED_METHOD]);
|
|
287
|
-
function ensureTransportSub(method) {
|
|
288
|
-
if (subscribedMethods.has(method)) return;
|
|
289
|
-
subscribedMethods.add(method);
|
|
290
|
-
const isToolResult = method === extApps.TOOL_RESULT_METHOD;
|
|
291
|
-
transport.onMessage(method, (params) => {
|
|
292
|
-
if (destroyed) return;
|
|
293
|
-
const set = handlers.get(method);
|
|
294
|
-
if (!set) return;
|
|
295
|
-
for (const handler of set) {
|
|
296
|
-
if (isToolResult) {
|
|
297
|
-
handler(parseToolResultParams(params));
|
|
298
|
-
} else {
|
|
299
|
-
handler(params);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
if (options.on) {
|
|
305
|
-
for (const [event, handler] of Object.entries(options.on)) {
|
|
306
|
-
if (typeof handler === "function") {
|
|
307
|
-
const method = resolveEventMethod(event);
|
|
308
|
-
if (!handlers.has(method)) handlers.set(method, /* @__PURE__ */ new Set());
|
|
309
|
-
handlers.get(method)?.add(handler);
|
|
310
|
-
ensureTransportSub(method);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
transport.send(extApps.INITIALIZED_METHOD, {});
|
|
315
|
-
const app = {
|
|
316
|
-
get theme() {
|
|
317
|
-
return { ...currentTheme };
|
|
318
|
-
},
|
|
319
|
-
get hostInfo() {
|
|
320
|
-
return { ...hostInfo };
|
|
321
|
-
},
|
|
322
|
-
get toolInfo() {
|
|
323
|
-
return toolInfo;
|
|
324
|
-
},
|
|
325
|
-
get containerDimensions() {
|
|
326
|
-
return containerDimensions;
|
|
327
|
-
},
|
|
328
|
-
on(event, handler) {
|
|
329
|
-
const method = resolveEventMethod(event);
|
|
330
|
-
if (!handlers.has(method)) {
|
|
331
|
-
handlers.set(method, /* @__PURE__ */ new Set());
|
|
332
|
-
}
|
|
333
|
-
handlers.get(method)?.add(handler);
|
|
334
|
-
ensureTransportSub(method);
|
|
335
|
-
return () => {
|
|
336
|
-
const set = handlers.get(method);
|
|
337
|
-
if (set) {
|
|
338
|
-
set.delete(handler);
|
|
339
|
-
if (set.size === 0) handlers.delete(method);
|
|
340
|
-
}
|
|
341
|
-
};
|
|
342
|
-
},
|
|
343
|
-
resize(width, height) {
|
|
344
|
-
resizer.resize(width, height);
|
|
345
|
-
},
|
|
346
|
-
openLink(url) {
|
|
347
|
-
if (destroyed) return;
|
|
348
|
-
const params = { url };
|
|
349
|
-
transport.request(extApps.OPEN_LINK_METHOD, params).catch(() => {
|
|
350
|
-
});
|
|
351
|
-
},
|
|
352
|
-
updateModelContext(state, summary) {
|
|
353
|
-
if (destroyed) return;
|
|
354
|
-
const params = {
|
|
355
|
-
structuredContent: state,
|
|
356
|
-
...summary !== void 0 && {
|
|
357
|
-
content: [{ type: "text", text: summary }]
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
transport.send("ui/update-model-context", params);
|
|
361
|
-
},
|
|
362
|
-
async callTool(toolName, args) {
|
|
363
|
-
const params = {
|
|
364
|
-
name: toolName,
|
|
365
|
-
arguments: args ?? {}
|
|
366
|
-
};
|
|
367
|
-
const raw = await transport.request(
|
|
368
|
-
"tools/call",
|
|
369
|
-
params
|
|
370
|
-
);
|
|
371
|
-
return parseToolResult(raw);
|
|
372
|
-
},
|
|
373
|
-
async readServerResource(params) {
|
|
374
|
-
const raw = await transport.request(
|
|
375
|
-
READ_RESOURCE_METHOD,
|
|
376
|
-
params
|
|
377
|
-
);
|
|
378
|
-
return raw;
|
|
379
|
-
},
|
|
380
|
-
sendMessage(text, context) {
|
|
381
|
-
if (destroyed) return;
|
|
382
|
-
const textBlock = {
|
|
383
|
-
type: "text",
|
|
384
|
-
text,
|
|
385
|
-
...context && { _meta: { context } }
|
|
386
|
-
};
|
|
387
|
-
const params = {
|
|
388
|
-
role: "user",
|
|
389
|
-
content: [textBlock]
|
|
390
|
-
};
|
|
391
|
-
transport.send(extApps.MESSAGE_METHOD, params);
|
|
392
|
-
},
|
|
393
|
-
destroy() {
|
|
394
|
-
if (destroyed) return;
|
|
395
|
-
destroyed = true;
|
|
396
|
-
resizer.destroy();
|
|
397
|
-
handlers.clear();
|
|
398
|
-
transport.destroy();
|
|
399
|
-
}
|
|
400
|
-
};
|
|
401
|
-
return app;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// src/keyboard.ts
|
|
405
|
-
var KeyboardForwarder = class {
|
|
406
|
-
listener;
|
|
407
|
-
destroyed = false;
|
|
408
|
-
constructor(transport, customKeys) {
|
|
409
|
-
const config = customKeys ?? null;
|
|
410
|
-
this.listener = (event) => {
|
|
411
|
-
if (this.destroyed) return;
|
|
412
|
-
if (this.shouldForward(event, config)) {
|
|
413
|
-
event.preventDefault();
|
|
414
|
-
transport.send("synapse/keydown", {
|
|
415
|
-
key: event.key,
|
|
416
|
-
ctrlKey: event.ctrlKey,
|
|
417
|
-
metaKey: event.metaKey,
|
|
418
|
-
shiftKey: event.shiftKey,
|
|
419
|
-
altKey: event.altKey
|
|
420
|
-
});
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
document.addEventListener("keydown", this.listener);
|
|
6
|
+
// src/internals.ts
|
|
7
|
+
var INTERNALS = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function registerInternals(app, internals) {
|
|
9
|
+
INTERNALS.set(app, internals);
|
|
10
|
+
}
|
|
11
|
+
function internalsFor(app) {
|
|
12
|
+
const internals = INTERNALS.get(app);
|
|
13
|
+
if (!internals) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
"This App did not come from this copy of @nimblebrain/synapse. Two copies of the package are installed (check for a duplicate in your lockfile, or a bundler resolving the ESM and CJS builds separately)."
|
|
16
|
+
);
|
|
424
17
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
18
|
+
return internals;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/result-parser.ts
|
|
22
|
+
function parseToolResult(raw) {
|
|
23
|
+
if (raw == null) {
|
|
24
|
+
return { data: null, isError: false };
|
|
429
25
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
if (event.key === "Escape") return true;
|
|
438
|
-
if (event.ctrlKey || event.metaKey) {
|
|
439
|
-
const key = event.key.toLowerCase();
|
|
440
|
-
if (key === "c" || key === "v" || key === "x" || key === "a") return false;
|
|
441
|
-
return true;
|
|
442
|
-
}
|
|
26
|
+
if (isCallToolResult(raw)) {
|
|
27
|
+
return parseCallToolResult(raw);
|
|
28
|
+
}
|
|
29
|
+
return { data: raw, isError: false };
|
|
30
|
+
}
|
|
31
|
+
function isCallToolResult(value) {
|
|
32
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
443
33
|
return false;
|
|
444
34
|
}
|
|
445
|
-
|
|
35
|
+
return Array.isArray(value.content);
|
|
36
|
+
}
|
|
37
|
+
function isTextBlock(block) {
|
|
38
|
+
if (block === null || typeof block !== "object" || Array.isArray(block)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const obj = block;
|
|
42
|
+
return obj.type === "text" && typeof obj.text === "string";
|
|
43
|
+
}
|
|
44
|
+
function extractMeta(result) {
|
|
45
|
+
const meta = result._meta;
|
|
46
|
+
if (!meta || typeof meta !== "object" || Array.isArray(meta)) return void 0;
|
|
47
|
+
return { ...meta };
|
|
48
|
+
}
|
|
49
|
+
function parseCallToolResult(result) {
|
|
50
|
+
const isError = result.isError === true;
|
|
51
|
+
const content = result.content;
|
|
52
|
+
const meta = extractMeta(result);
|
|
53
|
+
if (content.length === 0) {
|
|
54
|
+
return { data: null, isError, content, ...meta && { _meta: meta } };
|
|
55
|
+
}
|
|
56
|
+
const firstText = content.find(isTextBlock);
|
|
57
|
+
if (!firstText) {
|
|
58
|
+
return { data: content, isError, content, ...meta && { _meta: meta } };
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
return { data: JSON.parse(firstText.text), isError, content, ...meta && { _meta: meta } };
|
|
62
|
+
} catch {
|
|
63
|
+
return { data: firstText.text, isError, content, ...meta && { _meta: meta } };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
446
66
|
|
|
447
67
|
// src/task-handle.ts
|
|
448
68
|
var TOOLS_CALL_METHOD = "tools/call";
|
|
@@ -487,11 +107,12 @@ function createTaskStatusRouter(transport) {
|
|
|
487
107
|
}
|
|
488
108
|
};
|
|
489
109
|
}
|
|
490
|
-
async function callToolAsTask(
|
|
491
|
-
const
|
|
110
|
+
async function callToolAsTask(app, toolName, args, options) {
|
|
111
|
+
const deps = internalsFor(app);
|
|
112
|
+
const hostTasks = deps.hostTasksCapability;
|
|
492
113
|
if (!hostTasks?.requests?.tools?.call) {
|
|
493
114
|
throw new Error(
|
|
494
|
-
"callToolAsTask: host did not advertise tasks.requests.tools.call in its capabilities. Per MCP 2025-11-25 \xA7, requestors MUST NOT task-augment a tools/call without matching receiver capability. Fall back to `
|
|
115
|
+
"callToolAsTask: host did not advertise tasks.requests.tools.call in its capabilities. Per MCP 2025-11-25 \xA7, requestors MUST NOT task-augment a tools/call without matching receiver capability. Fall back to `app.callTool`."
|
|
495
116
|
);
|
|
496
117
|
}
|
|
497
118
|
const taskParam = {};
|
|
@@ -503,7 +124,7 @@ async function callToolAsTask(deps, toolName, args, options) {
|
|
|
503
124
|
task: taskParam,
|
|
504
125
|
...crossServer ? { server: deps.appName } : {}
|
|
505
126
|
};
|
|
506
|
-
const raw = await deps.
|
|
127
|
+
const raw = await deps.request(
|
|
507
128
|
TOOLS_CALL_METHOD,
|
|
508
129
|
callParams
|
|
509
130
|
);
|
|
@@ -520,7 +141,7 @@ async function callToolAsTask(deps, toolName, args, options) {
|
|
|
520
141
|
task: initialTask,
|
|
521
142
|
async result() {
|
|
522
143
|
const params = { taskId };
|
|
523
|
-
const rawResult = await deps.
|
|
144
|
+
const rawResult = await deps.request(
|
|
524
145
|
TASKS_RESULT_METHOD,
|
|
525
146
|
params
|
|
526
147
|
);
|
|
@@ -529,7 +150,7 @@ async function callToolAsTask(deps, toolName, args, options) {
|
|
|
529
150
|
},
|
|
530
151
|
async refresh() {
|
|
531
152
|
const params = { taskId };
|
|
532
|
-
const raw2 = await deps.
|
|
153
|
+
const raw2 = await deps.request(
|
|
533
154
|
TASKS_GET_METHOD,
|
|
534
155
|
params
|
|
535
156
|
);
|
|
@@ -537,7 +158,7 @@ async function callToolAsTask(deps, toolName, args, options) {
|
|
|
537
158
|
},
|
|
538
159
|
async cancel() {
|
|
539
160
|
const params = { taskId };
|
|
540
|
-
const raw2 = await deps.
|
|
161
|
+
const raw2 = await deps.request(
|
|
541
162
|
TASKS_CANCEL_METHOD,
|
|
542
163
|
params
|
|
543
164
|
);
|
|
@@ -546,7 +167,7 @@ async function callToolAsTask(deps, toolName, args, options) {
|
|
|
546
167
|
onStatus(cb) {
|
|
547
168
|
const existing = localCallbacks.get(cb);
|
|
548
169
|
if (existing) return existing;
|
|
549
|
-
const wireUnsub = deps.
|
|
170
|
+
const wireUnsub = deps.taskRouter.subscribe(taskId, (update) => {
|
|
550
171
|
const merged = {
|
|
551
172
|
taskId: update.taskId,
|
|
552
173
|
status: update.status,
|
|
@@ -567,42 +188,269 @@ async function callToolAsTask(deps, toolName, args, options) {
|
|
|
567
188
|
localCallbacks.set(cb, unsub);
|
|
568
189
|
return unsub;
|
|
569
190
|
}
|
|
570
|
-
};
|
|
571
|
-
return handle;
|
|
572
|
-
}
|
|
573
|
-
function projectTask(raw) {
|
|
574
|
-
return {
|
|
575
|
-
taskId: raw.taskId,
|
|
576
|
-
status: raw.status,
|
|
577
|
-
ttl: raw.ttl,
|
|
578
|
-
createdAt: raw.createdAt,
|
|
579
|
-
lastUpdatedAt: raw.lastUpdatedAt,
|
|
580
|
-
...raw.pollInterval !== void 0 && { pollInterval: raw.pollInterval },
|
|
581
|
-
...raw.statusMessage !== void 0 && { statusMessage: raw.statusMessage }
|
|
582
|
-
};
|
|
583
|
-
}
|
|
191
|
+
};
|
|
192
|
+
return handle;
|
|
193
|
+
}
|
|
194
|
+
function projectTask(raw) {
|
|
195
|
+
return {
|
|
196
|
+
taskId: raw.taskId,
|
|
197
|
+
status: raw.status,
|
|
198
|
+
ttl: raw.ttl,
|
|
199
|
+
createdAt: raw.createdAt,
|
|
200
|
+
lastUpdatedAt: raw.lastUpdatedAt,
|
|
201
|
+
...raw.pollInterval !== void 0 && { pollInterval: raw.pollInterval },
|
|
202
|
+
...raw.statusMessage !== void 0 && { statusMessage: raw.statusMessage }
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// src/content-parser.ts
|
|
207
|
+
function parseToolResultParams(params) {
|
|
208
|
+
const raw = params ?? {};
|
|
209
|
+
const structuredContent = raw.structuredContent ?? null;
|
|
210
|
+
if (structuredContent != null) {
|
|
211
|
+
return { content: structuredContent, structuredContent, raw };
|
|
212
|
+
}
|
|
213
|
+
const rawContent = raw.content;
|
|
214
|
+
if (Array.isArray(rawContent)) {
|
|
215
|
+
const texts = rawContent.filter(
|
|
216
|
+
(block) => block != null && typeof block === "object" && block.type === "text" && typeof block.text === "string"
|
|
217
|
+
).map((block) => block.text);
|
|
218
|
+
if (texts.length > 0) {
|
|
219
|
+
const joined = texts.join("");
|
|
220
|
+
try {
|
|
221
|
+
return { content: JSON.parse(joined), structuredContent: null, raw };
|
|
222
|
+
} catch {
|
|
223
|
+
return { content: joined, structuredContent: null, raw };
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return { content: rawContent, structuredContent: null, raw };
|
|
227
|
+
}
|
|
228
|
+
if (typeof rawContent === "string") {
|
|
229
|
+
try {
|
|
230
|
+
return { content: JSON.parse(rawContent), structuredContent: null, raw };
|
|
231
|
+
} catch {
|
|
232
|
+
return { content: rawContent, structuredContent: null, raw };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return { content: rawContent ?? null, structuredContent: null, raw };
|
|
236
|
+
}
|
|
237
|
+
var DATA_CHANGED_METHOD = "synapse/data-changed";
|
|
238
|
+
var ACTION_METHOD = "synapse/action";
|
|
239
|
+
var REQUEST_FILE_METHOD = "synapse/request-file";
|
|
240
|
+
var DOWNLOAD_FILE_METHOD = "synapse/download-file";
|
|
241
|
+
var EVENT_MAP = {
|
|
242
|
+
"tool-result": extApps.TOOL_RESULT_METHOD,
|
|
243
|
+
"tool-input": extApps.TOOL_INPUT_METHOD,
|
|
244
|
+
"tool-input-partial": extApps.TOOL_INPUT_PARTIAL_METHOD,
|
|
245
|
+
"tool-cancelled": extApps.TOOL_CANCELLED_METHOD,
|
|
246
|
+
teardown: extApps.RESOURCE_TEARDOWN_METHOD
|
|
247
|
+
};
|
|
248
|
+
function resolveEventMethod(name) {
|
|
249
|
+
return EVENT_MAP[name] ?? name;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// src/keyboard.ts
|
|
253
|
+
var KeyboardForwarder = class {
|
|
254
|
+
listener;
|
|
255
|
+
destroyed = false;
|
|
256
|
+
constructor(transport, customKeys) {
|
|
257
|
+
const config = customKeys ?? null;
|
|
258
|
+
this.listener = (event) => {
|
|
259
|
+
if (this.destroyed) return;
|
|
260
|
+
if (this.shouldForward(event, config)) {
|
|
261
|
+
event.preventDefault();
|
|
262
|
+
transport.send("synapse/keydown", {
|
|
263
|
+
key: event.key,
|
|
264
|
+
ctrlKey: event.ctrlKey,
|
|
265
|
+
metaKey: event.metaKey,
|
|
266
|
+
shiftKey: event.shiftKey,
|
|
267
|
+
altKey: event.altKey
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
document.addEventListener("keydown", this.listener);
|
|
272
|
+
}
|
|
273
|
+
destroy() {
|
|
274
|
+
if (this.destroyed) return;
|
|
275
|
+
this.destroyed = true;
|
|
276
|
+
document.removeEventListener("keydown", this.listener);
|
|
277
|
+
}
|
|
278
|
+
shouldForward(event, config) {
|
|
279
|
+
if (config && config.length === 0) return false;
|
|
280
|
+
if (config) {
|
|
281
|
+
return config.some(
|
|
282
|
+
(k) => event.key.toLowerCase() === k.key.toLowerCase() && (k.ctrl === void 0 || event.ctrlKey === k.ctrl) && (k.meta === void 0 || event.metaKey === k.meta) && (k.shift === void 0 || event.shiftKey === k.shift) && (k.alt === void 0 || event.altKey === k.alt)
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
if (event.key === "Escape") return true;
|
|
286
|
+
if (event.ctrlKey || event.metaKey) {
|
|
287
|
+
const key = event.key.toLowerCase();
|
|
288
|
+
if (key === "c" || key === "v" || key === "x" || key === "a") return false;
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// src/resize.ts
|
|
296
|
+
function createResizer(send, autoResize) {
|
|
297
|
+
let destroyed = false;
|
|
298
|
+
let observer = null;
|
|
299
|
+
let rafId = null;
|
|
300
|
+
function measureAndSend() {
|
|
301
|
+
if (destroyed) return;
|
|
302
|
+
const width = document.body.scrollWidth;
|
|
303
|
+
const height = document.body.scrollHeight;
|
|
304
|
+
send("ui/notifications/size-changed", { width, height });
|
|
305
|
+
}
|
|
306
|
+
function resize(width, height) {
|
|
307
|
+
if (destroyed) return;
|
|
308
|
+
if (width !== void 0 && height !== void 0) {
|
|
309
|
+
send("ui/notifications/size-changed", { width, height });
|
|
310
|
+
} else {
|
|
311
|
+
measureAndSend();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (autoResize && typeof ResizeObserver !== "undefined") {
|
|
315
|
+
observer = new ResizeObserver(() => {
|
|
316
|
+
if (destroyed) return;
|
|
317
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
318
|
+
rafId = requestAnimationFrame(() => {
|
|
319
|
+
rafId = null;
|
|
320
|
+
measureAndSend();
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
observer.observe(document.body);
|
|
324
|
+
}
|
|
325
|
+
function destroy() {
|
|
326
|
+
if (destroyed) return;
|
|
327
|
+
destroyed = true;
|
|
328
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
329
|
+
observer?.disconnect();
|
|
330
|
+
observer = null;
|
|
331
|
+
}
|
|
332
|
+
return { resize, measureAndSend, destroy };
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// src/transport.ts
|
|
336
|
+
var SynapseTransport = class {
|
|
337
|
+
counter = 0;
|
|
338
|
+
destroyed = false;
|
|
339
|
+
pending = /* @__PURE__ */ new Map();
|
|
340
|
+
handlers = /* @__PURE__ */ new Map();
|
|
341
|
+
listener;
|
|
342
|
+
constructor() {
|
|
343
|
+
this.listener = (event) => this.handleMessage(event);
|
|
344
|
+
window.addEventListener("message", this.listener);
|
|
345
|
+
}
|
|
346
|
+
send(method, params) {
|
|
347
|
+
if (this.destroyed) return;
|
|
348
|
+
const msg = {
|
|
349
|
+
jsonrpc: "2.0",
|
|
350
|
+
method,
|
|
351
|
+
...params !== void 0 && { params }
|
|
352
|
+
};
|
|
353
|
+
window.parent.postMessage(msg, "*");
|
|
354
|
+
}
|
|
355
|
+
request(method, params) {
|
|
356
|
+
if (this.destroyed) {
|
|
357
|
+
return Promise.reject(new Error("Transport destroyed"));
|
|
358
|
+
}
|
|
359
|
+
const id = `syn-${++this.counter}`;
|
|
360
|
+
const msg = {
|
|
361
|
+
jsonrpc: "2.0",
|
|
362
|
+
method,
|
|
363
|
+
id,
|
|
364
|
+
...params !== void 0 && { params }
|
|
365
|
+
};
|
|
366
|
+
return new Promise((resolve, reject) => {
|
|
367
|
+
this.pending.set(id, { resolve, reject });
|
|
368
|
+
window.parent.postMessage(msg, "*");
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
onMessage(method, callback) {
|
|
372
|
+
if (!this.handlers.has(method)) {
|
|
373
|
+
this.handlers.set(method, /* @__PURE__ */ new Set());
|
|
374
|
+
}
|
|
375
|
+
this.handlers.get(method)?.add(callback);
|
|
376
|
+
return () => {
|
|
377
|
+
const set = this.handlers.get(method);
|
|
378
|
+
if (set) {
|
|
379
|
+
set.delete(callback);
|
|
380
|
+
if (set.size === 0) {
|
|
381
|
+
this.handlers.delete(method);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
destroy() {
|
|
387
|
+
if (this.destroyed) return;
|
|
388
|
+
this.destroyed = true;
|
|
389
|
+
window.removeEventListener("message", this.listener);
|
|
390
|
+
const error = new Error("Transport destroyed");
|
|
391
|
+
for (const entry of this.pending.values()) {
|
|
392
|
+
entry.reject(error);
|
|
393
|
+
}
|
|
394
|
+
this.pending.clear();
|
|
395
|
+
this.handlers.clear();
|
|
396
|
+
}
|
|
397
|
+
handleMessage(event) {
|
|
398
|
+
if (this.destroyed) return;
|
|
399
|
+
const data = event.data;
|
|
400
|
+
if (!data || data.jsonrpc !== "2.0") return;
|
|
401
|
+
if ("id" in data && data.id && !("method" in data)) {
|
|
402
|
+
const response = data;
|
|
403
|
+
const entry = this.pending.get(response.id);
|
|
404
|
+
if (!entry) return;
|
|
405
|
+
this.pending.delete(response.id);
|
|
406
|
+
if (response.error) {
|
|
407
|
+
const err = new Error(response.error.message);
|
|
408
|
+
err.code = response.error.code;
|
|
409
|
+
err.data = response.error.data;
|
|
410
|
+
entry.reject(err);
|
|
411
|
+
} else {
|
|
412
|
+
entry.resolve(response.result);
|
|
413
|
+
}
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if ("method" in data && !("id" in data && data.id)) {
|
|
417
|
+
const notification = data;
|
|
418
|
+
const set = this.handlers.get(notification.method);
|
|
419
|
+
if (set) {
|
|
420
|
+
for (const handler of set) {
|
|
421
|
+
handler(notification.params);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
};
|
|
584
427
|
|
|
585
|
-
// src/
|
|
586
|
-
var
|
|
587
|
-
|
|
588
|
-
|
|
428
|
+
// src/connect.ts
|
|
429
|
+
var READ_RESOURCE_METHOD = "resources/read";
|
|
430
|
+
var UPDATE_MODEL_CONTEXT_METHOD = "ui/update-model-context";
|
|
431
|
+
async function connect(options) {
|
|
432
|
+
const { name, version, autoResize = false, internal = false, forwardKeys } = options;
|
|
589
433
|
const transport = new SynapseTransport();
|
|
590
|
-
let hostInfo = null;
|
|
591
|
-
let currentHostContext = {};
|
|
592
|
-
let currentFontFaces;
|
|
593
|
-
function syncFontFaces(ctx) {
|
|
594
|
-
currentFontFaces = chunkRYWW6EHB_cjs.foldFontFaces(currentFontFaces, ctx);
|
|
595
|
-
return currentFontFaces;
|
|
596
|
-
}
|
|
597
|
-
function resolveTheme(ctx) {
|
|
598
|
-
const theme = chunkRYWW6EHB_cjs.extractTheme(ctx);
|
|
599
|
-
return currentFontFaces ? { ...theme, fontFaces: currentFontFaces } : theme;
|
|
600
|
-
}
|
|
601
|
-
let hostTasksCapability = null;
|
|
602
434
|
let destroyed = false;
|
|
603
|
-
|
|
604
|
-
let
|
|
435
|
+
let hostContext = {};
|
|
436
|
+
let hostInfo = { name: "unknown", version: "unknown" };
|
|
437
|
+
let isNimbleBrainHost = false;
|
|
438
|
+
let toolInfo = null;
|
|
439
|
+
let containerDimensions = null;
|
|
440
|
+
let hostTasksCapability;
|
|
605
441
|
let keyboard = null;
|
|
442
|
+
let fontFaces;
|
|
443
|
+
function resolveTheme() {
|
|
444
|
+
const theme = chunkTXJMGQYF_cjs.extractTheme(hostContext);
|
|
445
|
+
return fontFaces ? { ...theme, fontFaces } : theme;
|
|
446
|
+
}
|
|
447
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
448
|
+
const themeCallbacks = /* @__PURE__ */ new Set();
|
|
449
|
+
const hostContextCallbacks = /* @__PURE__ */ new Set();
|
|
450
|
+
const dataCallbacks = /* @__PURE__ */ new Set();
|
|
451
|
+
const actionCallbacks = /* @__PURE__ */ new Set();
|
|
452
|
+
const resizer = createResizer((method, params) => transport.send(method, params), autoResize);
|
|
453
|
+
resizer.measureAndSend();
|
|
606
454
|
const appCapabilities = {
|
|
607
455
|
tasks: {
|
|
608
456
|
cancel: {},
|
|
@@ -614,30 +462,58 @@ function createSynapse(options) {
|
|
|
614
462
|
appInfo: { name, version },
|
|
615
463
|
appCapabilities
|
|
616
464
|
};
|
|
617
|
-
const
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
465
|
+
const result = await transport.request(
|
|
466
|
+
extApps.INITIALIZE_METHOD,
|
|
467
|
+
initParams
|
|
468
|
+
);
|
|
469
|
+
if (result) {
|
|
470
|
+
const detected = chunkTXJMGQYF_cjs.detectHost(result);
|
|
471
|
+
isNimbleBrainHost = detected.isNimbleBrain;
|
|
472
|
+
hostInfo = {
|
|
473
|
+
name: result.hostInfo?.name ?? "unknown",
|
|
474
|
+
version: result.hostInfo?.version ?? "unknown"
|
|
475
|
+
};
|
|
476
|
+
const rawTasks = result.hostCapabilities?.tasks;
|
|
622
477
|
hostTasksCapability = rawTasks && typeof rawTasks === "object" && !Array.isArray(rawTasks) ? rawTasks : void 0;
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
478
|
+
const ctx = result.hostContext;
|
|
479
|
+
if (ctx) {
|
|
480
|
+
hostContext = ctx;
|
|
481
|
+
fontFaces = chunkTXJMGQYF_cjs.foldFontFaces(fontFaces, ctx);
|
|
482
|
+
if (ctx.toolInfo && typeof ctx.toolInfo === "object") {
|
|
483
|
+
toolInfo = { tool: ctx.toolInfo.tool ?? {} };
|
|
484
|
+
}
|
|
485
|
+
if (ctx.containerDimensions && typeof ctx.containerDimensions === "object") {
|
|
486
|
+
containerDimensions = ctx.containerDimensions;
|
|
487
|
+
}
|
|
488
|
+
const theme = resolveTheme();
|
|
489
|
+
chunkTXJMGQYF_cjs.applyTheme(theme.mode, theme.tokens, theme.fontFaces);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
if (forwardKeys && isNimbleBrainHost) {
|
|
493
|
+
keyboard = new KeyboardForwarder(transport, forwardKeys === true ? void 0 : forwardKeys);
|
|
494
|
+
}
|
|
495
|
+
function fanOutRaw(method, params) {
|
|
496
|
+
const set = handlers.get(method);
|
|
497
|
+
if (!set) return;
|
|
498
|
+
for (const handler of set) handler(params);
|
|
499
|
+
}
|
|
500
|
+
transport.onMessage(extApps.HOST_CONTEXT_CHANGED_METHOD, (params) => {
|
|
501
|
+
if (destroyed) return;
|
|
502
|
+
const ctx = params ?? {};
|
|
503
|
+
const prevTheme = resolveTheme();
|
|
504
|
+
hostContext = { ...hostContext, ...ctx };
|
|
505
|
+
fontFaces = chunkTXJMGQYF_cjs.foldFontFaces(fontFaces, ctx);
|
|
506
|
+
const nextTheme = resolveTheme();
|
|
507
|
+
chunkTXJMGQYF_cjs.applyTheme(nextTheme.mode, nextTheme.tokens, nextTheme.fontFaces);
|
|
508
|
+
for (const cb of hostContextCallbacks) cb(hostContext);
|
|
509
|
+
fanOutRaw(extApps.HOST_CONTEXT_CHANGED_METHOD, params);
|
|
510
|
+
if (!themesEqual(prevTheme, nextTheme)) {
|
|
511
|
+
for (const cb of themeCallbacks) cb(nextTheme);
|
|
626
512
|
}
|
|
627
|
-
for (const cb of hostContextCallbacks) cb(currentHostContext);
|
|
628
|
-
transport.send(extApps.INITIALIZED_METHOD, {});
|
|
629
|
-
keyboard = new KeyboardForwarder(transport, forwardKeys);
|
|
630
|
-
});
|
|
631
|
-
const unsubHostContext = transport.onMessage(extApps.HOST_CONTEXT_CHANGED_METHOD, (params) => {
|
|
632
|
-
currentHostContext = params ?? {};
|
|
633
|
-
const theme = chunkRYWW6EHB_cjs.extractTheme(currentHostContext);
|
|
634
|
-
chunkRYWW6EHB_cjs.applyTheme(theme.mode, theme.tokens, syncFontFaces(currentHostContext));
|
|
635
|
-
for (const cb of hostContextCallbacks) cb(currentHostContext);
|
|
636
513
|
});
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
const unsubData = transport.onMessage("synapse/data-changed", (params) => {
|
|
514
|
+
transport.onMessage(DATA_CHANGED_METHOD, (params) => {
|
|
515
|
+
if (destroyed) return;
|
|
516
|
+
fanOutRaw(DATA_CHANGED_METHOD, params);
|
|
641
517
|
if (!params) return;
|
|
642
518
|
const event = {
|
|
643
519
|
source: "agent",
|
|
@@ -646,119 +522,157 @@ function createSynapse(options) {
|
|
|
646
522
|
};
|
|
647
523
|
for (const cb of dataCallbacks) cb(event);
|
|
648
524
|
});
|
|
649
|
-
|
|
525
|
+
transport.onMessage(ACTION_METHOD, (params) => {
|
|
526
|
+
if (destroyed) return;
|
|
527
|
+
fanOutRaw(ACTION_METHOD, params);
|
|
650
528
|
if (!params || typeof params.type !== "string") return;
|
|
651
|
-
const
|
|
529
|
+
const action2 = {
|
|
652
530
|
type: params.type,
|
|
653
531
|
payload: params.payload ?? {},
|
|
654
532
|
requiresConfirmation: params.requiresConfirmation === true,
|
|
655
533
|
label: typeof params.label === "string" ? params.label : void 0
|
|
656
534
|
};
|
|
657
|
-
for (const cb of actionCallbacks) cb(
|
|
535
|
+
for (const cb of actionCallbacks) cb(action2);
|
|
658
536
|
});
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
537
|
+
const subscribedMethods = /* @__PURE__ */ new Set([
|
|
538
|
+
extApps.HOST_CONTEXT_CHANGED_METHOD,
|
|
539
|
+
DATA_CHANGED_METHOD,
|
|
540
|
+
ACTION_METHOD
|
|
541
|
+
]);
|
|
542
|
+
function ensureTransportSub(method) {
|
|
543
|
+
if (subscribedMethods.has(method)) return;
|
|
544
|
+
subscribedMethods.add(method);
|
|
545
|
+
const isToolResult = method === extApps.TOOL_RESULT_METHOD;
|
|
546
|
+
transport.onMessage(method, (params) => {
|
|
547
|
+
if (destroyed) return;
|
|
548
|
+
const set = handlers.get(method);
|
|
549
|
+
if (!set) return;
|
|
550
|
+
for (const handler of set) {
|
|
551
|
+
if (isToolResult) {
|
|
552
|
+
handler(parseToolResultParams(params));
|
|
553
|
+
} else {
|
|
554
|
+
handler(params);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
function subscribe(event, handler) {
|
|
560
|
+
switch (event) {
|
|
561
|
+
case "theme-changed":
|
|
562
|
+
themeCallbacks.add(handler);
|
|
563
|
+
return () => {
|
|
564
|
+
themeCallbacks.delete(handler);
|
|
565
|
+
};
|
|
566
|
+
case "host-context-changed":
|
|
567
|
+
hostContextCallbacks.add(handler);
|
|
568
|
+
return () => {
|
|
569
|
+
hostContextCallbacks.delete(handler);
|
|
570
|
+
};
|
|
571
|
+
case "data-changed":
|
|
572
|
+
dataCallbacks.add(handler);
|
|
573
|
+
return () => {
|
|
574
|
+
dataCallbacks.delete(handler);
|
|
575
|
+
};
|
|
576
|
+
case "action":
|
|
577
|
+
actionCallbacks.add(handler);
|
|
578
|
+
return () => {
|
|
579
|
+
actionCallbacks.delete(handler);
|
|
580
|
+
};
|
|
581
|
+
default: {
|
|
582
|
+
const method = resolveEventMethod(event);
|
|
583
|
+
if (!handlers.has(method)) handlers.set(method, /* @__PURE__ */ new Set());
|
|
584
|
+
handlers.get(method)?.add(handler);
|
|
585
|
+
ensureTransportSub(method);
|
|
586
|
+
return () => {
|
|
587
|
+
const set = handlers.get(method);
|
|
588
|
+
if (set) {
|
|
589
|
+
set.delete(handler);
|
|
590
|
+
if (set.size === 0) handlers.delete(method);
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
if (options.on) {
|
|
597
|
+
for (const [event, handler] of Object.entries(options.on)) {
|
|
598
|
+
if (typeof handler === "function") subscribe(event, handler);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
transport.send(extApps.INITIALIZED_METHOD, {});
|
|
602
|
+
const taskRouter = createTaskStatusRouter(transport);
|
|
603
|
+
const app = {
|
|
604
|
+
get theme() {
|
|
605
|
+
return resolveTheme();
|
|
606
|
+
},
|
|
607
|
+
get hostInfo() {
|
|
608
|
+
return { ...hostInfo };
|
|
609
|
+
},
|
|
610
|
+
get hostContext() {
|
|
611
|
+
return hostContext;
|
|
663
612
|
},
|
|
664
613
|
get isNimbleBrainHost() {
|
|
665
|
-
return
|
|
614
|
+
return isNimbleBrainHost;
|
|
615
|
+
},
|
|
616
|
+
get toolInfo() {
|
|
617
|
+
return toolInfo;
|
|
618
|
+
},
|
|
619
|
+
get containerDimensions() {
|
|
620
|
+
return containerDimensions;
|
|
666
621
|
},
|
|
667
622
|
get destroyed() {
|
|
668
623
|
return destroyed;
|
|
669
624
|
},
|
|
670
|
-
|
|
625
|
+
get supportsTasks() {
|
|
626
|
+
return hostTasksCapability?.requests?.tools?.call !== void 0;
|
|
627
|
+
},
|
|
628
|
+
on(event, handler) {
|
|
629
|
+
return subscribe(event, handler);
|
|
630
|
+
},
|
|
631
|
+
resize(width, height) {
|
|
632
|
+
resizer.resize(width, height);
|
|
633
|
+
},
|
|
634
|
+
openLink(url) {
|
|
635
|
+
if (destroyed) return;
|
|
636
|
+
const params = { url };
|
|
637
|
+
transport.request(extApps.OPEN_LINK_METHOD, params).catch(() => {
|
|
638
|
+
window.open(url, "_blank", "noopener");
|
|
639
|
+
});
|
|
640
|
+
},
|
|
641
|
+
updateModelContext(state, summary) {
|
|
642
|
+
if (destroyed) return;
|
|
643
|
+
const params = {
|
|
644
|
+
structuredContent: state,
|
|
645
|
+
...summary !== void 0 && {
|
|
646
|
+
content: [{ type: "text", text: summary }]
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
transport.send(UPDATE_MODEL_CONTEXT_METHOD, params);
|
|
650
|
+
},
|
|
651
|
+
async callTool(toolName, args, callOptions) {
|
|
652
|
+
const server = callOptions?.server ?? (internal ? name : void 0);
|
|
671
653
|
const params = {
|
|
672
654
|
name: toolName,
|
|
673
|
-
arguments: args ?? {}
|
|
655
|
+
arguments: args ?? {},
|
|
656
|
+
...server !== void 0 && { server }
|
|
674
657
|
};
|
|
675
|
-
|
|
676
|
-
params.server = name;
|
|
677
|
-
}
|
|
678
|
-
const raw = await transport.request("tools/call", params);
|
|
658
|
+
const raw = await transport.request(TOOLS_CALL_METHOD, params);
|
|
679
659
|
return parseToolResult(raw);
|
|
680
660
|
},
|
|
681
|
-
async
|
|
682
|
-
return callToolAsTask(
|
|
683
|
-
{
|
|
684
|
-
transport,
|
|
685
|
-
router: taskStatusRouter,
|
|
686
|
-
getHostTasksCapability: () => hostTasksCapability,
|
|
687
|
-
appName: name,
|
|
688
|
-
internalApp: internal
|
|
689
|
-
},
|
|
690
|
-
toolName,
|
|
691
|
-
args,
|
|
692
|
-
options2
|
|
693
|
-
);
|
|
694
|
-
},
|
|
695
|
-
async readResource(uri) {
|
|
696
|
-
const params = { uri };
|
|
661
|
+
async readServerResource(params) {
|
|
697
662
|
const raw = await transport.request(
|
|
698
|
-
|
|
663
|
+
READ_RESOURCE_METHOD,
|
|
699
664
|
params
|
|
700
665
|
);
|
|
701
666
|
return raw;
|
|
702
667
|
},
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
return () => {
|
|
706
|
-
dataCallbacks.delete(callback);
|
|
707
|
-
};
|
|
708
|
-
},
|
|
709
|
-
onAction(callback) {
|
|
710
|
-
actionCallbacks.add(callback);
|
|
711
|
-
return () => {
|
|
712
|
-
actionCallbacks.delete(callback);
|
|
713
|
-
};
|
|
714
|
-
},
|
|
715
|
-
getHostContext() {
|
|
716
|
-
return currentHostContext;
|
|
717
|
-
},
|
|
718
|
-
onHostContextChanged(callback) {
|
|
719
|
-
hostContextCallbacks.add(callback);
|
|
720
|
-
return () => {
|
|
721
|
-
hostContextCallbacks.delete(callback);
|
|
722
|
-
};
|
|
723
|
-
},
|
|
724
|
-
getTheme() {
|
|
725
|
-
return resolveTheme(currentHostContext);
|
|
726
|
-
},
|
|
727
|
-
// Selector over `onHostContextChanged`: only fires when the *derived*
|
|
728
|
-
// theme actually changes, so theme subscribers don't see spurious
|
|
729
|
-
// updates when other host-context fields (e.g. workspace) change.
|
|
730
|
-
//
|
|
731
|
-
// Subscriber timing matters:
|
|
732
|
-
// - Subscribed BEFORE handshake: `prev = null` sentinel. The first
|
|
733
|
-
// fire (the handshake dispatch) always invokes the callback,
|
|
734
|
-
// even if the host's theme happens to derive to the default.
|
|
735
|
-
// Otherwise consumers using `onThemeChanged` as their init
|
|
736
|
-
// signal would silently miss it.
|
|
737
|
-
// - Subscribed AFTER handshake: `prev` is pre-seeded with the
|
|
738
|
-
// current derived theme, so a workspace-only `host-context-changed`
|
|
739
|
-
// notification correctly filters as a no-op.
|
|
740
|
-
onThemeChanged(callback) {
|
|
741
|
-
let prev = hostInfo !== null ? resolveTheme(currentHostContext) : null;
|
|
742
|
-
const wrapped = (ctx) => {
|
|
743
|
-
const next = resolveTheme(ctx);
|
|
744
|
-
if (prev !== null && themesEqual(prev, next)) return;
|
|
745
|
-
prev = next;
|
|
746
|
-
callback(next);
|
|
747
|
-
};
|
|
748
|
-
hostContextCallbacks.add(wrapped);
|
|
749
|
-
return () => {
|
|
750
|
-
hostContextCallbacks.delete(wrapped);
|
|
751
|
-
};
|
|
752
|
-
},
|
|
753
|
-
action(action, params) {
|
|
754
|
-
if (!isNB()) return;
|
|
755
|
-
transport.send("synapse/action", { action, ...params });
|
|
756
|
-
},
|
|
757
|
-
chat(message, context) {
|
|
668
|
+
sendMessage(text, context) {
|
|
669
|
+
if (destroyed) return;
|
|
758
670
|
const textBlock = {
|
|
759
671
|
type: "text",
|
|
760
|
-
text
|
|
761
|
-
|
|
672
|
+
text,
|
|
673
|
+
// `_meta.context` is a NimbleBrain convention; other hosts ignore it,
|
|
674
|
+
// but there is no reason to spend the bytes off one.
|
|
675
|
+
...isNimbleBrainHost && context && { _meta: { context } }
|
|
762
676
|
};
|
|
763
677
|
const params = {
|
|
764
678
|
role: "user",
|
|
@@ -766,80 +680,87 @@ function createSynapse(options) {
|
|
|
766
680
|
};
|
|
767
681
|
transport.send(extApps.MESSAGE_METHOD, params);
|
|
768
682
|
},
|
|
769
|
-
setVisibleState(state, summary) {
|
|
770
|
-
if (stateTimer) clearTimeout(stateTimer);
|
|
771
|
-
stateTimer = setTimeout(() => {
|
|
772
|
-
const params = {
|
|
773
|
-
structuredContent: state,
|
|
774
|
-
...summary !== void 0 && {
|
|
775
|
-
content: [{ type: "text", text: summary }]
|
|
776
|
-
}
|
|
777
|
-
};
|
|
778
|
-
transport.send("ui/update-model-context", params);
|
|
779
|
-
stateTimer = null;
|
|
780
|
-
}, 250);
|
|
781
|
-
},
|
|
782
|
-
downloadFile(filename, content, mimeType) {
|
|
783
|
-
const resolvedMime = mimeType || (content instanceof Blob ? content.type : "") || "application/octet-stream";
|
|
784
|
-
const blob = content instanceof Blob ? content : new Blob([content], { type: resolvedMime });
|
|
785
|
-
transport.send("synapse/download-file", {
|
|
786
|
-
data: blob,
|
|
787
|
-
filename,
|
|
788
|
-
mimeType: resolvedMime
|
|
789
|
-
});
|
|
790
|
-
},
|
|
791
|
-
openLink(url) {
|
|
792
|
-
const params = { url };
|
|
793
|
-
transport.request(extApps.OPEN_LINK_METHOD, params).catch(() => {
|
|
794
|
-
window.open(url, "_blank", "noopener");
|
|
795
|
-
});
|
|
796
|
-
},
|
|
797
|
-
async pickFile(options2) {
|
|
798
|
-
if (!isNB()) {
|
|
799
|
-
throw new Error("pickFile is not supported in this host");
|
|
800
|
-
}
|
|
801
|
-
const result = await requestFile(transport, options2, false);
|
|
802
|
-
if (result === null) return null;
|
|
803
|
-
return Array.isArray(result) ? result[0] ?? null : result;
|
|
804
|
-
},
|
|
805
|
-
async pickFiles(options2) {
|
|
806
|
-
if (!isNB()) {
|
|
807
|
-
throw new Error("pickFiles is not supported in this host");
|
|
808
|
-
}
|
|
809
|
-
const result = await requestFile(transport, options2, true);
|
|
810
|
-
if (result === null) return [];
|
|
811
|
-
return Array.isArray(result) ? result : [result];
|
|
812
|
-
},
|
|
813
|
-
_onMessage(method, callback) {
|
|
814
|
-
return transport.onMessage(method, callback);
|
|
815
|
-
},
|
|
816
|
-
_request(method, params) {
|
|
817
|
-
return transport.request(method, params);
|
|
818
|
-
},
|
|
819
|
-
get _hostTasksCapability() {
|
|
820
|
-
return hostTasksCapability;
|
|
821
|
-
},
|
|
822
683
|
destroy() {
|
|
823
684
|
if (destroyed) return;
|
|
824
685
|
destroyed = true;
|
|
825
|
-
if (stateTimer) clearTimeout(stateTimer);
|
|
826
686
|
keyboard?.destroy();
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
687
|
+
resizer.destroy();
|
|
688
|
+
taskRouter.dispose();
|
|
689
|
+
handlers.clear();
|
|
690
|
+
themeCallbacks.clear();
|
|
831
691
|
hostContextCallbacks.clear();
|
|
832
692
|
dataCallbacks.clear();
|
|
833
693
|
actionCallbacks.clear();
|
|
834
694
|
transport.destroy();
|
|
835
695
|
}
|
|
836
696
|
};
|
|
837
|
-
|
|
697
|
+
registerInternals(app, {
|
|
698
|
+
send(method, params) {
|
|
699
|
+
if (destroyed) return;
|
|
700
|
+
transport.send(method, params);
|
|
701
|
+
},
|
|
702
|
+
request(method, params) {
|
|
703
|
+
return transport.request(method, params);
|
|
704
|
+
},
|
|
705
|
+
onMessage(method, handler) {
|
|
706
|
+
return transport.onMessage(method, handler);
|
|
707
|
+
},
|
|
708
|
+
taskRouter,
|
|
709
|
+
get hostTasksCapability() {
|
|
710
|
+
return hostTasksCapability;
|
|
711
|
+
},
|
|
712
|
+
appName: name,
|
|
713
|
+
internalApp: internal
|
|
714
|
+
});
|
|
715
|
+
return app;
|
|
716
|
+
}
|
|
717
|
+
function themesEqual(a, b) {
|
|
718
|
+
if (a.mode !== b.mode) return false;
|
|
719
|
+
if (chunkTXJMGQYF_cjs.fontFacesKey(a.fontFaces) !== chunkTXJMGQYF_cjs.fontFacesKey(b.fontFaces)) return false;
|
|
720
|
+
const aKeys = Object.keys(a.tokens);
|
|
721
|
+
const bKeys = Object.keys(b.tokens);
|
|
722
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
723
|
+
for (const k of aKeys) {
|
|
724
|
+
if (a.tokens[k] !== b.tokens[k]) return false;
|
|
725
|
+
}
|
|
726
|
+
return true;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// src/extensions.ts
|
|
730
|
+
var DEFAULT_MAX_FILE_SIZE = 26214400;
|
|
731
|
+
function action(app, name, params) {
|
|
732
|
+
if (!app.isNimbleBrainHost) return;
|
|
733
|
+
internalsFor(app).send(ACTION_METHOD, { action: name, ...params });
|
|
734
|
+
}
|
|
735
|
+
function downloadFile(app, filename, content, mimeType) {
|
|
736
|
+
const resolvedMime = mimeType || (content instanceof Blob ? content.type : "") || "application/octet-stream";
|
|
737
|
+
const blob = content instanceof Blob ? content : new Blob([content], { type: resolvedMime });
|
|
738
|
+
internalsFor(app).send(DOWNLOAD_FILE_METHOD, {
|
|
739
|
+
data: blob,
|
|
740
|
+
filename,
|
|
741
|
+
mimeType: resolvedMime
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
async function pickFile(app, options) {
|
|
745
|
+
if (!app.isNimbleBrainHost) {
|
|
746
|
+
throw new Error("pickFile is not supported in this host");
|
|
747
|
+
}
|
|
748
|
+
const result = await requestFile(app, options, false);
|
|
749
|
+
if (result === null) return null;
|
|
750
|
+
return Array.isArray(result) ? result[0] ?? null : result;
|
|
751
|
+
}
|
|
752
|
+
async function pickFiles(app, options) {
|
|
753
|
+
if (!app.isNimbleBrainHost) {
|
|
754
|
+
throw new Error("pickFiles is not supported in this host");
|
|
755
|
+
}
|
|
756
|
+
const result = await requestFile(app, options, true);
|
|
757
|
+
if (result === null) return [];
|
|
758
|
+
return Array.isArray(result) ? result : [result];
|
|
838
759
|
}
|
|
839
|
-
async function requestFile(
|
|
840
|
-
const result = await
|
|
760
|
+
async function requestFile(app, options, multiple) {
|
|
761
|
+
const result = await internalsFor(app).request(REQUEST_FILE_METHOD, {
|
|
841
762
|
accept: options?.accept,
|
|
842
|
-
maxSize: options?.maxSize ??
|
|
763
|
+
maxSize: options?.maxSize ?? DEFAULT_MAX_FILE_SIZE,
|
|
843
764
|
multiple
|
|
844
765
|
});
|
|
845
766
|
if (result == null) return null;
|
|
@@ -856,19 +777,12 @@ function validateFileResult(value) {
|
|
|
856
777
|
}
|
|
857
778
|
return value;
|
|
858
779
|
}
|
|
859
|
-
function themesEqual(a, b) {
|
|
860
|
-
if (a.mode !== b.mode || a.primaryColor !== b.primaryColor) return false;
|
|
861
|
-
if (chunkRYWW6EHB_cjs.fontFacesKey(a.fontFaces) !== chunkRYWW6EHB_cjs.fontFacesKey(b.fontFaces)) return false;
|
|
862
|
-
const aKeys = Object.keys(a.tokens);
|
|
863
|
-
const bKeys = Object.keys(b.tokens);
|
|
864
|
-
if (aKeys.length !== bKeys.length) return false;
|
|
865
|
-
for (const k of aKeys) {
|
|
866
|
-
if (a.tokens[k] !== b.tokens[k]) return false;
|
|
867
|
-
}
|
|
868
|
-
return true;
|
|
869
|
-
}
|
|
870
780
|
|
|
781
|
+
exports.action = action;
|
|
782
|
+
exports.callToolAsTask = callToolAsTask;
|
|
871
783
|
exports.connect = connect;
|
|
872
|
-
exports.
|
|
873
|
-
|
|
874
|
-
|
|
784
|
+
exports.downloadFile = downloadFile;
|
|
785
|
+
exports.pickFile = pickFile;
|
|
786
|
+
exports.pickFiles = pickFiles;
|
|
787
|
+
//# sourceMappingURL=chunk-FDMRJZKT.cjs.map
|
|
788
|
+
//# sourceMappingURL=chunk-FDMRJZKT.cjs.map
|