@invergent/agent-chat-react 2.3.1 → 2.4.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.js CHANGED
@@ -885,9 +885,9 @@ var defaultGetThinkingMessage = (isStreaming, duration) => {
885
885
  return /* @__PURE__ */ jsx(Shimmer, { duration: 1, children: "Thinking..." });
886
886
  }
887
887
  if (duration === void 0) {
888
- return /* @__PURE__ */ jsx("p", { className: "text-foreground", children: "Thought for a few seconds" });
888
+ return /* @__PURE__ */ jsx("p", { className: "text-muted-foreground italic", children: "Thought for a few seconds" });
889
889
  }
890
- return /* @__PURE__ */ jsxs("p", { className: "text-foreground", children: [
890
+ return /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground italic", children: [
891
891
  "Thought for ",
892
892
  duration,
893
893
  " seconds"
@@ -6580,6 +6580,59 @@ function useSmoothStream(target, isStreaming) {
6580
6580
  }, [isActive]);
6581
6581
  return displayedLen >= target.length ? target : target.slice(0, displayedLen);
6582
6582
  }
6583
+
6584
+ // src/lib/next-action.ts
6585
+ var _NEXT_ACTION_RE = /<next_action([^>]*)>([\s\S]*?)<\/next_action>\s*/gi;
6586
+ var _ATTR_RE = /(\w+)="([^"]*)"/g;
6587
+ var _VALID_COMPLEXITY = /* @__PURE__ */ new Set([
6588
+ "low",
6589
+ "medium",
6590
+ "high"
6591
+ ]);
6592
+ var _VALID_SUMMARY = /* @__PURE__ */ new Set([
6593
+ "show",
6594
+ "hide"
6595
+ ]);
6596
+ function _parseAttrs(rawAttrs) {
6597
+ const out = {};
6598
+ for (const m of rawAttrs.matchAll(_ATTR_RE)) {
6599
+ out[m[1].toLowerCase()] = m[2];
6600
+ }
6601
+ return out;
6602
+ }
6603
+ function _inferNarration(text) {
6604
+ if (!text) return null;
6605
+ const head = text.trimStart().split(/\n\s*\n/, 1)[0].slice(0, 240);
6606
+ const endMatch = /([.!?])(\s|$)/.exec(head);
6607
+ const firstSentence = (endMatch ? head.slice(0, endMatch.index + 1) : head).trim();
6608
+ if (!firstSentence || firstSentence.length > 200) return null;
6609
+ return firstSentence;
6610
+ }
6611
+ function stripAndParseNextAction(text) {
6612
+ if (!text) {
6613
+ return { cleaned: text ?? "", action: null, inferredNarration: null };
6614
+ }
6615
+ let last = null;
6616
+ const matches = Array.from(text.matchAll(_NEXT_ACTION_RE));
6617
+ if (matches.length === 0) {
6618
+ return {
6619
+ cleaned: text,
6620
+ action: null,
6621
+ inferredNarration: _inferNarration(text)
6622
+ };
6623
+ }
6624
+ for (const match of matches) {
6625
+ const attrs = _parseAttrs(match[1] ?? "");
6626
+ const rawComplexity = (attrs["complexity"] ?? "").trim().toLowerCase();
6627
+ const complexity = _VALID_COMPLEXITY.has(rawComplexity) ? rawComplexity : "medium";
6628
+ const rawSummary = (attrs["summary"] ?? "").trim().toLowerCase();
6629
+ const summary = _VALID_SUMMARY.has(rawSummary) ? rawSummary : "hide";
6630
+ const body = (match[2] ?? "").trim() || "done";
6631
+ last = { complexity, summary, body };
6632
+ }
6633
+ const cleaned = text.replace(_NEXT_ACTION_RE, "").trimEnd();
6634
+ return { cleaned, action: last, inferredNarration: null };
6635
+ }
6583
6636
  var Artifact = ({ className, ...props }) => /* @__PURE__ */ jsx(
6584
6637
  "div",
6585
6638
  {
@@ -6705,12 +6758,21 @@ var EXPANDED_HEIGHT_PX = 800;
6705
6758
  var MIN_ZOOM = 0.5;
6706
6759
  var MAX_ZOOM = 2;
6707
6760
  var ZOOM_STEP = 0.1;
6761
+ var SAFETY_STYLE_PREAMBLE = "<style>html,body{max-height:100vh}canvas{max-height:80vh!important}</style>";
6762
+ function injectSafetyStyle(html) {
6763
+ const headCloseIdx = html.search(/<\/head\s*>/i);
6764
+ if (headCloseIdx >= 0) {
6765
+ return html.slice(0, headCloseIdx) + SAFETY_STYLE_PREAMBLE + html.slice(headCloseIdx);
6766
+ }
6767
+ return SAFETY_STYLE_PREAMBLE + html;
6768
+ }
6708
6769
  function ArtifactHtml({
6709
6770
  spec,
6710
6771
  fill = false
6711
6772
  }) {
6712
6773
  const [expanded, setExpanded] = useState(false);
6713
6774
  const [zoom, setZoom] = useState(1);
6775
+ const safeSrcdoc = useMemo(() => injectSafetyStyle(spec.html), [spec.html]);
6714
6776
  const viewportHeight = expanded ? EXPANDED_HEIGHT_PX : DEFAULT_HEIGHT_PX;
6715
6777
  const clamp = (v) => Math.round(Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, v)) * 100) / 100;
6716
6778
  return /* @__PURE__ */ jsxs(
@@ -6730,7 +6792,7 @@ function ArtifactHtml({
6730
6792
  "iframe",
6731
6793
  {
6732
6794
  title: "artifact-html",
6733
- srcDoc: spec.html,
6795
+ srcDoc: safeSrcdoc,
6734
6796
  sandbox: "allow-scripts",
6735
6797
  className: cn("border-0", fill && "h-full w-full"),
6736
6798
  style: fill ? { zoom } : {
@@ -7824,16 +7886,6 @@ function TurnSummaryCard({
7824
7886
  }) })
7825
7887
  ] });
7826
7888
  }
7827
- function TurnSummaryPending() {
7828
- return /* @__PURE__ */ jsxs("div", { className: "mt-3 rounded border border-border bg-muted/50 px-3 py-2 text-sm", children: [
7829
- /* @__PURE__ */ jsx("div", { className: "mb-2 text-xs font-semibold uppercase tracking-wide", children: "Summary" }),
7830
- /* @__PURE__ */ jsx(Shimmer, { duration: 3, spread: 3, className: "mb-2 text-sm", children: "Summarizing conversation..." }),
7831
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
7832
- /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-3/4" }),
7833
- /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-2/3" })
7834
- ] })
7835
- ] });
7836
- }
7837
7889
  function ArtifactRow({
7838
7890
  artifact,
7839
7891
  sessionId,
@@ -7896,6 +7948,7 @@ function ArtifactRow({
7896
7948
  }
7897
7949
  ) });
7898
7950
  }
7951
+ var WORKING_ON_IT_DELAY_MS = 250;
7899
7952
  function messageToEntries(msg, isLast, artifactFallbacks) {
7900
7953
  if (msg.role === "system") {
7901
7954
  if (msg.systemKind === "skill_invoked") {
@@ -7926,16 +7979,23 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
7926
7979
  const hasToolCalls = !!(msg.toolCalls && msg.toolCalls.length > 0);
7927
7980
  const hasContent = !!(msg.content && msg.content !== msg.reasoning);
7928
7981
  const isStreaming = msg.status === "streaming" && isLast;
7929
- const effectiveReasoning = hasToolCalls && hasContent ? msg.reasoning ? msg.reasoning + "\n" + msg.content : msg.content : msg.reasoning;
7930
7982
  const effectiveHasContent = hasContent && !hasToolCalls;
7931
- if (effectiveReasoning) {
7983
+ if (msg.reasoning) {
7932
7984
  entries.push({
7933
7985
  kind: "reasoning",
7934
7986
  key: `${msg.id}-reasoning`,
7935
- reasoning: effectiveReasoning,
7987
+ reasoning: msg.reasoning,
7936
7988
  isStreaming: isStreaming && !effectiveHasContent && !hasToolCalls
7937
7989
  });
7938
7990
  }
7991
+ if (hasContent && hasToolCalls) {
7992
+ entries.push({
7993
+ kind: "narration",
7994
+ key: `${msg.id}-narration`,
7995
+ text: msg.content,
7996
+ isStreaming: isStreaming && !effectiveHasContent
7997
+ });
7998
+ }
7939
7999
  if (hasToolCalls) {
7940
8000
  for (const tc of msg.toolCalls) {
7941
8001
  if (tc.toolName === "create_artifact") {
@@ -7966,12 +8026,6 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
7966
8026
  msg
7967
8027
  });
7968
8028
  }
7969
- const hasRunningTool = hasToolCalls && msg.toolCalls.some(
7970
- (tc) => tc.status === "running"
7971
- );
7972
- if (isStreaming && !effectiveHasContent && !hasRunningTool) {
7973
- entries.push({ kind: "thinking", key: `${msg.id}-thinking` });
7974
- }
7975
8029
  return entries;
7976
8030
  }
7977
8031
  function groupBrowserActivityEntries(entries) {
@@ -8083,7 +8137,10 @@ function OrphanSystemMarker({
8083
8137
  return /* @__PURE__ */ jsxs("div", { className: "my-2 flex items-center gap-2 px-4 text-xs text-foreground/60 ", children: [
8084
8138
  /* @__PURE__ */ jsx("span", { className: "size-2 rounded-full bg-emerald-500" }),
8085
8139
  /* @__PURE__ */ jsxs("span", { children: [
8086
- /* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: "Skill" }),
8140
+ /* @__PURE__ */ jsxs("span", { className: "font-semibold text-foreground", children: [
8141
+ "Running skill",
8142
+ " "
8143
+ ] }),
8087
8144
  /* @__PURE__ */ jsx("span", { className: "text-foreground/60 truncate", children: skill })
8088
8145
  ] })
8089
8146
  ] });
@@ -8198,6 +8255,9 @@ function TimelineEntryItem({
8198
8255
  if (entry.kind === "text") {
8199
8256
  return /* @__PURE__ */ jsx(TextEntry, { entry, step });
8200
8257
  }
8258
+ if (entry.kind === "narration") {
8259
+ return /* @__PURE__ */ jsx(NarrationEntry, { entry, step });
8260
+ }
8201
8261
  if (entry.kind === "skill_invoked") {
8202
8262
  return /* @__PURE__ */ jsxs(TimelineItem, { step, children: [
8203
8263
  /* @__PURE__ */ jsxs(TimelineHeader, { children: [
@@ -8256,18 +8316,35 @@ function ReasoningEntry({
8256
8316
  ] }) })
8257
8317
  ] });
8258
8318
  }
8319
+ function NarrationEntry({
8320
+ entry,
8321
+ step
8322
+ }) {
8323
+ const text = useSmoothStream(entry.text, entry.isStreaming);
8324
+ const { action, inferredNarration } = stripAndParseNextAction(text);
8325
+ const line = action ? action.body.trim().toLowerCase() === "done" ? null : action.body : inferredNarration;
8326
+ if (!line) return null;
8327
+ return /* @__PURE__ */ jsxs(TimelineItem, { step, children: [
8328
+ /* @__PURE__ */ jsxs(TimelineHeader, { children: [
8329
+ /* @__PURE__ */ jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
8330
+ /* @__PURE__ */ jsx(TimelineIndicator, { className: "size-2 border-none bg-foreground/30" })
8331
+ ] }),
8332
+ /* @__PURE__ */ jsx(TimelineContent, { children: /* @__PURE__ */ jsx("p", { children: line }) })
8333
+ ] });
8334
+ }
8259
8335
  function TextEntry({
8260
8336
  entry,
8261
8337
  step
8262
8338
  }) {
8263
8339
  const content = useSmoothStream(entry.content, entry.isStreaming);
8340
+ const { cleaned } = stripAndParseNextAction(content);
8264
8341
  return /* @__PURE__ */ jsxs(TimelineItem, { step, children: [
8265
8342
  /* @__PURE__ */ jsxs(TimelineHeader, { children: [
8266
8343
  /* @__PURE__ */ jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
8267
8344
  /* @__PURE__ */ jsx(TimelineIndicator, { className: "size-2 border-none bg-foreground/40" })
8268
8345
  ] }),
8269
8346
  /* @__PURE__ */ jsxs(TimelineContent, { children: [
8270
- /* @__PURE__ */ jsx(MessageResponse, { children: content }),
8347
+ /* @__PURE__ */ jsx(MessageResponse, { children: cleaned }),
8271
8348
  entry.isFinalTurnText && entry.msg.status === "complete" && /* @__PURE__ */ jsx(TurnFeedback, { msg: entry.msg })
8272
8349
  ] })
8273
8350
  ] });
@@ -8279,8 +8356,9 @@ function SimpleFinalAnswer({
8279
8356
  }) {
8280
8357
  const content = useSmoothStream(text, isStreaming);
8281
8358
  const revealComplete = content.length >= text.length;
8359
+ const { cleaned } = stripAndParseNextAction(content);
8282
8360
  return /* @__PURE__ */ jsxs("div", { children: [
8283
- /* @__PURE__ */ jsx(MessageResponse, { children: content }),
8361
+ /* @__PURE__ */ jsx(MessageResponse, { children: cleaned }),
8284
8362
  tail?.status === "complete" && revealComplete && /* @__PURE__ */ jsx(TurnFeedback, { msg: tail })
8285
8363
  ] });
8286
8364
  }
@@ -8573,7 +8651,7 @@ function IterationGroup({
8573
8651
  if (!label) {
8574
8652
  return null;
8575
8653
  }
8576
- const labelTone = summary ? "text-foreground/80" : "text-foreground/50";
8654
+ const labelTone = summary ? "text-muted-foreground italic" : "text-muted-foreground";
8577
8655
  return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
8578
8656
  /* @__PURE__ */ jsxs(
8579
8657
  "button",
@@ -8659,10 +8737,7 @@ function deriveFileArtifactsFromMessages(messages) {
8659
8737
  }
8660
8738
  function SimpleAssistantGroup({
8661
8739
  messages,
8662
- lastGlobalIndex,
8663
- totalMessages,
8664
8740
  isRunning,
8665
- terminal,
8666
8741
  sessionId,
8667
8742
  artifactFallbacks,
8668
8743
  onFileSelect,
@@ -8673,16 +8748,15 @@ function SimpleAssistantGroup({
8673
8748
  const tailHasTools = !!(tail?.toolCalls && tail.toolCalls.length > 0);
8674
8749
  const tailIsTextOnly = !!tail && !tailHasTools;
8675
8750
  const finalText = tailIsTextOnly && tail.content ? tail.content : "";
8676
- const isTailGroup = lastGlobalIndex === totalMessages - 1;
8677
- const tailRendersOwnShimmer = !!tail && isIterationLive(tail) && !tailIsTextOnly;
8678
- const showThinkingShim = isTailGroup && isRunning && !tailRendersOwnShimmer;
8679
8751
  const showErrorInfo = !!tail && tail.status === "error" && !!tail.errorInfo;
8680
8752
  const turnComplete = !isRunning && tail?.status === "complete";
8753
+ const summaryPref = finalText !== null ? stripAndParseNextAction(finalText).action?.summary ?? "hide" : "hide";
8681
8754
  const effectiveTurnSummary = (() => {
8682
8755
  const fromHarness = tail?.turnSummary;
8683
8756
  if (fromHarness && fromHarness.artifacts.length > 0) {
8684
8757
  return fromHarness;
8685
8758
  }
8759
+ if (summaryPref === "hide") return null;
8686
8760
  if (!turnComplete) return fromHarness;
8687
8761
  const derived = deriveFileArtifactsFromMessages(messages);
8688
8762
  if (derived.length === 0) return fromHarness;
@@ -8706,17 +8780,22 @@ function SimpleAssistantGroup({
8706
8780
  message.id
8707
8781
  );
8708
8782
  }
8709
- if (message === tail && tailIsTextOnly) return null;
8710
- return /* @__PURE__ */ jsx(
8711
- IterationGroup,
8712
- {
8713
- message,
8714
- sessionId,
8715
- artifactFallbacks,
8716
- onFileSelect
8717
- },
8718
- message.id
8719
- );
8783
+ if (message === tail && tailIsTextOnly && finalText) return null;
8784
+ const rawContent = (message.content ?? "").trim();
8785
+ const { action, inferredNarration } = stripAndParseNextAction(rawContent);
8786
+ const narrationLine = action ? action.body.trim().toLowerCase() === "done" ? null : action.body : inferredNarration;
8787
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8788
+ narrationLine && /* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: narrationLine }),
8789
+ /* @__PURE__ */ jsx(
8790
+ IterationGroup,
8791
+ {
8792
+ message,
8793
+ sessionId,
8794
+ artifactFallbacks,
8795
+ onFileSelect
8796
+ }
8797
+ )
8798
+ ] }, message.id);
8720
8799
  }) }),
8721
8800
  finalText && /* @__PURE__ */ jsx(
8722
8801
  SimpleFinalAnswer,
@@ -8726,8 +8805,7 @@ function SimpleAssistantGroup({
8726
8805
  tail
8727
8806
  }
8728
8807
  ),
8729
- showThinkingShim && /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx(Shimmer, { duration: 3, spread: 3, className: "text-sm", children: "Working on it..." }) }),
8730
- effectiveTurnSummary ? /* @__PURE__ */ jsx(
8808
+ effectiveTurnSummary && /* @__PURE__ */ jsx(
8731
8809
  TurnSummaryCard,
8732
8810
  {
8733
8811
  summary: effectiveTurnSummary,
@@ -8735,16 +8813,6 @@ function SimpleAssistantGroup({
8735
8813
  messages,
8736
8814
  onFileSelect
8737
8815
  }
8738
- ) : (
8739
- // The harness summarizer runs after the last assistant
8740
- // response and before ``session.complete``. Show a pending
8741
- // placeholder during that window so users aren't surprised
8742
- // when the Summary card pops in. Gated on ``!terminal``
8743
- // rather than ``isRunning`` because the text-only final
8744
- // ``llm.response`` already flips ``isRunning`` to false —
8745
- // the summarizer then runs in the gap before
8746
- // ``session.complete`` (which is what sets ``terminal``).
8747
- isTailGroup && !terminal && !!finalText && tail?.status === "complete" && /* @__PURE__ */ jsx(TurnSummaryPending, {})
8748
8816
  ),
8749
8817
  showErrorInfo && /* @__PURE__ */ jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsx(ErrorMessage, { errorInfo: tail.errorInfo, onRetry }) })
8750
8818
  ] }) });
@@ -8754,7 +8822,6 @@ function AssistantGroup({
8754
8822
  lastGlobalIndex,
8755
8823
  totalMessages,
8756
8824
  isRunning,
8757
- terminal,
8758
8825
  sessionId,
8759
8826
  artifactFallbacks,
8760
8827
  onFileSelect,
@@ -8766,10 +8833,7 @@ function AssistantGroup({
8766
8833
  SimpleAssistantGroup,
8767
8834
  {
8768
8835
  messages,
8769
- lastGlobalIndex,
8770
- totalMessages,
8771
8836
  isRunning,
8772
- terminal,
8773
8837
  sessionId,
8774
8838
  artifactFallbacks,
8775
8839
  onFileSelect,
@@ -8791,15 +8855,6 @@ function AssistantGroup({
8791
8855
  break;
8792
8856
  }
8793
8857
  }
8794
- const isTailGroup = lastGlobalIndex === totalMessages - 1;
8795
- const lastEntry = entries[entries.length - 1];
8796
- const hasRunningTool = entries.some(
8797
- (e) => e.kind === "tool" && e.tc.status === "running"
8798
- );
8799
- const tailMsg = messages[messages.length - 1];
8800
- if (isTailGroup && isRunning && !hasRunningTool && lastEntry?.kind !== "thinking") {
8801
- entries.push({ kind: "thinking", key: `${tailMsg.id}-tail-thinking` });
8802
- }
8803
8858
  const tail = messages[messages.length - 1];
8804
8859
  const showErrorInfo = tail && tail.role === "assistant" && tail.status === "error" && !!tail.errorInfo;
8805
8860
  return /* @__PURE__ */ jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsxs(MessageContent, { children: [
@@ -8847,11 +8902,30 @@ function RetryBanner({ indicator }) {
8847
8902
  }
8848
8903
  );
8849
8904
  }
8905
+ function WorkingOnItIndicator() {
8906
+ return /* @__PURE__ */ jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(Shimmer, { duration: 3, spread: 3, className: "text-sm", children: "Working on it..." }) }) });
8907
+ }
8908
+ function useDelayedRunningIndicator(isRunning) {
8909
+ const [visible, setVisible] = useState(isRunning);
8910
+ useEffect(() => {
8911
+ if (!isRunning) {
8912
+ setVisible(false);
8913
+ return;
8914
+ }
8915
+ if (visible) return;
8916
+ const timeout = window.setTimeout(() => {
8917
+ setVisible(true);
8918
+ }, WORKING_ON_IT_DELAY_MS);
8919
+ return () => {
8920
+ window.clearTimeout(timeout);
8921
+ };
8922
+ }, [isRunning, visible]);
8923
+ return visible;
8924
+ }
8850
8925
  function ChatThread({
8851
8926
  sessionId,
8852
8927
  messages,
8853
8928
  isRunning,
8854
- terminal,
8855
8929
  isLoadingHistory = false,
8856
8930
  onSend,
8857
8931
  onStop,
@@ -8872,6 +8946,7 @@ function ChatThread({
8872
8946
  onViewModeChange
8873
8947
  }) {
8874
8948
  const groups = useMemo(() => groupMessages(messages), [messages]);
8949
+ const showWorkingOnIt = useDelayedRunningIndicator(isRunning);
8875
8950
  const artifactFallbacks = useMemo(() => {
8876
8951
  const fallbacks = {};
8877
8952
  const createArtifactToolCallIds = [];
@@ -8905,7 +8980,7 @@ function ChatThread({
8905
8980
  }
8906
8981
  return null;
8907
8982
  }, [messages]);
8908
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden bg-background text-sm", children: [
8983
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden bg-background text-base", children: [
8909
8984
  /* @__PURE__ */ jsxs(Conversation, { className: "relative flex-1 min-h-0", children: [
8910
8985
  /* @__PURE__ */ jsx(ConversationContent, { className: "mx-auto w-full max-w-4xl", children: messages.length === 0 && isLoadingHistory ? /* @__PURE__ */ jsx(
8911
8986
  ConversationEmptyState,
@@ -8959,7 +9034,6 @@ function ChatThread({
8959
9034
  lastGlobalIndex: group.lastGlobalIndex,
8960
9035
  totalMessages: messages.length,
8961
9036
  isRunning,
8962
- terminal,
8963
9037
  sessionId,
8964
9038
  artifactFallbacks,
8965
9039
  onFileSelect,
@@ -8969,7 +9043,7 @@ function ChatThread({
8969
9043
  group.messages[0].id
8970
9044
  );
8971
9045
  }),
8972
- isRunning && messages.length > 0 && messages[messages.length - 1].role === "user" && /* @__PURE__ */ jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(Shimmer, { duration: 3, spread: 3, className: "text-sm", children: "Working on it..." }) }) })
9046
+ showWorkingOnIt && /* @__PURE__ */ jsx(WorkingOnItIndicator, {})
8973
9047
  ] }) }),
8974
9048
  /* @__PURE__ */ jsx(ConversationScrollButton, {})
8975
9049
  ] }),
@@ -9753,6 +9827,9 @@ function applyAgentChatEvent(state, event) {
9753
9827
  sessionDone: state.sessionDone || event.type === "session.done"
9754
9828
  };
9755
9829
  nextState = applyRetryIndicator(nextState, event);
9830
+ if (state.terminal && isPostTerminalLiveEvent(event.type)) {
9831
+ return nextState;
9832
+ }
9756
9833
  switch (event.type) {
9757
9834
  case "user.message":
9758
9835
  return withMessages(
@@ -9895,6 +9972,9 @@ function applyAgentChatEvent(state, event) {
9895
9972
  return applyTurnSummary(nextState, event);
9896
9973
  }
9897
9974
  }
9975
+ function isPostTerminalLiveEvent(type) {
9976
+ return type === "harness.wake" || type === "llm.request" || type === "session.resume" || type === "llm.delta" || type === "llm.response" || type === "llm.thinking" || type === "tool.call";
9977
+ }
9898
9978
  function applyRetryIndicator(state, event) {
9899
9979
  switch (event.type) {
9900
9980
  case "harness.wake":
@@ -10083,30 +10163,18 @@ function applyLlmResponse(state, event) {
10083
10163
  );
10084
10164
  if (state.hadDeltas && idx >= 0 && !hasUserAfter) {
10085
10165
  const current = messages[idx];
10086
- if (hasToolCalls) {
10087
- messages[idx] = {
10088
- ...current,
10089
- reasoning: (current.reasoning ?? "") + current.content,
10090
- content: "",
10091
- status: "streaming",
10092
- llmResponseEventId: event.eventId,
10093
- turnId: turnId ?? current.turnId,
10094
- iterationIndex: iterationIndex ?? current.iterationIndex
10095
- };
10096
- } else {
10097
- messages[idx] = {
10098
- ...current,
10099
- status: "complete",
10100
- llmResponseEventId: event.eventId,
10101
- turnId: turnId ?? current.turnId,
10102
- iterationIndex: iterationIndex ?? current.iterationIndex
10103
- };
10104
- }
10166
+ messages[idx] = {
10167
+ ...current,
10168
+ status: hasToolCalls ? "streaming" : "complete",
10169
+ llmResponseEventId: event.eventId,
10170
+ turnId: turnId ?? current.turnId,
10171
+ iterationIndex: iterationIndex ?? current.iterationIndex
10172
+ };
10105
10173
  } else if (matchesExistingToolTurn && idx >= 0) {
10106
10174
  const current = messages[idx];
10107
10175
  messages[idx] = {
10108
10176
  ...current,
10109
- reasoning: responseContent ? appendText(current.reasoning, responseContent) : current.reasoning,
10177
+ content: responseContent ? appendText(current.content, responseContent) : current.content,
10110
10178
  status: "streaming",
10111
10179
  llmResponseEventId: event.eventId,
10112
10180
  turnId: turnId ?? current.turnId,
@@ -10116,8 +10184,8 @@ function applyLlmResponse(state, event) {
10116
10184
  messages.push({
10117
10185
  id: `evt-${event.eventId}`,
10118
10186
  role: "assistant",
10119
- content: hasToolCalls ? "" : responseContent,
10120
- reasoning: hasToolCalls && responseContent ? responseContent : void 0,
10187
+ content: responseContent,
10188
+ reasoning: void 0,
10121
10189
  createdAt: /* @__PURE__ */ new Date(),
10122
10190
  status: hasToolCalls ? "streaming" : "complete",
10123
10191
  llmResponseEventId: event.eventId,
@@ -10126,25 +10194,14 @@ function applyLlmResponse(state, event) {
10126
10194
  });
10127
10195
  } else {
10128
10196
  const current = messages[idx];
10129
- if (hasToolCalls && responseContent) {
10130
- messages[idx] = {
10131
- ...current,
10132
- reasoning: (current.reasoning ?? "") + responseContent,
10133
- status: "streaming",
10134
- llmResponseEventId: event.eventId,
10135
- turnId: turnId ?? current.turnId,
10136
- iterationIndex: iterationIndex ?? current.iterationIndex
10137
- };
10138
- } else {
10139
- messages[idx] = {
10140
- ...current,
10141
- content: responseContent || current.content,
10142
- status: hasToolCalls ? "streaming" : "complete",
10143
- llmResponseEventId: event.eventId,
10144
- turnId: turnId ?? current.turnId,
10145
- iterationIndex: iterationIndex ?? current.iterationIndex
10146
- };
10147
- }
10197
+ messages[idx] = {
10198
+ ...current,
10199
+ content: responseContent || current.content,
10200
+ status: hasToolCalls ? "streaming" : "complete",
10201
+ llmResponseEventId: event.eventId,
10202
+ turnId: turnId ?? current.turnId,
10203
+ iterationIndex: iterationIndex ?? current.iterationIndex
10204
+ };
10148
10205
  }
10149
10206
  const inputTokens = numberValue(event.data.input_tokens);
10150
10207
  const outputTokens = numberValue(event.data.output_tokens);
@@ -13511,7 +13568,7 @@ function TreeNodeRow({
13511
13568
  type: "button",
13512
13569
  className: cn(
13513
13570
  "p-2 md:p-1 rounded hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none transition-all",
13514
- deletingSessionId === entry.id ? "opacity-100" : "opacity-100 md:opacity-0 md:group-hover:opacity-100 md:focus-visible:opacity-100"
13571
+ deletingSessionId === entry.id ? "opacity-100" : "opacity-60 md:opacity-50 md:group-hover:opacity-100 md:focus-visible:opacity-100"
13515
13572
  ),
13516
13573
  onClick: (e) => {
13517
13574
  e.stopPropagation();