@agent-native/toolkit 0.223.0 → 0.223.1-nightly-20261103004150
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/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +8 -3
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context.d.ts +6 -0
- package/dist/app/agentkit/react/context.d.ts.map +1 -1
- package/dist/app/agentkit/react/context.js.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +2 -0
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/observability/ThumbsFeedback.d.ts +5 -3
- package/dist/app/observability/ThumbsFeedback.d.ts.map +1 -1
- package/dist/app/observability/ThumbsFeedback.js +40 -11
- package/dist/app/observability/ThumbsFeedback.js.map +1 -1
- package/package.json +4 -4
- package/src/app/agentkit/react/components.tsx +24 -2
- package/src/app/agentkit/react/context.tsx +10 -0
- package/src/app/agentkit/react/message-actions.spec.tsx +114 -8
- package/src/app/chat/AgentKitAssistantChat.tsx +14 -0
- package/src/app/observability/ThumbsFeedback.spec.tsx +49 -0
- package/src/app/observability/ThumbsFeedback.tsx +118 -51
|
@@ -6,15 +6,27 @@ import { Textarea } from "@agent-native/toolkit/ui/textarea";
|
|
|
6
6
|
import { cn } from "@agent-native/toolkit/utils";
|
|
7
7
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
8
8
|
import { IconThumbUp, IconThumbDown } from "@tabler/icons-react";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
useState,
|
|
11
|
+
useCallback,
|
|
12
|
+
useEffect,
|
|
13
|
+
useId,
|
|
14
|
+
useRef,
|
|
15
|
+
type ReactNode,
|
|
16
|
+
} from "react";
|
|
10
17
|
|
|
11
18
|
import { submitFeedbackForm } from "../feedback/index.js";
|
|
12
19
|
|
|
13
20
|
export interface ThumbsFeedbackProps {
|
|
14
21
|
threadId: string;
|
|
15
|
-
runId
|
|
16
|
-
messageSeq
|
|
22
|
+
runId?: string;
|
|
23
|
+
messageSeq?: number;
|
|
17
24
|
className?: string;
|
|
25
|
+
renderNegativeTrigger?: (
|
|
26
|
+
toggle: () => void,
|
|
27
|
+
open: boolean,
|
|
28
|
+
contentId: string,
|
|
29
|
+
) => ReactNode;
|
|
18
30
|
}
|
|
19
31
|
|
|
20
32
|
type Selection = "up" | "down" | null;
|
|
@@ -24,7 +36,7 @@ const CONFIRMATION_DURATION_MS = 1400;
|
|
|
24
36
|
type TextFeedbackDelivery = {
|
|
25
37
|
value: string;
|
|
26
38
|
observabilityDelivered: boolean;
|
|
27
|
-
|
|
39
|
+
sharedFormStatus: "pending" | "submitted" | "unconfigured";
|
|
28
40
|
idempotencyKey: string;
|
|
29
41
|
};
|
|
30
42
|
|
|
@@ -43,6 +55,7 @@ export function ThumbsFeedback({
|
|
|
43
55
|
runId,
|
|
44
56
|
messageSeq,
|
|
45
57
|
className,
|
|
58
|
+
renderNegativeTrigger,
|
|
46
59
|
}: ThumbsFeedbackProps) {
|
|
47
60
|
const t = useT();
|
|
48
61
|
const { session } = useSession();
|
|
@@ -51,7 +64,11 @@ export function ThumbsFeedback({
|
|
|
51
64
|
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
52
65
|
const [textFeedback, setTextFeedback] = useState("");
|
|
53
66
|
const [textSubmitting, setTextSubmitting] = useState(false);
|
|
67
|
+
const [textSubmitFailed, setTextSubmitFailed] = useState(false);
|
|
54
68
|
const feedbackInputId = useId();
|
|
69
|
+
const feedbackContentId = useId();
|
|
70
|
+
const triggerAnchorRef = useRef<HTMLSpanElement>(null);
|
|
71
|
+
const restoreTriggerFocusRef = useRef(false);
|
|
55
72
|
const feedbackInputRef = useRef<HTMLTextAreaElement>(null);
|
|
56
73
|
const feedbackOpenedAtRef = useRef(0);
|
|
57
74
|
const textSubmissionInFlightRef = useRef(false);
|
|
@@ -157,12 +174,13 @@ export function ThumbsFeedback({
|
|
|
157
174
|
: {
|
|
158
175
|
value,
|
|
159
176
|
observabilityDelivered: false,
|
|
160
|
-
|
|
177
|
+
sharedFormStatus: "pending" as const,
|
|
161
178
|
idempotencyKey: createFeedbackIdempotencyKey(),
|
|
162
179
|
};
|
|
163
180
|
textFeedbackDeliveryRef.current = delivery;
|
|
164
181
|
textSubmissionInFlightRef.current = true;
|
|
165
182
|
setTextSubmitting(true);
|
|
183
|
+
setTextSubmitFailed(false);
|
|
166
184
|
|
|
167
185
|
const deliveries: Promise<void>[] = [];
|
|
168
186
|
if (!delivery.observabilityDelivered) {
|
|
@@ -174,7 +192,7 @@ export function ThumbsFeedback({
|
|
|
174
192
|
),
|
|
175
193
|
);
|
|
176
194
|
}
|
|
177
|
-
if (
|
|
195
|
+
if (delivery.sharedFormStatus === "pending") {
|
|
178
196
|
deliveries.push(
|
|
179
197
|
submitFeedbackForm({
|
|
180
198
|
value,
|
|
@@ -184,8 +202,8 @@ export function ThumbsFeedback({
|
|
|
184
202
|
activeRunId: runId,
|
|
185
203
|
submitterEmail: session?.email,
|
|
186
204
|
})
|
|
187
|
-
.then(() => {
|
|
188
|
-
delivery.
|
|
205
|
+
.then((result) => {
|
|
206
|
+
delivery.sharedFormStatus = result;
|
|
189
207
|
})
|
|
190
208
|
.catch((reason) => {
|
|
191
209
|
console.error(
|
|
@@ -198,11 +216,16 @@ export function ThumbsFeedback({
|
|
|
198
216
|
|
|
199
217
|
void Promise.all(deliveries)
|
|
200
218
|
.then(() => {
|
|
201
|
-
if (
|
|
219
|
+
if (
|
|
220
|
+
!delivery.observabilityDelivered ||
|
|
221
|
+
delivery.sharedFormStatus === "pending"
|
|
222
|
+
) {
|
|
223
|
+
setTextSubmitFailed(true);
|
|
202
224
|
return;
|
|
203
225
|
}
|
|
204
226
|
textFeedbackDeliveryRef.current = null;
|
|
205
227
|
setTextFeedback("");
|
|
228
|
+
restoreTriggerFocusRef.current = true;
|
|
206
229
|
setPopoverOpen(false);
|
|
207
230
|
})
|
|
208
231
|
.finally(() => {
|
|
@@ -216,53 +239,71 @@ export function ThumbsFeedback({
|
|
|
216
239
|
<span role="status" aria-live="polite" className="sr-only">
|
|
217
240
|
{confirmed ? t("agentChat.feedback.submitted") : ""}
|
|
218
241
|
</span>
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
242
|
+
{!renderNegativeTrigger && (
|
|
243
|
+
<button
|
|
244
|
+
type="button"
|
|
245
|
+
aria-label={t("agentChat.feedback.thumbsUp")}
|
|
246
|
+
title={t("agentChat.feedback.thumbsUp")}
|
|
247
|
+
aria-pressed={selection === "up"}
|
|
248
|
+
onClick={handleThumbsUp}
|
|
249
|
+
className={cn(
|
|
250
|
+
"flex h-6 w-6 items-center justify-center rounded transition-transform duration-200",
|
|
251
|
+
selection === "up"
|
|
252
|
+
? "text-foreground"
|
|
253
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50",
|
|
254
|
+
confirmed === "up" && "scale-110",
|
|
255
|
+
)}
|
|
256
|
+
>
|
|
257
|
+
<IconThumbUp
|
|
258
|
+
size={16}
|
|
259
|
+
stroke={selection === "up" ? 2.5 : 1.5}
|
|
260
|
+
fill={selection === "up" ? "currentColor" : "none"}
|
|
261
|
+
/>
|
|
262
|
+
</button>
|
|
263
|
+
)}
|
|
239
264
|
|
|
240
265
|
<PopoverPrimitive.Root open={popoverOpen} onOpenChange={setPopoverOpen}>
|
|
241
|
-
|
|
242
|
-
<
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
>
|
|
256
|
-
<
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
266
|
+
{renderNegativeTrigger ? (
|
|
267
|
+
<PopoverPrimitive.Anchor asChild>
|
|
268
|
+
<span ref={triggerAnchorRef}>
|
|
269
|
+
{renderNegativeTrigger(
|
|
270
|
+
() => {
|
|
271
|
+
if (!popoverOpen) feedbackOpenedAtRef.current = Date.now();
|
|
272
|
+
setPopoverOpen((open) => !open);
|
|
273
|
+
},
|
|
274
|
+
popoverOpen,
|
|
275
|
+
feedbackContentId,
|
|
276
|
+
)}
|
|
277
|
+
</span>
|
|
278
|
+
</PopoverPrimitive.Anchor>
|
|
279
|
+
) : (
|
|
280
|
+
<PopoverPrimitive.Trigger asChild>
|
|
281
|
+
<button
|
|
282
|
+
type="button"
|
|
283
|
+
aria-label={t("agentChat.feedback.thumbsDown")}
|
|
284
|
+
title={t("agentChat.feedback.thumbsDown")}
|
|
285
|
+
aria-pressed={selection === "down"}
|
|
286
|
+
onClick={handleThumbsDown}
|
|
287
|
+
className={cn(
|
|
288
|
+
"flex h-6 w-6 items-center justify-center rounded transition-transform duration-200",
|
|
289
|
+
selection === "down"
|
|
290
|
+
? "text-foreground"
|
|
291
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50",
|
|
292
|
+
confirmed === "down" && "scale-110",
|
|
293
|
+
)}
|
|
294
|
+
>
|
|
295
|
+
<IconThumbDown
|
|
296
|
+
size={16}
|
|
297
|
+
stroke={selection === "down" ? 2.5 : 1.5}
|
|
298
|
+
fill={selection === "down" ? "currentColor" : "none"}
|
|
299
|
+
/>
|
|
300
|
+
</button>
|
|
301
|
+
</PopoverPrimitive.Trigger>
|
|
302
|
+
)}
|
|
263
303
|
|
|
264
304
|
<PopoverPrimitive.Portal>
|
|
265
305
|
<PopoverPrimitive.Content
|
|
306
|
+
id={feedbackContentId}
|
|
266
307
|
side="bottom"
|
|
267
308
|
align="start"
|
|
268
309
|
sideOffset={4}
|
|
@@ -271,6 +312,27 @@ export function ThumbsFeedback({
|
|
|
271
312
|
event.preventDefault();
|
|
272
313
|
feedbackInputRef.current?.focus();
|
|
273
314
|
}}
|
|
315
|
+
onEscapeKeyDown={() => {
|
|
316
|
+
restoreTriggerFocusRef.current = true;
|
|
317
|
+
}}
|
|
318
|
+
onInteractOutside={(event) => {
|
|
319
|
+
if (
|
|
320
|
+
renderNegativeTrigger &&
|
|
321
|
+
event.target instanceof Node &&
|
|
322
|
+
triggerAnchorRef.current?.contains(event.target)
|
|
323
|
+
)
|
|
324
|
+
event.preventDefault();
|
|
325
|
+
}}
|
|
326
|
+
onCloseAutoFocus={(event) => {
|
|
327
|
+
if (!renderNegativeTrigger) return;
|
|
328
|
+
event.preventDefault();
|
|
329
|
+
if (restoreTriggerFocusRef.current) {
|
|
330
|
+
triggerAnchorRef.current
|
|
331
|
+
?.querySelector<HTMLButtonElement>("button")
|
|
332
|
+
?.focus();
|
|
333
|
+
}
|
|
334
|
+
restoreTriggerFocusRef.current = false;
|
|
335
|
+
}}
|
|
274
336
|
className="z-[300] w-[min(320px,calc(100vw-24px))] overflow-hidden rounded-lg border border-border bg-popover p-3 text-popover-foreground shadow-lg outline-none origin-[var(--radix-popover-content-transform-origin)]"
|
|
275
337
|
>
|
|
276
338
|
<form
|
|
@@ -307,6 +369,11 @@ export function ThumbsFeedback({
|
|
|
307
369
|
maxLength={2000}
|
|
308
370
|
className="min-h-20 resize-none px-2.5 py-2 text-xs"
|
|
309
371
|
/>
|
|
372
|
+
{textSubmitFailed ? (
|
|
373
|
+
<p role="alert" className="text-xs text-destructive">
|
|
374
|
+
{t("agentChat.composer.submitFailed")}
|
|
375
|
+
</p>
|
|
376
|
+
) : null}
|
|
310
377
|
<div className="flex items-center justify-between gap-2">
|
|
311
378
|
<span className="text-[11px] text-muted-foreground/75">
|
|
312
379
|
{t("agentChat.feedback.keyboardHint").replace(
|