@invergent/agent-chat-react 1.6.7 → 1.6.9
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 +226 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +227 -47
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -335,6 +335,16 @@ interface AgentChatAdapter {
|
|
|
335
335
|
eventId?: number;
|
|
336
336
|
status?: string;
|
|
337
337
|
}>;
|
|
338
|
+
defineOutcome?(input: {
|
|
339
|
+
sessionId: string;
|
|
340
|
+
description: string;
|
|
341
|
+
rubric?: string;
|
|
342
|
+
maxIterations?: number;
|
|
343
|
+
}): Promise<{
|
|
344
|
+
eventId?: number;
|
|
345
|
+
outcomeId?: string;
|
|
346
|
+
processedAt?: string;
|
|
347
|
+
}>;
|
|
338
348
|
pauseSession(input: {
|
|
339
349
|
sessionId: string;
|
|
340
350
|
}): Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -335,6 +335,16 @@ interface AgentChatAdapter {
|
|
|
335
335
|
eventId?: number;
|
|
336
336
|
status?: string;
|
|
337
337
|
}>;
|
|
338
|
+
defineOutcome?(input: {
|
|
339
|
+
sessionId: string;
|
|
340
|
+
description: string;
|
|
341
|
+
rubric?: string;
|
|
342
|
+
maxIterations?: number;
|
|
343
|
+
}): Promise<{
|
|
344
|
+
eventId?: number;
|
|
345
|
+
outcomeId?: string;
|
|
346
|
+
processedAt?: string;
|
|
347
|
+
}>;
|
|
338
348
|
pauseSession(input: {
|
|
339
349
|
sessionId: string;
|
|
340
350
|
}): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cn } from './chunk-QSC4UIVT.js';
|
|
2
|
-
import { createContext, memo, useRef,
|
|
3
|
-
import { ChevronDownIcon, AlertTriangle, ChevronDown, ChevronRight, RefreshCw, ChevronRightIcon, GitBranchIcon, XIcon, ThumbsUpIcon, ThumbsDownIcon, ActivityIcon, Loader2Icon, EyeIcon, GlobeIcon, SearchIcon, ListTodoIcon, XCircleIcon, CheckCircle2Icon, Code,
|
|
2
|
+
import { createContext, memo, useRef, useEffect, useCallback, useMemo, useState, lazy, useContext, Suspense, Children } from 'react';
|
|
3
|
+
import { ChevronDownIcon, AlertTriangle, ChevronDown, ChevronRight, RefreshCw, ChevronRightIcon, GitBranchIcon, XIcon, ThumbsUpIcon, ThumbsDownIcon, ActivityIcon, Loader2Icon, EyeIcon, GlobeIcon, CheckIcon, SearchIcon, ListTodoIcon, XCircleIcon, CheckCircle2Icon, Code, CopyIcon, TerminalIcon, Trash2Icon, CircleDotIcon, CircleCheckIcon, CircleXIcon, SkullIcon, ClockIcon, CheckCircleIcon, CircleIcon, InboxIcon, CalendarClockIcon, UsersIcon, MessageSquareIcon, ZapIcon, Maximize2Icon, FolderOpenIcon, UploadIcon, RefreshCwIcon, AlertCircleIcon, ExternalLinkIcon, ClipboardCheckIcon, ShieldAlertIcon, TimerIcon, SquareIcon, ArrowDownIcon, RotateCcwIcon, MousePointer2Icon, DownloadIcon, TrashIcon, ImageIcon, FileTextIcon, FolderIcon, FileIcon, ChevronLeftIcon, MinusIcon, PlusIcon, CornerDownLeftIcon } from 'lucide-react';
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
5
5
|
import { Collapsible as Collapsible$1, Slot, Dialog as Dialog$1, ScrollArea as ScrollArea$1, Tooltip as Tooltip$1, Tabs as Tabs$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, HoverCard as HoverCard$1, Progress as Progress$1 } from 'radix-ui';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -703,8 +703,7 @@ var useReasoning = () => {
|
|
|
703
703
|
}
|
|
704
704
|
return context;
|
|
705
705
|
};
|
|
706
|
-
var
|
|
707
|
-
var AUTO_OPEN_DELAY = 100;
|
|
706
|
+
var MIN_DURATION_MS = 100;
|
|
708
707
|
var MS_IN_S = 1e3;
|
|
709
708
|
var Reasoning = memo(
|
|
710
709
|
({
|
|
@@ -718,7 +717,6 @@ var Reasoning = memo(
|
|
|
718
717
|
...props
|
|
719
718
|
}) => {
|
|
720
719
|
const resolvedDefaultOpen = defaultOpen ?? false;
|
|
721
|
-
const isExplicitlyClosed = defaultOpen === false;
|
|
722
720
|
const [isOpen, setIsOpen] = useControllableState({
|
|
723
721
|
defaultProp: resolvedDefaultOpen,
|
|
724
722
|
onChange: onOpenChange,
|
|
@@ -728,8 +726,6 @@ var Reasoning = memo(
|
|
|
728
726
|
defaultProp: void 0,
|
|
729
727
|
prop: durationProp
|
|
730
728
|
});
|
|
731
|
-
const hasEverStreamedRef = useRef(false);
|
|
732
|
-
const [hasAutoClosed, setHasAutoClosed] = useState(false);
|
|
733
729
|
const startTimeRef = useRef(null);
|
|
734
730
|
useEffect(() => {
|
|
735
731
|
if (isStreaming) {
|
|
@@ -739,29 +735,11 @@ var Reasoning = memo(
|
|
|
739
735
|
} else if (startTimeRef.current !== null) {
|
|
740
736
|
const elapsed = Date.now() - startTimeRef.current;
|
|
741
737
|
startTimeRef.current = null;
|
|
742
|
-
if (elapsed >=
|
|
743
|
-
hasEverStreamedRef.current = true;
|
|
738
|
+
if (elapsed >= MIN_DURATION_MS) {
|
|
744
739
|
setDuration(Math.ceil(elapsed / MS_IN_S));
|
|
745
740
|
}
|
|
746
741
|
}
|
|
747
742
|
}, [isStreaming, setDuration]);
|
|
748
|
-
useEffect(() => {
|
|
749
|
-
if (!isStreaming || isOpen || isExplicitlyClosed) return;
|
|
750
|
-
const timer = setTimeout(() => {
|
|
751
|
-
hasEverStreamedRef.current = true;
|
|
752
|
-
setIsOpen(true);
|
|
753
|
-
}, AUTO_OPEN_DELAY);
|
|
754
|
-
return () => clearTimeout(timer);
|
|
755
|
-
}, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);
|
|
756
|
-
useEffect(() => {
|
|
757
|
-
if (hasEverStreamedRef.current && !isStreaming && isOpen && !hasAutoClosed) {
|
|
758
|
-
const timer = setTimeout(() => {
|
|
759
|
-
setIsOpen(false);
|
|
760
|
-
setHasAutoClosed(true);
|
|
761
|
-
}, AUTO_CLOSE_DELAY);
|
|
762
|
-
return () => clearTimeout(timer);
|
|
763
|
-
}
|
|
764
|
-
}, [isStreaming, isOpen, setIsOpen, hasAutoClosed]);
|
|
765
743
|
const handleOpenChange = useCallback(
|
|
766
744
|
(newOpen) => {
|
|
767
745
|
setIsOpen(newOpen);
|
|
@@ -1183,7 +1161,7 @@ function TerminalCollapsible({ command, output, isRunning, hasError }) {
|
|
|
1183
1161
|
className: "not-prose w-full",
|
|
1184
1162
|
children: [
|
|
1185
1163
|
/* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "group/trigger flex w-fit items-center gap-2 text-sm transition-colors", children: [
|
|
1186
|
-
/* @__PURE__ */ jsx("span", { className: "text-left", children: isRunning ? /* @__PURE__ */ jsx(Shimmer, { as: "span", duration: 1, children: "Running command..." }) : hasError ? /* @__PURE__ */ jsx("span", { className: "font-semibold text-destructive", children: "Command failed" }) : /* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: "Command
|
|
1164
|
+
/* @__PURE__ */ jsx("span", { className: "text-left", children: isRunning ? /* @__PURE__ */ jsx(Shimmer, { as: "span", duration: 1, children: "Running command..." }) : hasError ? /* @__PURE__ */ jsx("span", { className: "font-semibold text-destructive", children: "Command failed" }) : /* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: "Command" }) }),
|
|
1187
1165
|
/* @__PURE__ */ jsx(
|
|
1188
1166
|
ChevronDownIcon,
|
|
1189
1167
|
{
|
|
@@ -1234,14 +1212,16 @@ function TerminalToolBlock({ tc }) {
|
|
|
1234
1212
|
const isRunning = tc.status === "running";
|
|
1235
1213
|
const result = parseTerminalResult(tc.result, tc.args);
|
|
1236
1214
|
if (result) {
|
|
1237
|
-
const
|
|
1215
|
+
const hasError = result.exit_code !== 0 || Boolean(result.error);
|
|
1216
|
+
if (hasError) return null;
|
|
1217
|
+
const output = result.output || "";
|
|
1238
1218
|
return /* @__PURE__ */ jsx(
|
|
1239
1219
|
TerminalCollapsible,
|
|
1240
1220
|
{
|
|
1241
1221
|
command: result.command,
|
|
1242
1222
|
output,
|
|
1243
1223
|
isRunning,
|
|
1244
|
-
hasError:
|
|
1224
|
+
hasError: false
|
|
1245
1225
|
}
|
|
1246
1226
|
);
|
|
1247
1227
|
}
|
|
@@ -2064,10 +2044,7 @@ function WebToolBlock({ tc }) {
|
|
|
2064
2044
|
let displayText = "";
|
|
2065
2045
|
try {
|
|
2066
2046
|
const args = JSON.parse(tc.args);
|
|
2067
|
-
if (tc.toolName === "
|
|
2068
|
-
const urls = args.urls ?? [];
|
|
2069
|
-
displayText = urls[0] ?? "";
|
|
2070
|
-
} else if (tc.toolName === "web_search") {
|
|
2047
|
+
if (tc.toolName === "web_search") {
|
|
2071
2048
|
displayText = args.query ?? "";
|
|
2072
2049
|
} else if (tc.toolName === "web_crawl") {
|
|
2073
2050
|
displayText = args.url ?? "";
|
|
@@ -2075,12 +2052,10 @@ function WebToolBlock({ tc }) {
|
|
|
2075
2052
|
} catch {
|
|
2076
2053
|
}
|
|
2077
2054
|
const toolLabel2 = {
|
|
2078
|
-
web_extract: "Web Fetch",
|
|
2079
2055
|
web_search: "Web Search",
|
|
2080
2056
|
web_crawl: "Web Crawl"
|
|
2081
2057
|
}[tc.toolName] ?? tc.toolName;
|
|
2082
2058
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm py-0.5", children: [
|
|
2083
|
-
/* @__PURE__ */ jsx(GlobeIcon, { className: "size-3.5 text-muted-foreground/60 shrink-0" }),
|
|
2084
2059
|
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: toolLabel2 }),
|
|
2085
2060
|
displayText && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/70 truncate text-xs", children: displayText })
|
|
2086
2061
|
] });
|
|
@@ -2099,6 +2074,88 @@ function VisionAnalyzeBlock({ tc }) {
|
|
|
2099
2074
|
image && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/70 truncate text-xs", children: image })
|
|
2100
2075
|
] });
|
|
2101
2076
|
}
|
|
2077
|
+
function parseUrls(rawArgs) {
|
|
2078
|
+
try {
|
|
2079
|
+
const args = JSON.parse(rawArgs);
|
|
2080
|
+
if (Array.isArray(args.urls)) {
|
|
2081
|
+
return args.urls.filter((u) => typeof u === "string");
|
|
2082
|
+
}
|
|
2083
|
+
} catch {
|
|
2084
|
+
}
|
|
2085
|
+
return [];
|
|
2086
|
+
}
|
|
2087
|
+
function parseResult(rawResult) {
|
|
2088
|
+
const byUrl = /* @__PURE__ */ new Map();
|
|
2089
|
+
if (!rawResult) return { byUrl, toolError: null };
|
|
2090
|
+
try {
|
|
2091
|
+
const parsed = JSON.parse(rawResult);
|
|
2092
|
+
const entries = Array.isArray(parsed?.results) ? parsed.results : [];
|
|
2093
|
+
for (const entry of entries) {
|
|
2094
|
+
if (entry && typeof entry.url === "string") {
|
|
2095
|
+
byUrl.set(entry.url, entry);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
if (byUrl.size === 0 && typeof parsed?.error === "string") {
|
|
2099
|
+
return { byUrl, toolError: parsed.error };
|
|
2100
|
+
}
|
|
2101
|
+
} catch {
|
|
2102
|
+
}
|
|
2103
|
+
return { byUrl, toolError: null };
|
|
2104
|
+
}
|
|
2105
|
+
function domain(url) {
|
|
2106
|
+
try {
|
|
2107
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
2108
|
+
} catch {
|
|
2109
|
+
return url;
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
function WebExtractToolBlock({ tc }) {
|
|
2113
|
+
const urls = parseUrls(tc.args);
|
|
2114
|
+
const { byUrl, toolError } = parseResult(tc.result);
|
|
2115
|
+
const isComplete = tc.status === "complete" || tc.status === "error";
|
|
2116
|
+
if (urls.length === 0) {
|
|
2117
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm py-0.5", children: [
|
|
2118
|
+
/* @__PURE__ */ jsx(GlobeIcon, { className: "size-3.5 text-muted-foreground/60 shrink-0" }),
|
|
2119
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Web Fetch" })
|
|
2120
|
+
] });
|
|
2121
|
+
}
|
|
2122
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
2123
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
2124
|
+
/* @__PURE__ */ jsx(GlobeIcon, { className: "size-3.5 text-muted-foreground/60 shrink-0" }),
|
|
2125
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Web Fetch" }),
|
|
2126
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground/70 text-xs", children: [
|
|
2127
|
+
urls.length,
|
|
2128
|
+
" URL",
|
|
2129
|
+
urls.length !== 1 ? "s" : ""
|
|
2130
|
+
] })
|
|
2131
|
+
] }),
|
|
2132
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-1 ml-5 space-y-0.5", children: urls.map((url, i) => {
|
|
2133
|
+
const entry = byUrl.get(url);
|
|
2134
|
+
const perUrlError = entry?.error;
|
|
2135
|
+
const failure = perUrlError ?? (isComplete && !entry ? toolError : null);
|
|
2136
|
+
const fetched = entry && !perUrlError;
|
|
2137
|
+
const pending = !isComplete && !entry;
|
|
2138
|
+
const row = /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2139
|
+
/* @__PURE__ */ jsx(
|
|
2140
|
+
"span",
|
|
2141
|
+
{
|
|
2142
|
+
className: cn(
|
|
2143
|
+
"truncate",
|
|
2144
|
+
pending ? "text-muted-foreground/50" : "text-muted-foreground"
|
|
2145
|
+
),
|
|
2146
|
+
children: domain(url)
|
|
2147
|
+
}
|
|
2148
|
+
),
|
|
2149
|
+
fetched && /* @__PURE__ */ jsx(CheckIcon, { className: "size-3 text-green-500/70 shrink-0" }),
|
|
2150
|
+
failure && /* @__PURE__ */ jsx(XIcon, { className: "size-3 text-red-500/80 shrink-0" })
|
|
2151
|
+
] });
|
|
2152
|
+
return /* @__PURE__ */ jsx("li", { children: failure ? /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
2153
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: row }),
|
|
2154
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "top", children: failure })
|
|
2155
|
+
] }) : row }, `${url}-${i}`);
|
|
2156
|
+
}) })
|
|
2157
|
+
] });
|
|
2158
|
+
}
|
|
2102
2159
|
function splitChangeLines(change) {
|
|
2103
2160
|
const v = change.value;
|
|
2104
2161
|
if (v === "") return [];
|
|
@@ -2778,7 +2835,7 @@ function parseArgs2(args) {
|
|
|
2778
2835
|
return { action: "unknown" };
|
|
2779
2836
|
}
|
|
2780
2837
|
}
|
|
2781
|
-
function
|
|
2838
|
+
function parseResult2(result) {
|
|
2782
2839
|
if (!result) return null;
|
|
2783
2840
|
try {
|
|
2784
2841
|
return JSON.parse(result);
|
|
@@ -2996,7 +3053,7 @@ function OutputPreview({ output }) {
|
|
|
2996
3053
|
function ProcessToolBlock({ tc }) {
|
|
2997
3054
|
const isRunning = tc.status === "running";
|
|
2998
3055
|
const args = parseArgs2(tc.args);
|
|
2999
|
-
const result =
|
|
3056
|
+
const result = parseResult2(tc.result);
|
|
3000
3057
|
const action = args.action || "unknown";
|
|
3001
3058
|
const actionLabel = {
|
|
3002
3059
|
list: "Process List",
|
|
@@ -4033,6 +4090,7 @@ function ToolCallBlock({
|
|
|
4033
4090
|
case "session_search":
|
|
4034
4091
|
return /* @__PURE__ */ jsx(SessionSearchBlock, { tc });
|
|
4035
4092
|
case "web_extract":
|
|
4093
|
+
return /* @__PURE__ */ jsx(WebExtractToolBlock, { tc });
|
|
4036
4094
|
case "web_search":
|
|
4037
4095
|
case "web_crawl":
|
|
4038
4096
|
return /* @__PURE__ */ jsx(WebToolBlock, { tc });
|
|
@@ -4074,6 +4132,51 @@ function ToolCallBlock({
|
|
|
4074
4132
|
return /* @__PURE__ */ jsx(DefaultToolBlock, { tc });
|
|
4075
4133
|
}
|
|
4076
4134
|
}
|
|
4135
|
+
function parseQuery(rawArgs) {
|
|
4136
|
+
try {
|
|
4137
|
+
const args = JSON.parse(rawArgs);
|
|
4138
|
+
return typeof args.query === "string" ? args.query : "";
|
|
4139
|
+
} catch {
|
|
4140
|
+
return "";
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
function parseResultCount2(rawResult) {
|
|
4144
|
+
if (!rawResult) return null;
|
|
4145
|
+
try {
|
|
4146
|
+
const parsed = JSON.parse(rawResult);
|
|
4147
|
+
if (Array.isArray(parsed?.data?.web)) return parsed.data.web.length;
|
|
4148
|
+
if (Array.isArray(parsed?.results)) return parsed.results.length;
|
|
4149
|
+
} catch {
|
|
4150
|
+
}
|
|
4151
|
+
return null;
|
|
4152
|
+
}
|
|
4153
|
+
function WebSearchRow({ tc }) {
|
|
4154
|
+
const query = parseQuery(tc.args);
|
|
4155
|
+
const count = parseResultCount2(tc.result);
|
|
4156
|
+
const showCount = count !== null && tc.status === "complete";
|
|
4157
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs min-w-0", children: [
|
|
4158
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground truncate", children: query || "\u2014" }),
|
|
4159
|
+
showCount && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground/50 shrink-0", children: [
|
|
4160
|
+
count,
|
|
4161
|
+
" result",
|
|
4162
|
+
count !== 1 ? "s" : ""
|
|
4163
|
+
] })
|
|
4164
|
+
] });
|
|
4165
|
+
}
|
|
4166
|
+
function WebSearchGroupBlock({ tcs }) {
|
|
4167
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
4168
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
4169
|
+
/* @__PURE__ */ jsx(SearchIcon, { className: "size-3.5 text-muted-foreground/60 shrink-0" }),
|
|
4170
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Web Search" }),
|
|
4171
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground/70 text-xs", children: [
|
|
4172
|
+
tcs.length,
|
|
4173
|
+
" ",
|
|
4174
|
+
tcs.length === 1 ? "query" : "queries"
|
|
4175
|
+
] })
|
|
4176
|
+
] }),
|
|
4177
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-1 ml-5 space-y-0.5", children: tcs.map((tc) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(WebSearchRow, { tc }) }, tc.id)) })
|
|
4178
|
+
] });
|
|
4179
|
+
}
|
|
4077
4180
|
var ChatMessage = memo(function ChatMessage2({
|
|
4078
4181
|
message,
|
|
4079
4182
|
isLast,
|
|
@@ -5473,6 +5576,11 @@ function ChatComposerInner({
|
|
|
5473
5576
|
const builtin = [
|
|
5474
5577
|
{ value: "/clear", label: "/clear", description: "Clear conversation" },
|
|
5475
5578
|
{ value: "/compress", label: "/compress", description: "Compress context" },
|
|
5579
|
+
{ value: "/goal", label: "/goal", description: "Define an outcome goal" },
|
|
5580
|
+
{ value: "/goal status", label: "/goal status", description: "Show outcome goal status" },
|
|
5581
|
+
{ value: "/goal pause", label: "/goal pause", description: "Pause automatic goal continuation" },
|
|
5582
|
+
{ value: "/goal resume", label: "/goal resume", description: "Resume a paused goal" },
|
|
5583
|
+
{ value: "/goal clear", label: "/goal clear", description: "Clear the current goal" },
|
|
5476
5584
|
{ value: "/loop", label: "/loop", description: "Schedule recurring prompt" },
|
|
5477
5585
|
{ value: "/loop list", label: "/loop list", description: "List active loops" },
|
|
5478
5586
|
{ value: "/loop cancel", label: "/loop cancel", description: "Cancel a loop by ID" }
|
|
@@ -6256,6 +6364,10 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
|
|
|
6256
6364
|
});
|
|
6257
6365
|
continue;
|
|
6258
6366
|
}
|
|
6367
|
+
if (tc.toolName === "terminal" && tc.status !== "running") {
|
|
6368
|
+
const parsed = parseTerminalResult(tc.result, tc.args);
|
|
6369
|
+
if (parsed && (parsed.exit_code !== 0 || parsed.error)) continue;
|
|
6370
|
+
}
|
|
6259
6371
|
entries.push({ kind: "tool", key: tc.id, tc });
|
|
6260
6372
|
}
|
|
6261
6373
|
}
|
|
@@ -6296,6 +6408,33 @@ function groupBrowserActivityEntries(entries) {
|
|
|
6296
6408
|
function isBrowserToolCall(call) {
|
|
6297
6409
|
return call.toolName.startsWith("browser_");
|
|
6298
6410
|
}
|
|
6411
|
+
function groupWebSearchEntries(entries) {
|
|
6412
|
+
const grouped = [];
|
|
6413
|
+
let buffer = [];
|
|
6414
|
+
const flush = () => {
|
|
6415
|
+
if (buffer.length === 0) return;
|
|
6416
|
+
if (buffer.length === 1) {
|
|
6417
|
+
grouped.push({ kind: "tool", key: buffer[0].id, tc: buffer[0] });
|
|
6418
|
+
} else {
|
|
6419
|
+
grouped.push({
|
|
6420
|
+
kind: "web_search_group",
|
|
6421
|
+
key: `web-search-${buffer[0].id}-${buffer[buffer.length - 1].id}`,
|
|
6422
|
+
calls: buffer
|
|
6423
|
+
});
|
|
6424
|
+
}
|
|
6425
|
+
buffer = [];
|
|
6426
|
+
};
|
|
6427
|
+
for (const entry of entries) {
|
|
6428
|
+
if (entry.kind === "tool" && entry.tc.toolName === "web_search") {
|
|
6429
|
+
buffer.push(entry.tc);
|
|
6430
|
+
continue;
|
|
6431
|
+
}
|
|
6432
|
+
flush();
|
|
6433
|
+
grouped.push(entry);
|
|
6434
|
+
}
|
|
6435
|
+
flush();
|
|
6436
|
+
return grouped;
|
|
6437
|
+
}
|
|
6299
6438
|
function groupMessages(messages) {
|
|
6300
6439
|
const groups = [];
|
|
6301
6440
|
let pendingSystem = [];
|
|
@@ -6461,6 +6600,18 @@ function TimelineEntryItem({
|
|
|
6461
6600
|
/* @__PURE__ */ jsx(TimelineContent, { children: /* @__PURE__ */ jsx(BrowserActivityGroup, { calls: entry.calls }) })
|
|
6462
6601
|
] });
|
|
6463
6602
|
}
|
|
6603
|
+
if (entry.kind === "web_search_group") {
|
|
6604
|
+
const allComplete = entry.calls.every((tc) => tc.status === "complete");
|
|
6605
|
+
const anyRunning = entry.calls.some((tc) => tc.status === "running");
|
|
6606
|
+
const indicatorClass = anyRunning ? "bg-emerald-500 animate-pulse" : allComplete ? "bg-emerald-500" : "bg-red-500";
|
|
6607
|
+
return /* @__PURE__ */ jsxs(TimelineItem, { step, children: [
|
|
6608
|
+
/* @__PURE__ */ jsxs(TimelineHeader, { children: [
|
|
6609
|
+
/* @__PURE__ */ jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
|
|
6610
|
+
/* @__PURE__ */ jsx(TimelineIndicator, { className: cn("size-2 border-none", indicatorClass) })
|
|
6611
|
+
] }),
|
|
6612
|
+
/* @__PURE__ */ jsx(TimelineContent, { children: /* @__PURE__ */ jsx(WebSearchGroupBlock, { tcs: entry.calls }) })
|
|
6613
|
+
] });
|
|
6614
|
+
}
|
|
6464
6615
|
if (entry.kind === "text") {
|
|
6465
6616
|
return /* @__PURE__ */ jsxs(TimelineItem, { step, children: [
|
|
6466
6617
|
/* @__PURE__ */ jsxs(TimelineHeader, { children: [
|
|
@@ -6528,6 +6679,7 @@ function AssistantGroup({
|
|
|
6528
6679
|
entries.push(...messageToEntries(messages[i], isLast, artifactFallbacks));
|
|
6529
6680
|
}
|
|
6530
6681
|
entries = groupBrowserActivityEntries(entries);
|
|
6682
|
+
entries = groupWebSearchEntries(entries);
|
|
6531
6683
|
const isTailGroup = lastGlobalIndex === totalMessages - 1;
|
|
6532
6684
|
const lastEntry = entries[entries.length - 1];
|
|
6533
6685
|
const hasRunningTool = entries.some(
|
|
@@ -8683,11 +8835,12 @@ function useAgentChatRuntime({
|
|
|
8683
8835
|
const send = useCallback(
|
|
8684
8836
|
async (content, images) => {
|
|
8685
8837
|
markSending(content, images);
|
|
8838
|
+
const goal = images?.length ? null : parseGoalDefinition(content);
|
|
8686
8839
|
if (!sessionId) {
|
|
8687
8840
|
try {
|
|
8688
8841
|
const session2 = await adapter.createSession({ agentId });
|
|
8689
8842
|
onSessionChange?.(session2.id);
|
|
8690
|
-
await adapter
|
|
8843
|
+
await sendTurn(adapter, session2.id, content, images, goal);
|
|
8691
8844
|
} catch (error) {
|
|
8692
8845
|
markSendError(error instanceof Error ? error.message : "send failed");
|
|
8693
8846
|
throw error;
|
|
@@ -8696,7 +8849,7 @@ function useAgentChatRuntime({
|
|
|
8696
8849
|
}
|
|
8697
8850
|
try {
|
|
8698
8851
|
ensureStreamForNewTurn(sessionId);
|
|
8699
|
-
await adapter
|
|
8852
|
+
await sendTurn(adapter, sessionId, content, images, goal);
|
|
8700
8853
|
} catch (error) {
|
|
8701
8854
|
markSendError(error instanceof Error ? error.message : "send failed");
|
|
8702
8855
|
throw error;
|
|
@@ -8769,6 +8922,30 @@ function findLastAssistantIndex2(messages) {
|
|
|
8769
8922
|
}
|
|
8770
8923
|
return -1;
|
|
8771
8924
|
}
|
|
8925
|
+
var GOAL_RUBRIC_RE = /\n\s*(?:rubric|criteria)\s*:\s*\n/i;
|
|
8926
|
+
var GOAL_CONTROL_COMMANDS = /* @__PURE__ */ new Set(["", "status", "pause", "resume", "clear"]);
|
|
8927
|
+
async function sendTurn(adapter, sessionId, content, images, goal) {
|
|
8928
|
+
if (goal && adapter.defineOutcome) {
|
|
8929
|
+
await adapter.defineOutcome({
|
|
8930
|
+
sessionId,
|
|
8931
|
+
description: goal.description,
|
|
8932
|
+
rubric: goal.rubric
|
|
8933
|
+
});
|
|
8934
|
+
return;
|
|
8935
|
+
}
|
|
8936
|
+
await adapter.sendMessage({ sessionId, content, images });
|
|
8937
|
+
}
|
|
8938
|
+
function parseGoalDefinition(content) {
|
|
8939
|
+
const text = content.trim();
|
|
8940
|
+
if (text !== "/goal" && !text.startsWith("/goal ")) return null;
|
|
8941
|
+
const args = text.slice("/goal".length).trim();
|
|
8942
|
+
if (GOAL_CONTROL_COMMANDS.has(args.toLowerCase())) return null;
|
|
8943
|
+
const match = GOAL_RUBRIC_RE.exec(args);
|
|
8944
|
+
const description = (match ? args.slice(0, match.index) : args).trim();
|
|
8945
|
+
if (!description) return null;
|
|
8946
|
+
const rubric = match ? args.slice(match.index + match[0].length).trim() : "";
|
|
8947
|
+
return rubric ? { description, rubric } : { description };
|
|
8948
|
+
}
|
|
8772
8949
|
function AgentChat({
|
|
8773
8950
|
adapter,
|
|
8774
8951
|
agentId,
|
|
@@ -8866,7 +9043,7 @@ function AgentChat({
|
|
|
8866
9043
|
"div",
|
|
8867
9044
|
{
|
|
8868
9045
|
"data-testid": "workspace-panel-frame",
|
|
8869
|
-
className: hasBrowserPanel ? "h-1/2 min-h-0 w-full overflow-hidden" : "min-h-0",
|
|
9046
|
+
className: hasBrowserPanel ? "h-1/2 min-h-0 w-full overflow-hidden" : "min-h-0 h-full",
|
|
8870
9047
|
children: /* @__PURE__ */ jsx(
|
|
8871
9048
|
WorkspacePanel,
|
|
8872
9049
|
{
|
|
@@ -9583,10 +9760,11 @@ function formatKind(value) {
|
|
|
9583
9760
|
if (!value) return "Scheduled";
|
|
9584
9761
|
return value.split(/[_-]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
9585
9762
|
}
|
|
9586
|
-
function formatRelative2(value, label) {
|
|
9763
|
+
function formatRelative2(value, label, future = false) {
|
|
9587
9764
|
if (!value) return null;
|
|
9588
9765
|
const date = new Date(value);
|
|
9589
9766
|
if (Number.isNaN(date.getTime())) return null;
|
|
9767
|
+
if (future && date.getTime() <= Date.now()) return `${label} due now`;
|
|
9590
9768
|
return `${label} ${formatDistanceToNow(date, { addSuffix: true })}`;
|
|
9591
9769
|
}
|
|
9592
9770
|
function formatRuns(count) {
|
|
@@ -9633,10 +9811,10 @@ function ScheduledWorkRow({
|
|
|
9633
9811
|
const lastSessionId = item.lastSessionId ?? null;
|
|
9634
9812
|
const meta = [
|
|
9635
9813
|
scheduleDisplay(item),
|
|
9636
|
-
formatRelative2(item.nextRunAt, "Next"),
|
|
9814
|
+
formatRelative2(item.nextRunAt, "Next", true),
|
|
9637
9815
|
formatRelative2(item.lastRunAt, "Last"),
|
|
9638
9816
|
formatRuns(item.runCount),
|
|
9639
|
-
item.expiresAt ? formatRelative2(item.expiresAt, "Expires") : null
|
|
9817
|
+
item.expiresAt ? formatRelative2(item.expiresAt, "Expires", true) : null
|
|
9640
9818
|
].filter(Boolean);
|
|
9641
9819
|
const openLastRun = () => {
|
|
9642
9820
|
if (lastSessionId) onOpenLastRun(lastSessionId);
|
|
@@ -9987,8 +10165,7 @@ function TreeNodeRow({
|
|
|
9987
10165
|
const title = entry.title ?? fallbackSessionTitle(entry);
|
|
9988
10166
|
const subtitle = [
|
|
9989
10167
|
formatRunKind(entry.runKind),
|
|
9990
|
-
entry.agentType,
|
|
9991
|
-
entry.model ?? "default",
|
|
10168
|
+
entry.model ?? entry.agentType,
|
|
9992
10169
|
formatSessionTime(entry.updatedAt)
|
|
9993
10170
|
].filter(Boolean).join(" \xB7 ");
|
|
9994
10171
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -10043,7 +10220,10 @@ function TreeNodeRow({
|
|
|
10043
10220
|
"button",
|
|
10044
10221
|
{
|
|
10045
10222
|
type: "button",
|
|
10046
|
-
className:
|
|
10223
|
+
className: cn(
|
|
10224
|
+
"p-1 rounded hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none transition-all",
|
|
10225
|
+
deletingSessionId === entry.id ? "opacity-100" : "opacity-0 group-hover:opacity-100 focus-visible:opacity-100"
|
|
10226
|
+
),
|
|
10047
10227
|
onClick: (e) => {
|
|
10048
10228
|
e.stopPropagation();
|
|
10049
10229
|
onDelete(entry.id);
|
|
@@ -10051,7 +10231,7 @@ function TreeNodeRow({
|
|
|
10051
10231
|
"aria-label": "Delete session",
|
|
10052
10232
|
title: "Delete session",
|
|
10053
10233
|
disabled: deletingSessionId === entry.id,
|
|
10054
|
-
children: /* @__PURE__ */ jsx(Trash2Icon, { className: "w-3 h-3" })
|
|
10234
|
+
children: deletingSessionId === entry.id ? /* @__PURE__ */ jsx(Loader2Icon, { className: "w-3 h-3 animate-spin" }) : /* @__PURE__ */ jsx(Trash2Icon, { className: "w-3 h-3" })
|
|
10055
10235
|
}
|
|
10056
10236
|
)
|
|
10057
10237
|
]
|