@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
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
1
2
|
export interface ThumbsFeedbackProps {
|
|
2
3
|
threadId: string;
|
|
3
|
-
runId
|
|
4
|
-
messageSeq
|
|
4
|
+
runId?: string;
|
|
5
|
+
messageSeq?: number;
|
|
5
6
|
className?: string;
|
|
7
|
+
renderNegativeTrigger?: (toggle: () => void, open: boolean, contentId: string) => ReactNode;
|
|
6
8
|
}
|
|
7
|
-
export declare function ThumbsFeedback({ threadId, runId, messageSeq, className, }: ThumbsFeedbackProps): import("react").JSX.Element;
|
|
9
|
+
export declare function ThumbsFeedback({ threadId, runId, messageSeq, className, renderNegativeTrigger, }: ThumbsFeedbackProps): import("react").JSX.Element;
|
|
8
10
|
//# sourceMappingURL=ThumbsFeedback.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThumbsFeedback.d.ts","sourceRoot":"","sources":["../../../src/app/observability/ThumbsFeedback.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ThumbsFeedback.d.ts","sourceRoot":"","sources":["../../../src/app/observability/ThumbsFeedback.tsx"],"names":[],"mappings":"AAQA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB,CAAC,EAAE,CACtB,MAAM,EAAE,MAAM,IAAI,EAClB,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,KACd,SAAS,CAAC;CAChB;AAuBD,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,KAAK,EACL,UAAU,EACV,SAAS,EACT,qBAAqB,GACtB,EAAE,mBAAmB,+BAuVrB"}
|
|
@@ -7,7 +7,7 @@ import { Textarea } from "@agent-native/toolkit/ui/textarea";
|
|
|
7
7
|
import { cn } from "@agent-native/toolkit/utils";
|
|
8
8
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
9
9
|
import { IconThumbUp, IconThumbDown } from "@tabler/icons-react";
|
|
10
|
-
import { useState, useCallback, useEffect, useId, useRef } from "react";
|
|
10
|
+
import { useState, useCallback, useEffect, useId, useRef, } from "react";
|
|
11
11
|
import { submitFeedbackForm } from "../feedback/index.js";
|
|
12
12
|
const CONFIRMATION_DURATION_MS = 1400;
|
|
13
13
|
function createFeedbackIdempotencyKey() {
|
|
@@ -17,7 +17,7 @@ function createFeedbackIdempotencyKey() {
|
|
|
17
17
|
}
|
|
18
18
|
return `feedback-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
19
19
|
}
|
|
20
|
-
export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
20
|
+
export function ThumbsFeedback({ threadId, runId, messageSeq, className, renderNegativeTrigger, }) {
|
|
21
21
|
const t = useT();
|
|
22
22
|
const { session } = useSession();
|
|
23
23
|
const [selection, setSelection] = useState(null);
|
|
@@ -25,7 +25,11 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
25
25
|
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
26
26
|
const [textFeedback, setTextFeedback] = useState("");
|
|
27
27
|
const [textSubmitting, setTextSubmitting] = useState(false);
|
|
28
|
+
const [textSubmitFailed, setTextSubmitFailed] = useState(false);
|
|
28
29
|
const feedbackInputId = useId();
|
|
30
|
+
const feedbackContentId = useId();
|
|
31
|
+
const triggerAnchorRef = useRef(null);
|
|
32
|
+
const restoreTriggerFocusRef = useRef(false);
|
|
29
33
|
const feedbackInputRef = useRef(null);
|
|
30
34
|
const feedbackOpenedAtRef = useRef(0);
|
|
31
35
|
const textSubmissionInFlightRef = useRef(false);
|
|
@@ -119,19 +123,20 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
119
123
|
: {
|
|
120
124
|
value,
|
|
121
125
|
observabilityDelivered: false,
|
|
122
|
-
|
|
126
|
+
sharedFormStatus: "pending",
|
|
123
127
|
idempotencyKey: createFeedbackIdempotencyKey(),
|
|
124
128
|
};
|
|
125
129
|
textFeedbackDeliveryRef.current = delivery;
|
|
126
130
|
textSubmissionInFlightRef.current = true;
|
|
127
131
|
setTextSubmitting(true);
|
|
132
|
+
setTextSubmitFailed(false);
|
|
128
133
|
const deliveries = [];
|
|
129
134
|
if (!delivery.observabilityDelivered) {
|
|
130
135
|
deliveries.push(sendFeedback("text", value, delivery.idempotencyKey).then((submitted) => {
|
|
131
136
|
delivery.observabilityDelivered = submitted;
|
|
132
137
|
}));
|
|
133
138
|
}
|
|
134
|
-
if (
|
|
139
|
+
if (delivery.sharedFormStatus === "pending") {
|
|
135
140
|
deliveries.push(submitFeedbackForm({
|
|
136
141
|
value,
|
|
137
142
|
openedAt: feedbackOpenedAtRef.current,
|
|
@@ -140,8 +145,8 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
140
145
|
activeRunId: runId,
|
|
141
146
|
submitterEmail: session?.email,
|
|
142
147
|
})
|
|
143
|
-
.then(() => {
|
|
144
|
-
delivery.
|
|
148
|
+
.then((result) => {
|
|
149
|
+
delivery.sharedFormStatus = result;
|
|
145
150
|
})
|
|
146
151
|
.catch((reason) => {
|
|
147
152
|
console.error("[ThumbsFeedback] shared feedback form submission failed", reason);
|
|
@@ -149,11 +154,14 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
149
154
|
}
|
|
150
155
|
void Promise.all(deliveries)
|
|
151
156
|
.then(() => {
|
|
152
|
-
if (!delivery.observabilityDelivered ||
|
|
157
|
+
if (!delivery.observabilityDelivered ||
|
|
158
|
+
delivery.sharedFormStatus === "pending") {
|
|
159
|
+
setTextSubmitFailed(true);
|
|
153
160
|
return;
|
|
154
161
|
}
|
|
155
162
|
textFeedbackDeliveryRef.current = null;
|
|
156
163
|
setTextFeedback("");
|
|
164
|
+
restoreTriggerFocusRef.current = true;
|
|
157
165
|
setPopoverOpen(false);
|
|
158
166
|
})
|
|
159
167
|
.finally(() => {
|
|
@@ -161,13 +169,34 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
161
169
|
setTextSubmitting(false);
|
|
162
170
|
});
|
|
163
171
|
}, [runId, sendFeedback, session?.email, textFeedback, threadId]);
|
|
164
|
-
return (_jsxs("div", { className: cn("inline-flex items-center gap-0.5", className), children: [_jsx("span", { role: "status", "aria-live": "polite", className: "sr-only", children: confirmed ? t("agentChat.feedback.submitted") : "" }), _jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsUp"), title: t("agentChat.feedback.thumbsUp"), "aria-pressed": selection === "up", onClick: handleThumbsUp, className: cn("flex h-6 w-6 items-center justify-center rounded transition-transform duration-200", selection === "up"
|
|
172
|
+
return (_jsxs("div", { className: cn("inline-flex items-center gap-0.5", className), children: [_jsx("span", { role: "status", "aria-live": "polite", className: "sr-only", children: confirmed ? t("agentChat.feedback.submitted") : "" }), !renderNegativeTrigger && (_jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsUp"), title: t("agentChat.feedback.thumbsUp"), "aria-pressed": selection === "up", onClick: handleThumbsUp, className: cn("flex h-6 w-6 items-center justify-center rounded transition-transform duration-200", selection === "up"
|
|
165
173
|
? "text-foreground"
|
|
166
|
-
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50", confirmed === "up" && "scale-110"), children: _jsx(IconThumbUp, { size: 16, stroke: selection === "up" ? 2.5 : 1.5, fill: selection === "up" ? "currentColor" : "none" }) }), _jsxs(PopoverPrimitive.Root, { open: popoverOpen, onOpenChange: setPopoverOpen, children: [_jsx(PopoverPrimitive.
|
|
174
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50", confirmed === "up" && "scale-110"), children: _jsx(IconThumbUp, { size: 16, stroke: selection === "up" ? 2.5 : 1.5, fill: selection === "up" ? "currentColor" : "none" }) })), _jsxs(PopoverPrimitive.Root, { open: popoverOpen, onOpenChange: setPopoverOpen, children: [renderNegativeTrigger ? (_jsx(PopoverPrimitive.Anchor, { asChild: true, children: _jsx("span", { ref: triggerAnchorRef, children: renderNegativeTrigger(() => {
|
|
175
|
+
if (!popoverOpen)
|
|
176
|
+
feedbackOpenedAtRef.current = Date.now();
|
|
177
|
+
setPopoverOpen((open) => !open);
|
|
178
|
+
}, popoverOpen, feedbackContentId) }) })) : (_jsx(PopoverPrimitive.Trigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsDown"), title: t("agentChat.feedback.thumbsDown"), "aria-pressed": selection === "down", onClick: handleThumbsDown, className: cn("flex h-6 w-6 items-center justify-center rounded transition-transform duration-200", selection === "down"
|
|
167
179
|
? "text-foreground"
|
|
168
|
-
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50", confirmed === "down" && "scale-110"), children: _jsx(IconThumbDown, { size: 16, stroke: selection === "down" ? 2.5 : 1.5, fill: selection === "down" ? "currentColor" : "none" }) }) }), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { side: "bottom", align: "start", sideOffset: 4, collisionPadding: 8, onOpenAutoFocus: (event) => {
|
|
180
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50", confirmed === "down" && "scale-110"), children: _jsx(IconThumbDown, { size: 16, stroke: selection === "down" ? 2.5 : 1.5, fill: selection === "down" ? "currentColor" : "none" }) }) })), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { id: feedbackContentId, side: "bottom", align: "start", sideOffset: 4, collisionPadding: 8, onOpenAutoFocus: (event) => {
|
|
169
181
|
event.preventDefault();
|
|
170
182
|
feedbackInputRef.current?.focus();
|
|
183
|
+
}, onEscapeKeyDown: () => {
|
|
184
|
+
restoreTriggerFocusRef.current = true;
|
|
185
|
+
}, onInteractOutside: (event) => {
|
|
186
|
+
if (renderNegativeTrigger &&
|
|
187
|
+
event.target instanceof Node &&
|
|
188
|
+
triggerAnchorRef.current?.contains(event.target))
|
|
189
|
+
event.preventDefault();
|
|
190
|
+
}, onCloseAutoFocus: (event) => {
|
|
191
|
+
if (!renderNegativeTrigger)
|
|
192
|
+
return;
|
|
193
|
+
event.preventDefault();
|
|
194
|
+
if (restoreTriggerFocusRef.current) {
|
|
195
|
+
triggerAnchorRef.current
|
|
196
|
+
?.querySelector("button")
|
|
197
|
+
?.focus();
|
|
198
|
+
}
|
|
199
|
+
restoreTriggerFocusRef.current = false;
|
|
171
200
|
}, 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)]", children: _jsxs("form", { className: "flex flex-col gap-2.5", onSubmit: (event) => {
|
|
172
201
|
event.preventDefault();
|
|
173
202
|
handleTextFeedback();
|
|
@@ -177,7 +206,7 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
177
206
|
event.preventDefault();
|
|
178
207
|
handleTextFeedback();
|
|
179
208
|
}
|
|
180
|
-
}, placeholder: t("agentChat.feedback.placeholder"), rows: 3, maxLength: 2000, className: "min-h-20 resize-none px-2.5 py-2 text-xs" }), _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("span", { className: "text-[11px] text-muted-foreground/75", children: t("agentChat.feedback.keyboardHint").replace("{{shortcut}}", typeof navigator !== "undefined" &&
|
|
209
|
+
}, placeholder: t("agentChat.feedback.placeholder"), rows: 3, maxLength: 2000, className: "min-h-20 resize-none px-2.5 py-2 text-xs" }), textSubmitFailed ? (_jsx("p", { role: "alert", className: "text-xs text-destructive", children: t("agentChat.composer.submitFailed") })) : null, _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("span", { className: "text-[11px] text-muted-foreground/75", children: t("agentChat.feedback.keyboardHint").replace("{{shortcut}}", typeof navigator !== "undefined" &&
|
|
181
210
|
/Mac|iPhone|iPad/.test(navigator.userAgent)
|
|
182
211
|
? "⌘"
|
|
183
212
|
: "Ctrl") }), _jsx(Button, { type: "submit", size: "sm", disabled: textSubmitting || !textFeedback.trim(), className: "h-7 px-2.5 text-xs", children: t("agentChat.feedback.submit") })] })] }) }) })] })] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThumbsFeedback.js","sourceRoot":"","sources":["../../../src/app/observability/ThumbsFeedback.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AACjD,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,
|
|
1
|
+
{"version":3,"file":"ThumbsFeedback.js","sourceRoot":"","sources":["../../../src/app/observability/ThumbsFeedback.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/toolkit",
|
|
3
|
-
"version": "0.223.
|
|
3
|
+
"version": "0.223.1-nightly-20261103004150",
|
|
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": {
|
|
@@ -716,7 +716,7 @@
|
|
|
716
716
|
"y-protocols": "^1.0.7",
|
|
717
717
|
"yjs": "^13.6.33",
|
|
718
718
|
"zod": "^4.3.6",
|
|
719
|
-
"@agent-native/agentkit": "^0.223.
|
|
719
|
+
"@agent-native/agentkit": "^0.223.1-nightly-20261103004150"
|
|
720
720
|
},
|
|
721
721
|
"devDependencies": {
|
|
722
722
|
"@excalidraw/excalidraw": "0.18.1",
|
|
@@ -740,10 +740,10 @@
|
|
|
740
740
|
"typescript-7": "npm:typescript@^7.0.2",
|
|
741
741
|
"vite": "8.1.0",
|
|
742
742
|
"vitest": "^4.1.5",
|
|
743
|
-
"@agent-native/core": "^0.223.
|
|
743
|
+
"@agent-native/core": "^0.223.1-nightly-20261103004150"
|
|
744
744
|
},
|
|
745
745
|
"peerDependencies": {
|
|
746
|
-
"@agent-native/core": "
|
|
746
|
+
"@agent-native/core": "0.223.1-nightly-20261103004150",
|
|
747
747
|
"@excalidraw/excalidraw": ">=0.18",
|
|
748
748
|
"@excalidraw/mermaid-to-excalidraw": ">=2",
|
|
749
749
|
"@tanstack/react-query": "^5.99.2",
|
|
@@ -5670,7 +5670,11 @@ export const AgentMessageActions = memo(function AgentMessageActions({
|
|
|
5670
5670
|
{feedbackCapability.visible
|
|
5671
5671
|
? (["positive", "negative"] as const).map((value) => {
|
|
5672
5672
|
const chosen = feedback === value;
|
|
5673
|
-
|
|
5673
|
+
const renderFeedbackButton = (
|
|
5674
|
+
toggle?: () => void,
|
|
5675
|
+
open?: boolean,
|
|
5676
|
+
contentId?: string,
|
|
5677
|
+
) => (
|
|
5674
5678
|
<MessageActionButton
|
|
5675
5679
|
key={value}
|
|
5676
5680
|
label={
|
|
@@ -5695,15 +5699,33 @@ export const AgentMessageActions = memo(function AgentMessageActions({
|
|
|
5695
5699
|
className="size-6"
|
|
5696
5700
|
data-message-action={`feedback-${value}`}
|
|
5697
5701
|
aria-pressed={chosen}
|
|
5702
|
+
aria-haspopup={toggle ? "dialog" : undefined}
|
|
5703
|
+
aria-expanded={toggle ? open : undefined}
|
|
5704
|
+
aria-controls={toggle && open ? contentId : undefined}
|
|
5698
5705
|
disabled={
|
|
5699
5706
|
!feedbackCapability.enabled || feedbackAction.pending
|
|
5700
5707
|
}
|
|
5701
5708
|
{...(feedbackCapability.reason === undefined
|
|
5702
5709
|
? {}
|
|
5703
5710
|
: { title: feedbackCapability.reason })}
|
|
5704
|
-
onPress={() =>
|
|
5711
|
+
onPress={() => {
|
|
5712
|
+
toggle?.();
|
|
5713
|
+
// raw-sql-ok: This submits a UI feedback rating, not SQL.
|
|
5714
|
+
void rateResponse(value);
|
|
5715
|
+
}}
|
|
5705
5716
|
/>
|
|
5706
5717
|
);
|
|
5718
|
+
return value === "negative" && slots.feedbackNote ? (
|
|
5719
|
+
<slots.feedbackNote
|
|
5720
|
+
key={value}
|
|
5721
|
+
threadId={threadId}
|
|
5722
|
+
{...(runId ? { runId } : {})}
|
|
5723
|
+
{...(messageSeq >= 0 ? { messageSeq } : {})}
|
|
5724
|
+
renderTrigger={renderFeedbackButton}
|
|
5725
|
+
/>
|
|
5726
|
+
) : (
|
|
5727
|
+
renderFeedbackButton()
|
|
5728
|
+
);
|
|
5707
5729
|
})
|
|
5708
5730
|
: null}
|
|
5709
5731
|
</div>
|
|
@@ -143,6 +143,16 @@ export interface AgentKitSlots {
|
|
|
143
143
|
messageActions?: ComponentType<AgentKitRenderProps<AgentMessage>>;
|
|
144
144
|
/** Host-owned actions aligned with the trailing message-action group. */
|
|
145
145
|
messageActionsTrailing?: ComponentType<AgentKitRenderProps<AgentMessage>>;
|
|
146
|
+
feedbackNote?: ComponentType<{
|
|
147
|
+
threadId: ThreadId;
|
|
148
|
+
runId?: RunId;
|
|
149
|
+
messageSeq?: number;
|
|
150
|
+
renderTrigger: (
|
|
151
|
+
toggle: () => void,
|
|
152
|
+
open: boolean,
|
|
153
|
+
contentId: string,
|
|
154
|
+
) => ReactNode;
|
|
155
|
+
}>;
|
|
146
156
|
text?: ComponentType<
|
|
147
157
|
AgentKitRenderProps<Extract<AgentMessagePart, { type: "text" }>>
|
|
148
158
|
>;
|
|
@@ -11,10 +11,13 @@ import {
|
|
|
11
11
|
type AgentToolCall,
|
|
12
12
|
type AgentTransport,
|
|
13
13
|
} from "@agent-native/agentkit/protocol";
|
|
14
|
+
import { AgentNativeI18nProvider } from "@agent-native/core/client/i18n";
|
|
14
15
|
import { act, type ReactNode } from "react";
|
|
15
16
|
import { createRoot } from "react-dom/client";
|
|
16
17
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
17
18
|
|
|
19
|
+
import { createToolkitI18nCatalog } from "../../i18n.js";
|
|
20
|
+
import { ThumbsFeedback } from "../../observability/ThumbsFeedback.js";
|
|
18
21
|
import { AgentKitChat } from "./components.js";
|
|
19
22
|
import { AgentKitProvider, type AgentKitRunUsageLoader } from "./context.js";
|
|
20
23
|
|
|
@@ -114,6 +117,7 @@ async function renderChat(
|
|
|
114
117
|
onThreadForked?: () => void;
|
|
115
118
|
followUpModel?: string;
|
|
116
119
|
formatModelName?: (model: string) => string;
|
|
120
|
+
feedbackNote?: boolean;
|
|
117
121
|
} = {},
|
|
118
122
|
) {
|
|
119
123
|
const submitFeedback = options.submitFeedback ?? vi.fn(async () => undefined);
|
|
@@ -183,15 +187,32 @@ async function renderChat(
|
|
|
183
187
|
await Promise.resolve();
|
|
184
188
|
});
|
|
185
189
|
await render(
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
onThreadForked={options.onThreadForked ?? (() => undefined)}
|
|
190
|
-
loadRunUsage={options.loadRunUsage}
|
|
191
|
-
formatModelName={options.formatModelName}
|
|
190
|
+
<AgentNativeI18nProvider
|
|
191
|
+
catalog={createToolkitI18nCatalog({ messages: {} })}
|
|
192
|
+
persistPreference={false}
|
|
192
193
|
>
|
|
193
|
-
<
|
|
194
|
-
|
|
194
|
+
<AgentKitProvider
|
|
195
|
+
controller={client}
|
|
196
|
+
threadId={THREAD}
|
|
197
|
+
slots={
|
|
198
|
+
options.feedbackNote
|
|
199
|
+
? {
|
|
200
|
+
feedbackNote: ({ renderTrigger, ...props }) => (
|
|
201
|
+
<ThumbsFeedback
|
|
202
|
+
{...props}
|
|
203
|
+
renderNegativeTrigger={renderTrigger}
|
|
204
|
+
/>
|
|
205
|
+
),
|
|
206
|
+
}
|
|
207
|
+
: undefined
|
|
208
|
+
}
|
|
209
|
+
onThreadForked={options.onThreadForked ?? (() => undefined)}
|
|
210
|
+
loadRunUsage={options.loadRunUsage}
|
|
211
|
+
formatModelName={options.formatModelName}
|
|
212
|
+
>
|
|
213
|
+
<AgentKitChat composer={false} />
|
|
214
|
+
</AgentKitProvider>
|
|
215
|
+
</AgentNativeI18nProvider>,
|
|
195
216
|
);
|
|
196
217
|
cleanups.push(async () => {
|
|
197
218
|
await act(async () => {
|
|
@@ -251,6 +272,91 @@ function thumb(toolbar: HTMLElement, value: "positive" | "negative") {
|
|
|
251
272
|
}
|
|
252
273
|
|
|
253
274
|
describe("assistant reply toolbar", () => {
|
|
275
|
+
it("opens the note form after one negative vote and delivers the note to both destinations", async () => {
|
|
276
|
+
vi.stubEnv(
|
|
277
|
+
"VITE_AGENT_NATIVE_FEEDBACK_URL",
|
|
278
|
+
"https://forms.agent-native.com/f/agent-native-feedback/_16ewV",
|
|
279
|
+
);
|
|
280
|
+
const fetchMock = vi.fn(async (input: RequestInfo | URL) =>
|
|
281
|
+
String(input).includes("/api/forms/public/")
|
|
282
|
+
? Response.json({
|
|
283
|
+
id: "form-1",
|
|
284
|
+
fields: [{ id: "feedback", type: "textarea" }],
|
|
285
|
+
})
|
|
286
|
+
: Response.json({}),
|
|
287
|
+
);
|
|
288
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
289
|
+
try {
|
|
290
|
+
const { toolbar, submitFeedback } = await renderChat({
|
|
291
|
+
feedbackNote: true,
|
|
292
|
+
});
|
|
293
|
+
await press(thumb(toolbar("assistant-latest"), "negative"));
|
|
294
|
+
expect(submitFeedback).toHaveBeenCalledOnce();
|
|
295
|
+
let input = document.body.querySelector<HTMLTextAreaElement>("textarea");
|
|
296
|
+
expect(input).not.toBeNull();
|
|
297
|
+
const negative = thumb(toolbar("assistant-latest"), "negative");
|
|
298
|
+
expect(negative.getAttribute("aria-expanded")).toBe("true");
|
|
299
|
+
expect(
|
|
300
|
+
document.getElementById(negative.getAttribute("aria-controls")!),
|
|
301
|
+
).not.toBeNull();
|
|
302
|
+
await act(async () => {
|
|
303
|
+
negative.dispatchEvent(
|
|
304
|
+
new PointerEvent("pointerdown", {
|
|
305
|
+
bubbles: true,
|
|
306
|
+
button: 0,
|
|
307
|
+
pointerType: "mouse",
|
|
308
|
+
}),
|
|
309
|
+
);
|
|
310
|
+
negative.click();
|
|
311
|
+
});
|
|
312
|
+
expect(document.body.querySelector("textarea")).toBeNull();
|
|
313
|
+
await press(negative);
|
|
314
|
+
input = document.body.querySelector<HTMLTextAreaElement>("textarea");
|
|
315
|
+
expect(input).not.toBeNull();
|
|
316
|
+
await act(async () => {
|
|
317
|
+
input!.dispatchEvent(
|
|
318
|
+
new KeyboardEvent("keydown", { key: "Escape", bubbles: true }),
|
|
319
|
+
);
|
|
320
|
+
});
|
|
321
|
+
await vi.waitFor(() => expect(document.activeElement).toBe(negative));
|
|
322
|
+
await press(negative);
|
|
323
|
+
input = document.body.querySelector<HTMLTextAreaElement>("textarea");
|
|
324
|
+
expect(input).not.toBeNull();
|
|
325
|
+
await act(async () => {
|
|
326
|
+
Object.getOwnPropertyDescriptor(
|
|
327
|
+
HTMLTextAreaElement.prototype,
|
|
328
|
+
"value",
|
|
329
|
+
)?.set?.call(input, "The answer used the wrong source.");
|
|
330
|
+
input!.dispatchEvent(new Event("input", { bubbles: true }));
|
|
331
|
+
input!.form?.requestSubmit();
|
|
332
|
+
});
|
|
333
|
+
await vi.waitFor(() =>
|
|
334
|
+
expect(
|
|
335
|
+
fetchMock.mock.calls.some(([url]) =>
|
|
336
|
+
String(url).includes("/api/submit/"),
|
|
337
|
+
),
|
|
338
|
+
).toBe(true),
|
|
339
|
+
);
|
|
340
|
+
const calls = fetchMock.mock.calls as unknown as Array<
|
|
341
|
+
[RequestInfo | URL, RequestInit?]
|
|
342
|
+
>;
|
|
343
|
+
expect(
|
|
344
|
+
calls.some(
|
|
345
|
+
([url, init]) =>
|
|
346
|
+
String(url).includes("/observability/feedback") &&
|
|
347
|
+
JSON.parse(String(init?.body)).feedbackType === "text",
|
|
348
|
+
),
|
|
349
|
+
).toBe(true);
|
|
350
|
+
expect(submitFeedback).toHaveBeenCalledOnce();
|
|
351
|
+
await vi.waitFor(() =>
|
|
352
|
+
expect(document.body.querySelector("textarea")).toBeNull(),
|
|
353
|
+
);
|
|
354
|
+
await vi.waitFor(() => expect(document.activeElement).toBe(negative));
|
|
355
|
+
} finally {
|
|
356
|
+
vi.unstubAllGlobals();
|
|
357
|
+
vi.unstubAllEnvs();
|
|
358
|
+
}
|
|
359
|
+
});
|
|
254
360
|
it("shows Copy, both thumbs and More at rest, with no rating menu or timestamp", async () => {
|
|
255
361
|
const { footer, toolbar } = await renderChat();
|
|
256
362
|
const latest = toolbar("assistant-latest");
|
|
@@ -174,6 +174,7 @@ import {
|
|
|
174
174
|
import { isStreamingVoiceMessage } from "../agentkit/react/voice-transcripts.js";
|
|
175
175
|
import { ThreadContextRing } from "../context-xray/ThreadContextRing.js";
|
|
176
176
|
import { threadHasFinishedReply } from "../context-xray/use-thread-context-usage.js";
|
|
177
|
+
import { ThumbsFeedback } from "../observability/ThumbsFeedback.js";
|
|
177
178
|
import { useFirstRunOnboardingGateOwnsSurface } from "../onboarding/first-run-startup-gate.js";
|
|
178
179
|
import {
|
|
179
180
|
AgentKitDevCheckpointProvider,
|
|
@@ -1553,6 +1554,19 @@ const agentKitSlots = {
|
|
|
1553
1554
|
message: AgentKitUserMessage,
|
|
1554
1555
|
messageSupplement: AgentKitMessageSupplement,
|
|
1555
1556
|
messageActionsTrailing: AgentKitHistoryMessageSupplement,
|
|
1557
|
+
feedbackNote: ({
|
|
1558
|
+
renderTrigger,
|
|
1559
|
+
...props
|
|
1560
|
+
}: {
|
|
1561
|
+
threadId: string;
|
|
1562
|
+
runId?: string;
|
|
1563
|
+
messageSeq?: number;
|
|
1564
|
+
renderTrigger: (
|
|
1565
|
+
toggle: () => void,
|
|
1566
|
+
open: boolean,
|
|
1567
|
+
contentId: string,
|
|
1568
|
+
) => React.ReactNode;
|
|
1569
|
+
}) => <ThumbsFeedback {...props} renderNegativeTrigger={renderTrigger} />,
|
|
1556
1570
|
text: AgentKitMarkdownText,
|
|
1557
1571
|
tool: AgentKitTool,
|
|
1558
1572
|
connectionRequest: AgentKitConnectionRequest,
|
|
@@ -55,6 +55,50 @@ afterEach(() => {
|
|
|
55
55
|
const catalog = createToolkitI18nCatalog({ messages: {} });
|
|
56
56
|
|
|
57
57
|
describe("ThumbsFeedback localization", () => {
|
|
58
|
+
it("submits to observability when the optional shared form is unconfigured", async () => {
|
|
59
|
+
vi.stubEnv("VITE_AGENT_NATIVE_FEEDBACK_URL", "not-a-url");
|
|
60
|
+
act(() =>
|
|
61
|
+
root.render(
|
|
62
|
+
<AgentNativeI18nProvider
|
|
63
|
+
catalog={catalog}
|
|
64
|
+
initialLocale="en-US"
|
|
65
|
+
initialPreference="en-US"
|
|
66
|
+
persistPreference={false}
|
|
67
|
+
>
|
|
68
|
+
<ThumbsFeedback threadId="thread-1" runId="run-1" messageSeq={1} />
|
|
69
|
+
</AgentNativeI18nProvider>,
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
act(() =>
|
|
73
|
+
container
|
|
74
|
+
.querySelector<HTMLButtonElement>('[aria-label="Thumbs down"]')!
|
|
75
|
+
.click(),
|
|
76
|
+
);
|
|
77
|
+
const input = document.body.querySelector<HTMLTextAreaElement>("textarea")!;
|
|
78
|
+
act(() => {
|
|
79
|
+
Object.getOwnPropertyDescriptor(
|
|
80
|
+
HTMLTextAreaElement.prototype,
|
|
81
|
+
"value",
|
|
82
|
+
)?.set?.call(input, "A note");
|
|
83
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
84
|
+
input.form?.requestSubmit();
|
|
85
|
+
});
|
|
86
|
+
await vi.waitFor(() =>
|
|
87
|
+
expect(document.body.querySelector("textarea")).toBeNull(),
|
|
88
|
+
);
|
|
89
|
+
expect(
|
|
90
|
+
sharedFetchMock.mock.calls.some(
|
|
91
|
+
([url, init]) =>
|
|
92
|
+
String(url).includes("/observability/feedback") &&
|
|
93
|
+
JSON.parse(String(init?.body)).feedbackType === "text",
|
|
94
|
+
),
|
|
95
|
+
).toBe(true);
|
|
96
|
+
expect(
|
|
97
|
+
sharedFetchMock.mock.calls.some(([url]) =>
|
|
98
|
+
String(url).includes("/api/submit/"),
|
|
99
|
+
),
|
|
100
|
+
).toBe(false);
|
|
101
|
+
});
|
|
58
102
|
it("renders localized accessible labels and explanation copy", async () => {
|
|
59
103
|
act(() => {
|
|
60
104
|
root.render(
|
|
@@ -359,6 +403,11 @@ describe("ThumbsFeedback localization", () => {
|
|
|
359
403
|
_meta: { submitterEmail: "user@example.com" },
|
|
360
404
|
});
|
|
361
405
|
expect(document.body.querySelector("textarea")).not.toBeNull();
|
|
406
|
+
await vi.waitFor(() =>
|
|
407
|
+
expect(
|
|
408
|
+
document.body.querySelector('[role="alert"]')?.textContent,
|
|
409
|
+
).toContain("Could not submit"),
|
|
410
|
+
);
|
|
362
411
|
|
|
363
412
|
act(() => textarea.form?.requestSubmit());
|
|
364
413
|
await vi.waitFor(() => {
|