@runtypelabs/persona 4.6.1 → 4.8.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 (120) hide show
  1. package/dist/animations/glyph-cycle.cjs +2 -2
  2. package/dist/animations/glyph-cycle.d.cts +1 -1
  3. package/dist/animations/glyph-cycle.d.ts +1 -1
  4. package/dist/animations/glyph-cycle.js +2 -2
  5. package/dist/animations/{types-CSmiKRVa.d.cts → types-BsZtXPKK.d.cts} +43 -3
  6. package/dist/animations/{types-CSmiKRVa.d.ts → types-BsZtXPKK.d.ts} +43 -3
  7. package/dist/animations/wipe.cjs +2 -2
  8. package/dist/animations/wipe.d.cts +1 -1
  9. package/dist/animations/wipe.d.ts +1 -1
  10. package/dist/chunk-5EIIHQLQ.js +1 -0
  11. package/dist/codegen.cjs +12 -12
  12. package/dist/codegen.js +14 -14
  13. package/dist/index.cjs +91 -68
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +918 -174
  16. package/dist/index.d.ts +918 -174
  17. package/dist/index.global.js +81 -57
  18. package/dist/index.global.js.map +1 -1
  19. package/dist/index.js +89 -66
  20. package/dist/index.js.map +1 -1
  21. package/dist/install.global.js +1 -1
  22. package/dist/install.global.js.map +1 -1
  23. package/dist/launcher.global.js +3 -2
  24. package/dist/launcher.global.js.map +1 -1
  25. package/dist/markdown-parsers.js +24 -24
  26. package/dist/plugin-kit.cjs +1 -1
  27. package/dist/plugin-kit.js +1 -1
  28. package/dist/runtype-tts-entry-UJAEF7NZ.js +1 -0
  29. package/dist/runtype-tts.js +1 -1
  30. package/dist/session-reconnect-JKIJBHS5.js +1 -0
  31. package/dist/smart-dom-reader.cjs +17 -17
  32. package/dist/smart-dom-reader.d.cts +753 -15
  33. package/dist/smart-dom-reader.d.ts +753 -15
  34. package/dist/smart-dom-reader.js +17 -17
  35. package/dist/testing.cjs +3 -3
  36. package/dist/testing.js +3 -3
  37. package/dist/theme-editor-preview.cjs +81 -58
  38. package/dist/theme-editor-preview.d.cts +761 -15
  39. package/dist/theme-editor-preview.d.ts +761 -15
  40. package/dist/theme-editor-preview.js +81 -58
  41. package/dist/theme-editor.cjs +6 -6
  42. package/dist/theme-editor.d.cts +753 -15
  43. package/dist/theme-editor.d.ts +753 -15
  44. package/dist/theme-editor.js +10 -10
  45. package/dist/theme-reference.cjs +1 -1
  46. package/dist/theme-reference.d.cts +74 -0
  47. package/dist/theme-reference.d.ts +74 -0
  48. package/dist/theme-reference.js +1 -1
  49. package/dist/voice-worklet-player.cjs +2 -2
  50. package/dist/voice-worklet-player.js +2 -2
  51. package/dist/webmcp-polyfill.js +2 -2
  52. package/dist/widget.css +1 -1
  53. package/package.json +2 -3
  54. package/src/artifacts-session.test.ts +178 -0
  55. package/src/client.test.ts +500 -1
  56. package/src/client.ts +285 -93
  57. package/src/components/artifact-card.test.ts +333 -0
  58. package/src/components/artifact-card.ts +75 -28
  59. package/src/components/artifact-inline.test.ts +1328 -0
  60. package/src/components/artifact-inline.ts +920 -0
  61. package/src/components/artifact-pane.test.ts +1042 -0
  62. package/src/components/artifact-pane.ts +440 -131
  63. package/src/components/artifact-preview.test.ts +1155 -0
  64. package/src/components/artifact-preview.ts +994 -0
  65. package/src/components/pill-composer-builder.test.ts +6 -2
  66. package/src/components/pill-composer-builder.ts +6 -6
  67. package/src/components/reasoning-bubble.ts +1 -13
  68. package/src/components/registry.ts +38 -3
  69. package/src/components/tool-bubble.ts +1 -13
  70. package/src/defaults.ts +1 -0
  71. package/src/generated/runtype-openapi-contract.ts +55 -3
  72. package/src/index-core.ts +20 -1
  73. package/src/index.ts +8 -0
  74. package/src/markdown-parsers-loader.test.ts +158 -0
  75. package/src/markdown-parsers-loader.ts +74 -9
  76. package/src/runtime/host-layout.test.ts +163 -0
  77. package/src/runtime/host-layout.ts +110 -7
  78. package/src/runtime/init.ts +18 -61
  79. package/src/runtime/persist-state.test.ts +118 -0
  80. package/src/session.ts +76 -22
  81. package/src/styles/widget.css +773 -26
  82. package/src/theme-editor/preview.ts +2 -0
  83. package/src/theme-editor/sections.test.ts +26 -1
  84. package/src/theme-editor/sections.ts +10 -2
  85. package/src/theme-reference.ts +2 -2
  86. package/src/tool-call-display-defaults.test.ts +1 -0
  87. package/src/types/theme.ts +77 -0
  88. package/src/types.ts +516 -17
  89. package/src/ui.artifact-pane-gating.test.ts +636 -0
  90. package/src/ui.component-directive.test.ts +104 -0
  91. package/src/ui.composer-bar.test.ts +60 -2
  92. package/src/ui.detached-panel.test.ts +1049 -0
  93. package/src/ui.scroll-additive.test.ts +1 -1
  94. package/src/ui.streaming-coalescing.test.ts +312 -0
  95. package/src/ui.tool-display.test.ts +51 -0
  96. package/src/ui.ts +933 -214
  97. package/src/utils/artifact-custom-actions.ts +128 -0
  98. package/src/utils/artifact-display.test.ts +42 -0
  99. package/src/utils/artifact-display.ts +84 -0
  100. package/src/utils/artifact-file.test.ts +116 -0
  101. package/src/utils/artifact-file.ts +117 -0
  102. package/src/utils/artifact-gate.test.ts +112 -5
  103. package/src/utils/artifact-gate.ts +39 -14
  104. package/src/utils/artifact-loading-status.ts +55 -0
  105. package/src/utils/artifact-status-label.ts +190 -0
  106. package/src/utils/buttons.ts +7 -1
  107. package/src/utils/code-highlight.test.ts +186 -0
  108. package/src/utils/code-highlight.ts +400 -0
  109. package/src/utils/icons.ts +2 -0
  110. package/src/utils/roving-tablist.test.ts +152 -0
  111. package/src/utils/roving-tablist.ts +111 -0
  112. package/src/utils/spinner.ts +45 -0
  113. package/src/utils/theme.test.ts +48 -0
  114. package/src/utils/theme.ts +7 -0
  115. package/src/utils/tokens.ts +91 -0
  116. package/src/utils/tool-loading-animation.test.ts +32 -0
  117. package/src/utils/tool-loading-animation.ts +24 -0
  118. package/dist/chunk-DFBSCFYN.js +0 -1
  119. package/dist/runtype-tts-entry-HFUV2UF7.js +0 -1
  120. package/dist/session-reconnect-U77QFUR7.js +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runtypelabs/persona",
3
- "version": "4.6.1",
3
+ "version": "4.8.0",
4
4
  "description": "Themeable, pluggable streaming agent widget for websites, in plain JS with support for voice input and reasoning / tool output.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -74,8 +74,7 @@
74
74
  "idiomorph": "^0.7.4",
75
75
  "lucide": "^1.18.0",
76
76
  "marked": "^12.0.2",
77
- "partial-json": "^0.1.7",
78
- "zod": "^3.22.4"
77
+ "partial-json": "^0.1.7"
79
78
  },
80
79
  "devDependencies": {
81
80
  "@size-limit/file": "^12.1.0",
@@ -77,4 +77,182 @@ describe("AgentWidgetSession artifacts", () => {
77
77
  expect(session.getArtifacts()).toHaveLength(1);
78
78
  expect(session.getArtifacts()[0].markdown).toBe("C");
79
79
  });
80
+
81
+ it("stores file metadata via applyArtifactStreamEvent and keeps accumulating deltas", () => {
82
+ const session = new AgentWidgetSession(
83
+ {},
84
+ {
85
+ onMessagesChanged: () => {},
86
+ onStatusChanged: () => {},
87
+ onStreamingChanged: () => {},
88
+ onArtifactsState: () => {}
89
+ }
90
+ );
91
+ const file = { path: "outputs/cat.html", mimeType: "text/html", language: "html" };
92
+ session.injectTestEvent({
93
+ type: "artifact_start",
94
+ id: "f1",
95
+ artifactType: "markdown",
96
+ title: "outputs/cat.html",
97
+ file
98
+ });
99
+ session.injectTestEvent({ type: "artifact_delta", id: "f1", artDelta: "```html\n" });
100
+ session.injectTestEvent({ type: "artifact_delta", id: "f1", artDelta: "<h1>hi</h1>\n```" });
101
+ const rec = session.getArtifactById("f1");
102
+ expect(rec?.file).toEqual(file);
103
+ expect(rec?.markdown).toBe("```html\n<h1>hi</h1>\n```");
104
+ });
105
+
106
+ it("upsertArtifact injects a card transcript block by default", () => {
107
+ const session = new AgentWidgetSession(
108
+ {},
109
+ {
110
+ onMessagesChanged: () => {},
111
+ onStatusChanged: () => {},
112
+ onStreamingChanged: () => {},
113
+ onArtifactsState: () => {}
114
+ }
115
+ );
116
+ const rec = session.upsertArtifact({
117
+ artifactType: "markdown",
118
+ title: "Doc",
119
+ content: "# Hi"
120
+ });
121
+ const block = session
122
+ .getMessages()
123
+ .find((m) => m.id === `artifact-ref-${rec.id}`);
124
+ expect(block).toBeDefined();
125
+ expect(block?.role).toBe("assistant");
126
+ const parsed = JSON.parse(block!.rawContent!);
127
+ expect(parsed.component).toBe("PersonaArtifactCard");
128
+ expect(parsed.props).toMatchObject({
129
+ artifactId: rec.id,
130
+ title: "Doc",
131
+ artifactType: "markdown",
132
+ status: "complete",
133
+ markdown: "# Hi"
134
+ });
135
+ });
136
+
137
+ it("upsertArtifact injects an inline block when display resolves to inline", () => {
138
+ const session = new AgentWidgetSession(
139
+ { features: { artifacts: { enabled: true, display: "inline" } } },
140
+ {
141
+ onMessagesChanged: () => {},
142
+ onStatusChanged: () => {},
143
+ onStreamingChanged: () => {},
144
+ onArtifactsState: () => {}
145
+ }
146
+ );
147
+ const rec = session.upsertArtifact({
148
+ artifactType: "component",
149
+ title: "Chart",
150
+ component: "MyChart",
151
+ props: { series: [1, 2] }
152
+ });
153
+ const block = session
154
+ .getMessages()
155
+ .find((m) => m.id === `artifact-ref-${rec.id}`);
156
+ expect(block).toBeDefined();
157
+ const parsed = JSON.parse(block!.rawContent!);
158
+ expect(parsed.component).toBe("PersonaArtifactInline");
159
+ // Inline blocks render component artifacts through the registry, so the
160
+ // component name AND its props are embedded in the block props (the
161
+ // registry is not persisted, so hydration re-invokes the renderer from
162
+ // these).
163
+ expect(parsed.props.component).toBe("MyChart");
164
+ expect(parsed.props.componentProps).toEqual({ series: [1, 2] });
165
+ expect(parsed.props.status).toBe("complete");
166
+ });
167
+
168
+ it("upsertArtifact with transcript: false injects no transcript block", () => {
169
+ const session = new AgentWidgetSession(
170
+ {},
171
+ {
172
+ onMessagesChanged: () => {},
173
+ onStatusChanged: () => {},
174
+ onStreamingChanged: () => {},
175
+ onArtifactsState: () => {}
176
+ }
177
+ );
178
+ session.upsertArtifact({
179
+ id: "pane-only",
180
+ artifactType: "markdown",
181
+ content: "C",
182
+ transcript: false
183
+ });
184
+ expect(session.getArtifacts()).toHaveLength(1);
185
+ expect(session.getMessages()).toHaveLength(0);
186
+ });
187
+
188
+ it("upsertArtifact update to an existing artifact does not duplicate the block", () => {
189
+ const session = new AgentWidgetSession(
190
+ {},
191
+ {
192
+ onMessagesChanged: () => {},
193
+ onStatusChanged: () => {},
194
+ onStreamingChanged: () => {},
195
+ onArtifactsState: () => {}
196
+ }
197
+ );
198
+ session.upsertArtifact({ id: "a1", artifactType: "markdown", content: "v1" });
199
+ session.upsertArtifact({ id: "a1", artifactType: "markdown", content: "v2" });
200
+ const blocks = session
201
+ .getMessages()
202
+ .filter((m) => m.id === "artifact-ref-a1");
203
+ expect(blocks).toHaveLength(1);
204
+ expect(session.getArtifacts()).toHaveLength(1);
205
+ expect(session.getArtifactById("a1")?.markdown).toBe("v2");
206
+ });
207
+
208
+ it("upsertArtifact re-upsert rebuilds the existing block's persisted props", () => {
209
+ const session = new AgentWidgetSession(
210
+ {},
211
+ {
212
+ onMessagesChanged: () => {},
213
+ onStatusChanged: () => {},
214
+ onStreamingChanged: () => {},
215
+ onArtifactsState: () => {}
216
+ }
217
+ );
218
+ session.upsertArtifact({
219
+ id: "a1",
220
+ artifactType: "markdown",
221
+ title: "T1",
222
+ content: "v1"
223
+ });
224
+ session.upsertArtifact({
225
+ id: "a1",
226
+ artifactType: "markdown",
227
+ title: "T2",
228
+ content: "v2"
229
+ });
230
+ const blocks = session
231
+ .getMessages()
232
+ .filter((m) => m.id === "artifact-ref-a1");
233
+ expect(blocks).toHaveLength(1);
234
+ const parsed = JSON.parse(blocks[0].rawContent!);
235
+ expect(parsed.props.markdown).toBe("v2");
236
+ expect(parsed.props.title).toBe("T2");
237
+ });
238
+
239
+ it("stores file metadata via upsertArtifact", () => {
240
+ const session = new AgentWidgetSession(
241
+ {},
242
+ {
243
+ onMessagesChanged: () => {},
244
+ onStatusChanged: () => {},
245
+ onStreamingChanged: () => {},
246
+ onArtifactsState: () => {}
247
+ }
248
+ );
249
+ const file = { path: "notes.md", mimeType: "text/markdown" };
250
+ session.upsertArtifact({
251
+ artifactType: "markdown",
252
+ title: "notes.md",
253
+ content: "```md\n# Hi\n\n```",
254
+ file
255
+ });
256
+ expect(session.getArtifactById(session.getArtifacts()[0].id)?.file).toEqual(file);
257
+ });
80
258
  });