@runtypelabs/persona 4.23.0 → 4.23.2

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 (49) hide show
  1. package/dist/animations/glyph-cycle.d.cts +1 -1
  2. package/dist/animations/glyph-cycle.d.ts +1 -1
  3. package/dist/animations/{types-9Vxm-PPz.d.cts → types-CI7OckWI.d.cts} +23 -2
  4. package/dist/animations/{types-9Vxm-PPz.d.ts → types-CI7OckWI.d.ts} +23 -2
  5. package/dist/animations/wipe.d.cts +1 -1
  6. package/dist/animations/wipe.d.ts +1 -1
  7. package/dist/animations-extra.d.cts +23 -2
  8. package/dist/animations-extra.d.ts +23 -2
  9. package/dist/approval-ui.d.cts +46 -3
  10. package/dist/approval-ui.d.ts +46 -3
  11. package/dist/artifacts-ui.d.cts +46 -3
  12. package/dist/artifacts-ui.d.ts +46 -3
  13. package/dist/codegen.cjs +1 -1
  14. package/dist/codegen.js +1 -1
  15. package/dist/context-mentions.d.cts +46 -3
  16. package/dist/context-mentions.d.ts +46 -3
  17. package/dist/event-stream-view.d.cts +46 -3
  18. package/dist/event-stream-view.d.ts +46 -3
  19. package/dist/forms-ui.d.cts +46 -3
  20. package/dist/forms-ui.d.ts +46 -3
  21. package/dist/history-view.d.cts +23 -2
  22. package/dist/history-view.d.ts +23 -2
  23. package/dist/index.cjs +43 -43
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +67 -12
  26. package/dist/index.d.ts +67 -12
  27. package/dist/index.global.js +28 -28
  28. package/dist/index.global.js.map +1 -1
  29. package/dist/index.js +43 -43
  30. package/dist/index.js.map +1 -1
  31. package/dist/session-reconnect.d.cts +46 -3
  32. package/dist/session-reconnect.d.ts +46 -3
  33. package/dist/smart-dom-reader.d.cts +46 -3
  34. package/dist/smart-dom-reader.d.ts +46 -3
  35. package/dist/theme-editor-preview.cjs +49 -49
  36. package/dist/theme-editor-preview.d.cts +46 -3
  37. package/dist/theme-editor-preview.d.ts +46 -3
  38. package/dist/theme-editor-preview.js +33 -33
  39. package/dist/theme-editor.d.cts +46 -3
  40. package/dist/theme-editor.d.ts +46 -3
  41. package/package.json +1 -1
  42. package/src/client-session-renewal.test.ts +268 -0
  43. package/src/client.interrupt.test.ts +1 -1
  44. package/src/client.tool-pair-replay.test.ts +325 -0
  45. package/src/client.ts +93 -49
  46. package/src/generated/runtype-openapi-contract.ts +26 -11
  47. package/src/session.ts +32 -3
  48. package/src/types.ts +43 -1
  49. package/src/utils/tool-pair-replay.ts +100 -0
package/src/types.ts CHANGED
@@ -593,10 +593,34 @@ export type AgentWidgetContextMentionTokenRenderContext = {
593
593
  readonly: boolean;
594
594
  };
595
595
 
596
+ /** One earlier client-tool call replayed to the model, in `/v1/dispatch` shape. */
597
+ export type AgentWidgetReplayedToolCall = {
598
+ toolCallId: string;
599
+ /** Model-facing (sanitized) name, e.g. `webmcp_search`. */
600
+ toolName: string;
601
+ args: Record<string, unknown>;
602
+ };
603
+
604
+ /** The browser's answer to an {@link AgentWidgetReplayedToolCall}. */
605
+ export type AgentWidgetReplayedToolResult = {
606
+ toolCallId: string;
607
+ toolName: string;
608
+ result: unknown;
609
+ };
610
+
611
+ /**
612
+ * A message in the proxy/agent request payload. Earlier client-tool calls the
613
+ * browser answered replay as an assistant message carrying `toolCalls`,
614
+ * followed by a `tool` message carrying the matching `toolResults`; both have
615
+ * empty `content`. Client-token mode never sends them: the server replays
616
+ * from its own stored transcript there.
617
+ */
596
618
  export type AgentWidgetRequestPayloadMessage = {
597
- role: AgentWidgetMessageRole;
619
+ role: AgentWidgetMessageRole | "tool";
598
620
  content: MessageContent;
599
621
  createdAt: string;
622
+ toolCalls?: AgentWidgetReplayedToolCall[];
623
+ toolResults?: AgentWidgetReplayedToolResult[];
600
624
  };
601
625
 
602
626
  export type AgentWidgetRequestPayload = {
@@ -1032,6 +1056,24 @@ export type AgentMessageMetadata = {
1032
1056
  * never re-resume the call.
1033
1057
  */
1034
1058
  suggestRepliesResolved?: boolean;
1059
+ /**
1060
+ * The client-tool answer the server accepted through `/resume`, kept so
1061
+ * later proxy/agent turns can replay the call and its result to the model.
1062
+ * `toolName` is the widget's internal name (`webmcp:<name>` or a bare
1063
+ * built-in). Set only after the resume succeeds; preserved across
1064
+ * re-emissions of the tool message.
1065
+ */
1066
+ clientToolAnswer?: {
1067
+ toolCallId: string;
1068
+ toolName: string;
1069
+ args: unknown;
1070
+ result: unknown;
1071
+ /**
1072
+ * Shared by the answers posted in one `/resume`, i.e. one assistant
1073
+ * turn's parallel calls; a chained call gets a new batch.
1074
+ */
1075
+ batch?: string;
1076
+ };
1035
1077
  };
1036
1078
 
1037
1079
  export type AgentWidgetRequestMiddlewareContext = {
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Client-tool pair replay for the proxy and agent payload builders.
3
+ *
4
+ * In proxy and agent mode the widget holds the only copy of a client-tool
5
+ * result, so it owns replaying it. Each call the browser answered through
6
+ * `/resume` is sent to later turns as an assistant `toolCalls` message plus a
7
+ * `tool` message with the matching `toolResults`, with the full result.
8
+ * A pair replays even after the page stops offering its tool: the model
9
+ * already saw that result, and a follow-up about it must not lose it.
10
+ */
11
+
12
+ import type {
13
+ AgentWidgetMessage,
14
+ AgentWidgetReplayedToolCall,
15
+ AgentWidgetReplayedToolResult,
16
+ AgentWidgetRequestPayloadMessage,
17
+ } from "../types";
18
+
19
+ /**
20
+ * The name a tool reaches the model as (`webmcp:get_schema` ->
21
+ * `webmcp_get_schema`).
22
+ */
23
+ export const modelFacingToolName = (name: string): string =>
24
+ name
25
+ .replace(/[^a-zA-Z0-9_]/g, "_")
26
+ .toLowerCase()
27
+ .replace(/_+/g, "_")
28
+ .replace(/^_|_$/g, "");
29
+
30
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
31
+ typeof value === "object" && value !== null && !Array.isArray(value);
32
+
33
+ const replayablePair = (
34
+ message: AgentWidgetMessage,
35
+ ): { call: AgentWidgetReplayedToolCall; result: AgentWidgetReplayedToolResult } | null => {
36
+ if (message.variant !== "tool") return null;
37
+ const answer = message.agentMetadata?.clientToolAnswer;
38
+ if (!answer || !answer.toolCallId || answer.result === undefined) return null;
39
+ const toolName = modelFacingToolName(answer.toolName);
40
+ if (!toolName) return null;
41
+ return {
42
+ call: {
43
+ toolCallId: answer.toolCallId,
44
+ toolName,
45
+ args: isRecord(answer.args) ? answer.args : {},
46
+ },
47
+ result: { toolCallId: answer.toolCallId, toolName, result: answer.result },
48
+ };
49
+ };
50
+
51
+ /**
52
+ * Serialize time-ordered messages, interleaving replayable tool pairs.
53
+ * `toPayload` maps an ordinary message (or returns null to drop it). Answers
54
+ * posted in the same `/resume` batch are one assistant turn's parallel calls,
55
+ * so they group into one call message and one result message; a later batch
56
+ * (a chained call) starts a new pair even with no text between them.
57
+ */
58
+ export const serializeWithToolPairs = (
59
+ messages: readonly AgentWidgetMessage[],
60
+ toPayload: (message: AgentWidgetMessage) => AgentWidgetRequestPayloadMessage | null,
61
+ ): AgentWidgetRequestPayloadMessage[] => {
62
+ const out: AgentWidgetRequestPayloadMessage[] = [];
63
+ let calls: AgentWidgetReplayedToolCall[] = [];
64
+ let results: AgentWidgetReplayedToolResult[] = [];
65
+ let groupCreatedAt = "";
66
+ let groupBatch: string | undefined;
67
+
68
+ const flush = () => {
69
+ if (calls.length === 0) return;
70
+ out.push(
71
+ { role: "assistant", content: "", createdAt: groupCreatedAt, toolCalls: calls },
72
+ { role: "tool", content: "", createdAt: groupCreatedAt, toolResults: results },
73
+ );
74
+ calls = [];
75
+ results = [];
76
+ };
77
+
78
+ for (const message of messages) {
79
+ const pair = replayablePair(message);
80
+ if (pair) {
81
+ const batch = message.agentMetadata?.clientToolAnswer?.batch;
82
+ if (calls.length > 0 && (batch === undefined || batch !== groupBatch)) flush();
83
+ if (calls.length === 0) {
84
+ groupCreatedAt = message.createdAt;
85
+ groupBatch = batch;
86
+ }
87
+ if (!calls.some((call) => call.toolCallId === pair.call.toolCallId)) {
88
+ calls.push(pair.call);
89
+ results.push(pair.result);
90
+ }
91
+ continue;
92
+ }
93
+ const mapped = toPayload(message);
94
+ if (!mapped) continue;
95
+ flush();
96
+ out.push(mapped);
97
+ }
98
+ flush();
99
+ return out;
100
+ };