@nimblebrain/synapse 0.2.1 → 0.3.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 (36) hide show
  1. package/README.md +181 -45
  2. package/dist/{chunk-Y4ZDNAYQ.cjs → chunk-B3T6NB32.cjs} +349 -80
  3. package/dist/chunk-B3T6NB32.cjs.map +1 -0
  4. package/dist/{chunk-7KEYXJWD.js → chunk-GQ4L63CL.js} +349 -81
  5. package/dist/chunk-GQ4L63CL.js.map +1 -0
  6. package/dist/codegen/cli.cjs +1 -1
  7. package/dist/codegen/cli.js +1 -1
  8. package/dist/codegen/index.d.cts +1 -1
  9. package/dist/codegen/index.d.ts +1 -1
  10. package/dist/connect.iife.global.js +1 -0
  11. package/dist/index.cjs +8 -4
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +11 -3
  14. package/dist/index.d.ts +11 -3
  15. package/dist/index.js +3 -3
  16. package/dist/index.js.map +1 -1
  17. package/dist/react/index.cjs +119 -3
  18. package/dist/react/index.cjs.map +1 -1
  19. package/dist/react/index.d.cts +18 -2
  20. package/dist/react/index.d.ts +18 -2
  21. package/dist/react/index.js +114 -5
  22. package/dist/react/index.js.map +1 -1
  23. package/dist/{server-NNW54YW5.js → server-7BRGSPT3.js} +13 -13
  24. package/dist/{server-NNW54YW5.js.map → server-7BRGSPT3.js.map} +1 -1
  25. package/dist/{server-3BDZ5S72.cjs → server-SRE7E3G3.cjs} +13 -13
  26. package/dist/{server-3BDZ5S72.cjs.map → server-SRE7E3G3.cjs.map} +1 -1
  27. package/dist/synapse-runtime.iife.global.js +1 -1
  28. package/dist/{types-DElq_otH.d.cts → types-DJ32F5EL.d.cts} +79 -4
  29. package/dist/{types-DElq_otH.d.ts → types-DJ32F5EL.d.ts} +79 -4
  30. package/dist/vite/index.cjs +6 -6
  31. package/dist/vite/index.cjs.map +1 -1
  32. package/dist/vite/index.js +6 -6
  33. package/dist/vite/index.js.map +1 -1
  34. package/package.json +4 -1
  35. package/dist/chunk-7KEYXJWD.js.map +0 -1
  36. package/dist/chunk-Y4ZDNAYQ.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ (function(){'use strict';function I(s){let e=s??{},o=e.structuredContent??null;if(o!=null)return {content:o,structuredContent:o,raw:e};let n=e.content;if(Array.isArray(n)){let a=n.filter(r=>r!=null&&typeof r=="object"&&r.type==="text"&&typeof r.text=="string").map(r=>r.text);if(a.length>0){let r=a.join("");try{return {content:JSON.parse(r),structuredContent:null,raw:e}}catch{return {content:r,structuredContent:null,raw:e}}}return {content:n,structuredContent:null,raw:e}}if(typeof n=="string")try{return {content:JSON.parse(n),structuredContent:null,raw:e}}catch{return {content:n,structuredContent:null,raw:e}}return {content:n??null,structuredContent:null,raw:e}}var _={"tool-result":"ui/notifications/tool-result","tool-input":"ui/notifications/tool-input","tool-input-partial":"ui/notifications/tool-input-partial","tool-cancelled":"ui/notifications/tool-cancelled","theme-changed":"ui/notifications/host-context-changed",teardown:"ui/resource-teardown"};function C(s){return _[s]??s}function K(s,e){let o=false,n=null,a=null;function r(){if(o)return;let m=document.body.scrollWidth,p=document.body.scrollHeight;s("ui/notifications/size-changed",{width:m,height:p});}function d(m,p){o||(m!==void 0&&p!==void 0?s("ui/notifications/size-changed",{width:m,height:p}):r());}e&&typeof ResizeObserver<"u"&&(n=new ResizeObserver(()=>{o||(a!==null&&cancelAnimationFrame(a),a=requestAnimationFrame(()=>{a=null,r();}));}),n.observe(document.body));function c(){o||(o=true,a!==null&&cancelAnimationFrame(a),n?.disconnect(),n=null);}return {resize:d,measureAndSend:r,destroy:c}}function A(s){return s==null?{data:null,isError:false}:H(s)?B(s):{data:s,isError:false}}function H(s){return s===null||typeof s!="object"||Array.isArray(s)?false:Array.isArray(s.content)}function J(s){if(s===null||typeof s!="object"||Array.isArray(s))return false;let e=s;return e.type==="text"&&typeof e.text=="string"}function B(s){let e=s.isError===true,o=s.content;if(o.length===0)return {data:null,isError:e};let n=o.find(J);if(!n)return {data:o,isError:e};try{return {data:JSON.parse(n.text),isError:e}}catch{return {data:n.text,isError:e}}}var S=class{counter=0;destroyed=false;pending=new Map;handlers=new Map;listener;constructor(){this.listener=e=>this.handleMessage(e),window.addEventListener("message",this.listener);}send(e,o){if(this.destroyed)return;let n={jsonrpc:"2.0",method:e,...o!==void 0&&{params:o}};window.parent.postMessage(n,"*");}request(e,o){if(this.destroyed)return Promise.reject(new Error("Transport destroyed"));let n=`syn-${++this.counter}`,a={jsonrpc:"2.0",method:e,id:n,...o!==void 0&&{params:o}};return new Promise((r,d)=>{this.pending.set(n,{resolve:r,reject:d}),window.parent.postMessage(a,"*");})}onMessage(e,o){return this.handlers.has(e)||this.handlers.set(e,new Set),this.handlers.get(e)?.add(o),()=>{let n=this.handlers.get(e);n&&(n.delete(o),n.size===0&&this.handlers.delete(e));}}destroy(){if(this.destroyed)return;this.destroyed=true,window.removeEventListener("message",this.listener);let e=new Error("Transport destroyed");for(let o of this.pending.values())o.reject(e);this.pending.clear(),this.handlers.clear();}handleMessage(e){if(this.destroyed)return;let o=e.data;if(!(!o||o.jsonrpc!=="2.0")){if("id"in o&&o.id&&!("method"in o)){let n=o,a=this.pending.get(n.id);if(!a)return;if(this.pending.delete(n.id),n.error){let r=new Error(n.error.message);r.code=n.error.code,r.data=n.error.data,a.reject(r);}else a.resolve(n.result);return}if("method"in o&&!("id"in o&&o.id)){let n=o,a=this.handlers.get(n.method);if(a)for(let r of a)r(n.params);}}}};async function O(s){let{name:e,version:o,autoResize:n=false}=s,a=new S,r=false,d={mode:"light",tokens:{}},c={name:"unknown",version:"unknown"},m=null,p=null,g=new Map,v=K((u,t)=>a.send(u,t),n);v.measureAndSend();let w=await a.request("ui/initialize",{protocolVersion:"2026-01-26",clientInfo:{name:e,version:o},capabilities:{}})??{},h=x(w.serverInfo);c={name:typeof h?.name=="string"?h.name:"unknown",version:typeof h?.version=="string"?h.version:"unknown"};let y=x(w.hostContext);if(y){let u=x(y.theme);if(u&&(d={mode:u.mode==="dark"?"dark":"light",tokens:u.tokens&&typeof u.tokens=="object"&&!Array.isArray(u.tokens)?u.tokens:{}}),y.toolInfo&&typeof y.toolInfo=="object"){let i=y.toolInfo;m={tool:i.tool??i};}y.containerDimensions&&typeof y.containerDimensions=="object"&&(p=y.containerDimensions);let t=x(y.styles);D(t?.variables);}a.send("ui/notifications/initialized",{});let R=C("theme-changed");a.onMessage(R,u=>{if(r||!u)return;let t=u.theme==="dark"?"dark":"light",i=u.tokens&&typeof u.tokens=="object"&&!Array.isArray(u.tokens)?u.tokens:d.tokens;d={mode:t,tokens:i},D(i);let l=g.get(R);if(l)for(let k of l)k(d);});let T=new Set([R]);function j(u){if(T.has(u))return;T.add(u);let t=C("tool-result"),i=u===t;a.onMessage(u,l=>{if(r)return;let k=g.get(u);if(k)for(let F of k)F(i?I(l):l);});}return {get theme(){return {...d}},get hostInfo(){return {...c}},get toolInfo(){return m},get containerDimensions(){return p},on(u,t){let i=C(u);return g.has(i)||g.set(i,new Set),g.get(i)?.add(t),j(i),()=>{let l=g.get(i);l&&(l.delete(t),l.size===0&&g.delete(i));}},resize(u,t){v.resize(u,t);},openLink(u){r||a.send("ui/open-link",{url:u});},updateModelContext(u,t){r||a.send("ui/update-model-context",{structuredContent:u,...t!==void 0&&{content:[{type:"text",text:t}]}});},async callTool(u,t){let i=await a.request("tools/call",{name:u,arguments:t??{}});return A(i)},sendMessage(u,t){if(r)return;let i={type:"text",text:u};t&&(i._meta={context:t}),a.send("ui/message",{role:"user",content:[i]});},destroy(){r||(r=true,v.destroy(),g.clear(),a.destroy());}}}function x(s){if(s!==null&&typeof s=="object"&&!Array.isArray(s))return s}function D(s){if(!(!s||typeof s!="object"))for(let[e,o]of Object.entries(s))typeof e=="string"&&typeof o=="string"&&document.documentElement.style.setProperty(e,o);}var E={mode:"light",primaryColor:"#6366f1",tokens:{}};function q(s){let e=s,o=z(e?.serverInfo),n=typeof o?.name=="string"?o.name:"unknown",a=typeof e?.protocolVersion=="string"?e.protocolVersion:"unknown",r=z(e?.hostContext),d=L(r?.theme);return {isNimbleBrain:n==="nimblebrain",serverName:n,protocolVersion:a,theme:d}}function L(s){let e=z(s);if(!e)return {...E};let o=e.mode==="light"||e.mode==="dark"?e.mode:E.mode,n=typeof e.primaryColor=="string"?e.primaryColor:E.primaryColor,a=e.tokens!==null&&typeof e.tokens=="object"&&!Array.isArray(e.tokens)?e.tokens:{};return {mode:o,primaryColor:n,tokens:a}}function z(s){if(s!==null&&typeof s=="object"&&!Array.isArray(s))return s}var M=class{listener;destroyed=false;constructor(e,o){let n=o??null;this.listener=a=>{this.destroyed||this.shouldForward(a,n)&&(a.preventDefault(),e.send("synapse/keydown",{key:a.key,ctrlKey:a.ctrlKey,metaKey:a.metaKey,shiftKey:a.shiftKey,altKey:a.altKey}));},document.addEventListener("keydown",this.listener);}destroy(){this.destroyed||(this.destroyed=true,document.removeEventListener("keydown",this.listener));}shouldForward(e,o){if(o&&o.length===0)return false;if(o)return o.some(n=>e.key.toLowerCase()===n.key.toLowerCase()&&(n.ctrl===void 0||e.ctrlKey===n.ctrl)&&(n.meta===void 0||e.metaKey===n.meta)&&(n.shift===void 0||e.shiftKey===n.shift)&&(n.alt===void 0||e.altKey===n.alt));if(e.key==="Escape")return true;if(e.ctrlKey||e.metaKey){let n=e.key.toLowerCase();return !(n==="c"||n==="v"||n==="x"||n==="a")}return false}};function P(s){let{name:e,version:o,internal:n=false,forwardKeys:a}=s,r=new S,d=null,c={mode:"light",primaryColor:"#6366f1",tokens:{}},m=false,p=null,g=null,v=r.request("ui/initialize",{protocolVersion:"2026-01-26",clientInfo:{name:e,version:o},capabilities:{}}).then(t=>{d=q(t),c=d.theme,r.send("ui/notifications/initialized",{}),g=new M(r,a);}),f=r.onMessage("ui/notifications/host-context-changed",t=>{if(!t)return;let i=t.theme==="dark"?"dark":"light",l=t.tokens&&typeof t.tokens=="object"?t.tokens:c.tokens;c={mode:i,primaryColor:c.primaryColor,tokens:l};for(let k of h)k(c);}),w=r.onMessage("synapse/theme-changed",t=>{if(!t)return;let i=t.mode==="dark"||t.mode==="light"?t.mode:c.mode,l=t.tokens&&typeof t.tokens=="object"?t.tokens:c.tokens;c={mode:i,primaryColor:c.primaryColor,tokens:l};for(let k of h)k(c);}),h=new Set,y=new Set,R=new Set,T=r.onMessage("synapse/data-changed",t=>{if(!t)return;let i={source:"agent",server:t.server??"",tool:t.tool??""};for(let l of y)l(i);}),j=r.onMessage("synapse/action",t=>{if(!t||typeof t.type!="string")return;let i={type:t.type,payload:t.payload??{},requiresConfirmation:t.requiresConfirmation===true,label:typeof t.label=="string"?t.label:void 0};for(let l of R)l(i);}),b=()=>d?.isNimbleBrain===true;return {get ready(){return v},get isNimbleBrainHost(){return b()},get destroyed(){return m},async callTool(t,i){let l={name:t,arguments:i??{}};n&&(l.server=e);let k=await r.request("tools/call",l);return A(k)},onDataChanged(t){return y.add(t),()=>{y.delete(t);}},onAction(t){return R.add(t),()=>{R.delete(t);}},getTheme(){return {...c}},onThemeChanged(t){return h.add(t),()=>{h.delete(t);}},action(t,i){b()&&r.send("synapse/action",{action:t,...i});},chat(t,i){let l={type:"text",text:t};b()&&i&&(l._meta={context:i}),r.send("ui/message",{role:"user",content:[l]});},setVisibleState(t,i){p&&clearTimeout(p),p=setTimeout(()=>{r.send("ui/update-model-context",{structuredContent:t,...i!==void 0&&{content:[{type:"text",text:i}]}}),p=null;},250);},saveFile(t,i,l){let k=typeof i=="string"?i:"[Blob content not serializable]";r.send("synapse/save-file",{data:k,filename:t,mimeType:l??"application/octet-stream"});},openLink(t){r.send("ui/open-link",{url:t}),b()||window.open(t,"_blank","noopener");},async pickFile(t){if(!b())throw new Error("pickFile is not supported in this host");return await r.request("synapse/pick-file",{accept:t?.accept,maxSize:t?.maxSize??26214400,multiple:false})??null},async pickFiles(t){if(!b())throw new Error("pickFiles is not supported in this host");let i=await r.request("synapse/pick-file",{accept:t?.accept,maxSize:t?.maxSize??26214400,multiple:true});return i?Array.isArray(i)?i:[i]:[]},_onMessage(t,i){return r.onMessage(t,i)},_request(t,i){return r.request(t,i)},destroy(){m||(m=true,p&&clearTimeout(p),g?.destroy(),f(),w(),T(),j(),h.clear(),y.clear(),R.clear(),r.destroy());}}}function N(s,e){let o=structuredClone(e.initialState),n=new Set,a=false,r=null,d={};for(let f of Object.keys(e.actions))d[f]=w=>{a||(o=e.actions[f](o,w),c());};function c(){for(let f of n)f(o);e.visibleToAgent&&m(),e.persist&&p();}function m(){let f=e.summarize?.(o);s.setVisibleState(o,f);}function p(){r&&clearTimeout(r),r=setTimeout(()=>{s._request("synapse/persist-state",{state:o,version:e.version}).catch(()=>{}),r=null;},500);}let g;e.persist&&(g=s._onMessage("synapse/state-loaded",f=>{if(!f?.state)return;let w=f.state,h=f.version??1,y=e.version??1;if(e.migrations&&h<y){let R=h-1;for(let T=R;T<e.migrations.length;T++)w=e.migrations[T](w);}v.hydrate(w);}));let v={getState(){return o},subscribe(f){return n.add(f),()=>{n.delete(f);}},dispatch:d,hydrate(f){o=f;for(let w of n)w(o);},destroy(){a||(a=true,r&&clearTimeout(r),n.clear(),g?.());}};return v}window.Synapse={connect:O,createSynapse:P,createStore:N};})();
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkY4ZDNAYQ_cjs = require('./chunk-Y4ZDNAYQ.cjs');
3
+ var chunkB3T6NB32_cjs = require('./chunk-B3T6NB32.cjs');
4
4
 
5
5
  // src/store.ts
6
6
  function createStore(synapse, config) {
@@ -28,7 +28,7 @@ function createStore(synapse, config) {
28
28
  function schedulePersist() {
29
29
  if (persistTimer) clearTimeout(persistTimer);
30
30
  persistTimer = setTimeout(() => {
31
- synapse._request("ui/persistState", {
31
+ synapse._request("synapse/persist-state", {
32
32
  state,
33
33
  version: config.version
34
34
  }).catch(() => {
@@ -38,7 +38,7 @@ function createStore(synapse, config) {
38
38
  }
39
39
  let unsubStateLoaded;
40
40
  if (config.persist) {
41
- unsubStateLoaded = synapse._onMessage("ui/stateLoaded", (params) => {
41
+ unsubStateLoaded = synapse._onMessage("synapse/state-loaded", (params) => {
42
42
  if (!params?.state) return;
43
43
  let loaded = params.state;
44
44
  const loadedVersion = params.version ?? 1;
@@ -78,9 +78,13 @@ function createStore(synapse, config) {
78
78
  return store;
79
79
  }
80
80
 
81
+ Object.defineProperty(exports, "connect", {
82
+ enumerable: true,
83
+ get: function () { return chunkB3T6NB32_cjs.connect; }
84
+ });
81
85
  Object.defineProperty(exports, "createSynapse", {
82
86
  enumerable: true,
83
- get: function () { return chunkY4ZDNAYQ_cjs.createSynapse; }
87
+ get: function () { return chunkB3T6NB32_cjs.createSynapse; }
84
88
  });
85
89
  exports.createStore = createStore;
86
90
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"ui/persistState\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"ui/stateLoaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
1
+ {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"synapse/persist-state\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"synapse/state-loaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,13 @@
1
- import { S as SynapseOptions, a as Synapse, A as ActionReducer, b as StoreConfig, c as Store } from './types-DElq_otH.cjs';
2
- export { d as AgentAction, B as BuiltinActionType, D as DataChangedEvent, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, e as NotifyPayload, f as StateAcknowledgement, g as StoreDispatch, h as SynapseTheme, T as ToolCallResult, i as ToolDefinition, V as VisibleState } from './types-DElq_otH.cjs';
1
+ import { C as ConnectOptions, A as App, S as SynapseOptions, a as Synapse, b as ActionReducer, c as StoreConfig, d as Store } from './types-DJ32F5EL.cjs';
2
+ export { e as AgentAction, f as AppEventName, B as BuiltinActionType, D as DataChangedEvent, g as Dimensions, F as FileResult, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, h as NotifyPayload, R as RequestFileOptions, i as StateAcknowledgement, j as StoreDispatch, k as SynapseTheme, l as Theme, m as ToolCallResult, T as ToolDefinition, n as ToolResultData, V as VisibleState } from './types-DJ32F5EL.cjs';
3
+
4
+ /**
5
+ * Connect to a MCP Apps host.
6
+ *
7
+ * Owns the full ext-apps handshake (steps 1-9 from the RFC), content parsing,
8
+ * resize management, and event routing. Returns a ready-to-use `App` object.
9
+ */
10
+ declare function connect(options: ConnectOptions): Promise<App>;
3
11
 
4
12
  /**
5
13
  * Create a Synapse instance.
@@ -23,4 +31,4 @@ declare function createStore<TState, TActions extends Record<string, ActionReduc
23
31
  actions: TActions;
24
32
  }): Store<TState, TActions>;
25
33
 
26
- export { ActionReducer, Store, StoreConfig, Synapse, SynapseOptions, createStore, createSynapse };
34
+ export { ActionReducer, App, ConnectOptions, Store, StoreConfig, Synapse, SynapseOptions, connect, createStore, createSynapse };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,13 @@
1
- import { S as SynapseOptions, a as Synapse, A as ActionReducer, b as StoreConfig, c as Store } from './types-DElq_otH.js';
2
- export { d as AgentAction, B as BuiltinActionType, D as DataChangedEvent, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, e as NotifyPayload, f as StateAcknowledgement, g as StoreDispatch, h as SynapseTheme, T as ToolCallResult, i as ToolDefinition, V as VisibleState } from './types-DElq_otH.js';
1
+ import { C as ConnectOptions, A as App, S as SynapseOptions, a as Synapse, b as ActionReducer, c as StoreConfig, d as Store } from './types-DJ32F5EL.js';
2
+ export { e as AgentAction, f as AppEventName, B as BuiltinActionType, D as DataChangedEvent, g as Dimensions, F as FileResult, H as HostInfo, K as KeyForwardConfig, N as NavigatePayload, h as NotifyPayload, R as RequestFileOptions, i as StateAcknowledgement, j as StoreDispatch, k as SynapseTheme, l as Theme, m as ToolCallResult, T as ToolDefinition, n as ToolResultData, V as VisibleState } from './types-DJ32F5EL.js';
3
+
4
+ /**
5
+ * Connect to a MCP Apps host.
6
+ *
7
+ * Owns the full ext-apps handshake (steps 1-9 from the RFC), content parsing,
8
+ * resize management, and event routing. Returns a ready-to-use `App` object.
9
+ */
10
+ declare function connect(options: ConnectOptions): Promise<App>;
3
11
 
4
12
  /**
5
13
  * Create a Synapse instance.
@@ -23,4 +31,4 @@ declare function createStore<TState, TActions extends Record<string, ActionReduc
23
31
  actions: TActions;
24
32
  }): Store<TState, TActions>;
25
33
 
26
- export { ActionReducer, Store, StoreConfig, Synapse, SynapseOptions, createStore, createSynapse };
34
+ export { ActionReducer, App, ConnectOptions, Store, StoreConfig, Synapse, SynapseOptions, connect, createStore, createSynapse };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { createSynapse } from './chunk-7KEYXJWD.js';
1
+ export { connect, createSynapse } from './chunk-GQ4L63CL.js';
2
2
 
3
3
  // src/store.ts
4
4
  function createStore(synapse, config) {
@@ -26,7 +26,7 @@ function createStore(synapse, config) {
26
26
  function schedulePersist() {
27
27
  if (persistTimer) clearTimeout(persistTimer);
28
28
  persistTimer = setTimeout(() => {
29
- synapse._request("ui/persistState", {
29
+ synapse._request("synapse/persist-state", {
30
30
  state,
31
31
  version: config.version
32
32
  }).catch(() => {
@@ -36,7 +36,7 @@ function createStore(synapse, config) {
36
36
  }
37
37
  let unsubStateLoaded;
38
38
  if (config.persist) {
39
- unsubStateLoaded = synapse._onMessage("ui/stateLoaded", (params) => {
39
+ unsubStateLoaded = synapse._onMessage("synapse/state-loaded", (params) => {
40
40
  if (!params?.state) return;
41
41
  let loaded = params.state;
42
42
  const loadedVersion = params.version ?? 1;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"ui/persistState\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"ui/stateLoaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
1
+ {"version":3,"sources":["../src/store.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ActionReducer, Store, StoreConfig, StoreDispatch, Synapse } from \"./types.js\";\n\n/**\n * Create a typed state store with optional persistence and agent visibility.\n *\n * - `persist: true` — state survives iframe reloads via host storage\n * - `visibleToAgent: true` — state is pushed to the LLM context\n * - Both are independent and can be enabled separately\n */\nexport function createStore<\n TState,\n TActions extends Record<string, ActionReducer<TState, any>> = Record<\n string,\n ActionReducer<TState, any>\n >,\n>(synapse: Synapse, config: StoreConfig<TState> & { actions: TActions }): Store<TState, TActions> {\n let state = structuredClone(config.initialState);\n const subscribers = new Set<(state: TState) => void>();\n let destroyed = false;\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n // Build dispatch object from action reducers\n const dispatch = {} as StoreDispatch<TActions>;\n for (const key of Object.keys(config.actions)) {\n (dispatch as any)[key] = (payload: unknown) => {\n if (destroyed) return;\n state = config.actions[key](state, payload);\n notify();\n };\n }\n\n function notify(): void {\n for (const cb of subscribers) cb(state);\n if (config.visibleToAgent) pushToAgent();\n if (config.persist) schedulePersist();\n }\n\n function pushToAgent(): void {\n const summary = config.summarize?.(state);\n synapse.setVisibleState(state as unknown as Record<string, unknown>, summary);\n }\n\n function schedulePersist(): void {\n if (persistTimer) clearTimeout(persistTimer);\n persistTimer = setTimeout(() => {\n synapse\n ._request(\"synapse/persist-state\", {\n state: state as unknown as Record<string, unknown>,\n version: config.version,\n })\n .catch(() => {\n // Silently ignore persist failures (host may not support it)\n });\n persistTimer = null;\n }, 500);\n }\n\n // Listen for state loaded from host (on init)\n let unsubStateLoaded: (() => void) | undefined;\n if (config.persist) {\n unsubStateLoaded = synapse._onMessage(\"synapse/state-loaded\", (params) => {\n if (!params?.state) return;\n let loaded = params.state as TState;\n const loadedVersion = (params.version as number) ?? 1;\n const currentVersion = config.version ?? 1;\n\n // Run migrations if needed\n if (config.migrations && loadedVersion < currentVersion) {\n const startIdx = loadedVersion - 1;\n for (let i = startIdx; i < config.migrations.length; i++) {\n loaded = config.migrations[i](loaded);\n }\n }\n\n store.hydrate(loaded);\n });\n }\n\n const store: Store<TState, TActions> = {\n getState(): TState {\n return state;\n },\n\n subscribe(callback: (state: TState) => void): () => void {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n },\n\n dispatch,\n\n hydrate(newState: TState): void {\n state = newState;\n for (const cb of subscribers) cb(state);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (persistTimer) clearTimeout(persistTimer);\n subscribers.clear();\n unsubStateLoaded?.();\n },\n };\n\n return store;\n}\n"]}
@@ -1,16 +1,98 @@
1
1
  'use strict';
2
2
 
3
- var chunkY4ZDNAYQ_cjs = require('../chunk-Y4ZDNAYQ.cjs');
3
+ var chunkB3T6NB32_cjs = require('../chunk-B3T6NB32.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
7
+ var AppContext = react.createContext(null);
8
+ function AppProvider({ children, name, version, autoResize }) {
9
+ const [app, setApp] = react.useState(null);
10
+ const connectingRef = react.useRef(false);
11
+ react.useEffect(() => {
12
+ if (connectingRef.current) return;
13
+ connectingRef.current = true;
14
+ chunkB3T6NB32_cjs.connect({ name, version, autoResize }).then((a) => {
15
+ setApp(a);
16
+ });
17
+ }, []);
18
+ if (!app) return null;
19
+ return /* @__PURE__ */ jsxRuntime.jsx(AppContext.Provider, { value: app, children });
20
+ }
21
+ function useAppContext() {
22
+ const ctx = react.useContext(AppContext);
23
+ if (!ctx) {
24
+ throw new Error(
25
+ "useApp must be used within an <AppProvider>. Wrap your component tree with <AppProvider>."
26
+ );
27
+ }
28
+ return ctx;
29
+ }
30
+
31
+ // src/react/connect-hooks.ts
32
+ function useApp() {
33
+ return useAppContext();
34
+ }
35
+ function useToolResult() {
36
+ const app = useAppContext();
37
+ const [data, setData] = react.useState(null);
38
+ react.useEffect(() => {
39
+ return app.on("tool-result", (result) => {
40
+ setData(result);
41
+ });
42
+ }, [app]);
43
+ return data;
44
+ }
45
+ function useToolInput() {
46
+ const app = useAppContext();
47
+ const [input, setInput] = react.useState(null);
48
+ react.useEffect(() => {
49
+ return app.on("tool-input", (args) => {
50
+ setInput(args);
51
+ });
52
+ }, [app]);
53
+ return input;
54
+ }
55
+ function useConnectTheme() {
56
+ const app = useAppContext();
57
+ const [theme, setTheme] = react.useState(() => app.theme);
58
+ react.useEffect(() => {
59
+ setTheme(app.theme);
60
+ return app.on("theme-changed", (t) => {
61
+ setTheme(t);
62
+ });
63
+ }, [app]);
64
+ return theme;
65
+ }
66
+ function useResize() {
67
+ const app = useAppContext();
68
+ return react.useCallback((width, height) => app.resize(width, height), [app]);
69
+ }
7
70
  var SynapseContext = react.createContext(null);
8
71
  function SynapseProvider({ children, ...options }) {
9
72
  const ref = react.useRef(null);
10
73
  if (ref.current === null || ref.current.destroyed) {
11
- ref.current = chunkY4ZDNAYQ_cjs.createSynapse(options);
74
+ ref.current = chunkB3T6NB32_cjs.createSynapse(options);
12
75
  }
13
- return /* @__PURE__ */ jsxRuntime.jsx(SynapseContext.Provider, { value: ref.current, children });
76
+ return /* @__PURE__ */ jsxRuntime.jsxs(SynapseContext.Provider, { value: ref.current, children: [
77
+ /* @__PURE__ */ jsxRuntime.jsx(ThemeInjector, { synapse: ref.current }),
78
+ children
79
+ ] });
80
+ }
81
+ function ThemeInjector({ synapse }) {
82
+ const [theme, setTheme] = react.useState(() => synapse.getTheme());
83
+ react.useEffect(() => {
84
+ setTheme(synapse.getTheme());
85
+ return synapse.onThemeChanged(setTheme);
86
+ }, [synapse]);
87
+ react.useEffect(() => {
88
+ if (theme.tokens) {
89
+ const style = document.documentElement.style;
90
+ for (const [k, v] of Object.entries(theme.tokens)) {
91
+ style.setProperty(k, v);
92
+ }
93
+ }
94
+ }, [theme]);
95
+ return null;
14
96
  }
15
97
  function useSynapseContext() {
16
98
  const ctx = react.useContext(SynapseContext);
@@ -111,6 +193,33 @@ function useVisibleState(factory, deps) {
111
193
  }, [...deps ?? [], push]);
112
194
  if (!factory) return push;
113
195
  }
196
+ function useFileUpload() {
197
+ const synapse = useSynapseContext();
198
+ const [isPending, setIsPending] = react.useState(false);
199
+ const pickFile = react.useCallback(
200
+ async (options) => {
201
+ setIsPending(true);
202
+ try {
203
+ return await synapse.pickFile(options);
204
+ } finally {
205
+ setIsPending(false);
206
+ }
207
+ },
208
+ [synapse]
209
+ );
210
+ const pickFiles = react.useCallback(
211
+ async (options) => {
212
+ setIsPending(true);
213
+ try {
214
+ return await synapse.pickFiles(options);
215
+ } finally {
216
+ setIsPending(false);
217
+ }
218
+ },
219
+ [synapse]
220
+ );
221
+ return { pickFile, pickFiles, isPending };
222
+ }
114
223
  function useStore(store) {
115
224
  const state = react.useSyncExternalStore(
116
225
  (onStoreChange) => store.subscribe(onStoreChange),
@@ -120,15 +229,22 @@ function useStore(store) {
120
229
  return { state, dispatch: store.dispatch };
121
230
  }
122
231
 
232
+ exports.AppProvider = AppProvider;
123
233
  exports.SynapseProvider = SynapseProvider;
124
234
  exports.useAction = useAction;
125
235
  exports.useAgentAction = useAgentAction;
236
+ exports.useApp = useApp;
126
237
  exports.useCallTool = useCallTool;
127
238
  exports.useChat = useChat;
239
+ exports.useConnectTheme = useConnectTheme;
128
240
  exports.useDataSync = useDataSync;
241
+ exports.useFileUpload = useFileUpload;
242
+ exports.useResize = useResize;
129
243
  exports.useStore = useStore;
130
244
  exports.useSynapse = useSynapse;
131
245
  exports.useTheme = useTheme;
246
+ exports.useToolInput = useToolInput;
247
+ exports.useToolResult = useToolResult;
132
248
  exports.useVisibleState = useVisibleState;
133
249
  //# sourceMappingURL=index.cjs.map
134
250
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/provider.tsx","../../src/react/hooks.ts"],"names":["createContext","useRef","createSynapse","useContext","useState","useCallback","useEffect","useSyncExternalStore"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createContext, type ReactNode, useContext, useRef } from \"react\";\nimport { createSynapse } from \"../core.js\";\nimport type { Synapse, SynapseOptions } 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 <SynapseContext.Provider value={ref.current}>{children}</SynapseContext.Provider>;\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 { useCallback, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport type {\n ActionReducer,\n AgentAction,\n DataChangedEvent,\n Store,\n StoreDispatch,\n Synapse,\n SynapseTheme,\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\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 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"]}
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","useSyncExternalStore"],"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 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 if (theme.tokens) {\n const style = document.documentElement.style;\n for (const [k, v] of Object.entries(theme.tokens)) {\n style.setProperty(k, v);\n }\n }\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 { useCallback, useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport type {\n ActionReducer,\n AgentAction,\n DataChangedEvent,\n FileResult,\n RequestFileOptions,\n Store,\n StoreDispatch,\n Synapse,\n SynapseTheme,\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\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"]}
@@ -1,6 +1,17 @@
1
- import { S as SynapseOptions, d as AgentAction, T as ToolCallResult, D as DataChangedEvent, A as ActionReducer, c as Store, g as StoreDispatch, a as Synapse, h as SynapseTheme } from '../types-DElq_otH.cjs';
2
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
2
  import { ReactNode } from 'react';
3
+ import { C as ConnectOptions, A as App, l as Theme, n as ToolResultData, S as SynapseOptions, e as AgentAction, m as ToolCallResult, D as DataChangedEvent, R as RequestFileOptions, F as FileResult, b as ActionReducer, d as Store, j as StoreDispatch, a as Synapse, k as SynapseTheme } from '../types-DJ32F5EL.cjs';
4
+
5
+ interface AppProviderProps extends ConnectOptions {
6
+ children: ReactNode;
7
+ }
8
+ declare function AppProvider({ children, name, version, autoResize }: AppProviderProps): react_jsx_runtime.JSX.Element | null;
9
+
10
+ declare function useApp(): App;
11
+ declare function useToolResult(): ToolResultData | null;
12
+ declare function useToolInput(): Record<string, unknown> | null;
13
+ declare function useConnectTheme(): Theme;
14
+ declare function useResize(): (width?: number, height?: number) => void;
4
15
 
5
16
  interface SynapseProviderProps extends SynapseOptions {
6
17
  children: ReactNode;
@@ -60,9 +71,14 @@ declare function useVisibleState(factory: () => {
60
71
  state: Record<string, unknown>;
61
72
  summary?: string;
62
73
  }, deps: unknown[]): void;
74
+ declare function useFileUpload(): {
75
+ pickFile: (options?: RequestFileOptions) => Promise<FileResult | null>;
76
+ pickFiles: (options?: RequestFileOptions) => Promise<FileResult[]>;
77
+ isPending: boolean;
78
+ };
63
79
  declare function useStore<TState, TActions extends Record<string, ActionReducer<TState, any>>>(store: Store<TState, TActions>): {
64
80
  state: TState;
65
81
  dispatch: StoreDispatch<TActions>;
66
82
  };
67
83
 
68
- export { SynapseProvider, type SynapseProviderProps, useAction, useAgentAction, useCallTool, useChat, useDataSync, useStore, useSynapse, useTheme, useVisibleState };
84
+ export { AppProvider, type AppProviderProps, SynapseProvider, type SynapseProviderProps, useAction, useAgentAction, useApp, useCallTool, useChat, useConnectTheme, useDataSync, useFileUpload, useResize, useStore, useSynapse, useTheme, useToolInput, useToolResult, useVisibleState };
@@ -1,6 +1,17 @@
1
- import { S as SynapseOptions, d as AgentAction, T as ToolCallResult, D as DataChangedEvent, A as ActionReducer, c as Store, g as StoreDispatch, a as Synapse, h as SynapseTheme } from '../types-DElq_otH.js';
2
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
2
  import { ReactNode } from 'react';
3
+ import { C as ConnectOptions, A as App, l as Theme, n as ToolResultData, S as SynapseOptions, e as AgentAction, m as ToolCallResult, D as DataChangedEvent, R as RequestFileOptions, F as FileResult, b as ActionReducer, d as Store, j as StoreDispatch, a as Synapse, k as SynapseTheme } from '../types-DJ32F5EL.js';
4
+
5
+ interface AppProviderProps extends ConnectOptions {
6
+ children: ReactNode;
7
+ }
8
+ declare function AppProvider({ children, name, version, autoResize }: AppProviderProps): react_jsx_runtime.JSX.Element | null;
9
+
10
+ declare function useApp(): App;
11
+ declare function useToolResult(): ToolResultData | null;
12
+ declare function useToolInput(): Record<string, unknown> | null;
13
+ declare function useConnectTheme(): Theme;
14
+ declare function useResize(): (width?: number, height?: number) => void;
4
15
 
5
16
  interface SynapseProviderProps extends SynapseOptions {
6
17
  children: ReactNode;
@@ -60,9 +71,14 @@ declare function useVisibleState(factory: () => {
60
71
  state: Record<string, unknown>;
61
72
  summary?: string;
62
73
  }, deps: unknown[]): void;
74
+ declare function useFileUpload(): {
75
+ pickFile: (options?: RequestFileOptions) => Promise<FileResult | null>;
76
+ pickFiles: (options?: RequestFileOptions) => Promise<FileResult[]>;
77
+ isPending: boolean;
78
+ };
63
79
  declare function useStore<TState, TActions extends Record<string, ActionReducer<TState, any>>>(store: Store<TState, TActions>): {
64
80
  state: TState;
65
81
  dispatch: StoreDispatch<TActions>;
66
82
  };
67
83
 
68
- export { SynapseProvider, type SynapseProviderProps, useAction, useAgentAction, useCallTool, useChat, useDataSync, useStore, useSynapse, useTheme, useVisibleState };
84
+ export { AppProvider, type AppProviderProps, SynapseProvider, type SynapseProviderProps, useAction, useAgentAction, useApp, useCallTool, useChat, useConnectTheme, useDataSync, useFileUpload, useResize, useStore, useSynapse, useTheme, useToolInput, useToolResult, useVisibleState };