@nimblebrain/synapse 0.12.2 → 0.13.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 (51) hide show
  1. package/README.md +54 -2
  2. package/dist/{chunk-JVKQNMAP.js → chunk-5AR3IROW.js} +11 -6
  3. package/dist/chunk-5AR3IROW.js.map +1 -0
  4. package/dist/{chunk-XGJAADVV.js → chunk-AGN3NDOK.js} +25 -36
  5. package/dist/chunk-AGN3NDOK.js.map +1 -0
  6. package/dist/chunk-DOKVNVTI.js +162 -0
  7. package/dist/chunk-DOKVNVTI.js.map +1 -0
  8. package/dist/chunk-IA2M4GTK.cjs +170 -0
  9. package/dist/chunk-IA2M4GTK.cjs.map +1 -0
  10. package/dist/{chunk-A4ENX6XW.cjs → chunk-QHS7BJLI.cjs} +28 -39
  11. package/dist/chunk-QHS7BJLI.cjs.map +1 -0
  12. package/dist/{chunk-ANUZ7WFQ.cjs → chunk-VMUZMVKW.cjs} +11 -6
  13. package/dist/chunk-VMUZMVKW.cjs.map +1 -0
  14. package/dist/codegen/index.d.cts +1 -1
  15. package/dist/codegen/index.d.ts +1 -1
  16. package/dist/connect.iife.global.js +25 -25
  17. package/dist/{detect-DSnLT-_m.d.ts → detect-C_qmYsh9.d.cts} +6 -0
  18. package/dist/{detect-DSnLT-_m.d.cts → detect-Dfd0upoz.d.ts} +6 -0
  19. package/dist/host/index.cjs +14 -14
  20. package/dist/host/index.d.cts +10 -3
  21. package/dist/host/index.d.ts +10 -3
  22. package/dist/host/index.js +2 -2
  23. package/dist/index.cjs +13 -9
  24. package/dist/index.d.cts +16 -4
  25. package/dist/index.d.ts +16 -4
  26. package/dist/index.js +3 -3
  27. package/dist/react/index.cjs +5 -5
  28. package/dist/react/index.cjs.map +1 -1
  29. package/dist/react/index.d.cts +1 -1
  30. package/dist/react/index.d.ts +1 -1
  31. package/dist/react/index.js +3 -3
  32. package/dist/react/index.js.map +1 -1
  33. package/dist/synapse-runtime.iife.global.js +25 -25
  34. package/dist/synapse-ui.iife.global.js +1 -1
  35. package/dist/{types-C9utGXv_.d.cts → types-BSZasM8q.d.cts} +39 -1
  36. package/dist/{types-C9utGXv_.d.ts → types-BSZasM8q.d.ts} +39 -1
  37. package/package.json +1 -6
  38. package/dist/chunk-A4ENX6XW.cjs.map +0 -1
  39. package/dist/chunk-ANUZ7WFQ.cjs.map +0 -1
  40. package/dist/chunk-JVKQNMAP.js.map +0 -1
  41. package/dist/chunk-KTXASIFJ.cjs +0 -75
  42. package/dist/chunk-KTXASIFJ.cjs.map +0 -1
  43. package/dist/chunk-VXTMI266.js +0 -73
  44. package/dist/chunk-VXTMI266.js.map +0 -1
  45. package/dist/chunk-XGJAADVV.js.map +0 -1
  46. package/dist/ui/fonts.cjs +0 -19
  47. package/dist/ui/fonts.cjs.map +0 -1
  48. package/dist/ui/fonts.d.cts +0 -30
  49. package/dist/ui/fonts.d.ts +0 -30
  50. package/dist/ui/fonts.js +0 -17
  51. package/dist/ui/fonts.js.map +0 -1
@@ -1,3 +1,5 @@
1
+ import { F as FontFaceDescriptor } from './types-BSZasM8q.cjs';
2
+
1
3
  /**
2
4
  * Cross-host UI client — types and wire constants.
3
5
  *
@@ -17,6 +19,7 @@
17
19
  * hatch — apps should rarely branch on it; `capabilities()` is the supported way
18
20
  * to feature-detect. `"nimblebrain"` is reserved for the runtime adapter (P3).
19
21
  */
22
+
20
23
  type HostKind = "chatgpt" | "claude" | "nimblebrain" | "generic";
21
24
  /** Resolved theme. `mode` always resolves to light or dark. `tokens` are CSS
22
25
  * custom properties the host publishes — the MCP Apps adapter reads them from
@@ -25,6 +28,9 @@ type HostKind = "chatgpt" | "claude" | "nimblebrain" | "generic";
25
28
  interface SynapseUITheme {
26
29
  mode: "light" | "dark";
27
30
  tokens: Record<string, string>;
31
+ /** Font faces the host wants loaded. Absent where the host sends none, which
32
+ * leaves the SDK's web-safe fallbacks in force. See `FontFaceDescriptor`. */
33
+ fontFaces?: FontFaceDescriptor[];
28
34
  }
29
35
  /** What the active host actually supports. `data()`/`onData()`/`theme()`/
30
36
  * `resize()` work everywhere; these three vary. */
@@ -1,3 +1,5 @@
1
+ import { F as FontFaceDescriptor } from './types-BSZasM8q.js';
2
+
1
3
  /**
2
4
  * Cross-host UI client — types and wire constants.
3
5
  *
@@ -17,6 +19,7 @@
17
19
  * hatch — apps should rarely branch on it; `capabilities()` is the supported way
18
20
  * to feature-detect. `"nimblebrain"` is reserved for the runtime adapter (P3).
19
21
  */
22
+
20
23
  type HostKind = "chatgpt" | "claude" | "nimblebrain" | "generic";
21
24
  /** Resolved theme. `mode` always resolves to light or dark. `tokens` are CSS
22
25
  * custom properties the host publishes — the MCP Apps adapter reads them from
@@ -25,6 +28,9 @@ type HostKind = "chatgpt" | "claude" | "nimblebrain" | "generic";
25
28
  interface SynapseUITheme {
26
29
  mode: "light" | "dark";
27
30
  tokens: Record<string, string>;
31
+ /** Font faces the host wants loaded. Absent where the host sends none, which
32
+ * leaves the SDK's web-safe fallbacks in force. See `FontFaceDescriptor`. */
33
+ fontFaces?: FontFaceDescriptor[];
28
34
  }
29
35
  /** What the active host actually supports. `data()`/`onData()`/`theme()`/
30
36
  * `resize()` work everywhere; these three vary. */
@@ -1,57 +1,57 @@
1
1
  'use strict';
2
2
 
3
- var chunkANUZ7WFQ_cjs = require('../chunk-ANUZ7WFQ.cjs');
4
- require('../chunk-KTXASIFJ.cjs');
3
+ var chunkVMUZMVKW_cjs = require('../chunk-VMUZMVKW.cjs');
4
+ require('../chunk-IA2M4GTK.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "HostUnsupportedError", {
9
9
  enumerable: true,
10
- get: function () { return chunkANUZ7WFQ_cjs.HostUnsupportedError; }
10
+ get: function () { return chunkVMUZMVKW_cjs.HostUnsupportedError; }
11
11
  });
12
12
  Object.defineProperty(exports, "SYNAPSE_DATA_ELEMENT_ID", {
13
13
  enumerable: true,
14
- get: function () { return chunkANUZ7WFQ_cjs.SYNAPSE_DATA_ELEMENT_ID; }
14
+ get: function () { return chunkVMUZMVKW_cjs.SYNAPSE_DATA_ELEMENT_ID; }
15
15
  });
16
16
  Object.defineProperty(exports, "adapterForKind", {
17
17
  enumerable: true,
18
- get: function () { return chunkANUZ7WFQ_cjs.adapterForKind; }
18
+ get: function () { return chunkVMUZMVKW_cjs.adapterForKind; }
19
19
  });
20
20
  Object.defineProperty(exports, "applyHostTheme", {
21
21
  enumerable: true,
22
- get: function () { return chunkANUZ7WFQ_cjs.applyHostTheme; }
22
+ get: function () { return chunkVMUZMVKW_cjs.applyHostTheme; }
23
23
  });
24
24
  Object.defineProperty(exports, "coerceMode", {
25
25
  enumerable: true,
26
- get: function () { return chunkANUZ7WFQ_cjs.coerceMode; }
26
+ get: function () { return chunkVMUZMVKW_cjs.coerceMode; }
27
27
  });
28
28
  Object.defineProperty(exports, "connectUI", {
29
29
  enumerable: true,
30
- get: function () { return chunkANUZ7WFQ_cjs.connectUI; }
30
+ get: function () { return chunkVMUZMVKW_cjs.connectUI; }
31
31
  });
32
32
  Object.defineProperty(exports, "createChatGPTAdapter", {
33
33
  enumerable: true,
34
- get: function () { return chunkANUZ7WFQ_cjs.createChatGPTAdapter; }
34
+ get: function () { return chunkVMUZMVKW_cjs.createChatGPTAdapter; }
35
35
  });
36
36
  Object.defineProperty(exports, "createInlineAdapter", {
37
37
  enumerable: true,
38
- get: function () { return chunkANUZ7WFQ_cjs.createInlineAdapter; }
38
+ get: function () { return chunkVMUZMVKW_cjs.createInlineAdapter; }
39
39
  });
40
40
  Object.defineProperty(exports, "createMcpAppsAdapter", {
41
41
  enumerable: true,
42
- get: function () { return chunkANUZ7WFQ_cjs.createMcpAppsAdapter; }
42
+ get: function () { return chunkVMUZMVKW_cjs.createMcpAppsAdapter; }
43
43
  });
44
44
  Object.defineProperty(exports, "detectHostKind", {
45
45
  enumerable: true,
46
- get: function () { return chunkANUZ7WFQ_cjs.detectHostKind; }
46
+ get: function () { return chunkVMUZMVKW_cjs.detectHostKind; }
47
47
  });
48
48
  Object.defineProperty(exports, "preferredMode", {
49
49
  enumerable: true,
50
- get: function () { return chunkANUZ7WFQ_cjs.preferredMode; }
50
+ get: function () { return chunkVMUZMVKW_cjs.preferredMode; }
51
51
  });
52
52
  Object.defineProperty(exports, "selectAdapter", {
53
53
  enumerable: true,
54
- get: function () { return chunkANUZ7WFQ_cjs.selectAdapter; }
54
+ get: function () { return chunkVMUZMVKW_cjs.selectAdapter; }
55
55
  });
56
56
  //# sourceMappingURL=index.cjs.map
57
57
  //# sourceMappingURL=index.cjs.map
@@ -1,5 +1,8 @@
1
- import { C as ConnectUIOptions, g as HostAdapter, d as SynapseUITheme } from '../detect-DSnLT-_m.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-DSnLT-_m.cjs';
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';
4
+ import '@modelcontextprotocol/ext-apps';
5
+ import '@modelcontextprotocol/sdk/types.js';
3
6
 
4
7
  /**
5
8
  * ChatGPT (OpenAI Apps SDK) adapter.
@@ -50,12 +53,16 @@ declare function createMcpAppsAdapter(win: Window & typeof globalThis, options:
50
53
  * - `document.documentElement[data-theme="light"|"dark"]` — how self-contained
51
54
  * HTML components (Bassethound's report) gate their `--var` palettes, and the
52
55
  * lever a host's light/dark signal actually flips.
53
- * - CSS custom properties via {@link applyThemeVariables} — how the
56
+ * - CSS custom properties via {@link applyTheme} — how the
54
57
  * `@nimblebrain/synapse/ui` token components consume theme, backed by the
55
58
  * SDK's neutral defaults so every referenced var resolves in both modes.
56
59
  *
57
60
  * Setting both means an app can use either convention (or a host that supplies
58
61
  * only a mode string, like the OpenAI Apps SDK, still themes correctly). SSR-safe.
62
+ *
63
+ * Any `fontFaces` the host supplies are loaded here too — a token can name a
64
+ * family but not load it, so the two travel together. A host that sends none
65
+ * leaves the web-safe fallbacks in force.
59
66
  */
60
67
  declare function applyHostTheme(theme: SynapseUITheme): void;
61
68
  /** Read the OS-level color scheme as a sane default for hosts that don't push a
@@ -1,5 +1,8 @@
1
- import { C as ConnectUIOptions, g as HostAdapter, d as SynapseUITheme } from '../detect-DSnLT-_m.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-DSnLT-_m.js';
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';
4
+ import '@modelcontextprotocol/ext-apps';
5
+ import '@modelcontextprotocol/sdk/types.js';
3
6
 
4
7
  /**
5
8
  * ChatGPT (OpenAI Apps SDK) adapter.
@@ -50,12 +53,16 @@ declare function createMcpAppsAdapter(win: Window & typeof globalThis, options:
50
53
  * - `document.documentElement[data-theme="light"|"dark"]` — how self-contained
51
54
  * HTML components (Bassethound's report) gate their `--var` palettes, and the
52
55
  * lever a host's light/dark signal actually flips.
53
- * - CSS custom properties via {@link applyThemeVariables} — how the
56
+ * - CSS custom properties via {@link applyTheme} — how the
54
57
  * `@nimblebrain/synapse/ui` token components consume theme, backed by the
55
58
  * SDK's neutral defaults so every referenced var resolves in both modes.
56
59
  *
57
60
  * Setting both means an app can use either convention (or a host that supplies
58
61
  * only a mode string, like the OpenAI Apps SDK, still themes correctly). SSR-safe.
62
+ *
63
+ * Any `fontFaces` the host supplies are loaded here too — a token can name a
64
+ * family but not load it, so the two travel together. A host that sends none
65
+ * leaves the web-safe fallbacks in force.
59
66
  */
60
67
  declare function applyHostTheme(theme: SynapseUITheme): void;
61
68
  /** Read the OS-level color scheme as a sane default for hosts that don't push a
@@ -1,4 +1,4 @@
1
- export { HostUnsupportedError, SYNAPSE_DATA_ELEMENT_ID, adapterForKind, applyHostTheme, coerceMode, connectUI, createChatGPTAdapter, createInlineAdapter, createMcpAppsAdapter, detectHostKind, preferredMode, selectAdapter } from '../chunk-JVKQNMAP.js';
2
- import '../chunk-VXTMI266.js';
1
+ export { HostUnsupportedError, SYNAPSE_DATA_ELEMENT_ID, adapterForKind, applyHostTheme, coerceMode, connectUI, createChatGPTAdapter, createInlineAdapter, createMcpAppsAdapter, detectHostKind, preferredMode, selectAdapter } from '../chunk-5AR3IROW.js';
2
+ import '../chunk-DOKVNVTI.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkANUZ7WFQ_cjs = require('./chunk-ANUZ7WFQ.cjs');
4
- var chunkA4ENX6XW_cjs = require('./chunk-A4ENX6XW.cjs');
5
- require('./chunk-KTXASIFJ.cjs');
3
+ var chunkVMUZMVKW_cjs = require('./chunk-VMUZMVKW.cjs');
4
+ var chunkQHS7BJLI_cjs = require('./chunk-QHS7BJLI.cjs');
5
+ var chunkIA2M4GTK_cjs = require('./chunk-IA2M4GTK.cjs');
6
6
 
7
7
  // src/store.ts
8
8
  function createStore(synapse, config) {
@@ -82,27 +82,31 @@ function createStore(synapse, config) {
82
82
 
83
83
  Object.defineProperty(exports, "HostUnsupportedError", {
84
84
  enumerable: true,
85
- get: function () { return chunkANUZ7WFQ_cjs.HostUnsupportedError; }
85
+ get: function () { return chunkVMUZMVKW_cjs.HostUnsupportedError; }
86
86
  });
87
87
  Object.defineProperty(exports, "SYNAPSE_DATA_ELEMENT_ID", {
88
88
  enumerable: true,
89
- get: function () { return chunkANUZ7WFQ_cjs.SYNAPSE_DATA_ELEMENT_ID; }
89
+ get: function () { return chunkVMUZMVKW_cjs.SYNAPSE_DATA_ELEMENT_ID; }
90
90
  });
91
91
  Object.defineProperty(exports, "connectUI", {
92
92
  enumerable: true,
93
- get: function () { return chunkANUZ7WFQ_cjs.connectUI; }
93
+ get: function () { return chunkVMUZMVKW_cjs.connectUI; }
94
94
  });
95
95
  Object.defineProperty(exports, "detectHostKind", {
96
96
  enumerable: true,
97
- get: function () { return chunkANUZ7WFQ_cjs.detectHostKind; }
97
+ get: function () { return chunkVMUZMVKW_cjs.detectHostKind; }
98
98
  });
99
99
  Object.defineProperty(exports, "connect", {
100
100
  enumerable: true,
101
- get: function () { return chunkA4ENX6XW_cjs.connect; }
101
+ get: function () { return chunkQHS7BJLI_cjs.connect; }
102
102
  });
103
103
  Object.defineProperty(exports, "createSynapse", {
104
104
  enumerable: true,
105
- get: function () { return chunkA4ENX6XW_cjs.createSynapse; }
105
+ get: function () { return chunkQHS7BJLI_cjs.createSynapse; }
106
+ });
107
+ Object.defineProperty(exports, "FONT_FACES_CONTEXT_KEY", {
108
+ enumerable: true,
109
+ get: function () { return chunkIA2M4GTK_cjs.FONT_FACES_CONTEXT_KEY; }
106
110
  });
107
111
  exports.createStore = createStore;
108
112
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
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-C9utGXv_.cjs';
3
- export { e as AgentAction, f as AppEventName, B as BuiltinActionType, g as CallToolAsTaskOptions, D as DataChangedEvent, h as Dimensions, F as FileResult, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, i as NotifyPayload, R as RequestFileOptions, j as StateAcknowledgement, k as StoreDispatch, l as SynapseTheme, m as TaskHandle, n as TasksCapability, o as Theme, p as ToolCallResult, T as ToolDefinition, q as ToolResultData, V as VisibleState } from './types-C9utGXv_.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-DSnLT-_m.cjs';
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
5
  import '@modelcontextprotocol/ext-apps';
6
6
 
7
7
  /**
@@ -23,6 +23,18 @@ declare function connect(options: ConnectOptions): Promise<App>;
23
23
  */
24
24
  declare function createSynapse(options: SynapseOptions): Synapse;
25
25
 
26
+ /**
27
+ * Host-context key carrying `@font-face` descriptors.
28
+ *
29
+ * A NimbleBrain extension (`synapse/` prefix), because the ext-apps spec has no
30
+ * equivalent: `styles.variables` is a flat `Record<McpUiStyleVariableKey, string>`
31
+ * that can name a font family but cannot carry the rule that loads it.
32
+ * `McpUiHostContext` declares `[key: string]: unknown` for forward
33
+ * compatibility, so riding an extra key is spec-legal, and hosts that don't send
34
+ * it degrade to the web-safe token fallbacks.
35
+ */
36
+ declare const FONT_FACES_CONTEXT_KEY = "synapse/fontFaces";
37
+
26
38
  /**
27
39
  * Create a typed state store with optional persistence and agent visibility.
28
40
  *
@@ -34,4 +46,4 @@ declare function createStore<TState, TActions extends Record<string, ActionReduc
34
46
  actions: TActions;
35
47
  }): Store<TState, TActions>;
36
48
 
37
- export { ActionReducer, App, ConnectOptions, Store, StoreConfig, Synapse, SynapseOptions, connect, createStore, createSynapse };
49
+ export { ActionReducer, App, ConnectOptions, FONT_FACES_CONTEXT_KEY, Store, StoreConfig, Synapse, SynapseOptions, connect, createStore, createSynapse };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
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-C9utGXv_.js';
3
- export { e as AgentAction, f as AppEventName, B as BuiltinActionType, g as CallToolAsTaskOptions, D as DataChangedEvent, h as Dimensions, F as FileResult, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, i as NotifyPayload, R as RequestFileOptions, j as StateAcknowledgement, k as StoreDispatch, l as SynapseTheme, m as TaskHandle, n as TasksCapability, o as Theme, p as ToolCallResult, T as ToolDefinition, q as ToolResultData, V as VisibleState } from './types-C9utGXv_.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-DSnLT-_m.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
5
  import '@modelcontextprotocol/ext-apps';
6
6
 
7
7
  /**
@@ -23,6 +23,18 @@ declare function connect(options: ConnectOptions): Promise<App>;
23
23
  */
24
24
  declare function createSynapse(options: SynapseOptions): Synapse;
25
25
 
26
+ /**
27
+ * Host-context key carrying `@font-face` descriptors.
28
+ *
29
+ * A NimbleBrain extension (`synapse/` prefix), because the ext-apps spec has no
30
+ * equivalent: `styles.variables` is a flat `Record<McpUiStyleVariableKey, string>`
31
+ * that can name a font family but cannot carry the rule that loads it.
32
+ * `McpUiHostContext` declares `[key: string]: unknown` for forward
33
+ * compatibility, so riding an extra key is spec-legal, and hosts that don't send
34
+ * it degrade to the web-safe token fallbacks.
35
+ */
36
+ declare const FONT_FACES_CONTEXT_KEY = "synapse/fontFaces";
37
+
26
38
  /**
27
39
  * Create a typed state store with optional persistence and agent visibility.
28
40
  *
@@ -34,4 +46,4 @@ declare function createStore<TState, TActions extends Record<string, ActionReduc
34
46
  actions: TActions;
35
47
  }): Store<TState, TActions>;
36
48
 
37
- export { ActionReducer, App, ConnectOptions, Store, StoreConfig, Synapse, SynapseOptions, connect, createStore, createSynapse };
49
+ export { ActionReducer, App, ConnectOptions, FONT_FACES_CONTEXT_KEY, Store, StoreConfig, Synapse, SynapseOptions, connect, createStore, createSynapse };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- export { HostUnsupportedError, SYNAPSE_DATA_ELEMENT_ID, connectUI, detectHostKind } from './chunk-JVKQNMAP.js';
2
- export { connect, createSynapse } from './chunk-XGJAADVV.js';
3
- import './chunk-VXTMI266.js';
1
+ export { HostUnsupportedError, SYNAPSE_DATA_ELEMENT_ID, connectUI, detectHostKind } from './chunk-5AR3IROW.js';
2
+ export { connect, createSynapse } from './chunk-AGN3NDOK.js';
3
+ export { FONT_FACES_CONTEXT_KEY } from './chunk-DOKVNVTI.js';
4
4
 
5
5
  // src/store.ts
6
6
  function createStore(synapse, config) {
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkA4ENX6XW_cjs = require('../chunk-A4ENX6XW.cjs');
4
- var chunkKTXASIFJ_cjs = require('../chunk-KTXASIFJ.cjs');
3
+ var chunkQHS7BJLI_cjs = require('../chunk-QHS7BJLI.cjs');
4
+ var chunkIA2M4GTK_cjs = require('../chunk-IA2M4GTK.cjs');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
@@ -12,7 +12,7 @@ function AppProvider({ children, name, version, autoResize }) {
12
12
  react.useEffect(() => {
13
13
  if (connectingRef.current) return;
14
14
  connectingRef.current = true;
15
- chunkA4ENX6XW_cjs.connect({ name, version, autoResize }).then((a) => {
15
+ chunkQHS7BJLI_cjs.connect({ name, version, autoResize }).then((a) => {
16
16
  setApp(a);
17
17
  });
18
18
  }, []);
@@ -72,7 +72,7 @@ var SynapseContext = react.createContext(null);
72
72
  function SynapseProvider({ children, ...options }) {
73
73
  const ref = react.useRef(null);
74
74
  if (ref.current === null || ref.current.destroyed) {
75
- ref.current = chunkA4ENX6XW_cjs.createSynapse(options);
75
+ ref.current = chunkQHS7BJLI_cjs.createSynapse(options);
76
76
  }
77
77
  return /* @__PURE__ */ jsxRuntime.jsxs(SynapseContext.Provider, { value: ref.current, children: [
78
78
  /* @__PURE__ */ jsxRuntime.jsx(ThemeInjector, { synapse: ref.current }),
@@ -86,7 +86,7 @@ function ThemeInjector({ synapse }) {
86
86
  return synapse.onThemeChanged(setTheme);
87
87
  }, [synapse]);
88
88
  react.useEffect(() => {
89
- chunkKTXASIFJ_cjs.applyThemeVariables(theme.mode, theme.tokens);
89
+ chunkIA2M4GTK_cjs.applyTheme(theme.mode, theme.tokens, theme.fontFaces);
90
90
  }, [theme]);
91
91
  return null;
92
92
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/app-provider.tsx","../../src/react/connect-hooks.ts","../../src/react/provider.tsx","../../src/react/hooks.ts"],"names":["createContext","useState","useRef","useEffect","connect","useContext","useCallback","createSynapse","jsx","applyThemeVariables","useSyncExternalStore","isTerminal"],"mappings":";;;;;;;AAIA,IAAM,UAAA,GAAaA,oBAA0B,IAAI,CAAA;AAM1C,SAAS,YAAY,EAAE,QAAA,EAAU,IAAA,EAAM,OAAA,EAAS,YAAW,EAAqB;AACrF,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,CAAA,GAAIC,eAAqB,IAAI,CAAA;AAC/C,EAAA,MAAM,aAAA,GAAgBC,aAAO,KAAK,CAAA;AAGlC,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,cAAc,OAAA,EAAS;AAC3B,IAAA,aAAA,CAAc,OAAA,GAAU,IAAA;AAExB,IAAAC,yBAAA,CAAQ,EAAE,MAAM,OAAA,EAAS,UAAA,EAAY,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,KAAM;AACjD,MAAA,MAAA,CAAO,CAAC,CAAA;AAAA,IACV,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AAEjB,EAAA,sCAAQ,UAAA,CAAW,QAAA,EAAX,EAAoB,KAAA,EAAO,KAAM,QAAA,EAAS,CAAA;AACpD;AAEO,SAAS,aAAA,GAAqB;AACnC,EAAA,MAAM,GAAA,GAAMC,iBAAW,UAAU,CAAA;AACjC,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;;;AC/BO,SAAS,MAAA,GAAc;AAC5B,EAAA,OAAO,aAAA,EAAc;AACvB;AAEO,SAAS,aAAA,GAAuC;AACrD,EAAA,MAAM,MAAM,aAAA,EAAc;AAC1B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIJ,eAAgC,IAAI,CAAA;AAE5D,EAAAE,gBAAU,MAAM;AACd,IAAA,OAAO,GAAA,CAAI,EAAA,CAAG,aAAA,EAAe,CAAC,MAAA,KAA2B;AACvD,MAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,IAChB,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,YAAA,GAA+C;AAC7D,EAAA,MAAM,MAAM,aAAA,EAAc;AAC1B,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIF,eAAyC,IAAI,CAAA;AAEvE,EAAAE,gBAAU,MAAM;AACd,IAAA,OAAO,GAAA,CAAI,EAAA,CAAG,YAAA,EAAc,CAAC,IAAA,KAAkC;AAC7D,MAAA,QAAA,CAAS,IAAI,CAAA;AAAA,IACf,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,eAAA,GAAyB;AACvC,EAAA,MAAM,MAAM,aAAA,EAAc;AAC1B,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAIF,cAAAA,CAAgB,MAAM,IAAI,KAAK,CAAA;AAEzD,EAAAE,gBAAU,MAAM;AACd,IAAA,QAAA,CAAS,IAAI,KAAK,CAAA;AAClB,IAAA,OAAO,GAAA,CAAI,EAAA,CAAG,eAAA,EAAiB,CAAC,CAAA,KAAa;AAC3C,MAAA,QAAA,CAAS,CAAC,CAAA;AAAA,IACZ,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,SAAA,GAAuD;AACrE,EAAA,MAAM,MAAM,aAAA,EAAc;AAC1B,EAAA,OAAOG,iBAAA,CAAY,CAAC,KAAA,EAAgB,MAAA,KAAoB,GAAA,CAAI,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAC1F;AChDA,IAAM,cAAA,GAAiBN,oBAA8B,IAAI,CAAA;AAMlD,SAAS,eAAA,CAAgB,EAAE,QAAA,EAAU,GAAG,SAAQ,EAAyB;AAK9E,EAAA,MAAM,GAAA,GAAME,aAAuB,IAAI,CAAA;AAEvC,EAAA,IAAI,GAAA,CAAI,OAAA,KAAY,IAAA,IAAQ,GAAA,CAAI,QAAQ,SAAA,EAAW;AACjD,IAAA,GAAA,CAAI,OAAA,GAAUK,gCAAc,OAAO,CAAA;AAAA,EACrC;AAEA,EAAA,uCACG,cAAA,CAAe,QAAA,EAAf,EAAwB,KAAA,EAAO,IAAI,OAAA,EAClC,QAAA,EAAA;AAAA,oBAAAC,cAAAA,CAAC,aAAA,EAAA,EAAc,OAAA,EAAS,GAAA,CAAI,OAAA,EAAS,CAAA;AAAA,IACpC;AAAA,GAAA,EACH,CAAA;AAEJ;AAGA,SAAS,aAAA,CAAc,EAAE,OAAA,EAAQ,EAAyB;AACxD,EAAA,MAAM,CAAC,OAAO,QAAQ,CAAA,GAAIP,eAAuB,MAAM,OAAA,CAAQ,UAAU,CAAA;AAEzE,EAAAE,gBAAU,MAAM;AACd,IAAA,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA;AAC3B,IAAA,OAAO,OAAA,CAAQ,eAAe,QAAQ,CAAA;AAAA,EACxC,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAAA,gBAAU,MAAM;AAGd,IAAAM,qCAAA,CAAoB,KAAA,CAAM,IAAA,EAAM,KAAA,CAAM,MAAM,CAAA;AAAA,EAC9C,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,iBAAA,GAA6B;AAC3C,EAAA,MAAM,GAAA,GAAMJ,iBAAW,cAAc,CAAA;AACrC,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;;;ACnCO,SAAS,UAAA,GAAsB;AACpC,EAAA,OAAO,iBAAA,EAAkB;AAC3B;AAEO,SAAS,YACd,QAAA,EAMA;AACA,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIJ,eAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIA,eAAyB,IAAI,CAAA;AACrD,EAAA,MAAM,SAAA,GAAYC,aAAO,CAAC,CAAA;AAE1B,EAAA,MAAM,IAAA,GAAOI,iBAAAA;AAAA,IACX,OAAO,IAAA,KAAqE;AAC1E,MAAA,MAAM,EAAA,GAAK,EAAE,SAAA,CAAU,OAAA;AACvB,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,QAAA,CAAS,IAAI,CAAA;AAEb,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,QAAA,CAA2C,UAAU,IAAI,CAAA;AAEtF,QAAA,IAAI,EAAA,KAAO,UAAU,OAAA,EAAS;AAC5B,UAAA,OAAA,CAAQ,OAAO,IAAI,CAAA;AACnB,UAAA,YAAA,CAAa,KAAK,CAAA;AAAA,QACpB;AACA,QAAA,OAAO,MAAA;AAAA,MACT,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,EAAA,KAAO,UAAU,OAAA,EAAS;AAC5B,UAAA,MAAM,CAAA,GAAI,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAC5D,UAAA,QAAA,CAAS,CAAC,CAAA;AACV,UAAA,YAAA,CAAa,KAAK,CAAA;AAAA,QACpB;AACA,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,IACF,CAAA;AAAA,IACA,CAAC,SAAS,QAAQ;AAAA,GACpB;AAEA,EAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,IAAA,EAAK;AACxC;AAEO,SAAS,YAAY,QAAA,EAAmD;AAC7E,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,MAAM,WAAA,GAAcJ,aAAO,QAAQ,CAAA;AACnC,EAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAEtB,EAAAC,gBAAU,MAAM;AACd,IAAA,OAAO,QAAQ,aAAA,CAAc,CAAC,UAAU,WAAA,CAAY,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EACpE,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AACd;AAkBO,SAAS,eAAe,QAAA,EAA+C;AAC5E,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,MAAM,WAAA,GAAcD,aAAO,QAAQ,CAAA;AACnC,EAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAEtB,EAAAC,gBAAU,MAAM;AACd,IAAA,OAAO,QAAQ,QAAA,CAAS,CAAC,WAAW,WAAA,CAAY,OAAA,CAAQ,MAAM,CAAC,CAAA;AAAA,EACjE,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AACd;AAiBO,SAAS,cAAA,GAAmE;AACjF,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,MAAM,CAAC,KAAK,MAAM,CAAA,GAAIF,eAAY,MAAM,OAAA,CAAQ,gBAAqB,CAAA;AAErE,EAAAE,gBAAU,MAAM;AAEd,IAAA,MAAA,CAAO,OAAA,CAAQ,gBAAqB,CAAA;AACpC,IAAA,OAAO,QAAQ,oBAAA,CAAqB,CAAC,CAAA,KAAM,MAAA,CAAO,CAAM,CAAC,CAAA;AAAA,EAC3D,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,OAAO,GAAA;AACT;AAcO,SAAS,QAAA,GAAyB;AACvC,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,MAAM,CAAC,OAAO,QAAQ,CAAA,GAAIF,eAAuB,MAAM,OAAA,CAAQ,UAAU,CAAA;AAEzE,EAAAE,gBAAU,MAAM;AAEd,IAAA,QAAA,CAAS,OAAA,CAAQ,UAAU,CAAA;AAC3B,IAAA,OAAO,OAAA,CAAQ,eAAe,QAAQ,CAAA;AAAA,EACxC,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,SAAA,GAAwE;AACtF,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,OAAOG,iBAAAA;AAAA,IACL,CAAC,MAAA,EAAgB,MAAA,KAAqC,OAAA,CAAQ,MAAA,CAAO,QAAQ,MAAM,CAAA;AAAA,IACnF,CAAC,OAAO;AAAA,GACV;AACF;AAEO,SAAS,OAAA,GAGN;AACR,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,OAAOA,iBAAAA;AAAA,IACL,CAAC,OAAA,EAAiB,OAAA,KAChB,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,IAC/B,CAAC,OAAO;AAAA,GACV;AACF;AAwBO,SAAS,eAAA,CACd,SACA,IAAA,EAC0E;AAC1E,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,MAAM,IAAA,GAAOA,iBAAAA;AAAA,IACX,CAAC,KAAA,EAAgC,OAAA,KAAqB,OAAA,CAAQ,eAAA,CAAgB,OAAO,OAAO,CAAA;AAAA,IAC5F,CAAC,OAAO;AAAA,GACV;AAIA,EAAA,MAAM,UAAA,GAAaJ,aAAO,OAAO,CAAA;AACjC,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AACrB,EAAAC,gBAAU,MAAM;AACd,IAAA,IAAI,CAAC,WAAW,OAAA,EAAS;AACzB,IAAA,MAAM,EAAE,KAAA,EAAO,OAAA,EAAQ,GAAI,WAAW,OAAA,EAAQ;AAC9C,IAAA,IAAA,CAAK,OAAO,OAAO,CAAA;AAAA,EACrB,GAAG,CAAC,GAAI,QAAQ,EAAC,EAAI,IAAI,CAAC,CAAA;AAE1B,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AACvB;AAEO,SAAS,aAAA,GAId;AACA,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIF,eAAS,KAAK,CAAA;AAEhD,EAAA,MAAM,QAAA,GAAWK,iBAAAA;AAAA,IACf,OAAO,OAAA,KAAiC;AACtC,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA;AAAA,MACvC,CAAA,SAAE;AACA,QAAA,YAAA,CAAa,KAAK,CAAA;AAAA,MACpB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAA,MAAM,SAAA,GAAYA,iBAAAA;AAAA,IAChB,OAAO,OAAA,KAAiC;AACtC,MAAA,YAAA,CAAa,IAAI,CAAA;AACjB,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,OAAA,CAAQ,SAAA,CAAU,OAAO,CAAA;AAAA,MACxC,CAAA,SAAE;AACA,QAAA,YAAA,CAAa,KAAK,CAAA;AAAA,MACpB;AAAA,IACF,CAAA;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,SAAA,EAAU;AAC1C;AAEO,SAAS,SACd,KAAA,EAIA;AACA,EAAA,MAAM,KAAA,GAAQI,0BAAA;AAAA,IACZ,CAAC,aAAA,KAAkB,KAAA,CAAM,SAAA,CAAU,aAAa,CAAA;AAAA,IAChD,MAAM,MAAM,QAAA,EAAS;AAAA,IACrB,MAAM,MAAM,QAAA;AAAS,GACvB;AAEA,EAAA,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,KAAA,CAAM,QAAA,EAAS;AAC3C;AAaA,IAAM,gBAAA,GAAmB,WAAA;AACzB,IAAM,aAAA,GAAgB,QAAA;AACtB,IAAM,gBAAA,GAAmB,WAAA;AAEzB,IAAM,iBAAA,uBAAiD,GAAA,CAAgB;AAAA,EACrE,gBAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAC,CAAA;AAUD,IAAM,wBAAA,GAA2B,GAAA;AACjC,IAAM,wBAAA,GAA2B,GAAA;AAUjC,IAAM,oBAAA,GAAuB,CAAA;AAqDtB,SAAS,kBACd,QAAA,EAC0C;AAC1C,EAAA,MAAM,UAAU,iBAAA,EAAkB;AAElC,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIT,eAAsB,IAAI,CAAA;AAClD,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIA,eAAyC,IAAI,CAAA;AACzE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAuB,IAAI,CAAA;AAQrD,EAAA,MAAM,MAAA,GAASC,aAAO,CAAC,CAAA;AAKvB,EAAA,MAAM,SAAA,GAAYA,aAAmC,IAAI,CAAA;AACzD,EAAA,MAAM,cAAA,GAAiBA,aAA4B,IAAI,CAAA;AACvD,EAAA,MAAM,YAAA,GAAeA,aAA6C,IAAI,CAAA;AAItE,EAAA,MAAM,YAAA,GAAeA,YAAAA,CAAe,wBAAA,GAA2B,wBAAwB,CAAA;AAKvF,EAAA,MAAM,WAAA,GAAcA,aAAgB,KAAK,CAAA;AAIzC,EAAA,MAAM,sBAAA,GAAyBA,aAAe,CAAC,CAAA;AAE/C,EAAA,MAAM,cAAA,GAAiBI,kBAAY,MAAM;AACvC,IAAA,IAAI,YAAA,CAAa,YAAY,IAAA,EAAM;AACjC,MAAA,YAAA,CAAa,aAAa,OAAO,CAAA;AACjC,MAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AAAA,IACzB;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAA,GAAgBA,kBAAY,MAAM;AACtC,IAAA,cAAA,EAAe;AACf,IAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,MAAA,cAAA,CAAe,OAAA,EAAQ;AACvB,MAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,IAC3B;AACA,IAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AAAA,EACtB,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,EAAA,MAAM,gBAAA,GAAmBA,iBAAAA;AAAA,IACvB,CAAC,GAAA,KAAgB;AACf,MAAA,cAAA,EAAe;AACf,MAAA,IAAI,YAAY,OAAA,EAAS;AACzB,MAAA,YAAA,CAAa,OAAA,GAAU,WAAW,MAAM;AAEtC,QAAA,IAAI,GAAA,KAAQ,OAAO,OAAA,EAAS;AAC5B,QAAA,MAAM,IAAI,SAAA,CAAU,OAAA;AACpB,QAAA,IAAI,CAAC,CAAA,EAAG;AACR,QAAA,IAAI,YAAY,OAAA,EAAS;AAIzB,QAAA,CAAA,CAAE,SAAQ,CAAE,IAAA;AAAA,UACV,CAAC,KAAA,KAAU;AACT,YAAA,IAAI,GAAA,KAAQ,OAAO,OAAA,EAAS;AAC5B,YAAA,sBAAA,CAAuB,OAAA,GAAU,CAAA;AACjC,YAAA,OAAA,CAAQ,KAAK,CAAA;AACb,YAAA,MAAMK,WAAAA,GAAa,iBAAA,CAAkB,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA;AACrD,YAAA,WAAA,CAAY,OAAA,GAAUA,WAAAA;AACtB,YAAA,IAAI,CAACA,WAAAA,EAAY,gBAAA,CAAiB,GAAG,CAAA;AAAA,UACvC,CAAA;AAAA,UACA,MAAM;AAOJ,YAAA,IAAI,GAAA,KAAQ,OAAO,OAAA,EAAS;AAC5B,YAAA,sBAAA,CAAuB,OAAA,IAAW,CAAA;AAClC,YAAA,IAAI,sBAAA,CAAuB,WAAW,oBAAA,EAAsB;AAC5D,YAAA,IAAI,CAAC,WAAA,CAAY,OAAA,EAAS,gBAAA,CAAiB,GAAG,CAAA;AAAA,UAChD;AAAA,SACF;AAAA,MACF,CAAA,EAAG,aAAa,OAAO,CAAA;AAAA,IACzB,CAAA;AAAA,IACA,CAAC,cAAc;AAAA,GACjB;AAEA,EAAA,MAAM,IAAA,GAAOL,iBAAAA;AAAA,IACX,OAAO,MAAe,OAAA,KAAkE;AAKtF,MAAA,aAAA,EAAc;AACd,MAAA,MAAM,GAAA,GAAM,EAAE,MAAA,CAAO,OAAA;AAKrB,MAAA,SAAA,CAAU,IAAI,CAAA;AACd,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,WAAA,CAAY,OAAA,GAAU,KAAA;AACtB,MAAA,sBAAA,CAAuB,OAAA,GAAU,CAAA;AAEjC,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAM,OAAA,CAAQ,cAAA,CAAgC,QAAA,EAAU,MAAM,OAAO,CAAA;AAAA,MAChF,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,GAAA,KAAQ,MAAA,CAAO,OAAA,EAAS,MAAM,GAAA;AAClC,QAAA,MAAM,CAAA,GAAI,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAC5D,QAAA,QAAA,CAAS,CAAC,CAAA;AACV,QAAA,MAAM,GAAA;AAAA,MACR;AAKA,MAAA,IAAI,GAAA,KAAQ,MAAA,CAAO,OAAA,EAAS,OAAO,MAAA;AAEnC,MAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AAKpB,MAAA,MAAM,cAAA,GAAiB,OAAO,IAAA,CAAK,YAAA;AACnC,MAAA,YAAA,CAAa,OAAA,GACX,OAAO,cAAA,KAAmB,QAAA,IAAY,iBAAiB,CAAA,GACnD,cAAA,GAAiB,2BACjB,wBAAA,GAA2B,wBAAA;AAEjC,MAAA,OAAA,CAAQ,OAAO,IAAI,CAAA;AACnB,MAAA,WAAA,CAAY,OAAA,GAAU,iBAAA,CAAkB,GAAA,CAAI,MAAA,CAAO,KAAK,MAAM,CAAA;AAM9D,MAAA,cAAA,CAAe,OAAA,GAAU,MAAA,CAAO,QAAA,CAAS,CAAC,OAAA,KAAY;AACpD,QAAA,IAAI,GAAA,KAAQ,OAAO,OAAA,EAAS;AAC5B,QAAA,sBAAA,CAAuB,OAAA,GAAU,CAAA;AACjC,QAAA,OAAA,CAAQ,OAAO,CAAA;AACf,QAAA,MAAMK,WAAAA,GAAa,iBAAA,CAAkB,GAAA,CAAI,OAAA,CAAQ,MAAM,CAAA;AACvD,QAAA,WAAA,CAAY,OAAA,GAAUA,WAAAA;AACtB,QAAA,IAAIA,WAAAA,EAAY;AACd,UAAA,cAAA,EAAe;AAAA,QACjB,CAAA,MAAO;AACL,UAAA,gBAAA,CAAiB,GAAG,CAAA;AAAA,QACtB;AAAA,MACF,CAAC,CAAA;AASD,MAAA,MAAA,CAAO,QAAO,CAAE,IAAA;AAAA,QACd,CAAC,GAAA,KAAQ;AACP,UAAA,IAAI,GAAA,KAAQ,OAAO,OAAA,EAAS;AAC5B,UAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,UAAA,cAAA,EAAe;AAMf,UAAA,OAAA,CAAQ,CAAC,IAAA,KAAS;AAChB,YAAA,MAAM,MAAA,GAAqB,GAAA,CAAI,OAAA,GAAU,QAAA,GAAW,WAAA;AACpD,YAAA,MAAM,GAAA,GAAA,iBAAM,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACnC,YAAA,OAAO,OACH,EAAE,GAAG,MAAM,MAAA,EAAQ,aAAA,EAAe,KAAI,GACtC;AAAA,cACE,MAAA,EAAQ,OAAO,IAAA,CAAK,MAAA;AAAA,cACpB,MAAA;AAAA,cACA,GAAA,EAAK,OAAO,IAAA,CAAK,GAAA;AAAA,cACjB,SAAA,EAAW,OAAO,IAAA,CAAK,SAAA;AAAA,cACvB,aAAA,EAAe;AAAA,aACjB;AAAA,UACN,CAAC,CAAA;AACD,UAAA,IAAI,IAAI,OAAA,EAAS;AAMf,YAAA,SAAA,CAAU,GAAG,CAAA;AACb,YAAA,MAAM,GAAA,GACJ,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,IAAY,GAAA,CAAI,IAAA,CAAK,MAAA,GAAS,CAAA,GAC9C,GAAA,CAAI,IAAA,GACJ,CAAA,MAAA,EAAS,QAAQ,CAAA,wBAAA,CAAA;AACvB,YAAA,QAAA,CAAS,IAAI,KAAA,CAAM,GAAG,CAAC,CAAA;AAAA,UACzB,CAAA,MAAO;AACL,YAAA,SAAA,CAAU,GAAG,CAAA;AAAA,UACf;AAAA,QACF,CAAA;AAAA,QACA,CAAC,GAAA,KAAQ;AACP,UAAA,IAAI,GAAA,KAAQ,OAAO,OAAA,EAAS;AAQ5B,UAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,UAAA,cAAA,EAAe;AACf,UAAA,OAAA,CAAQ,CAAC,IAAA,KAAS;AAChB,YAAA,MAAM,GAAA,GAAA,iBAAM,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACnC,YAAA,OAAO,IAAA,GACH,EAAE,GAAG,IAAA,EAAM,QAAQ,QAAA,EAAU,aAAA,EAAe,KAAI,GAChD;AAAA,cACE,MAAA,EAAQ,OAAO,IAAA,CAAK,MAAA;AAAA,cACpB,MAAA,EAAQ,QAAA;AAAA,cACR,GAAA,EAAK,OAAO,IAAA,CAAK,GAAA;AAAA,cACjB,SAAA,EAAW,OAAO,IAAA,CAAK,SAAA;AAAA,cACvB,aAAA,EAAe;AAAA,aACjB;AAAA,UACN,CAAC,CAAA;AACD,UAAA,MAAM,CAAA,GAAI,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAC5D,UAAA,QAAA,CAAS,CAAC,CAAA;AAAA,QACZ;AAAA,OACF;AAGA,MAAA,IAAI,CAAC,WAAA,CAAY,OAAA,EAAS,gBAAA,CAAiB,GAAG,CAAA;AAE9C,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,OAAA,EAAS,QAAA,EAAU,aAAA,EAAe,gBAAgB,gBAAgB;AAAA,GACrE;AAEA,EAAA,MAAM,MAAA,GAASL,kBAAY,YAA2B;AACpD,IAAA,MAAM,IAAI,SAAA,CAAU,OAAA;AACpB,IAAA,IAAI,CAAC,CAAA,EAAG;AACR,IAAA,MAAM,MAAM,MAAA,CAAO,OAAA;AACnB,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,GAAY,MAAM,CAAA,CAAE,MAAA,EAAO;AACjC,MAAA,IAAI,GAAA,KAAQ,OAAO,OAAA,EAAS;AAC5B,MAAA,OAAA,CAAQ,SAAS,CAAA;AACjB,MAAA,WAAA,CAAY,OAAA,GAAU,iBAAA,CAAkB,GAAA,CAAI,SAAA,CAAU,MAAM,CAAA;AAC5D,MAAA,cAAA,EAAe;AAAA,IACjB,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,GAAA,KAAQ,OAAO,OAAA,EAAS;AAC5B,MAAA,MAAM,CAAA,GAAI,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAC5D,MAAA,QAAA,CAAS,CAAC,CAAA;AAAA,IACZ;AAAA,EACF,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAKnB,EAAAH,gBAAU,MAAM;AACd,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,OAAA,IAAW,CAAA;AAClB,MAAA,IAAI,YAAA,CAAa,YAAY,IAAA,EAAM;AACjC,QAAA,YAAA,CAAa,aAAa,OAAO,CAAA;AACjC,QAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AAAA,MACzB;AACA,MAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,QAAA,cAAA,CAAe,OAAA,EAAQ;AACvB,QAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,MAC3B;AACA,MAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AAAA,IACtB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,aAAa,IAAA,KAAS,IAAA,IAAQ,iBAAA,CAAkB,GAAA,CAAI,KAAK,MAAM,CAAA;AACrE,EAAA,MAAM,SAAA,GAAY,IAAA,KAAS,IAAA,IAAQ,CAAC,UAAA;AAEpC,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,QAAQ,KAAA,EAAO,SAAA,EAAW,YAAY,MAAA,EAAO;AACpE","file":"index.cjs","sourcesContent":["import { createContext, type ReactNode, useContext, useEffect, useRef, useState } from \"react\";\nimport { connect } from \"../connect.js\";\nimport type { App, ConnectOptions } from \"../types.js\";\n\nconst AppContext = createContext<App | null>(null);\n\nexport interface AppProviderProps extends ConnectOptions {\n children: ReactNode;\n}\n\nexport function AppProvider({ children, name, version, autoResize }: AppProviderProps) {\n const [app, setApp] = useState<App | null>(null);\n const connectingRef = useRef(false);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: connect once on mount\n useEffect(() => {\n if (connectingRef.current) return;\n connectingRef.current = true;\n\n connect({ name, version, autoResize }).then((a) => {\n setApp(a);\n });\n }, []);\n\n if (!app) return null; // Don't render children until connected\n\n return <AppContext.Provider value={app}>{children}</AppContext.Provider>;\n}\n\nexport function useAppContext(): App {\n const ctx = useContext(AppContext);\n if (!ctx) {\n throw new Error(\n \"useApp must be used within an <AppProvider>. Wrap your component tree with <AppProvider>.\",\n );\n }\n return ctx;\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { App, Theme, ToolResultData } from \"../types.js\";\nimport { AppProvider, useAppContext } from \"./app-provider.js\";\n\nexport { AppProvider };\n\nexport function useApp(): App {\n return useAppContext();\n}\n\nexport function useToolResult(): ToolResultData | null {\n const app = useAppContext();\n const [data, setData] = useState<ToolResultData | null>(null);\n\n useEffect(() => {\n return app.on(\"tool-result\", (result: ToolResultData) => {\n setData(result);\n });\n }, [app]);\n\n return data;\n}\n\nexport function useToolInput(): Record<string, unknown> | null {\n const app = useAppContext();\n const [input, setInput] = useState<Record<string, unknown> | null>(null);\n\n useEffect(() => {\n return app.on(\"tool-input\", (args: Record<string, unknown>) => {\n setInput(args);\n });\n }, [app]);\n\n return input;\n}\n\nexport function useConnectTheme(): Theme {\n const app = useAppContext();\n const [theme, setTheme] = useState<Theme>(() => app.theme);\n\n useEffect(() => {\n setTheme(app.theme); // Sync in case it changed between render and effect\n return app.on(\"theme-changed\", (t: Theme) => {\n setTheme(t);\n });\n }, [app]);\n\n return theme;\n}\n\nexport function useResize(): (width?: number, height?: number) => void {\n const app = useAppContext();\n return useCallback((width?: number, height?: number) => app.resize(width, height), [app]);\n}\n","import { createContext, type ReactNode, useContext, useEffect, useRef, useState } from \"react\";\nimport { createSynapse } from \"../core.js\";\nimport { applyThemeVariables } from \"../theme-defaults.js\";\nimport type { Synapse, SynapseOptions, SynapseTheme } from \"../types.js\";\n\nconst SynapseContext = createContext<Synapse | null>(null);\n\nexport interface SynapseProviderProps extends SynapseOptions {\n children: ReactNode;\n}\n\nexport function SynapseProvider({ children, ...options }: SynapseProviderProps) {\n // Use a ref so the same Synapse instance survives StrictMode's\n // unmount/remount cycle. We intentionally do NOT destroy on unmount\n // because StrictMode re-mounts immediately and the transport must\n // stay alive. The instance is GC'd when the provider is truly removed.\n const ref = useRef<Synapse | null>(null);\n\n if (ref.current === null || ref.current.destroyed) {\n ref.current = createSynapse(options);\n }\n\n return (\n <SynapseContext.Provider value={ref.current}>\n <ThemeInjector synapse={ref.current} />\n {children}\n </SynapseContext.Provider>\n );\n}\n\n/** Injects theme CSS variables onto document.documentElement whenever the theme changes. */\nfunction ThemeInjector({ synapse }: { synapse: Synapse }) {\n const [theme, setTheme] = useState<SynapseTheme>(() => synapse.getTheme());\n\n useEffect(() => {\n setTheme(synapse.getTheme());\n return synapse.onThemeChanged(setTheme);\n }, [synapse]);\n\n useEffect(() => {\n // Neutral defaults for the mode back any var the host omits, then host\n // values win — the same single path used by the handshake in core.ts.\n applyThemeVariables(theme.mode, theme.tokens);\n }, [theme]);\n\n return null;\n}\n\nexport function useSynapseContext(): Synapse {\n const ctx = useContext(SynapseContext);\n if (!ctx) {\n throw new Error(\n \"useSynapse must be used within a <SynapseProvider>. \" +\n \"Wrap your app component tree with <SynapseProvider>.\",\n );\n }\n return ctx;\n}\n","import type { McpUiHostContext } from \"@modelcontextprotocol/ext-apps\";\nimport type { Task, TaskStatus } from \"@modelcontextprotocol/sdk/types.js\";\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport type {\n ActionReducer,\n AgentAction,\n CallToolAsTaskOptions,\n DataChangedEvent,\n FileResult,\n RequestFileOptions,\n Store,\n StoreDispatch,\n Synapse,\n SynapseTheme,\n TaskHandle,\n ToolCallResult,\n} from \"../types.js\";\nimport { SynapseProvider, useSynapseContext } from \"./provider.js\";\n\n// Re-export provider components\nexport { SynapseProvider };\n\nexport function useSynapse(): Synapse {\n return useSynapseContext();\n}\n\nexport function useCallTool<TOutput = unknown>(\n toolName: string,\n): {\n call: (args?: Record<string, unknown>) => Promise<ToolCallResult<TOutput>>;\n isPending: boolean;\n error: Error | null;\n data: TOutput | null;\n} {\n const synapse = useSynapseContext();\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<TOutput | null>(null);\n const callIdRef = useRef(0);\n\n const call = useCallback(\n async (args?: Record<string, unknown>): Promise<ToolCallResult<TOutput>> => {\n const id = ++callIdRef.current;\n setIsPending(true);\n setError(null);\n\n try {\n const result = await synapse.callTool<Record<string, unknown>, TOutput>(toolName, args);\n // Stale guard: only update if this is still the latest call\n if (id === callIdRef.current) {\n setData(result.data);\n setIsPending(false);\n }\n return result;\n } catch (err) {\n if (id === callIdRef.current) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n setIsPending(false);\n }\n throw err;\n }\n },\n [synapse, toolName],\n );\n\n return { call, isPending, error, data };\n}\n\nexport function useDataSync(callback: (event: DataChangedEvent) => void): void {\n const synapse = useSynapseContext();\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n return synapse.onDataChanged((event) => callbackRef.current(event));\n }, [synapse]);\n}\n\n/**\n * Subscribe to agent actions — typed, declarative commands from the server.\n *\n * Actions are emitted by tools as deterministic side effects (e.g., \"navigate\n * to the board I just created\"). The UI decides how to handle each action type.\n *\n * @example\n * ```tsx\n * useAgentAction((action) => {\n * if (action.type === \"navigate\") {\n * const { entity, id } = action.payload as NavigatePayload;\n * if (entity === \"board\") setSelectedBoardId(id);\n * }\n * });\n * ```\n */\nexport function useAgentAction(callback: (action: AgentAction) => void): void {\n const synapse = useSynapseContext();\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n return synapse.onAction((action) => callbackRef.current(action));\n }, [synapse]);\n}\n\n/**\n * Subscribe to the full ext-apps host context.\n *\n * Returns the host context bag — spec-standardized fields (`theme`, `styles`,\n * `displayMode`, `toolInfo`) plus any host extensions. Re-renders on every\n * `ui/notifications/host-context-changed` notification.\n *\n * Prefer `useTheme()` when only theming matters (it filters no-op fires and\n * returns a typed `SynapseTheme`). Reach for `useHostContext()` for non-theme\n * fields like host-specific extensions, e.g. on NimbleBrain:\n *\n * ```tsx\n * const { workspace } = useHostContext<{ workspace?: { id: string } }>();\n * ```\n */\nexport function useHostContext<T extends McpUiHostContext = McpUiHostContext>(): T {\n const synapse = useSynapseContext();\n const [ctx, setCtx] = useState<T>(() => synapse.getHostContext() as T);\n\n useEffect(() => {\n // Sync in case context changed between render and effect\n setCtx(synapse.getHostContext() as T);\n return synapse.onHostContextChanged((c) => setCtx(c as T));\n }, [synapse]);\n\n return ctx;\n}\n\n/**\n * Re-renders only when the derived `SynapseTheme` actually changes (mode,\n * primaryColor, or any token value). Routes through `synapse.onThemeChanged`\n * — which is itself a `themesEqual`-filtered selector over the unified host\n * context — so a host-context update that doesn't move the theme (e.g. a\n * workspace switch) does NOT cause this hook's consumers to re-render.\n *\n * Building this on `useHostContext` instead would skip the filter: every\n * host-context-changed notification produces a new context reference, which\n * would propagate through `useState` and force a re-render even when the\n * derived theme is unchanged.\n */\nexport function useTheme(): SynapseTheme {\n const synapse = useSynapseContext();\n const [theme, setTheme] = useState<SynapseTheme>(() => synapse.getTheme());\n\n useEffect(() => {\n // Sync in case theme changed between render and effect\n setTheme(synapse.getTheme());\n return synapse.onThemeChanged(setTheme);\n }, [synapse]);\n\n return theme;\n}\n\nexport function useAction(): (action: string, params?: Record<string, unknown>) => void {\n const synapse = useSynapseContext();\n return useCallback(\n (action: string, params?: Record<string, unknown>) => synapse.action(action, params),\n [synapse],\n );\n}\n\nexport function useChat(): (\n message: string,\n context?: { action?: string; entity?: string },\n) => void {\n const synapse = useSynapseContext();\n return useCallback(\n (message: string, context?: { action?: string; entity?: string }) =>\n synapse.chat(message, context),\n [synapse],\n );\n}\n\n/**\n * Push the app's visible state to the agent via ext-apps `ui/update-model-context`.\n *\n * **Imperative** (no args) — returns a push function you call manually:\n * ```tsx\n * const push = useVisibleState();\n * push({ board: selectedBoard }, \"Viewing board X\");\n * ```\n *\n * **Declarative** (factory + deps) — auto-pushes when deps change:\n * ```tsx\n * useVisibleState(() => ({\n * state: { board: selectedBoard },\n * summary: `Viewing \"${selectedBoard?.name}\"`,\n * }), [selectedBoard]);\n * ```\n */\nexport function useVisibleState(): (state: Record<string, unknown>, summary?: string) => void;\nexport function useVisibleState(\n factory: () => { state: Record<string, unknown>; summary?: string },\n deps: unknown[],\n): void;\nexport function useVisibleState(\n factory?: () => { state: Record<string, unknown>; summary?: string },\n deps?: unknown[],\n): ((state: Record<string, unknown>, summary?: string) => void) | undefined {\n const synapse = useSynapseContext();\n const push = useCallback(\n (state: Record<string, unknown>, summary?: string) => synapse.setVisibleState(state, summary),\n [synapse],\n );\n\n // Declarative mode: auto-push when deps change.\n // The deps array is caller-provided (mirrors useMemo/useEffect pattern).\n const factoryRef = useRef(factory);\n factoryRef.current = factory;\n useEffect(() => {\n if (!factoryRef.current) return;\n const { state, summary } = factoryRef.current();\n push(state, summary);\n }, [...(deps ?? []), push]);\n\n if (!factory) return push;\n}\n\nexport function useFileUpload(): {\n pickFile: (options?: RequestFileOptions) => Promise<FileResult | null>;\n pickFiles: (options?: RequestFileOptions) => Promise<FileResult[]>;\n isPending: boolean;\n} {\n const synapse = useSynapseContext();\n const [isPending, setIsPending] = useState(false);\n\n const pickFile = useCallback(\n async (options?: RequestFileOptions) => {\n setIsPending(true);\n try {\n return await synapse.pickFile(options);\n } finally {\n setIsPending(false);\n }\n },\n [synapse],\n );\n\n const pickFiles = useCallback(\n async (options?: RequestFileOptions) => {\n setIsPending(true);\n try {\n return await synapse.pickFiles(options);\n } finally {\n setIsPending(false);\n }\n },\n [synapse],\n );\n\n return { pickFile, pickFiles, isPending };\n}\n\nexport function useStore<TState, TActions extends Record<string, ActionReducer<TState, any>>>(\n store: Store<TState, TActions>,\n): {\n state: TState;\n dispatch: StoreDispatch<TActions>;\n} {\n const state = useSyncExternalStore(\n (onStoreChange) => store.subscribe(onStoreChange),\n () => store.getState(),\n () => store.getState(),\n );\n\n return { state, dispatch: store.dispatch };\n}\n\n// -----------------------------------------------------------------------------\n// useCallToolAsTask — lifecycle wrapper around `synapse.callToolAsTask`\n// -----------------------------------------------------------------------------\n\n/**\n * Spec terminal status values for the MCP 2025-11-25 tasks utility.\n *\n * Typed via `satisfies TaskStatus` so a rename of any member of the\n * spec enum (`completed`/`failed`/`cancelled`) trips `tsc` — we never\n * hand-type these as bare string literals in comparisons.\n */\nconst COMPLETED_STATUS = \"completed\" satisfies TaskStatus;\nconst FAILED_STATUS = \"failed\" satisfies TaskStatus;\nconst CANCELLED_STATUS = \"cancelled\" satisfies TaskStatus;\n\nconst TERMINAL_STATUSES: ReadonlySet<TaskStatus> = new Set<TaskStatus>([\n COMPLETED_STATUS,\n FAILED_STATUS,\n CANCELLED_STATUS,\n]);\n\n/**\n * Fallback poll cadence used when the receiver's `CreateTaskResult.task`\n * carries no `pollInterval`. Chosen to roughly match the 5s cadence\n * described in Task 005 (\"a sensible default like 5s if pollInterval is\n * absent\") — the effective fire delay is this value × 1.5 ≈ 7.5s, well\n * below default TTLs but long enough to avoid hammering hosts that do\n * emit `notifications/tasks/status`.\n */\nconst DEFAULT_POLL_INTERVAL_MS = 5_000;\nconst POLL_FALLBACK_MULTIPLIER = 1.5;\n\n/**\n * Stop the poll fallback after this many consecutive `refresh()` failures.\n * Bridge teardown / TTL eviction / network outage all manifest as repeated\n * `tasks/get` rejections. Without a guard the timer re-arms forever; with\n * it we stop polling silently after `MAX_REFRESH_FAILURES` strikes — the\n * blocking `result()` path remains the authoritative source of truth, so\n * giving up on polling never loses the terminal value.\n */\nconst MAX_REFRESH_FAILURES = 5;\n\nexport interface UseCallToolAsTaskResult<TInput, TOutput> {\n /**\n * Start (or re-start) a task-augmented tool call. Returns the\n * resolved `TaskHandle` so callers can `await fire(...)` if they\n * want to know when the server has accepted the task, but reading\n * `task`/`result`/`error` from the hook is usually enough.\n *\n * Re-firing while a previous task is still in flight detaches this\n * hook from the prior handle (stops polling, unsubscribes) but does\n * NOT cancel the server-side task — the task keeps running and its\n * result may still be fetched elsewhere (e.g. on page revisit).\n */\n fire(args?: TInput, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>>;\n /** Latest `Task` state, or `null` before `fire()` has been called. */\n task: Task | null;\n /** Populated once `handle.result()` resolves non-error. */\n result: ToolCallResult<TOutput> | null;\n /** Populated on rejection or when `result.isError === true`. */\n error: Error | null;\n /** `true` while the task is non-terminal (`working` / `input_required`). */\n isWorking: boolean;\n /** `true` when `task.status ∈ {completed, failed, cancelled}`. */\n isTerminal: boolean;\n /**\n * Cancel the active task via `tasks/cancel`. No-op when no task is\n * active. Swallowed errors surface via `error`.\n */\n cancel(): Promise<void>;\n}\n\n/**\n * React hook wrapper around `synapse.callToolAsTask`.\n *\n * Handles the full MCP 2025-11-25 task lifecycle:\n *\n * 1. `fire(args, options?)` sends the task-augmented `tools/call` and\n * stores the returned `TaskHandle` in a ref.\n * 2. Subscribes to `handle.onStatus` — updates `task` whenever the\n * host emits `notifications/tasks/status` (OPTIONAL per spec).\n * 3. Starts a polling fallback: if no status notification arrives\n * within `pollInterval × 1.5` (defaulting to ~7.5s), calls\n * `handle.refresh()` for canonical state. Stops on terminal.\n * 4. Awaits `handle.result()` in the background — resolves to either\n * `result` (success / `isError: false`) or `error` (network reject\n * OR `result.isError === true`).\n *\n * Cleanup (unmount or re-fire) unsubscribes from status events and\n * clears the poll timer, but does NOT cancel the server-side task —\n * the caller may remount and recover state by firing again, and tasks\n * outlive iframe teardown until TTL elapses.\n */\nexport function useCallToolAsTask<TInput = Record<string, unknown>, TOutput = unknown>(\n toolName: string,\n): UseCallToolAsTaskResult<TInput, TOutput> {\n const synapse = useSynapseContext();\n\n const [task, setTask] = useState<Task | null>(null);\n const [result, setResult] = useState<ToolCallResult<TOutput> | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n // Per-fire generation counter. Every `fire()` increments; any\n // asynchronous callback (status listener, poll timer, `result()`\n // resolution) captures the gen at schedule time and bails if the\n // current gen has moved past it. This is the single source of truth\n // for \"is this work still relevant?\" — more robust than comparing\n // TaskHandle identity because handles can be detached by re-fire.\n const genRef = useRef(0);\n\n // Active handle + its teardown handles. We keep both in refs so the\n // hook's stable `fire`/`cancel` callbacks can reach the current\n // lifecycle state without re-binding on every render.\n const handleRef = useRef<TaskHandle<TOutput> | null>(null);\n const unsubscribeRef = useRef<(() => void) | null>(null);\n const pollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // `pollInterval × 1.5`, captured per-fire. Falls back to the 5s\n // default when the host didn't provide a `pollInterval` in the\n // initial CreateTaskResult.task.\n const pollDelayRef = useRef<number>(DEFAULT_POLL_INTERVAL_MS * POLL_FALLBACK_MULTIPLIER);\n\n // Track the latest known status out-of-band so the poll callback\n // can decide whether to keep polling without depending on the\n // `task` React state (which lags a render behind setState).\n const terminalRef = useRef<boolean>(false);\n\n // Consecutive `refresh()` failure count for the active fire. Reset\n // on every successful refresh, status notification, or new fire.\n const refreshFailureCountRef = useRef<number>(0);\n\n const clearPollTimer = useCallback(() => {\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n }, []);\n\n const detachCurrent = useCallback(() => {\n clearPollTimer();\n if (unsubscribeRef.current) {\n unsubscribeRef.current();\n unsubscribeRef.current = null;\n }\n handleRef.current = null;\n }, [clearPollTimer]);\n\n const scheduleNextPoll = useCallback(\n (gen: number) => {\n clearPollTimer();\n if (terminalRef.current) return;\n pollTimerRef.current = setTimeout(() => {\n // Bail if this fire has been superseded or torn down.\n if (gen !== genRef.current) return;\n const h = handleRef.current;\n if (!h) return;\n if (terminalRef.current) return;\n // `refresh()` is the canonical source for `createdAt` /\n // `lastUpdatedAt` / `ttl` — notification-derived Tasks carry\n // placeholders per the router in `task-handle.ts`.\n h.refresh().then(\n (fresh) => {\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current = 0;\n setTask(fresh);\n const isTerminal = TERMINAL_STATUSES.has(fresh.status);\n terminalRef.current = isTerminal;\n if (!isTerminal) scheduleNextPoll(gen);\n },\n () => {\n // Swallow refresh errors — the blocking `tasks/result` is\n // the authoritative path; polling is best-effort. But guard\n // against runaway re-arming: if the bridge is gone or the\n // task TTL has elapsed, every refresh rejects. Stop after\n // MAX_REFRESH_FAILURES consecutive strikes; result() will\n // still surface a terminal value or error when it settles.\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current += 1;\n if (refreshFailureCountRef.current >= MAX_REFRESH_FAILURES) return;\n if (!terminalRef.current) scheduleNextPoll(gen);\n },\n );\n }, pollDelayRef.current);\n },\n [clearPollTimer],\n );\n\n const fire = useCallback(\n async (args?: TInput, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>> => {\n // Detach any in-flight prior task BEFORE incrementing the gen so\n // its callbacks see the new gen and bail. (Incrementing then\n // detaching would also work, but detach-first makes the order\n // obvious: stop listening, bump generation, start fresh.)\n detachCurrent();\n const gen = ++genRef.current;\n\n // Reset per-fire state. Don't wipe `task` yet — `callToolAsTask`\n // is async; showing the previous terminal state briefly is less\n // jarring than flicker to null → working. We clear on resolution.\n setResult(null);\n setError(null);\n terminalRef.current = false;\n refreshFailureCountRef.current = 0;\n\n let handle: TaskHandle<TOutput>;\n try {\n handle = await synapse.callToolAsTask<TInput, TOutput>(toolName, args, options);\n } catch (err) {\n if (gen !== genRef.current) throw err;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw err;\n }\n\n // Caller superseded the fire between request and response —\n // don't attach listeners, but still return the handle so the\n // awaiter can observe it.\n if (gen !== genRef.current) return handle;\n\n handleRef.current = handle;\n\n // Derive the fallback poll delay from the receiver's advertised\n // `pollInterval`. Spec allows it to be absent; we then use the\n // 5s default described in Task 005.\n const hintedInterval = handle.task.pollInterval;\n pollDelayRef.current =\n typeof hintedInterval === \"number\" && hintedInterval > 0\n ? hintedInterval * POLL_FALLBACK_MULTIPLIER\n : DEFAULT_POLL_INTERVAL_MS * POLL_FALLBACK_MULTIPLIER;\n\n setTask(handle.task);\n terminalRef.current = TERMINAL_STATUSES.has(handle.task.status);\n\n // Subscribe to `notifications/tasks/status`. Each notification\n // resets the poll countdown (that's the whole point of the\n // \"notification OR polling\" contract — if notifications flow,\n // we don't poll; if they don't, the timer fires).\n unsubscribeRef.current = handle.onStatus((updated) => {\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current = 0;\n setTask(updated);\n const isTerminal = TERMINAL_STATUSES.has(updated.status);\n terminalRef.current = isTerminal;\n if (isTerminal) {\n clearPollTimer();\n } else {\n scheduleNextPoll(gen);\n }\n });\n\n // Kick off the blocking result fetch — this is the authoritative\n // terminal value regardless of whether notifications or polls\n // landed in between. By spec, `tasks/result` blocks until the task\n // reaches a terminal status, so when this settles we KNOW the task\n // is terminal — stop polling and synthesize a terminal `task`\n // status so derived flags (`isTerminal`, `isWorking`) match the\n // populated `result` / `error` immediately.\n handle.result().then(\n (res) => {\n if (gen !== genRef.current) return;\n terminalRef.current = true;\n clearPollTimer();\n // Synthesize the terminal Task: failed if `isError`, otherwise\n // completed. The next status notification or refresh would\n // confirm this, but we want internal state consistent the\n // instant `result` is populated — a \"result populated while\n // isWorking=true\" render is incoherent for consumers.\n setTask((prev) => {\n const status: TaskStatus = res.isError ? \"failed\" : \"completed\";\n const now = new Date().toISOString();\n return prev\n ? { ...prev, status, lastUpdatedAt: now }\n : {\n taskId: handle.task.taskId,\n status,\n ttl: handle.task.ttl,\n createdAt: handle.task.createdAt,\n lastUpdatedAt: now,\n };\n });\n if (res.isError) {\n // Spec: `CallToolResult.isError === true` is a tool-level\n // error, not a protocol error. Surface via `error` for\n // consumers who treat it as a failure, but also populate\n // `result` so callers inspecting the raw content block\n // still have access.\n setResult(res);\n const msg =\n typeof res.data === \"string\" && res.data.length > 0\n ? res.data\n : `Tool \"${toolName}\" returned isError: true`;\n setError(new Error(msg));\n } else {\n setResult(res);\n }\n },\n (err) => {\n if (gen !== genRef.current) return;\n // result() rejection means the `tasks/result` RPC failed\n // (transport error, taskId not found, bridge teardown). We\n // can't know the server-side task's actual final state, but\n // we know polling won't recover here either — same transport.\n // Mark terminal and synthesize `failed` status for UX\n // coherence; the populated `error` tells the consumer what\n // specifically went wrong.\n terminalRef.current = true;\n clearPollTimer();\n setTask((prev) => {\n const now = new Date().toISOString();\n return prev\n ? { ...prev, status: \"failed\", lastUpdatedAt: now }\n : {\n taskId: handle.task.taskId,\n status: \"failed\",\n ttl: handle.task.ttl,\n createdAt: handle.task.createdAt,\n lastUpdatedAt: now,\n };\n });\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n },\n );\n\n // Start the poll fallback only if we aren't already terminal.\n if (!terminalRef.current) scheduleNextPoll(gen);\n\n return handle;\n },\n [synapse, toolName, detachCurrent, clearPollTimer, scheduleNextPoll],\n );\n\n const cancel = useCallback(async (): Promise<void> => {\n const h = handleRef.current;\n if (!h) return;\n const gen = genRef.current;\n try {\n const cancelled = await h.cancel();\n if (gen !== genRef.current) return;\n setTask(cancelled);\n terminalRef.current = TERMINAL_STATUSES.has(cancelled.status);\n clearPollTimer();\n } catch (err) {\n if (gen !== genRef.current) return;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n }\n }, [clearPollTimer]);\n\n // Cleanup on unmount: stop polling, drop the status subscription.\n // Deliberately do NOT call `handle.cancel()` — per Task 005, the\n // server-side task keeps running so a remount can recover state.\n useEffect(() => {\n return () => {\n genRef.current += 1;\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n if (unsubscribeRef.current) {\n unsubscribeRef.current();\n unsubscribeRef.current = null;\n }\n handleRef.current = null;\n };\n }, []);\n\n const isTerminal = task !== null && TERMINAL_STATUSES.has(task.status);\n const isWorking = task !== null && !isTerminal;\n\n return { fire, task, result, error, isWorking, isTerminal, cancel };\n}\n"]}
1
+ {"version":3,"sources":["../../src/react/app-provider.tsx","../../src/react/connect-hooks.ts","../../src/react/provider.tsx","../../src/react/hooks.ts"],"names":["createContext","useState","useRef","useEffect","connect","useContext","useCallback","createSynapse","jsx","applyTheme","useSyncExternalStore","isTerminal"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createContext, type ReactNode, useContext, useEffect, useRef, useState } from \"react\";\nimport { connect } from \"../connect.js\";\nimport type { App, ConnectOptions } from \"../types.js\";\n\nconst AppContext = createContext<App | null>(null);\n\nexport interface AppProviderProps extends ConnectOptions {\n children: ReactNode;\n}\n\nexport function AppProvider({ children, name, version, autoResize }: AppProviderProps) {\n const [app, setApp] = useState<App | null>(null);\n const connectingRef = useRef(false);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: connect once on mount\n useEffect(() => {\n if (connectingRef.current) return;\n connectingRef.current = true;\n\n connect({ name, version, autoResize }).then((a) => {\n setApp(a);\n });\n }, []);\n\n if (!app) return null; // Don't render children until connected\n\n return <AppContext.Provider value={app}>{children}</AppContext.Provider>;\n}\n\nexport function useAppContext(): App {\n const ctx = useContext(AppContext);\n if (!ctx) {\n throw new Error(\n \"useApp must be used within an <AppProvider>. Wrap your component tree with <AppProvider>.\",\n );\n }\n return ctx;\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { App, Theme, ToolResultData } from \"../types.js\";\nimport { AppProvider, useAppContext } from \"./app-provider.js\";\n\nexport { AppProvider };\n\nexport function useApp(): App {\n return useAppContext();\n}\n\nexport function useToolResult(): ToolResultData | null {\n const app = useAppContext();\n const [data, setData] = useState<ToolResultData | null>(null);\n\n useEffect(() => {\n return app.on(\"tool-result\", (result: ToolResultData) => {\n setData(result);\n });\n }, [app]);\n\n return data;\n}\n\nexport function useToolInput(): Record<string, unknown> | null {\n const app = useAppContext();\n const [input, setInput] = useState<Record<string, unknown> | null>(null);\n\n useEffect(() => {\n return app.on(\"tool-input\", (args: Record<string, unknown>) => {\n setInput(args);\n });\n }, [app]);\n\n return input;\n}\n\nexport function useConnectTheme(): Theme {\n const app = useAppContext();\n const [theme, setTheme] = useState<Theme>(() => app.theme);\n\n useEffect(() => {\n setTheme(app.theme); // Sync in case it changed between render and effect\n return app.on(\"theme-changed\", (t: Theme) => {\n setTheme(t);\n });\n }, [app]);\n\n return theme;\n}\n\nexport function useResize(): (width?: number, height?: number) => void {\n const app = useAppContext();\n return useCallback((width?: number, height?: number) => app.resize(width, height), [app]);\n}\n","import { createContext, type ReactNode, useContext, useEffect, useRef, useState } from \"react\";\nimport { createSynapse } from \"../core.js\";\nimport { applyTheme } from \"../theme-defaults.js\";\nimport type { Synapse, SynapseOptions, SynapseTheme } from \"../types.js\";\n\nconst SynapseContext = createContext<Synapse | null>(null);\n\nexport interface SynapseProviderProps extends SynapseOptions {\n children: ReactNode;\n}\n\nexport function SynapseProvider({ children, ...options }: SynapseProviderProps) {\n // Use a ref so the same Synapse instance survives StrictMode's\n // unmount/remount cycle. We intentionally do NOT destroy on unmount\n // because StrictMode re-mounts immediately and the transport must\n // stay alive. The instance is GC'd when the provider is truly removed.\n const ref = useRef<Synapse | null>(null);\n\n if (ref.current === null || ref.current.destroyed) {\n ref.current = createSynapse(options);\n }\n\n return (\n <SynapseContext.Provider value={ref.current}>\n <ThemeInjector synapse={ref.current} />\n {children}\n </SynapseContext.Provider>\n );\n}\n\n/** Injects theme CSS variables onto document.documentElement whenever the theme changes. */\nfunction ThemeInjector({ synapse }: { synapse: Synapse }) {\n const [theme, setTheme] = useState<SynapseTheme>(() => synapse.getTheme());\n\n useEffect(() => {\n setTheme(synapse.getTheme());\n return synapse.onThemeChanged(setTheme);\n }, [synapse]);\n\n useEffect(() => {\n // Neutral defaults for the mode back any var the host omits, then host\n // values win — the same single path used by the handshake in core.ts.\n applyTheme(theme.mode, theme.tokens, theme.fontFaces);\n }, [theme]);\n\n return null;\n}\n\nexport function useSynapseContext(): Synapse {\n const ctx = useContext(SynapseContext);\n if (!ctx) {\n throw new Error(\n \"useSynapse must be used within a <SynapseProvider>. \" +\n \"Wrap your app component tree with <SynapseProvider>.\",\n );\n }\n return ctx;\n}\n","import type { McpUiHostContext } from \"@modelcontextprotocol/ext-apps\";\nimport type { Task, TaskStatus } from \"@modelcontextprotocol/sdk/types.js\";\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport type {\n ActionReducer,\n AgentAction,\n CallToolAsTaskOptions,\n DataChangedEvent,\n FileResult,\n RequestFileOptions,\n Store,\n StoreDispatch,\n Synapse,\n SynapseTheme,\n TaskHandle,\n ToolCallResult,\n} from \"../types.js\";\nimport { SynapseProvider, useSynapseContext } from \"./provider.js\";\n\n// Re-export provider components\nexport { SynapseProvider };\n\nexport function useSynapse(): Synapse {\n return useSynapseContext();\n}\n\nexport function useCallTool<TOutput = unknown>(\n toolName: string,\n): {\n call: (args?: Record<string, unknown>) => Promise<ToolCallResult<TOutput>>;\n isPending: boolean;\n error: Error | null;\n data: TOutput | null;\n} {\n const synapse = useSynapseContext();\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<TOutput | null>(null);\n const callIdRef = useRef(0);\n\n const call = useCallback(\n async (args?: Record<string, unknown>): Promise<ToolCallResult<TOutput>> => {\n const id = ++callIdRef.current;\n setIsPending(true);\n setError(null);\n\n try {\n const result = await synapse.callTool<Record<string, unknown>, TOutput>(toolName, args);\n // Stale guard: only update if this is still the latest call\n if (id === callIdRef.current) {\n setData(result.data);\n setIsPending(false);\n }\n return result;\n } catch (err) {\n if (id === callIdRef.current) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n setIsPending(false);\n }\n throw err;\n }\n },\n [synapse, toolName],\n );\n\n return { call, isPending, error, data };\n}\n\nexport function useDataSync(callback: (event: DataChangedEvent) => void): void {\n const synapse = useSynapseContext();\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n return synapse.onDataChanged((event) => callbackRef.current(event));\n }, [synapse]);\n}\n\n/**\n * Subscribe to agent actions — typed, declarative commands from the server.\n *\n * Actions are emitted by tools as deterministic side effects (e.g., \"navigate\n * to the board I just created\"). The UI decides how to handle each action type.\n *\n * @example\n * ```tsx\n * useAgentAction((action) => {\n * if (action.type === \"navigate\") {\n * const { entity, id } = action.payload as NavigatePayload;\n * if (entity === \"board\") setSelectedBoardId(id);\n * }\n * });\n * ```\n */\nexport function useAgentAction(callback: (action: AgentAction) => void): void {\n const synapse = useSynapseContext();\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n return synapse.onAction((action) => callbackRef.current(action));\n }, [synapse]);\n}\n\n/**\n * Subscribe to the full ext-apps host context.\n *\n * Returns the host context bag — spec-standardized fields (`theme`, `styles`,\n * `displayMode`, `toolInfo`) plus any host extensions. Re-renders on every\n * `ui/notifications/host-context-changed` notification.\n *\n * Prefer `useTheme()` when only theming matters (it filters no-op fires and\n * returns a typed `SynapseTheme`). Reach for `useHostContext()` for non-theme\n * fields like host-specific extensions, e.g. on NimbleBrain:\n *\n * ```tsx\n * const { workspace } = useHostContext<{ workspace?: { id: string } }>();\n * ```\n */\nexport function useHostContext<T extends McpUiHostContext = McpUiHostContext>(): T {\n const synapse = useSynapseContext();\n const [ctx, setCtx] = useState<T>(() => synapse.getHostContext() as T);\n\n useEffect(() => {\n // Sync in case context changed between render and effect\n setCtx(synapse.getHostContext() as T);\n return synapse.onHostContextChanged((c) => setCtx(c as T));\n }, [synapse]);\n\n return ctx;\n}\n\n/**\n * Re-renders only when the derived `SynapseTheme` actually changes (mode,\n * primaryColor, or any token value). Routes through `synapse.onThemeChanged`\n * — which is itself a `themesEqual`-filtered selector over the unified host\n * context — so a host-context update that doesn't move the theme (e.g. a\n * workspace switch) does NOT cause this hook's consumers to re-render.\n *\n * Building this on `useHostContext` instead would skip the filter: every\n * host-context-changed notification produces a new context reference, which\n * would propagate through `useState` and force a re-render even when the\n * derived theme is unchanged.\n */\nexport function useTheme(): SynapseTheme {\n const synapse = useSynapseContext();\n const [theme, setTheme] = useState<SynapseTheme>(() => synapse.getTheme());\n\n useEffect(() => {\n // Sync in case theme changed between render and effect\n setTheme(synapse.getTheme());\n return synapse.onThemeChanged(setTheme);\n }, [synapse]);\n\n return theme;\n}\n\nexport function useAction(): (action: string, params?: Record<string, unknown>) => void {\n const synapse = useSynapseContext();\n return useCallback(\n (action: string, params?: Record<string, unknown>) => synapse.action(action, params),\n [synapse],\n );\n}\n\nexport function useChat(): (\n message: string,\n context?: { action?: string; entity?: string },\n) => void {\n const synapse = useSynapseContext();\n return useCallback(\n (message: string, context?: { action?: string; entity?: string }) =>\n synapse.chat(message, context),\n [synapse],\n );\n}\n\n/**\n * Push the app's visible state to the agent via ext-apps `ui/update-model-context`.\n *\n * **Imperative** (no args) — returns a push function you call manually:\n * ```tsx\n * const push = useVisibleState();\n * push({ board: selectedBoard }, \"Viewing board X\");\n * ```\n *\n * **Declarative** (factory + deps) — auto-pushes when deps change:\n * ```tsx\n * useVisibleState(() => ({\n * state: { board: selectedBoard },\n * summary: `Viewing \"${selectedBoard?.name}\"`,\n * }), [selectedBoard]);\n * ```\n */\nexport function useVisibleState(): (state: Record<string, unknown>, summary?: string) => void;\nexport function useVisibleState(\n factory: () => { state: Record<string, unknown>; summary?: string },\n deps: unknown[],\n): void;\nexport function useVisibleState(\n factory?: () => { state: Record<string, unknown>; summary?: string },\n deps?: unknown[],\n): ((state: Record<string, unknown>, summary?: string) => void) | undefined {\n const synapse = useSynapseContext();\n const push = useCallback(\n (state: Record<string, unknown>, summary?: string) => synapse.setVisibleState(state, summary),\n [synapse],\n );\n\n // Declarative mode: auto-push when deps change.\n // The deps array is caller-provided (mirrors useMemo/useEffect pattern).\n const factoryRef = useRef(factory);\n factoryRef.current = factory;\n useEffect(() => {\n if (!factoryRef.current) return;\n const { state, summary } = factoryRef.current();\n push(state, summary);\n }, [...(deps ?? []), push]);\n\n if (!factory) return push;\n}\n\nexport function useFileUpload(): {\n pickFile: (options?: RequestFileOptions) => Promise<FileResult | null>;\n pickFiles: (options?: RequestFileOptions) => Promise<FileResult[]>;\n isPending: boolean;\n} {\n const synapse = useSynapseContext();\n const [isPending, setIsPending] = useState(false);\n\n const pickFile = useCallback(\n async (options?: RequestFileOptions) => {\n setIsPending(true);\n try {\n return await synapse.pickFile(options);\n } finally {\n setIsPending(false);\n }\n },\n [synapse],\n );\n\n const pickFiles = useCallback(\n async (options?: RequestFileOptions) => {\n setIsPending(true);\n try {\n return await synapse.pickFiles(options);\n } finally {\n setIsPending(false);\n }\n },\n [synapse],\n );\n\n return { pickFile, pickFiles, isPending };\n}\n\nexport function useStore<TState, TActions extends Record<string, ActionReducer<TState, any>>>(\n store: Store<TState, TActions>,\n): {\n state: TState;\n dispatch: StoreDispatch<TActions>;\n} {\n const state = useSyncExternalStore(\n (onStoreChange) => store.subscribe(onStoreChange),\n () => store.getState(),\n () => store.getState(),\n );\n\n return { state, dispatch: store.dispatch };\n}\n\n// -----------------------------------------------------------------------------\n// useCallToolAsTask — lifecycle wrapper around `synapse.callToolAsTask`\n// -----------------------------------------------------------------------------\n\n/**\n * Spec terminal status values for the MCP 2025-11-25 tasks utility.\n *\n * Typed via `satisfies TaskStatus` so a rename of any member of the\n * spec enum (`completed`/`failed`/`cancelled`) trips `tsc` — we never\n * hand-type these as bare string literals in comparisons.\n */\nconst COMPLETED_STATUS = \"completed\" satisfies TaskStatus;\nconst FAILED_STATUS = \"failed\" satisfies TaskStatus;\nconst CANCELLED_STATUS = \"cancelled\" satisfies TaskStatus;\n\nconst TERMINAL_STATUSES: ReadonlySet<TaskStatus> = new Set<TaskStatus>([\n COMPLETED_STATUS,\n FAILED_STATUS,\n CANCELLED_STATUS,\n]);\n\n/**\n * Fallback poll cadence used when the receiver's `CreateTaskResult.task`\n * carries no `pollInterval`. Chosen to roughly match the 5s cadence\n * described in Task 005 (\"a sensible default like 5s if pollInterval is\n * absent\") — the effective fire delay is this value × 1.5 ≈ 7.5s, well\n * below default TTLs but long enough to avoid hammering hosts that do\n * emit `notifications/tasks/status`.\n */\nconst DEFAULT_POLL_INTERVAL_MS = 5_000;\nconst POLL_FALLBACK_MULTIPLIER = 1.5;\n\n/**\n * Stop the poll fallback after this many consecutive `refresh()` failures.\n * Bridge teardown / TTL eviction / network outage all manifest as repeated\n * `tasks/get` rejections. Without a guard the timer re-arms forever; with\n * it we stop polling silently after `MAX_REFRESH_FAILURES` strikes — the\n * blocking `result()` path remains the authoritative source of truth, so\n * giving up on polling never loses the terminal value.\n */\nconst MAX_REFRESH_FAILURES = 5;\n\nexport interface UseCallToolAsTaskResult<TInput, TOutput> {\n /**\n * Start (or re-start) a task-augmented tool call. Returns the\n * resolved `TaskHandle` so callers can `await fire(...)` if they\n * want to know when the server has accepted the task, but reading\n * `task`/`result`/`error` from the hook is usually enough.\n *\n * Re-firing while a previous task is still in flight detaches this\n * hook from the prior handle (stops polling, unsubscribes) but does\n * NOT cancel the server-side task — the task keeps running and its\n * result may still be fetched elsewhere (e.g. on page revisit).\n */\n fire(args?: TInput, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>>;\n /** Latest `Task` state, or `null` before `fire()` has been called. */\n task: Task | null;\n /** Populated once `handle.result()` resolves non-error. */\n result: ToolCallResult<TOutput> | null;\n /** Populated on rejection or when `result.isError === true`. */\n error: Error | null;\n /** `true` while the task is non-terminal (`working` / `input_required`). */\n isWorking: boolean;\n /** `true` when `task.status ∈ {completed, failed, cancelled}`. */\n isTerminal: boolean;\n /**\n * Cancel the active task via `tasks/cancel`. No-op when no task is\n * active. Swallowed errors surface via `error`.\n */\n cancel(): Promise<void>;\n}\n\n/**\n * React hook wrapper around `synapse.callToolAsTask`.\n *\n * Handles the full MCP 2025-11-25 task lifecycle:\n *\n * 1. `fire(args, options?)` sends the task-augmented `tools/call` and\n * stores the returned `TaskHandle` in a ref.\n * 2. Subscribes to `handle.onStatus` — updates `task` whenever the\n * host emits `notifications/tasks/status` (OPTIONAL per spec).\n * 3. Starts a polling fallback: if no status notification arrives\n * within `pollInterval × 1.5` (defaulting to ~7.5s), calls\n * `handle.refresh()` for canonical state. Stops on terminal.\n * 4. Awaits `handle.result()` in the background — resolves to either\n * `result` (success / `isError: false`) or `error` (network reject\n * OR `result.isError === true`).\n *\n * Cleanup (unmount or re-fire) unsubscribes from status events and\n * clears the poll timer, but does NOT cancel the server-side task —\n * the caller may remount and recover state by firing again, and tasks\n * outlive iframe teardown until TTL elapses.\n */\nexport function useCallToolAsTask<TInput = Record<string, unknown>, TOutput = unknown>(\n toolName: string,\n): UseCallToolAsTaskResult<TInput, TOutput> {\n const synapse = useSynapseContext();\n\n const [task, setTask] = useState<Task | null>(null);\n const [result, setResult] = useState<ToolCallResult<TOutput> | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n // Per-fire generation counter. Every `fire()` increments; any\n // asynchronous callback (status listener, poll timer, `result()`\n // resolution) captures the gen at schedule time and bails if the\n // current gen has moved past it. This is the single source of truth\n // for \"is this work still relevant?\" — more robust than comparing\n // TaskHandle identity because handles can be detached by re-fire.\n const genRef = useRef(0);\n\n // Active handle + its teardown handles. We keep both in refs so the\n // hook's stable `fire`/`cancel` callbacks can reach the current\n // lifecycle state without re-binding on every render.\n const handleRef = useRef<TaskHandle<TOutput> | null>(null);\n const unsubscribeRef = useRef<(() => void) | null>(null);\n const pollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // `pollInterval × 1.5`, captured per-fire. Falls back to the 5s\n // default when the host didn't provide a `pollInterval` in the\n // initial CreateTaskResult.task.\n const pollDelayRef = useRef<number>(DEFAULT_POLL_INTERVAL_MS * POLL_FALLBACK_MULTIPLIER);\n\n // Track the latest known status out-of-band so the poll callback\n // can decide whether to keep polling without depending on the\n // `task` React state (which lags a render behind setState).\n const terminalRef = useRef<boolean>(false);\n\n // Consecutive `refresh()` failure count for the active fire. Reset\n // on every successful refresh, status notification, or new fire.\n const refreshFailureCountRef = useRef<number>(0);\n\n const clearPollTimer = useCallback(() => {\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n }, []);\n\n const detachCurrent = useCallback(() => {\n clearPollTimer();\n if (unsubscribeRef.current) {\n unsubscribeRef.current();\n unsubscribeRef.current = null;\n }\n handleRef.current = null;\n }, [clearPollTimer]);\n\n const scheduleNextPoll = useCallback(\n (gen: number) => {\n clearPollTimer();\n if (terminalRef.current) return;\n pollTimerRef.current = setTimeout(() => {\n // Bail if this fire has been superseded or torn down.\n if (gen !== genRef.current) return;\n const h = handleRef.current;\n if (!h) return;\n if (terminalRef.current) return;\n // `refresh()` is the canonical source for `createdAt` /\n // `lastUpdatedAt` / `ttl` — notification-derived Tasks carry\n // placeholders per the router in `task-handle.ts`.\n h.refresh().then(\n (fresh) => {\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current = 0;\n setTask(fresh);\n const isTerminal = TERMINAL_STATUSES.has(fresh.status);\n terminalRef.current = isTerminal;\n if (!isTerminal) scheduleNextPoll(gen);\n },\n () => {\n // Swallow refresh errors — the blocking `tasks/result` is\n // the authoritative path; polling is best-effort. But guard\n // against runaway re-arming: if the bridge is gone or the\n // task TTL has elapsed, every refresh rejects. Stop after\n // MAX_REFRESH_FAILURES consecutive strikes; result() will\n // still surface a terminal value or error when it settles.\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current += 1;\n if (refreshFailureCountRef.current >= MAX_REFRESH_FAILURES) return;\n if (!terminalRef.current) scheduleNextPoll(gen);\n },\n );\n }, pollDelayRef.current);\n },\n [clearPollTimer],\n );\n\n const fire = useCallback(\n async (args?: TInput, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>> => {\n // Detach any in-flight prior task BEFORE incrementing the gen so\n // its callbacks see the new gen and bail. (Incrementing then\n // detaching would also work, but detach-first makes the order\n // obvious: stop listening, bump generation, start fresh.)\n detachCurrent();\n const gen = ++genRef.current;\n\n // Reset per-fire state. Don't wipe `task` yet — `callToolAsTask`\n // is async; showing the previous terminal state briefly is less\n // jarring than flicker to null → working. We clear on resolution.\n setResult(null);\n setError(null);\n terminalRef.current = false;\n refreshFailureCountRef.current = 0;\n\n let handle: TaskHandle<TOutput>;\n try {\n handle = await synapse.callToolAsTask<TInput, TOutput>(toolName, args, options);\n } catch (err) {\n if (gen !== genRef.current) throw err;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw err;\n }\n\n // Caller superseded the fire between request and response —\n // don't attach listeners, but still return the handle so the\n // awaiter can observe it.\n if (gen !== genRef.current) return handle;\n\n handleRef.current = handle;\n\n // Derive the fallback poll delay from the receiver's advertised\n // `pollInterval`. Spec allows it to be absent; we then use the\n // 5s default described in Task 005.\n const hintedInterval = handle.task.pollInterval;\n pollDelayRef.current =\n typeof hintedInterval === \"number\" && hintedInterval > 0\n ? hintedInterval * POLL_FALLBACK_MULTIPLIER\n : DEFAULT_POLL_INTERVAL_MS * POLL_FALLBACK_MULTIPLIER;\n\n setTask(handle.task);\n terminalRef.current = TERMINAL_STATUSES.has(handle.task.status);\n\n // Subscribe to `notifications/tasks/status`. Each notification\n // resets the poll countdown (that's the whole point of the\n // \"notification OR polling\" contract — if notifications flow,\n // we don't poll; if they don't, the timer fires).\n unsubscribeRef.current = handle.onStatus((updated) => {\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current = 0;\n setTask(updated);\n const isTerminal = TERMINAL_STATUSES.has(updated.status);\n terminalRef.current = isTerminal;\n if (isTerminal) {\n clearPollTimer();\n } else {\n scheduleNextPoll(gen);\n }\n });\n\n // Kick off the blocking result fetch — this is the authoritative\n // terminal value regardless of whether notifications or polls\n // landed in between. By spec, `tasks/result` blocks until the task\n // reaches a terminal status, so when this settles we KNOW the task\n // is terminal — stop polling and synthesize a terminal `task`\n // status so derived flags (`isTerminal`, `isWorking`) match the\n // populated `result` / `error` immediately.\n handle.result().then(\n (res) => {\n if (gen !== genRef.current) return;\n terminalRef.current = true;\n clearPollTimer();\n // Synthesize the terminal Task: failed if `isError`, otherwise\n // completed. The next status notification or refresh would\n // confirm this, but we want internal state consistent the\n // instant `result` is populated — a \"result populated while\n // isWorking=true\" render is incoherent for consumers.\n setTask((prev) => {\n const status: TaskStatus = res.isError ? \"failed\" : \"completed\";\n const now = new Date().toISOString();\n return prev\n ? { ...prev, status, lastUpdatedAt: now }\n : {\n taskId: handle.task.taskId,\n status,\n ttl: handle.task.ttl,\n createdAt: handle.task.createdAt,\n lastUpdatedAt: now,\n };\n });\n if (res.isError) {\n // Spec: `CallToolResult.isError === true` is a tool-level\n // error, not a protocol error. Surface via `error` for\n // consumers who treat it as a failure, but also populate\n // `result` so callers inspecting the raw content block\n // still have access.\n setResult(res);\n const msg =\n typeof res.data === \"string\" && res.data.length > 0\n ? res.data\n : `Tool \"${toolName}\" returned isError: true`;\n setError(new Error(msg));\n } else {\n setResult(res);\n }\n },\n (err) => {\n if (gen !== genRef.current) return;\n // result() rejection means the `tasks/result` RPC failed\n // (transport error, taskId not found, bridge teardown). We\n // can't know the server-side task's actual final state, but\n // we know polling won't recover here either — same transport.\n // Mark terminal and synthesize `failed` status for UX\n // coherence; the populated `error` tells the consumer what\n // specifically went wrong.\n terminalRef.current = true;\n clearPollTimer();\n setTask((prev) => {\n const now = new Date().toISOString();\n return prev\n ? { ...prev, status: \"failed\", lastUpdatedAt: now }\n : {\n taskId: handle.task.taskId,\n status: \"failed\",\n ttl: handle.task.ttl,\n createdAt: handle.task.createdAt,\n lastUpdatedAt: now,\n };\n });\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n },\n );\n\n // Start the poll fallback only if we aren't already terminal.\n if (!terminalRef.current) scheduleNextPoll(gen);\n\n return handle;\n },\n [synapse, toolName, detachCurrent, clearPollTimer, scheduleNextPoll],\n );\n\n const cancel = useCallback(async (): Promise<void> => {\n const h = handleRef.current;\n if (!h) return;\n const gen = genRef.current;\n try {\n const cancelled = await h.cancel();\n if (gen !== genRef.current) return;\n setTask(cancelled);\n terminalRef.current = TERMINAL_STATUSES.has(cancelled.status);\n clearPollTimer();\n } catch (err) {\n if (gen !== genRef.current) return;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n }\n }, [clearPollTimer]);\n\n // Cleanup on unmount: stop polling, drop the status subscription.\n // Deliberately do NOT call `handle.cancel()` — per Task 005, the\n // server-side task keeps running so a remount can recover state.\n useEffect(() => {\n return () => {\n genRef.current += 1;\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n if (unsubscribeRef.current) {\n unsubscribeRef.current();\n unsubscribeRef.current = null;\n }\n handleRef.current = null;\n };\n }, []);\n\n const isTerminal = task !== null && TERMINAL_STATUSES.has(task.status);\n const isWorking = task !== null && !isTerminal;\n\n return { fire, task, result, error, isWorking, isTerminal, cancel };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { C as ConnectOptions, A as App, o as Theme, q as ToolResultData, S as SynapseOptions, g as CallToolAsTaskOptions, m as TaskHandle, p as ToolCallResult, e as AgentAction, D as DataChangedEvent, R as RequestFileOptions, F as FileResult, b as ActionReducer, d as Store, k as StoreDispatch, a as Synapse, l as SynapseTheme } from '../types-C9utGXv_.cjs';
3
+ import { C as ConnectOptions, A as App, q as Theme, s as ToolResultData, S as SynapseOptions, g as CallToolAsTaskOptions, o as TaskHandle, r as ToolCallResult, e as AgentAction, D as DataChangedEvent, R as RequestFileOptions, i as FileResult, b as ActionReducer, d as Store, m as StoreDispatch, a as Synapse, n as SynapseTheme } from '../types-BSZasM8q.cjs';
4
4
  import { McpUiHostContext } from '@modelcontextprotocol/ext-apps';
5
5
  import { Task } from '@modelcontextprotocol/sdk/types.js';
6
6
 
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { C as ConnectOptions, A as App, o as Theme, q as ToolResultData, S as SynapseOptions, g as CallToolAsTaskOptions, m as TaskHandle, p as ToolCallResult, e as AgentAction, D as DataChangedEvent, R as RequestFileOptions, F as FileResult, b as ActionReducer, d as Store, k as StoreDispatch, a as Synapse, l as SynapseTheme } from '../types-C9utGXv_.js';
3
+ import { C as ConnectOptions, A as App, q as Theme, s as ToolResultData, S as SynapseOptions, g as CallToolAsTaskOptions, o as TaskHandle, r as ToolCallResult, e as AgentAction, D as DataChangedEvent, R as RequestFileOptions, i as FileResult, b as ActionReducer, d as Store, m as StoreDispatch, a as Synapse, n as SynapseTheme } from '../types-BSZasM8q.js';
4
4
  import { McpUiHostContext } from '@modelcontextprotocol/ext-apps';
5
5
  import { Task } from '@modelcontextprotocol/sdk/types.js';
6
6
 
@@ -1,5 +1,5 @@
1
- import { connect, createSynapse } from '../chunk-XGJAADVV.js';
2
- import { applyThemeVariables } from '../chunk-VXTMI266.js';
1
+ import { connect, createSynapse } from '../chunk-AGN3NDOK.js';
2
+ import { applyTheme } from '../chunk-DOKVNVTI.js';
3
3
  import { createContext, useState, useRef, useEffect, useCallback, useSyncExternalStore, useContext } from 'react';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
5
5
 
@@ -84,7 +84,7 @@ function ThemeInjector({ synapse }) {
84
84
  return synapse.onThemeChanged(setTheme);
85
85
  }, [synapse]);
86
86
  useEffect(() => {
87
- applyThemeVariables(theme.mode, theme.tokens);
87
+ applyTheme(theme.mode, theme.tokens, theme.fontFaces);
88
88
  }, [theme]);
89
89
  return null;
90
90
  }