@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.
Files changed (59) hide show
  1. package/README.md +61 -111
  2. package/dist/{chunk-SN7YXLAV.cjs → chunk-EHLQWCYV.cjs} +6 -6
  3. package/dist/{chunk-SN7YXLAV.cjs.map → chunk-EHLQWCYV.cjs.map} +1 -1
  4. package/dist/{chunk-ZMNYUGSF.cjs → chunk-FDMRJZKT.cjs} +576 -662
  5. package/dist/chunk-FDMRJZKT.cjs.map +1 -0
  6. package/dist/{chunk-E7OOOYVR.js → chunk-SRQNQ26I.js} +3 -3
  7. package/dist/{chunk-E7OOOYVR.js.map → chunk-SRQNQ26I.js.map} +1 -1
  8. package/dist/{chunk-RYWW6EHB.cjs → chunk-TXJMGQYF.cjs} +3 -5
  9. package/dist/chunk-TXJMGQYF.cjs.map +1 -0
  10. package/dist/{chunk-J5ICAHK2.js → chunk-UPDBDXQB.js} +4 -5
  11. package/dist/chunk-UPDBDXQB.js.map +1 -0
  12. package/dist/{chunk-GNTQJSQX.js → chunk-VYR6V47N.js} +573 -663
  13. package/dist/chunk-VYR6V47N.js.map +1 -0
  14. package/dist/codegen/cli.cjs +1 -1
  15. package/dist/codegen/cli.js +1 -1
  16. package/dist/codegen/index.d.cts +1 -1
  17. package/dist/codegen/index.d.ts +1 -1
  18. package/dist/connect.iife.global.js +28 -28
  19. package/dist/{detect-C_qmYsh9.d.cts → detect-BHYg26_d.d.cts} +1 -1
  20. package/dist/{detect-Dfd0upoz.d.ts → detect-Bf8Q_0dK.d.ts} +1 -1
  21. package/dist/host/index.cjs +14 -14
  22. package/dist/host/index.d.cts +3 -3
  23. package/dist/host/index.d.ts +3 -3
  24. package/dist/host/index.js +2 -2
  25. package/dist/index.cjs +28 -87
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +58 -26
  28. package/dist/index.d.ts +58 -26
  29. package/dist/index.js +3 -81
  30. package/dist/index.js.map +1 -1
  31. package/dist/react/index.cjs +81 -140
  32. package/dist/react/index.cjs.map +1 -1
  33. package/dist/react/index.d.cts +66 -82
  34. package/dist/react/index.d.ts +66 -82
  35. package/dist/react/index.js +82 -136
  36. package/dist/react/index.js.map +1 -1
  37. package/dist/{server-ERRDGEZ7.js → server-5N76YCWC.js} +3 -3
  38. package/dist/{server-ERRDGEZ7.js.map → server-5N76YCWC.js.map} +1 -1
  39. package/dist/{server-P54IYX2G.cjs → server-QIYIJHD5.cjs} +3 -3
  40. package/dist/{server-P54IYX2G.cjs.map → server-QIYIJHD5.cjs.map} +1 -1
  41. package/dist/synapse-runtime.iife.global.js +28 -28
  42. package/dist/synapse-ui.iife.global.js +2 -2
  43. package/dist/{types-BSZasM8q.d.cts → types-uEO4VFJ2.d.cts} +87 -166
  44. package/dist/{types-BSZasM8q.d.ts → types-uEO4VFJ2.d.ts} +87 -166
  45. package/dist/ui/index.cjs +403 -91
  46. package/dist/ui/index.cjs.map +1 -1
  47. package/dist/ui/index.d.cts +115 -3
  48. package/dist/ui/index.d.ts +115 -3
  49. package/dist/ui/index.js +401 -93
  50. package/dist/ui/index.js.map +1 -1
  51. package/dist/vite/index.cjs +1 -1
  52. package/dist/vite/index.cjs.map +1 -1
  53. package/dist/vite/index.js +1 -1
  54. package/dist/vite/index.js.map +1 -1
  55. package/package.json +1 -1
  56. package/dist/chunk-GNTQJSQX.js.map +0 -1
  57. package/dist/chunk-J5ICAHK2.js.map +0 -1
  58. package/dist/chunk-RYWW6EHB.cjs.map +0 -1
  59. package/dist/chunk-ZMNYUGSF.cjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { F as FontFaceDescriptor } from './types-BSZasM8q.cjs';
1
+ import { g as FontFaceDescriptor } from './types-uEO4VFJ2.cjs';
2
2
 
3
3
  /**
4
4
  * Cross-host UI client — types and wire constants.
@@ -1,4 +1,4 @@
1
- import { F as FontFaceDescriptor } from './types-BSZasM8q.js';
1
+ import { g as FontFaceDescriptor } from './types-uEO4VFJ2.js';
2
2
 
3
3
  /**
4
4
  * Cross-host UI client — types and wire constants.
@@ -1,57 +1,57 @@
1
1
  'use strict';
2
2
 
3
- var chunkSN7YXLAV_cjs = require('../chunk-SN7YXLAV.cjs');
4
- require('../chunk-RYWW6EHB.cjs');
3
+ var chunkEHLQWCYV_cjs = require('../chunk-EHLQWCYV.cjs');
4
+ require('../chunk-TXJMGQYF.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "HostUnsupportedError", {
9
9
  enumerable: true,
10
- get: function () { return chunkSN7YXLAV_cjs.HostUnsupportedError; }
10
+ get: function () { return chunkEHLQWCYV_cjs.HostUnsupportedError; }
11
11
  });
12
12
  Object.defineProperty(exports, "SYNAPSE_DATA_ELEMENT_ID", {
13
13
  enumerable: true,
14
- get: function () { return chunkSN7YXLAV_cjs.SYNAPSE_DATA_ELEMENT_ID; }
14
+ get: function () { return chunkEHLQWCYV_cjs.SYNAPSE_DATA_ELEMENT_ID; }
15
15
  });
16
16
  Object.defineProperty(exports, "adapterForKind", {
17
17
  enumerable: true,
18
- get: function () { return chunkSN7YXLAV_cjs.adapterForKind; }
18
+ get: function () { return chunkEHLQWCYV_cjs.adapterForKind; }
19
19
  });
20
20
  Object.defineProperty(exports, "applyHostTheme", {
21
21
  enumerable: true,
22
- get: function () { return chunkSN7YXLAV_cjs.applyHostTheme; }
22
+ get: function () { return chunkEHLQWCYV_cjs.applyHostTheme; }
23
23
  });
24
24
  Object.defineProperty(exports, "coerceMode", {
25
25
  enumerable: true,
26
- get: function () { return chunkSN7YXLAV_cjs.coerceMode; }
26
+ get: function () { return chunkEHLQWCYV_cjs.coerceMode; }
27
27
  });
28
28
  Object.defineProperty(exports, "connectUI", {
29
29
  enumerable: true,
30
- get: function () { return chunkSN7YXLAV_cjs.connectUI; }
30
+ get: function () { return chunkEHLQWCYV_cjs.connectUI; }
31
31
  });
32
32
  Object.defineProperty(exports, "createChatGPTAdapter", {
33
33
  enumerable: true,
34
- get: function () { return chunkSN7YXLAV_cjs.createChatGPTAdapter; }
34
+ get: function () { return chunkEHLQWCYV_cjs.createChatGPTAdapter; }
35
35
  });
36
36
  Object.defineProperty(exports, "createInlineAdapter", {
37
37
  enumerable: true,
38
- get: function () { return chunkSN7YXLAV_cjs.createInlineAdapter; }
38
+ get: function () { return chunkEHLQWCYV_cjs.createInlineAdapter; }
39
39
  });
40
40
  Object.defineProperty(exports, "createMcpAppsAdapter", {
41
41
  enumerable: true,
42
- get: function () { return chunkSN7YXLAV_cjs.createMcpAppsAdapter; }
42
+ get: function () { return chunkEHLQWCYV_cjs.createMcpAppsAdapter; }
43
43
  });
44
44
  Object.defineProperty(exports, "detectHostKind", {
45
45
  enumerable: true,
46
- get: function () { return chunkSN7YXLAV_cjs.detectHostKind; }
46
+ get: function () { return chunkEHLQWCYV_cjs.detectHostKind; }
47
47
  });
48
48
  Object.defineProperty(exports, "preferredMode", {
49
49
  enumerable: true,
50
- get: function () { return chunkSN7YXLAV_cjs.preferredMode; }
50
+ get: function () { return chunkEHLQWCYV_cjs.preferredMode; }
51
51
  });
52
52
  Object.defineProperty(exports, "selectAdapter", {
53
53
  enumerable: true,
54
- get: function () { return chunkSN7YXLAV_cjs.selectAdapter; }
54
+ get: function () { return chunkEHLQWCYV_cjs.selectAdapter; }
55
55
  });
56
56
  //# sourceMappingURL=index.cjs.map
57
57
  //# sourceMappingURL=index.cjs.map
@@ -1,6 +1,6 @@
1
- import { C as ConnectUIOptions, g as HostAdapter, d as SynapseUITheme } from '../detect-C_qmYsh9.cjs';
2
- export { H as HostCapabilities, a as HostKind, b as HostUnsupportedError, S as SYNAPSE_DATA_ELEMENT_ID, c as SynapseUIClient, h as adapterForKind, e as connectUI, f as detectHostKind, s as selectAdapter } from '../detect-C_qmYsh9.cjs';
3
- import '../types-BSZasM8q.cjs';
1
+ import { C as ConnectUIOptions, g as HostAdapter, d as SynapseUITheme } from '../detect-BHYg26_d.cjs';
2
+ export { H as HostCapabilities, a as HostKind, b as HostUnsupportedError, S as SYNAPSE_DATA_ELEMENT_ID, c as SynapseUIClient, h as adapterForKind, e as connectUI, f as detectHostKind, s as selectAdapter } from '../detect-BHYg26_d.cjs';
3
+ import '../types-uEO4VFJ2.cjs';
4
4
  import '@modelcontextprotocol/ext-apps';
5
5
  import '@modelcontextprotocol/sdk/types.js';
6
6
 
@@ -1,6 +1,6 @@
1
- import { C as ConnectUIOptions, g as HostAdapter, d as SynapseUITheme } from '../detect-Dfd0upoz.js';
2
- export { H as HostCapabilities, a as HostKind, b as HostUnsupportedError, S as SYNAPSE_DATA_ELEMENT_ID, c as SynapseUIClient, h as adapterForKind, e as connectUI, f as detectHostKind, s as selectAdapter } from '../detect-Dfd0upoz.js';
3
- import '../types-BSZasM8q.js';
1
+ import { C as ConnectUIOptions, g as HostAdapter, d as SynapseUITheme } from '../detect-Bf8Q_0dK.js';
2
+ export { H as HostCapabilities, a as HostKind, b as HostUnsupportedError, S as SYNAPSE_DATA_ELEMENT_ID, c as SynapseUIClient, h as adapterForKind, e as connectUI, f as detectHostKind, s as selectAdapter } from '../detect-Bf8Q_0dK.js';
3
+ import '../types-uEO4VFJ2.js';
4
4
  import '@modelcontextprotocol/ext-apps';
5
5
  import '@modelcontextprotocol/sdk/types.js';
6
6
 
@@ -1,4 +1,4 @@
1
- export { HostUnsupportedError, SYNAPSE_DATA_ELEMENT_ID, adapterForKind, applyHostTheme, coerceMode, connectUI, createChatGPTAdapter, createInlineAdapter, createMcpAppsAdapter, detectHostKind, preferredMode, selectAdapter } from '../chunk-E7OOOYVR.js';
2
- import '../chunk-J5ICAHK2.js';
1
+ export { HostUnsupportedError, SYNAPSE_DATA_ELEMENT_ID, adapterForKind, applyHostTheme, coerceMode, connectUI, createChatGPTAdapter, createInlineAdapter, createMcpAppsAdapter, detectHostKind, preferredMode, selectAdapter } from '../chunk-SRQNQ26I.js';
2
+ import '../chunk-UPDBDXQB.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.cjs CHANGED
@@ -1,113 +1,54 @@
1
1
  'use strict';
2
2
 
3
- var chunkSN7YXLAV_cjs = require('./chunk-SN7YXLAV.cjs');
4
- var chunkZMNYUGSF_cjs = require('./chunk-ZMNYUGSF.cjs');
5
- var chunkRYWW6EHB_cjs = require('./chunk-RYWW6EHB.cjs');
3
+ var chunkEHLQWCYV_cjs = require('./chunk-EHLQWCYV.cjs');
4
+ var chunkFDMRJZKT_cjs = require('./chunk-FDMRJZKT.cjs');
5
+ var chunkTXJMGQYF_cjs = require('./chunk-TXJMGQYF.cjs');
6
+
6
7
 
7
- // src/store.ts
8
- function createStore(synapse, config) {
9
- let state = structuredClone(config.initialState);
10
- const subscribers = /* @__PURE__ */ new Set();
11
- let destroyed = false;
12
- let persistTimer = null;
13
- const dispatch = {};
14
- for (const key of Object.keys(config.actions)) {
15
- dispatch[key] = (payload) => {
16
- if (destroyed) return;
17
- state = config.actions[key](state, payload);
18
- notify();
19
- };
20
- }
21
- function notify() {
22
- for (const cb of subscribers) cb(state);
23
- if (config.visibleToAgent) pushToAgent();
24
- if (config.persist) schedulePersist();
25
- }
26
- function pushToAgent() {
27
- const summary = config.summarize?.(state);
28
- synapse.setVisibleState(state, summary);
29
- }
30
- function schedulePersist() {
31
- if (persistTimer) clearTimeout(persistTimer);
32
- persistTimer = setTimeout(() => {
33
- synapse._request("synapse/persist-state", {
34
- state,
35
- version: config.version
36
- }).catch(() => {
37
- });
38
- persistTimer = null;
39
- }, 500);
40
- }
41
- let unsubStateLoaded;
42
- if (config.persist) {
43
- unsubStateLoaded = synapse._onMessage("synapse/state-loaded", (params) => {
44
- if (!params?.state) return;
45
- let loaded = params.state;
46
- const loadedVersion = params.version ?? 1;
47
- const currentVersion = config.version ?? 1;
48
- if (config.migrations && loadedVersion < currentVersion) {
49
- const startIdx = loadedVersion - 1;
50
- for (let i = startIdx; i < config.migrations.length; i++) {
51
- loaded = config.migrations[i](loaded);
52
- }
53
- }
54
- store.hydrate(loaded);
55
- });
56
- }
57
- const store = {
58
- getState() {
59
- return state;
60
- },
61
- subscribe(callback) {
62
- subscribers.add(callback);
63
- return () => {
64
- subscribers.delete(callback);
65
- };
66
- },
67
- dispatch,
68
- hydrate(newState) {
69
- state = newState;
70
- for (const cb of subscribers) cb(state);
71
- },
72
- destroy() {
73
- if (destroyed) return;
74
- destroyed = true;
75
- if (persistTimer) clearTimeout(persistTimer);
76
- subscribers.clear();
77
- unsubStateLoaded?.();
78
- }
79
- };
80
- return store;
81
- }
82
8
 
83
9
  Object.defineProperty(exports, "HostUnsupportedError", {
84
10
  enumerable: true,
85
- get: function () { return chunkSN7YXLAV_cjs.HostUnsupportedError; }
11
+ get: function () { return chunkEHLQWCYV_cjs.HostUnsupportedError; }
86
12
  });
87
13
  Object.defineProperty(exports, "SYNAPSE_DATA_ELEMENT_ID", {
88
14
  enumerable: true,
89
- get: function () { return chunkSN7YXLAV_cjs.SYNAPSE_DATA_ELEMENT_ID; }
15
+ get: function () { return chunkEHLQWCYV_cjs.SYNAPSE_DATA_ELEMENT_ID; }
90
16
  });
91
17
  Object.defineProperty(exports, "connectUI", {
92
18
  enumerable: true,
93
- get: function () { return chunkSN7YXLAV_cjs.connectUI; }
19
+ get: function () { return chunkEHLQWCYV_cjs.connectUI; }
94
20
  });
95
21
  Object.defineProperty(exports, "detectHostKind", {
96
22
  enumerable: true,
97
- get: function () { return chunkSN7YXLAV_cjs.detectHostKind; }
23
+ get: function () { return chunkEHLQWCYV_cjs.detectHostKind; }
24
+ });
25
+ Object.defineProperty(exports, "action", {
26
+ enumerable: true,
27
+ get: function () { return chunkFDMRJZKT_cjs.action; }
28
+ });
29
+ Object.defineProperty(exports, "callToolAsTask", {
30
+ enumerable: true,
31
+ get: function () { return chunkFDMRJZKT_cjs.callToolAsTask; }
98
32
  });
99
33
  Object.defineProperty(exports, "connect", {
100
34
  enumerable: true,
101
- get: function () { return chunkZMNYUGSF_cjs.connect; }
35
+ get: function () { return chunkFDMRJZKT_cjs.connect; }
36
+ });
37
+ Object.defineProperty(exports, "downloadFile", {
38
+ enumerable: true,
39
+ get: function () { return chunkFDMRJZKT_cjs.downloadFile; }
40
+ });
41
+ Object.defineProperty(exports, "pickFile", {
42
+ enumerable: true,
43
+ get: function () { return chunkFDMRJZKT_cjs.pickFile; }
102
44
  });
103
- Object.defineProperty(exports, "createSynapse", {
45
+ Object.defineProperty(exports, "pickFiles", {
104
46
  enumerable: true,
105
- get: function () { return chunkZMNYUGSF_cjs.createSynapse; }
47
+ get: function () { return chunkFDMRJZKT_cjs.pickFiles; }
106
48
  });
107
49
  Object.defineProperty(exports, "FONT_FACES_CONTEXT_KEY", {
108
50
  enumerable: true,
109
- get: function () { return chunkRYWW6EHB_cjs.FONT_FACES_CONTEXT_KEY; }
51
+ get: function () { return chunkTXJMGQYF_cjs.FONT_FACES_CONTEXT_KEY; }
110
52
  });
111
- exports.createStore = createStore;
112
53
  //# sourceMappingURL=index.cjs.map
113
54
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"synapse/persist-state\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"synapse/state-loaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
package/dist/index.d.cts CHANGED
@@ -1,27 +1,21 @@
1
1
  export { CreateTaskResult, ReadResourceRequest, ReadResourceResult, Task, TaskStatus } from '@modelcontextprotocol/sdk/types.js';
2
- import { C as ConnectOptions, A as App, S as SynapseOptions, a as Synapse, b as ActionReducer, c as StoreConfig, d as Store } from './types-BSZasM8q.cjs';
3
- export { e as AgentAction, f as AppEventName, B as BuiltinActionType, g as CallToolAsTaskOptions, D as DataChangedEvent, h as Dimensions, i as FileResult, j as FontDisplayValue, F as FontFaceDescriptor, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, k as NotifyPayload, R as RequestFileOptions, l as StateAcknowledgement, m as StoreDispatch, n as SynapseTheme, o as TaskHandle, p as TasksCapability, q as Theme, r as ToolCallResult, T as ToolDefinition, s as ToolResultData, V as VisibleState } from './types-BSZasM8q.cjs';
4
- export { C as ConnectUIOptions, H as HostCapabilities, a as HostKind, b as HostUnsupportedError, S as SYNAPSE_DATA_ELEMENT_ID, c as SynapseUIClient, d as SynapseUITheme, e as connectUI, f as detectHostKind } from './detect-C_qmYsh9.cjs';
5
- import '@modelcontextprotocol/ext-apps';
2
+ import { C as ConnectOptions, A as App, R as RequestFileOptions, F as FileResult, a as CallToolAsTaskOptions, T as TaskHandle } from './types-uEO4VFJ2.cjs';
3
+ export { h as AgentAction, i as AppEventName, B as BuiltinActionType, c as CallToolOptions, D as DataChangedEvent, j as Dimensions, k as FontDisplayValue, g as FontFaceDescriptor, H as HostInfo, K as KeyForwardConfig, M as ModelContext, N as NavigatePayload, l as NotifyPayload, m as TasksCapability, d as Theme, b as ToolCallResult, f as ToolDefinition, e as ToolResultData } from './types-uEO4VFJ2.cjs';
4
+ export { C as ConnectUIOptions, H as HostCapabilities, a as HostKind, b as HostUnsupportedError, S as SYNAPSE_DATA_ELEMENT_ID, c as SynapseUIClient, d as SynapseUITheme, e as connectUI, f as detectHostKind } from './detect-BHYg26_d.cjs';
5
+ export { McpUiHostContext } from '@modelcontextprotocol/ext-apps';
6
6
 
7
7
  /**
8
- * Connect to a MCP Apps host.
8
+ * Connect to an MCP Apps host.
9
9
  *
10
- * Owns the full ext-apps handshake, content parsing, resize management,
11
- * and event routing. Returns a ready-to-use `App` object.
12
- */
13
- declare function connect(options: ConnectOptions): Promise<App>;
14
-
15
- /**
16
- * Create a Synapse instance.
17
- *
18
- * Wraps the ext-apps protocol handshake via `SynapseTransport` and provides
19
- * a typed, framework-agnostic API for calling tools, reacting to data changes,
20
- * dispatching actions, and pushing LLM-visible state.
10
+ * The one entry point: owns the ext-apps handshake, theme injection, content
11
+ * parsing, resize management, and event routing, and resolves to a ready
12
+ * {@link App}.
21
13
  *
22
- * In non-NimbleBrain hosts, NB-specific methods degrade to no-ops.
14
+ * The `App` it returns stays deliberately small. NimbleBrain's own extensions
15
+ * (`action`, the file picker, `downloadFile`) and the MCP tasks utility are
16
+ * composable functions over it — import them from the package root.
23
17
  */
24
- declare function createSynapse(options: SynapseOptions): Synapse;
18
+ declare function connect(options: ConnectOptions): Promise<App>;
25
19
 
26
20
  /**
27
21
  * Host-context key carrying `@font-face` descriptors.
@@ -36,14 +30,52 @@ declare function createSynapse(options: SynapseOptions): Synapse;
36
30
  declare const FONT_FACES_CONTEXT_KEY = "synapse/fontFaces";
37
31
 
38
32
  /**
39
- * Create a typed state store with optional persistence and agent visibility.
33
+ * Trigger a host-side action.
34
+ *
35
+ * The inverse direction of the `action` event: this sends a command *to* the
36
+ * host (navigate, open a panel), where `app.on("action", …)` receives the ones
37
+ * a tool emits. No-op off a NimbleBrain host.
38
+ */
39
+ declare function action(app: App, name: string, params?: Record<string, unknown>): void;
40
+ /**
41
+ * Hand the user a file to save.
42
+ *
43
+ * Precedence for the MIME type: the explicit argument, then the Blob's own
44
+ * type, then `application/octet-stream`. An empty-string argument falls
45
+ * through — a `""` MIME is effectively "no type".
46
+ */
47
+ declare function downloadFile(app: App, filename: string, content: string | Blob, mimeType?: string): void;
48
+ /**
49
+ * Request one file from the user via the host's native file picker.
50
+ *
51
+ * Resolves `null` if the user cancels. Throws off a NimbleBrain host.
52
+ */
53
+ declare function pickFile(app: App, options?: RequestFileOptions): Promise<FileResult | null>;
54
+ /**
55
+ * Request several files from the user.
56
+ *
57
+ * Resolves `[]` if the user cancels. Throws off a NimbleBrain host.
58
+ */
59
+ declare function pickFiles(app: App, options?: RequestFileOptions): Promise<FileResult[]>;
60
+
61
+ /**
62
+ * Task-augment a `tools/call` per the MCP 2025-11-25 tasks utility.
63
+ *
64
+ * A composable helper over {@link App} rather than a method on it: the object
65
+ * `connect()` returns carries the ext-apps surface, and tasks ride alongside.
66
+ * The receiver answers a task-augmented call with a `CreateTaskResult`
67
+ * promptly; the actual `CallToolResult` arrives later via `tasks/result`.
68
+ *
69
+ * ```ts
70
+ * const handle = await callToolAsTask(app, "deep_research", { topic });
71
+ * handle.onStatus((t) => setStatus(t.status));
72
+ * const result = await handle.result();
73
+ * ```
40
74
  *
41
- * - `persist: true` — state survives iframe reloads via host storage
42
- * - `visibleToAgent: true` — state is pushed to the LLM context
43
- * - Both are independent and can be enabled separately
75
+ * Throws if the host did not advertise `tasks.requests.tools.call` — per spec
76
+ * a requestor MUST NOT task-augment without matching receiver capability.
77
+ * Fall back to `app.callTool`.
44
78
  */
45
- declare function createStore<TState, TActions extends Record<string, ActionReducer<TState, any>> = Record<string, ActionReducer<TState, any>>>(synapse: Synapse, config: StoreConfig<TState> & {
46
- actions: TActions;
47
- }): Store<TState, TActions>;
79
+ declare function callToolAsTask<TOutput = unknown>(app: App, toolName: string, args?: unknown, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>>;
48
80
 
49
- export { ActionReducer, App, ConnectOptions, FONT_FACES_CONTEXT_KEY, Store, StoreConfig, Synapse, SynapseOptions, connect, createStore, createSynapse };
81
+ export { App, CallToolAsTaskOptions, ConnectOptions, FONT_FACES_CONTEXT_KEY, FileResult, RequestFileOptions, TaskHandle, action, callToolAsTask, connect, downloadFile, pickFile, pickFiles };
package/dist/index.d.ts CHANGED
@@ -1,27 +1,21 @@
1
1
  export { CreateTaskResult, ReadResourceRequest, ReadResourceResult, Task, TaskStatus } from '@modelcontextprotocol/sdk/types.js';
2
- import { C as ConnectOptions, A as App, S as SynapseOptions, a as Synapse, b as ActionReducer, c as StoreConfig, d as Store } from './types-BSZasM8q.js';
3
- export { e as AgentAction, f as AppEventName, B as BuiltinActionType, g as CallToolAsTaskOptions, D as DataChangedEvent, h as Dimensions, i as FileResult, j as FontDisplayValue, F as FontFaceDescriptor, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, k as NotifyPayload, R as RequestFileOptions, l as StateAcknowledgement, m as StoreDispatch, n as SynapseTheme, o as TaskHandle, p as TasksCapability, q as Theme, r as ToolCallResult, T as ToolDefinition, s as ToolResultData, V as VisibleState } from './types-BSZasM8q.js';
4
- export { C as ConnectUIOptions, H as HostCapabilities, a as HostKind, b as HostUnsupportedError, S as SYNAPSE_DATA_ELEMENT_ID, c as SynapseUIClient, d as SynapseUITheme, e as connectUI, f as detectHostKind } from './detect-Dfd0upoz.js';
5
- import '@modelcontextprotocol/ext-apps';
2
+ import { C as ConnectOptions, A as App, R as RequestFileOptions, F as FileResult, a as CallToolAsTaskOptions, T as TaskHandle } from './types-uEO4VFJ2.js';
3
+ export { h as AgentAction, i as AppEventName, B as BuiltinActionType, c as CallToolOptions, D as DataChangedEvent, j as Dimensions, k as FontDisplayValue, g as FontFaceDescriptor, H as HostInfo, K as KeyForwardConfig, M as ModelContext, N as NavigatePayload, l as NotifyPayload, m as TasksCapability, d as Theme, b as ToolCallResult, f as ToolDefinition, e as ToolResultData } from './types-uEO4VFJ2.js';
4
+ export { C as ConnectUIOptions, H as HostCapabilities, a as HostKind, b as HostUnsupportedError, S as SYNAPSE_DATA_ELEMENT_ID, c as SynapseUIClient, d as SynapseUITheme, e as connectUI, f as detectHostKind } from './detect-Bf8Q_0dK.js';
5
+ export { McpUiHostContext } from '@modelcontextprotocol/ext-apps';
6
6
 
7
7
  /**
8
- * Connect to a MCP Apps host.
8
+ * Connect to an MCP Apps host.
9
9
  *
10
- * Owns the full ext-apps handshake, content parsing, resize management,
11
- * and event routing. Returns a ready-to-use `App` object.
12
- */
13
- declare function connect(options: ConnectOptions): Promise<App>;
14
-
15
- /**
16
- * Create a Synapse instance.
17
- *
18
- * Wraps the ext-apps protocol handshake via `SynapseTransport` and provides
19
- * a typed, framework-agnostic API for calling tools, reacting to data changes,
20
- * dispatching actions, and pushing LLM-visible state.
10
+ * The one entry point: owns the ext-apps handshake, theme injection, content
11
+ * parsing, resize management, and event routing, and resolves to a ready
12
+ * {@link App}.
21
13
  *
22
- * In non-NimbleBrain hosts, NB-specific methods degrade to no-ops.
14
+ * The `App` it returns stays deliberately small. NimbleBrain's own extensions
15
+ * (`action`, the file picker, `downloadFile`) and the MCP tasks utility are
16
+ * composable functions over it — import them from the package root.
23
17
  */
24
- declare function createSynapse(options: SynapseOptions): Synapse;
18
+ declare function connect(options: ConnectOptions): Promise<App>;
25
19
 
26
20
  /**
27
21
  * Host-context key carrying `@font-face` descriptors.
@@ -36,14 +30,52 @@ declare function createSynapse(options: SynapseOptions): Synapse;
36
30
  declare const FONT_FACES_CONTEXT_KEY = "synapse/fontFaces";
37
31
 
38
32
  /**
39
- * Create a typed state store with optional persistence and agent visibility.
33
+ * Trigger a host-side action.
34
+ *
35
+ * The inverse direction of the `action` event: this sends a command *to* the
36
+ * host (navigate, open a panel), where `app.on("action", …)` receives the ones
37
+ * a tool emits. No-op off a NimbleBrain host.
38
+ */
39
+ declare function action(app: App, name: string, params?: Record<string, unknown>): void;
40
+ /**
41
+ * Hand the user a file to save.
42
+ *
43
+ * Precedence for the MIME type: the explicit argument, then the Blob's own
44
+ * type, then `application/octet-stream`. An empty-string argument falls
45
+ * through — a `""` MIME is effectively "no type".
46
+ */
47
+ declare function downloadFile(app: App, filename: string, content: string | Blob, mimeType?: string): void;
48
+ /**
49
+ * Request one file from the user via the host's native file picker.
50
+ *
51
+ * Resolves `null` if the user cancels. Throws off a NimbleBrain host.
52
+ */
53
+ declare function pickFile(app: App, options?: RequestFileOptions): Promise<FileResult | null>;
54
+ /**
55
+ * Request several files from the user.
56
+ *
57
+ * Resolves `[]` if the user cancels. Throws off a NimbleBrain host.
58
+ */
59
+ declare function pickFiles(app: App, options?: RequestFileOptions): Promise<FileResult[]>;
60
+
61
+ /**
62
+ * Task-augment a `tools/call` per the MCP 2025-11-25 tasks utility.
63
+ *
64
+ * A composable helper over {@link App} rather than a method on it: the object
65
+ * `connect()` returns carries the ext-apps surface, and tasks ride alongside.
66
+ * The receiver answers a task-augmented call with a `CreateTaskResult`
67
+ * promptly; the actual `CallToolResult` arrives later via `tasks/result`.
68
+ *
69
+ * ```ts
70
+ * const handle = await callToolAsTask(app, "deep_research", { topic });
71
+ * handle.onStatus((t) => setStatus(t.status));
72
+ * const result = await handle.result();
73
+ * ```
40
74
  *
41
- * - `persist: true` — state survives iframe reloads via host storage
42
- * - `visibleToAgent: true` — state is pushed to the LLM context
43
- * - Both are independent and can be enabled separately
75
+ * Throws if the host did not advertise `tasks.requests.tools.call` — per spec
76
+ * a requestor MUST NOT task-augment without matching receiver capability.
77
+ * Fall back to `app.callTool`.
44
78
  */
45
- declare function createStore<TState, TActions extends Record<string, ActionReducer<TState, any>> = Record<string, ActionReducer<TState, any>>>(synapse: Synapse, config: StoreConfig<TState> & {
46
- actions: TActions;
47
- }): Store<TState, TActions>;
79
+ declare function callToolAsTask<TOutput = unknown>(app: App, toolName: string, args?: unknown, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>>;
48
80
 
49
- export { ActionReducer, App, ConnectOptions, FONT_FACES_CONTEXT_KEY, Store, StoreConfig, Synapse, SynapseOptions, connect, createStore, createSynapse };
81
+ export { App, CallToolAsTaskOptions, ConnectOptions, FONT_FACES_CONTEXT_KEY, FileResult, RequestFileOptions, TaskHandle, action, callToolAsTask, connect, downloadFile, pickFile, pickFiles };
package/dist/index.js CHANGED
@@ -1,83 +1,5 @@
1
- export { HostUnsupportedError, SYNAPSE_DATA_ELEMENT_ID, connectUI, detectHostKind } from './chunk-E7OOOYVR.js';
2
- export { connect, createSynapse } from './chunk-GNTQJSQX.js';
3
- export { FONT_FACES_CONTEXT_KEY } from './chunk-J5ICAHK2.js';
4
-
5
- // src/store.ts
6
- function createStore(synapse, config) {
7
- let state = structuredClone(config.initialState);
8
- const subscribers = /* @__PURE__ */ new Set();
9
- let destroyed = false;
10
- let persistTimer = null;
11
- const dispatch = {};
12
- for (const key of Object.keys(config.actions)) {
13
- dispatch[key] = (payload) => {
14
- if (destroyed) return;
15
- state = config.actions[key](state, payload);
16
- notify();
17
- };
18
- }
19
- function notify() {
20
- for (const cb of subscribers) cb(state);
21
- if (config.visibleToAgent) pushToAgent();
22
- if (config.persist) schedulePersist();
23
- }
24
- function pushToAgent() {
25
- const summary = config.summarize?.(state);
26
- synapse.setVisibleState(state, summary);
27
- }
28
- function schedulePersist() {
29
- if (persistTimer) clearTimeout(persistTimer);
30
- persistTimer = setTimeout(() => {
31
- synapse._request("synapse/persist-state", {
32
- state,
33
- version: config.version
34
- }).catch(() => {
35
- });
36
- persistTimer = null;
37
- }, 500);
38
- }
39
- let unsubStateLoaded;
40
- if (config.persist) {
41
- unsubStateLoaded = synapse._onMessage("synapse/state-loaded", (params) => {
42
- if (!params?.state) return;
43
- let loaded = params.state;
44
- const loadedVersion = params.version ?? 1;
45
- const currentVersion = config.version ?? 1;
46
- if (config.migrations && loadedVersion < currentVersion) {
47
- const startIdx = loadedVersion - 1;
48
- for (let i = startIdx; i < config.migrations.length; i++) {
49
- loaded = config.migrations[i](loaded);
50
- }
51
- }
52
- store.hydrate(loaded);
53
- });
54
- }
55
- const store = {
56
- getState() {
57
- return state;
58
- },
59
- subscribe(callback) {
60
- subscribers.add(callback);
61
- return () => {
62
- subscribers.delete(callback);
63
- };
64
- },
65
- dispatch,
66
- hydrate(newState) {
67
- state = newState;
68
- for (const cb of subscribers) cb(state);
69
- },
70
- destroy() {
71
- if (destroyed) return;
72
- destroyed = true;
73
- if (persistTimer) clearTimeout(persistTimer);
74
- subscribers.clear();
75
- unsubStateLoaded?.();
76
- }
77
- };
78
- return store;
79
- }
80
-
81
- export { createStore };
1
+ export { HostUnsupportedError, SYNAPSE_DATA_ELEMENT_ID, connectUI, detectHostKind } from './chunk-SRQNQ26I.js';
2
+ export { action, callToolAsTask, connect, downloadFile, pickFile, pickFiles } from './chunk-VYR6V47N.js';
3
+ export { FONT_FACES_CONTEXT_KEY } from './chunk-UPDBDXQB.js';
82
4
  //# sourceMappingURL=index.js.map
83
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"synapse/persist-state\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"synapse/state-loaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}