@runtypelabs/persona 4.28.0 → 4.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/dist/{approval-ui-QAKWNFNM.js → approval-ui-OBBI62ES.js} +1 -1
- package/dist/approval-ui.cjs +2 -2
- package/dist/approval-ui.d.cts +7 -5
- package/dist/approval-ui.d.ts +7 -5
- package/dist/approval-ui.js +2 -2
- package/dist/artifacts-ui.d.cts +7 -5
- package/dist/artifacts-ui.d.ts +7 -5
- package/dist/{chunk-NQLDCJAP.js → chunk-D4TDKCT5.js} +2 -2
- package/dist/chunk-FNXK3VTC.js +1 -0
- package/dist/{client-history-LV3KHEFA.js → client-history-QGAFMCBE.js} +1 -1
- package/dist/client-history.js +1 -1
- package/dist/{client-stream-N22JHTLE.js → client-stream-WXD2FL23.js} +1 -1
- package/dist/client-stream.js +3 -3
- package/dist/codegen.cjs +4 -4
- package/dist/codegen.js +5 -5
- package/dist/context-mentions.d.cts +7 -5
- package/dist/context-mentions.d.ts +7 -5
- package/dist/event-stream-view.d.cts +7 -5
- package/dist/event-stream-view.d.ts +7 -5
- package/dist/forms-ui.d.cts +7 -5
- package/dist/forms-ui.d.ts +7 -5
- package/dist/index.cjs +40 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -30
- package/dist/index.d.ts +32 -30
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +41 -41
- package/dist/index.js.map +1 -1
- package/dist/session-reconnect.d.cts +7 -5
- package/dist/session-reconnect.d.ts +7 -5
- package/dist/smart-dom-reader.d.cts +7 -5
- package/dist/smart-dom-reader.d.ts +7 -5
- package/dist/theme-editor-preview.cjs +51 -51
- package/dist/theme-editor-preview.d.cts +7 -5
- package/dist/theme-editor-preview.d.ts +7 -5
- package/dist/theme-editor-preview.js +4 -4
- package/dist/theme-editor.d.cts +8 -6
- package/dist/theme-editor.d.ts +8 -6
- package/dist/{voice-runtime-LVUMPUDS.js → voice-runtime-TWFJ4UUS.js} +1 -1
- package/dist/voice-runtime.cjs +1 -1
- package/dist/voice-runtime.d.cts +7 -5
- package/dist/voice-runtime.d.ts +7 -5
- package/dist/voice-runtime.js +1 -1
- package/dist/webmcp-runtime-5Q3IHAHP.js +6 -0
- package/dist/webmcp-runtime.cjs +2 -2
- package/dist/webmcp-runtime.d.cts +22 -26
- package/dist/webmcp-runtime.d.ts +22 -26
- package/dist/webmcp-runtime.js +2 -2
- package/package.json +5 -2
- package/src/generated/runtype-openapi-contract.ts +3 -0
- package/src/theme-editor/webmcp/types.ts +1 -1
- package/src/types.ts +7 -5
- package/src/webmcp-bridge.test.ts +87 -21
- package/src/webmcp-bridge.ts +21 -26
- package/src/webmcp-polyfill.integration.test.ts +339 -0
- package/src/webmcp-polyfill.ts +7 -4
- package/src/webmcp-runtime-bundle.test.ts +1 -1
- package/src/webmcp-runtime-entry.ts +34 -19
- package/dist/chunk-AALCT54S.js +0 -1
- package/dist/webmcp-runtime-V6ZWW3PI.js +0 -6
package/dist/voice-runtime.d.cts
CHANGED
|
@@ -3281,9 +3281,8 @@ type WebMcpConfirmInfo = {
|
|
|
3281
3281
|
};
|
|
3282
3282
|
/**
|
|
3283
3283
|
* Why the confirm was requested. Currently always `'gate'`: the default
|
|
3284
|
-
* confirm-by-default gate that fires before every `webmcp:*` call.
|
|
3285
|
-
*
|
|
3286
|
-
* internally, so Persona no longer surfaces a nested in-tool confirm.)
|
|
3284
|
+
* confirm-by-default gate that fires before every `webmcp:*` call. Tool
|
|
3285
|
+
* callbacks on v6 receive an AbortSignal, not a nested confirmation API.
|
|
3287
3286
|
*/
|
|
3288
3287
|
reason: 'gate';
|
|
3289
3288
|
};
|
|
@@ -9554,8 +9553,11 @@ type AgentWidgetConfig = {
|
|
|
9554
9553
|
/**
|
|
9555
9554
|
* WebMCP: consume page-registered tools (`document.modelContext.registerTool`).
|
|
9556
9555
|
* When `enabled`, the widget installs `@mcp-b/webmcp-polyfill`, snapshots the
|
|
9557
|
-
* registry on every dispatch, ships it as `clientTools[]`,
|
|
9558
|
-
* returned `webmcp:*`
|
|
9556
|
+
* current document's registry on every dispatch, ships it as `clientTools[]`,
|
|
9557
|
+
* and executes returned `webmcp:*` calls with confirm-by-default gating.
|
|
9558
|
+
* Supports host-installed v5 JSON-string and v6 object-input contracts.
|
|
9559
|
+
* The automatic fallback stays on v5 to preserve existing browser support
|
|
9560
|
+
* and callback-result behavior.
|
|
9559
9561
|
*
|
|
9560
9562
|
* Server-side policy on the chat surface is the source of truth: these
|
|
9561
9563
|
* fields layer on top.
|
package/dist/voice-runtime.d.ts
CHANGED
|
@@ -3281,9 +3281,8 @@ type WebMcpConfirmInfo = {
|
|
|
3281
3281
|
};
|
|
3282
3282
|
/**
|
|
3283
3283
|
* Why the confirm was requested. Currently always `'gate'`: the default
|
|
3284
|
-
* confirm-by-default gate that fires before every `webmcp:*` call.
|
|
3285
|
-
*
|
|
3286
|
-
* internally, so Persona no longer surfaces a nested in-tool confirm.)
|
|
3284
|
+
* confirm-by-default gate that fires before every `webmcp:*` call. Tool
|
|
3285
|
+
* callbacks on v6 receive an AbortSignal, not a nested confirmation API.
|
|
3287
3286
|
*/
|
|
3288
3287
|
reason: 'gate';
|
|
3289
3288
|
};
|
|
@@ -9554,8 +9553,11 @@ type AgentWidgetConfig = {
|
|
|
9554
9553
|
/**
|
|
9555
9554
|
* WebMCP: consume page-registered tools (`document.modelContext.registerTool`).
|
|
9556
9555
|
* When `enabled`, the widget installs `@mcp-b/webmcp-polyfill`, snapshots the
|
|
9557
|
-
* registry on every dispatch, ships it as `clientTools[]`,
|
|
9558
|
-
* returned `webmcp:*`
|
|
9556
|
+
* current document's registry on every dispatch, ships it as `clientTools[]`,
|
|
9557
|
+
* and executes returned `webmcp:*` calls with confirm-by-default gating.
|
|
9558
|
+
* Supports host-installed v5 JSON-string and v6 object-input contracts.
|
|
9559
|
+
* The automatic fallback stays on v5 to preserve existing browser support
|
|
9560
|
+
* and callback-result behavior.
|
|
9559
9561
|
*
|
|
9560
9562
|
* Server-side policy on the chat surface is the source of truth: these
|
|
9561
9563
|
* fields layer on top.
|
package/dist/voice-runtime.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var L=class{#e=null;#i=0;#r=[];#n=[];#c=[];#l=!1;#m=!1;#y=0;#o=!1;#p=!1;#d;#t=[];#b=0;#_=!1;#a;#u;#g;#h=null;constructor(e=24e3,t={}){this.#u=e;let s=Math.max(0,t.prebufferMs??0);this.#g=Math.round(e*s/1e3),this.#d=this.#g>0}#w(){if(!this.#e){let t=typeof window<"u"?window:void 0;if(!t)throw new Error("AudioPlaybackManager requires a browser environment");let s=t.AudioContext||t.webkitAudioContext;this.#e=new s({sampleRate:this.#u})}let e=this.#e;return e.state==="suspended"&&!this.#p&&e.resume(),e}enqueue(e){if(e.length===0)return;let t=e;if(this.#h){let i=new Uint8Array(this.#h.length+e.length);i.set(this.#h),i.set(e,this.#h.length),t=i,this.#h=null}if(t.length%2!==0&&(this.#h=new Uint8Array([t[t.length-1]]),t=t.subarray(0,t.length-1)),t.length===0)return;let s=this.#f(t);s.length!==0&&(this.#d?(this.#t.push(s),this.#b+=s.length,clearTimeout(this.#a),this.#b>=this.#g?this.#S():this.#_&&(this.#a=setTimeout(()=>this.#S(),this.#g/this.#u*1e3))):this.#A(s))}markStreamEnd(){this.#t.length>0&&this.#S(),this.#m=!0,this.#k()}flush(){for(let e of this.#r){e.onended=null;try{e.stop(),e.disconnect()}catch{}}this.#r=[],this.#y=0,this.#i=0,this.#l=!1,this.#m=!1,this.#n=[],this.#c=[],this.#h=null,this.#t=[],this.#b=0,this.#d=this.#g>0,this.#o=!1,clearTimeout(this.#a)}setContinuousMode(e){this.#_=e}isPlaying(){return this.#l}onFinished(e){this.#n.push(e)}onStarted(e){this.#c.push(e)}pause(){this.#p=!0,this.#e&&this.#e.state==="running"&&this.#e.suspend()}resume(){this.#p=!1,this.#e&&this.#e.state==="suspended"&&this.#e.resume()}async destroy(){this.flush(),this.#e&&(await this.#e.close(),this.#e=null)}#S(){this.#d=!1;let e=this.#t;this.#t=[],this.#b=0;for(let t of e)this.#A(t)}#A(e){if(e.length===0)return;let t=this.#w(),s=t.createBuffer(1,e.length,this.#u);s.getChannelData(0).set(e);let i=t.createBufferSource();i.buffer=s,i.connect(t.destination);let r=t.currentTime;if(this.#i===0?this.#i=r:this.#i<r&&(this.#i=r,this.#g>0&&(this.#d=!0)),i.start(this.#i),this.#i+=s.duration,this.#r.push(i),this.#y++,this.#l=!0,!this.#o){this.#o=!0;let l=this.#c.slice();this.#c=[];for(let d of l)d()}i.onended=()=>{let l=this.#r.indexOf(i);l!==-1&&(this.#r.splice(l,1),this.#y--,this.#k())}}#k(){if(this.#m&&this.#y<=0&&this.#t.length===0){this.#l=!1,this.#m=!1;let e=this.#n.slice();this.#n=[];for(let t of e)t()}}#f(e){let t=Math.floor(e.length/2),s=new Float32Array(t),i=new DataView(e.buffer,e.byteOffset,e.byteLength);for(let r=0;r<t;r++){let l=i.getInt16(r*2,!0);s[r]=l/32768}return s}};var ae="4.28.
|
|
1
|
+
var L=class{#e=null;#i=0;#r=[];#n=[];#c=[];#l=!1;#m=!1;#y=0;#o=!1;#p=!1;#d;#t=[];#b=0;#_=!1;#a;#u;#g;#h=null;constructor(e=24e3,t={}){this.#u=e;let s=Math.max(0,t.prebufferMs??0);this.#g=Math.round(e*s/1e3),this.#d=this.#g>0}#w(){if(!this.#e){let t=typeof window<"u"?window:void 0;if(!t)throw new Error("AudioPlaybackManager requires a browser environment");let s=t.AudioContext||t.webkitAudioContext;this.#e=new s({sampleRate:this.#u})}let e=this.#e;return e.state==="suspended"&&!this.#p&&e.resume(),e}enqueue(e){if(e.length===0)return;let t=e;if(this.#h){let i=new Uint8Array(this.#h.length+e.length);i.set(this.#h),i.set(e,this.#h.length),t=i,this.#h=null}if(t.length%2!==0&&(this.#h=new Uint8Array([t[t.length-1]]),t=t.subarray(0,t.length-1)),t.length===0)return;let s=this.#f(t);s.length!==0&&(this.#d?(this.#t.push(s),this.#b+=s.length,clearTimeout(this.#a),this.#b>=this.#g?this.#S():this.#_&&(this.#a=setTimeout(()=>this.#S(),this.#g/this.#u*1e3))):this.#A(s))}markStreamEnd(){this.#t.length>0&&this.#S(),this.#m=!0,this.#k()}flush(){for(let e of this.#r){e.onended=null;try{e.stop(),e.disconnect()}catch{}}this.#r=[],this.#y=0,this.#i=0,this.#l=!1,this.#m=!1,this.#n=[],this.#c=[],this.#h=null,this.#t=[],this.#b=0,this.#d=this.#g>0,this.#o=!1,clearTimeout(this.#a)}setContinuousMode(e){this.#_=e}isPlaying(){return this.#l}onFinished(e){this.#n.push(e)}onStarted(e){this.#c.push(e)}pause(){this.#p=!0,this.#e&&this.#e.state==="running"&&this.#e.suspend()}resume(){this.#p=!1,this.#e&&this.#e.state==="suspended"&&this.#e.resume()}async destroy(){this.flush(),this.#e&&(await this.#e.close(),this.#e=null)}#S(){this.#d=!1;let e=this.#t;this.#t=[],this.#b=0;for(let t of e)this.#A(t)}#A(e){if(e.length===0)return;let t=this.#w(),s=t.createBuffer(1,e.length,this.#u);s.getChannelData(0).set(e);let i=t.createBufferSource();i.buffer=s,i.connect(t.destination);let r=t.currentTime;if(this.#i===0?this.#i=r:this.#i<r&&(this.#i=r,this.#g>0&&(this.#d=!0)),i.start(this.#i),this.#i+=s.duration,this.#r.push(i),this.#y++,this.#l=!0,!this.#o){this.#o=!0;let l=this.#c.slice();this.#c=[];for(let d of l)d()}i.onended=()=>{let l=this.#r.indexOf(i);l!==-1&&(this.#r.splice(l,1),this.#y--,this.#k())}}#k(){if(this.#m&&this.#y<=0&&this.#t.length===0){this.#l=!1,this.#m=!1;let e=this.#n.slice();this.#n=[];for(let t of e)t()}}#f(e){let t=Math.floor(e.length/2),s=new Float32Array(t),i=new DataView(e.buffer,e.byteOffset,e.byteLength);for(let r=0;r<t;r++){let l=i.getInt16(r*2,!0);s[r]=l/32768}return s}};var ae="4.28.1";var ce=ae;var Y=16e3,_e=24e3,Ee=4096,xe=Y*2*8,Ie=4,Pe=1380533830,Ve=3e4,Re=1e3,je=5e3,Le=3e4,Ne=3e4,Oe=6e5,Ue="full-duplex-v1",De=300,Be=2e3,qe=2e3,$e="runtype-browser-v1",We=54e4,He="You're talking to an AI assistant. Voice is processed by OpenAI.",Fe=new Map([["idle_timeout","Voice call ended after a quiet period."],["max_duration","This voice call reached its time limit."],["provider_ended","The voice session ended."],["quota","Voice is unavailable right now."],["auth_expired","Voice session expired. Tap the mic to reconnect."]]),le=["provider_error","server_restart"],N="Voice connection lost.",ze=8e3,Xe=4e3,Ge=12,de=2e3;function Ke(n,e){let t="Conversation so far:",s=e.slice(0,Xe).trim(),i=ze-(s?s.length+2:0)-t.length,r=[];for(let d of n.slice(-Ge).reverse()){let a=d.content.replace(/\s+/g," ").trim();if(!a)continue;a.length>de&&(a=`${a.slice(0,de-1)}\u2026`);let o=`${d.role==="user"?"User":"Assistant"}: ${a}`;if(o.length+1>i)break;i-=o.length+1,r.unshift(o)}let l=r.length>0?[`${t}
|
|
2
2
|
${r.join(`
|
|
3
3
|
`)}`]:[];return s&&l.push(s),l.join(`
|
|
4
4
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
var C="webmcp:",w=t=>t.startsWith(C)?t.slice(C.length):t,u={warn(t,...e){typeof console<"u"&&typeof console.warn=="function"&&console.warn(`[Persona/WebMCP] ${t}`,...e)}},b=class{constructor(e,n){this.config=e;this.#e=n,this.#o=e.onConfirm??null,this.#r=3e4}#o;#r;#t=!1;#i=null;#l=!1;#e;setConfirmHandler(e){this.#o=e}isOperational(){return this.config.enabled!==!0||!this.#t?!1:this.#n()!==null}async snapshotForDispatch(){if(await this.#s(),this.config.enabled!==!0)return[];let e=this.#n();if(!e)return[];let n;try{n=(await e.getTools()).filter(h)}catch(i){return u.warn("getTools() threw: shipping an empty WebMCP snapshot.",i),[]}this.#e.recordToolDisplayTitles(n);let o=typeof location<"u"?location.origin:"";return n.filter(i=>this.#c(i.name)).map(i=>{let l=P(i.annotations);return{name:i.name,description:i.description,parametersSchema:W(i.inputSchema),origin:"webmcp",...o?{pageOrigin:o}:{},...l?{annotations:l}:{},...l?.untrustedContentHint===!0?{untrustedContentHint:!0}:{}}})}async executeToolCall(e,n,o){if(await this.#s(),this.config.enabled!==!0)return s("WebMCP is not enabled on this widget.");let i=this.#n();if(!i){let r=typeof document<"u"&&!!document.modelContext;return s(r?"WebMCP is not operational: document.modelContext is present but does not expose the strict getTools()/executeTool() surface (likely a different or older WebMCP polyfill).":"WebMCP bridge is not operational on this page (document.modelContext not available).")}let l=w(e),c;try{c=(await i.getTools()).filter(h)}catch(r){let p=r instanceof Error?r.message:String(r);return s(`Failed to read WebMCP registry: ${p}`)}this.#e.recordToolDisplayTitles(c);let f=c.find(r=>r.name===l);if(!f)return s(`WebMCP tool not registered on this page: ${l}`);if(!this.#c(l))return s(`WebMCP tool not allowed by client allowlist: ${l}`);if(o?.aborted)return s("Aborted by cancel()");let m=this.#e.getToolDisplayTitle(l),M={toolName:l,args:n,description:f.description,...m?{title:m}:{},reason:"gate"};if(!await this.#u(M))return s("User declined the tool call.");if(o?.aborted)return s("Aborted by cancel()");let a=new AbortController,y=!1,T=setTimeout(()=>{y=!0,a.abort()},this.#r),g=()=>a.abort();o&&(o.aborted?a.abort():o.addEventListener("abort",g,{once:!0}));try{let r=await i.executeTool(f,O(n),{signal:a.signal});return A(r)}catch(r){if(y)return s(`WebMCP tool '${l}' timed out after ${this.#r}ms`);if(o?.aborted)return s("Aborted by cancel()");let p=r instanceof Error?r.message:String(r);return s(p)}finally{clearTimeout(T),o&&o.removeEventListener("abort",g)}}#s(){return this.config.enabled!==!0?Promise.resolve():(this.#i||(this.#i=this.#a()),this.#i)}async#a(){try{if(this.#n()){this.#t=!0;return}let e=await this.#e.loadPolyfill();"initializeWebMCPPolyfill"in e?e.initializeWebMCPPolyfill():e.installWebMCP(),this.#t=!0}catch(e){u.warn("Failed to load @mcp-b/webmcp-polyfill: WebMCP consumption disabled.",e),this.#t=!1}}#n(){if(typeof document>"u")return null;let e=document.modelContext;if(!e||typeof e!="object")return null;let n=e;return typeof n.getTools!="function"||typeof n.executeTool!="function"?(this.#l||(this.#l=!0,u.warn("document.modelContext is present but does not expose getTools()/executeTool(): WebMCP consumption is disabled. Another (incompatible or older) WebMCP polyfill likely installed document.modelContext before Persona. Remove it, or use a polyfill implementing the strict standard surface (e.g. @mcp-b/webmcp-polyfill).")),null):e}async#u(e){let n=this.#o??k;try{return await n(e)}catch(o){return u.warn(`Confirm handler threw for WebMCP tool '${e.toolName}'; declining.`,o),!1}}#c(e){let n=this.config.allowlist;return!n||n.length===0?!0:n.some(o=>x(e,o))}},x=(t,e)=>{if(e==="*")return!0;let n=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&");return new RegExp("^"+n.replace(/\*/g,".*")+"$").test(t)},d={type:"object",properties:{}},P=t=>{if(!t||typeof t!="object")return;let e={...typeof t.readOnlyHint=="boolean"?{readOnlyHint:t.readOnlyHint}:{},...typeof t.untrustedContentHint=="boolean"?{untrustedContentHint:t.untrustedContentHint}:{}};return Object.keys(e).length>0?e:void 0},W=t=>{if(t===void 0||t==="")return{...d};if(typeof t=="object")return t!==null&&!Array.isArray(t)?t:{...d};try{let e=JSON.parse(t);return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{...d}}catch{return{...d}}},A=t=>{if(t==null)return{content:[{type:"text",text:""}]};let e;try{e=JSON.parse(t)}catch{return{content:[{type:"text",text:t}]}}return e!==null&&typeof e=="object"&&Array.isArray(e.content)?e:{content:[{type:"text",text:typeof e=="string"?e:D(e)}]}},O=t=>{let e;try{e=JSON.stringify(t)??"{}"}catch{e="{}"}let n=JSON.parse(e);if(n===null||typeof n!="object")throw new TypeError("WebMCP tool arguments must be an object or array.");return Object.defineProperty(n,Symbol.toPrimitive,{value:()=>e}),n},s=t=>({isError:!0,content:[{type:"text",text:t}]}),k=async t=>{if(typeof window>"u"||typeof window.confirm!="function")return!1;let e=S(t.args),n=`Allow the AI to call ${t.toolName}`+(e?`
|
|
2
|
+
|
|
3
|
+
Arguments:
|
|
4
|
+
${e}`:"")+(t.description?`
|
|
5
|
+
|
|
6
|
+
${t.description}`:"");return window.confirm(n)},S=t=>{if(t==null)return"";try{let e=JSON.stringify(t,null,2);return e.length>500?e.slice(0,500)+"\u2026":e}catch{return String(t)}},h=t=>(t.window===void 0||typeof window<"u"&&t.window===window)&&(t.origin===void 0||typeof location<"u"&&t.origin===location.origin),D=t=>{if(t===void 0)return"";try{return JSON.stringify(t)}catch{return String(t)}};export{b as WebMcpBridge};
|
package/dist/webmcp-runtime.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";var m=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var
|
|
1
|
+
"use strict";var m=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var A=(t,e)=>{for(var n in e)m(t,n,{get:e[n],enumerable:!0})},O=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of P(e))!W.call(t,r)&&r!==n&&m(t,r,{get:()=>e[r],enumerable:!(o=x(e,r))||o.enumerable});return t};var k=t=>O(m({},"__esModule",{value:!0}),t);var N={};A(N,{WebMcpBridge:()=>f});module.exports=k(N);var h="webmcp:",S=t=>t.startsWith(h)?t.slice(h.length):t,u={warn(t,...e){typeof console<"u"&&typeof console.warn=="function"&&console.warn(`[Persona/WebMCP] ${t}`,...e)}},f=class{constructor(e,n){this.config=e;this.#e=n,this.#o=e.onConfirm??null,this.#r=3e4}#o;#r;#t=!1;#i=null;#l=!1;#e;setConfirmHandler(e){this.#o=e}isOperational(){return this.config.enabled!==!0||!this.#t?!1:this.#n()!==null}async snapshotForDispatch(){if(await this.#s(),this.config.enabled!==!0)return[];let e=this.#n();if(!e)return[];let n;try{n=(await e.getTools()).filter(M)}catch(r){return u.warn("getTools() threw: shipping an empty WebMCP snapshot.",r),[]}this.#e.recordToolDisplayTitles(n);let o=typeof location<"u"?location.origin:"";return n.filter(r=>this.#c(r.name)).map(r=>{let l=I(r.annotations);return{name:r.name,description:r.description,parametersSchema:j(r.inputSchema),origin:"webmcp",...o?{pageOrigin:o}:{},...l?{annotations:l}:{},...l?.untrustedContentHint===!0?{untrustedContentHint:!0}:{}}})}async executeToolCall(e,n,o){if(await this.#s(),this.config.enabled!==!0)return s("WebMCP is not enabled on this widget.");let r=this.#n();if(!r){let i=typeof document<"u"&&!!document.modelContext;return s(i?"WebMCP is not operational: document.modelContext is present but does not expose the strict getTools()/executeTool() surface (likely a different or older WebMCP polyfill).":"WebMCP bridge is not operational on this page (document.modelContext not available).")}let l=S(e),c;try{c=(await r.getTools()).filter(M)}catch(i){let b=i instanceof Error?i.message:String(i);return s(`Failed to read WebMCP registry: ${b}`)}this.#e.recordToolDisplayTitles(c);let p=c.find(i=>i.name===l);if(!p)return s(`WebMCP tool not registered on this page: ${l}`);if(!this.#c(l))return s(`WebMCP tool not allowed by client allowlist: ${l}`);if(o?.aborted)return s("Aborted by cancel()");let y=this.#e.getToolDisplayTitle(l),T={toolName:l,args:n,description:p.description,...y?{title:y}:{},reason:"gate"};if(!await this.#u(T))return s("User declined the tool call.");if(o?.aborted)return s("Aborted by cancel()");let a=new AbortController,g=!1,w=setTimeout(()=>{g=!0,a.abort()},this.#r),C=()=>a.abort();o&&(o.aborted?a.abort():o.addEventListener("abort",C,{once:!0}));try{let i=await r.executeTool(p,v(n),{signal:a.signal});return H(i)}catch(i){if(g)return s(`WebMCP tool '${l}' timed out after ${this.#r}ms`);if(o?.aborted)return s("Aborted by cancel()");let b=i instanceof Error?i.message:String(i);return s(b)}finally{clearTimeout(w),o&&o.removeEventListener("abort",C)}}#s(){return this.config.enabled!==!0?Promise.resolve():(this.#i||(this.#i=this.#a()),this.#i)}async#a(){try{if(this.#n()){this.#t=!0;return}let e=await this.#e.loadPolyfill();"initializeWebMCPPolyfill"in e?e.initializeWebMCPPolyfill():e.installWebMCP(),this.#t=!0}catch(e){u.warn("Failed to load @mcp-b/webmcp-polyfill: WebMCP consumption disabled.",e),this.#t=!1}}#n(){if(typeof document>"u")return null;let e=document.modelContext;if(!e||typeof e!="object")return null;let n=e;return typeof n.getTools!="function"||typeof n.executeTool!="function"?(this.#l||(this.#l=!0,u.warn("document.modelContext is present but does not expose getTools()/executeTool(): WebMCP consumption is disabled. Another (incompatible or older) WebMCP polyfill likely installed document.modelContext before Persona. Remove it, or use a polyfill implementing the strict standard surface (e.g. @mcp-b/webmcp-polyfill).")),null):e}async#u(e){let n=this.#o??E;try{return await n(e)}catch(o){return u.warn(`Confirm handler threw for WebMCP tool '${e.toolName}'; declining.`,o),!1}}#c(e){let n=this.config.allowlist;return!n||n.length===0?!0:n.some(o=>D(e,o))}},D=(t,e)=>{if(e==="*")return!0;let n=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&");return new RegExp("^"+n.replace(/\*/g,".*")+"$").test(t)},d={type:"object",properties:{}},I=t=>{if(!t||typeof t!="object")return;let e={...typeof t.readOnlyHint=="boolean"?{readOnlyHint:t.readOnlyHint}:{},...typeof t.untrustedContentHint=="boolean"?{untrustedContentHint:t.untrustedContentHint}:{}};return Object.keys(e).length>0?e:void 0},j=t=>{if(t===void 0||t==="")return{...d};if(typeof t=="object")return t!==null&&!Array.isArray(t)?t:{...d};try{let e=JSON.parse(t);return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{...d}}catch{return{...d}}},H=t=>{if(t==null)return{content:[{type:"text",text:""}]};let e;try{e=JSON.parse(t)}catch{return{content:[{type:"text",text:t}]}}return e!==null&&typeof e=="object"&&Array.isArray(e.content)?e:{content:[{type:"text",text:typeof e=="string"?e:L(e)}]}},v=t=>{let e;try{e=JSON.stringify(t)??"{}"}catch{e="{}"}let n=JSON.parse(e);if(n===null||typeof n!="object")throw new TypeError("WebMCP tool arguments must be an object or array.");return Object.defineProperty(n,Symbol.toPrimitive,{value:()=>e}),n},s=t=>({isError:!0,content:[{type:"text",text:t}]}),E=async t=>{if(typeof window>"u"||typeof window.confirm!="function")return!1;let e=$(t.args),n=`Allow the AI to call ${t.toolName}`+(e?`
|
|
2
2
|
|
|
3
3
|
Arguments:
|
|
4
4
|
${e}`:"")+(t.description?`
|
|
5
5
|
|
|
6
|
-
${t.description}`:"");return window.confirm(n)}
|
|
6
|
+
${t.description}`:"");return window.confirm(n)},$=t=>{if(t==null)return"";try{let e=JSON.stringify(t,null,2);return e.length>500?e.slice(0,500)+"\u2026":e}catch{return String(t)}},M=t=>(t.window===void 0||typeof window<"u"&&t.window===window)&&(t.origin===void 0||typeof location<"u"&&t.origin===location.origin),L=t=>{if(t===void 0)return"";try{return JSON.stringify(t)}catch{return String(t)}};0&&(module.exports={WebMcpBridge});
|
|
@@ -60,9 +60,8 @@ type WebMcpConfirmInfo = {
|
|
|
60
60
|
};
|
|
61
61
|
/**
|
|
62
62
|
* Why the confirm was requested. Currently always `'gate'`: the default
|
|
63
|
-
* confirm-by-default gate that fires before every `webmcp:*` call.
|
|
64
|
-
*
|
|
65
|
-
* internally, so Persona no longer surfaces a nested in-tool confirm.)
|
|
63
|
+
* confirm-by-default gate that fires before every `webmcp:*` call. Tool
|
|
64
|
+
* callbacks on v6 receive an AbortSignal, not a nested confirmation API.
|
|
66
65
|
*/
|
|
67
66
|
reason: 'gate';
|
|
68
67
|
};
|
|
@@ -153,26 +152,19 @@ type AgentWidgetWebMcpConfig = {
|
|
|
153
152
|
* enforcement live on the Runtype API; this bridge mirrors those checks
|
|
154
153
|
* client-side as a usability convenience, not a security boundary.
|
|
155
154
|
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* - `getTools()`: async; returns `{ name, description, inputSchema }` where
|
|
162
|
-
* `inputSchema` is a JSON *string*. Annotations are not exposed here.
|
|
163
|
-
* - `executeTool(toolInfo, inputArgsJson, { signal })`: async; validates args
|
|
164
|
-
* against the tool's schema, runs `execute()`, and returns the raw result as
|
|
165
|
-
* a JSON *string* (or `null` for `undefined`). Honors `signal` for abort.
|
|
155
|
+
* Supports v5's JSON-string input and v6's object input with a single call:
|
|
156
|
+
* the runtime passes a JSON object that also string-coerces to JSON text.
|
|
157
|
+
* Never infer the execution contract from metadata or retry a failed call.
|
|
158
|
+
* Only tools owned by this document are exposed: the wire addresses tools by
|
|
159
|
+
* name, not by frame. Callbacks must validate their own input.
|
|
166
160
|
*
|
|
167
|
-
* The
|
|
168
|
-
*
|
|
169
|
-
|
|
170
|
-
*
|
|
161
|
+
* The automatic fallback stays on v5 to preserve its browser requirements and
|
|
162
|
+
* result semantics. Host pages may install v5 or v6 themselves; Persona does
|
|
163
|
+
* not replace an existing context. v5's initializeWebMCPPolyfill() and v6's
|
|
164
|
+
* installWebMCP() are both accepted by custom loaders.
|
|
171
165
|
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* the spec's `client.requestUserInteraction` callback internally; Persona cannot
|
|
175
|
-
* inject a nested confirm there, so the single outer gate is the whole story.)
|
|
166
|
+
* Every call passes one confirm gate before execution, regardless of
|
|
167
|
+
* annotations.readOnlyHint. v6 callbacks also receive an invocation signal.
|
|
176
168
|
*/
|
|
177
169
|
|
|
178
170
|
/**
|
|
@@ -193,18 +185,20 @@ interface ModelContextToolInfo {
|
|
|
193
185
|
* object. `@mcp-b/webmcp-polyfill` made the switch in v5, and Chrome ships it
|
|
194
186
|
* from 154.0.8013 (cross-document tools first) -- but Chrome 149-153, most of
|
|
195
187
|
* the Origin Trial population, and 154's same-document tools still emit the
|
|
196
|
-
* string. Both
|
|
188
|
+
* string. Both input execution contracts are supported independently of
|
|
189
|
+
* schema representation.
|
|
197
190
|
*
|
|
198
191
|
* Absent when the tool registered no schema: v5 omits the member, where v4
|
|
199
192
|
* always emitted a `{"type":"object"}` string.
|
|
200
193
|
*/
|
|
201
194
|
inputSchema?: object | string;
|
|
195
|
+
/** Owning frame and origin, when supplied by the registry. Never sent on the wire. */
|
|
196
|
+
window?: Window;
|
|
197
|
+
origin?: string;
|
|
202
198
|
/**
|
|
203
199
|
* Display title declared on the tool (`ToolDescriptor.title` in the WebMCP
|
|
204
200
|
* spec). The polyfill returns `""` when the tool didn't declare one. Note:
|
|
205
|
-
* `
|
|
206
|
-
* this strict consumer surface: top-level `title` is the only display-name
|
|
207
|
-
* channel available to us.
|
|
201
|
+
* top-level `title` is the display-name channel, not `annotations.title`.
|
|
208
202
|
*/
|
|
209
203
|
title?: string;
|
|
210
204
|
/**
|
|
@@ -221,6 +215,8 @@ interface ModelContextToolInfo {
|
|
|
221
215
|
/** The slice of `@mcp-b/webmcp-polyfill` the bridge consumes on install. */
|
|
222
216
|
type WebMcpPolyfillModule = {
|
|
223
217
|
initializeWebMCPPolyfill: () => void;
|
|
218
|
+
} | {
|
|
219
|
+
installWebMCP: () => void;
|
|
224
220
|
};
|
|
225
221
|
|
|
226
222
|
/**
|
|
@@ -287,7 +283,7 @@ declare class WebMcpBridge {
|
|
|
287
283
|
* - tool not in registry (e.g. unmounted between snapshot and call)
|
|
288
284
|
* - tool excluded by the client allowlist
|
|
289
285
|
* - user declined the confirm gate
|
|
290
|
-
* - `execute()` threw or
|
|
286
|
+
* - `execute()` threw or returned a non-serializable result
|
|
291
287
|
* - `execute()` exceeded the 30s timeout
|
|
292
288
|
* - `signal` fired (session-level `cancel()`)
|
|
293
289
|
*
|
package/dist/webmcp-runtime.d.ts
CHANGED
|
@@ -60,9 +60,8 @@ type WebMcpConfirmInfo = {
|
|
|
60
60
|
};
|
|
61
61
|
/**
|
|
62
62
|
* Why the confirm was requested. Currently always `'gate'`: the default
|
|
63
|
-
* confirm-by-default gate that fires before every `webmcp:*` call.
|
|
64
|
-
*
|
|
65
|
-
* internally, so Persona no longer surfaces a nested in-tool confirm.)
|
|
63
|
+
* confirm-by-default gate that fires before every `webmcp:*` call. Tool
|
|
64
|
+
* callbacks on v6 receive an AbortSignal, not a nested confirmation API.
|
|
66
65
|
*/
|
|
67
66
|
reason: 'gate';
|
|
68
67
|
};
|
|
@@ -153,26 +152,19 @@ type AgentWidgetWebMcpConfig = {
|
|
|
153
152
|
* enforcement live on the Runtype API; this bridge mirrors those checks
|
|
154
153
|
* client-side as a usability convenience, not a security boundary.
|
|
155
154
|
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* - `getTools()`: async; returns `{ name, description, inputSchema }` where
|
|
162
|
-
* `inputSchema` is a JSON *string*. Annotations are not exposed here.
|
|
163
|
-
* - `executeTool(toolInfo, inputArgsJson, { signal })`: async; validates args
|
|
164
|
-
* against the tool's schema, runs `execute()`, and returns the raw result as
|
|
165
|
-
* a JSON *string* (or `null` for `undefined`). Honors `signal` for abort.
|
|
155
|
+
* Supports v5's JSON-string input and v6's object input with a single call:
|
|
156
|
+
* the runtime passes a JSON object that also string-coerces to JSON text.
|
|
157
|
+
* Never infer the execution contract from metadata or retry a failed call.
|
|
158
|
+
* Only tools owned by this document are exposed: the wire addresses tools by
|
|
159
|
+
* name, not by frame. Callbacks must validate their own input.
|
|
166
160
|
*
|
|
167
|
-
* The
|
|
168
|
-
*
|
|
169
|
-
|
|
170
|
-
*
|
|
161
|
+
* The automatic fallback stays on v5 to preserve its browser requirements and
|
|
162
|
+
* result semantics. Host pages may install v5 or v6 themselves; Persona does
|
|
163
|
+
* not replace an existing context. v5's initializeWebMCPPolyfill() and v6's
|
|
164
|
+
* installWebMCP() are both accepted by custom loaders.
|
|
171
165
|
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* the spec's `client.requestUserInteraction` callback internally; Persona cannot
|
|
175
|
-
* inject a nested confirm there, so the single outer gate is the whole story.)
|
|
166
|
+
* Every call passes one confirm gate before execution, regardless of
|
|
167
|
+
* annotations.readOnlyHint. v6 callbacks also receive an invocation signal.
|
|
176
168
|
*/
|
|
177
169
|
|
|
178
170
|
/**
|
|
@@ -193,18 +185,20 @@ interface ModelContextToolInfo {
|
|
|
193
185
|
* object. `@mcp-b/webmcp-polyfill` made the switch in v5, and Chrome ships it
|
|
194
186
|
* from 154.0.8013 (cross-document tools first) -- but Chrome 149-153, most of
|
|
195
187
|
* the Origin Trial population, and 154's same-document tools still emit the
|
|
196
|
-
* string. Both
|
|
188
|
+
* string. Both input execution contracts are supported independently of
|
|
189
|
+
* schema representation.
|
|
197
190
|
*
|
|
198
191
|
* Absent when the tool registered no schema: v5 omits the member, where v4
|
|
199
192
|
* always emitted a `{"type":"object"}` string.
|
|
200
193
|
*/
|
|
201
194
|
inputSchema?: object | string;
|
|
195
|
+
/** Owning frame and origin, when supplied by the registry. Never sent on the wire. */
|
|
196
|
+
window?: Window;
|
|
197
|
+
origin?: string;
|
|
202
198
|
/**
|
|
203
199
|
* Display title declared on the tool (`ToolDescriptor.title` in the WebMCP
|
|
204
200
|
* spec). The polyfill returns `""` when the tool didn't declare one. Note:
|
|
205
|
-
* `
|
|
206
|
-
* this strict consumer surface: top-level `title` is the only display-name
|
|
207
|
-
* channel available to us.
|
|
201
|
+
* top-level `title` is the display-name channel, not `annotations.title`.
|
|
208
202
|
*/
|
|
209
203
|
title?: string;
|
|
210
204
|
/**
|
|
@@ -221,6 +215,8 @@ interface ModelContextToolInfo {
|
|
|
221
215
|
/** The slice of `@mcp-b/webmcp-polyfill` the bridge consumes on install. */
|
|
222
216
|
type WebMcpPolyfillModule = {
|
|
223
217
|
initializeWebMCPPolyfill: () => void;
|
|
218
|
+
} | {
|
|
219
|
+
installWebMCP: () => void;
|
|
224
220
|
};
|
|
225
221
|
|
|
226
222
|
/**
|
|
@@ -287,7 +283,7 @@ declare class WebMcpBridge {
|
|
|
287
283
|
* - tool not in registry (e.g. unmounted between snapshot and call)
|
|
288
284
|
* - tool excluded by the client allowlist
|
|
289
285
|
* - user declined the confirm gate
|
|
290
|
-
* - `execute()` threw or
|
|
286
|
+
* - `execute()` threw or returned a non-serializable result
|
|
291
287
|
* - `execute()` exceeded the 30s timeout
|
|
292
288
|
* - `signal` fired (session-level `cancel()`)
|
|
293
289
|
*
|
package/dist/webmcp-runtime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
1
|
+
var C="webmcp:",w=t=>t.startsWith(C)?t.slice(C.length):t,u={warn(t,...e){typeof console<"u"&&typeof console.warn=="function"&&console.warn(`[Persona/WebMCP] ${t}`,...e)}},b=class{constructor(e,n){this.config=e;this.#e=n,this.#o=e.onConfirm??null,this.#r=3e4}#o;#r;#t=!1;#i=null;#l=!1;#e;setConfirmHandler(e){this.#o=e}isOperational(){return this.config.enabled!==!0||!this.#t?!1:this.#n()!==null}async snapshotForDispatch(){if(await this.#s(),this.config.enabled!==!0)return[];let e=this.#n();if(!e)return[];let n;try{n=(await e.getTools()).filter(h)}catch(i){return u.warn("getTools() threw: shipping an empty WebMCP snapshot.",i),[]}this.#e.recordToolDisplayTitles(n);let o=typeof location<"u"?location.origin:"";return n.filter(i=>this.#c(i.name)).map(i=>{let l=P(i.annotations);return{name:i.name,description:i.description,parametersSchema:W(i.inputSchema),origin:"webmcp",...o?{pageOrigin:o}:{},...l?{annotations:l}:{},...l?.untrustedContentHint===!0?{untrustedContentHint:!0}:{}}})}async executeToolCall(e,n,o){if(await this.#s(),this.config.enabled!==!0)return s("WebMCP is not enabled on this widget.");let i=this.#n();if(!i){let r=typeof document<"u"&&!!document.modelContext;return s(r?"WebMCP is not operational: document.modelContext is present but does not expose the strict getTools()/executeTool() surface (likely a different or older WebMCP polyfill).":"WebMCP bridge is not operational on this page (document.modelContext not available).")}let l=w(e),c;try{c=(await i.getTools()).filter(h)}catch(r){let p=r instanceof Error?r.message:String(r);return s(`Failed to read WebMCP registry: ${p}`)}this.#e.recordToolDisplayTitles(c);let f=c.find(r=>r.name===l);if(!f)return s(`WebMCP tool not registered on this page: ${l}`);if(!this.#c(l))return s(`WebMCP tool not allowed by client allowlist: ${l}`);if(o?.aborted)return s("Aborted by cancel()");let m=this.#e.getToolDisplayTitle(l),M={toolName:l,args:n,description:f.description,...m?{title:m}:{},reason:"gate"};if(!await this.#u(M))return s("User declined the tool call.");if(o?.aborted)return s("Aborted by cancel()");let a=new AbortController,y=!1,T=setTimeout(()=>{y=!0,a.abort()},this.#r),g=()=>a.abort();o&&(o.aborted?a.abort():o.addEventListener("abort",g,{once:!0}));try{let r=await i.executeTool(f,O(n),{signal:a.signal});return A(r)}catch(r){if(y)return s(`WebMCP tool '${l}' timed out after ${this.#r}ms`);if(o?.aborted)return s("Aborted by cancel()");let p=r instanceof Error?r.message:String(r);return s(p)}finally{clearTimeout(T),o&&o.removeEventListener("abort",g)}}#s(){return this.config.enabled!==!0?Promise.resolve():(this.#i||(this.#i=this.#a()),this.#i)}async#a(){try{if(this.#n()){this.#t=!0;return}let e=await this.#e.loadPolyfill();"initializeWebMCPPolyfill"in e?e.initializeWebMCPPolyfill():e.installWebMCP(),this.#t=!0}catch(e){u.warn("Failed to load @mcp-b/webmcp-polyfill: WebMCP consumption disabled.",e),this.#t=!1}}#n(){if(typeof document>"u")return null;let e=document.modelContext;if(!e||typeof e!="object")return null;let n=e;return typeof n.getTools!="function"||typeof n.executeTool!="function"?(this.#l||(this.#l=!0,u.warn("document.modelContext is present but does not expose getTools()/executeTool(): WebMCP consumption is disabled. Another (incompatible or older) WebMCP polyfill likely installed document.modelContext before Persona. Remove it, or use a polyfill implementing the strict standard surface (e.g. @mcp-b/webmcp-polyfill).")),null):e}async#u(e){let n=this.#o??k;try{return await n(e)}catch(o){return u.warn(`Confirm handler threw for WebMCP tool '${e.toolName}'; declining.`,o),!1}}#c(e){let n=this.config.allowlist;return!n||n.length===0?!0:n.some(o=>x(e,o))}},x=(t,e)=>{if(e==="*")return!0;let n=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&");return new RegExp("^"+n.replace(/\*/g,".*")+"$").test(t)},d={type:"object",properties:{}},P=t=>{if(!t||typeof t!="object")return;let e={...typeof t.readOnlyHint=="boolean"?{readOnlyHint:t.readOnlyHint}:{},...typeof t.untrustedContentHint=="boolean"?{untrustedContentHint:t.untrustedContentHint}:{}};return Object.keys(e).length>0?e:void 0},W=t=>{if(t===void 0||t==="")return{...d};if(typeof t=="object")return t!==null&&!Array.isArray(t)?t:{...d};try{let e=JSON.parse(t);return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{...d}}catch{return{...d}}},A=t=>{if(t==null)return{content:[{type:"text",text:""}]};let e;try{e=JSON.parse(t)}catch{return{content:[{type:"text",text:t}]}}return e!==null&&typeof e=="object"&&Array.isArray(e.content)?e:{content:[{type:"text",text:typeof e=="string"?e:D(e)}]}},O=t=>{let e;try{e=JSON.stringify(t)??"{}"}catch{e="{}"}let n=JSON.parse(e);if(n===null||typeof n!="object")throw new TypeError("WebMCP tool arguments must be an object or array.");return Object.defineProperty(n,Symbol.toPrimitive,{value:()=>e}),n},s=t=>({isError:!0,content:[{type:"text",text:t}]}),k=async t=>{if(typeof window>"u"||typeof window.confirm!="function")return!1;let e=S(t.args),n=`Allow the AI to call ${t.toolName}`+(e?`
|
|
2
2
|
|
|
3
3
|
Arguments:
|
|
4
4
|
${e}`:"")+(t.description?`
|
|
5
5
|
|
|
6
|
-
${t.description}`:"");return window.confirm(n)},
|
|
6
|
+
${t.description}`:"");return window.confirm(n)},S=t=>{if(t==null)return"";try{let e=JSON.stringify(t,null,2);return e.length>500?e.slice(0,500)+"\u2026":e}catch{return String(t)}},h=t=>(t.window===void 0||typeof window<"u"&&t.window===window)&&(t.origin===void 0||typeof location<"u"&&t.origin===location.origin),D=t=>{if(t===void 0)return"";try{return JSON.stringify(t)}catch{return String(t)}};export{b as WebMcpBridge};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runtypelabs/persona",
|
|
3
|
-
"version": "4.28.
|
|
3
|
+
"version": "4.28.1",
|
|
4
4
|
"description": "Themeable, pluggable streaming agent widget for websites, in plain JS with support for voice input and reasoning / tool output.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -138,6 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
"devDependencies": {
|
|
140
140
|
"@size-limit/file": "^12.1.0",
|
|
141
|
+
"@types/jsdom": "^30.0.0",
|
|
141
142
|
"@types/node": "^20.12.7",
|
|
142
143
|
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
143
144
|
"@typescript-eslint/parser": "^7.0.0",
|
|
@@ -147,12 +148,14 @@
|
|
|
147
148
|
"eslint": "^8.57.0",
|
|
148
149
|
"eslint-config-prettier": "^9.1.0",
|
|
149
150
|
"fake-indexeddb": "^6.2.5",
|
|
151
|
+
"jsdom": "^28.1.0",
|
|
150
152
|
"rimraf": "^5.0.5",
|
|
151
153
|
"size-limit": "^12.1.0",
|
|
152
154
|
"terser": "^5.49.0",
|
|
153
155
|
"tsup": "^8.0.1",
|
|
154
156
|
"typescript": "^5.4.5",
|
|
155
|
-
"vitest": "^4.0.9"
|
|
157
|
+
"vitest": "^4.0.9",
|
|
158
|
+
"webmcp-polyfill-v6": "npm:@mcp-b/webmcp-polyfill@6.0.0"
|
|
156
159
|
},
|
|
157
160
|
"engines": {
|
|
158
161
|
"node": ">=20.0.0"
|
|
@@ -683,6 +683,9 @@ export type RuntypeClientChatRequest = {
|
|
|
683
683
|
sessionId: string;
|
|
684
684
|
submitMode?: "normal" | "interrupt" | "steer";
|
|
685
685
|
turnId?: string;
|
|
686
|
+
voice?: {
|
|
687
|
+
spoken?: boolean;
|
|
688
|
+
};
|
|
686
689
|
};
|
|
687
690
|
|
|
688
691
|
export type RuntypeClientChatStreamEvent = RuntypeExecutionStreamEvent;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* We deliberately keep our own small WebMCP types rather than depending on
|
|
6
6
|
* `@mcp-b/webmcp-types`, so the tool definitions are transport-agnostic and the
|
|
7
|
-
*
|
|
7
|
+
* tool definitions do not depend on the polyfill's types. These mirror the WebMCP draft
|
|
8
8
|
* (`registerTool(tool, { signal })`) and the MCP tool-result envelope that
|
|
9
9
|
* `@mcp-b/webmcp-polyfill` expects `execute` to return.
|
|
10
10
|
*/
|
package/src/types.ts
CHANGED
|
@@ -881,9 +881,8 @@ export type WebMcpConfirmInfo = {
|
|
|
881
881
|
};
|
|
882
882
|
/**
|
|
883
883
|
* Why the confirm was requested. Currently always `'gate'`: the default
|
|
884
|
-
* confirm-by-default gate that fires before every `webmcp:*` call.
|
|
885
|
-
*
|
|
886
|
-
* internally, so Persona no longer surfaces a nested in-tool confirm.)
|
|
884
|
+
* confirm-by-default gate that fires before every `webmcp:*` call. Tool
|
|
885
|
+
* callbacks on v6 receive an AbortSignal, not a nested confirmation API.
|
|
887
886
|
*/
|
|
888
887
|
reason: 'gate';
|
|
889
888
|
};
|
|
@@ -7705,8 +7704,11 @@ export type AgentWidgetConfig = {
|
|
|
7705
7704
|
/**
|
|
7706
7705
|
* WebMCP: consume page-registered tools (`document.modelContext.registerTool`).
|
|
7707
7706
|
* When `enabled`, the widget installs `@mcp-b/webmcp-polyfill`, snapshots the
|
|
7708
|
-
* registry on every dispatch, ships it as `clientTools[]`,
|
|
7709
|
-
* returned `webmcp:*`
|
|
7707
|
+
* current document's registry on every dispatch, ships it as `clientTools[]`,
|
|
7708
|
+
* and executes returned `webmcp:*` calls with confirm-by-default gating.
|
|
7709
|
+
* Supports host-installed v5 JSON-string and v6 object-input contracts.
|
|
7710
|
+
* The automatic fallback stays on v5 to preserve existing browser support
|
|
7711
|
+
* and callback-result behavior.
|
|
7710
7712
|
*
|
|
7711
7713
|
* Server-side policy on the chat surface is the source of truth: these
|
|
7712
7714
|
* fields layer on top.
|