@runtypelabs/persona 4.23.1 → 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 +41 -41
- 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 +26 -26
- 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 +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 +48 -48
- package/dist/theme-editor-preview.d.cts +46 -3
- package/dist/theme-editor-preview.d.ts +46 -3
- package/dist/theme-editor-preview.js +31 -31
- package/dist/theme-editor.d.cts +46 -3
- package/dist/theme-editor.d.ts +46 -3
- package/package.json +1 -1
- package/src/client.tool-pair-replay.test.ts +325 -0
- package/src/client.ts +32 -31
- 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
|
@@ -78,6 +78,7 @@ export type RuntypeExecutionStreamEvent = ({
|
|
|
78
78
|
turnIndex?: number;
|
|
79
79
|
type: "turn_start";
|
|
80
80
|
}) | ({
|
|
81
|
+
attributes?: Record<string, string | number | boolean>;
|
|
81
82
|
completedAt?: string;
|
|
82
83
|
content?: string;
|
|
83
84
|
cost?: number;
|
|
@@ -136,7 +137,8 @@ export type RuntypeExecutionStreamEvent = ({
|
|
|
136
137
|
};
|
|
137
138
|
turnId?: string;
|
|
138
139
|
type: "model_call_start";
|
|
139
|
-
} | {
|
|
140
|
+
} | ({
|
|
141
|
+
attributes?: Record<string, string | number | boolean>;
|
|
140
142
|
completedAt?: string;
|
|
141
143
|
cost?: number;
|
|
142
144
|
durationMs?: number;
|
|
@@ -160,10 +162,11 @@ export type RuntypeExecutionStreamEvent = ({
|
|
|
160
162
|
cacheWrite?: number;
|
|
161
163
|
input: number;
|
|
162
164
|
output: number;
|
|
165
|
+
reasoning?: number;
|
|
163
166
|
};
|
|
164
167
|
turnId?: string;
|
|
165
168
|
type: "model_call_complete";
|
|
166
|
-
} | {
|
|
169
|
+
}) | {
|
|
167
170
|
executionId: string;
|
|
168
171
|
id: string;
|
|
169
172
|
index?: number;
|
|
@@ -558,38 +561,50 @@ export type RuntypeStopReasonKind = NonNullable<
|
|
|
558
561
|
RuntypeTurnCompleteEvent["stopReason"] | RuntypeStepCompleteEvent["stopReason"]
|
|
559
562
|
>;
|
|
560
563
|
|
|
561
|
-
export type RuntypeClientInitRequest = {
|
|
564
|
+
export type RuntypeClientInitRequest = ({
|
|
562
565
|
durableRecovery?: boolean;
|
|
563
566
|
flowId?: string;
|
|
564
|
-
identityProof?: string
|
|
567
|
+
identityProof?: string | {
|
|
568
|
+
provider: string;
|
|
569
|
+
token: string;
|
|
570
|
+
};
|
|
565
571
|
token: string;
|
|
566
572
|
visitorHistory?: boolean;
|
|
567
573
|
visitorToken?: string;
|
|
568
|
-
} | {
|
|
574
|
+
}) | ({
|
|
569
575
|
durableRecovery?: boolean;
|
|
570
576
|
flowId?: string;
|
|
571
|
-
identityProof?: string
|
|
577
|
+
identityProof?: string | {
|
|
578
|
+
provider: string;
|
|
579
|
+
token: string;
|
|
580
|
+
};
|
|
572
581
|
sessionId: string;
|
|
573
582
|
token: string;
|
|
574
583
|
visitorHistory?: boolean;
|
|
575
584
|
visitorToken?: string;
|
|
576
|
-
} | {
|
|
585
|
+
}) | ({
|
|
577
586
|
conversationId: string;
|
|
578
587
|
durableRecovery?: boolean;
|
|
579
588
|
flowId?: string;
|
|
580
|
-
identityProof?: string
|
|
589
|
+
identityProof?: string | {
|
|
590
|
+
provider: string;
|
|
591
|
+
token: string;
|
|
592
|
+
};
|
|
581
593
|
token: string;
|
|
582
594
|
visitorHistory?: boolean;
|
|
583
595
|
visitorToken: string;
|
|
584
|
-
} | {
|
|
596
|
+
}) | ({
|
|
585
597
|
conversationId: string;
|
|
586
598
|
durableRecovery?: boolean;
|
|
587
599
|
flowId?: string;
|
|
588
|
-
identityProof: string
|
|
600
|
+
identityProof: string | {
|
|
601
|
+
provider: string;
|
|
602
|
+
token: string;
|
|
603
|
+
};
|
|
589
604
|
token: string;
|
|
590
605
|
visitorHistory?: boolean;
|
|
591
606
|
visitorToken?: string;
|
|
592
|
-
};
|
|
607
|
+
});
|
|
593
608
|
|
|
594
609
|
export type RuntypeClientInitResponse = {
|
|
595
610
|
app?: {
|
package/src/session.ts
CHANGED
|
@@ -3816,16 +3816,34 @@ export class AgentWidgetSession {
|
|
|
3816
3816
|
// re-emits don't re-execute the page tool, then complete each bubble.
|
|
3817
3817
|
// Do this only after /resume HTTP success; if /resume fails, the server
|
|
3818
3818
|
// may still be paused and the retry path must not show a final result.
|
|
3819
|
+
const batch = ready[0]!.dedupeKey;
|
|
3819
3820
|
for (const r of ready) {
|
|
3820
3821
|
this.webMcpResolvedKeys.add(r.dedupeKey);
|
|
3822
|
+
const toolName = r.toolMessage.toolCall?.name;
|
|
3823
|
+
const toolCallId = r.toolMessage.agentMetadata?.webMcpToolCallId;
|
|
3821
3824
|
this.markWebMcpToolComplete(
|
|
3822
3825
|
r.toolMessage,
|
|
3823
3826
|
r.output,
|
|
3824
3827
|
r.startedAt,
|
|
3825
3828
|
r.completedAt,
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
+
{
|
|
3830
|
+
...(toolName === SUGGEST_REPLIES_TOOL_NAME
|
|
3831
|
+
? { suggestRepliesResolved: true }
|
|
3832
|
+
: {}),
|
|
3833
|
+
// Only a provider call id can be replayed: a legacy name-keyed
|
|
3834
|
+
// resume has nothing the model's transcript can reference.
|
|
3835
|
+
...(toolName && toolCallId
|
|
3836
|
+
? {
|
|
3837
|
+
clientToolAnswer: {
|
|
3838
|
+
toolCallId,
|
|
3839
|
+
toolName,
|
|
3840
|
+
args: r.toolMessage.toolCall?.args,
|
|
3841
|
+
result: r.output,
|
|
3842
|
+
batch,
|
|
3843
|
+
},
|
|
3844
|
+
}
|
|
3845
|
+
: {}),
|
|
3846
|
+
},
|
|
3829
3847
|
);
|
|
3830
3848
|
}
|
|
3831
3849
|
if (response.body) {
|
|
@@ -4928,6 +4946,17 @@ export class AgentWidgetSession {
|
|
|
4928
4946
|
awaitingLocalTool: false,
|
|
4929
4947
|
};
|
|
4930
4948
|
}
|
|
4949
|
+
// The accepted client-tool answer is what later proxy/agent turns
|
|
4950
|
+
// replay; a post-resume `tool_complete` re-emit carries a fresh
|
|
4951
|
+
// metadata skeleton and must not drop it.
|
|
4952
|
+
const clientToolAnswer = existing.agentMetadata?.clientToolAnswer;
|
|
4953
|
+
if (
|
|
4954
|
+
clientToolAnswer &&
|
|
4955
|
+
merged.agentMetadata &&
|
|
4956
|
+
!merged.agentMetadata.clientToolAnswer
|
|
4957
|
+
) {
|
|
4958
|
+
merged.agentMetadata = { ...merged.agentMetadata, clientToolAnswer };
|
|
4959
|
+
}
|
|
4931
4960
|
// Approval equivalent: `approval_complete` carries only the
|
|
4932
4961
|
// resolution (approvalId, decision, resolvedBy): the runtime does not
|
|
4933
4962
|
// re-send toolName/description/toolType/reason/parameters, so client.ts
|
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
|
+
};
|