@invergent/agent-chat-react 2.15.9 → 2.16.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 +184 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +184 -66
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5516,7 +5516,11 @@ function cancelledToolLabel(toolName) {
|
|
|
5516
5516
|
// Arbor research-mission tools (the /auto-research coordinator loop).
|
|
5517
5517
|
idea_tree: "Idea tree",
|
|
5518
5518
|
dispatch_experiments: "Dispatch experiments",
|
|
5519
|
-
merge_experiment: "Merge experiment"
|
|
5519
|
+
merge_experiment: "Merge experiment",
|
|
5520
|
+
kb_search_pages: "Knowledge base search",
|
|
5521
|
+
kb_list_pages: "Knowledge base index",
|
|
5522
|
+
kb_read_page: "Knowledge base page",
|
|
5523
|
+
vision_analyze: "Image analysis"
|
|
5520
5524
|
};
|
|
5521
5525
|
if (map[toolName]) return map[toolName];
|
|
5522
5526
|
if (toolName.startsWith("mcp__")) return formatMcpToolLabel(toolName);
|
|
@@ -5579,16 +5583,27 @@ function extractToolDetail(tc) {
|
|
|
5579
5583
|
return code3 ? truncate3(code3.split("\n")[0] ?? "", 40) : null;
|
|
5580
5584
|
}
|
|
5581
5585
|
case "web_search":
|
|
5582
|
-
case "
|
|
5586
|
+
case "session_search":
|
|
5583
5587
|
return stringArg("query");
|
|
5588
|
+
// web_crawl takes a start ``url``, not a query.
|
|
5589
|
+
case "web_crawl":
|
|
5584
5590
|
case "web_extract": {
|
|
5585
5591
|
const url = stringArg("url");
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
+
return url ? hostOf2(url) : null;
|
|
5593
|
+
}
|
|
5594
|
+
case "kb_search_pages": {
|
|
5595
|
+
const query = stringArg("query");
|
|
5596
|
+
return query ? truncate3(query, 60) : null;
|
|
5597
|
+
}
|
|
5598
|
+
case "kb_read_page": {
|
|
5599
|
+
const path = stringArg("path");
|
|
5600
|
+
if (!path) return null;
|
|
5601
|
+
const pages = stringArg("pages");
|
|
5602
|
+
return pages ? `${kbPageName(path)} \xB7 pages ${pages}` : kbPageName(path);
|
|
5603
|
+
}
|
|
5604
|
+
case "vision_analyze": {
|
|
5605
|
+
const image = stringArg("image");
|
|
5606
|
+
return image && !image.startsWith("data:") ? lastPathSegment(image) : null;
|
|
5592
5607
|
}
|
|
5593
5608
|
case "skill_view":
|
|
5594
5609
|
case "skill_manage":
|
|
@@ -5621,14 +5636,7 @@ function extractToolDetail(tc) {
|
|
|
5621
5636
|
const title = stringArg("title");
|
|
5622
5637
|
if (title) return truncate3(title, 60);
|
|
5623
5638
|
const url = stringArg("url");
|
|
5624
|
-
|
|
5625
|
-
try {
|
|
5626
|
-
return new URL(url).hostname.replace(/^www\./, "");
|
|
5627
|
-
} catch {
|
|
5628
|
-
return truncate3(url, 40);
|
|
5629
|
-
}
|
|
5630
|
-
}
|
|
5631
|
-
return null;
|
|
5639
|
+
return url ? hostOf2(url) : null;
|
|
5632
5640
|
}
|
|
5633
5641
|
if (action === "retrieve") {
|
|
5634
5642
|
return stringArg("query");
|
|
@@ -5661,6 +5669,34 @@ function lastPathSegment(path) {
|
|
|
5661
5669
|
function truncate3(s, max) {
|
|
5662
5670
|
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
5663
5671
|
}
|
|
5672
|
+
function hostOf2(url) {
|
|
5673
|
+
try {
|
|
5674
|
+
return new URL(url).hostname.replace(/^www\./, "") || truncate3(url, 40);
|
|
5675
|
+
} catch {
|
|
5676
|
+
return truncate3(url, 40);
|
|
5677
|
+
}
|
|
5678
|
+
}
|
|
5679
|
+
function kbPageName(path) {
|
|
5680
|
+
return lastPathSegment(path).replace(/\.(md|json)$/, "");
|
|
5681
|
+
}
|
|
5682
|
+
var _PLURAL_LABEL = {
|
|
5683
|
+
read_file: (n) => `Read ${n} files`,
|
|
5684
|
+
write_file: (n) => `Wrote ${n} files`,
|
|
5685
|
+
patch: (n) => `Edited ${n} files`,
|
|
5686
|
+
search_files: (n) => `Ran ${n} file searches`,
|
|
5687
|
+
terminal: (n) => `Ran ${n} commands`,
|
|
5688
|
+
web_search: (n) => `Ran ${n} web searches`,
|
|
5689
|
+
web_extract: (n) => `Fetched ${n} pages`,
|
|
5690
|
+
session_search: (n) => `Ran ${n} session searches`,
|
|
5691
|
+
kb_search_pages: (n) => `Ran ${n} knowledge base searches`,
|
|
5692
|
+
kb_read_page: (n) => `Read ${n} knowledge base pages`,
|
|
5693
|
+
vision_analyze: (n) => `Looked at ${n} images`,
|
|
5694
|
+
consult_expert: (n) => `Consulted ${n} experts`,
|
|
5695
|
+
delegate_task: (n) => `Delegated ${n} tasks`
|
|
5696
|
+
};
|
|
5697
|
+
function sameToolGroupLabel(toolName, count) {
|
|
5698
|
+
return _PLURAL_LABEL[toolName]?.(count) ?? `${cancelledToolLabel(toolName)} \xD7 ${count}`;
|
|
5699
|
+
}
|
|
5664
5700
|
function toolRowLabel(tc) {
|
|
5665
5701
|
const detail = extractToolDetail(tc);
|
|
5666
5702
|
switch (tc.toolName) {
|
|
@@ -5684,7 +5720,22 @@ function toolRowLabel(tc) {
|
|
|
5684
5720
|
case "web_search":
|
|
5685
5721
|
return detail ? `Searched the web for "${detail}"` : "Searched the web";
|
|
5686
5722
|
case "web_crawl":
|
|
5687
|
-
return detail ? `Crawled
|
|
5723
|
+
return detail ? `Crawled ${detail}` : "Crawled a site";
|
|
5724
|
+
case "kb_search_pages": {
|
|
5725
|
+
if (!detail) return "Searched the knowledge base";
|
|
5726
|
+
return stringField(parseArgs(tc.args), "mode") === "documents" ? `Looked up document "${detail}"` : `Searched the knowledge base for "${detail}"`;
|
|
5727
|
+
}
|
|
5728
|
+
case "kb_list_pages":
|
|
5729
|
+
return "Browsed the knowledge base index";
|
|
5730
|
+
case "kb_read_page": {
|
|
5731
|
+
const args = parseArgs(tc.args);
|
|
5732
|
+
const path = stringField(args, "path");
|
|
5733
|
+
if (!path) return "Read a knowledge base page";
|
|
5734
|
+
const pages = stringField(args, "pages");
|
|
5735
|
+
return pages ? `Read ${kbPageName(path)}, pages ${pages}` : `Read ${kbPageName(path)}`;
|
|
5736
|
+
}
|
|
5737
|
+
case "vision_analyze":
|
|
5738
|
+
return detail ? `Looked at ${detail}` : "Looked at an image";
|
|
5688
5739
|
case "web_extract":
|
|
5689
5740
|
return detail ? `Fetched ${detail}` : "Fetched a page";
|
|
5690
5741
|
case "session_search":
|
|
@@ -10882,6 +10933,17 @@ function useSmoothStream(target, isStreaming) {
|
|
|
10882
10933
|
return displayedLen >= target.length ? target : target.slice(0, displayedLen);
|
|
10883
10934
|
}
|
|
10884
10935
|
|
|
10936
|
+
// src/runtime/reasoning-tokens.ts
|
|
10937
|
+
function formatReasoningTokens(tokens) {
|
|
10938
|
+
if (tokens < 1e3) return String(tokens);
|
|
10939
|
+
return `${(tokens / 1e3).toFixed(1).replace(/\.0$/, "")}k`;
|
|
10940
|
+
}
|
|
10941
|
+
function reasoningTokenLabel(message, live) {
|
|
10942
|
+
const tokens = message.reasoningTokens ?? message.reasoningDeltaCount;
|
|
10943
|
+
if (tokens === void 0) return live ? "Thinking..." : "Thought";
|
|
10944
|
+
return `${live ? "Thinking..." : "Thought \xB7"} ${formatReasoningTokens(tokens)} tokens`;
|
|
10945
|
+
}
|
|
10946
|
+
|
|
10885
10947
|
// src/lib/next-action.ts
|
|
10886
10948
|
var _NEXT_ACTION_RE = /<next_action([^>]*)>([\s\S]*?)<\/next_action>\s*/gi;
|
|
10887
10949
|
var _PARTIAL_NEXT_ACTION_FOOTER_RE = /(?:^|\n)\s*<(?:n(?:e(?:x(?:t(?:_(?:a(?:c(?:t(?:i(?:o(?:n[\s\S]*)?)?)?)?)?)?)?)?)?)?)?$/i;
|
|
@@ -12452,7 +12514,7 @@ function SimpleFinalAnswer({
|
|
|
12452
12514
|
function deriveIterationLabel(message) {
|
|
12453
12515
|
const calls = visibleToolCalls(message);
|
|
12454
12516
|
if (calls.length === 0) {
|
|
12455
|
-
return message.reasoning
|
|
12517
|
+
return message.reasoning || message.reasoningTokens ? reasoningTokenLabel(message, false) : null;
|
|
12456
12518
|
}
|
|
12457
12519
|
if (calls.every((tc) => tc.toolName === "skill_view")) {
|
|
12458
12520
|
return skillViewLabel(calls);
|
|
@@ -12464,8 +12526,7 @@ function deriveIterationLabel(message) {
|
|
|
12464
12526
|
const firstName = calls[0].toolName;
|
|
12465
12527
|
const allSame = calls.every((tc) => tc.toolName === firstName);
|
|
12466
12528
|
if (allSame) {
|
|
12467
|
-
|
|
12468
|
-
return `${human} \xD7 ${calls.length}`;
|
|
12529
|
+
return sameToolGroupLabel(firstName, calls.length);
|
|
12469
12530
|
}
|
|
12470
12531
|
return `Used ${calls.length} tools`;
|
|
12471
12532
|
}
|
|
@@ -12484,11 +12545,28 @@ function isIterationLive(message) {
|
|
|
12484
12545
|
}
|
|
12485
12546
|
return message.status === "streaming";
|
|
12486
12547
|
}
|
|
12548
|
+
function hasInlineRunningIndicator(messages, viewMode) {
|
|
12549
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
12550
|
+
const message = messages[i];
|
|
12551
|
+
if (message.role === "user") return false;
|
|
12552
|
+
if (message.role !== "assistant") continue;
|
|
12553
|
+
if (viewMode === "simple") {
|
|
12554
|
+
if (message.toolCalls?.some((tc) => tc.toolName === "ask_user_question")) {
|
|
12555
|
+
return false;
|
|
12556
|
+
}
|
|
12557
|
+
return isIterationLive(message) && (!!message.toolCalls?.length || !message.content || message.content === message.reasoning);
|
|
12558
|
+
}
|
|
12559
|
+
return messageToEntries(message, i === messages.length - 1, {}).some(
|
|
12560
|
+
(entry) => entry.kind === "reasoning" && entry.isStreaming
|
|
12561
|
+
);
|
|
12562
|
+
}
|
|
12563
|
+
return false;
|
|
12564
|
+
}
|
|
12487
12565
|
function liveIterationLabel(message) {
|
|
12488
12566
|
const running = (message.toolCalls ?? []).filter(
|
|
12489
12567
|
(tc) => tc.status === "running" && !isHiddenSimpleTool(tc)
|
|
12490
12568
|
);
|
|
12491
|
-
if (running.length === 0) return
|
|
12569
|
+
if (running.length === 0) return reasoningTokenLabel(message, true);
|
|
12492
12570
|
if (running.every((tc) => tc.toolName === "skill_view")) {
|
|
12493
12571
|
return `${skillViewLabel(running)}\u2026`;
|
|
12494
12572
|
}
|
|
@@ -12528,7 +12606,11 @@ var _TOOL_ROW_ICON = {
|
|
|
12528
12606
|
research_memory: lucideReact.BookOpenIcon,
|
|
12529
12607
|
research_outline: lucideReact.ListIcon,
|
|
12530
12608
|
run_coding_agent: lucideReact.BotIcon,
|
|
12531
|
-
code_run: lucideReact.BotIcon
|
|
12609
|
+
code_run: lucideReact.BotIcon,
|
|
12610
|
+
kb_search_pages: lucideReact.LibraryIcon,
|
|
12611
|
+
kb_list_pages: lucideReact.LibraryIcon,
|
|
12612
|
+
kb_read_page: lucideReact.LibraryIcon,
|
|
12613
|
+
vision_analyze: lucideReact.EyeIcon
|
|
12532
12614
|
};
|
|
12533
12615
|
function _toolRowIcon(toolName) {
|
|
12534
12616
|
return _TOOL_ROW_ICON[toolName] ?? lucideReact.WrenchIcon;
|
|
@@ -12545,44 +12627,16 @@ function SimpleDetailRow({ icon: Icon, children }) {
|
|
|
12545
12627
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1 leading-relaxed text-foreground/60", children })
|
|
12546
12628
|
] });
|
|
12547
12629
|
}
|
|
12548
|
-
function ClampedReasoning({
|
|
12549
|
-
text,
|
|
12550
|
-
previewParagraphs = 2
|
|
12551
|
-
}) {
|
|
12552
|
-
const paragraphs = splitReasoningParagraphs(text);
|
|
12553
|
-
const [expanded, setExpanded] = react.useState(false);
|
|
12554
|
-
const hasMore = paragraphs.length > previewParagraphs;
|
|
12555
|
-
const visible = expanded || !hasMore ? paragraphs : paragraphs.slice(0, previewParagraphs);
|
|
12556
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
12557
|
-
visible.map((paragraph, i) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap", children: paragraph }, i)),
|
|
12558
|
-
hasMore && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12559
|
-
"button",
|
|
12560
|
-
{
|
|
12561
|
-
type: "button",
|
|
12562
|
-
onClick: () => setExpanded((prev) => !prev),
|
|
12563
|
-
className: "text-xs font-medium text-foreground hover:text-foreground/70 cursor-pointer",
|
|
12564
|
-
children: expanded ? "Show less" : "Show more..."
|
|
12565
|
-
}
|
|
12566
|
-
)
|
|
12567
|
-
] });
|
|
12568
|
-
}
|
|
12569
|
-
function splitReasoningParagraphs(text) {
|
|
12570
|
-
const trimmed = text.trim();
|
|
12571
|
-
if (!trimmed) return [];
|
|
12572
|
-
const blankSplit = trimmed.split(/\n\s*\n+/).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
12573
|
-
if (blankSplit.length > 1) return blankSplit;
|
|
12574
|
-
return trimmed.split(/\n+/).map((p) => p.trim()).filter((p) => p.length > 0);
|
|
12575
|
-
}
|
|
12576
12630
|
function IterationExpanded({
|
|
12577
12631
|
message
|
|
12578
12632
|
}) {
|
|
12579
12633
|
const calls = visibleToolCalls(message);
|
|
12580
|
-
const
|
|
12634
|
+
const hasReasoning = !!message.reasoning || !!message.reasoningTokens;
|
|
12581
12635
|
const anyVisibleRunning = calls.some((tc) => tc.status === "running");
|
|
12582
|
-
const showDone = !anyVisibleRunning && (calls.length > 0 ||
|
|
12583
|
-
if (!
|
|
12636
|
+
const showDone = !anyVisibleRunning && (calls.length > 0 || hasReasoning);
|
|
12637
|
+
if (!hasReasoning && calls.length === 0) return null;
|
|
12584
12638
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-2 space-y-3 border-l border-border/40 pl-4 py-1", children: [
|
|
12585
|
-
|
|
12639
|
+
hasReasoning && /* @__PURE__ */ jsxRuntime.jsx(SimpleDetailRow, { icon: lucideReact.ClockIcon, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: reasoningTokenLabel(message, false) }) }),
|
|
12586
12640
|
calls.map((tc) => {
|
|
12587
12641
|
if (tc.toolName === "todo") {
|
|
12588
12642
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-1", children: /* @__PURE__ */ jsxRuntime.jsx(TodoToolBlock, { tc }) }, tc.id);
|
|
@@ -12597,6 +12651,7 @@ function IterationExpanded({
|
|
|
12597
12651
|
}
|
|
12598
12652
|
function IterationGroup({
|
|
12599
12653
|
message,
|
|
12654
|
+
isActive = true,
|
|
12600
12655
|
sessionId,
|
|
12601
12656
|
artifactFallbacks,
|
|
12602
12657
|
onFileSelect
|
|
@@ -12616,7 +12671,7 @@ function IterationGroup({
|
|
|
12616
12671
|
}
|
|
12617
12672
|
) });
|
|
12618
12673
|
}
|
|
12619
|
-
if (isIterationLive(message)) {
|
|
12674
|
+
if (isActive && isIterationLive(message)) {
|
|
12620
12675
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12621
12676
|
OrbShimmerLabel,
|
|
12622
12677
|
{
|
|
@@ -12630,6 +12685,9 @@ function IterationGroup({
|
|
|
12630
12685
|
if (!label) {
|
|
12631
12686
|
return null;
|
|
12632
12687
|
}
|
|
12688
|
+
if (!summary && visibleToolCalls(message).length === 0) {
|
|
12689
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-0.5 text-sm text-muted-foreground", children: label });
|
|
12690
|
+
}
|
|
12633
12691
|
const labelTone = summary ? "text-muted-foreground italic" : "text-muted-foreground";
|
|
12634
12692
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
12635
12693
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -12723,6 +12781,7 @@ function LoopResultAffordance({ message }) {
|
|
|
12723
12781
|
}
|
|
12724
12782
|
function SimpleAssistantGroup({
|
|
12725
12783
|
messages,
|
|
12784
|
+
activeAssistantId,
|
|
12726
12785
|
isRunning,
|
|
12727
12786
|
sessionId,
|
|
12728
12787
|
artifactFallbacks,
|
|
@@ -12734,7 +12793,7 @@ function SimpleAssistantGroup({
|
|
|
12734
12793
|
const tail = assistantMessages[assistantMessages.length - 1];
|
|
12735
12794
|
const tailHasTools = !!(tail?.toolCalls && tail.toolCalls.length > 0);
|
|
12736
12795
|
const tailIsTextOnly = !!tail && !tailHasTools;
|
|
12737
|
-
const finalText = tailIsTextOnly && tail.content ? tail.content : "";
|
|
12796
|
+
const finalText = tailIsTextOnly && tail.content !== tail.reasoning ? tail.content : "";
|
|
12738
12797
|
const showErrorInfo = !!tail && tail.status === "error" && !!tail.errorInfo;
|
|
12739
12798
|
const turnComplete = !isRunning && tail?.status === "complete";
|
|
12740
12799
|
const summaryPref = finalText !== null ? stripAndParseNextAction(finalText).action?.summary ?? "hide" : "hide";
|
|
@@ -12771,7 +12830,7 @@ function SimpleAssistantGroup({
|
|
|
12771
12830
|
);
|
|
12772
12831
|
}
|
|
12773
12832
|
if (message === tail && tailIsTextOnly && finalText) return null;
|
|
12774
|
-
const rawContent = (message.content ?? "").trim();
|
|
12833
|
+
const rawContent = message.content === message.reasoning ? "" : (message.content ?? "").trim();
|
|
12775
12834
|
const { action, inferredNarration, cleaned } = stripAndParseNextAction(rawContent);
|
|
12776
12835
|
const narrationLine = action ? action.body.trim().toLowerCase() === "done" ? null : action.body : inferredNarration;
|
|
12777
12836
|
const askBody = hasUserFacingAskContent(message) ? cleaned : null;
|
|
@@ -12781,6 +12840,7 @@ function SimpleAssistantGroup({
|
|
|
12781
12840
|
IterationGroup,
|
|
12782
12841
|
{
|
|
12783
12842
|
message,
|
|
12843
|
+
isActive: message.id === activeAssistantId,
|
|
12784
12844
|
sessionId,
|
|
12785
12845
|
artifactFallbacks,
|
|
12786
12846
|
onFileSelect
|
|
@@ -12813,6 +12873,7 @@ function SimpleAssistantGroup({
|
|
|
12813
12873
|
}
|
|
12814
12874
|
function AssistantGroup({
|
|
12815
12875
|
messages,
|
|
12876
|
+
activeAssistantId,
|
|
12816
12877
|
lastGlobalIndex,
|
|
12817
12878
|
totalMessages,
|
|
12818
12879
|
isRunning,
|
|
@@ -12828,6 +12889,7 @@ function AssistantGroup({
|
|
|
12828
12889
|
SimpleAssistantGroup,
|
|
12829
12890
|
{
|
|
12830
12891
|
messages,
|
|
12892
|
+
activeAssistantId,
|
|
12831
12893
|
isRunning,
|
|
12832
12894
|
sessionId,
|
|
12833
12895
|
artifactFallbacks,
|
|
@@ -12959,6 +13021,15 @@ function ChatThread({
|
|
|
12959
13021
|
onOpenIntegrations
|
|
12960
13022
|
}) {
|
|
12961
13023
|
const groups = react.useMemo(() => groupMessages(messages), [messages]);
|
|
13024
|
+
const activeAssistantId = react.useMemo(() => {
|
|
13025
|
+
if (!isRunning) return void 0;
|
|
13026
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
13027
|
+
const message = messages[i];
|
|
13028
|
+
if (message.role === "user") return void 0;
|
|
13029
|
+
if (message.role === "assistant") return message.id;
|
|
13030
|
+
}
|
|
13031
|
+
return void 0;
|
|
13032
|
+
}, [messages, isRunning]);
|
|
12962
13033
|
const pendingAsk = react.useMemo(() => pendingAskCall(messages), [messages]);
|
|
12963
13034
|
const askPolicy = react.useMemo(
|
|
12964
13035
|
() => askComposerPolicy(pendingAsk),
|
|
@@ -12966,13 +13037,26 @@ function ChatThread({
|
|
|
12966
13037
|
);
|
|
12967
13038
|
const awaitingInput = askPolicy !== null;
|
|
12968
13039
|
const orbActivity = react.useMemo(
|
|
12969
|
-
() =>
|
|
12970
|
-
|
|
12971
|
-
|
|
12972
|
-
|
|
13040
|
+
() => {
|
|
13041
|
+
const activity = deriveOrbActivity(
|
|
13042
|
+
messages,
|
|
13043
|
+
viewMode === "simple" ? SIMPLE_MODE_ORB_OPTIONS : void 0
|
|
13044
|
+
);
|
|
13045
|
+
if (viewMode === "simple" && activity.state === "solving") {
|
|
13046
|
+
const latest = [...messages].reverse().find((message) => message.role === "assistant");
|
|
13047
|
+
if (latest && !latest.toolCalls?.some((tc) => tc.status === "running")) {
|
|
13048
|
+
return { ...activity, label: reasoningTokenLabel(latest, true) };
|
|
13049
|
+
}
|
|
13050
|
+
}
|
|
13051
|
+
return activity;
|
|
13052
|
+
},
|
|
12973
13053
|
[messages, viewMode]
|
|
12974
13054
|
);
|
|
12975
|
-
const
|
|
13055
|
+
const inlineRunningIndicator = react.useMemo(
|
|
13056
|
+
() => hasInlineRunningIndicator(messages, viewMode),
|
|
13057
|
+
[messages, viewMode]
|
|
13058
|
+
);
|
|
13059
|
+
const showWorkingOnIt = useDelayedRunningIndicator(isRunning) && !awaitingInput && !inlineRunningIndicator;
|
|
12976
13060
|
const composerLocked = askPolicy?.locked ?? false;
|
|
12977
13061
|
const composerDisabled = disabled || composerLocked;
|
|
12978
13062
|
const composerDisabledReason = composerLocked ? askPolicy?.reason : disabledReason;
|
|
@@ -13158,6 +13242,7 @@ function ChatThread({
|
|
|
13158
13242
|
AssistantGroup,
|
|
13159
13243
|
{
|
|
13160
13244
|
messages: group.messages,
|
|
13245
|
+
activeAssistantId,
|
|
13161
13246
|
lastGlobalIndex: group.lastGlobalIndex,
|
|
13162
13247
|
totalMessages: messages.length,
|
|
13163
13248
|
isRunning,
|
|
@@ -13403,8 +13488,17 @@ function applyAgentChatEvent(state, event) {
|
|
|
13403
13488
|
return collectResearchSource(withResult, toolName, event.data);
|
|
13404
13489
|
}
|
|
13405
13490
|
case "harness.wake":
|
|
13406
|
-
case "llm.request":
|
|
13407
13491
|
return { ...nextState, terminal: false, isRunning: true };
|
|
13492
|
+
case "llm.request":
|
|
13493
|
+
return {
|
|
13494
|
+
...nextState,
|
|
13495
|
+
terminal: false,
|
|
13496
|
+
isRunning: true,
|
|
13497
|
+
hadDeltas: false,
|
|
13498
|
+
messages: nextState.messages.map(
|
|
13499
|
+
(message) => message.role === "assistant" && message.status === "streaming" && !message.toolCalls?.some((tc) => tc.status === "running") ? { ...message, status: "complete" } : message
|
|
13500
|
+
)
|
|
13501
|
+
};
|
|
13408
13502
|
case "harness.crash":
|
|
13409
13503
|
case "stream.timeout":
|
|
13410
13504
|
return nextState;
|
|
@@ -13621,22 +13715,31 @@ function browserMarker(event) {
|
|
|
13621
13715
|
function applyLlmDelta(state, event) {
|
|
13622
13716
|
const deltaContent = stringValue2(event.data.content);
|
|
13623
13717
|
const deltaReasoning = stringValue2(event.data.reasoning);
|
|
13718
|
+
const reasoningTokens = typeof event.data.reasoning_tokens === "number" && Number.isInteger(event.data.reasoning_tokens) && event.data.reasoning_tokens >= 0 ? event.data.reasoning_tokens : void 0;
|
|
13624
13719
|
const { turnId, iterationIndex } = readTurnMeta(event.data);
|
|
13625
13720
|
const messages = [...state.messages];
|
|
13626
13721
|
const lastIdx = findLastAssistantIndex(messages);
|
|
13627
13722
|
const lastMsg = lastIdx >= 0 ? messages[lastIdx] : null;
|
|
13628
13723
|
const hasUserAfter = lastIdx >= 0 && hasUserAfterIndex(messages, lastIdx);
|
|
13724
|
+
const matchesIteration = (turnId === void 0 || lastMsg?.turnId === turnId) && (iterationIndex === void 0 || lastMsg?.iterationIndex === iterationIndex);
|
|
13725
|
+
const sameIteration = turnId !== void 0 && iterationIndex !== void 0 && matchesIteration;
|
|
13726
|
+
if (reasoningTokens !== void 0 && !deltaContent && !deltaReasoning && lastMsg && !hasUserAfter && matchesIteration) {
|
|
13727
|
+
messages[lastIdx] = { ...lastMsg, reasoningTokens };
|
|
13728
|
+
return { ...state, messages };
|
|
13729
|
+
}
|
|
13629
13730
|
const allToolsDone = Boolean(
|
|
13630
13731
|
lastMsg?.toolCalls?.length && lastMsg.toolCalls.every((tc) => tc.status !== "running")
|
|
13631
13732
|
);
|
|
13632
13733
|
const canAppend = Boolean(
|
|
13633
|
-
lastMsg && lastMsg.status === "streaming" && !allToolsDone && !hasUserAfter
|
|
13734
|
+
lastMsg && lastMsg.status === "streaming" && (!allToolsDone || sameIteration) && !hasUserAfter && matchesIteration
|
|
13634
13735
|
);
|
|
13635
13736
|
if (canAppend && lastMsg) {
|
|
13636
13737
|
messages[lastIdx] = {
|
|
13637
13738
|
...lastMsg,
|
|
13638
13739
|
content: deltaContent ? lastMsg.content + deltaContent : lastMsg.content,
|
|
13639
13740
|
reasoning: deltaReasoning ? (lastMsg.reasoning ?? "") + deltaReasoning : lastMsg.reasoning,
|
|
13741
|
+
reasoningTokens: reasoningTokens ?? lastMsg.reasoningTokens,
|
|
13742
|
+
reasoningDeltaCount: deltaReasoning ? (lastMsg.reasoningDeltaCount ?? 0) + 1 : lastMsg.reasoningDeltaCount,
|
|
13640
13743
|
turnId: turnId ?? lastMsg.turnId,
|
|
13641
13744
|
iterationIndex: iterationIndex ?? lastMsg.iterationIndex
|
|
13642
13745
|
};
|
|
@@ -13646,6 +13749,8 @@ function applyLlmDelta(state, event) {
|
|
|
13646
13749
|
role: "assistant",
|
|
13647
13750
|
content: deltaContent,
|
|
13648
13751
|
reasoning: deltaReasoning || void 0,
|
|
13752
|
+
reasoningTokens,
|
|
13753
|
+
reasoningDeltaCount: deltaReasoning ? 1 : void 0,
|
|
13649
13754
|
createdAt: /* @__PURE__ */ new Date(),
|
|
13650
13755
|
status: "streaming",
|
|
13651
13756
|
turnId,
|
|
@@ -13721,6 +13826,11 @@ function applyLlmResponse(state, event) {
|
|
|
13721
13826
|
}
|
|
13722
13827
|
const inputTokens = numberValue(event.data.input_tokens);
|
|
13723
13828
|
const outputTokens = numberValue(event.data.output_tokens);
|
|
13829
|
+
const reasoningTokens = numberValue(event.data.reasoning_tokens);
|
|
13830
|
+
if (reasoningTokens > 0) {
|
|
13831
|
+
const responseIdx = findLastAssistantIndex(messages);
|
|
13832
|
+
messages[responseIdx] = { ...messages[responseIdx], reasoningTokens };
|
|
13833
|
+
}
|
|
13724
13834
|
return {
|
|
13725
13835
|
...state,
|
|
13726
13836
|
messages,
|
|
@@ -13729,7 +13839,7 @@ function applyLlmResponse(state, event) {
|
|
|
13729
13839
|
tokenUsage: {
|
|
13730
13840
|
inputTokens,
|
|
13731
13841
|
outputTokens,
|
|
13732
|
-
reasoningTokens
|
|
13842
|
+
reasoningTokens,
|
|
13733
13843
|
cachedInputTokens: numberValue(event.data.cache_read_tokens),
|
|
13734
13844
|
totalTokens: inputTokens + outputTokens,
|
|
13735
13845
|
contextWindow: numberValue(event.data.context_window),
|
|
@@ -13748,6 +13858,8 @@ ${addition}`;
|
|
|
13748
13858
|
}
|
|
13749
13859
|
function applyLlmThinking(state, event) {
|
|
13750
13860
|
const reasoningText = stringValue2(event.data.reasoning) || stringValue2(event.data.content);
|
|
13861
|
+
const reasoningTokens = optionalNumberValue(event.data.reasoning_tokens);
|
|
13862
|
+
const reasoningDeltaCount = optionalNumberValue(event.data.reasoning_delta_count);
|
|
13751
13863
|
const { turnId, iterationIndex } = readTurnMeta(event.data);
|
|
13752
13864
|
const messages = [...state.messages];
|
|
13753
13865
|
const idx = findLastAssistantIndex(messages);
|
|
@@ -13756,12 +13868,16 @@ function applyLlmThinking(state, event) {
|
|
|
13756
13868
|
prev?.toolCalls?.length && prev.toolCalls.every((tc) => tc.status !== "running")
|
|
13757
13869
|
);
|
|
13758
13870
|
const hasUserAfter = idx >= 0 && hasUserAfterIndex(messages, idx);
|
|
13759
|
-
|
|
13871
|
+
const sameIteration = turnId !== void 0 && iterationIndex !== void 0 && (prev?.turnId === turnId && prev.iterationIndex === iterationIndex || prev?.turnId === void 0 && prev?.iterationIndex === void 0 && prev?.llmResponseEventId === void 0);
|
|
13872
|
+
const differentIteration = !!prev && (turnId !== void 0 && prev.turnId !== void 0 && turnId !== prev.turnId || iterationIndex !== void 0 && prev.iterationIndex !== void 0 && iterationIndex !== prev.iterationIndex);
|
|
13873
|
+
if (!prev || allToolsDone && !sameIteration || hasUserAfter || differentIteration) {
|
|
13760
13874
|
messages.push({
|
|
13761
13875
|
id: `evt-${event.eventId}`,
|
|
13762
13876
|
role: "assistant",
|
|
13763
13877
|
content: "",
|
|
13764
13878
|
reasoning: reasoningText,
|
|
13879
|
+
reasoningTokens: reasoningTokens ?? void 0,
|
|
13880
|
+
reasoningDeltaCount: reasoningDeltaCount ?? void 0,
|
|
13765
13881
|
createdAt: /* @__PURE__ */ new Date(),
|
|
13766
13882
|
status: "streaming",
|
|
13767
13883
|
turnId,
|
|
@@ -13771,6 +13887,8 @@ function applyLlmThinking(state, event) {
|
|
|
13771
13887
|
messages[idx] = {
|
|
13772
13888
|
...prev,
|
|
13773
13889
|
reasoning: appendText(prev.reasoning, reasoningText),
|
|
13890
|
+
reasoningTokens: reasoningTokens ?? prev.reasoningTokens,
|
|
13891
|
+
reasoningDeltaCount: reasoningDeltaCount ?? prev.reasoningDeltaCount,
|
|
13774
13892
|
turnId: turnId ?? prev.turnId,
|
|
13775
13893
|
iterationIndex: iterationIndex ?? prev.iterationIndex
|
|
13776
13894
|
};
|