@waniwani/sdk 0.4.0 → 0.4.3

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.
@@ -1,3 +1,3 @@
1
1
  "use client";
2
2
  import{App as g,PostMessageTransport as m}from"@modelcontextprotocol/ext-apps";var r=class{app;toolResultCallback=null;toolResponseMetadataChangeCallback=null;themeChangeCallback=null;displayModeChangeCallback=null;hostContext;latestToolResult=null;resizeCleanup=null;constructor(){this.app=new g({name:"WaniWani Widget",version:"1.0.0"},{},{autoResize:!1}),this.app.ontoolresult=e=>{let t=e,o=typeof t._meta=="object"&&t._meta!==null?t._meta:null,s=typeof t.meta=="object"&&t.meta!==null?t.meta:null,l=o??s??void 0,n={content:e.content,structuredContent:e.structuredContent,_meta:l,isError:typeof t.isError=="boolean"?t.isError:void 0};this.latestToolResult=n,this.toolResultCallback?.(n),this.toolResponseMetadataChangeCallback?.(n._meta??null)},this.app.onhostcontextchanged=e=>{this.hostContext={...this.hostContext,...e},e.theme&&this.themeChangeCallback?.(e.theme),e.displayMode&&this.displayModeChangeCallback?.(e.displayMode)}}async connect(){await this.app.connect(new m(window.parent,window.parent)),this.hostContext=this.app.getHostContext(),this.resizeCleanup=this.setupAutoResize()}async close(){this.resizeCleanup?.(),this.resizeCleanup=null,await this.app.close()}setupAutoResize(){let e=!1,t=0,o=0,s=()=>{e||(e=!0,requestAnimationFrame(()=>{e=!1;let n=document.documentElement,d=n.style.width;n.style.width="fit-content";let u=n.getBoundingClientRect();n.style.width=d;let h=window.innerWidth-n.clientWidth,a=Math.ceil(u.width+h),c=n.style.height,p=n.style.minHeight;n.style.height="0",n.style.minHeight="0";let i=n.scrollHeight;n.style.height=c,n.style.minHeight=p,(a!==t||i!==o)&&(t=a,o=i,this.app.sendSizeChanged({width:a,height:i}))}))};s();let l=new ResizeObserver(s);return l.observe(document.documentElement),l.observe(document.body),()=>l.disconnect()}getToolOutput(){return this.latestToolResult?.structuredContent?this.latestToolResult.structuredContent:null}onToolResult(e){return this.toolResultCallback=e,()=>{this.toolResultCallback=null}}async callTool(e,t){let o=await this.app.callServerTool({name:e,arguments:t});return{content:o.content,structuredContent:o.structuredContent,_meta:o._meta,isError:typeof o.isError=="boolean"?o.isError:void 0}}openExternal(e){this.app.sendOpenLink({url:e}).catch(t=>{console.error("Failed to open link:",t)})}sendFollowUp(e){this.app.sendMessage({role:"user",content:[{type:"text",text:e}]}).catch(t=>{console.error("Failed to send follow-up message:",t)})}updateModelContext(e){return this.app.updateModelContext({...e.content?{content:e.content}:{},...e.structuredContent?{structuredContent:e.structuredContent}:{}}).then(()=>{})}getTheme(){return this.hostContext?.theme??"light"}onThemeChange(e){return this.themeChangeCallback=e,()=>{this.themeChangeCallback=null}}getLocale(){return this.hostContext?.locale??"en"}getDisplayMode(){return this.hostContext?.displayMode??"inline"}async requestDisplayMode(e){return(await this.app.requestDisplayMode({mode:e})).mode}onDisplayModeChange(e){return this.displayModeChangeCallback=e,()=>{this.displayModeChangeCallback=null}}getSafeArea(){return null}onSafeAreaChange(){return()=>{}}getMaxHeight(){return null}onMaxHeightChange(){return()=>{}}getToolResponseMetadata(){return this.latestToolResult?._meta??null}onToolResponseMetadataChange(e){return this.toolResponseMetadataChangeCallback=e,()=>{this.toolResponseMetadataChangeCallback=null}}getWidgetState(){return null}onWidgetStateChange(){return()=>{}}};export{r as MCPAppsWidgetClient};
3
- //# sourceMappingURL=mcp-apps-client-AXOLX2YD.js.map
3
+ //# sourceMappingURL=mcp-apps-client-73TJHVUE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/react/widgets/mcp-apps-client.ts"],"sourcesContent":["import type { McpUiHostContext } from \"@modelcontextprotocol/ext-apps\";\nimport { App, PostMessageTransport } from \"@modelcontextprotocol/ext-apps\";\nimport type { ModelContextUpdate } from \"../../../shared/model-context\";\nimport type {\n\tDisplayMode,\n\tSafeArea,\n\tTheme,\n\tUnknownObject,\n} from \"../hooks/@types\";\nimport type {\n\tToolCallResult,\n\tToolResult,\n\tUnifiedWidgetClient,\n} from \"./widget-client\";\n\n/**\n * MCP Apps widget client implementation.\n * Uses the @modelcontextprotocol/ext-apps App class for communication.\n */\nexport class MCPAppsWidgetClient implements UnifiedWidgetClient {\n\tprivate app: App;\n\tprivate toolResultCallback: ((result: ToolResult) => void) | null = null;\n\tprivate toolResponseMetadataChangeCallback:\n\t\t| ((metadata: UnknownObject | null) => void)\n\t\t| null = null;\n\tprivate themeChangeCallback: ((theme: Theme) => void) | null = null;\n\tprivate displayModeChangeCallback: ((mode: DisplayMode) => void) | null =\n\t\tnull;\n\tprivate hostContext: McpUiHostContext | undefined;\n\tprivate latestToolResult: ToolResult | null = null;\n\tprivate resizeCleanup: (() => void) | null = null;\n\n\tconstructor() {\n\t\tthis.app = new App(\n\t\t\t{ name: \"WaniWani Widget\", version: \"1.0.0\" },\n\t\t\t{}, // capabilities\n\t\t\t{ autoResize: false },\n\t\t);\n\n\t\t// Set up notification handlers\n\t\tthis.app.ontoolresult = (params) => {\n\t\t\tconst rawParams = params as Record<string, unknown>;\n\t\t\tconst underscoreMeta =\n\t\t\t\ttypeof rawParams._meta === \"object\" && rawParams._meta !== null\n\t\t\t\t\t? (rawParams._meta as Record<string, unknown>)\n\t\t\t\t\t: null;\n\t\t\tconst meta =\n\t\t\t\ttypeof rawParams.meta === \"object\" && rawParams.meta !== null\n\t\t\t\t\t? (rawParams.meta as Record<string, unknown>)\n\t\t\t\t\t: null;\n\t\t\tconst resolvedMeta = underscoreMeta ?? meta ?? undefined;\n\n\t\t\tconst result: ToolResult = {\n\t\t\t\tcontent: params.content,\n\t\t\t\tstructuredContent: params.structuredContent as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t\t_meta: resolvedMeta,\n\t\t\t\tisError:\n\t\t\t\t\ttypeof rawParams.isError === \"boolean\"\n\t\t\t\t\t\t? rawParams.isError\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\t\tthis.latestToolResult = result;\n\t\t\tthis.toolResultCallback?.(result);\n\t\t\tthis.toolResponseMetadataChangeCallback?.(result._meta ?? null);\n\t\t};\n\n\t\tthis.app.onhostcontextchanged = (params) => {\n\t\t\tthis.hostContext = { ...this.hostContext, ...params };\n\t\t\tif (params.theme) {\n\t\t\t\tthis.themeChangeCallback?.(params.theme as Theme);\n\t\t\t}\n\t\t\tif (params.displayMode) {\n\t\t\t\tthis.displayModeChangeCallback?.(params.displayMode as DisplayMode);\n\t\t\t}\n\t\t};\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tawait this.app.connect(\n\t\t\tnew PostMessageTransport(window.parent, window.parent),\n\t\t);\n\t\tthis.hostContext = this.app.getHostContext();\n\t\tthis.resizeCleanup = this.setupAutoResize();\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.resizeCleanup?.();\n\t\tthis.resizeCleanup = null;\n\t\tawait this.app.close();\n\t}\n\n\t/**\n\t * Custom auto-resize that uses scrollHeight with a collapsed root element.\n\t * The library's built-in autoResize uses fit-content + getBoundingClientRect\n\t * which can fail to detect height changes when content grows.\n\t */\n\tprivate setupAutoResize(): () => void {\n\t\tlet rafPending = false;\n\t\tlet lastWidth = 0;\n\t\tlet lastHeight = 0;\n\n\t\tconst measure = () => {\n\t\t\tif (rafPending) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\trafPending = true;\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\trafPending = false;\n\t\t\t\tconst el = document.documentElement;\n\n\t\t\t\t// --- Width: use fit-content (same as library) ---\n\t\t\t\tconst savedWidth = el.style.width;\n\t\t\t\tel.style.width = \"fit-content\";\n\t\t\t\tconst fitRect = el.getBoundingClientRect();\n\t\t\t\tel.style.width = savedWidth;\n\t\t\t\tconst scrollbarGap = window.innerWidth - el.clientWidth;\n\t\t\t\tconst width = Math.ceil(fitRect.width + scrollbarGap);\n\n\t\t\t\t// --- Height: collapse root and read scrollHeight ---\n\t\t\t\t// fit-content on <html> can under-report when children use\n\t\t\t\t// percentage heights or viewport units. Collapsing to 0 and\n\t\t\t\t// reading scrollHeight gives the true content height.\n\t\t\t\tconst savedHeight = el.style.height;\n\t\t\t\tconst savedMinHeight = el.style.minHeight;\n\t\t\t\tel.style.height = \"0\";\n\t\t\t\tel.style.minHeight = \"0\";\n\t\t\t\tconst height = el.scrollHeight;\n\t\t\t\tel.style.height = savedHeight;\n\t\t\t\tel.style.minHeight = savedMinHeight;\n\n\t\t\t\tif (width !== lastWidth || height !== lastHeight) {\n\t\t\t\t\tlastWidth = width;\n\t\t\t\t\tlastHeight = height;\n\t\t\t\t\tthis.app.sendSizeChanged({ width, height });\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\tmeasure();\n\t\tconst observer = new ResizeObserver(measure);\n\t\tobserver.observe(document.documentElement);\n\t\tobserver.observe(document.body);\n\t\treturn () => observer.disconnect();\n\t}\n\n\tgetToolOutput<T = Record<string, unknown>>(): T | null {\n\t\t// In MCP Apps, tool output comes through ontoolresult notification\n\t\t// Return the latest cached result\n\t\tif (this.latestToolResult?.structuredContent) {\n\t\t\treturn this.latestToolResult.structuredContent as T;\n\t\t}\n\t\treturn null;\n\t}\n\n\tonToolResult(callback: (result: ToolResult) => void): () => void {\n\t\tthis.toolResultCallback = callback;\n\t\treturn () => {\n\t\t\tthis.toolResultCallback = null;\n\t\t};\n\t}\n\n\tasync callTool(\n\t\tname: string,\n\t\targs: Record<string, unknown>,\n\t): Promise<ToolCallResult> {\n\t\tconst result = await this.app.callServerTool({\n\t\t\tname,\n\t\t\targuments: args,\n\t\t});\n\t\treturn {\n\t\t\tcontent: result.content,\n\t\t\tstructuredContent: result.structuredContent as\n\t\t\t\t| Record<string, unknown>\n\t\t\t\t| undefined,\n\t\t\t_meta: result._meta as Record<string, unknown> | undefined,\n\t\t\tisError: typeof result.isError === \"boolean\" ? result.isError : undefined,\n\t\t};\n\t}\n\n\topenExternal(url: string): void {\n\t\tthis.app.sendOpenLink({ url }).catch((err: unknown) => {\n\t\t\tconsole.error(\"Failed to open link:\", err);\n\t\t});\n\t}\n\n\tsendFollowUp(prompt: string): void {\n\t\tthis.app\n\t\t\t.sendMessage({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: [{ type: \"text\", text: prompt }],\n\t\t\t})\n\t\t\t.catch((err: unknown) => {\n\t\t\t\tconsole.error(\"Failed to send follow-up message:\", err);\n\t\t\t});\n\t}\n\n\tupdateModelContext(context: ModelContextUpdate): Promise<void> {\n\t\treturn this.app\n\t\t\t.updateModelContext({\n\t\t\t\t...(context.content ? { content: context.content } : {}),\n\t\t\t\t...(context.structuredContent\n\t\t\t\t\t? { structuredContent: context.structuredContent }\n\t\t\t\t\t: {}),\n\t\t\t})\n\t\t\t.then(() => undefined);\n\t}\n\n\tgetTheme(): Theme {\n\t\treturn (this.hostContext?.theme as Theme) ?? \"light\";\n\t}\n\n\tonThemeChange(callback: (theme: Theme) => void): () => void {\n\t\tthis.themeChangeCallback = callback;\n\t\treturn () => {\n\t\t\tthis.themeChangeCallback = null;\n\t\t};\n\t}\n\n\tgetLocale(): string {\n\t\treturn (this.hostContext?.locale as string | undefined) ?? \"en\";\n\t}\n\n\tgetDisplayMode(): DisplayMode {\n\t\treturn (this.hostContext?.displayMode as DisplayMode) ?? \"inline\";\n\t}\n\n\tasync requestDisplayMode(mode: DisplayMode): Promise<DisplayMode> {\n\t\tconst result = await this.app.requestDisplayMode({ mode });\n\t\treturn result.mode as DisplayMode;\n\t}\n\n\tonDisplayModeChange(callback: (mode: DisplayMode) => void): () => void {\n\t\tthis.displayModeChangeCallback = callback;\n\t\treturn () => {\n\t\t\tthis.displayModeChangeCallback = null;\n\t\t};\n\t}\n\n\t// OPENAI specific methods\n\tgetSafeArea(): SafeArea | null {\n\t\treturn null;\n\t}\n\n\t// MCP Apps specific methods\n\tonSafeAreaChange(): () => void {\n\t\treturn () => {};\n\t}\n\n\t// OPENAI specific methods\n\tgetMaxHeight(): number | null {\n\t\treturn null;\n\t}\n\n\t// MCP Apps specific methods\n\tonMaxHeightChange(): () => void {\n\t\treturn () => {};\n\t}\n\n\t// MCP Apps specific methods\n\tgetToolResponseMetadata(): UnknownObject | null {\n\t\treturn this.latestToolResult?._meta ?? null;\n\t}\n\n\t// MCP Apps specific methods\n\tonToolResponseMetadataChange(\n\t\tcallback: (metadata: UnknownObject | null) => void,\n\t): () => void {\n\t\tthis.toolResponseMetadataChangeCallback = callback;\n\t\treturn () => {\n\t\t\tthis.toolResponseMetadataChangeCallback = null;\n\t\t};\n\t}\n\n\t// MCP Apps specific methods\n\tgetWidgetState(): UnknownObject | null {\n\t\treturn null;\n\t}\n\n\t// MCP Apps specific methods\n\tonWidgetStateChange(): () => void {\n\t\treturn () => {};\n\t}\n}\n"],"mappings":"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","names":["App","PostMessageTransport","MCPAppsWidgetClient","params","rawParams","underscoreMeta","meta","resolvedMeta","result","rafPending","lastWidth","lastHeight","measure","el","savedWidth","fitRect","scrollbarGap","width","savedHeight","savedMinHeight","height","observer","callback","name","args","url","err","prompt","context","mode"]}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import{a as l,d as a,e as d}from"./chunk-OMMDVQYW.js";var s=class{pendingModelContext=null;getGlobal(e,n){return typeof window>"u"?n:window.openai?.[e]??n}onGlobalChange(e,n,o){if(typeof window>"u")return()=>{};let i=r=>{let t=r.detail.globals[e];t!==void 0&&n(o?o(t):t)};return window.addEventListener(l,i,{passive:!0}),()=>window.removeEventListener(l,i)}async connect(){if(typeof window>"u"||!("openai"in window))throw new Error("OpenAI global not found. Are you running in ChatGPT?")}async close(){}getToolOutput(){return this.getGlobal("toolOutput",null)}onToolResult(e){return this.onGlobalChange("toolOutput",e,n=>({content:[],structuredContent:n??{}}))}async callTool(e,n){if(typeof window>"u"||!window.openai?.callTool)throw new Error("OpenAI callTool not available");return{content:[{type:"text",text:(await window.openai.callTool(e,n)).result}]}}openExternal(e){typeof window<"u"&&window.openai?.openExternal&&window.openai.openExternal({href:e})}sendFollowUp(e){if(typeof window<"u"&&window.openai?.sendFollowUpMessage){let n=d(this.pendingModelContext);this.pendingModelContext=null;let o=n?`${e}
2
+ import{a as l,d as a,e as d}from"./chunk-5OQXAEHG.js";var s=class{pendingModelContext=null;getGlobal(e,n){return typeof window>"u"?n:window.openai?.[e]??n}onGlobalChange(e,n,o){if(typeof window>"u")return()=>{};let i=r=>{let t=r.detail.globals[e];t!==void 0&&n(o?o(t):t)};return window.addEventListener(l,i,{passive:!0}),()=>window.removeEventListener(l,i)}async connect(){if(typeof window>"u"||!("openai"in window))throw new Error("OpenAI global not found. Are you running in ChatGPT?")}async close(){}getToolOutput(){return this.getGlobal("toolOutput",null)}onToolResult(e){return this.onGlobalChange("toolOutput",e,n=>({content:[],structuredContent:n??{}}))}async callTool(e,n){if(typeof window>"u"||!window.openai?.callTool)throw new Error("OpenAI callTool not available");return{content:[{type:"text",text:(await window.openai.callTool(e,n)).result}]}}openExternal(e){typeof window<"u"&&window.openai?.openExternal&&window.openai.openExternal({href:e})}sendFollowUp(e){if(typeof window<"u"&&window.openai?.sendFollowUpMessage){let n=d(this.pendingModelContext);this.pendingModelContext=null;let o=n?`${e}
3
3
 
4
4
  ${n}`:e;window.openai.sendFollowUpMessage({prompt:o})}}updateModelContext(e){this.pendingModelContext=a(this.pendingModelContext,e)}getTheme(){return this.getGlobal("theme","light")}onThemeChange(e){return this.onGlobalChange("theme",e)}getLocale(){return this.getGlobal("locale","en")}getDisplayMode(){return this.getGlobal("displayMode","inline")}async requestDisplayMode(e){return typeof window>"u"||!window.openai?.requestDisplayMode?"inline":(await window.openai.requestDisplayMode({mode:e})).mode}onDisplayModeChange(e){return this.onGlobalChange("displayMode",e)}getSafeArea(){return this.getGlobal("safeArea",null)}onSafeAreaChange(e){return this.onGlobalChange("safeArea",e,n=>n??null)}getMaxHeight(){return this.getGlobal("maxHeight",null)}onMaxHeightChange(e){return this.onGlobalChange("maxHeight",e,n=>n??null)}getToolResponseMetadata(){return this.getGlobal("toolResponseMetadata",null)}onToolResponseMetadataChange(e){return this.onGlobalChange("toolResponseMetadata",e,n=>n??null)}getWidgetState(){return this.getGlobal("widgetState",null)}onWidgetStateChange(e){return this.onGlobalChange("widgetState",e,n=>n??null)}};export{s as OpenAIWidgetClient};
5
- //# sourceMappingURL=openai-client-IAONK3N3.js.map
5
+ //# sourceMappingURL=openai-client-Q6DRRFMS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/react/widgets/openai-client.ts"],"sourcesContent":["import {\n\tformatModelContextForPrompt,\n\ttype ModelContextUpdate,\n\tmergeModelContext,\n} from \"../../../shared/model-context\";\nimport type {\n\tDisplayMode,\n\tSafeArea,\n\tTheme,\n\tUnknownObject,\n} from \"../hooks/@types\";\nimport { SET_GLOBALS_EVENT_TYPE, type SetGlobalsEvent } from \"../hooks/@types\";\nimport type {\n\tToolCallResult,\n\tToolResult,\n\tUnifiedWidgetClient,\n} from \"./widget-client\";\n\ntype GlobalsKey = keyof SetGlobalsEvent[\"detail\"][\"globals\"];\n\n/**\n * OpenAI widget client implementation.\n * Uses window.openai global object injected by ChatGPT.\n */\nexport class OpenAIWidgetClient implements UnifiedWidgetClient {\n\tprivate pendingModelContext: ModelContextUpdate | null = null;\n\n\tprivate getGlobal<T>(\n\t\tkey: keyof NonNullable<typeof window.openai>,\n\t\tfallback: T,\n\t): T {\n\t\tif (typeof window === \"undefined\") {\n\t\t\treturn fallback;\n\t\t}\n\t\treturn (window.openai?.[key] as T) ?? fallback;\n\t}\n\n\tprivate onGlobalChange<\n\t\tK extends GlobalsKey,\n\t\tT = SetGlobalsEvent[\"detail\"][\"globals\"][K],\n\t>(\n\t\tkey: K,\n\t\tcallback: (value: T) => void,\n\t\ttransform?: (value: SetGlobalsEvent[\"detail\"][\"globals\"][K]) => T,\n\t): () => void {\n\t\tif (typeof window === \"undefined\") {\n\t\t\treturn () => {};\n\t\t}\n\n\t\tconst handler = (event: SetGlobalsEvent) => {\n\t\t\tconst value = event.detail.globals[key];\n\t\t\tif (value !== undefined) {\n\t\t\t\tcallback(transform ? transform(value) : (value as T));\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener(SET_GLOBALS_EVENT_TYPE, handler, { passive: true });\n\t\treturn () => window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handler);\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (typeof window === \"undefined\" || !(\"openai\" in window)) {\n\t\t\tthrow new Error(\"OpenAI global not found. Are you running in ChatGPT?\");\n\t\t}\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// No-op for OpenAI - connection is managed by the host\n\t}\n\n\tgetToolOutput<T = Record<string, unknown>>(): T | null {\n\t\treturn this.getGlobal<T | null>(\"toolOutput\", null);\n\t}\n\n\tonToolResult(callback: (result: ToolResult) => void): () => void {\n\t\treturn this.onGlobalChange(\"toolOutput\", callback, (v) => ({\n\t\t\tcontent: [],\n\t\t\tstructuredContent: v ?? {},\n\t\t}));\n\t}\n\n\tasync callTool(\n\t\tname: string,\n\t\targs: Record<string, unknown>,\n\t): Promise<ToolCallResult> {\n\t\tif (typeof window === \"undefined\" || !window.openai?.callTool) {\n\t\t\tthrow new Error(\"OpenAI callTool not available\");\n\t\t}\n\t\tconst response = await window.openai.callTool(name, args);\n\t\treturn { content: [{ type: \"text\", text: response.result }] };\n\t}\n\n\topenExternal(url: string): void {\n\t\tif (typeof window !== \"undefined\" && window.openai?.openExternal) {\n\t\t\twindow.openai.openExternal({ href: url });\n\t\t}\n\t}\n\n\tsendFollowUp(prompt: string): void {\n\t\tif (typeof window !== \"undefined\" && window.openai?.sendFollowUpMessage) {\n\t\t\tconst hiddenContext = formatModelContextForPrompt(\n\t\t\t\tthis.pendingModelContext,\n\t\t\t);\n\t\t\tthis.pendingModelContext = null;\n\t\t\tconst message = hiddenContext ? `${prompt}\\n\\n${hiddenContext}` : prompt;\n\t\t\twindow.openai.sendFollowUpMessage({ prompt: message });\n\t\t}\n\t}\n\n\tupdateModelContext(context: ModelContextUpdate): void {\n\t\tthis.pendingModelContext = mergeModelContext(\n\t\t\tthis.pendingModelContext,\n\t\t\tcontext,\n\t\t);\n\t}\n\n\tgetTheme(): Theme {\n\t\treturn this.getGlobal(\"theme\", \"light\" as Theme);\n\t}\n\n\tonThemeChange(callback: (theme: Theme) => void): () => void {\n\t\treturn this.onGlobalChange(\"theme\", callback);\n\t}\n\n\tgetLocale(): string {\n\t\treturn this.getGlobal(\"locale\", \"en\");\n\t}\n\n\tgetDisplayMode(): DisplayMode {\n\t\treturn this.getGlobal(\"displayMode\", \"inline\" as DisplayMode);\n\t}\n\n\tasync requestDisplayMode(mode: DisplayMode): Promise<DisplayMode> {\n\t\tif (typeof window === \"undefined\" || !window.openai?.requestDisplayMode) {\n\t\t\treturn \"inline\";\n\t\t}\n\t\tconst result = await window.openai.requestDisplayMode({ mode });\n\t\treturn result.mode;\n\t}\n\n\tonDisplayModeChange(callback: (mode: DisplayMode) => void): () => void {\n\t\treturn this.onGlobalChange(\"displayMode\", callback);\n\t}\n\n\tgetSafeArea(): SafeArea | null {\n\t\treturn this.getGlobal(\"safeArea\", null);\n\t}\n\n\tonSafeAreaChange(callback: (safeArea: SafeArea | null) => void): () => void {\n\t\treturn this.onGlobalChange(\"safeArea\", callback, (v) => v ?? null);\n\t}\n\n\tgetMaxHeight(): number | null {\n\t\treturn this.getGlobal(\"maxHeight\", null);\n\t}\n\n\tonMaxHeightChange(callback: (maxHeight: number | null) => void): () => void {\n\t\treturn this.onGlobalChange(\"maxHeight\", callback, (v) => v ?? null);\n\t}\n\n\tgetToolResponseMetadata(): UnknownObject | null {\n\t\treturn this.getGlobal(\"toolResponseMetadata\", null);\n\t}\n\n\tonToolResponseMetadataChange(\n\t\tcallback: (metadata: UnknownObject | null) => void,\n\t): () => void {\n\t\treturn this.onGlobalChange(\n\t\t\t\"toolResponseMetadata\",\n\t\t\tcallback,\n\t\t\t(v) => v ?? null,\n\t\t);\n\t}\n\n\tgetWidgetState(): UnknownObject | null {\n\t\treturn this.getGlobal<UnknownObject | null>(\"widgetState\", null);\n\t}\n\n\tonWidgetStateChange(\n\t\tcallback: (state: UnknownObject | null) => void,\n\t): () => void {\n\t\treturn this.onGlobalChange(\"widgetState\", callback, (v) => v ?? null);\n\t}\n}\n"],"mappings":"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","names":["OpenAIWidgetClient","key","fallback","callback","transform","handler","event","value","SET_GLOBALS_EVENT_TYPE","v","name","args","url","prompt","hiddenContext","formatModelContextForPrompt","message","context","mergeModelContext","mode"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waniwani/sdk",
3
- "version": "0.4.0",
3
+ "version": "0.4.3",
4
4
  "description": "WaniWani SDK - MCP event tracking, widget framework, and tools",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/mcp/react/hooks/@types.ts","../src/shared/model-context.ts"],"sourcesContent":["/**\n * Source: https://github.com/openai/openai-apps-sdk-examples/tree/main/src\n */\n\nexport type OpenAIGlobals<\n\tToolInput = UnknownObject,\n\tToolOutput = UnknownObject,\n\tToolResponseMetadata = UnknownObject,\n\tWidgetState = UnknownObject,\n> = {\n\t// visuals\n\ttheme: Theme;\n\n\tuserAgent: UserAgent;\n\tlocale: string;\n\n\t// layout\n\tmaxHeight: number;\n\tdisplayMode: DisplayMode;\n\tsafeArea: SafeArea;\n\n\t// state\n\ttoolInput: ToolInput;\n\ttoolOutput: ToolOutput | null;\n\ttoolResponseMetadata: ToolResponseMetadata | null;\n\twidgetState: WidgetState | null;\n\tsetWidgetState: (state: WidgetState) => Promise<void>;\n};\n\ntype API = {\n\tcallTool: CallTool;\n\tsendFollowUpMessage: (args: { prompt: string }) => Promise<void>;\n\topenExternal(payload: { href: string }): void;\n\n\t// Layout controls\n\trequestDisplayMode: RequestDisplayMode;\n};\n\nexport type UnknownObject = Record<string, unknown>;\n\nexport type Theme = \"light\" | \"dark\";\n\nexport type SafeAreaInsets = {\n\ttop: number;\n\tbottom: number;\n\tleft: number;\n\tright: number;\n};\n\nexport type SafeArea = {\n\tinsets: SafeAreaInsets;\n};\n\nexport type DeviceType = \"mobile\" | \"tablet\" | \"desktop\" | \"unknown\";\n\nexport type UserAgent = {\n\tdevice: { type: DeviceType };\n\tcapabilities: {\n\t\thover: boolean;\n\t\ttouch: boolean;\n\t};\n};\n\n/** Display mode */\nexport type DisplayMode = \"pip\" | \"inline\" | \"fullscreen\";\nexport type RequestDisplayMode = (args: { mode: DisplayMode }) => Promise<{\n\t/**\n\t * The granted display mode. The host may reject the request.\n\t * For mobile, PiP is always coerced to fullscreen.\n\t */\n\tmode: DisplayMode;\n}>;\n\nexport type CallToolResponse = {\n\tresult: string;\n};\n\n/** Calling APIs */\nexport type CallTool = (\n\tname: string,\n\targs: Record<string, unknown>,\n) => Promise<CallToolResponse>;\n\n/** Extra events */\nexport const SET_GLOBALS_EVENT_TYPE = \"openai:set_globals\";\nexport class SetGlobalsEvent extends CustomEvent<{\n\tglobals: Partial<OpenAIGlobals>;\n}> {\n\tconstructor(detail: { globals: Partial<OpenAIGlobals> }) {\n\t\tsuper(SET_GLOBALS_EVENT_TYPE, { detail });\n\t}\n}\n\n/**\n * Global oai object injected by the web sandbox for communicating with chatgpt host page.\n */\ndeclare global {\n\tinterface Window {\n\t\topenai: API & OpenAIGlobals;\n\t\tinnerBaseUrl: string;\n\t}\n\n\tinterface WindowEventMap {\n\t\t[SET_GLOBALS_EVENT_TYPE]: SetGlobalsEvent;\n\t}\n}\n","import type { ContentBlock } from \"@modelcontextprotocol/sdk/types.js\";\n\nexport type ModelContextContentBlock = ContentBlock;\n\nexport type ModelContextUpdate = {\n\tcontent?: ModelContextContentBlock[];\n\tstructuredContent?: Record<string, unknown>;\n};\n\nexport function hasModelContext(\n\tvalue: ModelContextUpdate | null | undefined,\n): value is ModelContextUpdate {\n\tif (!value) return false;\n\tconst hasContent = Array.isArray(value.content) && value.content.length > 0;\n\tconst hasStructuredContent =\n\t\ttypeof value.structuredContent === \"object\" &&\n\t\tvalue.structuredContent !== null &&\n\t\tObject.keys(value.structuredContent).length > 0;\n\treturn hasContent || hasStructuredContent;\n}\n\nexport function mergeModelContext(\n\tcurrent: ModelContextUpdate | null | undefined,\n\tnext: ModelContextUpdate | null | undefined,\n): ModelContextUpdate | null {\n\tif (!hasModelContext(current) && !hasModelContext(next)) return null;\n\tif (!hasModelContext(current)) {\n\t\treturn {\n\t\t\t...(next?.content ? { content: [...next.content] } : {}),\n\t\t\t...(next?.structuredContent\n\t\t\t\t? { structuredContent: { ...next.structuredContent } }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\tif (!hasModelContext(next)) {\n\t\treturn {\n\t\t\t...(current.content ? { content: [...current.content] } : {}),\n\t\t\t...(current.structuredContent\n\t\t\t\t? { structuredContent: { ...current.structuredContent } }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\n\treturn {\n\t\t...(current.content || next.content\n\t\t\t? { content: [...(current.content ?? []), ...(next.content ?? [])] }\n\t\t\t: {}),\n\t\t...(current.structuredContent || next.structuredContent\n\t\t\t? {\n\t\t\t\t\tstructuredContent: {\n\t\t\t\t\t\t...(current.structuredContent ?? {}),\n\t\t\t\t\t\t...(next.structuredContent ?? {}),\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\nexport function formatModelContextForPrompt(\n\tvalue: ModelContextUpdate | null | undefined,\n): string {\n\tif (!hasModelContext(value)) return \"\";\n\n\tconst sections: string[] = [\n\t\t\"## Widget Model Context\",\n\t\t\"This hidden context was supplied by an MCP App via `ui/update-model-context`.\",\n\t\t\"Use it for the next assistant turn only. If it includes flow continuation or tool-call instructions, follow them exactly.\",\n\t];\n\n\tif (value.content?.length) {\n\t\tconst renderedBlocks = value.content\n\t\t\t.map((block) => {\n\t\t\t\tif (block.type === \"text\" && typeof block.text === \"string\") {\n\t\t\t\t\treturn block.text.trim();\n\t\t\t\t}\n\t\t\t\treturn JSON.stringify(block, null, 2);\n\t\t\t})\n\t\t\t.filter(Boolean)\n\t\t\t.join(\"\\n\\n\");\n\t\tif (renderedBlocks) {\n\t\t\tsections.push(`Content blocks:\\n${renderedBlocks}`);\n\t\t}\n\t}\n\n\tif (\n\t\tvalue.structuredContent &&\n\t\tObject.keys(value.structuredContent).length > 0\n\t) {\n\t\tsections.push(\n\t\t\t`Structured content JSON:\\n${JSON.stringify(value.structuredContent, null, 2)}`,\n\t\t);\n\t}\n\n\treturn sections.join(\"\\n\\n\");\n}\n"],"mappings":";AAoFO,IAAMA,EAAyB,qBACzBC,EAAN,cAA8B,WAElC,CACF,YAAYC,EAA6C,CACxD,MAAMF,EAAwB,CAAE,OAAAE,CAAO,CAAC,CACzC,CACD,EClFO,SAASC,EACfC,EAC8B,CAC9B,GAAI,CAACA,EAAO,MAAO,GACnB,IAAMC,EAAa,MAAM,QAAQD,EAAM,OAAO,GAAKA,EAAM,QAAQ,OAAS,EACpEE,EACL,OAAOF,EAAM,mBAAsB,UACnCA,EAAM,oBAAsB,MAC5B,OAAO,KAAKA,EAAM,iBAAiB,EAAE,OAAS,EAC/C,OAAOC,GAAcC,CACtB,CAEO,SAASC,EACfC,EACAC,EAC4B,CAC5B,MAAI,CAACN,EAAgBK,CAAO,GAAK,CAACL,EAAgBM,CAAI,EAAU,KAC3DN,EAAgBK,CAAO,EAQvBL,EAAgBM,CAAI,EASlB,CACN,GAAID,EAAQ,SAAWC,EAAK,QACzB,CAAE,QAAS,CAAC,GAAID,EAAQ,SAAW,CAAC,EAAI,GAAIC,EAAK,SAAW,CAAC,CAAE,CAAE,EACjE,CAAC,EACJ,GAAID,EAAQ,mBAAqBC,EAAK,kBACnC,CACA,kBAAmB,CAClB,GAAID,EAAQ,mBAAqB,CAAC,EAClC,GAAIC,EAAK,mBAAqB,CAAC,CAChC,CACD,EACC,CAAC,CACL,EApBQ,CACN,GAAID,EAAQ,QAAU,CAAE,QAAS,CAAC,GAAGA,EAAQ,OAAO,CAAE,EAAI,CAAC,EAC3D,GAAIA,EAAQ,kBACT,CAAE,kBAAmB,CAAE,GAAGA,EAAQ,iBAAkB,CAAE,EACtD,CAAC,CACL,EAbO,CACN,GAAIC,GAAM,QAAU,CAAE,QAAS,CAAC,GAAGA,EAAK,OAAO,CAAE,EAAI,CAAC,EACtD,GAAIA,GAAM,kBACP,CAAE,kBAAmB,CAAE,GAAGA,EAAK,iBAAkB,CAAE,EACnD,CAAC,CACL,CAwBF,CAEO,SAASC,EACfN,EACS,CACT,GAAI,CAACD,EAAgBC,CAAK,EAAG,MAAO,GAEpC,IAAMO,EAAqB,CAC1B,0BACA,gFACA,2HACD,EAEA,GAAIP,EAAM,SAAS,OAAQ,CAC1B,IAAMQ,EAAiBR,EAAM,QAC3B,IAAKS,GACDA,EAAM,OAAS,QAAU,OAAOA,EAAM,MAAS,SAC3CA,EAAM,KAAK,KAAK,EAEjB,KAAK,UAAUA,EAAO,KAAM,CAAC,CACpC,EACA,OAAO,OAAO,EACd,KAAK;AAAA;AAAA,CAAM,EACTD,GACHD,EAAS,KAAK;AAAA,EAAoBC,CAAc,EAAE,CAEpD,CAEA,OACCR,EAAM,mBACN,OAAO,KAAKA,EAAM,iBAAiB,EAAE,OAAS,GAE9CO,EAAS,KACR;AAAA,EAA6B,KAAK,UAAUP,EAAM,kBAAmB,KAAM,CAAC,CAAC,EAC9E,EAGMO,EAAS,KAAK;AAAA;AAAA,CAAM,CAC5B","names":["SET_GLOBALS_EVENT_TYPE","SetGlobalsEvent","detail","hasModelContext","value","hasContent","hasStructuredContent","mergeModelContext","current","next","formatModelContextForPrompt","sections","renderedBlocks","block"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/mcp/react/widgets/mcp-apps-client.ts"],"sourcesContent":["import type { McpUiHostContext } from \"@modelcontextprotocol/ext-apps\";\nimport { App, PostMessageTransport } from \"@modelcontextprotocol/ext-apps\";\nimport type { ModelContextUpdate } from \"../../../shared/model-context\";\nimport type {\n\tDisplayMode,\n\tSafeArea,\n\tTheme,\n\tUnknownObject,\n} from \"../hooks/@types\";\nimport type {\n\tToolCallResult,\n\tToolResult,\n\tUnifiedWidgetClient,\n} from \"./widget-client\";\n\n/**\n * MCP Apps widget client implementation.\n * Uses the @modelcontextprotocol/ext-apps App class for communication.\n */\nexport class MCPAppsWidgetClient implements UnifiedWidgetClient {\n\tprivate app: App;\n\tprivate toolResultCallback: ((result: ToolResult) => void) | null = null;\n\tprivate toolResponseMetadataChangeCallback:\n\t\t| ((metadata: UnknownObject | null) => void)\n\t\t| null = null;\n\tprivate themeChangeCallback: ((theme: Theme) => void) | null = null;\n\tprivate displayModeChangeCallback: ((mode: DisplayMode) => void) | null =\n\t\tnull;\n\tprivate hostContext: McpUiHostContext | undefined;\n\tprivate latestToolResult: ToolResult | null = null;\n\tprivate resizeCleanup: (() => void) | null = null;\n\n\tconstructor() {\n\t\tthis.app = new App(\n\t\t\t{ name: \"WaniWani Widget\", version: \"1.0.0\" },\n\t\t\t{}, // capabilities\n\t\t\t{ autoResize: false },\n\t\t);\n\n\t\t// Set up notification handlers\n\t\tthis.app.ontoolresult = (params) => {\n\t\t\tconst rawParams = params as Record<string, unknown>;\n\t\t\tconst underscoreMeta =\n\t\t\t\ttypeof rawParams._meta === \"object\" && rawParams._meta !== null\n\t\t\t\t\t? (rawParams._meta as Record<string, unknown>)\n\t\t\t\t\t: null;\n\t\t\tconst meta =\n\t\t\t\ttypeof rawParams.meta === \"object\" && rawParams.meta !== null\n\t\t\t\t\t? (rawParams.meta as Record<string, unknown>)\n\t\t\t\t\t: null;\n\t\t\tconst resolvedMeta = underscoreMeta ?? meta ?? undefined;\n\n\t\t\tconst result: ToolResult = {\n\t\t\t\tcontent: params.content,\n\t\t\t\tstructuredContent: params.structuredContent as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t\t_meta: resolvedMeta,\n\t\t\t\tisError:\n\t\t\t\t\ttypeof rawParams.isError === \"boolean\"\n\t\t\t\t\t\t? rawParams.isError\n\t\t\t\t\t\t: undefined,\n\t\t\t};\n\t\t\tthis.latestToolResult = result;\n\t\t\tthis.toolResultCallback?.(result);\n\t\t\tthis.toolResponseMetadataChangeCallback?.(result._meta ?? null);\n\t\t};\n\n\t\tthis.app.onhostcontextchanged = (params) => {\n\t\t\tthis.hostContext = { ...this.hostContext, ...params };\n\t\t\tif (params.theme) {\n\t\t\t\tthis.themeChangeCallback?.(params.theme as Theme);\n\t\t\t}\n\t\t\tif (params.displayMode) {\n\t\t\t\tthis.displayModeChangeCallback?.(params.displayMode as DisplayMode);\n\t\t\t}\n\t\t};\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tawait this.app.connect(\n\t\t\tnew PostMessageTransport(window.parent, window.parent),\n\t\t);\n\t\tthis.hostContext = this.app.getHostContext();\n\t\tthis.resizeCleanup = this.setupAutoResize();\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.resizeCleanup?.();\n\t\tthis.resizeCleanup = null;\n\t\tawait this.app.close();\n\t}\n\n\t/**\n\t * Custom auto-resize that uses scrollHeight with a collapsed root element.\n\t * The library's built-in autoResize uses fit-content + getBoundingClientRect\n\t * which can fail to detect height changes when content grows.\n\t */\n\tprivate setupAutoResize(): () => void {\n\t\tlet rafPending = false;\n\t\tlet lastWidth = 0;\n\t\tlet lastHeight = 0;\n\n\t\tconst measure = () => {\n\t\t\tif (rafPending) return;\n\t\t\trafPending = true;\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\trafPending = false;\n\t\t\t\tconst el = document.documentElement;\n\n\t\t\t\t// --- Width: use fit-content (same as library) ---\n\t\t\t\tconst savedWidth = el.style.width;\n\t\t\t\tel.style.width = \"fit-content\";\n\t\t\t\tconst fitRect = el.getBoundingClientRect();\n\t\t\t\tel.style.width = savedWidth;\n\t\t\t\tconst scrollbarGap = window.innerWidth - el.clientWidth;\n\t\t\t\tconst width = Math.ceil(fitRect.width + scrollbarGap);\n\n\t\t\t\t// --- Height: collapse root and read scrollHeight ---\n\t\t\t\t// fit-content on <html> can under-report when children use\n\t\t\t\t// percentage heights or viewport units. Collapsing to 0 and\n\t\t\t\t// reading scrollHeight gives the true content height.\n\t\t\t\tconst savedHeight = el.style.height;\n\t\t\t\tconst savedMinHeight = el.style.minHeight;\n\t\t\t\tel.style.height = \"0\";\n\t\t\t\tel.style.minHeight = \"0\";\n\t\t\t\tconst height = el.scrollHeight;\n\t\t\t\tel.style.height = savedHeight;\n\t\t\t\tel.style.minHeight = savedMinHeight;\n\n\t\t\t\tif (width !== lastWidth || height !== lastHeight) {\n\t\t\t\t\tlastWidth = width;\n\t\t\t\t\tlastHeight = height;\n\t\t\t\t\tthis.app.sendSizeChanged({ width, height });\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\tmeasure();\n\t\tconst observer = new ResizeObserver(measure);\n\t\tobserver.observe(document.documentElement);\n\t\tobserver.observe(document.body);\n\t\treturn () => observer.disconnect();\n\t}\n\n\tgetToolOutput<T = Record<string, unknown>>(): T | null {\n\t\t// In MCP Apps, tool output comes through ontoolresult notification\n\t\t// Return the latest cached result\n\t\tif (this.latestToolResult?.structuredContent) {\n\t\t\treturn this.latestToolResult.structuredContent as T;\n\t\t}\n\t\treturn null;\n\t}\n\n\tonToolResult(callback: (result: ToolResult) => void): () => void {\n\t\tthis.toolResultCallback = callback;\n\t\treturn () => {\n\t\t\tthis.toolResultCallback = null;\n\t\t};\n\t}\n\n\tasync callTool(\n\t\tname: string,\n\t\targs: Record<string, unknown>,\n\t): Promise<ToolCallResult> {\n\t\tconst result = await this.app.callServerTool({\n\t\t\tname,\n\t\t\targuments: args,\n\t\t});\n\t\treturn {\n\t\t\tcontent: result.content,\n\t\t\tstructuredContent: result.structuredContent as\n\t\t\t\t| Record<string, unknown>\n\t\t\t\t| undefined,\n\t\t\t_meta: result._meta as Record<string, unknown> | undefined,\n\t\t\tisError: typeof result.isError === \"boolean\" ? result.isError : undefined,\n\t\t};\n\t}\n\n\topenExternal(url: string): void {\n\t\tthis.app.sendOpenLink({ url }).catch((err: unknown) => {\n\t\t\tconsole.error(\"Failed to open link:\", err);\n\t\t});\n\t}\n\n\tsendFollowUp(prompt: string): void {\n\t\tthis.app\n\t\t\t.sendMessage({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: [{ type: \"text\", text: prompt }],\n\t\t\t})\n\t\t\t.catch((err: unknown) => {\n\t\t\t\tconsole.error(\"Failed to send follow-up message:\", err);\n\t\t\t});\n\t}\n\n\tupdateModelContext(context: ModelContextUpdate): Promise<void> {\n\t\treturn this.app\n\t\t\t.updateModelContext({\n\t\t\t\t...(context.content ? { content: context.content } : {}),\n\t\t\t\t...(context.structuredContent\n\t\t\t\t\t? { structuredContent: context.structuredContent }\n\t\t\t\t\t: {}),\n\t\t\t})\n\t\t\t.then(() => undefined);\n\t}\n\n\tgetTheme(): Theme {\n\t\treturn (this.hostContext?.theme as Theme) ?? \"light\";\n\t}\n\n\tonThemeChange(callback: (theme: Theme) => void): () => void {\n\t\tthis.themeChangeCallback = callback;\n\t\treturn () => {\n\t\t\tthis.themeChangeCallback = null;\n\t\t};\n\t}\n\n\tgetLocale(): string {\n\t\treturn (this.hostContext?.locale as string | undefined) ?? \"en\";\n\t}\n\n\tgetDisplayMode(): DisplayMode {\n\t\treturn (this.hostContext?.displayMode as DisplayMode) ?? \"inline\";\n\t}\n\n\tasync requestDisplayMode(mode: DisplayMode): Promise<DisplayMode> {\n\t\tconst result = await this.app.requestDisplayMode({ mode });\n\t\treturn result.mode as DisplayMode;\n\t}\n\n\tonDisplayModeChange(callback: (mode: DisplayMode) => void): () => void {\n\t\tthis.displayModeChangeCallback = callback;\n\t\treturn () => {\n\t\t\tthis.displayModeChangeCallback = null;\n\t\t};\n\t}\n\n\t// OPENAI specific methods\n\tgetSafeArea(): SafeArea | null {\n\t\treturn null;\n\t}\n\n\t// MCP Apps specific methods\n\tonSafeAreaChange(): () => void {\n\t\treturn () => {};\n\t}\n\n\t// OPENAI specific methods\n\tgetMaxHeight(): number | null {\n\t\treturn null;\n\t}\n\n\t// MCP Apps specific methods\n\tonMaxHeightChange(): () => void {\n\t\treturn () => {};\n\t}\n\n\t// MCP Apps specific methods\n\tgetToolResponseMetadata(): UnknownObject | null {\n\t\treturn this.latestToolResult?._meta ?? null;\n\t}\n\n\t// MCP Apps specific methods\n\tonToolResponseMetadataChange(\n\t\tcallback: (metadata: UnknownObject | null) => void,\n\t): () => void {\n\t\tthis.toolResponseMetadataChangeCallback = callback;\n\t\treturn () => {\n\t\t\tthis.toolResponseMetadataChangeCallback = null;\n\t\t};\n\t}\n\n\t// MCP Apps specific methods\n\tgetWidgetState(): UnknownObject | null {\n\t\treturn null;\n\t}\n\n\t// MCP Apps specific methods\n\tonWidgetStateChange(): () => void {\n\t\treturn () => {};\n\t}\n}\n"],"mappings":"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","names":["App","PostMessageTransport","MCPAppsWidgetClient","params","rawParams","underscoreMeta","meta","resolvedMeta","result","rafPending","lastWidth","lastHeight","measure","el","savedWidth","fitRect","scrollbarGap","width","savedHeight","savedMinHeight","height","observer","callback","name","args","url","err","prompt","context","mode"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/mcp/react/widgets/openai-client.ts"],"sourcesContent":["import {\n\tformatModelContextForPrompt,\n\ttype ModelContextUpdate,\n\tmergeModelContext,\n} from \"../../../shared/model-context\";\nimport type {\n\tDisplayMode,\n\tSafeArea,\n\tTheme,\n\tUnknownObject,\n} from \"../hooks/@types\";\nimport { SET_GLOBALS_EVENT_TYPE, type SetGlobalsEvent } from \"../hooks/@types\";\nimport type {\n\tToolCallResult,\n\tToolResult,\n\tUnifiedWidgetClient,\n} from \"./widget-client\";\n\ntype GlobalsKey = keyof SetGlobalsEvent[\"detail\"][\"globals\"];\n\n/**\n * OpenAI widget client implementation.\n * Uses window.openai global object injected by ChatGPT.\n */\nexport class OpenAIWidgetClient implements UnifiedWidgetClient {\n\tprivate pendingModelContext: ModelContextUpdate | null = null;\n\n\tprivate getGlobal<T>(\n\t\tkey: keyof NonNullable<typeof window.openai>,\n\t\tfallback: T,\n\t): T {\n\t\tif (typeof window === \"undefined\") return fallback;\n\t\treturn (window.openai?.[key] as T) ?? fallback;\n\t}\n\n\tprivate onGlobalChange<\n\t\tK extends GlobalsKey,\n\t\tT = SetGlobalsEvent[\"detail\"][\"globals\"][K],\n\t>(\n\t\tkey: K,\n\t\tcallback: (value: T) => void,\n\t\ttransform?: (value: SetGlobalsEvent[\"detail\"][\"globals\"][K]) => T,\n\t): () => void {\n\t\tif (typeof window === \"undefined\") return () => {};\n\n\t\tconst handler = (event: SetGlobalsEvent) => {\n\t\t\tconst value = event.detail.globals[key];\n\t\t\tif (value !== undefined) {\n\t\t\t\tcallback(transform ? transform(value) : (value as T));\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener(SET_GLOBALS_EVENT_TYPE, handler, { passive: true });\n\t\treturn () => window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handler);\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (typeof window === \"undefined\" || !(\"openai\" in window)) {\n\t\t\tthrow new Error(\"OpenAI global not found. Are you running in ChatGPT?\");\n\t\t}\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// No-op for OpenAI - connection is managed by the host\n\t}\n\n\tgetToolOutput<T = Record<string, unknown>>(): T | null {\n\t\treturn this.getGlobal<T | null>(\"toolOutput\", null);\n\t}\n\n\tonToolResult(callback: (result: ToolResult) => void): () => void {\n\t\treturn this.onGlobalChange(\"toolOutput\", callback, (v) => ({\n\t\t\tcontent: [],\n\t\t\tstructuredContent: v ?? {},\n\t\t}));\n\t}\n\n\tasync callTool(\n\t\tname: string,\n\t\targs: Record<string, unknown>,\n\t): Promise<ToolCallResult> {\n\t\tif (typeof window === \"undefined\" || !window.openai?.callTool) {\n\t\t\tthrow new Error(\"OpenAI callTool not available\");\n\t\t}\n\t\tconst response = await window.openai.callTool(name, args);\n\t\treturn { content: [{ type: \"text\", text: response.result }] };\n\t}\n\n\topenExternal(url: string): void {\n\t\tif (typeof window !== \"undefined\" && window.openai?.openExternal) {\n\t\t\twindow.openai.openExternal({ href: url });\n\t\t}\n\t}\n\n\tsendFollowUp(prompt: string): void {\n\t\tif (typeof window !== \"undefined\" && window.openai?.sendFollowUpMessage) {\n\t\t\tconst hiddenContext = formatModelContextForPrompt(\n\t\t\t\tthis.pendingModelContext,\n\t\t\t);\n\t\t\tthis.pendingModelContext = null;\n\t\t\tconst message = hiddenContext ? `${prompt}\\n\\n${hiddenContext}` : prompt;\n\t\t\twindow.openai.sendFollowUpMessage({ prompt: message });\n\t\t}\n\t}\n\n\tupdateModelContext(context: ModelContextUpdate): void {\n\t\tthis.pendingModelContext = mergeModelContext(\n\t\t\tthis.pendingModelContext,\n\t\t\tcontext,\n\t\t);\n\t}\n\n\tgetTheme(): Theme {\n\t\treturn this.getGlobal(\"theme\", \"light\" as Theme);\n\t}\n\n\tonThemeChange(callback: (theme: Theme) => void): () => void {\n\t\treturn this.onGlobalChange(\"theme\", callback);\n\t}\n\n\tgetLocale(): string {\n\t\treturn this.getGlobal(\"locale\", \"en\");\n\t}\n\n\tgetDisplayMode(): DisplayMode {\n\t\treturn this.getGlobal(\"displayMode\", \"inline\" as DisplayMode);\n\t}\n\n\tasync requestDisplayMode(mode: DisplayMode): Promise<DisplayMode> {\n\t\tif (typeof window === \"undefined\" || !window.openai?.requestDisplayMode) {\n\t\t\treturn \"inline\";\n\t\t}\n\t\tconst result = await window.openai.requestDisplayMode({ mode });\n\t\treturn result.mode;\n\t}\n\n\tonDisplayModeChange(callback: (mode: DisplayMode) => void): () => void {\n\t\treturn this.onGlobalChange(\"displayMode\", callback);\n\t}\n\n\tgetSafeArea(): SafeArea | null {\n\t\treturn this.getGlobal(\"safeArea\", null);\n\t}\n\n\tonSafeAreaChange(callback: (safeArea: SafeArea | null) => void): () => void {\n\t\treturn this.onGlobalChange(\"safeArea\", callback, (v) => v ?? null);\n\t}\n\n\tgetMaxHeight(): number | null {\n\t\treturn this.getGlobal(\"maxHeight\", null);\n\t}\n\n\tonMaxHeightChange(callback: (maxHeight: number | null) => void): () => void {\n\t\treturn this.onGlobalChange(\"maxHeight\", callback, (v) => v ?? null);\n\t}\n\n\tgetToolResponseMetadata(): UnknownObject | null {\n\t\treturn this.getGlobal(\"toolResponseMetadata\", null);\n\t}\n\n\tonToolResponseMetadataChange(\n\t\tcallback: (metadata: UnknownObject | null) => void,\n\t): () => void {\n\t\treturn this.onGlobalChange(\n\t\t\t\"toolResponseMetadata\",\n\t\t\tcallback,\n\t\t\t(v) => v ?? null,\n\t\t);\n\t}\n\n\tgetWidgetState(): UnknownObject | null {\n\t\treturn this.getGlobal<UnknownObject | null>(\"widgetState\", null);\n\t}\n\n\tonWidgetStateChange(\n\t\tcallback: (state: UnknownObject | null) => void,\n\t): () => void {\n\t\treturn this.onGlobalChange(\"widgetState\", callback, (v) => v ?? null);\n\t}\n}\n"],"mappings":"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","names":["OpenAIWidgetClient","key","fallback","callback","transform","handler","event","value","SET_GLOBALS_EVENT_TYPE","v","name","args","url","prompt","hiddenContext","formatModelContextForPrompt","message","context","mergeModelContext","mode"]}