@invergent/agent-chat-react 2.0.7 → 2.0.8
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/index.cjs +243 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +240 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6470,6 +6470,194 @@ function ChatComposerInner({
|
|
|
6470
6470
|
}
|
|
6471
6471
|
);
|
|
6472
6472
|
}
|
|
6473
|
+
|
|
6474
|
+
// src/components/chat/turn-feedback.tsx
|
|
6475
|
+
init_utils();
|
|
6476
|
+
var MAX_REASON_LENGTH2 = 500;
|
|
6477
|
+
function TurnFeedback({ msg }) {
|
|
6478
|
+
const { adapter, sessionId } = useAgentChatAdapterContext();
|
|
6479
|
+
const [pending, setPending] = react.useState(
|
|
6480
|
+
null
|
|
6481
|
+
);
|
|
6482
|
+
const [error, setError] = react.useState(null);
|
|
6483
|
+
const [reasonDraft, setReasonDraft] = react.useState(null);
|
|
6484
|
+
const llmResponseEventId = msg.llmResponseEventId;
|
|
6485
|
+
const canRate = llmResponseEventId !== void 0 && msg.status === "complete" && sessionId !== null && adapter.submitUserFeedback !== void 0;
|
|
6486
|
+
if (!canRate) return null;
|
|
6487
|
+
const rating = msg.userFeedback?.rating ?? pending;
|
|
6488
|
+
const alreadyRated = msg.userFeedback !== void 0;
|
|
6489
|
+
const submit = async (next, reason) => {
|
|
6490
|
+
if (sessionId === null || llmResponseEventId === void 0 || adapter.submitUserFeedback === void 0) return;
|
|
6491
|
+
setPending(next);
|
|
6492
|
+
setError(null);
|
|
6493
|
+
try {
|
|
6494
|
+
await adapter.submitUserFeedback({
|
|
6495
|
+
sessionId,
|
|
6496
|
+
llmResponseEventId,
|
|
6497
|
+
rating: next,
|
|
6498
|
+
...reason ? { reason } : {}
|
|
6499
|
+
});
|
|
6500
|
+
setReasonDraft(null);
|
|
6501
|
+
} catch (e) {
|
|
6502
|
+
setPending(null);
|
|
6503
|
+
setError(e instanceof Error ? e.message : "Failed to submit feedback");
|
|
6504
|
+
}
|
|
6505
|
+
};
|
|
6506
|
+
const handleRate = (next) => {
|
|
6507
|
+
if (alreadyRated || pending !== null) return;
|
|
6508
|
+
if (next === "down") {
|
|
6509
|
+
setReasonDraft("");
|
|
6510
|
+
return;
|
|
6511
|
+
}
|
|
6512
|
+
void submit("up");
|
|
6513
|
+
};
|
|
6514
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 space-y-1.5", children: [
|
|
6515
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
6516
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6517
|
+
Button,
|
|
6518
|
+
{
|
|
6519
|
+
type: "button",
|
|
6520
|
+
variant: "ghost",
|
|
6521
|
+
size: "icon-xs",
|
|
6522
|
+
"aria-label": "Good response",
|
|
6523
|
+
title: alreadyRated && rating === "up" ? "Good response (recorded)" : "Good response",
|
|
6524
|
+
disabled: pending !== null || alreadyRated,
|
|
6525
|
+
onClick: () => handleRate("up"),
|
|
6526
|
+
className: cn(
|
|
6527
|
+
rating === "up" ? "text-foreground" : "text-muted-foreground/60"
|
|
6528
|
+
),
|
|
6529
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ThumbsUpIcon, { className: "size-3.5" })
|
|
6530
|
+
}
|
|
6531
|
+
),
|
|
6532
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6533
|
+
Button,
|
|
6534
|
+
{
|
|
6535
|
+
type: "button",
|
|
6536
|
+
variant: "ghost",
|
|
6537
|
+
size: "icon-xs",
|
|
6538
|
+
"aria-label": "Poor response",
|
|
6539
|
+
title: alreadyRated && rating === "down" ? "Poor response (recorded)" : "Poor response",
|
|
6540
|
+
disabled: pending !== null || reasonDraft !== null || alreadyRated,
|
|
6541
|
+
onClick: () => handleRate("down"),
|
|
6542
|
+
className: cn(
|
|
6543
|
+
rating === "down" ? "text-foreground" : "text-muted-foreground/60"
|
|
6544
|
+
),
|
|
6545
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ThumbsDownIcon, { className: "size-3.5" })
|
|
6546
|
+
}
|
|
6547
|
+
),
|
|
6548
|
+
alreadyRated && msg.userFeedback?.reason && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6549
|
+
"span",
|
|
6550
|
+
{
|
|
6551
|
+
className: "text-muted-foreground/70 truncate max-w-xs",
|
|
6552
|
+
title: msg.userFeedback.reason,
|
|
6553
|
+
children: [
|
|
6554
|
+
'\xB7 "',
|
|
6555
|
+
msg.userFeedback.reason,
|
|
6556
|
+
'"'
|
|
6557
|
+
]
|
|
6558
|
+
}
|
|
6559
|
+
),
|
|
6560
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-1", children: error })
|
|
6561
|
+
] }),
|
|
6562
|
+
reasonDraft !== null && !alreadyRated && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6563
|
+
ReasonForm2,
|
|
6564
|
+
{
|
|
6565
|
+
initialValue: reasonDraft,
|
|
6566
|
+
busy: pending !== null,
|
|
6567
|
+
onSubmit: (reason) => void submit("down", reason),
|
|
6568
|
+
onCancel: () => {
|
|
6569
|
+
setReasonDraft(null);
|
|
6570
|
+
setError(null);
|
|
6571
|
+
}
|
|
6572
|
+
}
|
|
6573
|
+
)
|
|
6574
|
+
] });
|
|
6575
|
+
}
|
|
6576
|
+
function ReasonForm2({
|
|
6577
|
+
initialValue,
|
|
6578
|
+
busy,
|
|
6579
|
+
onSubmit,
|
|
6580
|
+
onCancel
|
|
6581
|
+
}) {
|
|
6582
|
+
const [value, setValue] = react.useState(initialValue);
|
|
6583
|
+
const trimmed = value.trim();
|
|
6584
|
+
const charsLeft = MAX_REASON_LENGTH2 - value.length;
|
|
6585
|
+
const submit = () => {
|
|
6586
|
+
if (trimmed && !busy) onSubmit(trimmed);
|
|
6587
|
+
};
|
|
6588
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md border border-border bg-muted/30 p-2 space-y-1.5", children: [
|
|
6589
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6590
|
+
"label",
|
|
6591
|
+
{
|
|
6592
|
+
className: "text-xs text-muted-foreground",
|
|
6593
|
+
htmlFor: "turn-feedback-reason",
|
|
6594
|
+
children: "What was wrong with the response?"
|
|
6595
|
+
}
|
|
6596
|
+
),
|
|
6597
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6598
|
+
Textarea,
|
|
6599
|
+
{
|
|
6600
|
+
id: "turn-feedback-reason",
|
|
6601
|
+
autoFocus: true,
|
|
6602
|
+
rows: 3,
|
|
6603
|
+
value,
|
|
6604
|
+
maxLength: MAX_REASON_LENGTH2,
|
|
6605
|
+
placeholder: "e.g. wrong answer, missed a constraint, hallucinated a fact\u2026",
|
|
6606
|
+
onChange: (e) => setValue(e.target.value),
|
|
6607
|
+
onKeyDown: (e) => {
|
|
6608
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
6609
|
+
e.preventDefault();
|
|
6610
|
+
submit();
|
|
6611
|
+
} else if (e.key === "Escape") {
|
|
6612
|
+
e.preventDefault();
|
|
6613
|
+
onCancel();
|
|
6614
|
+
}
|
|
6615
|
+
},
|
|
6616
|
+
className: "text-xs min-h-12",
|
|
6617
|
+
disabled: busy
|
|
6618
|
+
}
|
|
6619
|
+
),
|
|
6620
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
6621
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6622
|
+
"span",
|
|
6623
|
+
{
|
|
6624
|
+
className: cn(
|
|
6625
|
+
"text-[10px] tabular-nums",
|
|
6626
|
+
charsLeft < 50 ? "text-amber-500" : "text-muted-foreground/60"
|
|
6627
|
+
),
|
|
6628
|
+
children: [
|
|
6629
|
+
charsLeft,
|
|
6630
|
+
" characters left"
|
|
6631
|
+
]
|
|
6632
|
+
}
|
|
6633
|
+
),
|
|
6634
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
6635
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6636
|
+
Button,
|
|
6637
|
+
{
|
|
6638
|
+
type: "button",
|
|
6639
|
+
variant: "ghost",
|
|
6640
|
+
size: "xs",
|
|
6641
|
+
onClick: onCancel,
|
|
6642
|
+
disabled: busy,
|
|
6643
|
+
children: "Cancel"
|
|
6644
|
+
}
|
|
6645
|
+
),
|
|
6646
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6647
|
+
Button,
|
|
6648
|
+
{
|
|
6649
|
+
type: "button",
|
|
6650
|
+
variant: "default",
|
|
6651
|
+
size: "xs",
|
|
6652
|
+
onClick: submit,
|
|
6653
|
+
disabled: busy || !trimmed,
|
|
6654
|
+
children: busy ? "Sending\u2026" : "Send feedback"
|
|
6655
|
+
}
|
|
6656
|
+
)
|
|
6657
|
+
] })
|
|
6658
|
+
] })
|
|
6659
|
+
] });
|
|
6660
|
+
}
|
|
6473
6661
|
var MIN_CPS = 40;
|
|
6474
6662
|
var MAX_CPS = 240;
|
|
6475
6663
|
var DRAIN_SECONDS = 0.25;
|
|
@@ -7130,7 +7318,8 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
|
|
|
7130
7318
|
kind: "text",
|
|
7131
7319
|
key: `${msg.id}-text`,
|
|
7132
7320
|
content: msg.content,
|
|
7133
|
-
isStreaming
|
|
7321
|
+
isStreaming,
|
|
7322
|
+
msg
|
|
7134
7323
|
});
|
|
7135
7324
|
}
|
|
7136
7325
|
const hasRunningTool = hasToolCalls && msg.toolCalls.some(
|
|
@@ -7433,7 +7622,10 @@ function TextEntry({
|
|
|
7433
7622
|
/* @__PURE__ */ jsxRuntime.jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
|
|
7434
7623
|
/* @__PURE__ */ jsxRuntime.jsx(TimelineIndicator, { className: "size-2 border-none bg-foreground/40" })
|
|
7435
7624
|
] }),
|
|
7436
|
-
/* @__PURE__ */ jsxRuntime.
|
|
7625
|
+
/* @__PURE__ */ jsxRuntime.jsxs(TimelineContent, { children: [
|
|
7626
|
+
/* @__PURE__ */ jsxRuntime.jsx(MessageResponse, { children: content }),
|
|
7627
|
+
entry.isFinalTurnText && entry.msg.status === "complete" && /* @__PURE__ */ jsxRuntime.jsx(TurnFeedback, { msg: entry.msg })
|
|
7628
|
+
] })
|
|
7437
7629
|
] });
|
|
7438
7630
|
}
|
|
7439
7631
|
function AssistantGroup({
|
|
@@ -7453,6 +7645,13 @@ function AssistantGroup({
|
|
|
7453
7645
|
}
|
|
7454
7646
|
entries = groupBrowserActivityEntries(entries);
|
|
7455
7647
|
entries = groupWebSearchEntries(entries);
|
|
7648
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
7649
|
+
const entry = entries[i];
|
|
7650
|
+
if (entry?.kind === "text") {
|
|
7651
|
+
entries[i] = { ...entry, isFinalTurnText: true };
|
|
7652
|
+
break;
|
|
7653
|
+
}
|
|
7654
|
+
}
|
|
7456
7655
|
const isTailGroup = lastGlobalIndex === totalMessages - 1;
|
|
7457
7656
|
const lastEntry = entries[entries.length - 1];
|
|
7458
7657
|
const hasRunningTool = entries.some(
|
|
@@ -8774,6 +8973,7 @@ var AGENT_CHAT_LISTENED_EVENTS = [
|
|
|
8774
8973
|
"expert.result",
|
|
8775
8974
|
"expert.endorse",
|
|
8776
8975
|
"expert.override",
|
|
8976
|
+
"user.feedback",
|
|
8777
8977
|
"artifact.created",
|
|
8778
8978
|
"artifact.updated",
|
|
8779
8979
|
"browser.provisioned",
|
|
@@ -8932,6 +9132,11 @@ function applyAgentChatEvent(state, event) {
|
|
|
8932
9132
|
nextState,
|
|
8933
9133
|
applyExpertFeedback(nextState.messages, event.type, event.data)
|
|
8934
9134
|
);
|
|
9135
|
+
case "user.feedback":
|
|
9136
|
+
return withMessages(
|
|
9137
|
+
nextState,
|
|
9138
|
+
applyUserFeedback(nextState.messages, event.data)
|
|
9139
|
+
);
|
|
8935
9140
|
case "clarify.response":
|
|
8936
9141
|
return withMessages(
|
|
8937
9142
|
nextState,
|
|
@@ -9129,17 +9334,23 @@ function applyLlmResponse(state, event) {
|
|
|
9129
9334
|
...current,
|
|
9130
9335
|
reasoning: (current.reasoning ?? "") + current.content,
|
|
9131
9336
|
content: "",
|
|
9132
|
-
status: "streaming"
|
|
9337
|
+
status: "streaming",
|
|
9338
|
+
llmResponseEventId: event.eventId
|
|
9133
9339
|
};
|
|
9134
9340
|
} else {
|
|
9135
|
-
messages[idx] = {
|
|
9341
|
+
messages[idx] = {
|
|
9342
|
+
...current,
|
|
9343
|
+
status: "complete",
|
|
9344
|
+
llmResponseEventId: event.eventId
|
|
9345
|
+
};
|
|
9136
9346
|
}
|
|
9137
9347
|
} else if (matchesExistingToolTurn && idx >= 0) {
|
|
9138
9348
|
const current = messages[idx];
|
|
9139
9349
|
messages[idx] = {
|
|
9140
9350
|
...current,
|
|
9141
9351
|
reasoning: responseContent ? appendText(current.reasoning, responseContent) : current.reasoning,
|
|
9142
|
-
status: "streaming"
|
|
9352
|
+
status: "streaming",
|
|
9353
|
+
llmResponseEventId: event.eventId
|
|
9143
9354
|
};
|
|
9144
9355
|
} else if (prevHasTools || !prevAssistant || hasUserAfter) {
|
|
9145
9356
|
messages.push({
|
|
@@ -9148,7 +9359,8 @@ function applyLlmResponse(state, event) {
|
|
|
9148
9359
|
content: hasToolCalls ? "" : responseContent,
|
|
9149
9360
|
reasoning: hasToolCalls && responseContent ? responseContent : void 0,
|
|
9150
9361
|
createdAt: /* @__PURE__ */ new Date(),
|
|
9151
|
-
status: hasToolCalls ? "streaming" : "complete"
|
|
9362
|
+
status: hasToolCalls ? "streaming" : "complete",
|
|
9363
|
+
llmResponseEventId: event.eventId
|
|
9152
9364
|
});
|
|
9153
9365
|
} else {
|
|
9154
9366
|
const current = messages[idx];
|
|
@@ -9156,13 +9368,15 @@ function applyLlmResponse(state, event) {
|
|
|
9156
9368
|
messages[idx] = {
|
|
9157
9369
|
...current,
|
|
9158
9370
|
reasoning: (current.reasoning ?? "") + responseContent,
|
|
9159
|
-
status: "streaming"
|
|
9371
|
+
status: "streaming",
|
|
9372
|
+
llmResponseEventId: event.eventId
|
|
9160
9373
|
};
|
|
9161
9374
|
} else {
|
|
9162
9375
|
messages[idx] = {
|
|
9163
9376
|
...current,
|
|
9164
9377
|
content: responseContent || current.content,
|
|
9165
|
-
status: hasToolCalls ? "streaming" : "complete"
|
|
9378
|
+
status: hasToolCalls ? "streaming" : "complete",
|
|
9379
|
+
llmResponseEventId: event.eventId
|
|
9166
9380
|
};
|
|
9167
9381
|
}
|
|
9168
9382
|
}
|
|
@@ -9375,6 +9589,26 @@ function applyExpertFeedback(messages, type, data) {
|
|
|
9375
9589
|
}
|
|
9376
9590
|
return messages;
|
|
9377
9591
|
}
|
|
9592
|
+
function applyUserFeedback(messages, data) {
|
|
9593
|
+
const source = typeof data.source === "string" ? data.source : "user";
|
|
9594
|
+
if (source !== "user") return messages;
|
|
9595
|
+
const targetEventId = typeof data.target_event_id === "number" ? data.target_event_id : void 0;
|
|
9596
|
+
if (targetEventId == null) return messages;
|
|
9597
|
+
const rating = data.rating === "down" ? "down" : "up";
|
|
9598
|
+
const reason = typeof data.reason === "string" ? data.reason : void 0;
|
|
9599
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
9600
|
+
const msg = messages[i];
|
|
9601
|
+
if (msg?.role !== "assistant") continue;
|
|
9602
|
+
if (msg.llmResponseEventId !== targetEventId) continue;
|
|
9603
|
+
if (msg.userFeedback?.rating === rating && msg.userFeedback?.reason === reason) {
|
|
9604
|
+
return messages;
|
|
9605
|
+
}
|
|
9606
|
+
const next = [...messages];
|
|
9607
|
+
next[i] = { ...msg, userFeedback: { rating, reason } };
|
|
9608
|
+
return next;
|
|
9609
|
+
}
|
|
9610
|
+
return messages;
|
|
9611
|
+
}
|
|
9378
9612
|
function applyClarifyResponse(messages, data) {
|
|
9379
9613
|
const targetToolId = stringValue2(data.tool_call_id);
|
|
9380
9614
|
const responses = Array.isArray(data.responses) ? data.responses : void 0;
|
|
@@ -11494,7 +11728,6 @@ function MetadataPane({ mission }) {
|
|
|
11494
11728
|
}
|
|
11495
11729
|
init_utils();
|
|
11496
11730
|
var DEFAULT_POLL_INTERVAL_MS2 = 3e4;
|
|
11497
|
-
var DEFAULT_STATUS = "active,paused";
|
|
11498
11731
|
function fingerprint(items) {
|
|
11499
11732
|
return items.map(
|
|
11500
11733
|
(m) => `${m.id}:${m.status}:${m.iteration}:${m.lastEvaluationResult ?? ""}:${m.lastEvaluationAt ?? ""}:${m.pausedReason ?? ""}:${m.updatedAt}`
|
|
@@ -11620,7 +11853,7 @@ function MissionsPanel({
|
|
|
11620
11853
|
adapter,
|
|
11621
11854
|
agentId,
|
|
11622
11855
|
title = "Missions",
|
|
11623
|
-
status
|
|
11856
|
+
status,
|
|
11624
11857
|
hideHeader = false,
|
|
11625
11858
|
pollIntervalMs = DEFAULT_POLL_INTERVAL_MS2,
|
|
11626
11859
|
onMissionSelect,
|