@runtypelabs/persona 4.24.0 → 4.26.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/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/{types-Db61aI9J.d.cts → types-BwKTZhg9.d.cts} +14 -0
- package/dist/animations/{types-Db61aI9J.d.ts → types-BwKTZhg9.d.ts} +14 -0
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/animations-extra.d.cts +14 -0
- package/dist/animations-extra.d.ts +14 -0
- package/dist/approval-ui-QAKWNFNM.js +1 -0
- package/dist/approval-ui.cjs +2 -2
- package/dist/approval-ui.d.cts +243 -8
- package/dist/approval-ui.d.ts +243 -8
- package/dist/approval-ui.js +2 -2
- package/dist/{artifacts-ui-IGB5YKLO.js → artifacts-ui-NJGMM27I.js} +1 -1
- package/dist/artifacts-ui.cjs +4 -4
- package/dist/artifacts-ui.d.cts +243 -8
- package/dist/artifacts-ui.d.ts +243 -8
- package/dist/artifacts-ui.js +5 -5
- package/dist/chunk-2ANTRKTV.js +1 -0
- package/dist/chunk-4HPTPUC6.js +1 -0
- package/dist/chunk-6V3MNEKB.js +1 -0
- package/dist/chunk-HGUCGM3K.js +9 -0
- package/dist/chunk-IO5VVUKP.js +3 -0
- package/dist/chunk-J4J3Y2P2.js +1 -0
- package/dist/chunk-K6HKIP5K.js +1 -0
- package/dist/chunk-K7NA7G7J.js +1 -0
- package/dist/chunk-MXUTS3LB.js +1 -0
- package/dist/chunk-PDPVORUF.js +1 -0
- package/dist/chunk-QPPJUSZH.js +1 -0
- package/dist/chunk-QRKGQPU7.js +1 -0
- package/dist/chunk-S6PBWE75.js +1 -0
- package/dist/chunk-T7QM7YMF.js +1 -0
- package/dist/chunk-TR2H475E.js +1 -0
- package/dist/chunk-UPO4GUFC.js +1 -0
- package/dist/chunk-ZC66NAIR.js +1 -0
- package/dist/client-history-YPEG45Q4.js +1 -0
- package/dist/client-history.js +1 -0
- package/dist/client-stream-42FOI3EC.js +4 -0
- package/dist/client-stream.js +5 -0
- package/dist/codegen.cjs +1 -1
- package/dist/codegen.js +1 -1
- package/dist/context-mentions-E7HJYWO6.js +161 -0
- package/dist/{context-mentions-inline-I2RDEBAK.js → context-mentions-inline-QVESLW55.js} +1 -1
- package/dist/context-mentions.cjs +7 -7
- package/dist/context-mentions.d.cts +243 -8
- package/dist/context-mentions.d.ts +243 -8
- package/dist/context-mentions.js +8 -8
- package/dist/event-stream-view-FOIJHFQO.js +1 -0
- package/dist/event-stream-view.cjs +1 -1
- package/dist/event-stream-view.d.cts +246 -31
- package/dist/event-stream-view.d.ts +246 -31
- package/dist/event-stream-view.js +1 -1
- package/dist/forms-ui.d.cts +295 -667
- package/dist/forms-ui.d.ts +295 -667
- package/dist/history-shell-QDQ44PSE.js +3 -0
- package/dist/history-shell.js +3 -0
- package/dist/{history-view-BD6OXLNA.js → history-view-NCFBI5GR.js} +2 -2
- package/dist/history-view.cjs +2 -2
- package/dist/history-view.d.cts +35 -1
- package/dist/history-view.d.ts +35 -1
- package/dist/history-view.js +2 -2
- package/dist/index.cjs +80 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +301 -738
- package/dist/index.d.ts +301 -738
- package/dist/index.global.js +3 -215
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +81 -75
- package/dist/index.js.map +1 -1
- package/dist/install.global.js +1 -1
- package/dist/install.global.js.map +1 -1
- package/dist/launcher.global.js +3 -67
- package/dist/launcher.global.js.map +1 -1
- package/dist/markdown-parsers.js +22 -22
- package/dist/runtype-tts-entry-NFBVWR7N.js +1 -0
- package/dist/runtype-tts.js +1 -1
- package/dist/session-actions-ISSKSI66.js +1 -0
- package/dist/session-actions.js +1 -0
- package/dist/session-reconnect.d.cts +243 -8
- package/dist/session-reconnect.d.ts +243 -8
- package/dist/smart-dom-reader.cjs +13 -13
- package/dist/smart-dom-reader.d.cts +243 -8
- package/dist/smart-dom-reader.d.ts +243 -8
- package/dist/smart-dom-reader.js +11 -11
- package/dist/theme-editor-preview.cjs +116 -98
- package/dist/theme-editor-preview.d.cts +245 -8
- package/dist/theme-editor-preview.d.ts +245 -8
- package/dist/theme-editor-preview.js +49 -54
- package/dist/theme-editor.cjs +2 -2
- package/dist/theme-editor.d.cts +244 -23
- package/dist/theme-editor.d.ts +244 -23
- package/dist/theme-editor.js +2 -2
- package/dist/theme-reference.d.cts +14 -0
- package/dist/theme-reference.d.ts +14 -0
- package/dist/ui-extras-entry-WAYFKVNW.js +3 -0
- package/dist/ui-extras.js +72 -0
- package/dist/voice-runtime-UOQOFAFY.js +17 -0
- package/dist/voice-runtime.cjs +17 -1
- package/dist/voice-runtime.d.cts +11643 -192
- package/dist/voice-runtime.d.ts +11643 -192
- package/dist/voice-runtime.js +17 -1
- package/dist/voice-worklet-player.cjs +19 -4
- package/dist/voice-worklet-player.d.cts +9 -10
- package/dist/voice-worklet-player.d.ts +9 -10
- package/dist/voice-worklet-player.js +19 -4
- package/dist/webmcp-polyfill.js +1 -1
- package/dist/webmcp-runtime-V6ZWW3PI.js +6 -0
- package/dist/webmcp-runtime.cjs +2 -2
- package/dist/webmcp-runtime.d.cts +1 -33
- package/dist/webmcp-runtime.d.ts +1 -33
- package/dist/webmcp-runtime.js +2 -2
- package/dist/widget.css +1 -1
- package/package.json +11 -5
- package/src/approval-paused-tool-settle.test.ts +221 -0
- package/src/client-approve.test.ts +311 -0
- package/src/client-history-eager.ts +9 -0
- package/src/client-history-loader.ts +23 -0
- package/src/client-history.ts +579 -0
- package/src/client-resume.ts +177 -0
- package/src/client-stream-eager.ts +12 -0
- package/src/client-stream-loader.ts +25 -0
- package/src/client-stream.ts +1880 -0
- package/src/client.test.ts +31 -1
- package/src/client.ts +293 -2607
- package/src/components/approval-actions.test.ts +27 -0
- package/src/components/approval-actions.ts +27 -3
- package/src/components/message-bubble.test.ts +19 -0
- package/src/components/message-bubble.ts +2 -0
- package/src/components/registry.ts +6 -6
- package/src/components/tool-bubble.test.ts +9 -0
- package/src/components/tool-bubble.ts +1 -0
- package/src/history-shell-bundle.test.ts +54 -0
- package/src/history-shell-eager.ts +12 -0
- package/src/history-shell-loader.ts +27 -0
- package/src/history-shell.ts +2362 -0
- package/src/history-view-loader.ts +2 -0
- package/src/history-view.ts +3 -0
- package/src/index-core.ts +8 -0
- package/src/index-global.ts +90 -248
- package/src/index.ts +13 -0
- package/src/install.ts +6 -4
- package/src/internal/runtype-history-provider.test.ts +1 -0
- package/src/internal/runtype-history-provider.ts +28 -13
- package/src/plugins/registry.ts +8 -8
- package/src/session-actions-chunk.test.ts +55 -0
- package/src/session-actions-eager.ts +11 -0
- package/src/session-actions-loader.ts +37 -0
- package/src/session-actions.ts +909 -0
- package/src/session-history.test.ts +3 -1
- package/src/session.ts +875 -1530
- package/src/session.voice.test.ts +1241 -5
- package/src/styles/widget.css +58 -0
- package/src/theme-editor/state.ts +91 -91
- package/src/types.ts +269 -5
- package/src/ui-ask-user-sheet.ts +382 -0
- package/src/ui-extras-eager.ts +10 -0
- package/src/ui-extras-entry.ts +9 -0
- package/src/ui-extras-loader.ts +26 -0
- package/src/ui.artifact-rail-resize.test.ts +2 -1
- package/src/ui.ask-user-chunk.test.ts +93 -0
- package/src/ui.history-chunk.test.ts +2 -1
- package/src/ui.history-config-provider.test.ts +2 -1
- package/src/ui.history-confirm-fallback.test.ts +142 -0
- package/src/ui.history-controller.test.ts +2 -1
- package/src/ui.history-lifecycle.test.ts +2 -1
- package/src/ui.history-render-hooks.test.ts +2 -1
- package/src/ui.history-shell.test.ts +2 -1
- package/src/ui.rail-overlay.test.ts +2 -1
- package/src/ui.rail-resize.test.ts +2 -1
- package/src/ui.rail-trigger-pending.test.ts +2 -1
- package/src/ui.ts +399 -2770
- package/src/ui.voice-prewarm.test.ts +222 -0
- package/src/utils/attachment-manager.ts +67 -67
- package/src/utils/constants.ts +3 -0
- package/src/utils/context-mention-controller.ts +323 -323
- package/src/utils/context-mention-manager.ts +40 -40
- package/src/utils/context-mention-orchestrator.ts +28 -0
- package/src/utils/event-stream-buffer.ts +50 -50
- package/src/utils/event-stream-store.ts +43 -43
- package/src/utils/throughput-tracker.ts +34 -34
- package/src/utils/virtual-scroller.ts +67 -67
- package/src/utils/visitor-store.test.ts +50 -0
- package/src/utils/visitor-store.ts +23 -5
- package/src/voice/__fixtures__/voice-wire/README.md +1 -0
- package/src/voice/__fixtures__/voice-wire/client/cancel.json +3 -0
- package/src/voice/__fixtures__/voice-wire/client/context.json +4 -0
- package/src/voice/__fixtures__/voice-wire/client/delegation_result.json +6 -0
- package/src/voice/__fixtures__/voice-wire/client/delegation_update.json +6 -0
- package/src/voice/__fixtures__/voice-wire/client/ping.json +3 -0
- package/src/voice/__fixtures__/voice-wire/client/playback_progress.json +5 -0
- package/src/voice/__fixtures__/voice-wire/client/start.json +3 -0
- package/src/voice/__fixtures__/voice-wire/server/artifact.json +11 -0
- package/src/voice/__fixtures__/voice-wire/server/attached.json +4 -0
- package/src/voice/__fixtures__/voice-wire/server/audio_clear.json +4 -0
- package/src/voice/__fixtures__/voice-wire/server/audio_end.json +3 -0
- package/src/voice/__fixtures__/voice-wire/server/delegation_cancelled.json +5 -0
- package/src/voice/__fixtures__/voice-wire/server/delegation_completed.json +8 -0
- package/src/voice/__fixtures__/voice-wire/server/delegation_started.json +15 -0
- package/src/voice/__fixtures__/voice-wire/server/error.json +6 -0
- package/src/voice/__fixtures__/voice-wire/server/metrics.json +10 -0
- package/src/voice/__fixtures__/voice-wire/server/pong.json +3 -0
- package/src/voice/__fixtures__/voice-wire/server/session_config.json +16 -0
- package/src/voice/__fixtures__/voice-wire/server/transcript_final.json +7 -0
- package/src/voice/__fixtures__/voice-wire/server/transcript_interim.json +4 -0
- package/src/voice/__fixtures__/voice-wire/server/transcript_partial.json +6 -0
- package/src/voice/__fixtures__/voice-wire/server/transcript_update.json +10 -0
- package/src/voice/__fixtures__/voice-wire/server/warning.json +5 -0
- package/src/voice/audio-playback-manager.test.ts +57 -0
- package/src/voice/audio-playback-manager.ts +120 -98
- package/src/voice/browser-voice-provider.ts +37 -37
- package/src/voice/fallback-speech-engine.ts +22 -16
- package/src/voice/keyed-voice-transcript.ts +314 -0
- package/src/voice/mic-state-styles.ts +182 -0
- package/src/voice/read-aloud-controller.ts +46 -44
- package/src/voice/runtype-speech-engine.ts +35 -33
- package/src/voice/runtype-voice-provider.ts +856 -164
- package/src/voice/session-voice-wiring.ts +266 -0
- package/src/voice/voice-delegation.test.ts +71 -0
- package/src/voice/voice-delegation.ts +364 -0
- package/src/voice/voice-turn-tracker.ts +6 -6
- package/src/voice/voice.test.ts +1250 -7
- package/src/voice/worklet-playback-engine.test.ts +81 -0
- package/src/voice/worklet-playback-engine.ts +21 -3
- package/src/voice-runtime-loader.ts +4 -1
- package/src/voice-runtime.ts +7 -0
- package/src/webmcp-runtime-entry.ts +41 -39
- package/dist/approval-ui-3NMYNXBD.js +0 -1
- package/dist/chunk-5EIIHQLQ.js +0 -1
- package/dist/chunk-7CO4T5KB.js +0 -1
- package/dist/chunk-EFJBUH5F.js +0 -1
- package/dist/chunk-R2TMIMDI.js +0 -3
- package/dist/chunk-UTVLOTWB.js +0 -9
- package/dist/context-mentions-45MODWOY.js +0 -161
- package/dist/event-stream-view-GL3ADRY2.js +0 -1
- package/dist/runtype-tts-entry-UJAEF7NZ.js +0 -1
- package/dist/voice-runtime-EFR3R5ES.js +0 -1
- package/dist/webmcp-runtime-JI7T4QYF.js +0 -6
|
@@ -122,6 +122,33 @@ describe("built-in approval — flag off (default)", () => {
|
|
|
122
122
|
});
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
+
describe("built-in approval — client-token visitor", () => {
|
|
126
|
+
const cfg: AgentWidgetConfig = {
|
|
127
|
+
clientToken: "ct_live_demo",
|
|
128
|
+
approval: { detailsDisplay: "hidden" },
|
|
129
|
+
};
|
|
130
|
+
const message = makeMessage({
|
|
131
|
+
toolName: "place_pickup_order",
|
|
132
|
+
parameters: { item: "croissant", qty: 12 },
|
|
133
|
+
reason: "The user asked for this.",
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("keeps the raw call behind the disclosure without a client token", () => {
|
|
137
|
+
const { el } = render({}, message);
|
|
138
|
+
expect(el?.querySelector('[data-role="raw-call"]')).toBeNull();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("shows the raw tool name and parameters above the agent's reason", () => {
|
|
142
|
+
const { el } = render(cfg, message);
|
|
143
|
+
const call = el?.querySelector('[data-role="raw-call"]') as HTMLElement | null;
|
|
144
|
+
expect(call?.querySelector(".persona-approval-tool-name")?.textContent).toBe("place_pickup_order");
|
|
145
|
+
expect(call?.querySelector(".persona-approval-params")?.textContent).toContain("croissant");
|
|
146
|
+
const reason = el?.querySelector(".persona-approval-reason");
|
|
147
|
+
expect(reason?.textContent).toContain("Agent's stated reason:");
|
|
148
|
+
expect(call!.compareDocumentPosition(reason!) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
125
152
|
describe("built-in approval — flag on (enableAlwaysAllow)", () => {
|
|
126
153
|
const cfg: AgentWidgetConfig = { approval: { enableAlwaysAllow: true } };
|
|
127
154
|
|
|
@@ -180,7 +180,8 @@ const buildPending = (
|
|
|
180
180
|
approvalConfig: AgentWidgetApprovalConfig | undefined,
|
|
181
181
|
approve: Decide,
|
|
182
182
|
deny: Decide,
|
|
183
|
-
enableAlways: boolean
|
|
183
|
+
enableAlways: boolean,
|
|
184
|
+
showRawCall = false
|
|
184
185
|
): HTMLElement => {
|
|
185
186
|
const card = createElement("div", "persona-approval-card persona-shadow-sm");
|
|
186
187
|
card.id = `bubble-${message.id}`;
|
|
@@ -199,7 +200,8 @@ const buildPending = (
|
|
|
199
200
|
// name), so the description is only ever visible here. Mirrors the legacy
|
|
200
201
|
// bubble, which also opened a disclosure when only a description was present.
|
|
201
202
|
const hasDescription = Boolean(approval.description) && detailsMode !== "hidden";
|
|
202
|
-
|
|
203
|
+
// `showRawCall` lifts the parameters out of the disclosure (see below).
|
|
204
|
+
const hasParams = approval.parameters != null && detailsMode !== "hidden" && !showRawCall;
|
|
203
205
|
const hasDetails = hasDescription || hasParams;
|
|
204
206
|
const expanded = hasDetails && isDetailsExpanded(message.id, expansionState, approvalConfig);
|
|
205
207
|
|
|
@@ -263,6 +265,24 @@ const buildPending = (
|
|
|
263
265
|
body.appendChild(details);
|
|
264
266
|
}
|
|
265
267
|
|
|
268
|
+
// The raw tool name and arguments, always visible and above the reason, so
|
|
269
|
+
// what will actually run is never less prominent than the agent's claim.
|
|
270
|
+
if (showRawCall) {
|
|
271
|
+
const call = createElement("div", "persona-approval-call");
|
|
272
|
+
call.setAttribute("data-role", "raw-call");
|
|
273
|
+
const name = createElement("code", "persona-approval-tool-name");
|
|
274
|
+
name.textContent = approval.toolName;
|
|
275
|
+
call.appendChild(name);
|
|
276
|
+
if (approval.parameters != null) {
|
|
277
|
+
const pre = createElement("pre", "persona-approval-params");
|
|
278
|
+
if (approvalConfig?.parameterBackgroundColor) pre.style.background = approvalConfig.parameterBackgroundColor;
|
|
279
|
+
if (approvalConfig?.parameterTextColor) pre.style.color = approvalConfig.parameterTextColor;
|
|
280
|
+
pre.textContent = formatUnknownValue(approval.parameters);
|
|
281
|
+
call.appendChild(pre);
|
|
282
|
+
}
|
|
283
|
+
body.appendChild(call);
|
|
284
|
+
}
|
|
285
|
+
|
|
266
286
|
// Agent-authored justification: attacker-writable, so plain text + attributed.
|
|
267
287
|
if (approval.reason) {
|
|
268
288
|
const reasonLine = createElement("p", "persona-approval-reason");
|
|
@@ -422,6 +442,9 @@ export const createBuiltInApprovalPlugin = (
|
|
|
422
442
|
// closures, but KEEP this approval's place in the pending order so a
|
|
423
443
|
// re-render of an older card doesn't reorder it ahead of a newer one.
|
|
424
444
|
detachMessage(state, message.id);
|
|
445
|
+
// Client-token visitors answer the gate themselves, so they see the
|
|
446
|
+
// exact call rather than just the agent's framing.
|
|
447
|
+
const visitorGate = Boolean(config?.clientToken);
|
|
425
448
|
const enableAlways = approvalConfig?.enableAlwaysAllow === true;
|
|
426
449
|
const card = buildPending(
|
|
427
450
|
state,
|
|
@@ -431,7 +454,8 @@ export const createBuiltInApprovalPlugin = (
|
|
|
431
454
|
approvalConfig,
|
|
432
455
|
approve,
|
|
433
456
|
deny,
|
|
434
|
-
enableAlways
|
|
457
|
+
enableAlways,
|
|
458
|
+
visitorGate
|
|
435
459
|
);
|
|
436
460
|
|
|
437
461
|
if (enableAlways) {
|
|
@@ -333,6 +333,25 @@ describe("createStandardBubble", () => {
|
|
|
333
333
|
});
|
|
334
334
|
});
|
|
335
335
|
|
|
336
|
+
describe("createStandardBubble: message actions", () => {
|
|
337
|
+
const actions = { enabled: true, showCopy: true, visibility: "hover", align: "right", layout: "pill-inside" } as const;
|
|
338
|
+
|
|
339
|
+
it("gives a voice caption no message actions", () => {
|
|
340
|
+
const bubble = createStandardBubble(
|
|
341
|
+
makeMessage({ id: "caption", content: "Okay, placing that now.", voiceCaption: true }),
|
|
342
|
+
({ text }) => text,
|
|
343
|
+
undefined,
|
|
344
|
+
actions
|
|
345
|
+
);
|
|
346
|
+
expect(bubble.querySelector(".persona-message-actions")).toBeNull();
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it("keeps the copy action on an ordinary short reply", () => {
|
|
350
|
+
const bubble = createStandardBubble(makeMessage({ content: "Sure." }), ({ text }) => text, undefined, actions);
|
|
351
|
+
expect(bubble.querySelector('[data-action="copy"]')).not.toBeNull();
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
336
355
|
describe("createStandardBubble: components.message geometry tokens", () => {
|
|
337
356
|
const geometry = (bubble: HTMLElement) => ({
|
|
338
357
|
padding: bubble.style.padding,
|
|
@@ -1298,6 +1298,8 @@ export const createStandardBubble = (
|
|
|
1298
1298
|
const shouldShowActions =
|
|
1299
1299
|
message.role === "assistant" &&
|
|
1300
1300
|
!message.streaming &&
|
|
1301
|
+
// A voice caption (the voice model's own speech) is display-only.
|
|
1302
|
+
!message.voiceCaption &&
|
|
1301
1303
|
message.content &&
|
|
1302
1304
|
message.content.trim() &&
|
|
1303
1305
|
actionsConfig?.enabled !== false;
|
|
@@ -37,7 +37,7 @@ export interface ComponentRegistrationOptions {
|
|
|
37
37
|
*/
|
|
38
38
|
class ComponentRegistry {
|
|
39
39
|
private components: Map<string, ComponentRenderer> = new Map();
|
|
40
|
-
|
|
40
|
+
#options: Map<string, ComponentRegistrationOptions> = new Map();
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* Register a custom component
|
|
@@ -52,9 +52,9 @@ class ComponentRegistry {
|
|
|
52
52
|
}
|
|
53
53
|
this.components.set(name, renderer);
|
|
54
54
|
if (options) {
|
|
55
|
-
this
|
|
55
|
+
this.#options.set(name, options);
|
|
56
56
|
} else {
|
|
57
|
-
this
|
|
57
|
+
this.#options.delete(name);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -63,7 +63,7 @@ class ComponentRegistry {
|
|
|
63
63
|
*/
|
|
64
64
|
unregister(name: string): void {
|
|
65
65
|
this.components.delete(name);
|
|
66
|
-
this
|
|
66
|
+
this.#options.delete(name);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/**
|
|
@@ -84,7 +84,7 @@ class ComponentRegistry {
|
|
|
84
84
|
* Get the registration options for a component, if any were supplied
|
|
85
85
|
*/
|
|
86
86
|
getOptions(name: string): ComponentRegistrationOptions | undefined {
|
|
87
|
-
return this
|
|
87
|
+
return this.#options.get(name);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/**
|
|
@@ -99,7 +99,7 @@ class ComponentRegistry {
|
|
|
99
99
|
*/
|
|
100
100
|
clear(): void {
|
|
101
101
|
this.components.clear();
|
|
102
|
-
this
|
|
102
|
+
this.#options.clear();
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
@@ -49,3 +49,12 @@ describe("tool failure presentation", () => {
|
|
|
49
49
|
expect(bubble.querySelector("script")).toBeNull();
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
|
+
|
|
53
|
+
describe("approval-superseded presentation", () => {
|
|
54
|
+
it("labels an approved call that ran again under a new id", () => {
|
|
55
|
+
const message = makeMessage();
|
|
56
|
+
message.toolCall = { ...message.toolCall!, approvalStatus: "approved", superseded: true };
|
|
57
|
+
const bubble = createToolBubble(message);
|
|
58
|
+
expect(bubble.textContent).toContain("Approved, ran again below");
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Bundle guard for the lazy visitor-history shell.
|
|
7
|
+
*
|
|
8
|
+
* The CDN IIFE (`dist/index.global.js`) must not carry the shell: it ships as
|
|
9
|
+
* the sibling chunk `dist/history-shell.js`, fetched only when
|
|
10
|
+
* `features.history` is enabled or a history API is called. npm builds inline
|
|
11
|
+
* it (`history-shell-eager.ts`). A stray static import from core would pull
|
|
12
|
+
* it back into the IIFE; this fails then.
|
|
13
|
+
*
|
|
14
|
+
* Skips when `dist/` hasn't been built (e.g. a test-only CI step).
|
|
15
|
+
*/
|
|
16
|
+
const dist = (f: string) => resolve(__dirname, "..", "dist", f);
|
|
17
|
+
|
|
18
|
+
// Shell-only literals: rail/overlay chrome and conversation-open classes.
|
|
19
|
+
const RUNTIME_MARKERS = [
|
|
20
|
+
"persona-history-rail-shell",
|
|
21
|
+
"persona-history-rail-overlay",
|
|
22
|
+
"persona-conversation-loading-error",
|
|
23
|
+
"data-persona-history-toggle",
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
// Stateful core modules arrive through the shell's ctx, never bundled copies:
|
|
27
|
+
// the icon registry's map keys and the tooltip module only exist where bundled.
|
|
28
|
+
const NOT_IN_CHUNK = ["shopping-cart", "persona-tooltip"];
|
|
29
|
+
|
|
30
|
+
describe("history-shell bundle split", () => {
|
|
31
|
+
const iifeBuilt =
|
|
32
|
+
existsSync(dist("index.global.js")) && existsSync(dist("history-shell.js"));
|
|
33
|
+
|
|
34
|
+
it.runIf(iifeBuilt)("keeps the history shell OUT of the core IIFE bundle", () => {
|
|
35
|
+
const core = readFileSync(dist("index.global.js"), "utf8");
|
|
36
|
+
for (const marker of RUNTIME_MARKERS) {
|
|
37
|
+
expect(core.includes(marker), `IIFE bundle unexpectedly contains "${marker}"`).toBe(
|
|
38
|
+
false
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
// The loader stub (sibling-URL reference) must remain so the chunk can load.
|
|
42
|
+
expect(core).toContain("history-shell.js");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it.runIf(iifeBuilt)("ships the history shell in the sibling chunk", () => {
|
|
46
|
+
const chunk = readFileSync(dist("history-shell.js"), "utf8");
|
|
47
|
+
for (const marker of RUNTIME_MARKERS) {
|
|
48
|
+
expect(chunk.includes(marker), `chunk is missing "${marker}"`).toBe(true);
|
|
49
|
+
}
|
|
50
|
+
for (const marker of NOT_IN_CHUNK) {
|
|
51
|
+
expect(chunk.includes(marker), `chunk unexpectedly bundles "${marker}"`).toBe(false);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Eager history-shell registration for the bundled (ESM / CJS) builds.
|
|
3
|
+
*
|
|
4
|
+
* npm consumers bundle `history-shell.ts` anyway, so providing it up front
|
|
5
|
+
* keeps history setup synchronous at mount. Like `client-stream-eager.ts`,
|
|
6
|
+
* this module must NOT be reachable from `index-global.ts`: the IIFE/CDN build
|
|
7
|
+
* fetches the `history-shell.js` chunk only when history is used.
|
|
8
|
+
*/
|
|
9
|
+
import * as historyShell from "./history-shell";
|
|
10
|
+
import { provideHistoryShell } from "./history-shell-loader";
|
|
11
|
+
|
|
12
|
+
provideHistoryShell(historyShell);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createChunkLoader } from "./utils/chunk-loader";
|
|
2
|
+
import type { createHistoryShell } from "./history-shell";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Loader indirection for the visitor-history shell (`history-shell.ts`). The
|
|
6
|
+
* ESM/CJS fallback imports `./history-shell` directly (inlined by
|
|
7
|
+
* `--splitting false`, and provided eagerly by `history-shell-eager.ts`); the
|
|
8
|
+
* IIFE/CDN build marks it external and registers a loader for the sibling
|
|
9
|
+
* `history-shell.js` chunk (see `index-global.ts`).
|
|
10
|
+
*/
|
|
11
|
+
export type HistoryShellModule = { createHistoryShell: typeof createHistoryShell };
|
|
12
|
+
|
|
13
|
+
const { setLoader, load, provide, getSync } = createChunkLoader<HistoryShellModule>({
|
|
14
|
+
fallbackImport: () => import("./history-shell"),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
/** Override how the chunk is fetched (the IIFE build registers a sibling-URL loader). */
|
|
18
|
+
export const setHistoryShellLoader = setLoader;
|
|
19
|
+
|
|
20
|
+
/** Load the history shell. Memoized; retries after rejection. */
|
|
21
|
+
export const loadHistoryShell = load;
|
|
22
|
+
|
|
23
|
+
/** Eagerly supply the module (`history-shell-eager.ts`: npm builds and tests). */
|
|
24
|
+
export const provideHistoryShell = provide;
|
|
25
|
+
|
|
26
|
+
/** Synchronous access once loaded/provided; null before that. */
|
|
27
|
+
export const getHistoryShellSync = getSync;
|