@runtypelabs/persona 4.27.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.
Files changed (72) hide show
  1. package/README.md +25 -0
  2. package/dist/{approval-ui-QAKWNFNM.js → approval-ui-OBBI62ES.js} +1 -1
  3. package/dist/approval-ui.cjs +2 -2
  4. package/dist/approval-ui.d.cts +20 -5
  5. package/dist/approval-ui.d.ts +20 -5
  6. package/dist/approval-ui.js +2 -2
  7. package/dist/artifacts-ui.d.cts +20 -5
  8. package/dist/artifacts-ui.d.ts +20 -5
  9. package/dist/{chunk-NQLDCJAP.js → chunk-D4TDKCT5.js} +2 -2
  10. package/dist/chunk-FNXK3VTC.js +1 -0
  11. package/dist/{client-history-HTRKHBAF.js → client-history-QGAFMCBE.js} +1 -1
  12. package/dist/client-history.js +1 -1
  13. package/dist/{client-stream-N22JHTLE.js → client-stream-WXD2FL23.js} +1 -1
  14. package/dist/client-stream.js +3 -3
  15. package/dist/codegen.cjs +4 -4
  16. package/dist/codegen.js +5 -5
  17. package/dist/context-mentions.d.cts +20 -5
  18. package/dist/context-mentions.d.ts +20 -5
  19. package/dist/event-stream-view.d.cts +20 -5
  20. package/dist/event-stream-view.d.ts +20 -5
  21. package/dist/forms-ui.d.cts +26 -5
  22. package/dist/forms-ui.d.ts +26 -5
  23. package/dist/index.cjs +41 -41
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +59 -30
  26. package/dist/index.d.ts +59 -30
  27. package/dist/index.global.js +1 -1
  28. package/dist/index.global.js.map +1 -1
  29. package/dist/index.js +41 -41
  30. package/dist/index.js.map +1 -1
  31. package/dist/session-reconnect.d.cts +20 -5
  32. package/dist/session-reconnect.d.ts +20 -5
  33. package/dist/smart-dom-reader.d.cts +20 -5
  34. package/dist/smart-dom-reader.d.ts +20 -5
  35. package/dist/theme-editor-preview.cjs +63 -63
  36. package/dist/theme-editor-preview.d.cts +20 -5
  37. package/dist/theme-editor-preview.d.ts +20 -5
  38. package/dist/theme-editor-preview.js +6 -6
  39. package/dist/theme-editor.d.cts +21 -6
  40. package/dist/theme-editor.d.ts +21 -6
  41. package/dist/voice-runtime-TWFJ4UUS.js +17 -0
  42. package/dist/voice-runtime.cjs +8 -8
  43. package/dist/voice-runtime.d.cts +31 -5
  44. package/dist/voice-runtime.d.ts +31 -5
  45. package/dist/voice-runtime.js +8 -8
  46. package/dist/webmcp-runtime-5Q3IHAHP.js +6 -0
  47. package/dist/webmcp-runtime.cjs +2 -2
  48. package/dist/webmcp-runtime.d.cts +22 -26
  49. package/dist/webmcp-runtime.d.ts +22 -26
  50. package/dist/webmcp-runtime.js +2 -2
  51. package/package.json +5 -2
  52. package/src/client.interrupt.test.ts +18 -0
  53. package/src/client.ts +7 -0
  54. package/src/generated/runtype-openapi-contract.ts +3 -0
  55. package/src/session.ts +11 -3
  56. package/src/session.voice.test.ts +140 -0
  57. package/src/theme-editor/webmcp/types.ts +1 -1
  58. package/src/types.ts +26 -5
  59. package/src/voice/runtype-voice-provider.ts +93 -11
  60. package/src/voice/voice-clause-buffer.test.ts +143 -0
  61. package/src/voice/voice-clause-buffer.ts +187 -0
  62. package/src/voice/voice-delegation.ts +85 -3
  63. package/src/voice/voice.test.ts +257 -2
  64. package/src/webmcp-bridge.test.ts +87 -21
  65. package/src/webmcp-bridge.ts +21 -26
  66. package/src/webmcp-polyfill.integration.test.ts +339 -0
  67. package/src/webmcp-polyfill.ts +7 -4
  68. package/src/webmcp-runtime-bundle.test.ts +1 -1
  69. package/src/webmcp-runtime-entry.ts +34 -19
  70. package/dist/chunk-3255TNY7.js +0 -1
  71. package/dist/voice-runtime-RHRX4F3T.js +0 -17
  72. package/dist/webmcp-runtime-V6ZWW3PI.js +0 -6
package/dist/index.d.cts CHANGED
@@ -2413,6 +2413,9 @@ type RuntypeClientChatRequest = {
2413
2413
  sessionId: string;
2414
2414
  submitMode?: "normal" | "interrupt" | "steer";
2415
2415
  turnId?: string;
2416
+ voice?: {
2417
+ spoken?: boolean;
2418
+ };
2416
2419
  };
2417
2420
  type RuntypeClientChatStreamEvent = RuntypeExecutionStreamEvent;
2418
2421
  type RuntypeClientResumeRequest = {
@@ -3455,9 +3458,8 @@ type WebMcpConfirmInfo = {
3455
3458
  };
3456
3459
  /**
3457
3460
  * Why the confirm was requested. Currently always `'gate'`: the default
3458
- * confirm-by-default gate that fires before every `webmcp:*` call. (The
3459
- * `@mcp-b/webmcp-polyfill` owns the spec's `requestUserInteraction` callback
3460
- * internally, so Persona no longer surfaces a nested in-tool confirm.)
3461
+ * confirm-by-default gate that fires before every `webmcp:*` call. Tool
3462
+ * callbacks on v6 receive an AbortSignal, not a nested confirmation API.
3461
3463
  */
3462
3464
  reason: 'gate';
3463
3465
  };
@@ -7616,6 +7618,13 @@ type VoiceDelegationRequest = {
7616
7618
  role: string;
7617
7619
  content: unknown;
7618
7620
  }>;
7621
+ /**
7622
+ * Set when the server streams delegated answers (`delegation_stream`): called
7623
+ * with each speakable piece of the turn's answer, in order, while it renders.
7624
+ * The pieces, concatenated, are a prefix of the result's `text`; the result
7625
+ * says how much of it with `streamedChars`.
7626
+ */
7627
+ stream?: (text: string) => void;
7619
7628
  };
7620
7629
  /**
7621
7630
  * How a delegated turn ended, or that it waits on an approval (contract
@@ -7646,6 +7655,12 @@ type VoiceDelegationResult = {
7646
7655
  * @default true
7647
7656
  */
7648
7657
  inChat?: boolean;
7658
+ /**
7659
+ * How many leading characters of `text` already went out through
7660
+ * `request.stream` (the rest, such as an approval script, is unstreamed).
7661
+ * Omitted or 0: nothing was streamed.
7662
+ */
7663
+ streamedChars?: number;
7649
7664
  /**
7650
7665
  * Set when the turn parked on approvals (`text` then asks for the decision).
7651
7666
  * Resolves with the terminal result once the visitor decides (or the
@@ -8558,6 +8573,14 @@ type ClientChatRequest = {
8558
8573
  turnId?: RuntypeClientChatRequest['turnId'];
8559
8574
  /** Whether this turn should interrupt a prior in-flight response (from Core public OpenAPI). */
8560
8575
  submitMode?: RuntypeClientChatRequest['submitMode'];
8576
+ /**
8577
+ * Spoken-reply hint, set on a delegated voice turn whose reply a voice model
8578
+ * reads aloud: the server asks the agent for a speakable answer (the direct
8579
+ * answer first, in plain sentences). Not persisted into history.
8580
+ */
8581
+ voice?: {
8582
+ spoken: true;
8583
+ };
8561
8584
  };
8562
8585
  /**
8563
8586
  * Feedback types supported by the API
@@ -9927,8 +9950,11 @@ type AgentWidgetConfig = {
9927
9950
  /**
9928
9951
  * WebMCP: consume page-registered tools (`document.modelContext.registerTool`).
9929
9952
  * When `enabled`, the widget installs `@mcp-b/webmcp-polyfill`, snapshots the
9930
- * registry on every dispatch, ships it as `clientTools[]`, and executes
9931
- * returned `webmcp:*` tool calls with confirm-by-default gating.
9953
+ * current document's registry on every dispatch, ships it as `clientTools[]`,
9954
+ * and executes returned `webmcp:*` calls with confirm-by-default gating.
9955
+ * Supports host-installed v5 JSON-string and v6 object-input contracts.
9956
+ * The automatic fallback stays on v5 to preserve existing browser support
9957
+ * and callback-result behavior.
9932
9958
  *
9933
9959
  * Server-side policy on the chat surface is the source of truth: these
9934
9960
  * fields layer on top.
@@ -11022,6 +11048,12 @@ type DispatchOptions = {
11022
11048
  * `submitMode: "interrupt"` so the server cancels the prior run.
11023
11049
  */
11024
11050
  interrupt?: boolean;
11051
+ /**
11052
+ * Client-token only: a voice model reads the reply aloud (a delegated voice
11053
+ * turn). Sends `voice: { spoken: true }` so the server asks for a speakable
11054
+ * answer.
11055
+ */
11056
+ voiceSpoken?: boolean;
11025
11057
  };
11026
11058
  type SSEHandler = (event: AgentWidgetEvent) => void;
11027
11059
  type SSEEventCallback = (eventType: string, payload: unknown) => void;
@@ -12650,26 +12682,19 @@ declare const createWidgetHostLayout: (target: HTMLElement, config?: AgentWidget
12650
12682
  * enforcement live on the Runtype API; this bridge mirrors those checks
12651
12683
  * client-side as a usability convenience, not a security boundary.
12652
12684
  *
12653
- * About `@mcp-b/webmcp-polyfill`: it polyfills the *strict standard surface*
12654
- * only (`registerTool` / `getTools` / `executeTool` on `document.modelContext`),
12655
- * with no MCP-B-only extensions. The spec standardizes the *producer* side;
12656
- * Persona is an in-page *consumer*, so it reads the registry via the
12657
- * producer-facing preview API:
12658
- * - `getTools()`: async; returns `{ name, description, inputSchema }` where
12659
- * `inputSchema` is a JSON *string*. Annotations are not exposed here.
12660
- * - `executeTool(toolInfo, inputArgsJson, { signal })`: async; validates args
12661
- * against the tool's schema, runs `execute()`, and returns the raw result as
12662
- * a JSON *string* (or `null` for `undefined`). Honors `signal` for abort.
12663
- *
12664
- * The polyfill auto-installs `document.modelContext` at module-evaluation time,
12665
- * so it is imported *dynamically* and only when `config.webmcp.enabled === true`
12666
- *: a static import would install the global for every widget consumer,
12667
- * including those that never opted into WebMCP.
12668
- *
12669
- * Confirm model: every `webmcp:*` call goes through one confirm gate before
12670
- * `execute()` runs, regardless of `annotations.readOnlyHint`. (The polyfill owns
12671
- * the spec's `client.requestUserInteraction` callback internally; Persona cannot
12672
- * inject a nested confirm there, so the single outer gate is the whole story.)
12685
+ * Supports v5's JSON-string input and v6's object input with a single call:
12686
+ * the runtime passes a JSON object that also string-coerces to JSON text.
12687
+ * Never infer the execution contract from metadata or retry a failed call.
12688
+ * Only tools owned by this document are exposed: the wire addresses tools by
12689
+ * name, not by frame. Callbacks must validate their own input.
12690
+ *
12691
+ * The automatic fallback stays on v5 to preserve its browser requirements and
12692
+ * result semantics. Host pages may install v5 or v6 themselves; Persona does
12693
+ * not replace an existing context. v5's initializeWebMCPPolyfill() and v6's
12694
+ * installWebMCP() are both accepted by custom loaders.
12695
+ *
12696
+ * Every call passes one confirm gate before execution, regardless of
12697
+ * annotations.readOnlyHint. v6 callbacks also receive an invocation signal.
12673
12698
  */
12674
12699
 
12675
12700
  /** Server-applied wire prefix; strip when looking up registry entries. */
@@ -12692,18 +12717,20 @@ interface ModelContextToolInfo {
12692
12717
  * object. `@mcp-b/webmcp-polyfill` made the switch in v5, and Chrome ships it
12693
12718
  * from 154.0.8013 (cross-document tools first) -- but Chrome 149-153, most of
12694
12719
  * the Origin Trial population, and 154's same-document tools still emit the
12695
- * string. Both are live in the field, so we accept both.
12720
+ * string. Both input execution contracts are supported independently of
12721
+ * schema representation.
12696
12722
  *
12697
12723
  * Absent when the tool registered no schema: v5 omits the member, where v4
12698
12724
  * always emitted a `{"type":"object"}` string.
12699
12725
  */
12700
12726
  inputSchema?: object | string;
12727
+ /** Owning frame and origin, when supplied by the registry. Never sent on the wire. */
12728
+ window?: Window;
12729
+ origin?: string;
12701
12730
  /**
12702
12731
  * Display title declared on the tool (`ToolDescriptor.title` in the WebMCP
12703
12732
  * spec). The polyfill returns `""` when the tool didn't declare one. Note:
12704
- * `annotations` (incl. the legacy `annotations.title`) are NOT exposed on
12705
- * this strict consumer surface: top-level `title` is the only display-name
12706
- * channel available to us.
12733
+ * top-level `title` is the display-name channel, not `annotations.title`.
12707
12734
  */
12708
12735
  title?: string;
12709
12736
  /**
@@ -12720,6 +12747,8 @@ interface ModelContextToolInfo {
12720
12747
  /** The slice of `@mcp-b/webmcp-polyfill` the bridge consumes on install. */
12721
12748
  type WebMcpPolyfillModule = {
12722
12749
  initializeWebMCPPolyfill: () => void;
12750
+ } | {
12751
+ installWebMCP: () => void;
12723
12752
  };
12724
12753
  /**
12725
12754
  * Strip the server-applied `webmcp:` prefix from a wire-format tool name.
@@ -14516,7 +14545,7 @@ declare class WebMcpBridge$1 {
14516
14545
  * - tool not in registry (e.g. unmounted between snapshot and call)
14517
14546
  * - tool excluded by the client allowlist
14518
14547
  * - user declined the confirm gate
14519
- * - `execute()` threw or failed schema validation
14548
+ * - `execute()` threw or returned a non-serializable result
14520
14549
  * - `execute()` exceeded the 30s timeout
14521
14550
  * - `signal` fired (session-level `cancel()`)
14522
14551
  *
package/dist/index.d.ts CHANGED
@@ -2413,6 +2413,9 @@ type RuntypeClientChatRequest = {
2413
2413
  sessionId: string;
2414
2414
  submitMode?: "normal" | "interrupt" | "steer";
2415
2415
  turnId?: string;
2416
+ voice?: {
2417
+ spoken?: boolean;
2418
+ };
2416
2419
  };
2417
2420
  type RuntypeClientChatStreamEvent = RuntypeExecutionStreamEvent;
2418
2421
  type RuntypeClientResumeRequest = {
@@ -3455,9 +3458,8 @@ type WebMcpConfirmInfo = {
3455
3458
  };
3456
3459
  /**
3457
3460
  * Why the confirm was requested. Currently always `'gate'`: the default
3458
- * confirm-by-default gate that fires before every `webmcp:*` call. (The
3459
- * `@mcp-b/webmcp-polyfill` owns the spec's `requestUserInteraction` callback
3460
- * internally, so Persona no longer surfaces a nested in-tool confirm.)
3461
+ * confirm-by-default gate that fires before every `webmcp:*` call. Tool
3462
+ * callbacks on v6 receive an AbortSignal, not a nested confirmation API.
3461
3463
  */
3462
3464
  reason: 'gate';
3463
3465
  };
@@ -7616,6 +7618,13 @@ type VoiceDelegationRequest = {
7616
7618
  role: string;
7617
7619
  content: unknown;
7618
7620
  }>;
7621
+ /**
7622
+ * Set when the server streams delegated answers (`delegation_stream`): called
7623
+ * with each speakable piece of the turn's answer, in order, while it renders.
7624
+ * The pieces, concatenated, are a prefix of the result's `text`; the result
7625
+ * says how much of it with `streamedChars`.
7626
+ */
7627
+ stream?: (text: string) => void;
7619
7628
  };
7620
7629
  /**
7621
7630
  * How a delegated turn ended, or that it waits on an approval (contract
@@ -7646,6 +7655,12 @@ type VoiceDelegationResult = {
7646
7655
  * @default true
7647
7656
  */
7648
7657
  inChat?: boolean;
7658
+ /**
7659
+ * How many leading characters of `text` already went out through
7660
+ * `request.stream` (the rest, such as an approval script, is unstreamed).
7661
+ * Omitted or 0: nothing was streamed.
7662
+ */
7663
+ streamedChars?: number;
7649
7664
  /**
7650
7665
  * Set when the turn parked on approvals (`text` then asks for the decision).
7651
7666
  * Resolves with the terminal result once the visitor decides (or the
@@ -8558,6 +8573,14 @@ type ClientChatRequest = {
8558
8573
  turnId?: RuntypeClientChatRequest['turnId'];
8559
8574
  /** Whether this turn should interrupt a prior in-flight response (from Core public OpenAPI). */
8560
8575
  submitMode?: RuntypeClientChatRequest['submitMode'];
8576
+ /**
8577
+ * Spoken-reply hint, set on a delegated voice turn whose reply a voice model
8578
+ * reads aloud: the server asks the agent for a speakable answer (the direct
8579
+ * answer first, in plain sentences). Not persisted into history.
8580
+ */
8581
+ voice?: {
8582
+ spoken: true;
8583
+ };
8561
8584
  };
8562
8585
  /**
8563
8586
  * Feedback types supported by the API
@@ -9927,8 +9950,11 @@ type AgentWidgetConfig = {
9927
9950
  /**
9928
9951
  * WebMCP: consume page-registered tools (`document.modelContext.registerTool`).
9929
9952
  * When `enabled`, the widget installs `@mcp-b/webmcp-polyfill`, snapshots the
9930
- * registry on every dispatch, ships it as `clientTools[]`, and executes
9931
- * returned `webmcp:*` tool calls with confirm-by-default gating.
9953
+ * current document's registry on every dispatch, ships it as `clientTools[]`,
9954
+ * and executes returned `webmcp:*` calls with confirm-by-default gating.
9955
+ * Supports host-installed v5 JSON-string and v6 object-input contracts.
9956
+ * The automatic fallback stays on v5 to preserve existing browser support
9957
+ * and callback-result behavior.
9932
9958
  *
9933
9959
  * Server-side policy on the chat surface is the source of truth: these
9934
9960
  * fields layer on top.
@@ -11022,6 +11048,12 @@ type DispatchOptions = {
11022
11048
  * `submitMode: "interrupt"` so the server cancels the prior run.
11023
11049
  */
11024
11050
  interrupt?: boolean;
11051
+ /**
11052
+ * Client-token only: a voice model reads the reply aloud (a delegated voice
11053
+ * turn). Sends `voice: { spoken: true }` so the server asks for a speakable
11054
+ * answer.
11055
+ */
11056
+ voiceSpoken?: boolean;
11025
11057
  };
11026
11058
  type SSEHandler = (event: AgentWidgetEvent) => void;
11027
11059
  type SSEEventCallback = (eventType: string, payload: unknown) => void;
@@ -12650,26 +12682,19 @@ declare const createWidgetHostLayout: (target: HTMLElement, config?: AgentWidget
12650
12682
  * enforcement live on the Runtype API; this bridge mirrors those checks
12651
12683
  * client-side as a usability convenience, not a security boundary.
12652
12684
  *
12653
- * About `@mcp-b/webmcp-polyfill`: it polyfills the *strict standard surface*
12654
- * only (`registerTool` / `getTools` / `executeTool` on `document.modelContext`),
12655
- * with no MCP-B-only extensions. The spec standardizes the *producer* side;
12656
- * Persona is an in-page *consumer*, so it reads the registry via the
12657
- * producer-facing preview API:
12658
- * - `getTools()`: async; returns `{ name, description, inputSchema }` where
12659
- * `inputSchema` is a JSON *string*. Annotations are not exposed here.
12660
- * - `executeTool(toolInfo, inputArgsJson, { signal })`: async; validates args
12661
- * against the tool's schema, runs `execute()`, and returns the raw result as
12662
- * a JSON *string* (or `null` for `undefined`). Honors `signal` for abort.
12663
- *
12664
- * The polyfill auto-installs `document.modelContext` at module-evaluation time,
12665
- * so it is imported *dynamically* and only when `config.webmcp.enabled === true`
12666
- *: a static import would install the global for every widget consumer,
12667
- * including those that never opted into WebMCP.
12668
- *
12669
- * Confirm model: every `webmcp:*` call goes through one confirm gate before
12670
- * `execute()` runs, regardless of `annotations.readOnlyHint`. (The polyfill owns
12671
- * the spec's `client.requestUserInteraction` callback internally; Persona cannot
12672
- * inject a nested confirm there, so the single outer gate is the whole story.)
12685
+ * Supports v5's JSON-string input and v6's object input with a single call:
12686
+ * the runtime passes a JSON object that also string-coerces to JSON text.
12687
+ * Never infer the execution contract from metadata or retry a failed call.
12688
+ * Only tools owned by this document are exposed: the wire addresses tools by
12689
+ * name, not by frame. Callbacks must validate their own input.
12690
+ *
12691
+ * The automatic fallback stays on v5 to preserve its browser requirements and
12692
+ * result semantics. Host pages may install v5 or v6 themselves; Persona does
12693
+ * not replace an existing context. v5's initializeWebMCPPolyfill() and v6's
12694
+ * installWebMCP() are both accepted by custom loaders.
12695
+ *
12696
+ * Every call passes one confirm gate before execution, regardless of
12697
+ * annotations.readOnlyHint. v6 callbacks also receive an invocation signal.
12673
12698
  */
12674
12699
 
12675
12700
  /** Server-applied wire prefix; strip when looking up registry entries. */
@@ -12692,18 +12717,20 @@ interface ModelContextToolInfo {
12692
12717
  * object. `@mcp-b/webmcp-polyfill` made the switch in v5, and Chrome ships it
12693
12718
  * from 154.0.8013 (cross-document tools first) -- but Chrome 149-153, most of
12694
12719
  * the Origin Trial population, and 154's same-document tools still emit the
12695
- * string. Both are live in the field, so we accept both.
12720
+ * string. Both input execution contracts are supported independently of
12721
+ * schema representation.
12696
12722
  *
12697
12723
  * Absent when the tool registered no schema: v5 omits the member, where v4
12698
12724
  * always emitted a `{"type":"object"}` string.
12699
12725
  */
12700
12726
  inputSchema?: object | string;
12727
+ /** Owning frame and origin, when supplied by the registry. Never sent on the wire. */
12728
+ window?: Window;
12729
+ origin?: string;
12701
12730
  /**
12702
12731
  * Display title declared on the tool (`ToolDescriptor.title` in the WebMCP
12703
12732
  * spec). The polyfill returns `""` when the tool didn't declare one. Note:
12704
- * `annotations` (incl. the legacy `annotations.title`) are NOT exposed on
12705
- * this strict consumer surface: top-level `title` is the only display-name
12706
- * channel available to us.
12733
+ * top-level `title` is the display-name channel, not `annotations.title`.
12707
12734
  */
12708
12735
  title?: string;
12709
12736
  /**
@@ -12720,6 +12747,8 @@ interface ModelContextToolInfo {
12720
12747
  /** The slice of `@mcp-b/webmcp-polyfill` the bridge consumes on install. */
12721
12748
  type WebMcpPolyfillModule = {
12722
12749
  initializeWebMCPPolyfill: () => void;
12750
+ } | {
12751
+ installWebMCP: () => void;
12723
12752
  };
12724
12753
  /**
12725
12754
  * Strip the server-applied `webmcp:` prefix from a wire-format tool name.
@@ -14516,7 +14545,7 @@ declare class WebMcpBridge$1 {
14516
14545
  * - tool not in registry (e.g. unmounted between snapshot and call)
14517
14546
  * - tool excluded by the client allowlist
14518
14547
  * - user declined the confirm gate
14519
- * - `execute()` threw or failed schema validation
14548
+ * - `execute()` threw or returned a non-serializable result
14520
14549
  * - `execute()` exceeded the 30s timeout
14521
14550
  * - `signal` fired (session-level `cancel()`)
14522
14551
  *