@nimblebrain/synapse 0.18.0 → 0.20.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 +32 -37
- package/dist/check-JEM5PN64.cjs +435 -0
- package/dist/check-JEM5PN64.cjs.map +1 -0
- package/dist/check-YDZUQT6A.js +429 -0
- package/dist/check-YDZUQT6A.js.map +1 -0
- package/dist/{chunk-VDQZQDU3.cjs → chunk-BNF352SA.cjs} +56 -145
- package/dist/chunk-BNF352SA.cjs.map +1 -0
- package/dist/{chunk-HKRTDGXN.js → chunk-DJS2FKBN.js} +21 -89
- package/dist/chunk-DJS2FKBN.js.map +1 -0
- package/dist/chunk-H3INUKA3.js +32 -0
- package/dist/chunk-H3INUKA3.js.map +1 -0
- package/dist/{chunk-FB7GPBEM.cjs → chunk-HQLSVUOR.cjs} +193 -314
- package/dist/chunk-HQLSVUOR.cjs.map +1 -0
- package/dist/chunk-ISV6HFQE.cjs +40 -0
- package/dist/chunk-ISV6HFQE.cjs.map +1 -0
- package/dist/{chunk-3YSXPBEQ.js → chunk-TR2YNWZ5.js} +190 -313
- package/dist/chunk-TR2YNWZ5.js.map +1 -0
- package/dist/{chunk-ZLASWV4N.js → chunk-UKP4W6DI.js} +56 -145
- package/dist/chunk-UKP4W6DI.js.map +1 -0
- package/dist/{chunk-LPWEQCZV.cjs → chunk-YSL7KJNU.cjs} +21 -92
- package/dist/chunk-YSL7KJNU.cjs.map +1 -0
- package/dist/codegen/cli.cjs +38 -1
- package/dist/codegen/cli.cjs.map +1 -1
- package/dist/codegen/cli.js +38 -1
- package/dist/codegen/cli.js.map +1 -1
- package/dist/codegen/index.d.cts +1 -1
- package/dist/codegen/index.d.ts +1 -1
- package/dist/connect.iife.global.js +66 -43
- package/dist/{detect-BHYg26_d.d.cts → detect-DVGaL2bH.d.cts} +39 -33
- package/dist/{detect-Bf8Q_0dK.d.ts → detect-DVGaL2bH.d.ts} +39 -33
- package/dist/host/index.cjs +17 -17
- package/dist/host/index.d.cts +11 -27
- package/dist/host/index.d.ts +11 -27
- package/dist/host/index.js +2 -2
- package/dist/index.cjs +52 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -31
- package/dist/index.d.ts +104 -31
- package/dist/index.js +34 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +11 -10
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +49 -12
- package/dist/react/index.d.ts +49 -12
- package/dist/react/index.js +6 -5
- package/dist/react/index.js.map +1 -1
- package/dist/{server-QIYIJHD5.cjs → server-BR5MNFOB.cjs} +40 -29
- package/dist/server-BR5MNFOB.cjs.map +1 -0
- package/dist/{server-5N76YCWC.js → server-OOEEWAEG.js} +40 -30
- package/dist/server-OOEEWAEG.js.map +1 -0
- package/dist/synapse-runtime.iife.global.js +66 -43
- package/dist/synapse-ui.iife.global.js +4 -4
- package/dist/{types-uEO4VFJ2.d.cts → types-BxPfGHKO.d.cts} +48 -125
- package/dist/{types-uEO4VFJ2.d.ts → types-BxPfGHKO.d.ts} +48 -125
- package/dist/vite/index.cjs +77 -33
- package/dist/vite/index.cjs.map +1 -1
- package/dist/vite/index.d.cts +5 -1
- package/dist/vite/index.d.ts +5 -1
- package/dist/vite/index.js +77 -33
- package/dist/vite/index.js.map +1 -1
- package/package.json +12 -6
- package/dist/chunk-3YSXPBEQ.js.map +0 -1
- package/dist/chunk-FB7GPBEM.cjs.map +0 -1
- package/dist/chunk-HKRTDGXN.js.map +0 -1
- package/dist/chunk-LPWEQCZV.cjs.map +0 -1
- package/dist/chunk-VDQZQDU3.cjs.map +0 -1
- package/dist/chunk-ZLASWV4N.js.map +0 -1
- package/dist/server-5N76YCWC.js.map +0 -1
- package/dist/server-QIYIJHD5.cjs.map +0 -1
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkYSL7KJNU_cjs = require('./chunk-YSL7KJNU.cjs');
|
|
4
|
+
var chunkISV6HFQE_cjs = require('./chunk-ISV6HFQE.cjs');
|
|
4
5
|
var extApps = require('@modelcontextprotocol/ext-apps');
|
|
6
|
+
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
7
|
+
|
|
8
|
+
// src/errors.ts
|
|
9
|
+
var HostCapabilityError = class extends Error {
|
|
10
|
+
capability;
|
|
11
|
+
constructor(feature, capability) {
|
|
12
|
+
super(`${feature} is not supported in this host: it did not declare ${capability}`);
|
|
13
|
+
this.name = "HostCapabilityError";
|
|
14
|
+
this.capability = capability;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
5
17
|
|
|
6
18
|
// src/internals.ts
|
|
7
19
|
var INTERNALS = /* @__PURE__ */ new WeakMap();
|
|
@@ -65,14 +77,18 @@ function parseCallToolResult(result) {
|
|
|
65
77
|
}
|
|
66
78
|
|
|
67
79
|
// src/task-handle.ts
|
|
68
|
-
var
|
|
80
|
+
var TASKS_EXTENSION_ID = "io.modelcontextprotocol/tasks";
|
|
81
|
+
function readHostTasksCapability(capabilities) {
|
|
82
|
+
const entry = capabilities?.experimental?.[TASKS_EXTENSION_ID];
|
|
83
|
+
return entry && typeof entry === "object" && !Array.isArray(entry) ? entry : void 0;
|
|
84
|
+
}
|
|
69
85
|
var TASKS_GET_METHOD = "tasks/get";
|
|
70
86
|
var TASKS_RESULT_METHOD = "tasks/result";
|
|
71
87
|
var TASKS_CANCEL_METHOD = "tasks/cancel";
|
|
72
88
|
var TASKS_STATUS_NOTIFICATION_METHOD = "notifications/tasks/status";
|
|
73
|
-
function createTaskStatusRouter(
|
|
89
|
+
function createTaskStatusRouter(subscribe) {
|
|
74
90
|
const listeners = /* @__PURE__ */ new Map();
|
|
75
|
-
const unsub =
|
|
91
|
+
const unsub = subscribe(TASKS_STATUS_NOTIFICATION_METHOD, (rawParams) => {
|
|
76
92
|
if (!rawParams) return;
|
|
77
93
|
const params = rawParams;
|
|
78
94
|
const taskId = params.taskId;
|
|
@@ -111,21 +127,20 @@ async function callToolAsTask(app, toolName, args, options) {
|
|
|
111
127
|
const deps = internalsFor(app);
|
|
112
128
|
const hostTasks = deps.hostTasksCapability;
|
|
113
129
|
if (!hostTasks?.requests?.tools?.call) {
|
|
114
|
-
throw new
|
|
115
|
-
"callToolAsTask
|
|
130
|
+
throw new HostCapabilityError(
|
|
131
|
+
"callToolAsTask",
|
|
132
|
+
`${TASKS_EXTENSION_ID} with requests.tools.call`
|
|
116
133
|
);
|
|
117
134
|
}
|
|
118
135
|
const taskParam = {};
|
|
119
136
|
if (options?.ttl !== void 0) taskParam.ttl = options.ttl;
|
|
120
|
-
const crossServer = options?.internal ?? deps.internalApp;
|
|
121
137
|
const callParams = {
|
|
122
138
|
name: toolName,
|
|
123
139
|
arguments: args ?? {},
|
|
124
|
-
task: taskParam
|
|
125
|
-
...crossServer ? { server: deps.appName } : {}
|
|
140
|
+
task: taskParam
|
|
126
141
|
};
|
|
127
142
|
const raw = await deps.request(
|
|
128
|
-
TOOLS_CALL_METHOD,
|
|
143
|
+
chunkISV6HFQE_cjs.TOOLS_CALL_METHOD,
|
|
129
144
|
callParams
|
|
130
145
|
);
|
|
131
146
|
const createResult = raw;
|
|
@@ -234,32 +249,18 @@ function parseToolResultParams(params) {
|
|
|
234
249
|
}
|
|
235
250
|
return { content: rawContent ?? null, structuredContent: null, raw };
|
|
236
251
|
}
|
|
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
|
|
|
252
253
|
// src/keyboard.ts
|
|
253
254
|
var KeyboardForwarder = class {
|
|
254
255
|
listener;
|
|
255
256
|
destroyed = false;
|
|
256
|
-
constructor(
|
|
257
|
+
constructor(send, customKeys) {
|
|
257
258
|
const config = customKeys ?? null;
|
|
258
259
|
this.listener = (event) => {
|
|
259
260
|
if (this.destroyed) return;
|
|
260
261
|
if (this.shouldForward(event, config)) {
|
|
261
262
|
event.preventDefault();
|
|
262
|
-
|
|
263
|
+
send(chunkISV6HFQE_cjs.KEYDOWN_METHOD, {
|
|
263
264
|
key: event.key,
|
|
264
265
|
ctrlKey: event.ctrlKey,
|
|
265
266
|
metaKey: event.metaKey,
|
|
@@ -291,271 +292,125 @@ var KeyboardForwarder = class {
|
|
|
291
292
|
return false;
|
|
292
293
|
}
|
|
293
294
|
};
|
|
294
|
-
|
|
295
|
-
// src/resize.ts
|
|
296
295
|
function createResizer(send, autoResize) {
|
|
297
296
|
let destroyed = false;
|
|
298
297
|
let observer = null;
|
|
299
|
-
let rafId = null;
|
|
300
298
|
function measureAndSend() {
|
|
301
299
|
if (destroyed) return;
|
|
302
300
|
const width = document.body.scrollWidth;
|
|
303
301
|
const height = document.body.scrollHeight;
|
|
304
|
-
send(
|
|
302
|
+
send(extApps.SIZE_CHANGED_METHOD, { width, height });
|
|
305
303
|
}
|
|
306
304
|
function resize(width, height) {
|
|
307
305
|
if (destroyed) return;
|
|
308
306
|
if (width !== void 0 && height !== void 0) {
|
|
309
|
-
send(
|
|
307
|
+
send(extApps.SIZE_CHANGED_METHOD, { width, height });
|
|
310
308
|
} else {
|
|
311
309
|
measureAndSend();
|
|
312
310
|
}
|
|
313
311
|
}
|
|
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
312
|
function destroy() {
|
|
326
313
|
if (destroyed) return;
|
|
327
314
|
destroyed = true;
|
|
328
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
329
315
|
observer?.disconnect();
|
|
330
316
|
observer = null;
|
|
331
317
|
}
|
|
332
318
|
return { resize, measureAndSend, destroy };
|
|
333
319
|
}
|
|
334
320
|
|
|
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
|
-
};
|
|
427
|
-
|
|
428
321
|
// src/connect.ts
|
|
429
|
-
var
|
|
430
|
-
var
|
|
322
|
+
var NIMBLEBRAIN_HOST = "nimblebrain";
|
|
323
|
+
var CHAT_CONTEXT_META_KEY = "ai.nimblebrain/context";
|
|
324
|
+
var NO_DEADLINE = { timeout: 2147483647 };
|
|
325
|
+
var MAPPED_EVENTS = [
|
|
326
|
+
["toolinput", extApps.TOOL_INPUT_METHOD],
|
|
327
|
+
["toolinputpartial", extApps.TOOL_INPUT_PARTIAL_METHOD],
|
|
328
|
+
["toolresult", extApps.TOOL_RESULT_METHOD],
|
|
329
|
+
["toolcancelled", extApps.TOOL_CANCELLED_METHOD]
|
|
330
|
+
];
|
|
431
331
|
async function connect(options) {
|
|
432
|
-
const { name, version, autoResize = false,
|
|
433
|
-
const transport = new SynapseTransport();
|
|
332
|
+
const { name, version, autoResize = false, forwardKeys } = options;
|
|
434
333
|
let destroyed = false;
|
|
435
|
-
let hostContext = {};
|
|
436
334
|
let hostInfo = { name: "unknown", version: "unknown" };
|
|
437
335
|
let isNimbleBrainHost = false;
|
|
438
336
|
let toolInfo = null;
|
|
439
337
|
let containerDimensions = null;
|
|
338
|
+
let hostCapabilities = {};
|
|
440
339
|
let hostTasksCapability;
|
|
441
340
|
let keyboard = null;
|
|
442
|
-
let
|
|
443
|
-
function resolveTheme() {
|
|
444
|
-
const theme = chunkLPWEQCZV_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();
|
|
341
|
+
let appliedTheme = { mode: "light", tokens: {} };
|
|
454
342
|
const appCapabilities = {
|
|
455
343
|
tasks: {
|
|
456
344
|
cancel: {},
|
|
457
345
|
requests: { tools: { call: {} } }
|
|
458
346
|
}
|
|
459
347
|
};
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
};
|
|
465
|
-
const result = await transport.request(
|
|
466
|
-
extApps.INITIALIZE_METHOD,
|
|
467
|
-
initParams
|
|
348
|
+
const client = new extApps.App(
|
|
349
|
+
{ name, version },
|
|
350
|
+
appCapabilities,
|
|
351
|
+
{ autoResize }
|
|
468
352
|
);
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
version: result.hostInfo?.version ?? "unknown"
|
|
475
|
-
};
|
|
476
|
-
const rawTasks = result.hostCapabilities?.tasks;
|
|
477
|
-
hostTasksCapability = rawTasks && typeof rawTasks === "object" && !Array.isArray(rawTasks) ? rawTasks : void 0;
|
|
478
|
-
const ctx = result.hostContext;
|
|
479
|
-
if (ctx) {
|
|
480
|
-
hostContext = ctx;
|
|
481
|
-
fontFaces = chunkLPWEQCZV_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
|
-
chunkLPWEQCZV_cjs.applyTheme(theme.mode, theme.tokens, theme.fontFaces);
|
|
490
|
-
}
|
|
353
|
+
function currentContext() {
|
|
354
|
+
return client.getHostContext() ?? {};
|
|
355
|
+
}
|
|
356
|
+
function resolveTheme() {
|
|
357
|
+
return chunkYSL7KJNU_cjs.extractTheme(currentContext());
|
|
491
358
|
}
|
|
492
|
-
|
|
493
|
-
|
|
359
|
+
function applyFontsFrom(ctx) {
|
|
360
|
+
const css = chunkYSL7KJNU_cjs.extractHostFontCss(ctx);
|
|
361
|
+
if (css !== void 0 && typeof document !== "undefined") extApps.applyHostFonts(css);
|
|
494
362
|
}
|
|
495
|
-
function
|
|
363
|
+
function applyResolvedTheme() {
|
|
364
|
+
const theme = resolveTheme();
|
|
365
|
+
chunkYSL7KJNU_cjs.applyTheme(theme.mode, theme.tokens);
|
|
366
|
+
appliedTheme = theme;
|
|
367
|
+
return theme;
|
|
368
|
+
}
|
|
369
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
370
|
+
const themeCallbacks = /* @__PURE__ */ new Set();
|
|
371
|
+
const hostContextCallbacks = /* @__PURE__ */ new Set();
|
|
372
|
+
function fanOut(method, payload) {
|
|
496
373
|
const set = handlers.get(method);
|
|
497
374
|
if (!set) return;
|
|
498
|
-
for (const handler of set) handler(
|
|
375
|
+
for (const handler of set) handler(payload);
|
|
376
|
+
}
|
|
377
|
+
function sendRaw(method, params) {
|
|
378
|
+
if (destroyed) return;
|
|
379
|
+
void client.notification({ method, params }).catch(() => {
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
function requestRaw(method, params) {
|
|
383
|
+
return client.request({ method, params }, types_js.ResultSchema, NO_DEADLINE);
|
|
384
|
+
}
|
|
385
|
+
for (const [event, method] of MAPPED_EVENTS) {
|
|
386
|
+
client.addEventListener(event, (params) => {
|
|
387
|
+
if (destroyed) return;
|
|
388
|
+
fanOut(
|
|
389
|
+
method,
|
|
390
|
+
method === extApps.TOOL_RESULT_METHOD ? parseToolResultParams(params) : params
|
|
391
|
+
);
|
|
392
|
+
});
|
|
499
393
|
}
|
|
500
|
-
|
|
394
|
+
client.addEventListener("hostcontextchanged", (params) => {
|
|
501
395
|
if (destroyed) return;
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
for (const cb of hostContextCallbacks) cb(hostContext);
|
|
509
|
-
fanOutRaw(extApps.HOST_CONTEXT_CHANGED_METHOD, params);
|
|
396
|
+
const prevTheme = appliedTheme;
|
|
397
|
+
applyFontsFrom(params);
|
|
398
|
+
const nextTheme = applyResolvedTheme();
|
|
399
|
+
const merged = currentContext();
|
|
400
|
+
for (const cb of hostContextCallbacks) cb(merged);
|
|
401
|
+
fanOut(extApps.HOST_CONTEXT_CHANGED_METHOD, params);
|
|
510
402
|
if (!themesEqual(prevTheme, nextTheme)) {
|
|
511
403
|
for (const cb of themeCallbacks) cb(nextTheme);
|
|
512
404
|
}
|
|
513
405
|
});
|
|
514
|
-
|
|
515
|
-
if (destroyed)
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
source: "agent",
|
|
520
|
-
server: params.server ?? "",
|
|
521
|
-
tool: params.tool ?? ""
|
|
522
|
-
};
|
|
523
|
-
for (const cb of dataCallbacks) cb(event);
|
|
524
|
-
});
|
|
525
|
-
transport.onMessage(ACTION_METHOD, (params) => {
|
|
406
|
+
client.onteardown = (params) => {
|
|
407
|
+
if (!destroyed) fanOut(extApps.RESOURCE_TEARDOWN_METHOD, params);
|
|
408
|
+
return {};
|
|
409
|
+
};
|
|
410
|
+
client.fallbackNotificationHandler = async (notification) => {
|
|
526
411
|
if (destroyed) return;
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
const action2 = {
|
|
530
|
-
type: params.type,
|
|
531
|
-
payload: params.payload ?? {},
|
|
532
|
-
requiresConfirmation: params.requiresConfirmation === true,
|
|
533
|
-
label: typeof params.label === "string" ? params.label : void 0
|
|
534
|
-
};
|
|
535
|
-
for (const cb of actionCallbacks) cb(action2);
|
|
536
|
-
});
|
|
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
|
-
}
|
|
412
|
+
fanOut(notification.method, notification.params);
|
|
413
|
+
};
|
|
559
414
|
function subscribe(event, handler) {
|
|
560
415
|
switch (event) {
|
|
561
416
|
case "theme-changed":
|
|
@@ -568,21 +423,10 @@ async function connect(options) {
|
|
|
568
423
|
return () => {
|
|
569
424
|
hostContextCallbacks.delete(handler);
|
|
570
425
|
};
|
|
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
426
|
default: {
|
|
582
|
-
const method = resolveEventMethod(event);
|
|
427
|
+
const method = chunkISV6HFQE_cjs.resolveEventMethod(event);
|
|
583
428
|
if (!handlers.has(method)) handlers.set(method, /* @__PURE__ */ new Set());
|
|
584
429
|
handlers.get(method)?.add(handler);
|
|
585
|
-
ensureTransportSub(method);
|
|
586
430
|
return () => {
|
|
587
431
|
const set = handlers.get(method);
|
|
588
432
|
if (set) {
|
|
@@ -598,8 +442,36 @@ async function connect(options) {
|
|
|
598
442
|
if (typeof handler === "function") subscribe(event, handler);
|
|
599
443
|
}
|
|
600
444
|
}
|
|
601
|
-
|
|
602
|
-
const
|
|
445
|
+
await client.connect();
|
|
446
|
+
const hostVersion = client.getHostVersion();
|
|
447
|
+
hostInfo = {
|
|
448
|
+
name: hostVersion?.name ?? "unknown",
|
|
449
|
+
version: hostVersion?.version ?? "unknown"
|
|
450
|
+
};
|
|
451
|
+
isNimbleBrainHost = hostInfo.name === NIMBLEBRAIN_HOST;
|
|
452
|
+
hostCapabilities = client.getHostCapabilities() ?? {};
|
|
453
|
+
hostTasksCapability = readHostTasksCapability(hostCapabilities);
|
|
454
|
+
const initialContext = client.getHostContext();
|
|
455
|
+
if (initialContext) {
|
|
456
|
+
if (initialContext.toolInfo && typeof initialContext.toolInfo === "object") {
|
|
457
|
+
toolInfo = {
|
|
458
|
+
tool: initialContext.toolInfo.tool ?? {}
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
if (initialContext.containerDimensions && typeof initialContext.containerDimensions === "object") {
|
|
462
|
+
containerDimensions = initialContext.containerDimensions;
|
|
463
|
+
}
|
|
464
|
+
applyFontsFrom(initialContext);
|
|
465
|
+
applyResolvedTheme();
|
|
466
|
+
}
|
|
467
|
+
if (forwardKeys && hostCapabilities.experimental?.[chunkISV6HFQE_cjs.NIMBLEBRAIN_EXTENSIONS.keydown.capability] !== void 0) {
|
|
468
|
+
keyboard = new KeyboardForwarder(sendRaw, forwardKeys === true ? void 0 : forwardKeys);
|
|
469
|
+
}
|
|
470
|
+
const resizer = createResizer(sendRaw);
|
|
471
|
+
if (!autoResize) resizer.measureAndSend();
|
|
472
|
+
const taskRouter = createTaskStatusRouter(
|
|
473
|
+
(method, handler) => subscribe(method, handler)
|
|
474
|
+
);
|
|
603
475
|
const app = {
|
|
604
476
|
get theme() {
|
|
605
477
|
return resolveTheme();
|
|
@@ -608,7 +480,10 @@ async function connect(options) {
|
|
|
608
480
|
return { ...hostInfo };
|
|
609
481
|
},
|
|
610
482
|
get hostContext() {
|
|
611
|
-
return
|
|
483
|
+
return currentContext();
|
|
484
|
+
},
|
|
485
|
+
get hostCapabilities() {
|
|
486
|
+
return hostCapabilities;
|
|
612
487
|
},
|
|
613
488
|
get isNimbleBrainHost() {
|
|
614
489
|
return isNimbleBrainHost;
|
|
@@ -633,52 +508,62 @@ async function connect(options) {
|
|
|
633
508
|
},
|
|
634
509
|
openLink(url) {
|
|
635
510
|
if (destroyed) return;
|
|
511
|
+
if (!hostCapabilities.openLinks) {
|
|
512
|
+
window.open(url, "_blank", "noopener");
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
636
515
|
const params = { url };
|
|
637
|
-
|
|
516
|
+
client.openLink(params, NO_DEADLINE).catch(() => {
|
|
638
517
|
window.open(url, "_blank", "noopener");
|
|
639
518
|
});
|
|
640
519
|
},
|
|
641
520
|
updateModelContext(state, summary) {
|
|
642
|
-
if (destroyed) return;
|
|
521
|
+
if (destroyed || !hostCapabilities.updateModelContext) return;
|
|
643
522
|
const params = {
|
|
644
523
|
structuredContent: state,
|
|
645
524
|
...summary !== void 0 && {
|
|
646
525
|
content: [{ type: "text", text: summary }]
|
|
647
526
|
}
|
|
648
527
|
};
|
|
649
|
-
|
|
528
|
+
client.updateModelContext(params, NO_DEADLINE).catch(() => {
|
|
529
|
+
});
|
|
650
530
|
},
|
|
651
|
-
async callTool(toolName, args
|
|
652
|
-
|
|
531
|
+
async callTool(toolName, args) {
|
|
532
|
+
if (!hostCapabilities.serverTools) {
|
|
533
|
+
throw new HostCapabilityError("callTool", "serverTools");
|
|
534
|
+
}
|
|
653
535
|
const params = {
|
|
654
536
|
name: toolName,
|
|
655
|
-
arguments: args ?? {}
|
|
656
|
-
...server !== void 0 && { server }
|
|
537
|
+
arguments: args ?? {}
|
|
657
538
|
};
|
|
658
|
-
const raw = await
|
|
539
|
+
const raw = await client.request(
|
|
540
|
+
{ method: chunkISV6HFQE_cjs.TOOLS_CALL_METHOD, params },
|
|
541
|
+
types_js.CallToolResultSchema,
|
|
542
|
+
NO_DEADLINE
|
|
543
|
+
);
|
|
659
544
|
return parseToolResult(raw);
|
|
660
545
|
},
|
|
661
546
|
async readServerResource(params) {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
);
|
|
666
|
-
return raw;
|
|
547
|
+
if (!hostCapabilities.serverResources) {
|
|
548
|
+
throw new HostCapabilityError("readServerResource", "serverResources");
|
|
549
|
+
}
|
|
550
|
+
return await client.readServerResource(params, NO_DEADLINE);
|
|
667
551
|
},
|
|
668
552
|
sendMessage(text, context) {
|
|
669
|
-
if (destroyed) return;
|
|
553
|
+
if (destroyed || !hostCapabilities.message) return;
|
|
670
554
|
const textBlock = {
|
|
671
555
|
type: "text",
|
|
672
556
|
text,
|
|
673
|
-
//
|
|
557
|
+
// The chat context is a NimbleBrain host field; other hosts ignore it,
|
|
674
558
|
// but there is no reason to spend the bytes off one.
|
|
675
|
-
...isNimbleBrainHost && context && { _meta: { context } }
|
|
559
|
+
...isNimbleBrainHost && context && { _meta: { [CHAT_CONTEXT_META_KEY]: context } }
|
|
676
560
|
};
|
|
677
561
|
const params = {
|
|
678
562
|
role: "user",
|
|
679
563
|
content: [textBlock]
|
|
680
564
|
};
|
|
681
|
-
|
|
565
|
+
client.sendMessage(params, NO_DEADLINE).catch(() => {
|
|
566
|
+
});
|
|
682
567
|
},
|
|
683
568
|
destroy() {
|
|
684
569
|
if (destroyed) return;
|
|
@@ -689,34 +574,28 @@ async function connect(options) {
|
|
|
689
574
|
handlers.clear();
|
|
690
575
|
themeCallbacks.clear();
|
|
691
576
|
hostContextCallbacks.clear();
|
|
692
|
-
|
|
693
|
-
actionCallbacks.clear();
|
|
694
|
-
transport.destroy();
|
|
577
|
+
void client.close();
|
|
695
578
|
}
|
|
696
579
|
};
|
|
697
580
|
registerInternals(app, {
|
|
698
581
|
send(method, params) {
|
|
699
|
-
|
|
700
|
-
transport.send(method, params);
|
|
582
|
+
sendRaw(method, params);
|
|
701
583
|
},
|
|
702
584
|
request(method, params) {
|
|
703
|
-
return
|
|
585
|
+
return requestRaw(method, params);
|
|
704
586
|
},
|
|
705
587
|
onMessage(method, handler) {
|
|
706
|
-
return
|
|
588
|
+
return subscribe(method, handler);
|
|
707
589
|
},
|
|
708
590
|
taskRouter,
|
|
709
591
|
get hostTasksCapability() {
|
|
710
592
|
return hostTasksCapability;
|
|
711
|
-
}
|
|
712
|
-
appName: name,
|
|
713
|
-
internalApp: internal
|
|
593
|
+
}
|
|
714
594
|
});
|
|
715
595
|
return app;
|
|
716
596
|
}
|
|
717
597
|
function themesEqual(a, b) {
|
|
718
598
|
if (a.mode !== b.mode) return false;
|
|
719
|
-
if (chunkLPWEQCZV_cjs.fontFacesKey(a.fontFaces) !== chunkLPWEQCZV_cjs.fontFacesKey(b.fontFaces)) return false;
|
|
720
599
|
const aKeys = Object.keys(a.tokens);
|
|
721
600
|
const bKeys = Object.keys(b.tokens);
|
|
722
601
|
if (aKeys.length !== bKeys.length) return false;
|
|
@@ -727,62 +606,62 @@ function themesEqual(a, b) {
|
|
|
727
606
|
}
|
|
728
607
|
|
|
729
608
|
// src/extensions.ts
|
|
609
|
+
function hostSupports(app, extension) {
|
|
610
|
+
const { capability } = chunkISV6HFQE_cjs.NIMBLEBRAIN_EXTENSIONS[extension];
|
|
611
|
+
return app.hostCapabilities.experimental?.[capability] !== void 0;
|
|
612
|
+
}
|
|
730
613
|
var DEFAULT_MAX_FILE_SIZE = 26214400;
|
|
731
614
|
function action(app, name, params) {
|
|
732
|
-
if (!app
|
|
733
|
-
internalsFor(app).send(
|
|
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
|
-
});
|
|
615
|
+
if (!hostSupports(app, "action")) return;
|
|
616
|
+
internalsFor(app).send(chunkISV6HFQE_cjs.NIMBLEBRAIN_EXTENSIONS.action.method, { action: name, ...params });
|
|
743
617
|
}
|
|
744
618
|
async function pickFile(app, options) {
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
const result = await requestFile(app, options, false);
|
|
749
|
-
if (result === null) return null;
|
|
750
|
-
return Array.isArray(result) ? result[0] ?? null : result;
|
|
619
|
+
requireRequestFile("pickFile", app);
|
|
620
|
+
const files = await requestFile(app, options, false);
|
|
621
|
+
return files[0] ?? null;
|
|
751
622
|
}
|
|
752
623
|
async function pickFiles(app, options) {
|
|
753
|
-
|
|
754
|
-
|
|
624
|
+
requireRequestFile("pickFiles", app);
|
|
625
|
+
return await requestFile(app, options, true);
|
|
626
|
+
}
|
|
627
|
+
function requireRequestFile(feature, app) {
|
|
628
|
+
if (!hostSupports(app, "requestFile")) {
|
|
629
|
+
throw new HostCapabilityError(feature, chunkISV6HFQE_cjs.NIMBLEBRAIN_EXTENSIONS.requestFile.capability);
|
|
755
630
|
}
|
|
756
|
-
const result = await requestFile(app, options, true);
|
|
757
|
-
if (result === null) return [];
|
|
758
|
-
return Array.isArray(result) ? result : [result];
|
|
759
631
|
}
|
|
760
632
|
async function requestFile(app, options, multiple) {
|
|
761
|
-
const result = await internalsFor(app).request(
|
|
633
|
+
const result = await internalsFor(app).request(chunkISV6HFQE_cjs.NIMBLEBRAIN_EXTENSIONS.requestFile.method, {
|
|
762
634
|
accept: options?.accept,
|
|
763
635
|
maxSize: options?.maxSize ?? DEFAULT_MAX_FILE_SIZE,
|
|
764
636
|
multiple
|
|
765
637
|
});
|
|
766
|
-
|
|
767
|
-
if (
|
|
768
|
-
|
|
638
|
+
const files = result?.files;
|
|
639
|
+
if (files === void 0) {
|
|
640
|
+
throw new Error(
|
|
641
|
+
"ai.nimblebrain/request-file returned no `files`. The host is older than this SDK targets: it answers the picker with a bare array or `null`, which a spec-compliant client cannot parse."
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
if (!Array.isArray(files)) {
|
|
645
|
+
throw new Error("ai.nimblebrain/request-file returned a `files` field that is not an array.");
|
|
769
646
|
}
|
|
770
|
-
return validateFileResult
|
|
647
|
+
return files.map(validateFileResult);
|
|
771
648
|
}
|
|
772
649
|
function validateFileResult(value) {
|
|
773
650
|
if (typeof value !== "object" || value === null || typeof value.id !== "string") {
|
|
774
651
|
throw new Error(
|
|
775
|
-
"
|
|
652
|
+
"ai.nimblebrain/request-file returned a result without a string `id`. The host appears to be on a version older than this SDK targets \u2014 @nimblebrain/synapse 0.8.0+ requires a host with POST /v1/resources (NimbleBrain \u2265 the version that ships PR #93)."
|
|
776
653
|
);
|
|
777
654
|
}
|
|
778
655
|
return value;
|
|
779
656
|
}
|
|
780
657
|
|
|
658
|
+
exports.HostCapabilityError = HostCapabilityError;
|
|
781
659
|
exports.action = action;
|
|
782
660
|
exports.callToolAsTask = callToolAsTask;
|
|
783
661
|
exports.connect = connect;
|
|
784
|
-
exports.
|
|
662
|
+
exports.hostSupports = hostSupports;
|
|
663
|
+
exports.internalsFor = internalsFor;
|
|
785
664
|
exports.pickFile = pickFile;
|
|
786
665
|
exports.pickFiles = pickFiles;
|
|
787
|
-
//# sourceMappingURL=chunk-
|
|
788
|
-
//# sourceMappingURL=chunk-
|
|
666
|
+
//# sourceMappingURL=chunk-HQLSVUOR.cjs.map
|
|
667
|
+
//# sourceMappingURL=chunk-HQLSVUOR.cjs.map
|