@runtypelabs/persona 4.13.0 → 4.15.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 +4 -4
- package/dist/animations/glyph-cycle.d.cts +1 -1
- package/dist/animations/glyph-cycle.d.ts +1 -1
- package/dist/animations/{types-DveIaNx6.d.cts → types-BpWGm7_6.d.cts} +17 -0
- package/dist/animations/{types-DveIaNx6.d.ts → types-BpWGm7_6.d.ts} +17 -0
- package/dist/animations/wipe.d.cts +1 -1
- package/dist/animations/wipe.d.ts +1 -1
- package/dist/chunk-QJ4LV2KW.js +1 -0
- package/dist/codegen.cjs +12 -11
- package/dist/codegen.js +14 -13
- package/dist/{context-mentions-ONG7A7M6.js → context-mentions-BTSTIBFC.js} +1 -1
- package/dist/context-mentions.cjs +11 -8
- package/dist/context-mentions.d.cts +339 -22
- package/dist/context-mentions.d.ts +339 -22
- package/dist/context-mentions.js +11 -8
- package/dist/index.cjs +68 -67
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +483 -48
- package/dist/index.d.ts +483 -48
- package/dist/index.global.js +61 -58
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +70 -69
- package/dist/index.js.map +1 -1
- package/dist/launcher.global.js +5 -2
- package/dist/launcher.global.js.map +1 -1
- package/dist/smart-dom-reader.d.cts +339 -22
- package/dist/smart-dom-reader.d.ts +339 -22
- package/dist/theme-editor-preview.cjs +67 -67
- package/dist/theme-editor-preview.d.cts +355 -23
- package/dist/theme-editor-preview.d.ts +355 -23
- package/dist/theme-editor-preview.js +75 -75
- package/dist/theme-editor.cjs +10 -10
- package/dist/theme-editor.d.cts +376 -24
- package/dist/theme-editor.d.ts +376 -24
- package/dist/theme-editor.js +10 -10
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.d.cts +38 -0
- package/dist/theme-reference.d.ts +38 -0
- package/dist/theme-reference.js +1 -1
- package/dist/widget.css +1 -1
- package/package.json +1 -1
- package/src/artifacts-session.test.ts +106 -0
- package/src/ask-user-question-tool.ts +10 -7
- package/src/client.test.ts +2 -2
- package/src/client.ts +4 -1
- package/src/components/artifact-card.ts +13 -2
- package/src/components/artifact-inline.ts +11 -2
- package/src/components/artifact-preview.ts +1 -1
- package/src/components/composer-builder.test.ts +2 -0
- package/src/components/composer-builder.ts +1 -1
- package/src/components/composer-parts.test.ts +105 -4
- package/src/components/composer-parts.ts +54 -16
- package/src/components/message-bubble.test.ts +7 -1
- package/src/components/message-bubble.ts +11 -8
- package/src/components/messages.ts +5 -2
- package/src/components/panel.ts +31 -5
- package/src/components/pill-composer-builder.test.ts +18 -0
- package/src/components/suggestions.test.ts +233 -0
- package/src/components/suggestions.ts +463 -81
- package/src/components/widget-view.ts +4 -0
- package/src/defaults.ts +5 -3
- package/src/generated/runtype-openapi-contract.ts +17 -0
- package/src/index-core.ts +52 -2
- package/src/launcher-global.ts +1 -1
- package/src/plugins/types.ts +71 -3
- package/src/presets.ts +3 -3
- package/src/session.ts +55 -12
- package/src/styles/widget-styles.test.ts +162 -0
- package/src/styles/widget.css +440 -1
- package/src/suggest-replies-tool.test.ts +233 -2
- package/src/suggest-replies-tool.ts +115 -39
- package/src/theme-editor/index.ts +5 -0
- package/src/theme-editor/presets.test.ts +43 -0
- package/src/theme-editor/presets.ts +101 -87
- package/src/theme-editor/preview-utils.test.ts +34 -0
- package/src/theme-editor/preview-utils.ts +77 -2
- package/src/theme-editor/sections.test.ts +72 -7
- package/src/theme-editor/sections.ts +113 -13
- package/src/theme-editor/state-preferences.test.ts +15 -0
- package/src/theme-editor/state.ts +46 -0
- package/src/theme-editor/types.ts +15 -1
- package/src/theme-editor/webmcp/tools.test.ts +13 -0
- package/src/theme-editor/webmcp/tools.ts +5 -0
- package/src/theme-reference.ts +9 -2
- package/src/types/theme.ts +32 -0
- package/src/types.ts +291 -25
- package/src/ui.artifact-pane-gating.test.ts +5 -5
- package/src/ui.config-preferences.test.ts +166 -0
- package/src/ui.detached-panel.test.ts +1 -1
- package/src/ui.suggest-replies.test.ts +1066 -1
- package/src/ui.ts +311 -45
- package/src/ui.typing-indicator.test.ts +135 -0
- package/src/utils/artifact-display.test.ts +180 -16
- package/src/utils/artifact-display.ts +155 -14
- package/src/utils/artifact-file.test.ts +1 -1
- package/src/utils/code-generators.test.ts +40 -0
- package/src/utils/code-generators.ts +22 -0
- package/src/utils/config-merge.test.ts +84 -0
- package/src/utils/config-merge.ts +6 -1
- package/src/utils/feature-preferences.test.ts +326 -0
- package/src/utils/feature-preferences.ts +498 -0
- package/src/utils/icons.test.ts +26 -0
- package/src/utils/icons.ts +8 -0
- package/src/utils/theme.test.ts +171 -0
- package/src/utils/tokens.ts +71 -7
- package/dist/chunk-MMUPR2JW.js +0 -1
|
@@ -27,7 +27,7 @@ beforeAll(() => {
|
|
|
27
27
|
*
|
|
28
28
|
* The pane's own `update()` unhides its shell whenever records exist, so the
|
|
29
29
|
* gate in `syncArtifactPane` must re-assert `persona-hidden` for artifacts
|
|
30
|
-
* whose resolved mode is "
|
|
30
|
+
* whose resolved mode is "collapsed" or "inline". The original implementation only
|
|
31
31
|
* removed the class in the show branch and never re-added it, so inline-mode
|
|
32
32
|
* artifacts still auto-opened the pane.
|
|
33
33
|
*/
|
|
@@ -88,8 +88,8 @@ describe("artifact pane auto-open gating by display mode", () => {
|
|
|
88
88
|
controller.destroy();
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
-
it('keeps the pane hidden for "
|
|
92
|
-
const { mount, controller } = mountWithDisplay("
|
|
91
|
+
it('keeps the pane hidden for "collapsed" mode until an explicit open', () => {
|
|
92
|
+
const { mount, controller } = mountWithDisplay("collapsed");
|
|
93
93
|
upsertSample(controller);
|
|
94
94
|
expect(paneEl(mount).classList.contains("persona-hidden")).toBe(true);
|
|
95
95
|
|
|
@@ -109,7 +109,7 @@ describe("artifact pane auto-open gating by display mode", () => {
|
|
|
109
109
|
urlWithBlob.createObjectURL = () => "blob:persona-test";
|
|
110
110
|
urlWithBlob.revokeObjectURL = () => {};
|
|
111
111
|
try {
|
|
112
|
-
const { mount, controller } = mountWithDisplay("
|
|
112
|
+
const { mount, controller } = mountWithDisplay("collapsed");
|
|
113
113
|
upsertSample(controller);
|
|
114
114
|
|
|
115
115
|
// Recreate the reference card the way the default renderer shapes it
|
|
@@ -170,7 +170,7 @@ describe("artifact card custom actions (full widget)", () => {
|
|
|
170
170
|
artifacts: {
|
|
171
171
|
enabled: true,
|
|
172
172
|
allowedTypes: ["markdown", "component"],
|
|
173
|
-
display: "
|
|
173
|
+
display: "collapsed",
|
|
174
174
|
cardActions,
|
|
175
175
|
},
|
|
176
176
|
},
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { afterEach, beforeAll, describe, expect, it } from "vitest";
|
|
4
|
+
|
|
5
|
+
import { createAgentExperience } from "./ui";
|
|
6
|
+
import type {
|
|
7
|
+
AgentWidgetArtifactsFeature,
|
|
8
|
+
AgentWidgetConfig,
|
|
9
|
+
WidgetPreferenceSlice,
|
|
10
|
+
} from "./types";
|
|
11
|
+
|
|
12
|
+
beforeAll(() => {
|
|
13
|
+
// jsdom does not implement matchMedia; the pane's layout code touches it.
|
|
14
|
+
if (!window.matchMedia) {
|
|
15
|
+
window.matchMedia = ((query: string) => ({
|
|
16
|
+
matches: false,
|
|
17
|
+
media: query,
|
|
18
|
+
onchange: null,
|
|
19
|
+
addListener: () => {},
|
|
20
|
+
removeListener: () => {},
|
|
21
|
+
addEventListener: () => {},
|
|
22
|
+
removeEventListener: () => {},
|
|
23
|
+
dispatchEvent: () => false,
|
|
24
|
+
})) as unknown as typeof window.matchMedia;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Config-level `preferences` are per-instance display overrides baked over
|
|
30
|
+
* `features` (utils/feature-preferences.ts `resolveConfigPreferences`). The
|
|
31
|
+
* pane's auto-open state is the observable for the effective display mode:
|
|
32
|
+
* "panel" opens it on upsert, "inline"/"collapsed" keep it hidden.
|
|
33
|
+
*
|
|
34
|
+
* The update() path must re-resolve from the pre-preference base features:
|
|
35
|
+
* changing or clearing preferences may not stack onto previously overlaid
|
|
36
|
+
* values.
|
|
37
|
+
*/
|
|
38
|
+
describe("config preferences overrides", () => {
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
document.body.innerHTML = "";
|
|
41
|
+
try {
|
|
42
|
+
window.localStorage.clear();
|
|
43
|
+
} catch {
|
|
44
|
+
/* jsdom edge cases */
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
function mountWith(
|
|
49
|
+
display: AgentWidgetArtifactsFeature["display"],
|
|
50
|
+
preferences?: WidgetPreferenceSlice
|
|
51
|
+
) {
|
|
52
|
+
const mount = document.createElement("div");
|
|
53
|
+
document.body.appendChild(mount);
|
|
54
|
+
const config: AgentWidgetConfig = {
|
|
55
|
+
apiUrl: "https://api.example.com/chat",
|
|
56
|
+
launcher: { enabled: false },
|
|
57
|
+
features: {
|
|
58
|
+
artifacts: {
|
|
59
|
+
enabled: true,
|
|
60
|
+
allowedTypes: ["markdown", "component"],
|
|
61
|
+
...(display ? { display } : {}),
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
...(preferences ? { preferences } : {}),
|
|
65
|
+
};
|
|
66
|
+
const controller = createAgentExperience(mount, config);
|
|
67
|
+
return { mount, controller };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function paneHidden(mount: HTMLElement): boolean {
|
|
71
|
+
const el = mount.querySelector<HTMLElement>(".persona-artifact-pane");
|
|
72
|
+
expect(el).not.toBeNull();
|
|
73
|
+
return el!.classList.contains("persona-hidden");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function upsertSample(
|
|
77
|
+
controller: ReturnType<typeof createAgentExperience>,
|
|
78
|
+
id = "prefs-test"
|
|
79
|
+
) {
|
|
80
|
+
controller.upsertArtifact({
|
|
81
|
+
id,
|
|
82
|
+
title: "Preferences test",
|
|
83
|
+
artifactType: "markdown",
|
|
84
|
+
content: "# Hello",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
it("applies initial preferences over base features", () => {
|
|
89
|
+
// Base says panel (auto-open); the instance preference says inline.
|
|
90
|
+
const { mount, controller } = mountWith("panel", {
|
|
91
|
+
artifacts: { display: "inline" },
|
|
92
|
+
});
|
|
93
|
+
upsertSample(controller);
|
|
94
|
+
expect(paneHidden(mount)).toBe(true);
|
|
95
|
+
controller.destroy();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("applies preferences passed through controller.update()", () => {
|
|
99
|
+
const { mount, controller } = mountWith("panel");
|
|
100
|
+
controller.update({ preferences: { artifacts: { display: "collapsed" } } });
|
|
101
|
+
upsertSample(controller);
|
|
102
|
+
expect(paneHidden(mount)).toBe(true);
|
|
103
|
+
controller.destroy();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// A "panel" upsert marks the pane user-opened, which is sticky by design,
|
|
107
|
+
// so the remaining tests observe the effective mode through the transcript
|
|
108
|
+
// block type instead: refreshArtifactReferenceBlocks re-materializes blocks
|
|
109
|
+
// on a live display change ("inline" → .persona-artifact-inline preview,
|
|
110
|
+
// otherwise the reference card).
|
|
111
|
+
function inlineBlockCount(mount: HTMLElement): number {
|
|
112
|
+
return mount.querySelectorAll(".persona-artifact-inline").length;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
it("clearing preferences reverts to the base features", () => {
|
|
116
|
+
const { mount, controller } = mountWith("inline", {
|
|
117
|
+
artifacts: { display: "panel" },
|
|
118
|
+
});
|
|
119
|
+
upsertSample(controller);
|
|
120
|
+
expect(inlineBlockCount(mount)).toBe(0);
|
|
121
|
+
|
|
122
|
+
// Explicit-undefined deletes the key (config-merge reset semantics); the
|
|
123
|
+
// effective mode must fall back to the base "inline", not keep "panel".
|
|
124
|
+
controller.update({ preferences: undefined });
|
|
125
|
+
expect(inlineBlockCount(mount)).toBe(1);
|
|
126
|
+
controller.destroy();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("an update's slice replaces the previous slice; dropped keys revert", () => {
|
|
130
|
+
const { mount, controller } = mountWith("collapsed");
|
|
131
|
+
controller.update({
|
|
132
|
+
preferences: {
|
|
133
|
+
showReasoning: false,
|
|
134
|
+
artifacts: { display: "inline" },
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
upsertSample(controller);
|
|
138
|
+
expect(inlineBlockCount(mount)).toBe(1);
|
|
139
|
+
|
|
140
|
+
// The new slice keeps showReasoning but drops the artifacts key. Patch
|
|
141
|
+
// semantics would strand display:"inline"; replace semantics revert the
|
|
142
|
+
// block to the base "collapsed" card.
|
|
143
|
+
controller.update({ preferences: { showReasoning: false } });
|
|
144
|
+
expect(inlineBlockCount(mount)).toBe(0);
|
|
145
|
+
controller.destroy();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("replacing preferences re-resolves from the base, not the prior overlay", () => {
|
|
149
|
+
const { mount, controller } = mountWith(
|
|
150
|
+
{ default: "collapsed", byKind: { markdown: "inline" } },
|
|
151
|
+
{ artifacts: { display: "panel" } }
|
|
152
|
+
);
|
|
153
|
+
upsertSample(controller);
|
|
154
|
+
expect(inlineBlockCount(mount)).toBe(0);
|
|
155
|
+
|
|
156
|
+
// The object-form preference refines the base, so byKind.markdown →
|
|
157
|
+
// "inline" survives and the block converts to an inline preview. If the
|
|
158
|
+
// prior "panel" string overlay had been folded into the base, byKind
|
|
159
|
+
// would be gone and this would resolve "collapsed" (a card).
|
|
160
|
+
controller.update({
|
|
161
|
+
preferences: { artifacts: { display: { default: "collapsed" } } },
|
|
162
|
+
});
|
|
163
|
+
expect(inlineBlockCount(mount)).toBe(1);
|
|
164
|
+
controller.destroy();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
@@ -907,7 +907,7 @@ describe("createAgentExperience welded artifact split chrome", () => {
|
|
|
907
907
|
|
|
908
908
|
controller.hideArtifacts();
|
|
909
909
|
|
|
910
|
-
//
|
|
910
|
+
// Same as pane-closed: container carries the border, panel does not.
|
|
911
911
|
expect(mount.classList.contains("persona-artifact-welded-split")).toBe(false);
|
|
912
912
|
expect(container?.style.border).toContain("--persona-panel-border");
|
|
913
913
|
expect(panel?.style.border).toBe("");
|