@waniwani/sdk 0.11.11 → 0.11.12
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.
- package/README.md +92 -93
- package/dist/chat/embed.js +51 -51
- package/dist/chat/embed.js.map +1 -1
- package/dist/chat/express-js/index.d.ts +8 -1
- package/dist/chat/express-js/index.js.map +1 -1
- package/dist/chat/index.d.ts +1 -22
- package/dist/chat/index.js +7 -7
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/next-js/index.d.ts +5 -3
- package/dist/chat/next-js/index.js.map +1 -1
- package/dist/chat/server/index.js +1 -1
- package/dist/chat/server/index.js.map +1 -1
- package/dist/chat/styles.css +1 -1
- package/dist/{chunk-DGSC74SV.js → chunk-DP6SAQTK.js} +1 -1
- package/dist/chunk-DP6SAQTK.js.map +1 -0
- package/dist/{chunk-5OQXAEHG.js → chunk-RZKVTH7F.js} +1 -1
- package/dist/chunk-RZKVTH7F.js.map +1 -0
- package/dist/legacy/chat/express-js/index.d.ts +407 -0
- package/dist/legacy/chat/express-js/index.js +10 -0
- package/dist/legacy/chat/express-js/index.js.map +1 -0
- package/dist/legacy/chat/next-js/index.d.ts +368 -0
- package/dist/legacy/chat/next-js/index.js +10 -0
- package/dist/legacy/chat/next-js/index.js.map +1 -0
- package/dist/legacy/index.d.ts +335 -0
- package/dist/legacy/index.js +2 -0
- package/dist/legacy/index.js.map +1 -0
- package/dist/legacy/mcp/react.d.ts +573 -0
- package/dist/legacy/mcp/react.js +68 -0
- package/dist/legacy/mcp/react.js.map +1 -0
- package/dist/mcp/index.d.ts +1153 -1117
- package/dist/mcp/index.js +5 -5
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/react.d.ts +170 -74
- package/dist/mcp/react.js +7 -7
- package/dist/mcp/react.js.map +1 -1
- package/dist/{mcp-apps-client-PUL4H54S.js → mcp-apps-client-OFYMQOI3.js} +1 -1
- package/dist/mcp-apps-client-OFYMQOI3.js.map +1 -0
- package/dist/{openai-client-QAC3ZD5W.js → openai-client-TZIOCMXP.js} +2 -2
- package/dist/openai-client-TZIOCMXP.js.map +1 -0
- package/dist/platform-LKQFC3AJ.js +3 -0
- package/package.json +34 -21
- package/dist/chunk-5OQXAEHG.js.map +0 -1
- package/dist/chunk-DGSC74SV.js.map +0 -1
- package/dist/evals/index.d.ts +0 -156
- package/dist/evals/index.js +0 -2
- package/dist/evals/index.js.map +0 -1
- package/dist/evals/scorers.d.ts +0 -92
- package/dist/evals/scorers.js +0 -8
- package/dist/evals/scorers.js.map +0 -1
- package/dist/mcp-apps-client-PUL4H54S.js.map +0 -1
- package/dist/openai-client-QAC3ZD5W.js.map +0 -1
- package/dist/platform-GKYYQBCS.js +0 -3
- /package/dist/{platform-GKYYQBCS.js.map → platform-LKQFC3AJ.js.map} +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import{App as m,PostMessageTransport as C}from"@modelcontextprotocol/ext-apps";var d=class{app;toolResultCallback=null;toolResponseMetadataChangeCallback=null;themeChangeCallback=null;displayModeChangeCallback=null;hostContext;latestToolResult=null;resizeCleanup=null;constructor(){this.app=new m({name:"WaniWani Widget",version:"1.0.0"},{},{autoResize:!1}),this.app.ontoolresult=e=>{let t=e,n=typeof t._meta=="object"&&t._meta!==null?t._meta:null,s=typeof t.meta=="object"&&t.meta!==null?t.meta:null,l=n??s??void 0,o={content:e.content,structuredContent:e.structuredContent,_meta:l,isError:typeof t.isError=="boolean"?t.isError:void 0};this.latestToolResult=o,this.toolResultCallback?.(o),this.toolResponseMetadataChangeCallback?.(o._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 C(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,n=0,s=()=>{e||(e=!0,requestAnimationFrame(()=>{e=!1;let o=document.documentElement,u=o.style.width;o.style.width="fit-content";let c=o.getBoundingClientRect();o.style.width=u;let h=window.innerWidth-o.clientWidth,a=Math.ceil(c.width+h),r=getComputedStyle(document.body),p=parseFloat(r.marginTop)+parseFloat(r.marginBottom),i=Math.ceil(document.body.scrollHeight+p);(a!==t||i!==n)&&(t=a,n=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 n=await this.app.callServerTool({name:e,arguments:t});return{content:n.content,structuredContent:n.structuredContent,_meta:n._meta,isError:typeof n.isError=="boolean"?n.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{d as MCPAppsWidgetClient};
|
|
3
|
-
//# sourceMappingURL=mcp-apps-client-
|
|
3
|
+
//# sourceMappingURL=mcp-apps-client-OFYMQOI3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/legacy/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: read body.scrollHeight + body margins ---\n\t\t\t\t// We use document.body.scrollHeight rather than collapsing\n\t\t\t\t// <html> and reading its scrollHeight, because in an iframe\n\t\t\t\t// document.documentElement.scrollHeight never drops below\n\t\t\t\t// the viewport height (set by the parent iframe element),\n\t\t\t\t// causing a ratchet effect where the iframe only ever grows.\n\t\t\t\t// scrollHeight excludes the body's own margins, so we add\n\t\t\t\t// them back to avoid clipping.\n\t\t\t\tconst bodyStyle = getComputedStyle(document.body);\n\t\t\t\tconst bodyMargins =\n\t\t\t\t\tparseFloat(bodyStyle.marginTop) + parseFloat(bodyStyle.marginBottom);\n\t\t\t\tconst height = Math.ceil(document.body.scrollHeight + bodyMargins);\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","bodyStyle","bodyMargins","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 i,e as s}from"./chunk-
|
|
2
|
+
import{a as l,d as i,e as s}from"./chunk-RZKVTH7F.js";import{App as u,PostMessageTransport as p}from"@modelcontextprotocol/ext-apps";var r=class{pendingModelContext=null;app;getGlobal(e,n){return typeof window>"u"?n:window.openai?.[e]??n}onGlobalChange(e,n,t){if(typeof window>"u")return()=>{};let a=d=>{let o=d.detail.globals[e];o!==void 0&&n(t?t(o):o)};return window.addEventListener(l,a,{passive:!0}),()=>window.removeEventListener(l,a)}constructor(){this.app=new u({name:"WaniWani Widget",version:"1.0.0"},{},{autoResize:!1})}async connect(){if(typeof window>"u"||!("openai"in window))throw new Error("OpenAI global not found. Are you running in ChatGPT?");await this.app.connect(new p(window.parent,window.parent))}async close(){await this.app.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){let n=s(this.pendingModelContext);this.pendingModelContext=null;let t=n?`${e}
|
|
3
3
|
|
|
4
4
|
${n}`:e;return this.app.sendMessage({role:"user",content:[{type:"text",text:t}]}).then(()=>{})}updateModelContext(e){this.pendingModelContext=i(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{r as OpenAIWidgetClient};
|
|
5
|
-
//# sourceMappingURL=openai-client-
|
|
5
|
+
//# sourceMappingURL=openai-client-TZIOCMXP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/legacy/mcp/react/widgets/openai-client.ts"],"sourcesContent":["import { App, PostMessageTransport } from \"@modelcontextprotocol/ext-apps\";\nimport {\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\tprivate app: App;\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\tconstructor() {\n\t\tthis.app = new App(\n\t\t\t{ name: \"WaniWani Widget\", version: \"1.0.0\" },\n\t\t\t{},\n\t\t\t{ autoResize: false },\n\t\t);\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\tawait this.app.connect(\n\t\t\tnew PostMessageTransport(window.parent, window.parent),\n\t\t);\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.app.close();\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): Promise<void> {\n\t\tconst hiddenContext = formatModelContextForPrompt(this.pendingModelContext);\n\t\tthis.pendingModelContext = null;\n\t\tconst message = hiddenContext ? `${prompt}\\n\\n${hiddenContext}` : prompt;\n\t\treturn this.app\n\t\t\t.sendMessage({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\t})\n\t\t\t.then(() => undefined);\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":["App","PostMessageTransport","OpenAIWidgetClient","key","fallback","callback","transform","handler","event","value","SET_GLOBALS_EVENT_TYPE","App","PostMessageTransport","v","name","args","url","prompt","hiddenContext","formatModelContextForPrompt","message","context","mergeModelContext","mode"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waniwani/sdk",
|
|
3
|
-
"version": "0.11.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.11.12",
|
|
4
|
+
"description": "MCP distribution SDK. Build sales funnels, lead generation, booking, and quote apps on top of your MCP server. Event tracking, flows, widgets, knowledge base.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -46,15 +46,25 @@
|
|
|
46
46
|
"import": "./dist/kb/index.js",
|
|
47
47
|
"default": "./dist/kb/index.js"
|
|
48
48
|
},
|
|
49
|
-
"./
|
|
50
|
-
"types": "./dist/
|
|
51
|
-
"import": "./dist/
|
|
52
|
-
"default": "./dist/
|
|
53
|
-
},
|
|
54
|
-
"./
|
|
55
|
-
"types": "./dist/
|
|
56
|
-
"import": "./dist/
|
|
57
|
-
"default": "./dist/
|
|
49
|
+
"./legacy": {
|
|
50
|
+
"types": "./dist/legacy/index.d.ts",
|
|
51
|
+
"import": "./dist/legacy/index.js",
|
|
52
|
+
"default": "./dist/legacy/index.js"
|
|
53
|
+
},
|
|
54
|
+
"./legacy/react": {
|
|
55
|
+
"types": "./dist/legacy/mcp/react.d.ts",
|
|
56
|
+
"import": "./dist/legacy/mcp/react.js",
|
|
57
|
+
"default": "./dist/legacy/mcp/react.js"
|
|
58
|
+
},
|
|
59
|
+
"./legacy/next-js": {
|
|
60
|
+
"types": "./dist/legacy/chat/next-js/index.d.ts",
|
|
61
|
+
"import": "./dist/legacy/chat/next-js/index.js",
|
|
62
|
+
"default": "./dist/legacy/chat/next-js/index.js"
|
|
63
|
+
},
|
|
64
|
+
"./legacy/express-js": {
|
|
65
|
+
"types": "./dist/legacy/chat/express-js/index.d.ts",
|
|
66
|
+
"import": "./dist/legacy/chat/express-js/index.js",
|
|
67
|
+
"default": "./dist/legacy/chat/express-js/index.js"
|
|
58
68
|
}
|
|
59
69
|
},
|
|
60
70
|
"files": [
|
|
@@ -84,9 +94,7 @@
|
|
|
84
94
|
"zod": ">=4.0.0",
|
|
85
95
|
"@ai-sdk/react": ">=1.0.0",
|
|
86
96
|
"ai": ">=6.0.141",
|
|
87
|
-
"@ai-sdk/mcp": ">=1.0.0"
|
|
88
|
-
"braintrust": ">=3.0.0",
|
|
89
|
-
"autoevals": ">=0.0.100"
|
|
97
|
+
"@ai-sdk/mcp": ">=1.0.0"
|
|
90
98
|
},
|
|
91
99
|
"peerDependenciesMeta": {
|
|
92
100
|
"@modelcontextprotocol/sdk": {
|
|
@@ -109,12 +117,6 @@
|
|
|
109
117
|
},
|
|
110
118
|
"@ai-sdk/mcp": {
|
|
111
119
|
"optional": true
|
|
112
|
-
},
|
|
113
|
-
"braintrust": {
|
|
114
|
-
"optional": true
|
|
115
|
-
},
|
|
116
|
-
"autoevals": {
|
|
117
|
-
"optional": true
|
|
118
120
|
}
|
|
119
121
|
},
|
|
120
122
|
"devDependencies": {
|
|
@@ -132,7 +134,6 @@
|
|
|
132
134
|
"@types/react": "^19.0.0",
|
|
133
135
|
"@types/react-dom": "^19.2.3",
|
|
134
136
|
"ai": "^6.0.141",
|
|
135
|
-
"autoevals": "^0.0.132",
|
|
136
137
|
"clsx": "^2.1.1",
|
|
137
138
|
"fake-indexeddb": "^6.2.5",
|
|
138
139
|
"happy-dom": "^20.7.0",
|
|
@@ -160,6 +161,18 @@
|
|
|
160
161
|
"sdk",
|
|
161
162
|
"mcp",
|
|
162
163
|
"waniwani",
|
|
164
|
+
"mcp-funnel",
|
|
165
|
+
"mcp-distribution",
|
|
166
|
+
"mcp-sdk",
|
|
167
|
+
"sales-funnel",
|
|
168
|
+
"lead-generation",
|
|
169
|
+
"lead-capture",
|
|
170
|
+
"booking",
|
|
171
|
+
"insurance",
|
|
172
|
+
"quote",
|
|
173
|
+
"conversational-mcp",
|
|
174
|
+
"flows",
|
|
175
|
+
"knowledge-base",
|
|
163
176
|
"tracking",
|
|
164
177
|
"events",
|
|
165
178
|
"tools",
|
|
@@ -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) {\n\t\treturn false;\n\t}\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)) {\n\t\treturn null;\n\t}\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)) {\n\t\treturn \"\";\n\t}\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,EACJ,MAAO,GAER,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,EAC9C,KAEHN,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,EACzB,MAAO,GAGR,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/platform.ts"],"sourcesContent":["/**\n * Widget platform types\n */\nexport type WidgetPlatform = \"openai\" | \"mcp-apps\";\n\n/**\n * Detects which platform the widget is running on.\n *\n * OpenAI injects a global `window.openai` object.\n * MCP Apps runs in a sandboxed iframe and uses postMessage.\n */\nexport function detectPlatform(): WidgetPlatform {\n\tif (typeof window !== \"undefined\" && \"openai\" in window) {\n\t\treturn \"openai\";\n\t}\n\treturn \"mcp-apps\";\n}\n\n/**\n * Check if running on OpenAI platform\n */\nexport function isOpenAI(): boolean {\n\treturn detectPlatform() === \"openai\";\n}\n\n/**\n * Check if running on MCP Apps platform\n */\nexport function isMCPApps(): boolean {\n\treturn detectPlatform() === \"mcp-apps\";\n}\n"],"mappings":";AAWO,SAASA,GAAiC,CAChD,OAAI,OAAO,OAAW,KAAe,WAAY,OACzC,SAED,UACR,CAKO,SAASC,GAAoB,CACnC,OAAOD,EAAe,IAAM,QAC7B,CAKO,SAASE,GAAqB,CACpC,OAAOF,EAAe,IAAM,UAC7B","names":["detectPlatform","isOpenAI","isMCPApps"]}
|
package/dist/evals/index.d.ts
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { UIMessage } from 'ai';
|
|
2
|
-
|
|
3
|
-
interface ToolCallTrace {
|
|
4
|
-
name: string;
|
|
5
|
-
input: Record<string, unknown>;
|
|
6
|
-
output: unknown;
|
|
7
|
-
}
|
|
8
|
-
interface ChatResult {
|
|
9
|
-
output: string;
|
|
10
|
-
toolsCalled: string[];
|
|
11
|
-
toolCallTraces: ToolCallTrace[];
|
|
12
|
-
}
|
|
13
|
-
/** A single turn in a multi-turn conversation. */
|
|
14
|
-
interface ConversationTurn {
|
|
15
|
-
input: string;
|
|
16
|
-
}
|
|
17
|
-
/** Assertion result for a single tool call check within a turn. */
|
|
18
|
-
interface TurnAssertion {
|
|
19
|
-
/** Whether the actual tool calls matched the expected ones. */
|
|
20
|
-
passed: boolean;
|
|
21
|
-
/** Expected tool names recorded in the session. */
|
|
22
|
-
expected: string[];
|
|
23
|
-
/** Actual tool names called during replay. */
|
|
24
|
-
actual: string[];
|
|
25
|
-
}
|
|
26
|
-
/** Result of a single turn. */
|
|
27
|
-
interface ConversationTurnResult {
|
|
28
|
-
input: string;
|
|
29
|
-
response: ChatResult;
|
|
30
|
-
/** Auto-derived assertion results comparing actual vs. recorded tool calls. */
|
|
31
|
-
assertions: TurnAssertion[];
|
|
32
|
-
}
|
|
33
|
-
/** Full result of a multi-turn conversation. */
|
|
34
|
-
interface ConversationResult {
|
|
35
|
-
turns: ConversationTurnResult[];
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Scenario category for grouping and filtering eval scenarios.
|
|
39
|
-
* - **"regulatory"**: Checks against legal/regulatory requirements (e.g. did the agent push a sale?).
|
|
40
|
-
* - **"functional"**: Checks product behavior and correctness (e.g. did the flow return the right data?).
|
|
41
|
-
* - **"adversarial"**: Edge cases and robustness (e.g. weird inputs, missing data, contradictory requests).
|
|
42
|
-
*/
|
|
43
|
-
type EvalScenarioType = "regulatory" | "functional" | "adversarial";
|
|
44
|
-
/**
|
|
45
|
-
* A recorded conversation that can be replayed as an automated eval test.
|
|
46
|
-
* Messages use the AI SDK's UIMessage format — same as what the
|
|
47
|
-
* Export button in the chatbar produces.
|
|
48
|
-
*
|
|
49
|
-
* Two replay modes:
|
|
50
|
-
* - **"regenerate"** (default): Only user messages are sent.
|
|
51
|
-
* The LLM generates fresh responses at each turn. Assertions are
|
|
52
|
-
* auto-derived by comparing actual tool calls to the recorded ones.
|
|
53
|
-
*
|
|
54
|
-
* - **"inject"**: Prior turns are injected as-is, only the
|
|
55
|
-
* final user message gets a fresh LLM response.
|
|
56
|
-
*/
|
|
57
|
-
interface EvalScenario {
|
|
58
|
-
name: string;
|
|
59
|
-
type?: EvalScenarioType;
|
|
60
|
-
messages: UIMessage[];
|
|
61
|
-
mode?: "regenerate" | "inject";
|
|
62
|
-
/**
|
|
63
|
-
* Optional session-level outcome assertion.
|
|
64
|
-
* Checks that all listed tools were called at least once across the scenario.
|
|
65
|
-
*/
|
|
66
|
-
outcome?: {
|
|
67
|
-
toolsCalled: string[];
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* A scenario definition for dynamic multi-turn simulation.
|
|
72
|
-
* An LLM user simulator plays the persona while the agent
|
|
73
|
-
* tries to complete the flow through conversation.
|
|
74
|
-
*/
|
|
75
|
-
interface Scenario {
|
|
76
|
-
/** Human-readable name for this scenario. */
|
|
77
|
-
name: string;
|
|
78
|
-
/** Natural-language persona description fed to the user simulator LLM. */
|
|
79
|
-
persona: string;
|
|
80
|
-
/** The first user message that kicks off the conversation. */
|
|
81
|
-
openingMessage: string;
|
|
82
|
-
/** Language the simulated user speaks. */
|
|
83
|
-
language: "en" | "sv" | "fr" | "de";
|
|
84
|
-
/** Expected fields in the accumulated state at conversation end (for future evaluation). */
|
|
85
|
-
expectedState: Record<string, unknown>;
|
|
86
|
-
/** Tools that should be called at some point during the conversation (for future evaluation). */
|
|
87
|
-
expectedToolsCalled?: string[];
|
|
88
|
-
/** Maximum turns before considering the conversation stuck. Defaults to 15. */
|
|
89
|
-
maxTurns?: number;
|
|
90
|
-
}
|
|
91
|
-
/** A single turn in a simulated conversation. */
|
|
92
|
-
interface SimulationTurn {
|
|
93
|
-
userMessage: string;
|
|
94
|
-
assistantText: string;
|
|
95
|
-
toolsCalled: string[];
|
|
96
|
-
toolCallTraces: ToolCallTrace[];
|
|
97
|
-
}
|
|
98
|
-
/** Result of a dynamic scenario simulation run. */
|
|
99
|
-
interface SimulationResult {
|
|
100
|
-
/** Unique identifier for this simulation run. */
|
|
101
|
-
id: string;
|
|
102
|
-
/** Name of the scenario that was simulated. */
|
|
103
|
-
scenarioName: string;
|
|
104
|
-
/** Current status of the simulation. */
|
|
105
|
-
status: "pending" | "running" | "completed" | "failed";
|
|
106
|
-
/** All conversation turns. */
|
|
107
|
-
turns: SimulationTurn[];
|
|
108
|
-
/** Accumulated stateUpdates from all tool calls, deep-merged. */
|
|
109
|
-
accumulatedState: Record<string, unknown>;
|
|
110
|
-
/** Whether the flow reached completion. */
|
|
111
|
-
completed: boolean;
|
|
112
|
-
/** Total number of turns in the conversation. */
|
|
113
|
-
totalTurns: number;
|
|
114
|
-
/** Error message if status is "failed". */
|
|
115
|
-
error?: string;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Load all session replay JSON files from a directory.
|
|
120
|
-
* Drop any exported session JSON there — it just works.
|
|
121
|
-
*
|
|
122
|
-
* @param dir - Path to the sessions directory. Defaults to `evals/sessions`.
|
|
123
|
-
*/
|
|
124
|
-
/**
|
|
125
|
-
* Save an eval scenario JSON file to the scenarios directory.
|
|
126
|
-
*
|
|
127
|
-
* @param scenario - The scenario to save.
|
|
128
|
-
* @param dir - Path to the scenarios directory. Defaults to `evals/scenarios`.
|
|
129
|
-
* @returns The filename that was written.
|
|
130
|
-
*/
|
|
131
|
-
declare function saveScenario(scenario: EvalScenario, dir?: string): string;
|
|
132
|
-
declare function loadScenarios(dir?: string): EvalScenario[];
|
|
133
|
-
/**
|
|
134
|
-
* Send a single user message to a WaniWani MCP chat endpoint.
|
|
135
|
-
*/
|
|
136
|
-
declare function chat(url: string, message: string): Promise<ChatResult>;
|
|
137
|
-
/**
|
|
138
|
-
* Run a multi-turn conversation. Returns the result of each turn.
|
|
139
|
-
*/
|
|
140
|
-
declare function conversation(url: string, turns: ConversationTurn[]): Promise<ConversationResult>;
|
|
141
|
-
/**
|
|
142
|
-
* Replay a recorded eval scenario (exported from the chatbar debug button).
|
|
143
|
-
* Uses UIMessage[] directly — same format as useChat's messages array.
|
|
144
|
-
*
|
|
145
|
-
* **"regenerate" mode** (default):
|
|
146
|
-
* Sends only user messages. The LLM generates fresh responses.
|
|
147
|
-
* Per-turn assertions are auto-derived by comparing actual tool calls
|
|
148
|
-
* to the tool calls recorded in the scenario.
|
|
149
|
-
*
|
|
150
|
-
* **"inject" mode**:
|
|
151
|
-
* Injects the recorded conversation as-is, only generates a fresh
|
|
152
|
-
* response for the final user message.
|
|
153
|
-
*/
|
|
154
|
-
declare function replayScenario(url: string, scenario: EvalScenario): Promise<ConversationResult>;
|
|
155
|
-
|
|
156
|
-
export { type ChatResult, type ConversationResult, type ConversationTurn, type ConversationTurnResult, type EvalScenario, type EvalScenarioType, type Scenario, type SimulationResult, type SimulationTurn, type ToolCallTrace, type TurnAssertion, chat, conversation, loadScenarios, replayScenario, saveScenario };
|
package/dist/evals/index.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{mkdirSync as M,readdirSync as U,readFileSync as I,writeFileSync as R}from"fs";import{join as c}from"path";import{parseJsonEventStream as E,readUIMessageStream as j,uiMessageChunkSchema as b}from"ai";import{z as a}from"zod";var k=a.object({name:a.string(),type:a.enum(["regulatory","functional","tone"]).optional(),mode:a.enum(["synthetic","manual"]).optional(),outcome:a.object({toolsCalled:a.array(a.string())}).optional(),messages:a.array(a.looseObject({id:a.string(),role:a.enum(["user","assistant","system","data"]),parts:a.array(a.record(a.string(),a.unknown()))}))});function h(n){let t=n.parts.filter(e=>e.type==="text").map(e=>e.text).join(""),s=n.parts.filter(e=>e.type.startsWith("tool-")||e.type==="dynamic-tool").map(e=>e),o=s.map(e=>e.toolName),r=s.map(e=>({name:e.toolName,input:e.input??{},output:e.output}));return{output:t,toolsCalled:o,toolCallTraces:r}}function f(n){return n.parts.filter(t=>t.type==="text").map(t=>t.text).join("")}function N(n){return n.parts.filter(t=>t.type==="dynamic-tool"||t.type.startsWith("tool-")).map(t=>t.toolName).filter(Boolean)}async function p(n,t){let s=await fetch(`${n}/api/waniwani`,{method:"POST",headers:{"Content-Type":"application/json"},signal:AbortSignal.timeout(6e4),body:JSON.stringify({messages:t})});if(!s.ok)throw new Error(`Chat returned ${s.status}: ${await s.text()}`);if(!s.body)throw new Error("Chat response has no body");let o=E({stream:s.body,schema:b}).pipeThrough(new TransformStream({transform(e,i){e.success&&i.enqueue(e.value)}})),r;for await(let e of j({stream:o}))r=e;if(!r)throw new Error("No message received from stream");return{result:h(r),message:r}}function P(n,t="evals/scenarios"){let s=c(process.cwd(),t);M(s,{recursive:!0});let o=`${n.name}.json`;return R(c(s,o),JSON.stringify(n,null,2)),o}function A(n="evals/scenarios"){let t=c(process.cwd(),n);return U(t).filter(s=>s.endsWith(".json")).sort().map(s=>{let o=JSON.parse(I(c(t,s),"utf8"));return k.parse(o)})}async function O(n,t){let s={id:crypto.randomUUID(),role:"user",parts:[{type:"text",text:t}]},{result:o}=await p(n,[s]);return o}async function J(n,t){let s=[],o=[];for(let r of t){s.push({id:crypto.randomUUID(),role:"user",parts:[{type:"text",text:r.input}]});let{result:e,message:i}=await p(n,s);s.push(i),o.push({input:r.input,response:e,assertions:[]})}return{turns:o}}async function $(n,t){let s=t.mode??"regenerate",o=[],r=[],e=[];for(let i=0;i<t.messages.length;i++){let l=t.messages[i];if(l.role==="user"){let u=t.messages[i+1];e.push({userMsg:l,assistantMsg:u?.role==="assistant"?u:void 0})}}for(let i=0;i<e.length;i++){let{userMsg:l,assistantMsg:u}=e[i],S=i===e.length-1,m=u?N(u):[];if(o.push(l),s==="inject"&&!S&&u){o.push(u);let d=h(u),w=y(m,d.toolsCalled);r.push({input:f(l),response:d,assertions:w});continue}let{result:g,message:v}=await p(n,o);o.push(v);let C=y(m,g.toolsCalled);r.push({input:f(l),response:g,assertions:C})}return{turns:r}}function y(n,t){if(n.length===0)return[];let s=new Set(t);return[...new Set(n)].map(r=>({passed:s.has(r),expected:[r],actual:t}))}export{O as chat,J as conversation,A as loadScenarios,$ as replayScenario,P as saveScenario};
|
|
2
|
-
//# sourceMappingURL=index.js.map
|
package/dist/evals/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/evals/chat.ts"],"sourcesContent":["import { mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n\tparseJsonEventStream,\n\treadUIMessageStream,\n\ttype UIMessage,\n\tuiMessageChunkSchema,\n} from \"ai\";\nimport { z } from \"zod\";\nimport type {\n\tChatResult,\n\tConversationResult,\n\tConversationTurn,\n\tConversationTurnResult,\n\tEvalScenario,\n\tToolCallTrace,\n\tTurnAssertion,\n} from \"./types\";\n\n// UIMessage parts are heterogeneous — validate the fields we need, pass extras through\nconst evalScenarioSchema = z.object({\n\tname: z.string(),\n\ttype: z.enum([\"regulatory\", \"functional\", \"tone\"]).optional(),\n\tmode: z.enum([\"synthetic\", \"manual\"]).optional(),\n\toutcome: z.object({ toolsCalled: z.array(z.string()) }).optional(),\n\tmessages: z.array(\n\t\tz.looseObject({\n\t\t\tid: z.string(),\n\t\t\trole: z.enum([\"user\", \"assistant\", \"system\", \"data\"]),\n\t\t\tparts: z.array(z.record(z.string(), z.unknown())),\n\t\t}),\n\t),\n});\n\n// --- Internal helpers ---\n\nfunction parseUIMessage(msg: UIMessage): ChatResult {\n\tconst output = msg.parts\n\t\t.filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n\t\t.map((p) => p.text)\n\t\t.join(\"\");\n\n\tconst toolParts = msg.parts\n\t\t.filter((p) => p.type.startsWith(\"tool-\") || p.type === \"dynamic-tool\")\n\t\t.map(\n\t\t\t(p) =>\n\t\t\t\tp as unknown as {\n\t\t\t\t\ttoolName: string;\n\t\t\t\t\tinput?: Record<string, unknown>;\n\t\t\t\t\toutput?: unknown;\n\t\t\t\t},\n\t\t);\n\tconst toolsCalled = toolParts.map((p) => p.toolName);\n\tconst toolCallTraces: ToolCallTrace[] = toolParts.map((p) => ({\n\t\tname: p.toolName,\n\t\tinput: p.input ?? {},\n\t\toutput: p.output,\n\t}));\n\n\treturn { output, toolsCalled, toolCallTraces };\n}\n\nfunction textFromUIMessage(msg: UIMessage): string {\n\treturn msg.parts\n\t\t.filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n\t\t.map((p) => p.text)\n\t\t.join(\"\");\n}\n\n/** Extract the tool names called in a recorded assistant UIMessage. */\nfunction extractRecordedTools(msg: UIMessage): string[] {\n\treturn msg.parts\n\t\t.filter((p) => p.type === \"dynamic-tool\" || p.type.startsWith(\"tool-\"))\n\t\t.map((p) => (p as unknown as { toolName: string }).toolName)\n\t\t.filter(Boolean);\n}\n\nasync function sendMessages(\n\turl: string,\n\tmessages: UIMessage[],\n): Promise<{ result: ChatResult; message: UIMessage }> {\n\tconst response = await fetch(`${url}/api/waniwani`, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\tsignal: AbortSignal.timeout(60_000),\n\t\tbody: JSON.stringify({ messages }),\n\t});\n\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`Chat returned ${response.status}: ${await response.text()}`,\n\t\t);\n\t}\n\n\tif (!response.body) {\n\t\tthrow new Error(\"Chat response has no body\");\n\t}\n\n\tconst chunkStream = parseJsonEventStream({\n\t\tstream: response.body,\n\t\tschema: uiMessageChunkSchema,\n\t}).pipeThrough(\n\t\tnew TransformStream({\n\t\t\ttransform(chunk, controller) {\n\t\t\t\tif (chunk.success) {\n\t\t\t\t\tcontroller.enqueue(chunk.value);\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\t);\n\n\tlet finalMessage: UIMessage | undefined;\n\tfor await (const msg of readUIMessageStream({ stream: chunkStream })) {\n\t\tfinalMessage = msg;\n\t}\n\n\tif (!finalMessage) {\n\t\tthrow new Error(\"No message received from stream\");\n\t}\n\n\treturn { result: parseUIMessage(finalMessage), message: finalMessage };\n}\n\n// --- Public API ---\n\n/**\n * Load all session replay JSON files from a directory.\n * Drop any exported session JSON there — it just works.\n *\n * @param dir - Path to the sessions directory. Defaults to `evals/sessions`.\n */\n/**\n * Save an eval scenario JSON file to the scenarios directory.\n *\n * @param scenario - The scenario to save.\n * @param dir - Path to the scenarios directory. Defaults to `evals/scenarios`.\n * @returns The filename that was written.\n */\nexport function saveScenario(\n\tscenario: EvalScenario,\n\tdir = \"evals/scenarios\",\n): string {\n\tconst root = join(process.cwd(), dir);\n\tmkdirSync(root, { recursive: true });\n\tconst filename = `${scenario.name}.json`;\n\twriteFileSync(join(root, filename), JSON.stringify(scenario, null, 2));\n\treturn filename;\n}\n\nexport function loadScenarios(dir = \"evals/scenarios\"): EvalScenario[] {\n\tconst root = join(process.cwd(), dir);\n\treturn readdirSync(root)\n\t\t.filter((f) => f.endsWith(\".json\"))\n\t\t.sort()\n\t\t.map((f) => {\n\t\t\tconst raw = JSON.parse(readFileSync(join(root, f), \"utf8\"));\n\t\t\treturn evalScenarioSchema.parse(raw) as unknown as EvalScenario;\n\t\t});\n}\n\n/**\n * Send a single user message to a WaniWani MCP chat endpoint.\n */\nexport async function chat(url: string, message: string): Promise<ChatResult> {\n\tconst userMsg: UIMessage = {\n\t\tid: crypto.randomUUID(),\n\t\trole: \"user\",\n\t\tparts: [{ type: \"text\", text: message }],\n\t};\n\tconst { result } = await sendMessages(url, [userMsg]);\n\treturn result;\n}\n\n/**\n * Run a multi-turn conversation. Returns the result of each turn.\n */\nexport async function conversation(\n\turl: string,\n\tturns: ConversationTurn[],\n): Promise<ConversationResult> {\n\tconst history: UIMessage[] = [];\n\tconst turnResults: ConversationTurnResult[] = [];\n\n\tfor (const turn of turns) {\n\t\thistory.push({\n\t\t\tid: crypto.randomUUID(),\n\t\t\trole: \"user\",\n\t\t\tparts: [{ type: \"text\", text: turn.input }],\n\t\t});\n\n\t\tconst { result, message } = await sendMessages(url, history);\n\t\thistory.push(message);\n\n\t\tturnResults.push({ input: turn.input, response: result, assertions: [] });\n\t}\n\n\treturn { turns: turnResults };\n}\n\n/**\n * Replay a recorded eval scenario (exported from the chatbar debug button).\n * Uses UIMessage[] directly — same format as useChat's messages array.\n *\n * **\"regenerate\" mode** (default):\n * Sends only user messages. The LLM generates fresh responses.\n * Per-turn assertions are auto-derived by comparing actual tool calls\n * to the tool calls recorded in the scenario.\n *\n * **\"inject\" mode**:\n * Injects the recorded conversation as-is, only generates a fresh\n * response for the final user message.\n */\nexport async function replayScenario(\n\turl: string,\n\tscenario: EvalScenario,\n): Promise<ConversationResult> {\n\tconst mode = scenario.mode ?? \"regenerate\";\n\tconst history: UIMessage[] = [];\n\tconst turnResults: ConversationTurnResult[] = [];\n\n\t// Pair user messages with their assistant responses\n\tconst userTurns: { userMsg: UIMessage; assistantMsg?: UIMessage }[] = [];\n\tfor (let i = 0; i < scenario.messages.length; i++) {\n\t\tconst msg = scenario.messages[i];\n\t\tif (msg.role === \"user\") {\n\t\t\tconst next = scenario.messages[i + 1];\n\t\t\tuserTurns.push({\n\t\t\t\tuserMsg: msg,\n\t\t\t\tassistantMsg: next?.role === \"assistant\" ? next : undefined,\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (let turnIdx = 0; turnIdx < userTurns.length; turnIdx++) {\n\t\tconst { userMsg, assistantMsg } = userTurns[turnIdx];\n\t\tconst isLastTurn = turnIdx === userTurns.length - 1;\n\n\t\t// Extract expected tools from the recorded assistant message\n\t\tconst expectedTools = assistantMsg\n\t\t\t? extractRecordedTools(assistantMsg)\n\t\t\t: [];\n\n\t\thistory.push(userMsg);\n\n\t\tif (mode === \"inject\" && !isLastTurn && assistantMsg) {\n\t\t\thistory.push(assistantMsg);\n\t\t\tconst response = parseUIMessage(assistantMsg);\n\t\t\tconst assertions = buildAssertions(expectedTools, response.toolsCalled);\n\t\t\tturnResults.push({\n\t\t\t\tinput: textFromUIMessage(userMsg),\n\t\t\t\tresponse,\n\t\t\t\tassertions,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { result, message } = await sendMessages(url, history);\n\t\thistory.push(message);\n\n\t\tconst assertions = buildAssertions(expectedTools, result.toolsCalled);\n\t\tturnResults.push({\n\t\t\tinput: textFromUIMessage(userMsg),\n\t\t\tresponse: result,\n\t\t\tassertions,\n\t\t});\n\t}\n\n\treturn { turns: turnResults };\n}\n\n/** Compare expected vs. actual tool calls and return assertion results. */\nfunction buildAssertions(\n\texpected: string[],\n\tactual: string[],\n): TurnAssertion[] {\n\tif (expected.length === 0) {\n\t\treturn [];\n\t}\n\n\t// Group expected tools and check each against actual calls\n\tconst actualSet = new Set(actual);\n\tconst expectedUnique = [...new Set(expected)];\n\n\treturn expectedUnique.map((tool) => ({\n\t\tpassed: actualSet.has(tool),\n\t\texpected: [tool],\n\t\tactual,\n\t}));\n}\n"],"mappings":"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","names":["mkdirSync","readdirSync","readFileSync","writeFileSync","join","parseJsonEventStream","readUIMessageStream","uiMessageChunkSchema","z","evalScenarioSchema","parseUIMessage","msg","output","p","toolParts","toolsCalled","toolCallTraces","textFromUIMessage","extractRecordedTools","sendMessages","url","messages","response","chunkStream","chunk","controller","finalMessage","saveScenario","scenario","dir","root","filename","loadScenarios","f","raw","chat","message","userMsg","result","conversation","turns","history","turnResults","turn","replayScenario","mode","userTurns","next","turnIdx","assistantMsg","isLastTurn","expectedTools","assertions","buildAssertions","expected","actual","actualSet","tool"]}
|
package/dist/evals/scorers.d.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Create a local Braintrust reporter that writes JSON results to a directory and
|
|
3
|
-
* prints a summary to console.
|
|
4
|
-
*
|
|
5
|
-
* Requires the `braintrust` package: bun add -d braintrust
|
|
6
|
-
*
|
|
7
|
-
* @param outputDir - Directory to write JSON result files (default: "evals/runs")
|
|
8
|
-
*/
|
|
9
|
-
declare function createLocalReporter(outputDir?: string): unknown;
|
|
10
|
-
|
|
11
|
-
interface ToolCallTrace {
|
|
12
|
-
name: string;
|
|
13
|
-
input: Record<string, unknown>;
|
|
14
|
-
output: unknown;
|
|
15
|
-
}
|
|
16
|
-
interface ChatResult {
|
|
17
|
-
output: string;
|
|
18
|
-
toolsCalled: string[];
|
|
19
|
-
toolCallTraces: ToolCallTrace[];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Parse the JSON-stringified ChatResult from a Braintrust task output.
|
|
24
|
-
*/
|
|
25
|
-
declare function parseTaskOutput(output: unknown): ChatResult;
|
|
26
|
-
/**
|
|
27
|
-
* Checks whether the expected tool was called.
|
|
28
|
-
* Looks for the tool name in `metadata.expectedTool` first (for cases where `expected` is a
|
|
29
|
-
* reference answer), then falls back to `expected` directly.
|
|
30
|
-
*/
|
|
31
|
-
declare function calledExpectedTool({ output, expected, metadata, }: {
|
|
32
|
-
output: unknown;
|
|
33
|
-
expected?: unknown;
|
|
34
|
-
metadata?: Record<string, unknown>;
|
|
35
|
-
}): {
|
|
36
|
-
name: string;
|
|
37
|
-
score: number;
|
|
38
|
-
metadata: {
|
|
39
|
-
expected: string;
|
|
40
|
-
actual: string[];
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Checks whether the assistant produced any text output.
|
|
45
|
-
*/
|
|
46
|
-
declare function hasOutput({ output }: {
|
|
47
|
-
output: unknown;
|
|
48
|
-
}): {
|
|
49
|
-
name: string;
|
|
50
|
-
score: number;
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* Checks specific fields in the first tool call's `stateUpdates` against expected values.
|
|
54
|
-
* Supports nested fields via dot notation (e.g. "mixedBreed.knowsBreeds").
|
|
55
|
-
* Returns partial credit (fraction of matching fields).
|
|
56
|
-
*/
|
|
57
|
-
declare function toolInputFieldsMatch({ output, metadata, }: {
|
|
58
|
-
output: unknown;
|
|
59
|
-
metadata?: Record<string, unknown>;
|
|
60
|
-
}): {
|
|
61
|
-
name: string;
|
|
62
|
-
score: number;
|
|
63
|
-
metadata?: undefined;
|
|
64
|
-
} | {
|
|
65
|
-
name: string;
|
|
66
|
-
score: number;
|
|
67
|
-
metadata: Record<string, {
|
|
68
|
-
expected: unknown;
|
|
69
|
-
actual: unknown;
|
|
70
|
-
match: boolean;
|
|
71
|
-
}>;
|
|
72
|
-
};
|
|
73
|
-
/** ClosedQA — checks if the answer correctly addresses the question given a reference answer. */
|
|
74
|
-
declare const FaqAccuracy: (args: {
|
|
75
|
-
input: unknown;
|
|
76
|
-
output: unknown;
|
|
77
|
-
expected?: unknown;
|
|
78
|
-
}) => Promise<unknown>;
|
|
79
|
-
/** Factuality — checks if the output is factually consistent with the expected output. */
|
|
80
|
-
declare const OutputFactuality: (args: {
|
|
81
|
-
input: unknown;
|
|
82
|
-
output: unknown;
|
|
83
|
-
expected?: unknown;
|
|
84
|
-
}) => Promise<unknown>;
|
|
85
|
-
/** Moderation — flags unsafe or inappropriate content. */
|
|
86
|
-
declare const SafetyCheck: (args: {
|
|
87
|
-
input: unknown;
|
|
88
|
-
output: unknown;
|
|
89
|
-
expected?: unknown;
|
|
90
|
-
}) => Promise<unknown>;
|
|
91
|
-
|
|
92
|
-
export { FaqAccuracy, OutputFactuality, SafetyCheck, calledExpectedTool, createLocalReporter, hasOutput, parseTaskOutput, toolInputFieldsMatch };
|
package/dist/evals/scorers.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
var y=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(n,r)=>(typeof require<"u"?require:n)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});import{existsSync as S,mkdirSync as v,writeFileSync as T}from"fs";function c(t){try{return JSON.parse(t)}catch{return{output:"",toolsCalled:[],toolCallTraces:[]}}}function R({output:t,expected:n,metadata:r}){let e=c(t),s=r?.expectedTool??n;return{name:"called_expected_tool",score:e.toolsCalled.includes(s)?1:0,metadata:{expected:s,actual:e.toolsCalled}}}function C({output:t}){return{name:"has_output",score:c(t).output.length>0?1:0}}function O({output:t,metadata:n}){let r=c(t),e=n?.expectedFields??{},s=Object.keys(e);if(s.length===0)return{name:"field_extraction",score:1};let i=r.toolCallTraces[0]?.input?.stateUpdates??{},p=0,l={};for(let o of s){let a=e[o],u;if(o.includes(".")){let[k,h]=o.split(".");u=i[k]?.[h]}else u=i[o];let d=JSON.stringify(u)===JSON.stringify(a);d&&p++,l[o]={expected:a,actual:u,match:d}}return{name:"field_extraction",score:p/s.length,metadata:l}}function m(t){return async n=>{let r=c(n.output);return t({input:n.input,output:r.output,expected:n.expected})}}async function g(t){return(await import("autoevals").catch(()=>{throw new Error(`LLM scorer "${t}" requires the "autoevals" package: bun add -d autoevals`)}))[t]}var b=async t=>m(await g("ClosedQA"))(t),F=async t=>m(await g("Factuality"))(t),$=async t=>m(await g("Moderation"))(t);function A(t="evals/runs"){let n;try{n=y("braintrust").Reporter}catch{throw new Error('Local reporter requires the "braintrust" package: bun add -d braintrust')}return S(t)||v(t,{recursive:!0}),n("local",{reportEval(r,e){let s=r.experimentName??"unknown",w=new Date().toISOString().replace(/[:.]/g,"-"),i=e.results.map(o=>{let a=o.scores??{},u=c(o.output);return{input:o.input,output:u.output,toolsCalled:u.toolsCalled,toolCallTraces:u.toolCallTraces,scores:a}}),p=`${t}/${s}-${w}.json`;T(p,JSON.stringify(i,null,2)),console.log(`
|
|
2
|
-
\u{1F4CA} ${s} (${e.results.length} cases):
|
|
3
|
-
`);let l=0;for(let o of e.results){let a=o.scores??{},u=a.called_expected_tool===1;u||l++,console.log(` ${u?"\u2705":"\u274C"} ${o.input.slice(0,70)}`);for(let[d,k]of Object.entries(a))console.log(` ${d}: ${k}`)}return console.log(`
|
|
4
|
-
${e.results.length-l}/${e.results.length} passed`),console.log(` \u2192 ${p}
|
|
5
|
-
`),l===0},reportRun(r){let e=r.every(s=>s===!0);return console.log(e?`
|
|
6
|
-
\u2705 All experiments passed`:`
|
|
7
|
-
\u274C Some experiments failed`),e}})}export{b as FaqAccuracy,F as OutputFactuality,$ as SafetyCheck,R as calledExpectedTool,A as createLocalReporter,C as hasOutput,c as parseTaskOutput,O as toolInputFieldsMatch};
|
|
8
|
-
//# sourceMappingURL=scorers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/evals/reporter.ts","../../src/evals/scorers.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { parseTaskOutput } from \"./scorers\";\n\ntype ReporterFn = (\n\tname: string,\n\thandlers: {\n\t\treportEval(\n\t\t\tevaluator: unknown,\n\t\t\tresult: {\n\t\t\t\tresults: Array<{\n\t\t\t\t\tinput: unknown;\n\t\t\t\t\toutput: unknown;\n\t\t\t\t\tscores?: Record<string, number>;\n\t\t\t\t}>;\n\t\t\t},\n\t\t): boolean;\n\t\treportRun(results: boolean[]): boolean;\n\t},\n) => unknown;\n\n/**\n * Create a local Braintrust reporter that writes JSON results to a directory and\n * prints a summary to console.\n *\n * Requires the `braintrust` package: bun add -d braintrust\n *\n * @param outputDir - Directory to write JSON result files (default: \"evals/runs\")\n */\nexport function createLocalReporter(outputDir = \"evals/runs\") {\n\tlet Reporter: ReporterFn;\n\ttry {\n\t\tReporter = (require(\"braintrust\") as { Reporter: ReporterFn }).Reporter;\n\t} catch {\n\t\tthrow new Error(\n\t\t\t'Local reporter requires the \"braintrust\" package: bun add -d braintrust',\n\t\t);\n\t}\n\n\tif (!existsSync(outputDir)) {\n\t\tmkdirSync(outputDir, { recursive: true });\n\t}\n\n\treturn Reporter(\"local\", {\n\t\treportEval(\n\t\t\tevaluator: unknown,\n\t\t\tresult: {\n\t\t\t\tresults: Array<{\n\t\t\t\t\tinput: unknown;\n\t\t\t\t\toutput: unknown;\n\t\t\t\t\tscores?: Record<string, number>;\n\t\t\t\t}>;\n\t\t\t},\n\t\t) {\n\t\t\tconst name =\n\t\t\t\t(evaluator as { experimentName?: string }).experimentName ?? \"unknown\";\n\t\t\tconst timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n\t\t\tconst rows = result.results.map((r) => {\n\t\t\t\tconst scores = r.scores ?? {};\n\t\t\t\tconst parsed = parseTaskOutput(r.output);\n\t\t\t\treturn {\n\t\t\t\t\tinput: r.input,\n\t\t\t\t\toutput: parsed.output,\n\t\t\t\t\ttoolsCalled: parsed.toolsCalled,\n\t\t\t\t\ttoolCallTraces: parsed.toolCallTraces,\n\t\t\t\t\tscores,\n\t\t\t\t};\n\t\t\t});\n\n\t\t\tconst outPath = `${outputDir}/${name}-${timestamp}.json`;\n\t\t\twriteFileSync(outPath, JSON.stringify(rows, null, 2));\n\n\t\t\tconsole.log(`\\n📊 ${name} (${result.results.length} cases):\\n`);\n\n\t\t\tlet failures = 0;\n\t\t\tfor (const r of result.results) {\n\t\t\t\tconst scores = r.scores ?? {};\n\t\t\t\tconst pass = scores.called_expected_tool === 1;\n\t\t\t\tif (!pass) {\n\t\t\t\t\tfailures++;\n\t\t\t\t}\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ${pass ? \"✅\" : \"❌\"} ${(r.input as string).slice(0, 70)}`,\n\t\t\t\t);\n\t\t\t\tfor (const [scoreName, value] of Object.entries(scores)) {\n\t\t\t\t\tconsole.log(` ${scoreName}: ${value}`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconsole.log(\n\t\t\t\t`\\n ${result.results.length - failures}/${result.results.length} passed`,\n\t\t\t);\n\t\t\tconsole.log(` → ${outPath}\\n`);\n\t\t\treturn failures === 0;\n\t\t},\n\n\t\treportRun(results: boolean[]) {\n\t\t\tconst allPassed = results.every((r) => r === true);\n\t\t\tconsole.log(\n\t\t\t\tallPassed\n\t\t\t\t\t? \"\\n✅ All experiments passed\"\n\t\t\t\t\t: \"\\n❌ Some experiments failed\",\n\t\t\t);\n\t\t\treturn allPassed;\n\t\t},\n\t});\n}\n","import type { ChatResult } from \"./types\";\n\n/**\n * Parse the JSON-stringified ChatResult from a Braintrust task output.\n */\nexport function parseTaskOutput(output: unknown): ChatResult {\n\ttry {\n\t\treturn JSON.parse(output as string);\n\t} catch {\n\t\treturn { output: \"\", toolsCalled: [], toolCallTraces: [] };\n\t}\n}\n\n/**\n * Checks whether the expected tool was called.\n * Looks for the tool name in `metadata.expectedTool` first (for cases where `expected` is a\n * reference answer), then falls back to `expected` directly.\n */\nexport function calledExpectedTool({\n\toutput,\n\texpected,\n\tmetadata,\n}: {\n\toutput: unknown;\n\texpected?: unknown;\n\tmetadata?: Record<string, unknown>;\n}) {\n\tconst parsed = parseTaskOutput(output);\n\tconst expectedTool =\n\t\t(metadata?.expectedTool as string) ?? (expected as string);\n\tconst found = parsed.toolsCalled.includes(expectedTool);\n\treturn {\n\t\tname: \"called_expected_tool\",\n\t\tscore: found ? 1 : 0,\n\t\tmetadata: { expected: expectedTool, actual: parsed.toolsCalled },\n\t};\n}\n\n/**\n * Checks whether the assistant produced any text output.\n */\nexport function hasOutput({ output }: { output: unknown }) {\n\tconst parsed = parseTaskOutput(output);\n\treturn {\n\t\tname: \"has_output\",\n\t\tscore: parsed.output.length > 0 ? 1 : 0,\n\t};\n}\n\n/**\n * Checks specific fields in the first tool call's `stateUpdates` against expected values.\n * Supports nested fields via dot notation (e.g. \"mixedBreed.knowsBreeds\").\n * Returns partial credit (fraction of matching fields).\n */\nexport function toolInputFieldsMatch({\n\toutput,\n\tmetadata,\n}: {\n\toutput: unknown;\n\tmetadata?: Record<string, unknown>;\n}) {\n\tconst parsed = parseTaskOutput(output);\n\tconst expectedFields = (metadata?.expectedFields ?? {}) as Record<\n\t\tstring,\n\t\tunknown\n\t>;\n\tconst fieldNames = Object.keys(expectedFields);\n\n\tif (fieldNames.length === 0) {\n\t\treturn { name: \"field_extraction\", score: 1 };\n\t}\n\n\tconst trace = parsed.toolCallTraces[0];\n\tconst stateUpdates = (trace?.input?.stateUpdates ?? {}) as Record<\n\t\tstring,\n\t\tunknown\n\t>;\n\n\tlet matches = 0;\n\tconst details: Record<\n\t\tstring,\n\t\t{ expected: unknown; actual: unknown; match: boolean }\n\t> = {};\n\n\tfor (const field of fieldNames) {\n\t\tconst expected = expectedFields[field];\n\t\tlet actual: unknown;\n\n\t\tif (field.includes(\".\")) {\n\t\t\tconst [parent, child] = field.split(\".\");\n\t\t\tactual = (stateUpdates[parent] as Record<string, unknown>)?.[child];\n\t\t} else {\n\t\t\tactual = stateUpdates[field];\n\t\t}\n\n\t\tconst match = JSON.stringify(actual) === JSON.stringify(expected);\n\t\tif (match) {\n\t\t\tmatches++;\n\t\t}\n\t\tdetails[field] = { expected, actual, match };\n\t}\n\n\treturn {\n\t\tname: \"field_extraction\",\n\t\tscore: matches / fieldNames.length,\n\t\tmetadata: details,\n\t};\n}\n\n/**\n * Wraps an autoevals scorer to extract the text output from the JSON-stringified ChatResult.\n * Requires the `autoevals` package: bun add -d autoevals\n */\nfunction wrapAutoeval(\n\tscorer: (args: {\n\t\tinput: unknown;\n\t\toutput: string;\n\t\texpected?: unknown;\n\t}) => unknown,\n) {\n\treturn async (args: {\n\t\tinput: unknown;\n\t\toutput: unknown;\n\t\texpected?: unknown;\n\t}) => {\n\t\tconst parsed = parseTaskOutput(args.output);\n\t\treturn scorer({\n\t\t\tinput: args.input,\n\t\t\toutput: parsed.output,\n\t\t\texpected: args.expected,\n\t\t});\n\t};\n}\n\n// LLM-based scorers — require `autoevals` as a dev dependency.\n// These are dynamically imported so the module loads even if autoevals is not installed.\n// Using LLM scorers without autoevals installed will throw at call time.\n\nasync function getAutoeval(name: string) {\n\tconst mod = await import(\"autoevals\").catch(() => {\n\t\tthrow new Error(\n\t\t\t`LLM scorer \"${name}\" requires the \"autoevals\" package: bun add -d autoevals`,\n\t\t);\n\t});\n\treturn (mod as Record<string, unknown>)[name] as (args: {\n\t\tinput: unknown;\n\t\toutput: string;\n\t\texpected?: unknown;\n\t}) => unknown;\n}\n\n/** ClosedQA — checks if the answer correctly addresses the question given a reference answer. */\nexport const FaqAccuracy = async (args: {\n\tinput: unknown;\n\toutput: unknown;\n\texpected?: unknown;\n}): Promise<unknown> => wrapAutoeval(await getAutoeval(\"ClosedQA\"))(args);\n\n/** Factuality — checks if the output is factually consistent with the expected output. */\nexport const OutputFactuality = async (args: {\n\tinput: unknown;\n\toutput: unknown;\n\texpected?: unknown;\n}): Promise<unknown> => wrapAutoeval(await getAutoeval(\"Factuality\"))(args);\n\n/** Moderation — flags unsafe or inappropriate content. */\nexport const SafetyCheck = async (args: {\n\tinput: unknown;\n\toutput: unknown;\n\texpected?: unknown;\n}): Promise<unknown> => wrapAutoeval(await getAutoeval(\"Moderation\"))(args);\n"],"mappings":"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","names":["existsSync","mkdirSync","writeFileSync","parseTaskOutput","output","calledExpectedTool","expected","metadata","parsed","expectedTool","hasOutput","toolInputFieldsMatch","expectedFields","fieldNames","stateUpdates","matches","details","field","actual","parent","child","match","wrapAutoeval","scorer","args","getAutoeval","name","FaqAccuracy","OutputFactuality","SafetyCheck","createLocalReporter","outputDir","Reporter","existsSync","mkdirSync","evaluator","result","name","timestamp","rows","r","scores","parsed","parseTaskOutput","outPath","writeFileSync","failures","pass","scoreName","value","results","allPassed"]}
|
|
@@ -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) {\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: read body.scrollHeight + body margins ---\n\t\t\t\t// We use document.body.scrollHeight rather than collapsing\n\t\t\t\t// <html> and reading its scrollHeight, because in an iframe\n\t\t\t\t// document.documentElement.scrollHeight never drops below\n\t\t\t\t// the viewport height (set by the parent iframe element),\n\t\t\t\t// causing a ratchet effect where the iframe only ever grows.\n\t\t\t\t// scrollHeight excludes the body's own margins, so we add\n\t\t\t\t// them back to avoid clipping.\n\t\t\t\tconst bodyStyle = getComputedStyle(document.body);\n\t\t\t\tconst bodyMargins =\n\t\t\t\t\tparseFloat(bodyStyle.marginTop) + parseFloat(bodyStyle.marginBottom);\n\t\t\t\tconst height = Math.ceil(document.body.scrollHeight + bodyMargins);\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":";AACA,OAAS,OAAAA,EAAK,wBAAAC,MAA4B,iCAkBnC,IAAMC,EAAN,KAAyD,CACvD,IACA,mBAA4D,KAC5D,mCAEE,KACF,oBAAuD,KACvD,0BACP,KACO,YACA,iBAAsC,KACtC,cAAqC,KAE7C,aAAc,CACb,KAAK,IAAM,IAAIF,EACd,CAAE,KAAM,kBAAmB,QAAS,OAAQ,EAC5C,CAAC,EACD,CAAE,WAAY,EAAM,CACrB,EAGA,KAAK,IAAI,aAAgBG,GAAW,CACnC,IAAMC,EAAYD,EACZE,EACL,OAAOD,EAAU,OAAU,UAAYA,EAAU,QAAU,KACvDA,EAAU,MACX,KACEE,EACL,OAAOF,EAAU,MAAS,UAAYA,EAAU,OAAS,KACrDA,EAAU,KACX,KACEG,EAAeF,GAAkBC,GAAQ,OAEzCE,EAAqB,CAC1B,QAASL,EAAO,QAChB,kBAAmBA,EAAO,kBAG1B,MAAOI,EACP,QACC,OAAOH,EAAU,SAAY,UAC1BA,EAAU,QACV,MACL,EACA,KAAK,iBAAmBI,EACxB,KAAK,qBAAqBA,CAAM,EAChC,KAAK,qCAAqCA,EAAO,OAAS,IAAI,CAC/D,EAEA,KAAK,IAAI,qBAAwBL,GAAW,CAC3C,KAAK,YAAc,CAAE,GAAG,KAAK,YAAa,GAAGA,CAAO,EAChDA,EAAO,OACV,KAAK,sBAAsBA,EAAO,KAAc,EAE7CA,EAAO,aACV,KAAK,4BAA4BA,EAAO,WAA0B,CAEpE,CACD,CAEA,MAAM,SAAyB,CAC9B,MAAM,KAAK,IAAI,QACd,IAAIF,EAAqB,OAAO,OAAQ,OAAO,MAAM,CACtD,EACA,KAAK,YAAc,KAAK,IAAI,eAAe,EAC3C,KAAK,cAAgB,KAAK,gBAAgB,CAC3C,CAEA,MAAM,OAAuB,CAC5B,KAAK,gBAAgB,EACrB,KAAK,cAAgB,KACrB,MAAM,KAAK,IAAI,MAAM,CACtB,CAOQ,iBAA8B,CACrC,IAAIQ,EAAa,GACbC,EAAY,EACZC,EAAa,EAEXC,EAAU,IAAM,CACjBH,IAGJA,EAAa,GACb,sBAAsB,IAAM,CAC3BA,EAAa,GACb,IAAMI,EAAK,SAAS,gBAGdC,EAAaD,EAAG,MAAM,MAC5BA,EAAG,MAAM,MAAQ,cACjB,IAAME,EAAUF,EAAG,sBAAsB,EACzCA,EAAG,MAAM,MAAQC,EACjB,IAAME,EAAe,OAAO,WAAaH,EAAG,YACtCI,EAAQ,KAAK,KAAKF,EAAQ,MAAQC,CAAY,EAU9CE,EAAY,iBAAiB,SAAS,IAAI,EAC1CC,EACL,WAAWD,EAAU,SAAS,EAAI,WAAWA,EAAU,YAAY,EAC9DE,EAAS,KAAK,KAAK,SAAS,KAAK,aAAeD,CAAW,GAE7DF,IAAUP,GAAaU,IAAWT,KACrCD,EAAYO,EACZN,EAAaS,EACb,KAAK,IAAI,gBAAgB,CAAE,MAAAH,EAAO,OAAAG,CAAO,CAAC,EAE5C,CAAC,EACF,EAEAR,EAAQ,EACR,IAAMS,EAAW,IAAI,eAAeT,CAAO,EAC3C,OAAAS,EAAS,QAAQ,SAAS,eAAe,EACzCA,EAAS,QAAQ,SAAS,IAAI,EACvB,IAAMA,EAAS,WAAW,CAClC,CAEA,eAAuD,CAGtD,OAAI,KAAK,kBAAkB,kBACnB,KAAK,iBAAiB,kBAEvB,IACR,CAEA,aAAaC,EAAoD,CAChE,YAAK,mBAAqBA,EACnB,IAAM,CACZ,KAAK,mBAAqB,IAC3B,CACD,CAEA,MAAM,SACLC,EACAC,EAC0B,CAC1B,IAAMhB,EAAS,MAAM,KAAK,IAAI,eAAe,CAC5C,KAAAe,EACA,UAAWC,CACZ,CAAC,EACD,MAAO,CACN,QAAShB,EAAO,QAChB,kBAAmBA,EAAO,kBAG1B,MAAOA,EAAO,MACd,QAAS,OAAOA,EAAO,SAAY,UAAYA,EAAO,QAAU,MACjE,CACD,CAEA,aAAaiB,EAAmB,CAC/B,KAAK,IAAI,aAAa,CAAE,IAAAA,CAAI,CAAC,EAAE,MAAOC,GAAiB,CACtD,QAAQ,MAAM,uBAAwBA,CAAG,CAC1C,CAAC,CACF,CAEA,aAAaC,EAAsB,CAClC,KAAK,IACH,YAAY,CACZ,KAAM,OACN,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAMA,CAAO,CAAC,CACzC,CAAC,EACA,MAAOD,GAAiB,CACxB,QAAQ,MAAM,oCAAqCA,CAAG,CACvD,CAAC,CACH,CAEA,mBAAmBE,EAA4C,CAC9D,OAAO,KAAK,IACV,mBAAmB,CACnB,GAAIA,EAAQ,QAAU,CAAE,QAASA,EAAQ,OAAQ,EAAI,CAAC,EACtD,GAAIA,EAAQ,kBACT,CAAE,kBAAmBA,EAAQ,iBAAkB,EAC/C,CAAC,CACL,CAAC,EACA,KAAK,IAAG,EAAY,CACvB,CAEA,UAAkB,CACjB,OAAQ,KAAK,aAAa,OAAmB,OAC9C,CAEA,cAAcN,EAA8C,CAC3D,YAAK,oBAAsBA,EACpB,IAAM,CACZ,KAAK,oBAAsB,IAC5B,CACD,CAEA,WAAoB,CACnB,OAAQ,KAAK,aAAa,QAAiC,IAC5D,CAEA,gBAA8B,CAC7B,OAAQ,KAAK,aAAa,aAA+B,QAC1D,CAEA,MAAM,mBAAmBO,EAAyC,CAEjE,OADe,MAAM,KAAK,IAAI,mBAAmB,CAAE,KAAAA,CAAK,CAAC,GAC3C,IACf,CAEA,oBAAoBP,EAAmD,CACtE,YAAK,0BAA4BA,EAC1B,IAAM,CACZ,KAAK,0BAA4B,IAClC,CACD,CAGA,aAA+B,CAC9B,OAAO,IACR,CAGA,kBAA+B,CAC9B,MAAO,IAAM,CAAC,CACf,CAGA,cAA8B,CAC7B,OAAO,IACR,CAGA,mBAAgC,CAC/B,MAAO,IAAM,CAAC,CACf,CAGA,yBAAgD,CAC/C,OAAO,KAAK,kBAAkB,OAAS,IACxC,CAGA,6BACCA,EACa,CACb,YAAK,mCAAqCA,EACnC,IAAM,CACZ,KAAK,mCAAqC,IAC3C,CACD,CAGA,gBAAuC,CACtC,OAAO,IACR,CAGA,qBAAkC,CACjC,MAAO,IAAM,CAAC,CACf,CACD","names":["App","PostMessageTransport","MCPAppsWidgetClient","params","rawParams","underscoreMeta","meta","resolvedMeta","result","rafPending","lastWidth","lastHeight","measure","el","savedWidth","fitRect","scrollbarGap","width","bodyStyle","bodyMargins","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 { App, PostMessageTransport } from \"@modelcontextprotocol/ext-apps\";\nimport {\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\tprivate app: App;\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\tconstructor() {\n\t\tthis.app = new App(\n\t\t\t{ name: \"WaniWani Widget\", version: \"1.0.0\" },\n\t\t\t{},\n\t\t\t{ autoResize: false },\n\t\t);\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\tawait this.app.connect(\n\t\t\tnew PostMessageTransport(window.parent, window.parent),\n\t\t);\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.app.close();\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): Promise<void> {\n\t\tconst hiddenContext = formatModelContextForPrompt(this.pendingModelContext);\n\t\tthis.pendingModelContext = null;\n\t\tconst message = hiddenContext ? `${prompt}\\n\\n${hiddenContext}` : prompt;\n\t\treturn this.app\n\t\t\t.sendMessage({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: [{ type: \"text\", text: message }],\n\t\t\t})\n\t\t\t.then(() => undefined);\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":["App","PostMessageTransport","OpenAIWidgetClient","key","fallback","callback","transform","handler","event","value","SET_GLOBALS_EVENT_TYPE","App","PostMessageTransport","v","name","args","url","prompt","hiddenContext","formatModelContextForPrompt","message","context","mergeModelContext","mode"]}
|
|
File without changes
|