@runtypelabs/persona 3.16.0 → 3.18.0
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 +142 -0
- package/dist/animations/glyph-cycle.cjs +279 -0
- package/dist/animations/glyph-cycle.d.cts +5 -0
- package/dist/animations/glyph-cycle.d.ts +5 -0
- package/dist/animations/glyph-cycle.js +252 -0
- package/dist/animations/types-cwY5HaFD.d.cts +307 -0
- package/dist/animations/types-cwY5HaFD.d.ts +307 -0
- package/dist/animations/wipe.cjs +107 -0
- package/dist/animations/wipe.d.cts +5 -0
- package/dist/animations/wipe.d.ts +5 -0
- package/dist/animations/wipe.js +80 -0
- package/dist/index.cjs +49 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +504 -1
- package/dist/index.d.ts +504 -1
- package/dist/index.global.js +143 -88
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +49 -48
- package/dist/index.js.map +1 -1
- package/dist/testing.cjs +85 -0
- package/dist/testing.d.cts +39 -0
- package/dist/testing.d.ts +39 -0
- package/dist/testing.js +56 -0
- package/dist/theme-editor.cjs +2095 -207
- package/dist/theme-editor.d.cts +432 -2
- package/dist/theme-editor.d.ts +432 -2
- package/dist/theme-editor.js +2093 -207
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +14 -0
- package/dist/theme-reference.d.ts +14 -0
- package/dist/widget.css +565 -0
- package/package.json +20 -3
- package/src/animations/glyph-cycle.ts +332 -0
- package/src/animations/wipe.ts +66 -0
- package/src/client.test.ts +275 -0
- package/src/client.ts +99 -0
- package/src/components/ask-user-question-bubble.test.ts +583 -0
- package/src/components/ask-user-question-bubble.ts +924 -0
- package/src/components/composer-builder.ts +61 -10
- package/src/components/message-bubble.test.ts +181 -2
- package/src/components/message-bubble.ts +209 -14
- package/src/components/messages.ts +33 -1
- package/src/components/panel.ts +45 -5
- package/src/defaults.ts +37 -0
- package/src/index-global.ts +31 -0
- package/src/index.ts +34 -1
- package/src/plugins/types.ts +57 -0
- package/src/session.test.ts +276 -1
- package/src/session.ts +247 -3
- package/src/styles/widget.css +565 -0
- package/src/testing/index.ts +11 -0
- package/src/testing/mock-stream.test.ts +80 -0
- package/src/testing/mock-stream.ts +94 -0
- package/src/testing.ts +2 -0
- package/src/theme-editor/index.ts +4 -0
- package/src/theme-editor/preview-utils.test.ts +60 -0
- package/src/theme-editor/preview-utils.ts +129 -0
- package/src/theme-editor/sections.test.ts +19 -0
- package/src/theme-editor/sections.ts +84 -1
- package/src/types/theme.ts +15 -0
- package/src/types.ts +360 -0
- package/src/ui.ask-user-question-plugin.test.ts +649 -0
- package/src/ui.stop-button.test.ts +165 -0
- package/src/ui.ts +706 -11
- package/src/utils/message-fingerprint.ts +2 -0
- package/src/utils/morph.ts +7 -0
- package/src/utils/storage.ts +10 -2
- package/src/utils/stream-animation.test.ts +417 -0
- package/src/utils/stream-animation.ts +449 -0
- package/src/utils/theme.test.ts +36 -0
- package/src/utils/tokens.ts +23 -0
package/src/client.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
AgentWidgetHeadersFunction,
|
|
14
14
|
AgentWidgetSSEEventResult as _AgentWidgetSSEEventResult,
|
|
15
15
|
AgentExecutionState,
|
|
16
|
+
StopReasonKind,
|
|
16
17
|
ClientSession,
|
|
17
18
|
ClientInitResponse,
|
|
18
19
|
ClientChatRequest,
|
|
@@ -774,6 +775,49 @@ export class AgentWidgetClient {
|
|
|
774
775
|
});
|
|
775
776
|
}
|
|
776
777
|
|
|
778
|
+
/**
|
|
779
|
+
* Resume a paused flow execution by supplying outputs for LOCAL
|
|
780
|
+
* (client-executed) tools. Used by the built-in `ask_user_question`
|
|
781
|
+
* answer-pill sheet, but generic enough for any LOCAL tool.
|
|
782
|
+
*
|
|
783
|
+
* Posts to the upstream `/resume` endpoint (the dispatch URL with
|
|
784
|
+
* `/dispatch` replaced by `/resume` — works for both direct-to-Runtype
|
|
785
|
+
* and the persona proxy) and returns the raw Response so the caller can
|
|
786
|
+
* pipe its SSE body through `connectStream()`.
|
|
787
|
+
*
|
|
788
|
+
* @param executionId - The paused execution id carried on `step_await`.
|
|
789
|
+
* @param toolOutputs - Map keyed by tool name → the tool's result value.
|
|
790
|
+
*/
|
|
791
|
+
public async resumeFlow(
|
|
792
|
+
executionId: string,
|
|
793
|
+
toolOutputs: Record<string, unknown>,
|
|
794
|
+
options?: { streamResponse?: boolean }
|
|
795
|
+
): Promise<Response> {
|
|
796
|
+
const trimmed = this.config.apiUrl?.replace(/\/+$/, '') || DEFAULT_CLIENT_API_BASE;
|
|
797
|
+
// Runtype mounts POST /resume as a child route of /v1/dispatch, so the
|
|
798
|
+
// final URL is always `${apiUrl}/resume`. Proxies should follow the
|
|
799
|
+
// same shape (`/api/chat/dispatch/resume`) to keep the widget agnostic.
|
|
800
|
+
const url = `${trimmed}/resume`;
|
|
801
|
+
|
|
802
|
+
let headers: Record<string, string> = {
|
|
803
|
+
'Content-Type': 'application/json',
|
|
804
|
+
...this.headers
|
|
805
|
+
};
|
|
806
|
+
if (this.getHeaders) {
|
|
807
|
+
Object.assign(headers, await this.getHeaders());
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
return fetch(url, {
|
|
811
|
+
method: 'POST',
|
|
812
|
+
headers,
|
|
813
|
+
body: JSON.stringify({
|
|
814
|
+
executionId,
|
|
815
|
+
toolOutputs,
|
|
816
|
+
streamResponse: options?.streamResponse ?? true,
|
|
817
|
+
}),
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
|
|
777
821
|
private async buildAgentPayload(
|
|
778
822
|
messages: AgentWidgetMessage[]
|
|
779
823
|
): Promise<AgentWidgetAgentRequestPayload> {
|
|
@@ -1721,6 +1765,34 @@ export class AgentWidgetClient {
|
|
|
1721
1765
|
if (callKey) {
|
|
1722
1766
|
toolContext.byCall.delete(callKey);
|
|
1723
1767
|
}
|
|
1768
|
+
} else if (payloadType === "step_await" && payload.awaitReason === "local_tool_required" && payload.toolName) {
|
|
1769
|
+
// LOCAL tool pause. Runtype's prompt step throws LocalToolRequiredError
|
|
1770
|
+
// when the model calls a tool with `toolType: "local"`. The server
|
|
1771
|
+
// emits step_await with the tool name, params, and execution id; the
|
|
1772
|
+
// execution pauses until the client POSTs /resume with toolOutputs.
|
|
1773
|
+
//
|
|
1774
|
+
// Upsert a fully-populated tool-variant message so the existing
|
|
1775
|
+
// ask_user_question bubble + sheet paths fire. Mark the message with
|
|
1776
|
+
// `awaitingLocalTool: true` so the UI knows to resolve via
|
|
1777
|
+
// resumeFlow rather than the legacy sendMessage fallback.
|
|
1778
|
+
const toolId = (payload.toolId as string) ?? `local-${nextSequence()}`;
|
|
1779
|
+
const toolMessage = ensureToolMessage(toolId);
|
|
1780
|
+
const tool = toolMessage.toolCall ?? { id: toolId, status: "pending" as const };
|
|
1781
|
+
tool.name = payload.toolName as string;
|
|
1782
|
+
tool.args = payload.parameters;
|
|
1783
|
+
tool.status = "complete";
|
|
1784
|
+
tool.chunks = tool.chunks ?? [];
|
|
1785
|
+
tool.startedAt =
|
|
1786
|
+
tool.startedAt ?? resolveTimestamp(payload.startedAt ?? payload.timestamp);
|
|
1787
|
+
tool.completedAt = tool.completedAt ?? tool.startedAt;
|
|
1788
|
+
toolMessage.toolCall = tool;
|
|
1789
|
+
toolMessage.streaming = false;
|
|
1790
|
+
toolMessage.agentMetadata = {
|
|
1791
|
+
...toolMessage.agentMetadata,
|
|
1792
|
+
executionId: (payload.executionId as string) ?? toolMessage.agentMetadata?.executionId,
|
|
1793
|
+
awaitingLocalTool: true,
|
|
1794
|
+
};
|
|
1795
|
+
emitMessage(toolMessage);
|
|
1724
1796
|
} else if (payloadType === "text_start") {
|
|
1725
1797
|
// Lifecycle event: a new text segment is beginning (emitted at tool boundaries).
|
|
1726
1798
|
// When toolContext is present this fired inside a nested flow — it must not
|
|
@@ -2094,11 +2166,20 @@ export class AgentWidgetClient {
|
|
|
2094
2166
|
continue;
|
|
2095
2167
|
}
|
|
2096
2168
|
|
|
2169
|
+
// Capture optional per-step stopReason emitted by the runtime
|
|
2170
|
+
// (e.g. `'max_tool_calls'`, `'length'`). This is the dispatch-mode
|
|
2171
|
+
// fallback — `agent_turn_complete` will overwrite it later in
|
|
2172
|
+
// agent-loop streams.
|
|
2173
|
+
const stepStopReason = (payload as any).stopReason as
|
|
2174
|
+
| StopReasonKind
|
|
2175
|
+
| undefined;
|
|
2176
|
+
|
|
2097
2177
|
if (didSplitByPartId) {
|
|
2098
2178
|
// Sealed segment(s) — do not create a second bubble from step_complete.
|
|
2099
2179
|
// Merge authoritative final response into the last sealed segment (fixes async lag).
|
|
2100
2180
|
if (assistantMessage !== null) {
|
|
2101
2181
|
const msg: AgentWidgetMessage = assistantMessage;
|
|
2182
|
+
if (stepStopReason) msg.stopReason = stepStopReason;
|
|
2102
2183
|
streamParsers.delete(msg.id);
|
|
2103
2184
|
rawContentBuffers.delete(msg.id);
|
|
2104
2185
|
if (msg.streaming !== false) {
|
|
@@ -2109,6 +2190,7 @@ export class AgentWidgetClient {
|
|
|
2109
2190
|
const splitFinalContent = payload.result?.response;
|
|
2110
2191
|
const sealedForReconcile = lastSealedTextSegment;
|
|
2111
2192
|
if (sealedForReconcile) {
|
|
2193
|
+
if (stepStopReason) sealedForReconcile.stopReason = stepStopReason;
|
|
2112
2194
|
if (splitFinalContent !== undefined && splitFinalContent !== null) {
|
|
2113
2195
|
reconcileSealedAssistantWithFinalResponse(sealedForReconcile, splitFinalContent);
|
|
2114
2196
|
} else {
|
|
@@ -2121,6 +2203,7 @@ export class AgentWidgetClient {
|
|
|
2121
2203
|
}
|
|
2122
2204
|
const finalContent = payload.result?.response;
|
|
2123
2205
|
const assistant = ensureAssistantMessage();
|
|
2206
|
+
if (stepStopReason) assistant.stopReason = stepStopReason;
|
|
2124
2207
|
if (finalContent !== undefined && finalContent !== null) {
|
|
2125
2208
|
// Check if we already have extracted text from streaming
|
|
2126
2209
|
const parser = streamParsers.get(assistant.id);
|
|
@@ -2408,6 +2491,22 @@ export class AgentWidgetClient {
|
|
|
2408
2491
|
emitMessage(reasoningMessage);
|
|
2409
2492
|
}
|
|
2410
2493
|
}
|
|
2494
|
+
|
|
2495
|
+
// Attach the turn-level stopReason to the assistant message
|
|
2496
|
+
// produced by this turn. Only overwrite the current message —
|
|
2497
|
+
// prior turns already sealed their own stopReason via step_complete.
|
|
2498
|
+
const turnStopReason = (payload as any).stopReason as
|
|
2499
|
+
| StopReasonKind
|
|
2500
|
+
| undefined;
|
|
2501
|
+
if (turnStopReason && assistantMessage !== null) {
|
|
2502
|
+
const turnId = payload.turnId;
|
|
2503
|
+
const matchesTurn =
|
|
2504
|
+
!turnId || assistantMessage.agentMetadata?.turnId === turnId;
|
|
2505
|
+
if (matchesTurn) {
|
|
2506
|
+
assistantMessage.stopReason = turnStopReason;
|
|
2507
|
+
emitMessage(assistantMessage);
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2411
2510
|
} else if (payloadType === "agent_tool_start") {
|
|
2412
2511
|
const toolId = payload.toolCallId ?? `agent-tool-${nextSequence()}`;
|
|
2413
2512
|
trackToolId(getToolCallKey(payload), toolId);
|