@runtypelabs/persona 4.4.2 → 4.6.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.
Files changed (46) 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-C6tFDxKy.d.cts → types-8RICZWQe.d.cts} +6 -0
  4. package/dist/animations/{types-C6tFDxKy.d.ts → types-8RICZWQe.d.ts} +6 -0
  5. package/dist/animations/wipe.d.cts +1 -1
  6. package/dist/animations/wipe.d.ts +1 -1
  7. package/dist/chunk-DFBSCFYN.js +1 -0
  8. package/dist/codegen.cjs +1 -1
  9. package/dist/codegen.js +1 -1
  10. package/dist/index.cjs +50 -50
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +286 -11
  13. package/dist/index.d.ts +286 -11
  14. package/dist/index.global.js +39 -39
  15. package/dist/index.global.js.map +1 -1
  16. package/dist/index.js +51 -51
  17. package/dist/index.js.map +1 -1
  18. package/dist/launcher.global.js.map +1 -1
  19. package/dist/markdown-parsers-entry-NVFT3TE6.js +1 -0
  20. package/dist/runtype-tts-entry-HFUV2UF7.js +1 -0
  21. package/dist/session-reconnect-U77QFUR7.js +1 -0
  22. package/dist/smart-dom-reader.d.cts +147 -8
  23. package/dist/smart-dom-reader.d.ts +147 -8
  24. package/dist/theme-editor-preview.cjs +48 -48
  25. package/dist/theme-editor-preview.d.cts +187 -9
  26. package/dist/theme-editor-preview.d.ts +187 -9
  27. package/dist/theme-editor-preview.js +48 -48
  28. package/dist/theme-editor.cjs +1 -1
  29. package/dist/theme-editor.d.cts +147 -8
  30. package/dist/theme-editor.d.ts +147 -8
  31. package/dist/theme-editor.js +1 -1
  32. package/package.json +2 -2
  33. package/src/client.ts +48 -7
  34. package/src/defaults.ts +9 -1
  35. package/src/generated/runtype-openapi-contract.ts +6 -0
  36. package/src/index-core.ts +5 -0
  37. package/src/reconnect-wake.test.ts +162 -0
  38. package/src/reconnect.test.ts +430 -0
  39. package/src/session-reconnect.ts +282 -0
  40. package/src/session.ts +408 -5
  41. package/src/types.ts +165 -9
  42. package/src/ui.scroll-additive.test.ts +451 -0
  43. package/src/ui.scroll.test.ts +8 -2
  44. package/src/ui.stream-animation-update.test.ts +99 -0
  45. package/src/ui.ts +371 -41
  46. package/src/utils/constants.ts +3 -1
@@ -912,9 +912,12 @@ describe("createAgentExperience streaming scroll", () => {
912
912
  it("re-sticks to the bottom when the user sends a message after scrolling up", () => {
913
913
  const raf = installRafMock();
914
914
  const mount = createMount();
915
+ // Follow-specific: a user send re-sticks to the bottom (anchor-top, the
916
+ // default, would pin the sent message near the top instead).
915
917
  const controller = createAgentExperience(mount, {
916
918
  apiUrl: "https://api.example.com/chat",
917
- launcher: { enabled: false }
919
+ launcher: { enabled: false },
920
+ features: { scrollBehavior: { mode: "follow" } }
918
921
  });
919
922
 
920
923
  const scrollContainer = mount.querySelector<HTMLElement>("#persona-scroll-container");
@@ -941,9 +944,12 @@ describe("createAgentExperience streaming scroll", () => {
941
944
  it("shows a count badge for messages that arrive while paused", () => {
942
945
  const raf = installRafMock();
943
946
  const mount = createMount();
947
+ // Follow-specific paused-badge semantics (wheel-up pauses auto-follow, then
948
+ // a message arrives while paused and below the fold).
944
949
  const controller = createAgentExperience(mount, {
945
950
  apiUrl: "https://api.example.com/chat",
946
- launcher: { enabled: false }
951
+ launcher: { enabled: false },
952
+ features: { scrollBehavior: { mode: "follow" } }
947
953
  });
948
954
 
949
955
  const scrollContainer = mount.querySelector<HTMLElement>("#persona-scroll-container");
@@ -0,0 +1,99 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+
5
+ import { createAgentExperience } from "./ui";
6
+ import {
7
+ registerStreamAnimationPlugin,
8
+ unregisterStreamAnimationPlugin,
9
+ } from "./utils/stream-animation";
10
+ import type { StreamAnimationPlugin } from "./types";
11
+
12
+ // A plugin animation carries its own CSS (built-in animations live in
13
+ // widget.css). Plugin styles are injected only via ensurePluginActive, which the
14
+ // initial mount runs but controller.update() historically skipped — so switching
15
+ // to a plugin animation live used to set the type without ever injecting the CSS.
16
+ const TEST_PLUGIN: StreamAnimationPlugin = {
17
+ name: "test-reveal",
18
+ containerClass: "test-reveal-stream",
19
+ wrap: "char",
20
+ styles: ".test-reveal-stream .persona-stream-char { opacity: 0; }",
21
+ };
22
+
23
+ const createMount = () => {
24
+ const mount = document.createElement("div");
25
+ document.body.appendChild(mount);
26
+ return mount;
27
+ };
28
+
29
+ const styleTag = (mount: HTMLElement) =>
30
+ mount.querySelector('style[data-persona-animation="test-reveal"]');
31
+
32
+ describe("createAgentExperience: stream-animation plugin activation on update()", () => {
33
+ beforeEach(() => {
34
+ vi.stubGlobal("requestAnimationFrame", (cb: (time: number) => void) => {
35
+ cb(0);
36
+ return 1;
37
+ });
38
+ vi.stubGlobal("cancelAnimationFrame", () => {});
39
+ window.scrollTo = vi.fn();
40
+ registerStreamAnimationPlugin(TEST_PLUGIN);
41
+ });
42
+
43
+ afterEach(() => {
44
+ unregisterStreamAnimationPlugin("test-reveal");
45
+ document.body.innerHTML = "";
46
+ vi.restoreAllMocks();
47
+ });
48
+
49
+ it("injects a plugin animation's styles when switched in via update()", () => {
50
+ const mount = createMount();
51
+ const controller = createAgentExperience(mount, {
52
+ apiUrl: "https://api.example.com/chat",
53
+ launcher: { enabled: false },
54
+ features: { streamAnimation: { type: "none" } },
55
+ });
56
+
57
+ // Nothing injected while the type is "none".
58
+ expect(styleTag(mount)).toBeNull();
59
+
60
+ controller.update({
61
+ features: { streamAnimation: { type: "test-reveal" } },
62
+ });
63
+
64
+ // The plugin's <style> is now present, so the animation can actually render.
65
+ expect(styleTag(mount)).not.toBeNull();
66
+
67
+ controller.destroy();
68
+ });
69
+
70
+ it("activates the plugin at mount when configured up front", () => {
71
+ const mount = createMount();
72
+ const controller = createAgentExperience(mount, {
73
+ apiUrl: "https://api.example.com/chat",
74
+ launcher: { enabled: false },
75
+ features: { streamAnimation: { type: "test-reveal" } },
76
+ });
77
+
78
+ expect(styleTag(mount)).not.toBeNull();
79
+ controller.destroy();
80
+ });
81
+
82
+ it("does not duplicate the style tag when the same plugin is re-selected", () => {
83
+ const mount = createMount();
84
+ const controller = createAgentExperience(mount, {
85
+ apiUrl: "https://api.example.com/chat",
86
+ launcher: { enabled: false },
87
+ features: { streamAnimation: { type: "test-reveal" } },
88
+ });
89
+
90
+ controller.update({ features: { streamAnimation: { type: "none" } } });
91
+ controller.update({ features: { streamAnimation: { type: "test-reveal" } } });
92
+
93
+ expect(
94
+ mount.querySelectorAll('style[data-persona-animation="test-reveal"]'),
95
+ ).toHaveLength(1);
96
+
97
+ controller.destroy();
98
+ });
99
+ });