@genesislcap/ai-assistant 14.458.3 → 14.460.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/ai-assistant.api.json +38 -11
- package/dist/ai-assistant.d.ts +49 -5
- package/dist/dts/components/chat-driver/chat-driver.d.ts +3 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/flowing-waves-indicator.d.ts +32 -0
- package/dist/dts/components/flowing-waves-indicator.d.ts.map +1 -0
- package/dist/dts/components/plasma-orb-indicator.d.ts +22 -0
- package/dist/dts/components/plasma-orb-indicator.d.ts.map +1 -0
- package/dist/dts/components/waves-indicator.d.ts +30 -0
- package/dist/dts/components/waves-indicator.d.ts.map +1 -0
- package/dist/dts/main/main.d.ts.map +1 -1
- package/dist/dts/main/main.styles.d.ts.map +1 -1
- package/dist/dts/main/main.template.d.ts.map +1 -1
- package/dist/dts/main/main.types.d.ts +44 -4
- package/dist/dts/main/main.types.d.ts.map +1 -1
- package/dist/dts/utils/animation-exclusivity.d.ts +23 -0
- package/dist/dts/utils/animation-exclusivity.d.ts.map +1 -0
- package/dist/dts/utils/animation-exclusivity.test.d.ts +2 -0
- package/dist/dts/utils/animation-exclusivity.test.d.ts.map +1 -0
- package/dist/esm/components/chat-driver/chat-driver.js +7 -2
- package/dist/esm/components/chat-driver/chat-driver.test.js +24 -0
- package/dist/esm/components/flowing-waves-indicator.js +222 -0
- package/dist/esm/components/plasma-orb-indicator.js +280 -0
- package/dist/esm/components/waves-indicator.js +189 -0
- package/dist/esm/main/main.js +20 -9
- package/dist/esm/main/main.styles.js +62 -7
- package/dist/esm/main/main.template.js +75 -21
- package/dist/esm/main/main.types.js +46 -3
- package/dist/esm/utils/animation-exclusivity.js +33 -0
- package/dist/esm/utils/animation-exclusivity.test.js +52 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -16
- package/src/components/chat-driver/chat-driver.test.ts +36 -0
- package/src/components/chat-driver/chat-driver.ts +10 -2
- package/src/components/flowing-waves-indicator.ts +260 -0
- package/src/components/plasma-orb-indicator.ts +281 -0
- package/src/components/waves-indicator.ts +221 -0
- package/src/main/main.styles.ts +62 -7
- package/src/main/main.template.ts +88 -27
- package/src/main/main.ts +24 -8
- package/src/main/main.types.ts +56 -5
- package/src/utils/animation-exclusivity.test.ts +72 -0
- package/src/utils/animation-exclusivity.ts +40 -0
package/src/main/main.types.ts
CHANGED
|
@@ -53,24 +53,53 @@ export type SuggestionsState =
|
|
|
53
53
|
export interface AiAssistantAnimationDef {
|
|
54
54
|
/** Display label shown in the settings multiselect. */
|
|
55
55
|
label: string;
|
|
56
|
-
/** Short description shown
|
|
57
|
-
|
|
56
|
+
/** Short description shown beneath the label in the categorized multiselect. */
|
|
57
|
+
description: string;
|
|
58
|
+
/** Group heading the option is listed under in the settings multiselect. */
|
|
59
|
+
category: string;
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
/**
|
|
61
63
|
* Registry of all available animations with their display metadata.
|
|
62
64
|
* Adding an entry here automatically extends the {@link AiAssistantAnimation} type.
|
|
63
65
|
*
|
|
66
|
+
* @remarks
|
|
67
|
+
* `loading` (dots), `waves`, `flowingWaves` and `plasma` are interchangeable
|
|
68
|
+
* styles of the same "is the assistant working" indicator and are therefore
|
|
69
|
+
* grouped under the same {@link AiAssistantAnimationDef.category}. They are
|
|
70
|
+
* mutually exclusive — see `LOADING_STYLE_ANIMATIONS`.
|
|
71
|
+
*
|
|
64
72
|
* @beta
|
|
65
73
|
*/
|
|
66
74
|
export const ANIMATION_DEFS = {
|
|
67
75
|
loading: {
|
|
68
|
-
label: '
|
|
69
|
-
|
|
76
|
+
label: 'Dots',
|
|
77
|
+
description: 'Shows pulsing dots while the assistant is generating a response.',
|
|
78
|
+
category: 'Loading style',
|
|
79
|
+
},
|
|
80
|
+
waves: {
|
|
81
|
+
label: 'Waves',
|
|
82
|
+
description:
|
|
83
|
+
'Shows glowing sine waves inside a circle while the assistant is generating a response.',
|
|
84
|
+
category: 'Loading style',
|
|
85
|
+
},
|
|
86
|
+
flowingWaves: {
|
|
87
|
+
label: 'Flowing waves',
|
|
88
|
+
description:
|
|
89
|
+
'Shows coloured waves rising and settling from a line while the assistant is generating a response.',
|
|
90
|
+
category: 'Loading style',
|
|
91
|
+
},
|
|
92
|
+
plasma: {
|
|
93
|
+
label: 'Plasma orb',
|
|
94
|
+
description:
|
|
95
|
+
'Shows a glowing plasma sphere with drifting energy while the assistant is generating a response.',
|
|
96
|
+
category: 'Loading style',
|
|
70
97
|
},
|
|
71
98
|
halo: {
|
|
72
99
|
label: 'Halo',
|
|
73
|
-
|
|
100
|
+
description:
|
|
101
|
+
'Displays a glowing halo around the assistant avatar while a response is streaming.',
|
|
102
|
+
category: 'Effects',
|
|
74
103
|
},
|
|
75
104
|
} satisfies Record<string, AiAssistantAnimationDef>;
|
|
76
105
|
|
|
@@ -87,3 +116,25 @@ export type AiAssistantAnimation = keyof typeof ANIMATION_DEFS;
|
|
|
87
116
|
* @internal
|
|
88
117
|
*/
|
|
89
118
|
export const ALL_ANIMATIONS = Object.keys(ANIMATION_DEFS) as AiAssistantAnimation[];
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The interchangeable "assistant is working" loading-indicator styles. At most
|
|
122
|
+
* one of these may be enabled at a time — enabling one disables the other.
|
|
123
|
+
*
|
|
124
|
+
* @internal
|
|
125
|
+
*/
|
|
126
|
+
export const LOADING_STYLE_ANIMATIONS = [
|
|
127
|
+
'loading',
|
|
128
|
+
'waves',
|
|
129
|
+
'flowingWaves',
|
|
130
|
+
'plasma',
|
|
131
|
+
] as const satisfies readonly AiAssistantAnimation[];
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Animations enabled by default when a consumer opts into the animations
|
|
135
|
+
* feature without specifying an explicit `enabled` list. Keeps the dots loading
|
|
136
|
+
* style (the long-standing default); the waves style is opt-in.
|
|
137
|
+
*
|
|
138
|
+
* @internal
|
|
139
|
+
*/
|
|
140
|
+
export const DEFAULT_ANIMATIONS: AiAssistantAnimation[] = ['loading', 'halo'];
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
|
|
2
|
+
import type { AiAssistantAnimation } from '../main/main.types';
|
|
3
|
+
import { resolveExclusiveLoadingStyle } from './animation-exclusivity';
|
|
4
|
+
|
|
5
|
+
const suite = createLogicSuite('resolveExclusiveLoadingStyle');
|
|
6
|
+
|
|
7
|
+
suite('leaves a selection with only the dots loading style untouched', () => {
|
|
8
|
+
const next: AiAssistantAnimation[] = ['loading', 'halo'];
|
|
9
|
+
assert.equal(resolveExclusiveLoadingStyle(next, ['halo']), ['loading', 'halo']);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
suite('leaves a selection with only the waves loading style untouched', () => {
|
|
13
|
+
const next: AiAssistantAnimation[] = ['waves', 'halo'];
|
|
14
|
+
assert.equal(resolveExclusiveLoadingStyle(next, ['halo']), ['waves', 'halo']);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
suite('leaves a selection with no loading style untouched', () => {
|
|
18
|
+
assert.equal(resolveExclusiveLoadingStyle(['halo'], []), ['halo']);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
suite('drops dots when waves was just added on top of dots', () => {
|
|
22
|
+
// Previously dots was on; user ticks waves → waves wins, dots removed.
|
|
23
|
+
const result = resolveExclusiveLoadingStyle(['loading', 'waves', 'halo'], ['loading', 'halo']);
|
|
24
|
+
assert.equal(result, ['waves', 'halo']);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
suite('drops waves when dots was just added on top of waves', () => {
|
|
28
|
+
// Previously waves was on; user ticks dots → dots wins, waves removed.
|
|
29
|
+
const result = resolveExclusiveLoadingStyle(['loading', 'waves', 'halo'], ['waves', 'halo']);
|
|
30
|
+
assert.equal(result, ['loading', 'halo']);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
suite('preserves the order of the surviving selection', () => {
|
|
34
|
+
const result = resolveExclusiveLoadingStyle(['halo', 'loading', 'waves'], ['halo', 'loading']);
|
|
35
|
+
// waves was just added → loading dropped; halo and waves keep their order.
|
|
36
|
+
assert.equal(result, ['halo', 'waves']);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
suite('falls back to dots when both are present with no prior state (e.g. bad config)', () => {
|
|
40
|
+
const result = resolveExclusiveLoadingStyle(['loading', 'waves', 'halo'], []);
|
|
41
|
+
assert.equal(result, ['loading', 'halo']);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
suite('falls back to dots when both were already present (neither newly added)', () => {
|
|
45
|
+
const result = resolveExclusiveLoadingStyle(['loading', 'waves'], ['loading', 'waves', 'halo']);
|
|
46
|
+
assert.equal(result, ['loading']);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
suite('handles an empty selection', () => {
|
|
50
|
+
assert.equal(resolveExclusiveLoadingStyle([], ['loading']), []);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
suite('switching between any two loading styles keeps only the newly added one', () => {
|
|
54
|
+
// flowingWaves was on; user picks plasma → plasma wins, flowingWaves dropped.
|
|
55
|
+
assert.equal(
|
|
56
|
+
resolveExclusiveLoadingStyle(['flowingWaves', 'plasma', 'halo'], ['flowingWaves', 'halo']),
|
|
57
|
+
['plasma', 'halo'],
|
|
58
|
+
);
|
|
59
|
+
// plasma was on; user picks the dots → dots win, plasma dropped.
|
|
60
|
+
assert.equal(resolveExclusiveLoadingStyle(['plasma', 'loading'], ['plasma']), ['loading']);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
suite('drops all but the newly added style when several are somehow selected', () => {
|
|
64
|
+
const result = resolveExclusiveLoadingStyle(
|
|
65
|
+
['loading', 'waves', 'flowingWaves', 'plasma'],
|
|
66
|
+
['loading', 'waves', 'plasma'],
|
|
67
|
+
);
|
|
68
|
+
// flowingWaves is the only one absent from `previous`, so it wins.
|
|
69
|
+
assert.equal(result, ['flowingWaves']);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
suite.run();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AiAssistantAnimation } from '../main/main.types';
|
|
2
|
+
import { LOADING_STYLE_ANIMATIONS } from '../main/main.types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Enforces that at most one loading-indicator style (dots vs. waves) is enabled
|
|
6
|
+
* at a time. The two are alternative presentations of the same "assistant is
|
|
7
|
+
* working" state, so selecting one must deselect the other.
|
|
8
|
+
*
|
|
9
|
+
* The settings control is a multiselect (checkboxes), which permits selecting
|
|
10
|
+
* both; this resolver makes the loading-style group behave like a radio group
|
|
11
|
+
* by dropping the previously-selected style whenever a new one is added.
|
|
12
|
+
*
|
|
13
|
+
* @param next - The freshly-selected animation list (e.g. emitted by the
|
|
14
|
+
* multiselect, or read from consumer config).
|
|
15
|
+
* @param previous - The animation list in effect before this change. Used to
|
|
16
|
+
* work out which loading style was just added so the other can be dropped.
|
|
17
|
+
* Pass `[]` when resolving an initial/config value with no prior state.
|
|
18
|
+
* @returns `next` with at most one loading style retained. When both are
|
|
19
|
+
* present and neither is newly added (e.g. a misconfigured `enabled` list),
|
|
20
|
+
* the first entry of `LOADING_STYLE_ANIMATIONS` (dots) wins.
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export function resolveExclusiveLoadingStyle(
|
|
25
|
+
next: AiAssistantAnimation[],
|
|
26
|
+
previous: AiAssistantAnimation[] = [],
|
|
27
|
+
): AiAssistantAnimation[] {
|
|
28
|
+
const selectedStyles = LOADING_STYLE_ANIMATIONS.filter((style) => next.includes(style));
|
|
29
|
+
if (selectedStyles.length <= 1) {
|
|
30
|
+
return next;
|
|
31
|
+
}
|
|
32
|
+
// Both styles selected — keep whichever was just added (absent from
|
|
33
|
+
// `previous`); fall back to the first declared style on ambiguity.
|
|
34
|
+
const justAdded = selectedStyles.find((style) => !previous.includes(style)) ?? selectedStyles[0];
|
|
35
|
+
return next.filter(
|
|
36
|
+
(animation) =>
|
|
37
|
+
animation === justAdded ||
|
|
38
|
+
!(LOADING_STYLE_ANIMATIONS as readonly AiAssistantAnimation[]).includes(animation),
|
|
39
|
+
);
|
|
40
|
+
}
|