@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.
- package/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/{types-9Vxm-PPz.d.cts → types-CI7OckWI.d.cts} +23 -2
- package/dist/animations/{types-9Vxm-PPz.d.ts → types-CI7OckWI.d.ts} +23 -2
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/animations-extra.d.cts +23 -2
- package/dist/animations-extra.d.ts +23 -2
- package/dist/approval-ui.d.cts +46 -3
- package/dist/approval-ui.d.ts +46 -3
- package/dist/artifacts-ui.d.cts +46 -3
- package/dist/artifacts-ui.d.ts +46 -3
- package/dist/codegen.cjs +1 -1
- package/dist/codegen.js +1 -1
- package/dist/context-mentions.d.cts +46 -3
- package/dist/context-mentions.d.ts +46 -3
- package/dist/event-stream-view.d.cts +46 -3
- package/dist/event-stream-view.d.ts +46 -3
- package/dist/forms-ui.d.cts +46 -3
- package/dist/forms-ui.d.ts +46 -3
- package/dist/history-view.d.cts +23 -2
- package/dist/history-view.d.ts +23 -2
- package/dist/index.cjs +43 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -12
- package/dist/index.d.ts +67 -12
- package/dist/index.global.js +28 -28
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +43 -43
- package/dist/index.js.map +1 -1
- package/dist/session-reconnect.d.cts +46 -3
- package/dist/session-reconnect.d.ts +46 -3
- package/dist/smart-dom-reader.d.cts +46 -3
- package/dist/smart-dom-reader.d.ts +46 -3
- package/dist/theme-editor-preview.cjs +49 -49
- package/dist/theme-editor-preview.d.cts +46 -3
- package/dist/theme-editor-preview.d.ts +46 -3
- package/dist/theme-editor-preview.js +33 -33
- package/dist/theme-editor.d.cts +46 -3
- package/dist/theme-editor.d.ts +46 -3
- package/package.json +1 -1
- package/src/client-session-renewal.test.ts +268 -0
- package/src/client.interrupt.test.ts +1 -1
- package/src/client.tool-pair-replay.test.ts +325 -0
- package/src/client.ts +93 -49
- package/src/generated/runtype-openapi-contract.ts +26 -11
- package/src/session.ts +32 -3
- package/src/types.ts +43 -1
- 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
|
+
};
|