@nimblebrain/synapse 0.16.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +61 -111
  2. package/dist/{chunk-SN7YXLAV.cjs → chunk-EHLQWCYV.cjs} +6 -6
  3. package/dist/{chunk-SN7YXLAV.cjs.map → chunk-EHLQWCYV.cjs.map} +1 -1
  4. package/dist/{chunk-ZMNYUGSF.cjs → chunk-FDMRJZKT.cjs} +576 -662
  5. package/dist/chunk-FDMRJZKT.cjs.map +1 -0
  6. package/dist/{chunk-E7OOOYVR.js → chunk-SRQNQ26I.js} +3 -3
  7. package/dist/{chunk-E7OOOYVR.js.map → chunk-SRQNQ26I.js.map} +1 -1
  8. package/dist/{chunk-RYWW6EHB.cjs → chunk-TXJMGQYF.cjs} +3 -5
  9. package/dist/chunk-TXJMGQYF.cjs.map +1 -0
  10. package/dist/{chunk-J5ICAHK2.js → chunk-UPDBDXQB.js} +4 -5
  11. package/dist/chunk-UPDBDXQB.js.map +1 -0
  12. package/dist/{chunk-GNTQJSQX.js → chunk-VYR6V47N.js} +573 -663
  13. package/dist/chunk-VYR6V47N.js.map +1 -0
  14. package/dist/codegen/cli.cjs +1 -1
  15. package/dist/codegen/cli.js +1 -1
  16. package/dist/codegen/index.d.cts +1 -1
  17. package/dist/codegen/index.d.ts +1 -1
  18. package/dist/connect.iife.global.js +28 -28
  19. package/dist/{detect-C_qmYsh9.d.cts → detect-BHYg26_d.d.cts} +1 -1
  20. package/dist/{detect-Dfd0upoz.d.ts → detect-Bf8Q_0dK.d.ts} +1 -1
  21. package/dist/host/index.cjs +14 -14
  22. package/dist/host/index.d.cts +3 -3
  23. package/dist/host/index.d.ts +3 -3
  24. package/dist/host/index.js +2 -2
  25. package/dist/index.cjs +28 -87
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +58 -26
  28. package/dist/index.d.ts +58 -26
  29. package/dist/index.js +3 -81
  30. package/dist/index.js.map +1 -1
  31. package/dist/react/index.cjs +81 -140
  32. package/dist/react/index.cjs.map +1 -1
  33. package/dist/react/index.d.cts +66 -82
  34. package/dist/react/index.d.ts +66 -82
  35. package/dist/react/index.js +82 -136
  36. package/dist/react/index.js.map +1 -1
  37. package/dist/{server-ERRDGEZ7.js → server-5N76YCWC.js} +3 -3
  38. package/dist/{server-ERRDGEZ7.js.map → server-5N76YCWC.js.map} +1 -1
  39. package/dist/{server-P54IYX2G.cjs → server-QIYIJHD5.cjs} +3 -3
  40. package/dist/{server-P54IYX2G.cjs.map → server-QIYIJHD5.cjs.map} +1 -1
  41. package/dist/synapse-runtime.iife.global.js +28 -28
  42. package/dist/synapse-ui.iife.global.js +2 -2
  43. package/dist/{types-BSZasM8q.d.cts → types-uEO4VFJ2.d.cts} +87 -166
  44. package/dist/{types-BSZasM8q.d.ts → types-uEO4VFJ2.d.ts} +87 -166
  45. package/dist/ui/index.cjs +48 -35
  46. package/dist/ui/index.cjs.map +1 -1
  47. package/dist/ui/index.d.cts +1 -1
  48. package/dist/ui/index.d.ts +1 -1
  49. package/dist/ui/index.js +48 -35
  50. package/dist/ui/index.js.map +1 -1
  51. package/dist/vite/index.cjs +1 -1
  52. package/dist/vite/index.cjs.map +1 -1
  53. package/dist/vite/index.js +1 -1
  54. package/dist/vite/index.js.map +1 -1
  55. package/package.json +1 -1
  56. package/dist/chunk-GNTQJSQX.js.map +0 -1
  57. package/dist/chunk-J5ICAHK2.js.map +0 -1
  58. package/dist/chunk-RYWW6EHB.cjs.map +0 -1
  59. package/dist/chunk-ZMNYUGSF.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
- (function(){'use strict';var be=new Set(["auto","block","swap","fallback","optional"]),ke={"--color-background-primary":"#ffffff","--color-background-secondary":"#fafafa","--color-background-tertiary":"#f3f4f6","--color-text-primary":"#111827","--color-text-secondary":"#6b7280","--color-text-tertiary":"#9ca3af","--color-text-accent":"#2563eb","--nb-color-accent-foreground":"#ffffff","--color-border-primary":"#e5e7eb","--color-border-secondary":"#d1d5db","--color-ring-primary":"#2563eb","--nb-color-danger":"#dc2626","--nb-color-success":"#059669","--nb-color-warning":"#f59e0b","--nb-color-processing":"#7c3aed","--nb-color-processing-light":"#f3eeff","--nb-color-info-light":"#eef4ff"},Pe={"--color-background-primary":"#18181b","--color-background-secondary":"#27272a","--color-background-tertiary":"#2f2f34","--color-text-primary":"#fafafa","--color-text-secondary":"#a1a1aa","--color-text-tertiary":"#71717a","--color-text-accent":"#818cf8","--nb-color-accent-foreground":"#ffffff","--color-border-primary":"#3f3f46","--color-border-secondary":"#52525b","--color-ring-primary":"#818cf8","--nb-color-danger":"#f87171","--nb-color-success":"#34d399","--nb-color-warning":"#fbbf24","--nb-color-processing":"#a78bfa","--nb-color-processing-light":"#2a2440","--nb-color-info-light":"#1e2a44"},Ee={light:ke,dark:Pe},Ie="synapse-defaults",G="synapse-theme-defaults",W=new Set;function ve(){return typeof document<"u"&&typeof document.getElementById=="function"&&typeof document.createElement=="function"&&typeof document.head?.prepend=="function"}function Ce(e){if(!ve())return;let o=Object.entries(Ee[e]).map(([a,p])=>` ${a}: ${p};`).join(`
1
+ (function(){'use strict';var be=new Set(["auto","block","swap","fallback","optional"]),ke={"--color-background-primary":"#ffffff","--color-background-secondary":"#fafafa","--color-background-tertiary":"#f3f4f6","--color-text-primary":"#111827","--color-text-secondary":"#6b7280","--color-text-tertiary":"#9ca3af","--color-text-accent":"#2563eb","--nb-color-accent-foreground":"#ffffff","--color-border-primary":"#e5e7eb","--color-border-secondary":"#d1d5db","--color-ring-primary":"#2563eb","--nb-color-danger":"#dc2626","--nb-color-success":"#059669","--nb-color-warning":"#f59e0b","--nb-color-processing":"#7c3aed","--nb-color-processing-light":"#f3eeff","--nb-color-info-light":"#eef4ff"},Pe={"--color-background-primary":"#18181b","--color-background-secondary":"#27272a","--color-background-tertiary":"#2f2f34","--color-text-primary":"#fafafa","--color-text-secondary":"#a1a1aa","--color-text-tertiary":"#71717a","--color-text-accent":"#818cf8","--nb-color-accent-foreground":"#ffffff","--color-border-primary":"#3f3f46","--color-border-secondary":"#52525b","--color-ring-primary":"#818cf8","--nb-color-danger":"#f87171","--nb-color-success":"#34d399","--nb-color-warning":"#fbbf24","--nb-color-processing":"#a78bfa","--nb-color-processing-light":"#2a2440","--nb-color-info-light":"#1e2a44"},Ee={light:ke,dark:Pe},Ie="synapse-defaults",G="synapse-theme-defaults",W=new Set;function ve(){return typeof document<"u"&&typeof document.getElementById=="function"&&typeof document.createElement=="function"&&typeof document.head?.prepend=="function"}function we(e){if(!ve())return;let o=Object.entries(Ee[e]).map(([a,p])=>` ${a}: ${p};`).join(`
2
2
  `),n=`@layer ${Ie} {
3
3
  :root {
4
4
  ${o}
5
5
  }
6
- }`,s=document.getElementById(G);if(s){s.textContent!==n&&(s.textContent=n);return}let i=document.createElement("style");i.id=G,i.textContent=n,document.head.prepend(i);}function we(e,o){if(typeof document>"u")return;Ce(e);let n={};if(o&&typeof o=="object")for(let[i,a]of Object.entries(o))typeof i=="string"&&typeof a=="string"&&(n[i]=a);let s=document.documentElement.style;if(typeof s.removeProperty=="function")for(let i of W)i in n||s.removeProperty(i);for(let[i,a]of Object.entries(n))s.setProperty(i,a);W=new Set(Object.keys(n));}var F=new Set,Y="";function A(e){return Array.isArray(e)?JSON.stringify(e.map(o=>[o.family,o.src,o.weight,o.style,o.display])):""}function M(e){if(!Array.isArray(e))return;let o=e.filter(Oe);if(!(e.length>0&&o.length===0))return o}function Ae(e){let o=M(e);if(o===void 0||typeof document>"u"||!document.fonts||typeof FontFace>"u")return;let n=A(o);if(n!==Y){Y=n;for(let s of F)try{document.fonts.delete(s);}catch{}F.clear();for(let s of o)try{let i=new FontFace(s.family,s.src,{weight:s.weight,style:s.style,display:s.display&&be.has(s.display)?s.display:"swap"});document.fonts.add(i),F.add(i);}catch{}}}function Oe(e){if(!e||typeof e!="object")return false;let o=e;return typeof o.family=="string"&&typeof o.src=="string"}function V(e,o,n){we(e,o),Ae(n);}function R(e){typeof document<"u"&&document.documentElement.setAttribute("data-theme",e.mode),V(e.mode,e.tokens,e.fontFaces);}function O(e){try{if(e?.matchMedia?.("(prefers-color-scheme: dark)").matches)return "dark"}catch{}return "light"}function h(e,o){return e==="light"||e==="dark"?e:o}var T=class extends Error{constructor(o,n){super(`"${o}" is not supported by the "${n}" host`),this.name="HostUnsupportedError";}},_="synapse-ui-data",Z="ui-lifecycle-iframe-ready",$="ui-lifecycle-iframe-render-data",B="ui-size-change",q="link",Q="prompt",U="openai:set_globals",X="2026-01-26",J="ui/initialize",ee="ui/notifications/initialized",te="ui/notifications/tool-result",ne="ui/notifications/host-context-changed",oe="ui/notifications/size-changed",re="ui/open-link",se="ui/message",ie="ui/resource-teardown",ae="tools/call";function ce(e,o){let n=()=>e.openai,s=n()?.toolOutput??null,i={mode:h(n()?.theme,"light"),tokens:{}},a=new Set,p=new Set,f=false,m=c=>{if(f)return;let l=c.detail?.globals;if(l){if("toolOutput"in l&&l.toolOutput!=null){s=l.toolOutput;for(let u of a)u(s);}if("theme"in l&&l.theme!=null){let u=h(l.theme,i.mode);if(u!==i.mode){i={mode:u,tokens:{}};for(let b of p)b(i);}}}};return {host:"chatgpt",getData:()=>s,onData(c){return a.add(c),()=>a.delete(c)},getTheme:()=>i,onTheme(c){return p.add(c),()=>p.delete(c)},async callTool(c,l){let u=n()?.callTool;if(!u)throw new T("callTool","chatgpt");return await u(c,l??{})},sendPrompt(c){let l=n();(l?.sendFollowUpMessage??l?.sendFollowupMessage)?.({prompt:c});},openLink(c){let l=n()?.openExternal;l?l({href:c}):e.open(c,"_blank","noopener,noreferrer");},resize(){},capabilities(){let c=n();return {pull:typeof c?.callTool=="function",sendPrompt:typeof c?.sendFollowUpMessage=="function"||typeof c?.sendFollowupMessage=="function",openLink:true}},start(){e.addEventListener(U,m,{passive:true}),s=n()?.toolOutput??s;},destroy(){f||(f=true,e.removeEventListener(U,m),a.clear(),p.clear());}}}function S(e,o){if(!e)return null;let s=e.getElementById(o)?.textContent;if(!s)return null;try{return JSON.parse(s)??null}catch{return null}}function L(e){if(e==null||typeof e!="object")return null;let o=e,n=o.renderData,s=n!=null&&typeof n=="object"?n:o;return s.toolOutput!=null?s.toolOutput:s.structuredContent!=null?s.structuredContent:s}function le(e,o){let n=o.dataElementId??_,s=null,i={mode:O(e),tokens:{}},a=new Set,p=false,f=null,m=c=>{if(p)return;let l=h(c.matches?"dark":"light",i.mode);if(l!==i.mode){i={mode:l,tokens:{}};for(let u of a)u(i);}};return {host:"generic",getData:()=>s,onData(){return ()=>{}},getTheme:()=>i,onTheme(c){return a.add(c),()=>a.delete(c)},async callTool(c){throw new T("callTool","generic")},sendPrompt(){},openLink(c){e.open(c,"_blank","noopener,noreferrer");},resize(){},capabilities(){return {pull:false,sendPrompt:false,openLink:true}},start(){s=S(e.document,n);try{f=e.matchMedia?.("(prefers-color-scheme: dark)")??null,f?.addEventListener?.("change",m);}catch{f=null;}},destroy(){p||(p=true,f?.removeEventListener?.("change",m),f=null,a.clear());}}}var _e="synapse/fontFaces";function Se(e){return M(e?.[_e])}function de(e,o){return Se(o)??e}var xe=3e4;function pe(e,o){let n=o.dataElementId??_,s=o.autoResize!==false,i=null,a={mode:O(e),tokens:{}},p=new Set,f=new Set,m=false,c=false,l=1,u=new Map,b=-1,v=null,k=null,H=()=>e.parent??e;function P(t){H().postMessage(t,"*");}function x(t){c||P(t);}function N(t,r){P({jsonrpc:"2.0",method:t,params:r??{}});}function C(t,r){let d=l++;return new Promise((y,g)=>{let I=setTimeout(()=>{u.delete(d),g(new Error(`"${t}" timed out`));},xe);u.set(d,{resolve:y,reject:g,timer:I}),P({jsonrpc:"2.0",id:d,method:t,params:r??{}});})}function z(t){if(t!=null){i=t;for(let r of p)r(t);}}function D(t){if(!t||typeof t!="object")return;let{mode:r,tokens:d,fontFaces:y}=a,g=false;if(t.theme!=null){let w=h(t.theme,r);w!==r&&(r=w,g=true);}let I=t.styles;I?.variables&&typeof I.variables=="object"&&(d={...d,...I.variables},g=true);let K=de(y,t);if(A(K)!==A(y)&&(y=K,g=true),g){a={mode:r,tokens:d,...y?{fontFaces:y}:{}};for(let w of f)w(a);}}function E(t){if(m)return;let r=typeof t=="number"?t:Math.ceil(e.document.body.scrollHeight);r!==b&&(b=r,N(oe,{height:r}),x({type:B,payload:{height:r}}));}function me(t){let r=Number(t.id),d=u.get(r);if(d)if(u.delete(r),clearTimeout(d.timer),t.error!=null){let y=t.error;d.reject(new Error(y.message??"request failed"));}else d.resolve(t.result);}function ye(t,r){if(t===te){let d=r.structuredContent;z(d??L(r));}else t===ne&&D(r);}function ge(t){t.method===ie&&P({jsonrpc:"2.0",id:t.id,result:{}});}function he(t){if(t.type===$||t.type==="renderData"){let{theme:r,...d}=t.payload??{};r!=null&&D({theme:r}),Object.keys(d).length>0&&z(L(d));}}let j=t=>{if(m||t.source&&t.source!==H())return;let r=t.data;if(!(!r||typeof r!="object")){if(r.jsonrpc!=="2.0"){he(r);return}r.id!=null&&("result"in r||"error"in r)?me(r):typeof r.method=="string"&&(r.id!=null?ge(r):ye(r.method,r.params??{}));}};function Te(){k=()=>E(),e.addEventListener("resize",k),typeof e.ResizeObserver<"u"&&(v=new e.ResizeObserver(()=>E()),v.observe(e.document.body));}return {host:"claude",getData:()=>i,onData(t){return p.add(t),()=>p.delete(t)},getTheme:()=>a,onTheme(t){return f.add(t),()=>f.delete(t)},async callTool(t,r){return await C(ae,{name:t,arguments:r??{}})},sendPrompt(t){C(se,{role:"user",content:[{type:"text",text:t}]}).catch(()=>{}),x({type:Q,payload:{prompt:t}});},openLink(t){C(re,{url:t}).catch(()=>{}),x({type:q,payload:{url:t}});},resize(t){E(t);},capabilities(){return {pull:true,sendPrompt:true,openLink:true}},start(){e.addEventListener("message",j),i=S(e.document,n),s&&Te(),P({type:Z}),C(J,{appInfo:{name:o.name??"synapse-ui",version:o.version??"0.0.0"},appCapabilities:{availableDisplayModes:["inline"]},protocolVersion:X}).then(t=>{m||(c=true,D(t?.hostContext),N(ee,{}),b=-1,E());}).catch(()=>{}),E();},destroy(){if(!m){m=true,e.removeEventListener("message",j),k&&e.removeEventListener("resize",k),k=null,v?.disconnect(),v=null;for(let t of u.values())clearTimeout(t.timer),t.reject(new Error("adapter destroyed"));u.clear(),p.clear(),f.clear();}}}}function De(e){if(e.openai!=null)return "chatgpt";try{if(e.parent!=null&&e.parent!==e)return "claude"}catch{return "claude"}return "generic"}function Fe(e,o,n){switch(e){case "chatgpt":return ce(o);case "claude":case "nimblebrain":return pe(o,n);default:return le(o,n)}}function ue(e,o){let n=o.host??De(e);return Fe(n,e,o)}function fe(e={}){let o=e.window??globalThis,n=ue(o,e);R(n.getTheme());let s=n.onTheme(R);n.start();let i=false;return {data:()=>n.getData(),onData:a=>n.onData(a),theme:()=>n.getTheme(),onTheme:a=>n.onTheme(a),callTool:(a,p)=>n.callTool(a,p),sendPrompt:a=>n.sendPrompt(a),openLink:a=>n.openLink(a),resize:a=>n.resize(a),capabilities:()=>n.capabilities(),host:()=>n.host,destroy(){i||(i=true,s(),n.destroy());}}}globalThis.SynapseUI={connect:fe};})();
6
+ }`,s=document.getElementById(G);if(s){s.textContent!==n&&(s.textContent=n);return}let i=document.createElement("style");i.id=G,i.textContent=n,document.head.prepend(i);}function Ae(e,o){if(typeof document>"u")return;we(e);let n={};if(o&&typeof o=="object")for(let[i,a]of Object.entries(o))typeof i=="string"&&typeof a=="string"&&(n[i]=a);let s=document.documentElement.style;if(typeof s.removeProperty=="function")for(let i of W)i in n||s.removeProperty(i);for(let[i,a]of Object.entries(n))s.setProperty(i,a);W=new Set(Object.keys(n));}var F=new Set,Y="";function C(e){return Array.isArray(e)?JSON.stringify(e.map(o=>[o.family,o.src,o.weight,o.style,o.display])):""}function M(e){if(!Array.isArray(e))return;let o=e.filter(Oe);if(!(e.length>0&&o.length===0))return o}function Ce(e){let o=M(e);if(o===void 0||typeof document>"u"||!document.fonts||typeof FontFace>"u")return;let n=C(o);if(n!==Y){Y=n;for(let s of F)try{document.fonts.delete(s);}catch{}F.clear();for(let s of o)try{let i=new FontFace(s.family,s.src,{weight:s.weight,style:s.style,display:s.display&&be.has(s.display)?s.display:"swap"});document.fonts.add(i),F.add(i);}catch{}}}function Oe(e){if(!e||typeof e!="object")return false;let o=e;return typeof o.family=="string"&&typeof o.src=="string"}function V(e,o,n){Ae(e,o),Ce(n);}function R(e){typeof document<"u"&&document.documentElement.setAttribute("data-theme",e.mode),V(e.mode,e.tokens,e.fontFaces);}function O(e){try{if(e?.matchMedia?.("(prefers-color-scheme: dark)").matches)return "dark"}catch{}return "light"}function h(e,o){return e==="light"||e==="dark"?e:o}var T=class extends Error{constructor(o,n){super(`"${o}" is not supported by the "${n}" host`),this.name="HostUnsupportedError";}},_="synapse-ui-data",Z="ui-lifecycle-iframe-ready",$="ui-lifecycle-iframe-render-data",B="ui-size-change",q="link",Q="prompt",U="openai:set_globals",X="2026-01-26",J="ui/initialize",ee="ui/notifications/initialized",te="ui/notifications/tool-result",ne="ui/notifications/host-context-changed",oe="ui/notifications/size-changed",re="ui/open-link",se="ui/message",ie="ui/resource-teardown",ae="tools/call";function ce(e,o){let n=()=>e.openai,s=n()?.toolOutput??null,i={mode:h(n()?.theme,"light"),tokens:{}},a=new Set,p=new Set,f=false,m=c=>{if(f)return;let l=c.detail?.globals;if(l){if("toolOutput"in l&&l.toolOutput!=null){s=l.toolOutput;for(let u of a)u(s);}if("theme"in l&&l.theme!=null){let u=h(l.theme,i.mode);if(u!==i.mode){i={mode:u,tokens:{}};for(let b of p)b(i);}}}};return {host:"chatgpt",getData:()=>s,onData(c){return a.add(c),()=>a.delete(c)},getTheme:()=>i,onTheme(c){return p.add(c),()=>p.delete(c)},async callTool(c,l){let u=n()?.callTool;if(!u)throw new T("callTool","chatgpt");return await u(c,l??{})},sendPrompt(c){let l=n();(l?.sendFollowUpMessage??l?.sendFollowupMessage)?.({prompt:c});},openLink(c){let l=n()?.openExternal;l?l({href:c}):e.open(c,"_blank","noopener,noreferrer");},resize(){},capabilities(){let c=n();return {pull:typeof c?.callTool=="function",sendPrompt:typeof c?.sendFollowUpMessage=="function"||typeof c?.sendFollowupMessage=="function",openLink:true}},start(){e.addEventListener(U,m,{passive:true}),s=n()?.toolOutput??s;},destroy(){f||(f=true,e.removeEventListener(U,m),a.clear(),p.clear());}}}function x(e,o){if(!e)return null;let s=e.getElementById(o)?.textContent;if(!s)return null;try{return JSON.parse(s)??null}catch{return null}}function L(e){if(e==null||typeof e!="object")return null;let o=e,n=o.renderData,s=n!=null&&typeof n=="object"?n:o;return s.toolOutput!=null?s.toolOutput:s.structuredContent!=null?s.structuredContent:s}function le(e,o){let n=o.dataElementId??_,s=null,i={mode:O(e),tokens:{}},a=new Set,p=false,f=null,m=c=>{if(p)return;let l=h(c.matches?"dark":"light",i.mode);if(l!==i.mode){i={mode:l,tokens:{}};for(let u of a)u(i);}};return {host:"generic",getData:()=>s,onData(){return ()=>{}},getTheme:()=>i,onTheme(c){return a.add(c),()=>a.delete(c)},async callTool(c){throw new T("callTool","generic")},sendPrompt(){},openLink(c){e.open(c,"_blank","noopener,noreferrer");},resize(){},capabilities(){return {pull:false,sendPrompt:false,openLink:true}},start(){s=x(e.document,n);try{f=e.matchMedia?.("(prefers-color-scheme: dark)")??null,f?.addEventListener?.("change",m);}catch{f=null;}},destroy(){p||(p=true,f?.removeEventListener?.("change",m),f=null,a.clear());}}}var _e="synapse/fontFaces";function xe(e){return M(e?.[_e])}function de(e,o){return xe(o)??e}var De=3e4;function pe(e,o){let n=o.dataElementId??_,s=o.autoResize!==false,i=null,a={mode:O(e),tokens:{}},p=new Set,f=new Set,m=false,c=false,l=1,u=new Map,b=-1,v=null,k=null,H=()=>e.parent??e;function P(t){H().postMessage(t,"*");}function D(t){c||P(t);}function N(t,r){P({jsonrpc:"2.0",method:t,params:r??{}});}function w(t,r){let d=l++;return new Promise((y,g)=>{let I=setTimeout(()=>{u.delete(d),g(new Error(`"${t}" timed out`));},De);u.set(d,{resolve:y,reject:g,timer:I}),P({jsonrpc:"2.0",id:d,method:t,params:r??{}});})}function z(t){if(t!=null){i=t;for(let r of p)r(t);}}function S(t){if(!t||typeof t!="object")return;let{mode:r,tokens:d,fontFaces:y}=a,g=false;if(t.theme!=null){let A=h(t.theme,r);A!==r&&(r=A,g=true);}let I=t.styles;I?.variables&&typeof I.variables=="object"&&(d={...d,...I.variables},g=true);let K=de(y,t);if(C(K)!==C(y)&&(y=K,g=true),g){a={mode:r,tokens:d,...y?{fontFaces:y}:{}};for(let A of f)A(a);}}function E(t){if(m)return;let r=typeof t=="number"?t:Math.ceil(e.document.body.scrollHeight);r!==b&&(b=r,N(oe,{height:r}),D({type:B,payload:{height:r}}));}function me(t){let r=Number(t.id),d=u.get(r);if(d)if(u.delete(r),clearTimeout(d.timer),t.error!=null){let y=t.error;d.reject(new Error(y.message??"request failed"));}else d.resolve(t.result);}function ye(t,r){if(t===te){let d=r.structuredContent;z(d??L(r));}else t===ne&&S(r);}function ge(t){t.method===ie&&P({jsonrpc:"2.0",id:t.id,result:{}});}function he(t){if(t.type===$||t.type==="renderData"){let{theme:r,...d}=t.payload??{};r!=null&&S({theme:r}),Object.keys(d).length>0&&z(L(d));}}let j=t=>{if(m||t.source&&t.source!==H())return;let r=t.data;if(!(!r||typeof r!="object")){if(r.jsonrpc!=="2.0"){he(r);return}r.id!=null&&("result"in r||"error"in r)?me(r):typeof r.method=="string"&&(r.id!=null?ge(r):ye(r.method,r.params??{}));}};function Te(){k=()=>E(),e.addEventListener("resize",k),typeof e.ResizeObserver<"u"&&(v=new e.ResizeObserver(()=>E()),v.observe(e.document.body));}return {host:"claude",getData:()=>i,onData(t){return p.add(t),()=>p.delete(t)},getTheme:()=>a,onTheme(t){return f.add(t),()=>f.delete(t)},async callTool(t,r){return await w(ae,{name:t,arguments:r??{}})},sendPrompt(t){w(se,{role:"user",content:[{type:"text",text:t}]}).catch(()=>{}),D({type:Q,payload:{prompt:t}});},openLink(t){w(re,{url:t}).catch(()=>{}),D({type:q,payload:{url:t}});},resize(t){E(t);},capabilities(){return {pull:true,sendPrompt:true,openLink:true}},start(){e.addEventListener("message",j),i=x(e.document,n),s&&Te(),P({type:Z}),w(J,{appInfo:{name:o.name??"synapse-ui",version:o.version??"0.0.0"},appCapabilities:{availableDisplayModes:["inline"]},protocolVersion:X}).then(t=>{m||(c=true,S(t?.hostContext),N(ee,{}),b=-1,E());}).catch(()=>{}),E();},destroy(){if(!m){m=true,e.removeEventListener("message",j),k&&e.removeEventListener("resize",k),k=null,v?.disconnect(),v=null;for(let t of u.values())clearTimeout(t.timer),t.reject(new Error("adapter destroyed"));u.clear(),p.clear(),f.clear();}}}}function Se(e){if(e.openai!=null)return "chatgpt";try{if(e.parent!=null&&e.parent!==e)return "claude"}catch{return "claude"}return "generic"}function Fe(e,o,n){switch(e){case "chatgpt":return ce(o);case "claude":case "nimblebrain":return pe(o,n);default:return le(o,n)}}function ue(e,o){let n=o.host??Se(e);return Fe(n,e,o)}function fe(e={}){let o=e.window??globalThis,n=ue(o,e);R(n.getTheme());let s=n.onTheme(R);n.start();let i=false;return {data:()=>n.getData(),onData:a=>n.onData(a),theme:()=>n.getTheme(),onTheme:a=>n.onTheme(a),callTool:(a,p)=>n.callTool(a,p),sendPrompt:a=>n.sendPrompt(a),openLink:a=>n.openLink(a),resize:a=>n.resize(a),capabilities:()=>n.capabilities(),host:()=>n.host,destroy(){i||(i=true,s(),n.destroy());}}}globalThis.SynapseUI={connect:fe};})();
@@ -100,19 +100,6 @@ interface TaskHandle<TOutput = unknown> {
100
100
  onStatus(cb: (task: Task) => void): () => void;
101
101
  }
102
102
 
103
- interface SynapseOptions {
104
- /** App name — must match the bundle name registered with the host */
105
- name: string;
106
- /** Semver version string */
107
- version: string;
108
- /**
109
- * Mark as internal NimbleBrain app. Enables cross-server tool calls.
110
- * External apps MUST NOT set this.
111
- */
112
- internal?: boolean;
113
- /** Key combos to forward from iframe to host. Default: all Ctrl/Cmd combos + Escape. */
114
- forwardKeys?: KeyForwardConfig[];
115
- }
116
103
  /**
117
104
  * One `@font-face` a host asks the app to load.
118
105
  *
@@ -143,9 +130,8 @@ interface FontFaceDescriptor {
143
130
  }
144
131
  /** The CSS `font-display` values. Closed set — anything else is ignored. */
145
132
  type FontDisplayValue = "auto" | "block" | "swap" | "fallback" | "optional";
146
- interface SynapseTheme {
133
+ interface Theme {
147
134
  mode: "light" | "dark";
148
- primaryColor: string;
149
135
  tokens: Record<string, string>;
150
136
  /**
151
137
  * Font faces the host wants loaded into the app document. Optional — a host
@@ -248,149 +234,13 @@ interface RequestFileOptions {
248
234
  /** Allow multiple file selection. Default: false */
249
235
  multiple?: boolean;
250
236
  }
251
- interface Synapse {
252
- readonly ready: Promise<void>;
253
- readonly isNimbleBrainHost: boolean;
254
- callTool<TInput = Record<string, unknown>, TOutput = unknown>(name: string, args?: TInput): Promise<ToolCallResult<TOutput>>;
255
- /**
256
- * Task-augmented variant of `callTool` per MCP 2025-11-25. Sends
257
- * `tools/call` with a `task` param; the receiver returns a
258
- * `CreateTaskResult` promptly and the actual `CallToolResult` lands
259
- * via `tasks/result`. Returns a `TaskHandle` that exposes
260
- * `result()`/`refresh()`/`cancel()`/`onStatus()`.
261
- *
262
- * Throws if the host did not advertise `tasks.requests.tools.call` in
263
- * its init-response capabilities — requestors MUST NOT task-augment
264
- * without matching receiver capability.
265
- */
266
- callToolAsTask<TInput = Record<string, unknown>, TOutput = unknown>(name: string, args?: TInput, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>>;
267
- /**
268
- * Read an MCP resource from the originating server via the host bridge
269
- * (ext-apps `resources/read`).
270
- *
271
- * Use this to resolve `resource_link` content blocks returned by tools, or
272
- * to fetch any known resource URI exposed by the MCP server. The host
273
- * proxies the request to the server and forwards the result unchanged.
274
- *
275
- * @param uri The resource URI (e.g. `"videos://bunny-1mb"`).
276
- * @returns The server's `ReadResourceResult` — `contents` is an array of
277
- * blocks, each with a `uri`, optional `mimeType`, and either `text` or
278
- * `blob` (base64).
279
- */
280
- readResource(uri: string): Promise<ReadResourceResult>;
281
- onDataChanged(callback: (event: DataChangedEvent) => void): () => void;
282
- /**
283
- * Subscribe to agent actions — typed, declarative commands from the server.
284
- *
285
- * Actions are deterministic side effects of tool execution. The server/tool
286
- * decides what action to emit; the UI decides how to handle it.
287
- *
288
- * The callback receives an AgentAction with a `type` discriminator and typed
289
- * `payload`. Apps should handle known types and ignore unknown ones.
290
- */
291
- onAction(callback: (action: AgentAction) => void): () => void;
292
- /**
293
- * Read the current ext-apps host context as last received from the host.
294
- *
295
- * Spec-standardized fields (`theme`, `styles`, `displayMode`, `toolInfo`)
296
- * are typed; the open `[key: string]: unknown` allows hosts to publish
297
- * extensions (e.g. NimbleBrain populates `workspace`). Apps reading
298
- * host-specific fields should treat them as optional and tolerate
299
- * missing values when running on other hosts.
300
- *
301
- * Returns the empty object before the `ui/initialize` handshake completes.
302
- */
303
- getHostContext(): McpUiHostContext;
304
- /**
305
- * Subscribe to host-context updates. Fires once per
306
- * `ui/notifications/host-context-changed` notification (which carries a
307
- * full snapshot, not a delta) and once on handshake completion.
308
- *
309
- * `getTheme`/`onThemeChanged` are typed selectors over this same state —
310
- * prefer them when only theming matters, since they filter no-op fires.
311
- */
312
- onHostContextChanged(callback: (ctx: McpUiHostContext) => void): () => void;
313
- getTheme(): SynapseTheme;
314
- onThemeChanged(callback: (theme: SynapseTheme) => void): () => void;
315
- /** NimbleBrain-only: trigger a host-side action. No-op in other hosts. */
316
- action(action: string, params?: Record<string, unknown>): void;
317
- /**
318
- * Send a user message into the agent conversation (ext-apps `ui/message`).
319
- *
320
- * @param context NimbleBrain-specific metadata, included as `_meta.context`
321
- * on the content block. Ignored by non-NimbleBrain hosts.
322
- */
323
- chat(message: string, context?: {
324
- action?: string;
325
- entity?: string;
326
- }): void;
327
- /**
328
- * Push the app's current visible state to the agent (ext-apps `ui/update-model-context`).
329
- *
330
- * The `summary` string is what the LLM reads as a text content block.
331
- * The `state` object is included as `structuredContent` for tools that need IDs/values.
332
- * Debounced at 250ms. Each call overwrites the previous context.
333
- */
334
- setVisibleState(state: Record<string, unknown>, summary?: string): void;
335
- downloadFile(filename: string, content: string | Blob, mimeType?: string): void;
336
- openLink(url: string): void;
337
- /**
338
- * Request a file from the user via the host's native file picker.
339
- * NimbleBrain-only: throws in non-NimbleBrain hosts.
340
- * Returns null if the user cancels.
341
- */
342
- pickFile(options?: RequestFileOptions): Promise<FileResult | null>;
343
- /**
344
- * Pick multiple files from the user.
345
- * NimbleBrain-only: throws in non-NimbleBrain hosts.
346
- * Returns empty array if the user cancels.
347
- */
348
- pickFiles(options?: RequestFileOptions): Promise<FileResult[]>;
349
- /** @internal — used by createStore for synapse/state-loaded */
350
- _onMessage(method: string, callback: (params: Record<string, unknown> | undefined) => void): () => void;
351
- /** @internal — used by createStore for synapse/persist-state */
352
- _request(method: string, params?: Record<string, unknown>): Promise<unknown>;
353
- /**
354
- * @internal — host's declared `tasks` capability from the `ui/initialize`
355
- * response, or `undefined` if absent. Read by the task-augmented tool call
356
- * path (future `callToolAsTask`) to decide whether task augmentation is
357
- * negotiated. `null` before the handshake completes.
358
- *
359
- * Requestors MUST NOT task-augment a tool call unless this is defined and
360
- * carries `requests.tools.call` per MCP 2025-11-25.
361
- */
362
- readonly _hostTasksCapability: TasksCapability | undefined | null;
363
- /** True after destroy() has been called. */
364
- readonly destroyed: boolean;
365
- destroy(): void;
366
- }
367
- interface VisibleState {
237
+ /** What `useModelContext`'s declarative factory returns. */
238
+ interface ModelContext {
239
+ /** Structured state the agent's tools can read ids and values out of. */
368
240
  state: Record<string, unknown>;
241
+ /** The one line the model actually reads. */
369
242
  summary?: string;
370
243
  }
371
- interface StateAcknowledgement {
372
- truncated: boolean;
373
- }
374
- type ActionReducer<TState, TPayload = unknown> = (state: TState, payload: TPayload) => TState;
375
- interface StoreConfig<TState> {
376
- initialState: TState;
377
- actions: Record<string, ActionReducer<TState, any>>;
378
- persist?: boolean;
379
- visibleToAgent?: boolean;
380
- summarize?: (state: TState) => string;
381
- version?: number;
382
- migrations?: Array<(oldState: any) => any>;
383
- }
384
- type StoreDispatch<TActions extends Record<string, ActionReducer<any, any>>> = {
385
- [K in keyof TActions]: Parameters<TActions[K]>[1] extends undefined ? () => void : (payload: Parameters<TActions[K]>[1]) => void;
386
- };
387
- interface Store<TState, TActions extends Record<string, ActionReducer<TState, any>> = Record<string, ActionReducer<TState, any>>> {
388
- getState(): TState;
389
- subscribe(callback: (state: TState) => void): () => void;
390
- dispatch: StoreDispatch<TActions>;
391
- hydrate(state: TState): void;
392
- destroy(): void;
393
- }
394
244
  interface KeyForwardConfig {
395
245
  key: string;
396
246
  ctrl?: boolean;
@@ -410,19 +260,35 @@ interface HostInfo {
410
260
  protocolVersion: string;
411
261
  }
412
262
  interface ConnectOptions {
263
+ /** App name — must match the bundle name registered with the host. */
413
264
  name: string;
265
+ /** Semver version string. */
414
266
  version: string;
267
+ /** Track the document height and re-send `size-changed` as it moves. */
415
268
  autoResize?: boolean;
269
+ /**
270
+ * Mark as an internal NimbleBrain app. Enables cross-server tool calls:
271
+ * `callTool` carries a `server` param so the host can route the call to a
272
+ * sibling server. External apps MUST NOT set this.
273
+ */
274
+ internal?: boolean;
275
+ /**
276
+ * Forward keyboard shortcuts from this iframe up to the host, so the host's
277
+ * own shortcuts still fire while focus is inside the app.
278
+ *
279
+ * `true` forwards the default set (Escape plus every Ctrl/Cmd combo except
280
+ * the clipboard keys the browser must handle itself); an array forwards
281
+ * exactly the listed combos. Absent means no forwarding.
282
+ *
283
+ * Only a NimbleBrain host consumes `synapse/keydown`, so forwarding stays
284
+ * off everywhere else — a `preventDefault` on a host that does nothing with
285
+ * the key would swallow it for no one's benefit.
286
+ */
287
+ forwardKeys?: boolean | KeyForwardConfig[];
416
288
  /** Pre-register event handlers before the handshake completes.
417
289
  * These are wired before `initialized` is sent, so no messages are lost. */
418
290
  on?: Record<string, (data: any) => void>;
419
291
  }
420
- interface Theme {
421
- mode: "light" | "dark";
422
- tokens: Record<string, string>;
423
- /** Font faces the host wants loaded. See {@link FontFaceDescriptor}. */
424
- fontFaces?: FontFaceDescriptor[];
425
- }
426
292
  interface Dimensions {
427
293
  width?: number;
428
294
  height?: number;
@@ -434,8 +300,27 @@ interface ToolResultData {
434
300
  structuredContent: unknown;
435
301
  raw: Record<string, unknown>;
436
302
  }
437
- /** Known short event names for App.on() */
438
- type AppEventName = "tool-result" | "tool-input" | "tool-input-partial" | "tool-cancelled" | "theme-changed" | "teardown";
303
+ /** Per-call overrides for {@link App.callTool}. */
304
+ interface CallToolOptions {
305
+ /**
306
+ * Route the call to a sibling MCP server rather than the app's own.
307
+ * Internal apps only — the host rejects it otherwise. Defaults to this
308
+ * app's name when `connect({ internal: true })` was used, which is what
309
+ * makes a plain `callTool` work for an internal app.
310
+ */
311
+ server?: string;
312
+ }
313
+ /** Known short event names for {@link App.on}. */
314
+ type AppEventName = "tool-result" | "tool-input" | "tool-input-partial" | "tool-cancelled" | "theme-changed" | "host-context-changed" | "data-changed" | "action" | "teardown";
315
+ /**
316
+ * A connected app — what `connect()` resolves to, and the only runtime object
317
+ * this SDK hands out.
318
+ *
319
+ * Deliberately small: it carries the ext-apps spec surface plus the state the
320
+ * handshake established. NimbleBrain's own extensions (the file picker,
321
+ * `action`, `downloadFile`) and the MCP tasks utility are composable functions
322
+ * over this object rather than more methods on it.
323
+ */
439
324
  interface App {
440
325
  readonly theme: Theme;
441
326
  readonly hostInfo: {
@@ -446,21 +331,57 @@ interface App {
446
331
  tool: Record<string, unknown>;
447
332
  } | null;
448
333
  readonly containerDimensions: Dimensions | null;
334
+ /**
335
+ * The current host context: the handshake's, with every
336
+ * `host-context-changed` delta merged into it. Spec fields (`theme`,
337
+ * `styles`, `displayMode`, `toolInfo`) are typed; the open index signature
338
+ * carries host extensions — NimbleBrain publishes `workspace` here. Read
339
+ * host-specific fields as optional; another host will not send them.
340
+ */
341
+ readonly hostContext: McpUiHostContext;
342
+ /** True when the host identified itself as NimbleBrain in the handshake. */
343
+ readonly isNimbleBrainHost: boolean;
344
+ /** True after `destroy()` has been called. */
345
+ readonly destroyed: boolean;
346
+ /**
347
+ * Whether the host negotiated the MCP tasks utility for `tools/call`.
348
+ *
349
+ * `callToolAsTask` throws when this is false — per MCP 2025-11-25 a
350
+ * requestor MUST NOT task-augment a call the receiver did not advertise. Read
351
+ * it to decide whether to offer a long-running action at all, rather than to
352
+ * discover the answer from an exception.
353
+ */
354
+ readonly supportsTasks: boolean;
449
355
  on(event: "tool-input", handler: (args: Record<string, unknown>) => void): () => void;
450
356
  on(event: "tool-result", handler: (data: ToolResultData) => void): () => void;
451
357
  on(event: "theme-changed", handler: (theme: Theme) => void): () => void;
358
+ /** Fires with the merged snapshot — the same value as `hostContext`. For the
359
+ * notification exactly as sent, subscribe to the wire method instead:
360
+ * `on("ui/notifications/host-context-changed", …)`. */
361
+ on(event: "host-context-changed", handler: (ctx: McpUiHostContext) => void): () => void;
362
+ on(event: "data-changed", handler: (event: DataChangedEvent) => void): () => void;
363
+ on(event: "action", handler: (action: AgentAction) => void): () => void;
452
364
  on(event: "teardown", handler: () => void): () => void;
453
- on(event: string, handler: (params: unknown) => void): () => void;
365
+ on(event: string, handler: (params: any) => void): () => void;
454
366
  resize(width?: number, height?: number): void;
455
367
  openLink(url: string): void;
368
+ /**
369
+ * Push the app's visible state to the agent (ext-apps
370
+ * `ui/update-model-context`). `summary` is what the model reads as text;
371
+ * `state` rides along as `structuredContent` for tools that need the ids.
372
+ *
373
+ * Sends immediately. Callers that push on every keystroke or selection
374
+ * change want `useModelContext`, which debounces.
375
+ */
456
376
  updateModelContext(state: Record<string, unknown>, summary?: string): void;
457
- callTool(name: string, args?: Record<string, unknown>): Promise<ToolCallResult>;
377
+ callTool<TOutput = unknown>(name: string, args?: Record<string, unknown>, options?: CallToolOptions): Promise<ToolCallResult<TOutput>>;
458
378
  /**
459
379
  * Read an MCP resource from the originating server via the host bridge
460
380
  * (ext-apps `resources/read`). Named to mirror the ext-apps spec's
461
381
  * `App.readServerResource`.
462
382
  */
463
383
  readServerResource(params: ReadResourceRequest["params"]): Promise<ReadResourceResult>;
384
+ /** Send a user message into the agent conversation (ext-apps `ui/message`). */
464
385
  sendMessage(text: string, context?: {
465
386
  action?: string;
466
387
  entity?: string;
@@ -468,4 +389,4 @@ interface App {
468
389
  destroy(): void;
469
390
  }
470
391
 
471
- export type { App as A, BuiltinActionType as B, ConnectOptions as C, DataChangedEvent as D, FontFaceDescriptor as F, HostInfo as H, KeyForwardConfig as K, NavigatePayload as N, RequestFileOptions as R, SynapseOptions as S, ToolDefinition as T, VisibleState as V, Synapse as a, ActionReducer as b, StoreConfig as c, Store as d, AgentAction as e, AppEventName as f, CallToolAsTaskOptions as g, Dimensions as h, FileResult as i, FontDisplayValue as j, NotifyPayload as k, StateAcknowledgement as l, StoreDispatch as m, SynapseTheme as n, TaskHandle as o, TasksCapability as p, Theme as q, ToolCallResult as r, ToolResultData as s };
392
+ export type { App as A, BuiltinActionType as B, ConnectOptions as C, DataChangedEvent as D, FileResult as F, HostInfo as H, KeyForwardConfig as K, ModelContext as M, NavigatePayload as N, RequestFileOptions as R, TaskHandle as T, CallToolAsTaskOptions as a, ToolCallResult as b, CallToolOptions as c, Theme as d, ToolResultData as e, ToolDefinition as f, FontFaceDescriptor as g, AgentAction as h, AppEventName as i, Dimensions as j, FontDisplayValue as k, NotifyPayload as l, TasksCapability as m };