@agent-native/toolkit 0.10.0 → 0.10.2

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 (49) hide show
  1. package/dist/chat-history.css +2 -2
  2. package/dist/composer/PromptComposer.d.ts.map +1 -1
  3. package/dist/composer/PromptComposer.js +1 -24
  4. package/dist/composer/PromptComposer.js.map +1 -1
  5. package/dist/composer/RealtimeVoiceMode.d.ts.map +1 -1
  6. package/dist/composer/RealtimeVoiceMode.js +59 -11
  7. package/dist/composer/RealtimeVoiceMode.js.map +1 -1
  8. package/dist/composer/RealtimeVoiceMode.spec.js +68 -7
  9. package/dist/composer/RealtimeVoiceMode.spec.js.map +1 -1
  10. package/dist/composer/useRealtimeVoiceMode.d.ts.map +1 -1
  11. package/dist/composer/useRealtimeVoiceMode.js +32 -0
  12. package/dist/composer/useRealtimeVoiceMode.js.map +1 -1
  13. package/dist/composer/useRealtimeVoiceMode.spec.js +25 -2
  14. package/dist/composer/useRealtimeVoiceMode.spec.js.map +1 -1
  15. package/dist/conformance/conformance.spec.js +30 -1
  16. package/dist/conformance/conformance.spec.js.map +1 -1
  17. package/dist/conformance/runner.d.ts.map +1 -1
  18. package/dist/conformance/runner.js +75 -1
  19. package/dist/conformance/runner.js.map +1 -1
  20. package/dist/editor/SharedRichEditor.d.ts.map +1 -1
  21. package/dist/editor/SharedRichEditor.js +3 -2
  22. package/dist/editor/SharedRichEditor.js.map +1 -1
  23. package/dist/editor/SlashCommandMenu.d.ts +8 -0
  24. package/dist/editor/SlashCommandMenu.d.ts.map +1 -1
  25. package/dist/editor/SlashCommandMenu.js +6 -0
  26. package/dist/editor/SlashCommandMenu.js.map +1 -1
  27. package/dist/editor/SlashCommandMenu.spec.d.ts +2 -0
  28. package/dist/editor/SlashCommandMenu.spec.d.ts.map +1 -0
  29. package/dist/editor/SlashCommandMenu.spec.js +20 -0
  30. package/dist/editor/SlashCommandMenu.spec.js.map +1 -0
  31. package/dist/editor/index.d.ts +1 -1
  32. package/dist/editor/index.d.ts.map +1 -1
  33. package/dist/editor/index.js +1 -1
  34. package/dist/editor/index.js.map +1 -1
  35. package/dist/styles.css +197 -21
  36. package/package.json +1 -1
  37. package/src/chat-history.css +2 -2
  38. package/src/composer/PromptComposer.tsx +0 -27
  39. package/src/composer/RealtimeVoiceMode.spec.tsx +131 -9
  40. package/src/composer/RealtimeVoiceMode.tsx +124 -31
  41. package/src/composer/useRealtimeVoiceMode.spec.ts +28 -2
  42. package/src/composer/useRealtimeVoiceMode.tsx +30 -0
  43. package/src/conformance/conformance.spec.tsx +61 -1
  44. package/src/conformance/runner.tsx +153 -1
  45. package/src/editor/SharedRichEditor.tsx +13 -2
  46. package/src/editor/SlashCommandMenu.spec.ts +33 -0
  47. package/src/editor/SlashCommandMenu.tsx +20 -0
  48. package/src/editor/index.ts +2 -0
  49. package/src/styles.css +197 -21
@@ -1,7 +1,7 @@
1
1
  export { createSharedEditorExtensions, MARKDOWN_DIALECT_CONFIG, type RichMarkdownDialect, type RichMarkdownEditorPreset, type RichMarkdownCollabUser, type SharedEditorCollab, type SharedEditorFeatures, type CreateSharedEditorExtensionsOptions, } from "./extensions.js";
2
2
  export { useCollabReconcile, getEditorMarkdown, RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION, type UseCollabReconcileOptions, type UseCollabReconcileResult, } from "./useCollabReconcile.js";
3
3
  export { applyDocSurgically, defaultParseValue, diffTopLevel, type TopLevelDiff, } from "./surgical-apply.js";
4
- export { SlashCommandMenu, DEFAULT_SLASH_COMMANDS, createImageSlashCommand, type SlashCommandItem, type SlashCommandMenuProps, } from "./SlashCommandMenu.js";
4
+ export { SlashCommandMenu, DEFAULT_SLASH_COMMANDS, createImageSlashCommand, filterSlashCommandItems, type SlashCommandItem, type SlashCommandMenuProps, type SlashCommandFeatureFlags, } from "./SlashCommandMenu.js";
5
5
  export { SharedImage, createImageExtension, pickAndInsertImage, type ImageUploadFn, type SharedImageOptions, } from "./ImageExtension.js";
6
6
  export { BubbleToolbar, buildDefaultBubbleItems, type BubbleToolbarItem, type BubbleToolbarProps, } from "./BubbleToolbar.js";
7
7
  export { SharedRichEditor, type SharedRichEditorProps, } from "./SharedRichEditor.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,mCAAmC,GACzC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sCAAsC,EACtC,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,GAChC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,mCAAmC,GACzC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,UAAU,EACV,oCAAoC,EACpC,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,8BAA8B,EACnC,KAAK,2BAA2B,EAChC,KAAK,sBAAsB,EAC3B,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,GAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,+BAA+B,EAC/B,KAAK,mCAAmC,EACxC,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,GAC5B,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,mCAAmC,GACzC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sCAAsC,EACtC,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,GAC9B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,GAChC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,mCAAmC,GACzC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,UAAU,EACV,oCAAoC,EACpC,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,8BAA8B,EACnC,KAAK,2BAA2B,EAChC,KAAK,sBAAsB,EAC3B,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,GAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,+BAA+B,EAC/B,KAAK,mCAAmC,EACxC,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,GAC5B,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
@@ -1,7 +1,7 @@
1
1
  export { createSharedEditorExtensions, MARKDOWN_DIALECT_CONFIG, } from "./extensions.js";
2
2
  export { useCollabReconcile, getEditorMarkdown, RICH_MARKDOWN_PROGRAMMATIC_TRANSACTION, } from "./useCollabReconcile.js";
3
3
  export { applyDocSurgically, defaultParseValue, diffTopLevel, } from "./surgical-apply.js";
4
- export { SlashCommandMenu, DEFAULT_SLASH_COMMANDS, createImageSlashCommand, } from "./SlashCommandMenu.js";
4
+ export { SlashCommandMenu, DEFAULT_SLASH_COMMANDS, createImageSlashCommand, filterSlashCommandItems, } from "./SlashCommandMenu.js";
5
5
  export { SharedImage, createImageExtension, pickAndInsertImage, } from "./ImageExtension.js";
6
6
  export { BubbleToolbar, buildDefaultBubbleItems, } from "./BubbleToolbar.js";
7
7
  export { SharedRichEditor, } from "./SharedRichEditor.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,GAOxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sCAAsC,GAGvC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GAEb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,GAGxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,kBAAkB,GAGnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,uBAAuB,GAGxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,GAIvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,4BAA4B,GAG7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,UAAU,EACV,oCAAoC,GAIrC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,GASrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,+BAA+B,GAIhC,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,GAOxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,sCAAsC,GAGvC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GAEb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,GAIxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,kBAAkB,GAGnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,aAAa,EACb,uBAAuB,GAGxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,GAIvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,4BAA4B,GAG7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,UAAU,EACV,oCAAoC,GAIrC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,GASrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,+BAA+B,GAIhC,MAAM,4BAA4B,CAAC"}
package/dist/styles.css CHANGED
@@ -20,37 +20,213 @@
20
20
  */
21
21
  @source "./**/*.{js,ts,tsx}";
22
22
 
23
- .agent-realtime-voice-working::after {
23
+ @property --agent-realtime-voice-angle {
24
+ syntax: "<angle>";
25
+ inherits: true;
26
+ initial-value: 0deg;
27
+ }
28
+
29
+ .agent-realtime-voice-glow {
30
+ --agent-realtime-voice-angle: 0deg;
31
+ --agent-realtime-voice-proximity: 72;
32
+ --agent-realtime-voice-edge-sensitivity: 30;
33
+ --agent-realtime-voice-color-sensitivity: 50;
34
+ --agent-realtime-voice-cone-spread: 25;
35
+ --agent-realtime-voice-fill-opacity: 0.5;
36
+ --agent-realtime-voice-card-bg: hsl(var(--background));
37
+ --agent-realtime-voice-glow-color: 40 80% 80%;
38
+ --agent-realtime-voice-glow-padding: 18px;
39
+ --agent-realtime-voice-gradient-one: radial-gradient(
40
+ at 80% 55%,
41
+ #c084fc 0,
42
+ transparent 50%
43
+ );
44
+ --agent-realtime-voice-gradient-two: radial-gradient(
45
+ at 69% 34%,
46
+ #f472b6 0,
47
+ transparent 50%
48
+ );
49
+ --agent-realtime-voice-gradient-three: radial-gradient(
50
+ at 8% 6%,
51
+ #38bdf8 0,
52
+ transparent 50%
53
+ );
54
+ --agent-realtime-voice-gradient-four: radial-gradient(
55
+ at 41% 38%,
56
+ #c084fc 0,
57
+ transparent 50%
58
+ );
59
+ --agent-realtime-voice-gradient-five: radial-gradient(
60
+ at 86% 85%,
61
+ #f472b6 0,
62
+ transparent 50%
63
+ );
64
+ --agent-realtime-voice-gradient-six: radial-gradient(
65
+ at 82% 18%,
66
+ #38bdf8 0,
67
+ transparent 50%
68
+ );
69
+ --agent-realtime-voice-gradient-seven: radial-gradient(
70
+ at 51% 4%,
71
+ #f472b6 0,
72
+ transparent 50%
73
+ );
24
74
  position: absolute;
25
75
  z-index: 0;
76
+ inset: -1px;
77
+ border-radius: inherit;
78
+ isolation: isolate;
79
+ pointer-events: none;
80
+ transform: translate3d(0, 0, 0.01px);
81
+ }
82
+
83
+ .agent-realtime-voice-working {
84
+ --agent-realtime-voice-proximity: 96;
85
+ }
86
+
87
+ .agent-realtime-voice-glow::before,
88
+ .agent-realtime-voice-glow::after {
89
+ position: absolute;
26
90
  inset: 0;
91
+ z-index: 0;
27
92
  border-radius: inherit;
28
93
  pointer-events: none;
29
94
  content: "";
95
+ transition: opacity 250ms ease-out;
96
+ }
97
+
98
+ .agent-realtime-voice-glow::before {
99
+ border: 1px solid transparent;
100
+ background:
101
+ linear-gradient(
102
+ var(--agent-realtime-voice-card-bg),
103
+ var(--agent-realtime-voice-card-bg)
104
+ )
105
+ padding-box,
106
+ linear-gradient(transparent 0 100%) border-box,
107
+ var(--agent-realtime-voice-gradient-one) border-box,
108
+ var(--agent-realtime-voice-gradient-two) border-box,
109
+ var(--agent-realtime-voice-gradient-three) border-box,
110
+ var(--agent-realtime-voice-gradient-four) border-box,
111
+ var(--agent-realtime-voice-gradient-five) border-box,
112
+ var(--agent-realtime-voice-gradient-six) border-box,
113
+ var(--agent-realtime-voice-gradient-seven) border-box,
114
+ linear-gradient(#c084fc 0 100%) border-box;
115
+ opacity: calc(
116
+ (
117
+ var(--agent-realtime-voice-proximity) -
118
+ var(--agent-realtime-voice-color-sensitivity)
119
+ ) /
120
+ (100 - var(--agent-realtime-voice-color-sensitivity))
121
+ );
122
+ mask-image: conic-gradient(
123
+ from var(--agent-realtime-voice-angle) at center,
124
+ #000 calc(var(--agent-realtime-voice-cone-spread) * 1%),
125
+ rgb(0 0 0 / 75%) calc((var(--agent-realtime-voice-cone-spread) + 4) * 1%),
126
+ rgb(0 0 0 / 45%) calc((var(--agent-realtime-voice-cone-spread) + 8) * 1%),
127
+ rgb(0 0 0 / 18%) calc((var(--agent-realtime-voice-cone-spread) + 12) * 1%),
128
+ transparent calc((var(--agent-realtime-voice-cone-spread) + 15) * 1%),
129
+ transparent calc((100 - var(--agent-realtime-voice-cone-spread) - 15) * 1%),
130
+ rgb(0 0 0 / 18%)
131
+ calc((100 - var(--agent-realtime-voice-cone-spread) - 12) * 1%),
132
+ rgb(0 0 0 / 45%)
133
+ calc((100 - var(--agent-realtime-voice-cone-spread) - 8) * 1%),
134
+ rgb(0 0 0 / 75%)
135
+ calc((100 - var(--agent-realtime-voice-cone-spread) - 4) * 1%),
136
+ #000 calc((100 - var(--agent-realtime-voice-cone-spread)) * 1%)
137
+ );
30
138
  }
31
139
 
32
- @media (prefers-reduced-motion: no-preference) {
33
- .agent-realtime-voice-working::after {
34
- background: linear-gradient(
35
- 90deg,
36
- transparent 0%,
37
- transparent 36%,
38
- hsl(var(--foreground) / 0.14) 50%,
39
- transparent 64%,
40
- transparent 100%
140
+ .agent-realtime-voice-glow::after {
141
+ border: 1px solid transparent;
142
+ background:
143
+ var(--agent-realtime-voice-gradient-one) padding-box,
144
+ var(--agent-realtime-voice-gradient-two) padding-box,
145
+ var(--agent-realtime-voice-gradient-three) padding-box,
146
+ var(--agent-realtime-voice-gradient-four) padding-box,
147
+ var(--agent-realtime-voice-gradient-five) padding-box,
148
+ var(--agent-realtime-voice-gradient-six) padding-box,
149
+ var(--agent-realtime-voice-gradient-seven) padding-box,
150
+ linear-gradient(#c084fc 0 100%) padding-box;
151
+ mask-image:
152
+ linear-gradient(to bottom, #000, #000),
153
+ radial-gradient(ellipse at 50% 50%, #000 40%, transparent 65%),
154
+ radial-gradient(ellipse at 66% 66%, #000 5%, transparent 40%),
155
+ radial-gradient(ellipse at 33% 33%, #000 5%, transparent 40%),
156
+ radial-gradient(ellipse at 66% 33%, #000 5%, transparent 40%),
157
+ radial-gradient(ellipse at 33% 66%, #000 5%, transparent 40%),
158
+ conic-gradient(
159
+ from var(--agent-realtime-voice-angle) at center,
160
+ transparent 5%,
161
+ #000 15%,
162
+ #000 85%,
163
+ transparent 95%
41
164
  );
42
- background-repeat: repeat;
43
- background-size: 14rem 100%;
44
- animation: agent-realtime-voice-shine 2.6s linear infinite;
45
- }
165
+ mask-composite: subtract, add, add, add, add, add;
166
+ opacity: calc(
167
+ var(--agent-realtime-voice-fill-opacity) *
168
+ (
169
+ var(--agent-realtime-voice-proximity) -
170
+ var(--agent-realtime-voice-color-sensitivity)
171
+ ) /
172
+ (100 - var(--agent-realtime-voice-color-sensitivity))
173
+ );
174
+ mix-blend-mode: soft-light;
175
+ }
46
176
 
47
- @keyframes agent-realtime-voice-shine {
48
- from {
49
- background-position: 0 0;
50
- }
177
+ .agent-realtime-voice-edge-light {
178
+ position: absolute;
179
+ z-index: 1;
180
+ inset: calc(var(--agent-realtime-voice-glow-padding) * -1);
181
+ border-radius: inherit;
182
+ pointer-events: none;
183
+ opacity: calc(
184
+ (
185
+ var(--agent-realtime-voice-proximity) -
186
+ var(--agent-realtime-voice-edge-sensitivity)
187
+ ) /
188
+ (100 - var(--agent-realtime-voice-edge-sensitivity))
189
+ );
190
+ mask-image: conic-gradient(
191
+ from var(--agent-realtime-voice-angle) at center,
192
+ #000 2.5%,
193
+ rgb(0 0 0 / 85%) 4%,
194
+ rgb(0 0 0 / 55%) 7%,
195
+ rgb(0 0 0 / 25%) 11%,
196
+ transparent 15%,
197
+ transparent 85%,
198
+ rgb(0 0 0 / 25%) 89%,
199
+ rgb(0 0 0 / 55%) 93%,
200
+ rgb(0 0 0 / 85%) 96%,
201
+ #000 97.5%
202
+ );
203
+ mix-blend-mode: plus-lighter;
204
+ transition: opacity 250ms ease-out;
205
+ }
206
+
207
+ .agent-realtime-voice-edge-light::before {
208
+ position: absolute;
209
+ inset: var(--agent-realtime-voice-glow-padding);
210
+ border-radius: inherit;
211
+ content: "";
212
+ box-shadow:
213
+ inset 0 0 0 1px hsl(var(--agent-realtime-voice-glow-color) / 100%),
214
+ inset 0 0 1px hsl(var(--agent-realtime-voice-glow-color) / 60%),
215
+ inset 0 0 3px hsl(var(--agent-realtime-voice-glow-color) / 50%),
216
+ inset 0 0 6px hsl(var(--agent-realtime-voice-glow-color) / 40%),
217
+ inset 0 0 15px hsl(var(--agent-realtime-voice-glow-color) / 30%),
218
+ inset 0 0 25px 2px hsl(var(--agent-realtime-voice-glow-color) / 20%),
219
+ inset 0 0 50px 2px hsl(var(--agent-realtime-voice-glow-color) / 10%),
220
+ 0 0 1px hsl(var(--agent-realtime-voice-glow-color) / 60%),
221
+ 0 0 3px hsl(var(--agent-realtime-voice-glow-color) / 50%),
222
+ 0 0 6px hsl(var(--agent-realtime-voice-glow-color) / 40%),
223
+ 0 0 15px hsl(var(--agent-realtime-voice-glow-color) / 30%),
224
+ 0 0 25px 2px hsl(var(--agent-realtime-voice-glow-color) / 20%),
225
+ 0 0 50px 2px hsl(var(--agent-realtime-voice-glow-color) / 10%);
226
+ }
51
227
 
52
- to {
53
- background-position: 14rem 0;
54
- }
228
+ @media (prefers-reduced-motion: reduce) {
229
+ .agent-realtime-voice-glow {
230
+ --agent-realtime-voice-angle: 35deg;
55
231
  }
56
232
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/toolkit",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "Reusable app-building UI and helpers for Agent-Native apps.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -211,7 +211,7 @@
211
211
  white-space: nowrap;
212
212
  font-size: 12px;
213
213
  font-weight: 500;
214
- color: hsl(var(--foreground));
214
+ color: hsl(var(--muted-foreground));
215
215
  }
216
216
 
217
217
  .an-chat-history-row--active .an-chat-history-row__title {
@@ -227,7 +227,7 @@
227
227
  .an-chat-history--rail
228
228
  .an-chat-history-row--pinned:not(.an-chat-history-row--active)
229
229
  .an-chat-history-row__title {
230
- color: hsl(var(--foreground));
230
+ color: hsl(var(--muted-foreground));
231
231
  }
232
232
 
233
233
  .an-chat-history-row__timestamp {
@@ -59,7 +59,6 @@ import type {
59
59
  } from "./types.js";
60
60
 
61
61
  const MAX_INLINE_TEXT_FILE_CHARS = 60_000;
62
- const SUBMIT_ENGINE_STATUS_TIMEOUT_MS = 1000;
63
62
 
64
63
  /**
65
64
  * Files the user attached via the "+" button in PromptComposer. The host owns
@@ -532,31 +531,6 @@ function PromptComposerInner({
532
531
  window.dispatchEvent(new Event("agent-engine:configured-changed"));
533
532
  }
534
533
  }, []);
535
- const ensureAgentEngineReadyForSubmit = useCallback(async () => {
536
- if (!resolvedModelStatusChecksEnabled) return true;
537
- const state =
538
- agentEngineConfigured.state === "missing"
539
- ? "missing"
540
- : await modelsAdapter.fetchAgentEngineConfiguredState!(
541
- resolvedModelStatusChecksEnabled,
542
- {
543
- timeoutMs: SUBMIT_ENGINE_STATUS_TIMEOUT_MS,
544
- },
545
- );
546
- if (state === "missing") {
547
- bounceMissingKeySetup();
548
- return false;
549
- }
550
- if (typeof window !== "undefined") {
551
- window.dispatchEvent(new Event("agent-engine:configured-changed"));
552
- }
553
- return false;
554
- }, [
555
- agentEngineConfigured.state,
556
- bounceMissingKeySetup,
557
- modelsAdapter,
558
- resolvedModelStatusChecksEnabled,
559
- ]);
560
534
  const retryAgentEngineStatus = useCallback(() => {
561
535
  if (typeof window !== "undefined") {
562
536
  window.dispatchEvent(new Event("agent-engine:configured-changed"));
@@ -653,7 +627,6 @@ function PromptComposerInner({
653
627
  initialText={initialText}
654
628
  initialTextKey={initialTextKey}
655
629
  onSubmit={handleSubmit}
656
- onBeforeSubmit={ensureAgentEngineReadyForSubmit}
657
630
  clearOnSubmit={!preserveDraftOnSubmit}
658
631
  plusMenuMode={
659
632
  plusMenuMode ?? (attachmentsEnabled ? "upload-only" : "hidden")
@@ -89,9 +89,28 @@ const copy: RealtimeVoiceModeCopy = {
89
89
  describe("RealtimeVoiceMode", () => {
90
90
  let container: HTMLDivElement;
91
91
  let root: Root;
92
+ let animate: ReturnType<typeof vi.fn>;
93
+ let cancelGlowAnimation: ReturnType<typeof vi.fn>;
94
+ let updateGlowPlaybackRate: ReturnType<typeof vi.fn>;
95
+ let originalAnimate: typeof HTMLElement.prototype.animate | undefined;
92
96
 
93
97
  beforeEach(() => {
94
98
  vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
99
+ originalAnimate = HTMLElement.prototype.animate;
100
+ cancelGlowAnimation = vi.fn();
101
+ updateGlowPlaybackRate = vi.fn();
102
+ animate = vi.fn(
103
+ () =>
104
+ ({
105
+ cancel: cancelGlowAnimation,
106
+ playbackRate: 1,
107
+ updatePlaybackRate: updateGlowPlaybackRate,
108
+ }) as unknown as Animation,
109
+ );
110
+ Object.defineProperty(HTMLElement.prototype, "animate", {
111
+ configurable: true,
112
+ value: animate,
113
+ });
95
114
  container = document.createElement("div");
96
115
  document.body.appendChild(container);
97
116
  root = createRoot(container);
@@ -100,6 +119,14 @@ describe("RealtimeVoiceMode", () => {
100
119
  afterEach(() => {
101
120
  act(() => root.unmount());
102
121
  container.remove();
122
+ if (originalAnimate) {
123
+ Object.defineProperty(HTMLElement.prototype, "animate", {
124
+ configurable: true,
125
+ value: originalAnimate,
126
+ });
127
+ } else {
128
+ Reflect.deleteProperty(HTMLElement.prototype, "animate");
129
+ }
103
130
  vi.unstubAllGlobals();
104
131
  });
105
132
 
@@ -291,22 +318,21 @@ describe("RealtimeVoiceMode", () => {
291
318
  expect(document.body.textContent).toContain("Set up voice mode");
292
319
  const prompt = document.querySelector<HTMLElement>('[role="dialog"]');
293
320
  expect(prompt?.className).toContain(
294
- "w-[min(calc(100vw-2rem),var(--radix-popover-content-available-width,30rem),30rem)]",
321
+ "w-[min(calc(100vw-2rem),var(--radix-popover-content-available-width,24rem),24rem)]",
295
322
  );
296
323
  expect(prompt?.dataset.collisionBoundary).toBe("agent-panel");
297
324
  const actions = Array.from(prompt?.querySelectorAll("div") ?? []).find(
298
- (element) => element.className.includes("sm:flex-row"),
325
+ (element) => element.className.includes("bg-muted/30"),
299
326
  );
300
327
  const actionClasses = actions?.className.split(/\s+/) ?? [];
301
- expect(actionClasses).toContain("sm:flex-wrap");
302
- expect(actionClasses).not.toContain("sm:flex-nowrap");
328
+ expect(actionClasses).toContain("grid");
329
+ expect(actionClasses).toContain("rounded-lg");
303
330
  const buttons = Array.from(
304
331
  document.querySelectorAll<HTMLButtonElement>("button"),
305
332
  );
306
333
  expect(
307
- buttons.find((button) => button.textContent === "Connect Builder.io")
308
- ?.className,
309
- ).toContain("whitespace-nowrap");
334
+ buttons.find((button) => button.textContent === "Connect Builder.io"),
335
+ ).toBeDefined();
310
336
  act(() =>
311
337
  buttons
312
338
  .find((button) => button.textContent === "Connect Builder.io")
@@ -766,7 +792,31 @@ describe("RealtimeVoiceMode", () => {
766
792
  },
767
793
  );
768
794
 
769
- it("shines only while the agent is working", () => {
795
+ it.each(["listening", "speaking"] as const)(
796
+ "keeps a soft session glow while %s",
797
+ (state) => {
798
+ render(
799
+ <RealtimeVoiceModeDock
800
+ state={state}
801
+ copy={copy}
802
+ chatVisible={false}
803
+ onToggleChat={vi.fn()}
804
+ onEndVoiceMode={vi.fn()}
805
+ />,
806
+ );
807
+ expect(
808
+ document.querySelector(".agent-realtime-voice-glow"),
809
+ ).not.toBeNull();
810
+ expect(
811
+ document.querySelector(".agent-realtime-voice-edge-light"),
812
+ ).not.toBeNull();
813
+ expect(
814
+ document.querySelector(".agent-realtime-voice-working"),
815
+ ).toBeNull();
816
+ },
817
+ );
818
+
819
+ it("brightens the live glow while working", () => {
770
820
  render(
771
821
  <RealtimeVoiceModeDock
772
822
  state="working"
@@ -776,10 +826,14 @@ describe("RealtimeVoiceMode", () => {
776
826
  onEndVoiceMode={vi.fn()}
777
827
  />,
778
828
  );
829
+ expect(document.querySelector(".agent-realtime-voice-glow")).not.toBeNull();
779
830
  expect(
780
831
  document.querySelector(".agent-realtime-voice-working"),
781
832
  ).not.toBeNull();
833
+ });
782
834
 
835
+ it("changes glow speed without restarting or jumping its rotation", () => {
836
+ vi.useFakeTimers();
783
837
  render(
784
838
  <RealtimeVoiceModeDock
785
839
  state="listening"
@@ -789,9 +843,77 @@ describe("RealtimeVoiceMode", () => {
789
843
  onEndVoiceMode={vi.fn()}
790
844
  />,
791
845
  );
792
- expect(document.querySelector(".agent-realtime-voice-working")).toBeNull();
846
+ const glow = document.querySelector('[data-realtime-voice-glow="true"]');
847
+
848
+ expect(animate).toHaveBeenCalledTimes(1);
849
+ expect(animate).toHaveBeenCalledWith(
850
+ [
851
+ { "--agent-realtime-voice-angle": "0deg" },
852
+ { "--agent-realtime-voice-angle": "360deg" },
853
+ ],
854
+ {
855
+ duration: 12_000,
856
+ easing: "linear",
857
+ iterations: Number.POSITIVE_INFINITY,
858
+ },
859
+ );
860
+ expect(updateGlowPlaybackRate).toHaveBeenLastCalledWith(1);
861
+
862
+ render(
863
+ <RealtimeVoiceModeDock
864
+ state="working"
865
+ copy={copy}
866
+ chatVisible={false}
867
+ onToggleChat={vi.fn()}
868
+ onEndVoiceMode={vi.fn()}
869
+ />,
870
+ );
871
+
872
+ expect(document.querySelector('[data-realtime-voice-glow="true"]')).toBe(
873
+ glow,
874
+ );
875
+ expect(animate).toHaveBeenCalledTimes(1);
876
+ expect(cancelGlowAnimation).not.toHaveBeenCalled();
877
+ expect(updateGlowPlaybackRate).toHaveBeenLastCalledWith(2.4);
878
+
879
+ render(
880
+ <RealtimeVoiceModeDock
881
+ state="speaking"
882
+ copy={copy}
883
+ chatVisible={false}
884
+ onToggleChat={vi.fn()}
885
+ onEndVoiceMode={vi.fn()}
886
+ />,
887
+ );
888
+
889
+ expect(animate).toHaveBeenCalledTimes(1);
890
+ expect(cancelGlowAnimation).not.toHaveBeenCalled();
891
+ expect(updateGlowPlaybackRate).toHaveBeenLastCalledWith(2.4);
892
+
893
+ act(() => vi.advanceTimersByTime(800));
894
+ expect(updateGlowPlaybackRate).toHaveBeenLastCalledWith(1);
895
+ vi.useRealTimers();
793
896
  });
794
897
 
898
+ it.each(["connecting", "error", "ending"] as const)(
899
+ "does not show the live glow while %s",
900
+ (state) => {
901
+ render(
902
+ <RealtimeVoiceModeDock
903
+ state={state}
904
+ copy={copy}
905
+ chatVisible={false}
906
+ onToggleChat={vi.fn()}
907
+ onEndVoiceMode={vi.fn()}
908
+ />,
909
+ );
910
+ expect(document.querySelector(".agent-realtime-voice-glow")).toBeNull();
911
+ expect(
912
+ document.querySelector(".agent-realtime-voice-working"),
913
+ ).toBeNull();
914
+ },
915
+ );
916
+
795
917
  it("shows an unmistakable loader and ignores early audio until connected", () => {
796
918
  const audioLevels = createRealtimeVoiceAudioLevelStore();
797
919
  audioLevels.set({ input: 0.8, output: 0 });