@agents24/chat-react 0.4.0 → 0.5.1

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 (132) hide show
  1. package/README.md +92 -18
  2. package/compatibility.json +10 -10
  3. package/dist/chunk-SSUO4EPD.js +189 -0
  4. package/dist/chunk-SSUO4EPD.js.map +1 -0
  5. package/dist/chunk-ZCNHLFRB.js +108 -0
  6. package/dist/chunk-ZCNHLFRB.js.map +1 -0
  7. package/dist/index.cjs +112 -95
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.ts +0 -1
  10. package/dist/index.js +362 -68
  11. package/dist/index.js.map +1 -1
  12. package/dist/mcp-oauth.d.ts +13 -0
  13. package/dist/runtime/index.cjs +594 -0
  14. package/dist/runtime/index.cjs.map +1 -0
  15. package/dist/runtime/index.d.ts +2 -0
  16. package/dist/runtime/index.js +458 -0
  17. package/dist/runtime/index.js.map +1 -0
  18. package/dist/runtime/input-contract.d.ts +20 -0
  19. package/dist/runtime/use-agent-chat-runtime.d.ts +83 -0
  20. package/dist/scaffold/app.d.ts +30 -0
  21. package/dist/scaffold/components/chat/chat-composer.d.ts +21 -0
  22. package/dist/scaffold/components/chat/chat-message.d.ts +21 -0
  23. package/dist/scaffold/components/chat/chat-shell.d.ts +8 -0
  24. package/dist/scaffold/components/chat/collapsible-user-message.d.ts +3 -0
  25. package/dist/scaffold/components/chat/external-link-dialog.d.ts +2 -0
  26. package/dist/scaffold/components/chat/identity-control.d.ts +4 -0
  27. package/dist/scaffold/components/chat/message-parts.d.ts +12 -0
  28. package/dist/scaffold/components/chat/theme-menu.d.ts +1 -0
  29. package/dist/scaffold/components/chat/thread-sidebar.d.ts +16 -0
  30. package/dist/scaffold/components/chat/timeline-loading.d.ts +7 -0
  31. package/dist/scaffold/components/chat/turn-outline.d.ts +4 -0
  32. package/dist/scaffold/components/theme-provider.d.ts +20 -0
  33. package/dist/scaffold/components/ui/attachment.d.ts +24 -0
  34. package/dist/scaffold/components/ui/bubble.d.ts +17 -0
  35. package/dist/scaffold/components/ui/button-group.d.ts +11 -0
  36. package/dist/scaffold/components/ui/button.d.ts +10 -0
  37. package/dist/scaffold/components/ui/dialog.d.ts +17 -0
  38. package/dist/scaffold/components/ui/dropdown-menu.d.ts +29 -0
  39. package/dist/scaffold/components/ui/input.d.ts +3 -0
  40. package/dist/scaffold/components/ui/marker.d.ts +11 -0
  41. package/dist/scaffold/components/ui/message-scroller.d.ts +10 -0
  42. package/dist/scaffold/components/ui/message.d.ts +10 -0
  43. package/dist/scaffold/components/ui/popover.d.ts +6 -0
  44. package/dist/scaffold/components/ui/select.d.ts +8 -0
  45. package/dist/scaffold/components/ui/separator.d.ts +4 -0
  46. package/dist/scaffold/components/ui/sheet.d.ts +14 -0
  47. package/dist/scaffold/components/ui/sidebar.d.ts +69 -0
  48. package/dist/scaffold/components/ui/skeleton.d.ts +2 -0
  49. package/dist/scaffold/components/ui/textarea.d.ts +3 -0
  50. package/dist/scaffold/components/ui/tooltip.d.ts +15 -0
  51. package/dist/scaffold/hooks/use-mobile.d.ts +1 -0
  52. package/dist/scaffold/identity.d.ts +10 -0
  53. package/dist/scaffold/index.cjs +2270 -0
  54. package/dist/scaffold/index.cjs.map +1 -0
  55. package/dist/scaffold/index.d.ts +14 -0
  56. package/dist/scaffold/index.js +2244 -0
  57. package/dist/scaffold/index.js.map +1 -0
  58. package/dist/scaffold/lib/utils.d.ts +2 -0
  59. package/dist/styles.css +143 -298
  60. package/dist/types.d.ts +3 -13
  61. package/dist/ui/adapters.d.ts +1 -1
  62. package/dist/ui/agent-chat-actions.d.ts +12 -5
  63. package/dist/ui/agent-chat-composer.d.ts +2 -1
  64. package/dist/ui/agent-chat-context-compression-row.d.ts +5 -0
  65. package/dist/ui/agent-chat-context-status.d.ts +13 -0
  66. package/dist/ui/agent-chat-message.d.ts +7 -5
  67. package/dist/ui/agent-response-timeline.d.ts +29 -7
  68. package/dist/ui/ask-user-interaction-state.d.ts +20 -0
  69. package/dist/ui/ask-user-interaction.d.ts +8 -0
  70. package/dist/ui/index.cjs +1392 -272
  71. package/dist/ui/index.cjs.map +1 -1
  72. package/dist/ui/index.d.ts +5 -0
  73. package/dist/ui/index.js +2380 -65
  74. package/dist/ui/index.js.map +1 -1
  75. package/dist/ui/tool-sessions.d.ts +70 -0
  76. package/dist/ui/use-audio-recorder.d.ts +8 -0
  77. package/package.json +27 -12
  78. package/scaffold/components.json +25 -0
  79. package/scaffold/manifest.json +28 -0
  80. package/scaffold/src/app.tsx +71 -0
  81. package/scaffold/src/chat.css +54 -0
  82. package/scaffold/src/components/chat/chat-composer.tsx +237 -0
  83. package/scaffold/src/components/chat/chat-message.tsx +76 -0
  84. package/scaffold/src/components/chat/chat-shell.tsx +257 -0
  85. package/scaffold/src/components/chat/collapsible-user-message.tsx +37 -0
  86. package/scaffold/src/components/chat/external-link-dialog.tsx +48 -0
  87. package/scaffold/src/components/chat/identity-control.tsx +69 -0
  88. package/scaffold/src/components/chat/message-parts.tsx +83 -0
  89. package/scaffold/src/components/chat/theme-menu.tsx +79 -0
  90. package/scaffold/src/components/chat/thread-sidebar.tsx +114 -0
  91. package/scaffold/src/components/chat/timeline-loading.ts +17 -0
  92. package/scaffold/src/components/chat/turn-outline.tsx +73 -0
  93. package/scaffold/src/components/theme-provider.tsx +91 -0
  94. package/scaffold/src/components/ui/attachment.tsx +204 -0
  95. package/scaffold/src/components/ui/bubble.tsx +125 -0
  96. package/scaffold/src/components/ui/button-group.tsx +83 -0
  97. package/scaffold/src/components/ui/button.tsx +65 -0
  98. package/scaffold/src/components/ui/dialog.tsx +171 -0
  99. package/scaffold/src/components/ui/dropdown-menu.tsx +271 -0
  100. package/scaffold/src/components/ui/input.tsx +19 -0
  101. package/scaffold/src/components/ui/marker.tsx +69 -0
  102. package/scaffold/src/components/ui/message-scroller.tsx +129 -0
  103. package/scaffold/src/components/ui/message.tsx +92 -0
  104. package/scaffold/src/components/ui/popover.tsx +40 -0
  105. package/scaffold/src/components/ui/select.tsx +92 -0
  106. package/scaffold/src/components/ui/separator.tsx +28 -0
  107. package/scaffold/src/components/ui/sheet.tsx +150 -0
  108. package/scaffold/src/components/ui/sidebar.tsx +677 -0
  109. package/scaffold/src/components/ui/skeleton.tsx +13 -0
  110. package/scaffold/src/components/ui/textarea.tsx +18 -0
  111. package/scaffold/src/components/ui/tooltip.tsx +56 -0
  112. package/scaffold/src/hooks/use-mobile.ts +24 -0
  113. package/scaffold/src/identity.ts +17 -0
  114. package/scaffold/src/index.css +222 -0
  115. package/scaffold/src/index.tsx +39 -0
  116. package/scaffold/src/lib/utils.ts +6 -0
  117. package/scaffold/styles.css +3 -0
  118. package/dist/chunk-CHAU7FNW.js +0 -140
  119. package/dist/chunk-CHAU7FNW.js.map +0 -1
  120. package/dist/chunk-LI67M74F.js +0 -445
  121. package/dist/chunk-LI67M74F.js.map +0 -1
  122. package/dist/chunk-NLEOWTZG.js +0 -1327
  123. package/dist/chunk-NLEOWTZG.js.map +0 -1
  124. package/dist/renderers.d.ts +0 -10
  125. package/dist/templates/agent-chat-app.d.ts +0 -18
  126. package/dist/templates/agent-chat-layout.d.ts +0 -69
  127. package/dist/templates/agent-chat-shell.d.ts +0 -37
  128. package/dist/templates/index.cjs +0 -2476
  129. package/dist/templates/index.cjs.map +0 -1
  130. package/dist/templates/index.d.ts +0 -3
  131. package/dist/templates/index.js +0 -723
  132. package/dist/templates/index.js.map +0 -1
@@ -0,0 +1,56 @@
1
+ import * as React from "react"
2
+ import { Slot } from "radix-ui"
3
+
4
+ import { cn } from "../../lib/utils"
5
+
6
+ function TooltipProvider({ children }: { children: React.ReactNode }) {
7
+ return children
8
+ }
9
+
10
+ function Tooltip({ className, ...props }: React.ComponentProps<"span">) {
11
+ return (
12
+ <span
13
+ data-slot="tooltip"
14
+ className={cn("group/tooltip relative inline-flex", className)}
15
+ {...props}
16
+ />
17
+ )
18
+ }
19
+
20
+ function TooltipTrigger({
21
+ asChild: _asChild,
22
+ ...props
23
+ }: React.ComponentProps<typeof Slot.Root> & { asChild?: boolean }) {
24
+ return <Slot.Root data-slot="tooltip-trigger" {...props} />
25
+ }
26
+
27
+ function TooltipContent({
28
+ className,
29
+ align: _align,
30
+ side = "top",
31
+ sideOffset: _sideOffset,
32
+ ...props
33
+ }: React.ComponentProps<"span"> & {
34
+ side?: "top" | "right" | "bottom" | "left"
35
+ sideOffset?: number
36
+ align?: "start" | "center" | "end"
37
+ }) {
38
+ return (
39
+ <span
40
+ role="tooltip"
41
+ data-side={side}
42
+ data-slot="tooltip-content"
43
+ className={cn(
44
+ "pointer-events-none absolute z-50 hidden w-max max-w-xs items-center gap-1.5 rounded-xl bg-foreground px-3 py-1.5 text-xs text-background group-hover/tooltip:inline-flex group-focus-within/tooltip:inline-flex",
45
+ "data-[side=top]:bottom-full data-[side=top]:left-1/2 data-[side=top]:mb-2 data-[side=top]:-translate-x-1/2",
46
+ "data-[side=bottom]:top-full data-[side=bottom]:left-1/2 data-[side=bottom]:mt-2 data-[side=bottom]:-translate-x-1/2",
47
+ "data-[side=left]:end-full data-[side=left]:top-1/2 data-[side=left]:me-2 data-[side=left]:-translate-y-1/2",
48
+ "data-[side=right]:start-full data-[side=right]:top-1/2 data-[side=right]:ms-2 data-[side=right]:-translate-y-1/2",
49
+ className
50
+ )}
51
+ {...props}
52
+ />
53
+ )
54
+ }
55
+
56
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
@@ -0,0 +1,24 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const onChange = () => {
10
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
11
+ }
12
+ if (typeof window.matchMedia !== "function") {
13
+ onChange()
14
+ window.addEventListener("resize", onChange)
15
+ return () => window.removeEventListener("resize", onChange)
16
+ }
17
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
18
+ mql.addEventListener("change", onChange)
19
+ onChange()
20
+ return () => mql.removeEventListener("change", onChange)
21
+ }, [])
22
+
23
+ return !!isMobile
24
+ }
@@ -0,0 +1,17 @@
1
+ export type Agents24ChatIdentityState =
2
+ | "loading"
3
+ | "guest"
4
+ | "authenticated"
5
+ | "signed_out"
6
+ | "error"
7
+
8
+ export type Agents24ChatIdentity = {
9
+ state: Agents24ChatIdentityState
10
+ displayName?: string
11
+ secondaryText?: string
12
+ avatarUrl?: string
13
+ onSignIn?: () => void | Promise<void>
14
+ onSignOut?: () => void | Promise<void>
15
+ }
16
+
17
+ export const GUEST_CHAT_IDENTITY: Agents24ChatIdentity = { state: "guest" }
@@ -0,0 +1,222 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @import "shadcn/tailwind.css";
4
+ @import "@fontsource-variable/jetbrains-mono";
5
+ @import "@fontsource-variable/merriweather";
6
+ @import "@fontsource-variable/inter";
7
+
8
+ @source "./**/*.{ts,tsx}";
9
+
10
+ @custom-variant dark (&:is(.dark *));
11
+
12
+ @theme inline {
13
+ --font-heading: var(--a24-font-heading);
14
+ --font-sans: var(--a24-font-sans);
15
+ --color-sidebar-ring: var(--sidebar-ring);
16
+ --color-sidebar-border: var(--sidebar-border);
17
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
18
+ --color-sidebar-accent: var(--sidebar-accent);
19
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
20
+ --color-sidebar-primary: var(--sidebar-primary);
21
+ --color-sidebar-foreground: var(--sidebar-foreground);
22
+ --color-sidebar: var(--sidebar);
23
+ --color-ring: var(--ring);
24
+ --color-input: var(--input);
25
+ --color-border: var(--border);
26
+ --color-destructive: var(--destructive);
27
+ --color-accent-foreground: var(--accent-foreground);
28
+ --color-accent: var(--accent);
29
+ --color-muted-foreground: var(--muted-foreground);
30
+ --color-muted: var(--muted);
31
+ --color-secondary-foreground: var(--secondary-foreground);
32
+ --color-secondary: var(--secondary);
33
+ --color-primary-foreground: var(--primary-foreground);
34
+ --color-primary: var(--primary);
35
+ --color-popover-foreground: var(--popover-foreground);
36
+ --color-popover: var(--popover);
37
+ --color-card-foreground: var(--card-foreground);
38
+ --color-card: var(--card);
39
+ --color-foreground: var(--foreground);
40
+ --color-background: var(--background);
41
+ --radius-sm: calc(var(--radius) * 0.6);
42
+ --radius-md: calc(var(--radius) * 0.8);
43
+ --radius-lg: var(--radius);
44
+ --radius-xl: calc(var(--radius) * 1.4);
45
+ --radius-2xl: calc(var(--radius) * 1.8);
46
+ --radius-3xl: calc(var(--radius) * 2.2);
47
+ --radius-4xl: calc(var(--radius) * 2.6);
48
+ --a24-composer-single-row-radius: 9999px;
49
+ --color-chart-5: var(--chart-5);
50
+ --color-chart-4: var(--chart-4);
51
+ --color-chart-3: var(--chart-3);
52
+ --color-chart-2: var(--chart-2);
53
+ --color-chart-1: var(--chart-1);
54
+ --font-serif: var(--a24-font-heading);
55
+ --font-mono: var(--a24-font-mono);
56
+ }
57
+
58
+ [data-agents24-theme-root] {
59
+ color-scheme: light;
60
+ --a24-font-heading: 'Inter Variable', sans-serif;
61
+ --a24-font-sans: 'Inter Variable', sans-serif;
62
+ --a24-font-mono: 'JetBrains Mono Variable', monospace;
63
+ --radius-sm: calc(var(--radius) * 0.6);
64
+ --radius-md: calc(var(--radius) * 0.8);
65
+ --radius-lg: var(--radius);
66
+ --radius-xl: calc(var(--radius) * 1.4);
67
+ --radius-2xl: calc(var(--radius) * 1.8);
68
+ --radius-3xl: calc(var(--radius) * 2.2);
69
+ --radius-4xl: calc(var(--radius) * 2.6);
70
+ --background: oklch(1 0 0);
71
+ --foreground: oklch(0.147 0.004 49.25);
72
+ --card: oklch(1 0 0);
73
+ --card-foreground: oklch(0.147 0.004 49.25);
74
+ --popover: oklch(1 0 0);
75
+ --popover-foreground: oklch(0.147 0.004 49.25);
76
+ --primary: oklch(0.52 0.105 223.128);
77
+ --primary-foreground: oklch(0.984 0.019 200.873);
78
+ --secondary: oklch(0.967 0.001 286.375);
79
+ --secondary-foreground: oklch(0.21 0.006 285.885);
80
+ --muted: oklch(0.97 0.001 106.424);
81
+ --muted-foreground: oklch(0.553 0.013 58.071);
82
+ --accent: oklch(0.97 0.001 106.424);
83
+ --accent-foreground: oklch(0.216 0.006 56.043);
84
+ --destructive: oklch(0.577 0.245 27.325);
85
+ --border: oklch(0.923 0.003 48.717);
86
+ --input: oklch(0.923 0.003 48.717);
87
+ --ring: oklch(0.709 0.01 56.259);
88
+ --radius: 0.875rem;
89
+ --sidebar: oklch(0.985 0.001 106.423);
90
+ --sidebar-foreground: oklch(0.147 0.004 49.25);
91
+ --sidebar-primary: oklch(0.609 0.126 221.723);
92
+ --sidebar-primary-foreground: oklch(0.984 0.019 200.873);
93
+ --sidebar-accent: oklch(0.97 0.001 106.424);
94
+ --sidebar-accent-foreground: oklch(0.216 0.006 56.043);
95
+ --sidebar-border: oklch(0.923 0.003 48.717);
96
+ --sidebar-ring: oklch(0.709 0.01 56.259);
97
+ --chart-1: oklch(0.845 0.143 164.978);
98
+ --chart-2: oklch(0.696 0.17 162.48);
99
+ --chart-3: oklch(0.596 0.145 163.225);
100
+ --chart-4: oklch(0.508 0.118 165.612);
101
+ --chart-5: oklch(0.432 0.095 166.913);
102
+ }
103
+
104
+ [data-agents24-theme-root].dark {
105
+ color-scheme: dark;
106
+ --background: oklch(0.147 0.004 49.25);
107
+ --foreground: oklch(0.985 0.001 106.423);
108
+ --card: oklch(0.216 0.006 56.043);
109
+ --card-foreground: oklch(0.985 0.001 106.423);
110
+ --popover: oklch(0.216 0.006 56.043);
111
+ --popover-foreground: oklch(0.985 0.001 106.423);
112
+ --primary: oklch(0.45 0.085 224.283);
113
+ --primary-foreground: oklch(0.984 0.019 200.873);
114
+ --secondary: oklch(0.274 0.006 286.033);
115
+ --secondary-foreground: oklch(0.985 0 0);
116
+ --muted: oklch(0.268 0.007 34.298);
117
+ --muted-foreground: oklch(0.709 0.01 56.259);
118
+ --accent: oklch(0.268 0.007 34.298);
119
+ --accent-foreground: oklch(0.985 0.001 106.423);
120
+ --destructive: oklch(0.704 0.191 22.216);
121
+ --border: oklch(1 0 0 / 10%);
122
+ --input: oklch(1 0 0 / 15%);
123
+ --ring: oklch(0.553 0.013 58.071);
124
+ --sidebar: oklch(0.216 0.006 56.043);
125
+ --sidebar-foreground: oklch(0.985 0.001 106.423);
126
+ --sidebar-primary: oklch(0.715 0.143 215.221);
127
+ --sidebar-primary-foreground: oklch(0.302 0.056 229.695);
128
+ --sidebar-accent: oklch(0.268 0.007 34.298);
129
+ --sidebar-accent-foreground: oklch(0.985 0.001 106.423);
130
+ --sidebar-border: oklch(1 0 0 / 10%);
131
+ --sidebar-ring: oklch(0.553 0.013 58.071);
132
+ --chart-1: oklch(0.845 0.143 164.978);
133
+ --chart-2: oklch(0.696 0.17 162.48);
134
+ --chart-3: oklch(0.596 0.145 163.225);
135
+ --chart-4: oklch(0.508 0.118 165.612);
136
+ --chart-5: oklch(0.432 0.095 166.913);
137
+ }
138
+
139
+ [data-agents24-theme-root][data-agents24-theme="sharp"] {
140
+ --a24-composer-single-row-radius: 0;
141
+ --a24-font-heading: 'Merriweather Variable', serif;
142
+ --a24-font-sans: 'JetBrains Mono Variable', monospace;
143
+ --a24-font-mono: 'JetBrains Mono Variable', monospace;
144
+ --background: oklch(1 0 0);
145
+ --foreground: oklch(0.141 0.005 285.823);
146
+ --card: oklch(1 0 0);
147
+ --card-foreground: oklch(0.141 0.005 285.823);
148
+ --popover: oklch(1 0 0);
149
+ --popover-foreground: oklch(0.141 0.005 285.823);
150
+ --primary: oklch(0.21 0.006 285.885);
151
+ --primary-foreground: oklch(0.985 0 0);
152
+ --secondary: oklch(0.967 0.001 286.375);
153
+ --secondary-foreground: oklch(0.21 0.006 285.885);
154
+ --muted: oklch(0.967 0.001 286.375);
155
+ --muted-foreground: oklch(0.552 0.016 285.938);
156
+ --accent: oklch(0.967 0.001 286.375);
157
+ --accent-foreground: oklch(0.21 0.006 285.885);
158
+ --destructive: oklch(0.577 0.245 27.325);
159
+ --border: oklch(0.92 0.004 286.32);
160
+ --input: oklch(0.92 0.004 286.32);
161
+ --ring: oklch(0.705 0.015 286.067);
162
+ --radius: 0;
163
+ --sidebar: oklch(0.985 0 0);
164
+ --sidebar-foreground: oklch(0.141 0.005 285.823);
165
+ --sidebar-primary: oklch(0.21 0.006 285.885);
166
+ --sidebar-primary-foreground: oklch(0.985 0 0);
167
+ --sidebar-accent: oklch(0.967 0.001 286.375);
168
+ --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
169
+ --sidebar-border: oklch(0.92 0.004 286.32);
170
+ --sidebar-ring: oklch(0.705 0.015 286.067);
171
+ --chart-1: oklch(0.865 0.127 207.078);
172
+ --chart-2: oklch(0.715 0.143 215.221);
173
+ --chart-3: oklch(0.609 0.126 221.723);
174
+ --chart-4: oklch(0.52 0.105 223.128);
175
+ --chart-5: oklch(0.45 0.085 224.283);
176
+ }
177
+
178
+ [data-agents24-theme-root][data-agents24-theme="sharp"].dark {
179
+ --background: oklch(0.141 0.005 285.823);
180
+ --foreground: oklch(0.985 0 0);
181
+ --card: oklch(0.21 0.006 285.885);
182
+ --card-foreground: oklch(0.985 0 0);
183
+ --popover: oklch(0.21 0.006 285.885);
184
+ --popover-foreground: oklch(0.985 0 0);
185
+ --primary: oklch(0.92 0.004 286.32);
186
+ --primary-foreground: oklch(0.21 0.006 285.885);
187
+ --secondary: oklch(0.274 0.006 286.033);
188
+ --secondary-foreground: oklch(0.985 0 0);
189
+ --muted: oklch(0.274 0.006 286.033);
190
+ --muted-foreground: oklch(0.705 0.015 286.067);
191
+ --accent: oklch(0.274 0.006 286.033);
192
+ --accent-foreground: oklch(0.985 0 0);
193
+ --destructive: oklch(0.704 0.191 22.216);
194
+ --border: oklch(1 0 0 / 10%);
195
+ --input: oklch(1 0 0 / 15%);
196
+ --ring: oklch(0.552 0.016 285.938);
197
+ --sidebar: oklch(0.21 0.006 285.885);
198
+ --sidebar-foreground: oklch(0.985 0 0);
199
+ --sidebar-primary: oklch(0.488 0.243 264.376);
200
+ --sidebar-primary-foreground: oklch(0.985 0 0);
201
+ --sidebar-accent: oklch(0.274 0.006 286.033);
202
+ --sidebar-accent-foreground: oklch(0.985 0 0);
203
+ --sidebar-border: oklch(1 0 0 / 10%);
204
+ --sidebar-ring: oklch(0.552 0.016 285.938);
205
+ --chart-1: oklch(0.865 0.127 207.078);
206
+ --chart-2: oklch(0.715 0.143 215.221);
207
+ --chart-3: oklch(0.609 0.126 221.723);
208
+ --chart-4: oklch(0.52 0.105 223.128);
209
+ --chart-5: oklch(0.45 0.085 224.283);
210
+ }
211
+
212
+ @layer base {
213
+ [data-agents24-theme-root], [data-agents24-theme-root] * {
214
+ @apply border-border outline-ring/50;
215
+ box-sizing: border-box;
216
+ }
217
+ [data-agents24-theme-root] {
218
+ @apply size-full overflow-hidden bg-background font-sans text-foreground antialiased;
219
+ }
220
+ [data-agents24-theme-root] button,
221
+ [data-agents24-theme-root] textarea { font: inherit; }
222
+ }
@@ -0,0 +1,39 @@
1
+ import * as React from "react"
2
+
3
+ import { App, type Agents24ChatAppProps } from "./app"
4
+ import {
5
+ ThemeProvider,
6
+ type Agents24ChatAppearanceController,
7
+ type Agents24ChatTheme,
8
+ } from "./components/theme-provider"
9
+ import { TooltipProvider } from "./components/ui/tooltip"
10
+
11
+ export type Agents24ChatScaffoldProps = Agents24ChatAppProps & {
12
+ appearanceController?: Agents24ChatAppearanceController
13
+ theme?: Agents24ChatTheme
14
+ }
15
+
16
+ export function Agents24ChatScaffold({ appearanceController, theme, ...props }: Agents24ChatScaffoldProps) {
17
+ return (
18
+ <ThemeProvider controller={appearanceController} theme={theme}>
19
+ <TooltipProvider>
20
+ <App {...props} />
21
+ </TooltipProvider>
22
+ </ThemeProvider>
23
+ )
24
+ }
25
+
26
+ export { App as Agents24ChatScaffoldApp }
27
+ export { ThemeProvider as Agents24ChatThemeProvider }
28
+ export type {
29
+ Agents24ChatAppearance,
30
+ Agents24ChatAppearanceController,
31
+ Agents24ChatTheme,
32
+ } from "./components/theme-provider"
33
+ export type { Agents24ChatIdentity, Agents24ChatIdentityState } from "./identity"
34
+ export type {
35
+ ChatHitlResponse,
36
+ Agents24ChatScaffoldComponents,
37
+ Agents24ChatTimelineSlotProps,
38
+ } from "./app"
39
+ export { TooltipProvider as Agents24ChatTooltipProvider }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -0,0 +1,3 @@
1
+ @import "@agents24/chat-react/styles.css";
2
+ @import "./src/index.css";
3
+ @import "./src/chat.css";
@@ -1,140 +0,0 @@
1
- // src/streaming-text.ts
2
- import { useEffect, useRef, useState } from "react";
3
- var DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;
4
- var defaultCompletedTextCache = /* @__PURE__ */ new Map();
5
- var defaultStreamingTextCache = {
6
- get: (id) => defaultCompletedTextCache.get(id),
7
- set: (id, text) => {
8
- defaultCompletedTextCache.set(id, text);
9
- if (defaultCompletedTextCache.size > DEFAULT_COMPLETED_TEXT_CACHE_SIZE) {
10
- const firstKey = defaultCompletedTextCache.keys().next().value;
11
- if (firstKey) defaultCompletedTextCache.delete(firstKey);
12
- }
13
- }
14
- };
15
- var getActiveStreamingTextPartId = (message, streamingMessageId) => {
16
- if (message.role !== "assistant" || streamingMessageId !== message.id) return null;
17
- return message.parts.slice().reverse().find((part) => part.kind === "text")?.id || null;
18
- };
19
- var isActiveStreamingTextPart = (message, part, streamingMessageId) => part.kind === "text" && part.id === getActiveStreamingTextPartId(message, streamingMessageId);
20
- function useStreamingText({
21
- id,
22
- isStreaming,
23
- text,
24
- cache = defaultStreamingTextCache,
25
- charsPerSecond = 72,
26
- catchupThreshold = 40,
27
- maxCatchupChars = 20
28
- }) {
29
- const cacheAdapter = cache === false ? null : cache;
30
- const [displayedText, setDisplayedText] = useState(() => {
31
- const cachedText = cacheAdapter?.get(id);
32
- return cachedText && text.startsWith(cachedText) ? cachedText : text;
33
- });
34
- const targetRef = useRef(text);
35
- const displayedRef = useRef(displayedText);
36
- const rafRef = useRef(null);
37
- const lastFrameAtRef = useRef(null);
38
- const idRef = useRef(id);
39
- const shouldAnimateRef = useRef(isStreaming);
40
- useEffect(() => {
41
- if (isStreaming || !text) return;
42
- cacheAdapter?.set(id, text);
43
- }, [cacheAdapter, id, isStreaming, text]);
44
- useEffect(() => {
45
- targetRef.current = text;
46
- }, [text]);
47
- useEffect(() => {
48
- if (idRef.current === id) return;
49
- idRef.current = id;
50
- const cachedText = cacheAdapter?.get(id);
51
- const initial = cachedText && text.startsWith(cachedText) ? cachedText : text;
52
- shouldAnimateRef.current = isStreaming && initial !== text;
53
- displayedRef.current = initial;
54
- setDisplayedText(initial);
55
- if (rafRef.current !== null) {
56
- cancelAnimationFrame(rafRef.current);
57
- rafRef.current = null;
58
- }
59
- lastFrameAtRef.current = null;
60
- }, [cacheAdapter, id, isStreaming, text]);
61
- useEffect(() => {
62
- if (typeof window === "undefined") {
63
- displayedRef.current = text;
64
- setDisplayedText(text);
65
- return;
66
- }
67
- const reduceMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
68
- if (reduceMotion) {
69
- displayedRef.current = text;
70
- setDisplayedText(text);
71
- shouldAnimateRef.current = false;
72
- return;
73
- }
74
- const cachedText = cacheAdapter?.get(id);
75
- if (cachedText === text) {
76
- displayedRef.current = text;
77
- setDisplayedText(text);
78
- shouldAnimateRef.current = false;
79
- return;
80
- }
81
- if (isStreaming) {
82
- shouldAnimateRef.current = true;
83
- }
84
- if (!shouldAnimateRef.current) {
85
- displayedRef.current = text;
86
- setDisplayedText(text);
87
- return;
88
- }
89
- if (!text.startsWith(displayedRef.current)) {
90
- displayedRef.current = "";
91
- setDisplayedText("");
92
- }
93
- const tick = (timestamp) => {
94
- const previousTimestamp = lastFrameAtRef.current ?? timestamp;
95
- lastFrameAtRef.current = timestamp;
96
- const target = targetRef.current;
97
- const current = displayedRef.current;
98
- if (current.length >= target.length) {
99
- shouldAnimateRef.current = false;
100
- rafRef.current = null;
101
- return;
102
- }
103
- const elapsedMs = Math.max(8, timestamp - previousTimestamp);
104
- const charsFromTime = Math.max(1, Math.floor(elapsedMs / 1e3 * charsPerSecond));
105
- const gap = target.length - current.length;
106
- const catchupStep = gap > catchupThreshold ? Math.min(maxCatchupChars, Math.ceil(gap / 10)) : charsFromTime;
107
- const nextLength = Math.min(
108
- target.length,
109
- current.length + Math.max(charsFromTime, catchupStep)
110
- );
111
- const next = target.slice(0, nextLength);
112
- displayedRef.current = next;
113
- setDisplayedText(next);
114
- rafRef.current = window.requestAnimationFrame(tick);
115
- };
116
- if (rafRef.current === null && displayedRef.current.length < text.length) {
117
- rafRef.current = window.requestAnimationFrame(tick);
118
- }
119
- return () => {
120
- if (rafRef.current !== null) {
121
- cancelAnimationFrame(rafRef.current);
122
- rafRef.current = null;
123
- }
124
- lastFrameAtRef.current = null;
125
- };
126
- }, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars, text]);
127
- return {
128
- displayedText,
129
- isAnimating: isStreaming,
130
- mode: isStreaming ? "streaming" : "static",
131
- parseIncompleteMarkdown: isStreaming
132
- };
133
- }
134
-
135
- export {
136
- getActiveStreamingTextPartId,
137
- isActiveStreamingTextPart,
138
- useStreamingText
139
- };
140
- //# sourceMappingURL=chunk-CHAU7FNW.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/streaming-text.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nimport type { ChatMessage, ChatPart } from \"./types\";\n\nexport type StreamingTextMode = \"streaming\" | \"static\";\n\nexport type StreamingTextCache = {\n get: (id: string) => string | undefined;\n set: (id: string, text: string) => void;\n};\n\nexport type UseStreamingTextOptions = {\n id: string;\n isStreaming: boolean;\n text: string;\n cache?: StreamingTextCache | false;\n charsPerSecond?: number;\n catchupThreshold?: number;\n maxCatchupChars?: number;\n};\n\nexport type UseStreamingTextResult = {\n displayedText: string;\n isAnimating: boolean;\n mode: StreamingTextMode;\n parseIncompleteMarkdown: boolean;\n};\n\nconst DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;\nconst defaultCompletedTextCache = new Map<string, string>();\n\nconst defaultStreamingTextCache: StreamingTextCache = {\n get: (id) => defaultCompletedTextCache.get(id),\n set: (id, text) => {\n defaultCompletedTextCache.set(id, text);\n if (defaultCompletedTextCache.size > DEFAULT_COMPLETED_TEXT_CACHE_SIZE) {\n const firstKey = defaultCompletedTextCache.keys().next().value;\n if (firstKey) defaultCompletedTextCache.delete(firstKey);\n }\n },\n};\n\nexport const getActiveStreamingTextPartId = (\n message: ChatMessage,\n streamingMessageId: string | null\n) => {\n if (message.role !== \"assistant\" || streamingMessageId !== message.id) return null;\n return (\n message.parts\n .slice()\n .reverse()\n .find((part) => part.kind === \"text\")?.id || null\n );\n};\n\nexport const isActiveStreamingTextPart = (\n message: ChatMessage,\n part: ChatPart,\n streamingMessageId: string | null\n) => part.kind === \"text\" && part.id === getActiveStreamingTextPartId(message, streamingMessageId);\n\nexport function useStreamingText({\n id,\n isStreaming,\n text,\n cache = defaultStreamingTextCache,\n charsPerSecond = 72,\n catchupThreshold = 40,\n maxCatchupChars = 20,\n}: UseStreamingTextOptions): UseStreamingTextResult {\n const cacheAdapter = cache === false ? null : cache;\n const [displayedText, setDisplayedText] = useState(() => {\n const cachedText = cacheAdapter?.get(id);\n return cachedText && text.startsWith(cachedText) ? cachedText : text;\n });\n const targetRef = useRef(text);\n const displayedRef = useRef(displayedText);\n const rafRef = useRef<number | null>(null);\n const lastFrameAtRef = useRef<number | null>(null);\n const idRef = useRef(id);\n const shouldAnimateRef = useRef(isStreaming);\n\n useEffect(() => {\n if (isStreaming || !text) return;\n cacheAdapter?.set(id, text);\n }, [cacheAdapter, id, isStreaming, text]);\n\n useEffect(() => {\n targetRef.current = text;\n }, [text]);\n\n useEffect(() => {\n if (idRef.current === id) return;\n\n idRef.current = id;\n const cachedText = cacheAdapter?.get(id);\n const initial = cachedText && text.startsWith(cachedText) ? cachedText : text;\n shouldAnimateRef.current = isStreaming && initial !== text;\n displayedRef.current = initial;\n setDisplayedText(initial);\n\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n lastFrameAtRef.current = null;\n }, [cacheAdapter, id, isStreaming, text]);\n\n useEffect(() => {\n if (typeof window === \"undefined\") {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n const reduceMotion =\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n if (reduceMotion) {\n displayedRef.current = text;\n setDisplayedText(text);\n shouldAnimateRef.current = false;\n return;\n }\n\n const cachedText = cacheAdapter?.get(id);\n if (cachedText === text) {\n displayedRef.current = text;\n setDisplayedText(text);\n shouldAnimateRef.current = false;\n return;\n }\n\n if (isStreaming) {\n shouldAnimateRef.current = true;\n }\n\n if (!shouldAnimateRef.current) {\n displayedRef.current = text;\n setDisplayedText(text);\n return;\n }\n\n if (!text.startsWith(displayedRef.current)) {\n displayedRef.current = \"\";\n setDisplayedText(\"\");\n }\n\n const tick = (timestamp: number) => {\n const previousTimestamp = lastFrameAtRef.current ?? timestamp;\n lastFrameAtRef.current = timestamp;\n\n const target = targetRef.current;\n const current = displayedRef.current;\n\n if (current.length >= target.length) {\n shouldAnimateRef.current = false;\n rafRef.current = null;\n return;\n }\n\n const elapsedMs = Math.max(8, timestamp - previousTimestamp);\n const charsFromTime = Math.max(1, Math.floor((elapsedMs / 1000) * charsPerSecond));\n const gap = target.length - current.length;\n const catchupStep =\n gap > catchupThreshold ? Math.min(maxCatchupChars, Math.ceil(gap / 10)) : charsFromTime;\n const nextLength = Math.min(\n target.length,\n current.length + Math.max(charsFromTime, catchupStep)\n );\n\n const next = target.slice(0, nextLength);\n displayedRef.current = next;\n setDisplayedText(next);\n rafRef.current = window.requestAnimationFrame(tick);\n };\n\n if (rafRef.current === null && displayedRef.current.length < text.length) {\n rafRef.current = window.requestAnimationFrame(tick);\n }\n\n return () => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n lastFrameAtRef.current = null;\n };\n }, [cacheAdapter, catchupThreshold, charsPerSecond, id, isStreaming, maxCatchupChars, text]);\n\n return {\n displayedText,\n isAnimating: isStreaming,\n mode: isStreaming ? \"streaming\" : \"static\",\n parseIncompleteMarkdown: isStreaming,\n };\n}\n"],"mappings":"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","names":[]}