@invergent/agent-chat-react 2.4.13 → 2.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.
- package/dist/index.cjs +548 -187
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -2
- package/dist/index.d.ts +55 -2
- package/dist/index.js +541 -188
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2428,6 +2428,37 @@ function MCPToolBlock({ tc }) {
|
|
|
2428
2428
|
summary && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/60 truncate text-xs", children: summary })
|
|
2429
2429
|
] });
|
|
2430
2430
|
}
|
|
2431
|
+
function ResearchMemoryBlock({ tc }) {
|
|
2432
|
+
const args = parseArgs(tc.args) ?? {};
|
|
2433
|
+
const result = tc.result ? parseArgs(tc.result) ?? {} : {};
|
|
2434
|
+
let detail = "";
|
|
2435
|
+
if (args.action === "add") {
|
|
2436
|
+
const host = args.url ? hostname(args.url) : "";
|
|
2437
|
+
const sid = result.source_id ?? "";
|
|
2438
|
+
detail = sid ? `recorded ${sid}${host ? ` \xB7 ${host}` : ""}` : host ? `recorded \xB7 ${host}` : "recorded";
|
|
2439
|
+
} else if (args.action === "retrieve") {
|
|
2440
|
+
const n = result.sources?.length ?? 0;
|
|
2441
|
+
detail = args.query ? `${n} source${n === 1 ? "" : "s"} for "${truncate2(args.query, 40)}"` : `${n} source${n === 1 ? "" : "s"}`;
|
|
2442
|
+
} else if (args.action === "list") {
|
|
2443
|
+
const n = result.sources?.length ?? 0;
|
|
2444
|
+
detail = `${n} source${n === 1 ? "" : "s"}`;
|
|
2445
|
+
}
|
|
2446
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm py-0.5", children: [
|
|
2447
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BookOpenIcon, { className: "size-3.5 text-muted-foreground/60 shrink-0" }),
|
|
2448
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground", children: "Research" }),
|
|
2449
|
+
detail && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70 truncate text-xs", children: detail })
|
|
2450
|
+
] });
|
|
2451
|
+
}
|
|
2452
|
+
function hostname(url) {
|
|
2453
|
+
try {
|
|
2454
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
2455
|
+
} catch {
|
|
2456
|
+
return url;
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
function truncate2(s, n) {
|
|
2460
|
+
return s.length > n ? `${s.slice(0, n)}\u2026` : s;
|
|
2461
|
+
}
|
|
2431
2462
|
function VisionAnalyzeBlock({ tc }) {
|
|
2432
2463
|
let image = "";
|
|
2433
2464
|
try {
|
|
@@ -4143,21 +4174,15 @@ function ArtifactToolBlock({
|
|
|
4143
4174
|
name && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground truncate", children: name })
|
|
4144
4175
|
] });
|
|
4145
4176
|
}
|
|
4146
|
-
|
|
4147
|
-
// src/components/chat/tools/delegate-tool.tsx
|
|
4148
4177
|
init_utils();
|
|
4149
4178
|
function firstLine(s) {
|
|
4150
4179
|
const idx = s.indexOf("\n");
|
|
4151
4180
|
return idx === -1 ? s : s.slice(0, idx);
|
|
4152
4181
|
}
|
|
4153
4182
|
function DelegateToolBlock({ tc }) {
|
|
4154
|
-
const [expanded, setExpanded] = react.useState(false);
|
|
4155
4183
|
const args = parseArgs(tc.args);
|
|
4156
|
-
const goal = args?.goal ?? "";
|
|
4157
|
-
const context = args?.context ?? "";
|
|
4184
|
+
const goal = firstLine(args?.goal ?? "").trim();
|
|
4158
4185
|
const agentType = args?.agent_type;
|
|
4159
|
-
const model = args?.model;
|
|
4160
|
-
const summary = firstLine(goal).trim();
|
|
4161
4186
|
let resultError = null;
|
|
4162
4187
|
if (tc.result) {
|
|
4163
4188
|
try {
|
|
@@ -4166,84 +4191,29 @@ function DelegateToolBlock({ tc }) {
|
|
|
4166
4191
|
} catch {
|
|
4167
4192
|
}
|
|
4168
4193
|
}
|
|
4169
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4170
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4171
|
-
|
|
4194
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm py-0.5", children: [
|
|
4195
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranchIcon, { className: "size-3.5 text-muted-foreground/60 shrink-0" }),
|
|
4196
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground", children: "Delegate" }),
|
|
4197
|
+
agentType && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground/70 text-xs", children: [
|
|
4198
|
+
"\xB7 ",
|
|
4199
|
+
agentType
|
|
4200
|
+
] }),
|
|
4201
|
+
goal && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground/70 truncate text-xs italic", children: [
|
|
4202
|
+
"\xB7 \u201C",
|
|
4203
|
+
goal,
|
|
4204
|
+
"\u201D"
|
|
4205
|
+
] }),
|
|
4206
|
+
resultError && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4207
|
+
"span",
|
|
4172
4208
|
{
|
|
4173
|
-
type: "button",
|
|
4174
|
-
onClick: () => setExpanded(!expanded),
|
|
4175
4209
|
className: cn(
|
|
4176
|
-
"
|
|
4177
|
-
"text-
|
|
4210
|
+
"shrink-0 text-xs",
|
|
4211
|
+
"text-destructive"
|
|
4178
4212
|
),
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
lucideReact.ChevronRightIcon,
|
|
4182
|
-
{
|
|
4183
|
-
className: cn(
|
|
4184
|
-
"size-3 shrink-0 transition-transform duration-150",
|
|
4185
|
-
expanded && "rotate-90"
|
|
4186
|
-
)
|
|
4187
|
-
}
|
|
4188
|
-
),
|
|
4189
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranchIcon, { className: "size-3.5 shrink-0 text-muted-foreground" }),
|
|
4190
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-foreground/80", children: "delegate_task" }),
|
|
4191
|
-
agentType && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
|
|
4192
|
-
"\xB7 ",
|
|
4193
|
-
agentType
|
|
4194
|
-
] }),
|
|
4195
|
-
summary && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground truncate min-w-0", children: [
|
|
4196
|
-
"\xB7 ",
|
|
4197
|
-
summary
|
|
4198
|
-
] })
|
|
4199
|
-
]
|
|
4213
|
+
title: resultError,
|
|
4214
|
+
children: "\xB7 failed"
|
|
4200
4215
|
}
|
|
4201
|
-
)
|
|
4202
|
-
expanded && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-6 mt-0.5 space-y-1.5 text-sm font-mono", children: [
|
|
4203
|
-
(agentType || model) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-x-3 gap-y-0.5 text-xs text-muted-foreground", children: [
|
|
4204
|
-
agentType && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4205
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70", children: "agent:" }),
|
|
4206
|
-
" ",
|
|
4207
|
-
agentType
|
|
4208
|
-
] }),
|
|
4209
|
-
model && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4210
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70", children: "model:" }),
|
|
4211
|
-
" ",
|
|
4212
|
-
model
|
|
4213
|
-
] })
|
|
4214
|
-
] }),
|
|
4215
|
-
goal && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded bg-muted/40 px-2 py-1", children: [
|
|
4216
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground/70", children: "Goal" }),
|
|
4217
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "mt-0.5 whitespace-pre-wrap break-words text-foreground/90", children: goal })
|
|
4218
|
-
] }),
|
|
4219
|
-
context && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded bg-muted/40 px-2 py-1", children: [
|
|
4220
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground/70", children: "Context" }),
|
|
4221
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "mt-0.5 whitespace-pre-wrap break-words text-muted-foreground", children: truncate(context, 2e3) })
|
|
4222
|
-
] }),
|
|
4223
|
-
tc.status === "running" && !tc.result && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground italic", children: "Sub-agent running\u2026" }),
|
|
4224
|
-
tc.result && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4225
|
-
"div",
|
|
4226
|
-
{
|
|
4227
|
-
className: cn(
|
|
4228
|
-
"rounded px-2 py-1 max-h-64 overflow-y-auto",
|
|
4229
|
-
resultError ? "bg-destructive/10" : "bg-muted/40"
|
|
4230
|
-
),
|
|
4231
|
-
children: [
|
|
4232
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4233
|
-
"div",
|
|
4234
|
-
{
|
|
4235
|
-
className: cn(
|
|
4236
|
-
"text-[10px] uppercase tracking-wide",
|
|
4237
|
-
resultError ? "text-destructive/80" : "text-emerald-600 dark:text-emerald-400"
|
|
4238
|
-
),
|
|
4239
|
-
children: resultError ? "Error" : "Sub-agent response"
|
|
4240
|
-
}
|
|
4241
|
-
),
|
|
4242
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "mt-0.5 whitespace-pre-wrap break-words text-foreground/90", children: truncate(resultError ?? tc.result, 4e3) })
|
|
4243
|
-
]
|
|
4244
|
-
}
|
|
4245
|
-
)
|
|
4246
|
-
] })
|
|
4216
|
+
)
|
|
4247
4217
|
] });
|
|
4248
4218
|
}
|
|
4249
4219
|
init_utils();
|
|
@@ -4473,6 +4443,19 @@ function DefaultToolBlock({ tc }) {
|
|
|
4473
4443
|
] })
|
|
4474
4444
|
] });
|
|
4475
4445
|
}
|
|
4446
|
+
function ResearchOutlineBlock({ tc }) {
|
|
4447
|
+
const args = parseArgs(tc.args) ?? {};
|
|
4448
|
+
const result = tc.result ? parseArgs(tc.result) ?? {} : {};
|
|
4449
|
+
const outline = args.action === "set" ? args.outline ?? "" : result.outline ?? "";
|
|
4450
|
+
const sections = result.sections ?? [];
|
|
4451
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-border bg-muted/40 p-2 text-xs", children: [
|
|
4452
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1 font-semibold uppercase tracking-widest text-muted-foreground", children: [
|
|
4453
|
+
"Research outline",
|
|
4454
|
+
sections.length ? ` \xB7 ${sections.length} sections` : ""
|
|
4455
|
+
] }),
|
|
4456
|
+
outline ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap font-mono text-[11px] leading-snug", children: outline }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "updated" })
|
|
4457
|
+
] });
|
|
4458
|
+
}
|
|
4476
4459
|
function ToolCallBlock({
|
|
4477
4460
|
tc,
|
|
4478
4461
|
resolvedArtifactName,
|
|
@@ -4525,6 +4508,10 @@ function ToolCallBlock({
|
|
|
4525
4508
|
return /* @__PURE__ */ jsxRuntime.jsx(DelegateToolBlock, { tc });
|
|
4526
4509
|
case "memory":
|
|
4527
4510
|
return /* @__PURE__ */ jsxRuntime.jsx(MemoryToolBlock, { tc });
|
|
4511
|
+
case "research_outline":
|
|
4512
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ResearchOutlineBlock, { tc });
|
|
4513
|
+
case "research_memory":
|
|
4514
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ResearchMemoryBlock, { tc });
|
|
4528
4515
|
case "spawn_worker":
|
|
4529
4516
|
case "send_worker_message":
|
|
4530
4517
|
case "stop_worker":
|
|
@@ -4578,12 +4565,14 @@ function WebSearchGroupBlock({ tcs }) {
|
|
|
4578
4565
|
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-1 ml-5 space-y-0.5", children: tcs.map((tc) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(WebSearchRow, { tc }) }, tc.id)) })
|
|
4579
4566
|
] });
|
|
4580
4567
|
}
|
|
4568
|
+
init_utils();
|
|
4569
|
+
var COLLAPSED_MAX_HEIGHT_PX = 160;
|
|
4581
4570
|
var ChatMessage = react.memo(function ChatMessage2({
|
|
4582
4571
|
message,
|
|
4583
4572
|
onFileSelect
|
|
4584
4573
|
}) {
|
|
4585
4574
|
return /* @__PURE__ */ jsxRuntime.jsx(Message, { from: "user", children: /* @__PURE__ */ jsxRuntime.jsxs(MessageContent, { children: [
|
|
4586
|
-
message.content,
|
|
4575
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleMessageBody, { content: message.content }),
|
|
4587
4576
|
message.images && message.images.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2 mt-2", children: message.images.map((img, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
4588
4577
|
"img",
|
|
4589
4578
|
{
|
|
@@ -4603,6 +4592,48 @@ var ChatMessage = react.memo(function ChatMessage2({
|
|
|
4603
4592
|
)) })
|
|
4604
4593
|
] }) });
|
|
4605
4594
|
});
|
|
4595
|
+
function CollapsibleMessageBody({ content }) {
|
|
4596
|
+
const ref = react.useRef(null);
|
|
4597
|
+
const [overflowing, setOverflowing] = react.useState(false);
|
|
4598
|
+
const [expanded, setExpanded] = react.useState(false);
|
|
4599
|
+
react.useLayoutEffect(() => {
|
|
4600
|
+
const el = ref.current;
|
|
4601
|
+
if (!el) return;
|
|
4602
|
+
const measure = () => {
|
|
4603
|
+
setOverflowing(el.scrollHeight > el.clientHeight + 1);
|
|
4604
|
+
};
|
|
4605
|
+
measure();
|
|
4606
|
+
const observer = new ResizeObserver(measure);
|
|
4607
|
+
observer.observe(el);
|
|
4608
|
+
return () => observer.disconnect();
|
|
4609
|
+
}, [content]);
|
|
4610
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
4611
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4612
|
+
"div",
|
|
4613
|
+
{
|
|
4614
|
+
ref,
|
|
4615
|
+
className: cn(
|
|
4616
|
+
"whitespace-pre-wrap wrap-break-word",
|
|
4617
|
+
!expanded && "overflow-hidden"
|
|
4618
|
+
),
|
|
4619
|
+
style: !expanded ? { maxHeight: COLLAPSED_MAX_HEIGHT_PX } : void 0,
|
|
4620
|
+
children: content
|
|
4621
|
+
}
|
|
4622
|
+
),
|
|
4623
|
+
(overflowing || expanded) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4624
|
+
"button",
|
|
4625
|
+
{
|
|
4626
|
+
type: "button",
|
|
4627
|
+
onClick: () => setExpanded((prev) => !prev),
|
|
4628
|
+
className: cn(
|
|
4629
|
+
"mt-2 text-xs font-bold text-primary",
|
|
4630
|
+
"hover:underline focus:outline-none focus-visible:underline"
|
|
4631
|
+
),
|
|
4632
|
+
children: expanded ? "Show less..." : "Show more..."
|
|
4633
|
+
}
|
|
4634
|
+
)
|
|
4635
|
+
] });
|
|
4636
|
+
}
|
|
4606
4637
|
function iconForMime(mime) {
|
|
4607
4638
|
if (!mime) return lucideReact.File;
|
|
4608
4639
|
if (mime.startsWith("image/")) return lucideReact.FileImage;
|
|
@@ -6073,6 +6104,7 @@ function ChatComposerInner({
|
|
|
6073
6104
|
onToggleWorkspace,
|
|
6074
6105
|
canShowBrowser = false,
|
|
6075
6106
|
canShowWorkspace = false,
|
|
6107
|
+
deepResearchEnabled = false,
|
|
6076
6108
|
viewMode = "simple",
|
|
6077
6109
|
onViewModeChange
|
|
6078
6110
|
}) {
|
|
@@ -6091,10 +6123,10 @@ function ChatComposerInner({
|
|
|
6091
6123
|
}
|
|
6092
6124
|
}, [buttonMenuOpen, menuDismissed, textInput.value]);
|
|
6093
6125
|
react.useEffect(() => {
|
|
6094
|
-
if (textInput.value.startsWith("/")) {
|
|
6126
|
+
if (!buttonMenuOpen && textInput.value.startsWith("/")) {
|
|
6095
6127
|
setMenuMode("all");
|
|
6096
6128
|
}
|
|
6097
|
-
}, [textInput.value]);
|
|
6129
|
+
}, [buttonMenuOpen, textInput.value]);
|
|
6098
6130
|
react.useEffect(() => {
|
|
6099
6131
|
if (showSlashMenu && (menuMode === "skills" || menuMode === "all")) {
|
|
6100
6132
|
adapter.listSlashCommands?.().then(setAdapterCommands).catch(() => {
|
|
@@ -6102,24 +6134,34 @@ function ChatComposerInner({
|
|
|
6102
6134
|
}
|
|
6103
6135
|
}, [adapter, showSlashMenu, menuMode]);
|
|
6104
6136
|
const builtinCommands = react.useMemo(
|
|
6105
|
-
() =>
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6137
|
+
() => {
|
|
6138
|
+
const base = [
|
|
6139
|
+
{ value: "/clear", label: "/clear", description: "Clear conversation" },
|
|
6140
|
+
{ value: "/compress", label: "/compress", description: "Compress context" },
|
|
6141
|
+
{ value: "/goal", label: "/goal", description: "Define an outcome goal" },
|
|
6142
|
+
{ value: "/goal status", label: "/goal status", description: "Show outcome goal status" },
|
|
6143
|
+
{ value: "/goal pause", label: "/goal pause", description: "Pause automatic goal continuation" },
|
|
6144
|
+
{ value: "/goal resume", label: "/goal resume", description: "Resume a paused goal" },
|
|
6145
|
+
{ value: "/goal clear", label: "/goal clear", description: "Clear the current goal" },
|
|
6146
|
+
{ value: "/mission ", label: "/mission", description: "Start an orchestrated rubric-judged mission" },
|
|
6147
|
+
{ value: "/mission status", label: "/mission status", description: "Show current mission status" },
|
|
6148
|
+
{ value: "/mission pause", label: "/mission pause", description: "Pause the mission evaluator" },
|
|
6149
|
+
{ value: "/mission resume", label: "/mission resume", description: "Resume a paused mission" },
|
|
6150
|
+
{ value: "/mission cancel", label: "/mission cancel", description: "Cancel the mission" },
|
|
6151
|
+
{ value: "/loop", label: "/loop", description: "Schedule recurring prompt" },
|
|
6152
|
+
{ value: "/loop list", label: "/loop list", description: "List active loops" },
|
|
6153
|
+
{ value: "/loop cancel", label: "/loop cancel", description: "Cancel a loop by ID" }
|
|
6154
|
+
];
|
|
6155
|
+
if (deepResearchEnabled) {
|
|
6156
|
+
base.push({
|
|
6157
|
+
value: "/deep-research ",
|
|
6158
|
+
label: "/deep-research",
|
|
6159
|
+
description: "Delegate a topic to the deep-research workflow"
|
|
6160
|
+
});
|
|
6161
|
+
}
|
|
6162
|
+
return base;
|
|
6163
|
+
},
|
|
6164
|
+
[deepResearchEnabled]
|
|
6123
6165
|
);
|
|
6124
6166
|
const scheduledExamples = react.useMemo(
|
|
6125
6167
|
() => [
|
|
@@ -6256,7 +6298,7 @@ function ChatComposerInner({
|
|
|
6256
6298
|
},
|
|
6257
6299
|
children: [
|
|
6258
6300
|
/* @__PURE__ */ jsxRuntime.jsx(AttachmentPreviewStrip, {}),
|
|
6259
|
-
viewMode === "expert" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2 px-1 pb-2", children: [
|
|
6301
|
+
viewMode === "expert" && !disabled && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2 px-1 pb-2", children: [
|
|
6260
6302
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6261
6303
|
Button,
|
|
6262
6304
|
{
|
|
@@ -6331,7 +6373,7 @@ function ChatComposerInner({
|
|
|
6331
6373
|
) }),
|
|
6332
6374
|
/* @__PURE__ */ jsxRuntime.jsxs(PromptInputFooter, { children: [
|
|
6333
6375
|
/* @__PURE__ */ jsxRuntime.jsxs(PromptInputTools, { children: [
|
|
6334
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: addMenuOpen, onOpenChange: setAddMenuOpen, children: [
|
|
6376
|
+
!disabled && /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: addMenuOpen, onOpenChange: setAddMenuOpen, children: [
|
|
6335
6377
|
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(PromptInputButton, { "aria-label": "Add", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusIcon, { className: "size-4" }) }) }),
|
|
6336
6378
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6337
6379
|
PopoverContent,
|
|
@@ -6403,7 +6445,7 @@ function ChatComposerInner({
|
|
|
6403
6445
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderIcon, { className: "size-4" })
|
|
6404
6446
|
}
|
|
6405
6447
|
),
|
|
6406
|
-
tokenUsage && tokenUsage.contextWindow > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6448
|
+
!disabled && tokenUsage && tokenUsage.contextWindow > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6407
6449
|
Context,
|
|
6408
6450
|
{
|
|
6409
6451
|
usedTokens: tokenUsage.totalTokens,
|
|
@@ -6491,7 +6533,7 @@ function ChatComposerInner({
|
|
|
6491
6533
|
]
|
|
6492
6534
|
}
|
|
6493
6535
|
),
|
|
6494
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6536
|
+
!disabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6495
6537
|
PromptInputSubmit,
|
|
6496
6538
|
{
|
|
6497
6539
|
status,
|
|
@@ -6629,6 +6671,83 @@ function ChatComposerInner({
|
|
|
6629
6671
|
);
|
|
6630
6672
|
}
|
|
6631
6673
|
|
|
6674
|
+
// src/components/research/research-sources-panel.tsx
|
|
6675
|
+
init_utils();
|
|
6676
|
+
function ResearchSourcesPanel({
|
|
6677
|
+
sources
|
|
6678
|
+
}) {
|
|
6679
|
+
const [expanded, setExpanded] = react.useState(false);
|
|
6680
|
+
const rootRef = react.useRef(null);
|
|
6681
|
+
react.useEffect(() => {
|
|
6682
|
+
const root = rootRef.current;
|
|
6683
|
+
if (!root) return;
|
|
6684
|
+
const handler = (event) => {
|
|
6685
|
+
const target = event.target;
|
|
6686
|
+
if (target?.closest('[id^="source-"]')) {
|
|
6687
|
+
setExpanded(true);
|
|
6688
|
+
}
|
|
6689
|
+
};
|
|
6690
|
+
document.addEventListener("scroll-to-source", handler, true);
|
|
6691
|
+
return () => document.removeEventListener("scroll-to-source", handler, true);
|
|
6692
|
+
}, []);
|
|
6693
|
+
if (sources.length === 0) return null;
|
|
6694
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6695
|
+
"div",
|
|
6696
|
+
{
|
|
6697
|
+
ref: rootRef,
|
|
6698
|
+
className: "rounded-md border border-line bg-card",
|
|
6699
|
+
children: [
|
|
6700
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
6701
|
+
"button",
|
|
6702
|
+
{
|
|
6703
|
+
type: "button",
|
|
6704
|
+
onClick: () => setExpanded((prev) => !prev),
|
|
6705
|
+
"aria-expanded": expanded,
|
|
6706
|
+
className: "flex w-full items-center gap-1.5 px-2 py-1.5 text-left hover:bg-muted/40",
|
|
6707
|
+
children: [
|
|
6708
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6709
|
+
lucideReact.ChevronRightIcon,
|
|
6710
|
+
{
|
|
6711
|
+
className: cn(
|
|
6712
|
+
"size-3 shrink-0 text-muted-foreground transition-transform duration-150",
|
|
6713
|
+
expanded && "rotate-90"
|
|
6714
|
+
)
|
|
6715
|
+
}
|
|
6716
|
+
),
|
|
6717
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-muted-foreground", children: [
|
|
6718
|
+
"Sources \xB7 ",
|
|
6719
|
+
sources.length
|
|
6720
|
+
] })
|
|
6721
|
+
]
|
|
6722
|
+
}
|
|
6723
|
+
),
|
|
6724
|
+
expanded && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "max-h-35 overflow-y-auto border-t border-line py-1", children: sources.map((s) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6725
|
+
"a",
|
|
6726
|
+
{
|
|
6727
|
+
id: `source-${s.sourceId}`,
|
|
6728
|
+
href: s.url,
|
|
6729
|
+
target: "_blank",
|
|
6730
|
+
rel: "noreferrer",
|
|
6731
|
+
className: "group flex items-baseline gap-2 px-2 py-1 hover:bg-muted/60",
|
|
6732
|
+
children: [
|
|
6733
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-[10px] font-semibold text-primary tabular-nums", children: s.sourceId }),
|
|
6734
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-foreground group-hover:underline", children: s.title || s.url }),
|
|
6735
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto shrink-0 truncate text-[10px] text-muted-foreground max-w-[40%]", children: hostname2(s.url) })
|
|
6736
|
+
]
|
|
6737
|
+
}
|
|
6738
|
+
) }, s.sourceId)) })
|
|
6739
|
+
]
|
|
6740
|
+
}
|
|
6741
|
+
);
|
|
6742
|
+
}
|
|
6743
|
+
function hostname2(url) {
|
|
6744
|
+
try {
|
|
6745
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
6746
|
+
} catch {
|
|
6747
|
+
return url;
|
|
6748
|
+
}
|
|
6749
|
+
}
|
|
6750
|
+
|
|
6632
6751
|
// src/components/chat/turn-feedback.tsx
|
|
6633
6752
|
init_utils();
|
|
6634
6753
|
var MAX_REASON_LENGTH2 = 500;
|
|
@@ -7006,8 +7125,23 @@ var ArtifactContent = ({
|
|
|
7006
7125
|
className,
|
|
7007
7126
|
...props
|
|
7008
7127
|
}) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex-1 overflow-auto p-4", className), ...props });
|
|
7009
|
-
|
|
7010
|
-
|
|
7128
|
+
|
|
7129
|
+
// src/components/chat/artifacts/artifact-markdown.tsx
|
|
7130
|
+
init_utils();
|
|
7131
|
+
function ArtifactMarkdown({
|
|
7132
|
+
spec,
|
|
7133
|
+
fill = false
|
|
7134
|
+
}) {
|
|
7135
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7136
|
+
"div",
|
|
7137
|
+
{
|
|
7138
|
+
className: cn(
|
|
7139
|
+
"px-4 py-3",
|
|
7140
|
+
!fill && "max-h-112 overflow-y-auto"
|
|
7141
|
+
),
|
|
7142
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MessageResponse, { children: spec.content ?? "" })
|
|
7143
|
+
}
|
|
7144
|
+
);
|
|
7011
7145
|
}
|
|
7012
7146
|
function formatCell(value) {
|
|
7013
7147
|
if (value == null) return "";
|
|
@@ -7380,7 +7514,7 @@ function ArtifactBody({
|
|
|
7380
7514
|
}
|
|
7381
7515
|
switch (payload.kind) {
|
|
7382
7516
|
case "markdown":
|
|
7383
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactMarkdown, { spec: payload.spec });
|
|
7517
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactMarkdown, { spec: payload.spec, fill });
|
|
7384
7518
|
case "table":
|
|
7385
7519
|
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactTable, { spec: payload.spec });
|
|
7386
7520
|
case "chart":
|
|
@@ -8281,17 +8415,15 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
|
|
|
8281
8415
|
}];
|
|
8282
8416
|
}
|
|
8283
8417
|
if (msg.systemKind === "artifact") {
|
|
8284
|
-
const { artifactId, name, kind, version } = unpackArtifactMeta(
|
|
8285
|
-
msg.systemMeta,
|
|
8286
|
-
msg.content
|
|
8287
|
-
);
|
|
8418
|
+
const { artifactId, name, kind, version, originatingSessionId } = unpackArtifactMeta(msg.systemMeta, msg.content);
|
|
8288
8419
|
return [{
|
|
8289
8420
|
kind: "artifact",
|
|
8290
8421
|
key: msg.id,
|
|
8291
8422
|
artifactId,
|
|
8292
8423
|
name,
|
|
8293
8424
|
artifactKind: kind,
|
|
8294
|
-
version
|
|
8425
|
+
version,
|
|
8426
|
+
originatingSessionId
|
|
8295
8427
|
}];
|
|
8296
8428
|
}
|
|
8297
8429
|
if (msg.systemKind === "browser_marker" || msg.systemKind === "browser_marker_warning") {
|
|
@@ -8463,7 +8595,8 @@ function unpackArtifactMeta(systemMeta, fallbackName) {
|
|
|
8463
8595
|
artifactId: meta.artifact_id ?? "",
|
|
8464
8596
|
name: meta.name ?? fallbackName,
|
|
8465
8597
|
kind: meta.kind ?? "markdown",
|
|
8466
|
-
version: meta.version ?? 1
|
|
8598
|
+
version: meta.version ?? 1,
|
|
8599
|
+
originatingSessionId: meta.originating_session_id ?? null
|
|
8467
8600
|
};
|
|
8468
8601
|
}
|
|
8469
8602
|
function OrphanSystemMarker({
|
|
@@ -8489,7 +8622,7 @@ function OrphanSystemMarker({
|
|
|
8489
8622
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8490
8623
|
ArtifactBlock,
|
|
8491
8624
|
{
|
|
8492
|
-
sessionId,
|
|
8625
|
+
sessionId: unpacked.originatingSessionId ?? sessionId,
|
|
8493
8626
|
artifactId: unpacked.artifactId,
|
|
8494
8627
|
name: unpacked.name,
|
|
8495
8628
|
kind: unpacked.kind,
|
|
@@ -8522,25 +8655,32 @@ function OrphanSystemMarker({
|
|
|
8522
8655
|
function cancelledToolLabel(toolName) {
|
|
8523
8656
|
const map = {
|
|
8524
8657
|
terminal: "Command",
|
|
8525
|
-
execute_code: "Execute
|
|
8658
|
+
execute_code: "Execute code",
|
|
8526
8659
|
read_file: "Read",
|
|
8527
8660
|
write_file: "Write",
|
|
8528
8661
|
patch: "Patch",
|
|
8529
|
-
search_files: "Search
|
|
8530
|
-
list_files: "List
|
|
8531
|
-
web_search: "Web
|
|
8532
|
-
web_extract: "Web
|
|
8533
|
-
web_crawl: "Web
|
|
8534
|
-
session_search: "Session
|
|
8662
|
+
search_files: "Search files",
|
|
8663
|
+
list_files: "List files",
|
|
8664
|
+
web_search: "Web search",
|
|
8665
|
+
web_extract: "Web fetch",
|
|
8666
|
+
web_crawl: "Web crawl",
|
|
8667
|
+
session_search: "Session search",
|
|
8535
8668
|
memory: "Memory",
|
|
8536
8669
|
todo: "Todo",
|
|
8537
8670
|
skills_list: "Skills",
|
|
8538
8671
|
skill_view: "Skill",
|
|
8539
8672
|
consult_expert: "Expert",
|
|
8540
|
-
delegate_task: "Delegate",
|
|
8673
|
+
delegate_task: "Delegate task",
|
|
8541
8674
|
ask_user_question: "Ask User Question",
|
|
8542
8675
|
process: "Process",
|
|
8543
|
-
create_artifact: "
|
|
8676
|
+
create_artifact: "Create artifact",
|
|
8677
|
+
// ``Research memory`` reads as a noun ("memory of research") and
|
|
8678
|
+
// makes the shimmer awkward ("Running Research memory…"). The
|
|
8679
|
+
// one-liner renderer shows just ``Research`` as the label, so
|
|
8680
|
+
// mirror that here so the live shimmer matches the row that
|
|
8681
|
+
// replaces it on completion.
|
|
8682
|
+
research_memory: "Research",
|
|
8683
|
+
research_outline: "Research"
|
|
8544
8684
|
};
|
|
8545
8685
|
return map[toolName] ?? toolName;
|
|
8546
8686
|
}
|
|
@@ -8669,7 +8809,7 @@ function TimelineEntryItem({
|
|
|
8669
8809
|
/* @__PURE__ */ jsxRuntime.jsx(TimelineContent, { children: sessionId ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8670
8810
|
ArtifactBlock,
|
|
8671
8811
|
{
|
|
8672
|
-
sessionId,
|
|
8812
|
+
sessionId: entry.originatingSessionId ?? sessionId,
|
|
8673
8813
|
artifactId: entry.artifactId,
|
|
8674
8814
|
name: entry.name,
|
|
8675
8815
|
kind: entry.artifactKind,
|
|
@@ -8801,17 +8941,24 @@ function extractToolDetail(tc) {
|
|
|
8801
8941
|
}
|
|
8802
8942
|
case "terminal": {
|
|
8803
8943
|
const cmd = stringArg("command");
|
|
8804
|
-
return cmd ?
|
|
8944
|
+
return cmd ? truncate3(cmd, 40) : null;
|
|
8805
8945
|
}
|
|
8806
8946
|
case "execute_code": {
|
|
8807
8947
|
const code3 = stringArg("code");
|
|
8808
|
-
return code3 ?
|
|
8948
|
+
return code3 ? truncate3(code3.split("\n")[0] ?? "", 40) : null;
|
|
8809
8949
|
}
|
|
8810
8950
|
case "web_search":
|
|
8811
8951
|
case "web_crawl":
|
|
8812
8952
|
return stringArg("query");
|
|
8813
|
-
case "web_extract":
|
|
8814
|
-
|
|
8953
|
+
case "web_extract": {
|
|
8954
|
+
const url = stringArg("url");
|
|
8955
|
+
if (!url) return null;
|
|
8956
|
+
try {
|
|
8957
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
8958
|
+
} catch {
|
|
8959
|
+
return truncate3(url, 40);
|
|
8960
|
+
}
|
|
8961
|
+
}
|
|
8815
8962
|
case "skill_view":
|
|
8816
8963
|
case "skill_manage":
|
|
8817
8964
|
return stringArg("name") ?? stringArg("skill");
|
|
@@ -8821,6 +8968,40 @@ function extractToolDetail(tc) {
|
|
|
8821
8968
|
return stringArg("name") ?? stringArg("task") ?? stringArg("title");
|
|
8822
8969
|
case "memory":
|
|
8823
8970
|
return stringArg("action") ?? stringArg("key");
|
|
8971
|
+
case "research_memory": {
|
|
8972
|
+
const action = stringArg("action");
|
|
8973
|
+
if (action === "add") {
|
|
8974
|
+
const title = stringArg("title");
|
|
8975
|
+
if (title) return truncate3(title, 60);
|
|
8976
|
+
const url = stringArg("url");
|
|
8977
|
+
if (url) {
|
|
8978
|
+
try {
|
|
8979
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
8980
|
+
} catch {
|
|
8981
|
+
return truncate3(url, 40);
|
|
8982
|
+
}
|
|
8983
|
+
}
|
|
8984
|
+
return null;
|
|
8985
|
+
}
|
|
8986
|
+
if (action === "retrieve") {
|
|
8987
|
+
return stringArg("query");
|
|
8988
|
+
}
|
|
8989
|
+
return action;
|
|
8990
|
+
}
|
|
8991
|
+
case "research_outline": {
|
|
8992
|
+
const action = stringArg("action");
|
|
8993
|
+
if (action === "set") {
|
|
8994
|
+
const outline = stringArg("outline");
|
|
8995
|
+
if (outline) {
|
|
8996
|
+
const sections = outline.split(/\r?\n/).filter((line) => /^#{2,6}\s+\S/.test(line)).length;
|
|
8997
|
+
if (sections > 0) {
|
|
8998
|
+
return `${sections} ${sections === 1 ? "section" : "sections"}`;
|
|
8999
|
+
}
|
|
9000
|
+
}
|
|
9001
|
+
return "outline";
|
|
9002
|
+
}
|
|
9003
|
+
return action;
|
|
9004
|
+
}
|
|
8824
9005
|
default:
|
|
8825
9006
|
return null;
|
|
8826
9007
|
}
|
|
@@ -8830,7 +9011,7 @@ function lastPathSegment(path) {
|
|
|
8830
9011
|
const idx = cleaned.lastIndexOf("/");
|
|
8831
9012
|
return idx >= 0 ? cleaned.slice(idx + 1) : cleaned;
|
|
8832
9013
|
}
|
|
8833
|
-
function
|
|
9014
|
+
function truncate3(s, max) {
|
|
8834
9015
|
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
8835
9016
|
}
|
|
8836
9017
|
var _SIMPLE_MODE_HIDDEN_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -8906,7 +9087,9 @@ var _TOOL_ROW_ICON = {
|
|
|
8906
9087
|
delegate_task: lucideReact.ArrowRight,
|
|
8907
9088
|
create_artifact: lucideReact.FileTextIcon,
|
|
8908
9089
|
memory: lucideReact.PenLineIcon,
|
|
8909
|
-
todo: lucideReact.ListIcon
|
|
9090
|
+
todo: lucideReact.ListIcon,
|
|
9091
|
+
research_memory: lucideReact.BookOpenIcon,
|
|
9092
|
+
research_outline: lucideReact.ListIcon
|
|
8910
9093
|
};
|
|
8911
9094
|
function _toolRowIcon(toolName) {
|
|
8912
9095
|
return _TOOL_ROW_ICON[toolName] ?? lucideReact.WrenchIcon;
|
|
@@ -8952,6 +9135,31 @@ function _toolRowLabel(tc) {
|
|
|
8952
9135
|
return detail ? `Memory ${detail}` : "Updated memory";
|
|
8953
9136
|
case "todo":
|
|
8954
9137
|
return detail ? `Todo ${detail}` : "Updated todo list";
|
|
9138
|
+
case "research_memory": {
|
|
9139
|
+
const args = parseArgs(tc.args);
|
|
9140
|
+
const action = args?.action;
|
|
9141
|
+
if (action === "add") {
|
|
9142
|
+
return detail ? `Stored source "${detail}"` : "Stored a source";
|
|
9143
|
+
}
|
|
9144
|
+
if (action === "retrieve") {
|
|
9145
|
+
return detail ? `Retrieved sources for "${detail}"` : "Retrieved sources";
|
|
9146
|
+
}
|
|
9147
|
+
if (action === "list") {
|
|
9148
|
+
return "Listed sources";
|
|
9149
|
+
}
|
|
9150
|
+
return "Updated research memory";
|
|
9151
|
+
}
|
|
9152
|
+
case "research_outline": {
|
|
9153
|
+
const args = parseArgs(tc.args);
|
|
9154
|
+
const action = args?.action;
|
|
9155
|
+
if (action === "set") {
|
|
9156
|
+
return detail ? `Updated outline (${detail})` : "Updated outline";
|
|
9157
|
+
}
|
|
9158
|
+
if (action === "get") {
|
|
9159
|
+
return "Read outline";
|
|
9160
|
+
}
|
|
9161
|
+
return "Touched outline";
|
|
9162
|
+
}
|
|
8955
9163
|
default:
|
|
8956
9164
|
return cancelledToolLabel(tc.toolName);
|
|
8957
9165
|
}
|
|
@@ -9125,7 +9333,8 @@ function SimpleAssistantGroup({
|
|
|
9125
9333
|
sessionId,
|
|
9126
9334
|
artifactFallbacks,
|
|
9127
9335
|
onFileSelect,
|
|
9128
|
-
onRetry
|
|
9336
|
+
onRetry,
|
|
9337
|
+
hideTurnSummary = false
|
|
9129
9338
|
}) {
|
|
9130
9339
|
const assistantMessages = messages.filter((m) => m.role === "assistant");
|
|
9131
9340
|
const tail = assistantMessages[assistantMessages.length - 1];
|
|
@@ -9193,7 +9402,7 @@ function SimpleAssistantGroup({
|
|
|
9193
9402
|
tail
|
|
9194
9403
|
}
|
|
9195
9404
|
),
|
|
9196
|
-
effectiveTurnSummary && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9405
|
+
effectiveTurnSummary && !hideTurnSummary && /* @__PURE__ */ jsxRuntime.jsx(
|
|
9197
9406
|
TurnSummaryCard,
|
|
9198
9407
|
{
|
|
9199
9408
|
summary: effectiveTurnSummary,
|
|
@@ -9214,7 +9423,8 @@ function AssistantGroup({
|
|
|
9214
9423
|
artifactFallbacks,
|
|
9215
9424
|
onFileSelect,
|
|
9216
9425
|
onRetry,
|
|
9217
|
-
viewMode = "simple"
|
|
9426
|
+
viewMode = "simple",
|
|
9427
|
+
hideTurnSummary = false
|
|
9218
9428
|
}) {
|
|
9219
9429
|
if (viewMode === "simple") {
|
|
9220
9430
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -9225,7 +9435,8 @@ function AssistantGroup({
|
|
|
9225
9435
|
sessionId,
|
|
9226
9436
|
artifactFallbacks,
|
|
9227
9437
|
onFileSelect,
|
|
9228
|
-
onRetry
|
|
9438
|
+
onRetry,
|
|
9439
|
+
hideTurnSummary
|
|
9229
9440
|
}
|
|
9230
9441
|
);
|
|
9231
9442
|
}
|
|
@@ -9331,7 +9542,10 @@ function ChatThread({
|
|
|
9331
9542
|
canShowBrowser = false,
|
|
9332
9543
|
canShowWorkspace = false,
|
|
9333
9544
|
viewMode = "simple",
|
|
9334
|
-
onViewModeChange
|
|
9545
|
+
onViewModeChange,
|
|
9546
|
+
deepResearchEnabled = false,
|
|
9547
|
+
researchSources = [],
|
|
9548
|
+
hideTurnSummary = false
|
|
9335
9549
|
}) {
|
|
9336
9550
|
const groups = react.useMemo(() => groupMessages(messages), [messages]);
|
|
9337
9551
|
const awaitingInput = react.useMemo(() => isAwaitingUserInput(messages), [messages]);
|
|
@@ -9429,7 +9643,8 @@ function ChatThread({
|
|
|
9429
9643
|
artifactFallbacks,
|
|
9430
9644
|
onFileSelect,
|
|
9431
9645
|
onRetry: groupRetry,
|
|
9432
|
-
viewMode
|
|
9646
|
+
viewMode,
|
|
9647
|
+
hideTurnSummary
|
|
9433
9648
|
},
|
|
9434
9649
|
group.messages[0].id
|
|
9435
9650
|
);
|
|
@@ -9440,14 +9655,8 @@ function ChatThread({
|
|
|
9440
9655
|
] }),
|
|
9441
9656
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto w-full max-w-4xl px-3 sm:px-6 pb-3 sm:pb-5 pt-3", children: [
|
|
9442
9657
|
retryIndicator && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsx(RetryBanner, { indicator: retryIndicator }) }),
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
{
|
|
9446
|
-
className: "rounded border border-line bg-muted/40 px-3 py-2 text-sm text-foreground/60",
|
|
9447
|
-
role: "status",
|
|
9448
|
-
children: composerDisabledReason
|
|
9449
|
-
}
|
|
9450
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
9658
|
+
researchSources.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsx(ResearchSourcesPanel, { sources: researchSources }) }),
|
|
9659
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9451
9660
|
ChatComposer,
|
|
9452
9661
|
{
|
|
9453
9662
|
onSend,
|
|
@@ -9464,7 +9673,8 @@ function ChatThread({
|
|
|
9464
9673
|
canShowBrowser,
|
|
9465
9674
|
canShowWorkspace,
|
|
9466
9675
|
viewMode,
|
|
9467
|
-
onViewModeChange
|
|
9676
|
+
onViewModeChange,
|
|
9677
|
+
deepResearchEnabled
|
|
9468
9678
|
}
|
|
9469
9679
|
)
|
|
9470
9680
|
] })
|
|
@@ -10147,6 +10357,29 @@ function isScheduledRunSession(session) {
|
|
|
10147
10357
|
session?.channel === "scheduled" || session?.config?.scheduled_session_id
|
|
10148
10358
|
);
|
|
10149
10359
|
}
|
|
10360
|
+
var _SUB_AGENT_CHANNELS = /* @__PURE__ */ new Set([
|
|
10361
|
+
"delegation",
|
|
10362
|
+
"worker",
|
|
10363
|
+
"task"
|
|
10364
|
+
]);
|
|
10365
|
+
function isSubAgentSession(session) {
|
|
10366
|
+
if (!session) return false;
|
|
10367
|
+
if (session.parentId) return true;
|
|
10368
|
+
if (session.channel && _SUB_AGENT_CHANNELS.has(session.channel)) return true;
|
|
10369
|
+
return false;
|
|
10370
|
+
}
|
|
10371
|
+
function readOnlyReasonForSession(session) {
|
|
10372
|
+
if (isScheduledRunSession(session)) {
|
|
10373
|
+
return { readOnly: true, reason: "Scheduled run is read-only" };
|
|
10374
|
+
}
|
|
10375
|
+
if (isSubAgentSession(session)) {
|
|
10376
|
+
return {
|
|
10377
|
+
readOnly: true,
|
|
10378
|
+
reason: "Sub-task started by parent session \u2014 read-only"
|
|
10379
|
+
};
|
|
10380
|
+
}
|
|
10381
|
+
return { readOnly: false };
|
|
10382
|
+
}
|
|
10150
10383
|
|
|
10151
10384
|
// src/runtime/events.ts
|
|
10152
10385
|
var WORKSPACE_MUTATING_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -10216,7 +10449,8 @@ function createInitialAgentChatState(options = {}) {
|
|
|
10216
10449
|
terminal: false,
|
|
10217
10450
|
workspaceRefreshKey: 0,
|
|
10218
10451
|
browser: null,
|
|
10219
|
-
viewMode: options.viewMode ?? "simple"
|
|
10452
|
+
viewMode: options.viewMode ?? "simple",
|
|
10453
|
+
researchSources: []
|
|
10220
10454
|
};
|
|
10221
10455
|
}
|
|
10222
10456
|
function applyAgentChatEvent(state, event) {
|
|
@@ -10268,7 +10502,13 @@ function applyAgentChatEvent(state, event) {
|
|
|
10268
10502
|
name: event.data.name,
|
|
10269
10503
|
kind: event.data.kind,
|
|
10270
10504
|
version: event.data.version,
|
|
10271
|
-
size: event.data.size
|
|
10505
|
+
size: event.data.size,
|
|
10506
|
+
// Propagated artifacts (a delegated child's report
|
|
10507
|
+
// surfacing on the parent's chat thread) carry this
|
|
10508
|
+
// field; without it the ArtifactBlock fetches via the
|
|
10509
|
+
// chat's own session id and 404s because the spec lives
|
|
10510
|
+
// under the writer's S3 prefix, not the parent's.
|
|
10511
|
+
originating_session_id: event.data.originating_session_id
|
|
10272
10512
|
}
|
|
10273
10513
|
}
|
|
10274
10514
|
]);
|
|
@@ -10302,11 +10542,12 @@ function applyAgentChatEvent(state, event) {
|
|
|
10302
10542
|
const toolName = findToolNameById(nextState.messages, toolCallId);
|
|
10303
10543
|
const messages = applyToolResult(nextState.messages, event.data);
|
|
10304
10544
|
const mutatesWorkspace = toolName !== null && WORKSPACE_MUTATING_TOOLS.has(toolName);
|
|
10305
|
-
|
|
10545
|
+
const withResult = {
|
|
10306
10546
|
...nextState,
|
|
10307
10547
|
messages,
|
|
10308
10548
|
workspaceRefreshKey: mutatesWorkspace ? nextState.workspaceRefreshKey + 1 : nextState.workspaceRefreshKey
|
|
10309
10549
|
};
|
|
10550
|
+
return collectResearchSource(withResult, toolName, event.data);
|
|
10310
10551
|
}
|
|
10311
10552
|
case "harness.wake":
|
|
10312
10553
|
case "llm.request":
|
|
@@ -10654,7 +10895,7 @@ function applyLlmThinking(state, event) {
|
|
|
10654
10895
|
} else {
|
|
10655
10896
|
messages[idx] = {
|
|
10656
10897
|
...prev,
|
|
10657
|
-
reasoning: (prev.reasoning
|
|
10898
|
+
reasoning: appendText(prev.reasoning, reasoningText),
|
|
10658
10899
|
turnId: turnId ?? prev.turnId,
|
|
10659
10900
|
iterationIndex: iterationIndex ?? prev.iterationIndex
|
|
10660
10901
|
};
|
|
@@ -11038,6 +11279,32 @@ function findToolNameById(messages, toolCallId) {
|
|
|
11038
11279
|
}
|
|
11039
11280
|
return null;
|
|
11040
11281
|
}
|
|
11282
|
+
function collectResearchSource(state, toolName, data) {
|
|
11283
|
+
if (toolName !== "research_memory") return state;
|
|
11284
|
+
const rawResult = data.content ?? data.result;
|
|
11285
|
+
const resultText = typeof rawResult === "string" ? rawResult : JSON.stringify(rawResult ?? {});
|
|
11286
|
+
let parsed;
|
|
11287
|
+
try {
|
|
11288
|
+
parsed = JSON.parse(resultText);
|
|
11289
|
+
} catch {
|
|
11290
|
+
return state;
|
|
11291
|
+
}
|
|
11292
|
+
if (!parsed.success || !parsed.source_id || !parsed.url) return state;
|
|
11293
|
+
if (state.researchSources.some((s) => s.sourceId === parsed.source_id)) {
|
|
11294
|
+
return state;
|
|
11295
|
+
}
|
|
11296
|
+
return {
|
|
11297
|
+
...state,
|
|
11298
|
+
researchSources: [
|
|
11299
|
+
...state.researchSources,
|
|
11300
|
+
{
|
|
11301
|
+
sourceId: parsed.source_id,
|
|
11302
|
+
url: parsed.url,
|
|
11303
|
+
title: parsed.title ?? ""
|
|
11304
|
+
}
|
|
11305
|
+
]
|
|
11306
|
+
};
|
|
11307
|
+
}
|
|
11041
11308
|
function findLatestConsultExpertCall(messages) {
|
|
11042
11309
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
11043
11310
|
const msg = messages[i];
|
|
@@ -11487,7 +11754,8 @@ function useAgentChatRuntime({
|
|
|
11487
11754
|
markSending,
|
|
11488
11755
|
markSendError,
|
|
11489
11756
|
viewMode: state.viewMode,
|
|
11490
|
-
setViewMode
|
|
11757
|
+
setViewMode,
|
|
11758
|
+
researchSources: state.researchSources
|
|
11491
11759
|
};
|
|
11492
11760
|
}
|
|
11493
11761
|
function parseEventData(data) {
|
|
@@ -11546,7 +11814,8 @@ function AgentChat({
|
|
|
11546
11814
|
onFileSelect,
|
|
11547
11815
|
onMessagesChange,
|
|
11548
11816
|
disabled,
|
|
11549
|
-
onComposerError
|
|
11817
|
+
onComposerError,
|
|
11818
|
+
deepResearchEnabled = false
|
|
11550
11819
|
}) {
|
|
11551
11820
|
const [workspacePath, setWorkspacePath] = react.useState(null);
|
|
11552
11821
|
const [mobileView, setMobileView] = react.useState("chat");
|
|
@@ -11561,9 +11830,18 @@ function AgentChat({
|
|
|
11561
11830
|
react.useEffect(() => {
|
|
11562
11831
|
setShowWorkspace(runtime.viewMode === "expert");
|
|
11563
11832
|
}, [runtime.viewMode]);
|
|
11564
|
-
const
|
|
11565
|
-
const effectiveDisabled = disabled ||
|
|
11566
|
-
const disabledReason =
|
|
11833
|
+
const readOnly = readOnlyReasonForSession(runtime.session);
|
|
11834
|
+
const effectiveDisabled = disabled || readOnly.readOnly;
|
|
11835
|
+
const disabledReason = readOnly.reason;
|
|
11836
|
+
const orchestratesDeepResearch = react.useMemo(
|
|
11837
|
+
() => runtime.messages.some(
|
|
11838
|
+
(m) => m.toolCalls?.some(
|
|
11839
|
+
(tc) => tc.toolName === "delegate_task" && delegateTaskTargets(tc.args).includes("deep-research")
|
|
11840
|
+
)
|
|
11841
|
+
),
|
|
11842
|
+
[runtime.messages]
|
|
11843
|
+
);
|
|
11844
|
+
const hideTurnSummary = isSubAgentSession(runtime.session) || orchestratesDeepResearch;
|
|
11567
11845
|
const browserState = runtime.state.browser;
|
|
11568
11846
|
const browserAvailable = browserState !== null && browserState.status !== "closed" && !!sessionId;
|
|
11569
11847
|
const browserVisible = browserAvailable && showBrowser;
|
|
@@ -11684,7 +11962,10 @@ function AgentChat({
|
|
|
11684
11962
|
canShowBrowser: browserAvailable,
|
|
11685
11963
|
canShowWorkspace: workspaceAvailable,
|
|
11686
11964
|
viewMode: runtime.viewMode,
|
|
11687
|
-
onViewModeChange: runtime.setViewMode
|
|
11965
|
+
onViewModeChange: runtime.setViewMode,
|
|
11966
|
+
deepResearchEnabled,
|
|
11967
|
+
researchSources: runtime.researchSources,
|
|
11968
|
+
hideTurnSummary
|
|
11688
11969
|
}
|
|
11689
11970
|
)
|
|
11690
11971
|
}
|
|
@@ -11754,6 +12035,27 @@ function AgentChat({
|
|
|
11754
12035
|
}
|
|
11755
12036
|
);
|
|
11756
12037
|
}
|
|
12038
|
+
function delegateTaskTargets(rawArgs) {
|
|
12039
|
+
if (!rawArgs) return [];
|
|
12040
|
+
let parsed;
|
|
12041
|
+
try {
|
|
12042
|
+
parsed = JSON.parse(rawArgs);
|
|
12043
|
+
} catch {
|
|
12044
|
+
return [];
|
|
12045
|
+
}
|
|
12046
|
+
if (!parsed || typeof parsed !== "object") return [];
|
|
12047
|
+
const out = [];
|
|
12048
|
+
const a = parsed;
|
|
12049
|
+
if (typeof a.agent_type === "string") out.push(a.agent_type);
|
|
12050
|
+
if (Array.isArray(a.goals)) {
|
|
12051
|
+
for (const g of a.goals) {
|
|
12052
|
+
if (g && typeof g === "object" && typeof g.agent_type === "string") {
|
|
12053
|
+
out.push(g.agent_type);
|
|
12054
|
+
}
|
|
12055
|
+
}
|
|
12056
|
+
}
|
|
12057
|
+
return out;
|
|
12058
|
+
}
|
|
11757
12059
|
init_utils();
|
|
11758
12060
|
var DEFAULT_LIMIT = 50;
|
|
11759
12061
|
function requireInboxAdapter(adapter) {
|
|
@@ -12493,7 +12795,7 @@ function groupMissionTasksByBucket(tasks) {
|
|
|
12493
12795
|
function deriveMissionWorkerActivityLabel(worker) {
|
|
12494
12796
|
const kind = worker.latestEventKind;
|
|
12495
12797
|
if (kind === "tool.call" && worker.latestEventSummary) {
|
|
12496
|
-
return `tool: ${
|
|
12798
|
+
return `tool: ${truncate4(worker.latestEventSummary, 80)}`;
|
|
12497
12799
|
}
|
|
12498
12800
|
if (kind === "llm.response") {
|
|
12499
12801
|
return "thinking";
|
|
@@ -12502,11 +12804,11 @@ function deriveMissionWorkerActivityLabel(worker) {
|
|
|
12502
12804
|
return "received tool result";
|
|
12503
12805
|
}
|
|
12504
12806
|
if (kind && worker.latestEventSummary) {
|
|
12505
|
-
return `${kind}: ${
|
|
12807
|
+
return `${kind}: ${truncate4(worker.latestEventSummary, 60)}`;
|
|
12506
12808
|
}
|
|
12507
12809
|
return worker.sessionStatus || "active";
|
|
12508
12810
|
}
|
|
12509
|
-
function
|
|
12811
|
+
function truncate4(s, max) {
|
|
12510
12812
|
if (s.length <= max) return s;
|
|
12511
12813
|
return `${s.slice(0, max - 1)}\u2026`;
|
|
12512
12814
|
}
|
|
@@ -13494,6 +13796,50 @@ function MissionsPanel({
|
|
|
13494
13796
|
)) })
|
|
13495
13797
|
] });
|
|
13496
13798
|
}
|
|
13799
|
+
var CITATION_RE = /\[(S\d+(?:\s*,\s*S\d+)*)\]/g;
|
|
13800
|
+
function splitCitations(text) {
|
|
13801
|
+
if (!text) return [];
|
|
13802
|
+
const segments = [];
|
|
13803
|
+
let lastIndex = 0;
|
|
13804
|
+
for (const match of text.matchAll(CITATION_RE)) {
|
|
13805
|
+
const start = match.index ?? 0;
|
|
13806
|
+
if (start > lastIndex) {
|
|
13807
|
+
segments.push({ kind: "text", value: text.slice(lastIndex, start) });
|
|
13808
|
+
}
|
|
13809
|
+
for (const id of match[1].split(",")) {
|
|
13810
|
+
segments.push({ kind: "cite", value: id.trim() });
|
|
13811
|
+
}
|
|
13812
|
+
lastIndex = start + match[0].length;
|
|
13813
|
+
}
|
|
13814
|
+
if (lastIndex < text.length) {
|
|
13815
|
+
segments.push({ kind: "text", value: text.slice(lastIndex) });
|
|
13816
|
+
}
|
|
13817
|
+
return segments;
|
|
13818
|
+
}
|
|
13819
|
+
function CitationText({
|
|
13820
|
+
text,
|
|
13821
|
+
sources,
|
|
13822
|
+
onCitationClick
|
|
13823
|
+
}) {
|
|
13824
|
+
const byId = new Map(sources.map((s) => [s.sourceId, s]));
|
|
13825
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: splitCitations(text).map((seg, i) => {
|
|
13826
|
+
if (seg.kind === "text") {
|
|
13827
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: seg.value }, i);
|
|
13828
|
+
}
|
|
13829
|
+
const src = byId.get(seg.value);
|
|
13830
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13831
|
+
"button",
|
|
13832
|
+
{
|
|
13833
|
+
type: "button",
|
|
13834
|
+
title: src ? `${src.title} \u2014 ${src.url}` : seg.value,
|
|
13835
|
+
onClick: () => onCitationClick?.(seg.value),
|
|
13836
|
+
className: "mx-0.5 inline-flex items-center rounded-sm bg-muted px-1 text-[10px] font-semibold text-primary hover:bg-primary/10",
|
|
13837
|
+
children: seg.value
|
|
13838
|
+
},
|
|
13839
|
+
i
|
|
13840
|
+
);
|
|
13841
|
+
}) });
|
|
13842
|
+
}
|
|
13497
13843
|
init_utils();
|
|
13498
13844
|
var DEFAULT_LIMIT2 = 50;
|
|
13499
13845
|
var DEFAULT_POLL_INTERVAL_MS3 = 3e4;
|
|
@@ -13862,7 +14208,7 @@ function mergeTreeNodes(groups) {
|
|
|
13862
14208
|
}
|
|
13863
14209
|
return Array.from(byId.values());
|
|
13864
14210
|
}
|
|
13865
|
-
function
|
|
14211
|
+
function collectDeletedSessionIds(nodes, deletedSessionId) {
|
|
13866
14212
|
const deletedIds = /* @__PURE__ */ new Set([deletedSessionId]);
|
|
13867
14213
|
let changed = true;
|
|
13868
14214
|
while (changed) {
|
|
@@ -13874,7 +14220,7 @@ function pruneDeletedSessionNodes(nodes, deletedSessionId) {
|
|
|
13874
14220
|
}
|
|
13875
14221
|
}
|
|
13876
14222
|
}
|
|
13877
|
-
return
|
|
14223
|
+
return deletedIds;
|
|
13878
14224
|
}
|
|
13879
14225
|
function formatSessionTime(value) {
|
|
13880
14226
|
const normalized = /[zZ]|[+-]\d{2}:?\d{2}$/.test(value) ? value : `${value}Z`;
|
|
@@ -13905,7 +14251,6 @@ function TreeNodeRow({
|
|
|
13905
14251
|
activeSessionId,
|
|
13906
14252
|
canStop,
|
|
13907
14253
|
canDelete,
|
|
13908
|
-
deletingSessionId,
|
|
13909
14254
|
onSelect,
|
|
13910
14255
|
onStop,
|
|
13911
14256
|
onDelete
|
|
@@ -13973,18 +14318,14 @@ function TreeNodeRow({
|
|
|
13973
14318
|
"button",
|
|
13974
14319
|
{
|
|
13975
14320
|
type: "button",
|
|
13976
|
-
className:
|
|
13977
|
-
"p-2 md:p-1 rounded hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none transition-all",
|
|
13978
|
-
deletingSessionId === entry.id ? "opacity-100" : "opacity-60 md:opacity-50 md:group-hover:opacity-100 md:focus-visible:opacity-100"
|
|
13979
|
-
),
|
|
14321
|
+
className: "p-2 md:p-1 rounded opacity-60 md:opacity-50 md:group-hover:opacity-100 md:focus-visible:opacity-100 hover:bg-destructive/10 hover:text-destructive transition-all",
|
|
13980
14322
|
onClick: (e) => {
|
|
13981
14323
|
e.stopPropagation();
|
|
13982
14324
|
onDelete(entry.id);
|
|
13983
14325
|
},
|
|
13984
14326
|
"aria-label": "Delete session",
|
|
13985
14327
|
title: "Delete session",
|
|
13986
|
-
|
|
13987
|
-
children: deletingSessionId === entry.id ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { className: "w-3 h-3 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2Icon, { className: "w-3 h-3" })
|
|
14328
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2Icon, { className: "w-3 h-3" })
|
|
13988
14329
|
}
|
|
13989
14330
|
)
|
|
13990
14331
|
]
|
|
@@ -13998,7 +14339,6 @@ function TreeNodeRow({
|
|
|
13998
14339
|
activeSessionId,
|
|
13999
14340
|
canStop,
|
|
14000
14341
|
canDelete,
|
|
14001
|
-
deletingSessionId,
|
|
14002
14342
|
onSelect,
|
|
14003
14343
|
onStop,
|
|
14004
14344
|
onDelete
|
|
@@ -14023,10 +14363,8 @@ function SessionTreePanel({
|
|
|
14023
14363
|
const [nodes, setNodes] = react.useState([]);
|
|
14024
14364
|
const [error, setError] = react.useState(null);
|
|
14025
14365
|
const [hasEverLoaded, setHasEverLoaded] = react.useState(false);
|
|
14026
|
-
const [deletingSessionId, setDeletingSessionId] = react.useState(
|
|
14027
|
-
null
|
|
14028
|
-
);
|
|
14029
14366
|
const mounted = react.useRef(true);
|
|
14367
|
+
const pendingDeleteIds = react.useRef(/* @__PURE__ */ new Set());
|
|
14030
14368
|
const requestId = react.useRef(0);
|
|
14031
14369
|
const lastFingerprint = react.useRef("");
|
|
14032
14370
|
const resetContext = react.useRef(null);
|
|
@@ -14051,10 +14389,23 @@ function SessionTreePanel({
|
|
|
14051
14389
|
sessionTreePromise
|
|
14052
14390
|
]);
|
|
14053
14391
|
if (!mounted.current || currentRequestId !== requestId.current) return;
|
|
14054
|
-
|
|
14392
|
+
let nextNodes = mergeTreeNodes([
|
|
14055
14393
|
sessionList?.sessions.map(sessionToTreeNode) ?? [],
|
|
14056
14394
|
sessionTree?.nodes ?? []
|
|
14057
14395
|
]);
|
|
14396
|
+
if (pendingDeleteIds.current.size > 0) {
|
|
14397
|
+
const stillReturned = /* @__PURE__ */ new Set();
|
|
14398
|
+
nextNodes = nextNodes.filter((node) => {
|
|
14399
|
+
if (!pendingDeleteIds.current.has(node.id)) return true;
|
|
14400
|
+
stillReturned.add(node.id);
|
|
14401
|
+
return false;
|
|
14402
|
+
});
|
|
14403
|
+
for (const pendingId of pendingDeleteIds.current) {
|
|
14404
|
+
if (!stillReturned.has(pendingId)) {
|
|
14405
|
+
pendingDeleteIds.current.delete(pendingId);
|
|
14406
|
+
}
|
|
14407
|
+
}
|
|
14408
|
+
}
|
|
14058
14409
|
const fp = treeFingerprint(nextNodes);
|
|
14059
14410
|
if (fp !== lastFingerprint.current) {
|
|
14060
14411
|
lastFingerprint.current = fp;
|
|
@@ -14085,6 +14436,7 @@ function SessionTreePanel({
|
|
|
14085
14436
|
setNodes([]);
|
|
14086
14437
|
setHasEverLoaded(false);
|
|
14087
14438
|
lastFingerprint.current = "";
|
|
14439
|
+
pendingDeleteIds.current.clear();
|
|
14088
14440
|
}
|
|
14089
14441
|
setError(null);
|
|
14090
14442
|
void refetch();
|
|
@@ -14121,24 +14473,31 @@ function SessionTreePanel({
|
|
|
14121
14473
|
);
|
|
14122
14474
|
const handleDelete = react.useCallback(
|
|
14123
14475
|
async (id) => {
|
|
14124
|
-
if (!adapter.deleteSession
|
|
14125
|
-
|
|
14476
|
+
if (!adapter.deleteSession) return;
|
|
14477
|
+
const deletedIds = collectDeletedSessionIds(nodes, id);
|
|
14478
|
+
for (const deletedId of deletedIds) {
|
|
14479
|
+
pendingDeleteIds.current.add(deletedId);
|
|
14480
|
+
}
|
|
14481
|
+
setNodes((current) => {
|
|
14482
|
+
const next = current.filter((node) => !deletedIds.has(node.id));
|
|
14483
|
+
lastFingerprint.current = treeFingerprint(next);
|
|
14484
|
+
return next;
|
|
14485
|
+
});
|
|
14486
|
+
onSessionDelete?.(id);
|
|
14126
14487
|
try {
|
|
14127
14488
|
await adapter.deleteSession({ sessionId: id });
|
|
14128
|
-
setNodes((current) => {
|
|
14129
|
-
const next = pruneDeletedSessionNodes(current, id);
|
|
14130
|
-
lastFingerprint.current = treeFingerprint(next);
|
|
14131
|
-
return next;
|
|
14132
|
-
});
|
|
14133
|
-
onSessionDelete?.(id);
|
|
14134
14489
|
await refetch({ silent: true });
|
|
14135
14490
|
} catch (e) {
|
|
14136
|
-
|
|
14137
|
-
|
|
14138
|
-
|
|
14491
|
+
for (const deletedId of deletedIds) {
|
|
14492
|
+
pendingDeleteIds.current.delete(deletedId);
|
|
14493
|
+
}
|
|
14494
|
+
if (mounted.current) {
|
|
14495
|
+
setError(e instanceof Error ? e.message : "Failed to delete session");
|
|
14496
|
+
}
|
|
14497
|
+
await refetch({ silent: true });
|
|
14139
14498
|
}
|
|
14140
14499
|
},
|
|
14141
|
-
[adapter,
|
|
14500
|
+
[adapter, nodes, onSessionDelete, refetch]
|
|
14142
14501
|
);
|
|
14143
14502
|
if (!hasEverLoaded) return null;
|
|
14144
14503
|
if (nodes.length === 0) return null;
|
|
@@ -14159,7 +14518,6 @@ function SessionTreePanel({
|
|
|
14159
14518
|
activeSessionId: activeSessionId ?? "",
|
|
14160
14519
|
canStop: Boolean(adapter.stopSession),
|
|
14161
14520
|
canDelete: Boolean(adapter.deleteSession),
|
|
14162
|
-
deletingSessionId,
|
|
14163
14521
|
onSelect: handleSelect,
|
|
14164
14522
|
onStop: handleStop,
|
|
14165
14523
|
onDelete: handleDelete
|
|
@@ -14172,16 +14530,19 @@ function SessionTreePanel({
|
|
|
14172
14530
|
exports.ACTIVE_MISSION_STATUSES = ACTIVE_MISSION_STATUSES;
|
|
14173
14531
|
exports.AgentChat = AgentChat;
|
|
14174
14532
|
exports.AgentChatAdapterProvider = AgentChatAdapterProvider;
|
|
14533
|
+
exports.CitationText = CitationText;
|
|
14175
14534
|
exports.InboxPanel = InboxPanel;
|
|
14176
14535
|
exports.MessageResponse = MessageResponse;
|
|
14177
14536
|
exports.MissionDashboard = MissionDashboard;
|
|
14178
14537
|
exports.MissionsPanel = MissionsPanel;
|
|
14538
|
+
exports.ResearchSourcesPanel = ResearchSourcesPanel;
|
|
14179
14539
|
exports.ScheduledWorkPanel = ScheduledWorkPanel;
|
|
14180
14540
|
exports.SessionTreePanel = SessionTreePanel;
|
|
14181
14541
|
exports.deriveMissionWorkerActivityLabel = deriveMissionWorkerActivityLabel;
|
|
14182
14542
|
exports.groupMissionTasksByBucket = groupMissionTasksByBucket;
|
|
14183
14543
|
exports.isTerminalMissionStatus = isTerminalMissionStatus;
|
|
14184
14544
|
exports.missionTaskBucket = missionTaskBucket;
|
|
14545
|
+
exports.splitCitations = splitCitations;
|
|
14185
14546
|
exports.useAgentChatAdapterContext = useAgentChatAdapterContext;
|
|
14186
14547
|
exports.useAgentChatRuntime = useAgentChatRuntime;
|
|
14187
14548
|
exports.useChatViewMode = useChatViewMode;
|