@invergent/agent-chat-react 2.4.11 → 2.4.13

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
@@ -7958,6 +7958,20 @@ function ArtifactRow({
7958
7958
  ) });
7959
7959
  }
7960
7960
  var WORKING_ON_IT_DELAY_MS = 250;
7961
+ function hasUserFacingAskContent(msg) {
7962
+ return !!msg.toolCalls?.some((tc) => tc.toolName === "ask_user_question");
7963
+ }
7964
+ function isAwaitingUserInput(messages) {
7965
+ for (let i = messages.length - 1; i >= 0; i--) {
7966
+ const m = messages[i];
7967
+ if (m.role === "user") return false;
7968
+ if (m.role !== "assistant") continue;
7969
+ return !!m.toolCalls?.some(
7970
+ (tc) => tc.toolName === "ask_user_question" && tc.status === "running"
7971
+ );
7972
+ }
7973
+ return false;
7974
+ }
7961
7975
  function messageToEntries(msg, isLast, artifactFallbacks) {
7962
7976
  if (msg.role === "system") {
7963
7977
  if (msg.systemKind === "skill_invoked") {
@@ -7982,6 +7996,14 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
7982
7996
  version
7983
7997
  }];
7984
7998
  }
7999
+ if (msg.systemKind === "browser_marker" || msg.systemKind === "browser_marker_warning") {
8000
+ return [{
8001
+ kind: "browser_marker",
8002
+ key: msg.id,
8003
+ content: msg.content,
8004
+ warning: msg.systemKind === "browser_marker_warning"
8005
+ }];
8006
+ }
7985
8007
  return [];
7986
8008
  }
7987
8009
  const entries = [];
@@ -7998,12 +8020,22 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
7998
8020
  });
7999
8021
  }
8000
8022
  if (hasContent && hasToolCalls) {
8001
- entries.push({
8002
- kind: "narration",
8003
- key: `${msg.id}-narration`,
8004
- text: msg.content,
8005
- isStreaming: isStreaming && !effectiveHasContent
8006
- });
8023
+ if (hasUserFacingAskContent(msg)) {
8024
+ entries.push({
8025
+ kind: "text",
8026
+ key: `${msg.id}-text`,
8027
+ content: msg.content,
8028
+ isStreaming: false,
8029
+ msg
8030
+ });
8031
+ } else {
8032
+ entries.push({
8033
+ kind: "narration",
8034
+ key: `${msg.id}-narration`,
8035
+ text: msg.content,
8036
+ isStreaming: isStreaming && !effectiveHasContent
8037
+ });
8038
+ }
8007
8039
  }
8008
8040
  if (hasToolCalls) {
8009
8041
  for (const tc of msg.toolCalls) {
@@ -8167,6 +8199,23 @@ function OrphanSystemMarker({
8167
8199
  }
8168
8200
  );
8169
8201
  }
8202
+ if (message.systemKind === "browser_marker" || message.systemKind === "browser_marker_warning") {
8203
+ const warning = message.systemKind === "browser_marker_warning";
8204
+ return /* @__PURE__ */ jsxs(
8205
+ "div",
8206
+ {
8207
+ className: cn(
8208
+ "my-2 flex items-center gap-2 px-4 text-xs",
8209
+ warning ? "text-amber-600" : "text-foreground/60"
8210
+ ),
8211
+ role: warning ? "alert" : "status",
8212
+ children: [
8213
+ warning ? /* @__PURE__ */ jsx(AlertTriangle, { className: "size-3.5 shrink-0", "aria-hidden": true }) : /* @__PURE__ */ jsx("span", { className: "size-2 rounded-full bg-foreground/30" }),
8214
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: message.content })
8215
+ ]
8216
+ }
8217
+ );
8218
+ }
8170
8219
  if (message.systemKind === "error" && message.errorInfo) {
8171
8220
  return /* @__PURE__ */ jsx("div", { className: "mx-auto my-2 w-full max-w-4xl", children: /* @__PURE__ */ jsx(ErrorMessage, { errorInfo: message.errorInfo, onRetry }) });
8172
8221
  }
@@ -8267,6 +8316,36 @@ function TimelineEntryItem({
8267
8316
  if (entry.kind === "narration") {
8268
8317
  return /* @__PURE__ */ jsx(NarrationEntry, { entry, step });
8269
8318
  }
8319
+ if (entry.kind === "browser_marker") {
8320
+ return /* @__PURE__ */ jsxs(TimelineItem, { step, children: [
8321
+ /* @__PURE__ */ jsxs(TimelineHeader, { children: [
8322
+ /* @__PURE__ */ jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
8323
+ /* @__PURE__ */ jsx(
8324
+ TimelineIndicator,
8325
+ {
8326
+ className: cn(
8327
+ "size-2 border-none",
8328
+ entry.warning ? "bg-amber-500" : "bg-foreground/30"
8329
+ )
8330
+ }
8331
+ )
8332
+ ] }),
8333
+ /* @__PURE__ */ jsx(TimelineContent, { children: /* @__PURE__ */ jsxs(
8334
+ "div",
8335
+ {
8336
+ className: cn(
8337
+ "flex items-center gap-1.5 py-1 text-sm",
8338
+ entry.warning ? "text-amber-600" : "text-foreground/60"
8339
+ ),
8340
+ role: entry.warning ? "alert" : "status",
8341
+ children: [
8342
+ entry.warning && /* @__PURE__ */ jsx(AlertTriangle, { className: "size-3.5 shrink-0", "aria-hidden": true }),
8343
+ /* @__PURE__ */ jsx("span", { children: entry.content })
8344
+ ]
8345
+ }
8346
+ ) })
8347
+ ] });
8348
+ }
8270
8349
  if (entry.kind === "skill_invoked") {
8271
8350
  return /* @__PURE__ */ jsxs(TimelineItem, { step, children: [
8272
8351
  /* @__PURE__ */ jsxs(TimelineHeader, { children: [
@@ -8646,13 +8725,13 @@ function IterationGroup({
8646
8725
  }) {
8647
8726
  const summary = message.iterationSummary?.summary;
8648
8727
  const [open, setOpen] = useState(false);
8728
+ const askCall = (message.toolCalls ?? []).find(
8729
+ (tc) => tc.toolName === "ask_user_question"
8730
+ );
8731
+ if (askCall) {
8732
+ return /* @__PURE__ */ jsx("div", { className: "px-1 py-0.5", children: /* @__PURE__ */ jsx(AskUserQuestionToolBlock, { tc: askCall }) });
8733
+ }
8649
8734
  if (isIterationLive(message)) {
8650
- const askCall = (message.toolCalls ?? []).find(
8651
- (tc) => tc.toolName === "ask_user_question" && tc.status === "running"
8652
- );
8653
- if (askCall) {
8654
- return /* @__PURE__ */ jsx("div", { className: "px-1 py-0.5", children: /* @__PURE__ */ jsx(AskUserQuestionToolBlock, { tc: askCall }) });
8655
- }
8656
8735
  const label2 = liveIterationLabel(message);
8657
8736
  return /* @__PURE__ */ jsx("div", { className: "py-0.5 text-sm", children: /* @__PURE__ */ jsx(Shimmer, { duration: 3, spread: 3, className: "text-sm", children: label2 }) });
8658
8737
  }
@@ -8711,6 +8790,14 @@ function deriveFileArtifactsFromMessages(messages) {
8711
8790
  const seen = /* @__PURE__ */ new Set();
8712
8791
  const out = [];
8713
8792
  for (const msg of messages) {
8793
+ if (msg.role === "system") {
8794
+ if (msg.systemKind !== "artifact") continue;
8795
+ const { artifactId, name } = unpackArtifactMeta(msg.systemMeta, msg.content);
8796
+ if (!artifactId || seen.has(`artifact:${artifactId}`)) continue;
8797
+ seen.add(`artifact:${artifactId}`);
8798
+ out.push({ kind: "artifact", label: name, ref: artifactId });
8799
+ continue;
8800
+ }
8714
8801
  if (msg.role !== "assistant" || !msg.toolCalls) continue;
8715
8802
  for (const tc of msg.toolCalls) {
8716
8803
  const status = effectiveStatus(tc);
@@ -8730,16 +8817,6 @@ function deriveFileArtifactsFromMessages(messages) {
8730
8817
  });
8731
8818
  continue;
8732
8819
  }
8733
- if (tc.toolName === "create_artifact") {
8734
- const name = typeof args.name === "string" ? args.name : "";
8735
- if (!name || seen.has(`artifact:${name}`)) continue;
8736
- seen.add(`artifact:${name}`);
8737
- out.push({
8738
- kind: "artifact",
8739
- label: name,
8740
- ref: name
8741
- });
8742
- }
8743
8820
  }
8744
8821
  }
8745
8822
  return out;
@@ -8765,15 +8842,18 @@ function SimpleAssistantGroup({
8765
8842
  if (fromHarness && fromHarness.artifacts.length > 0) {
8766
8843
  return fromHarness;
8767
8844
  }
8845
+ if (turnComplete) {
8846
+ const derived = deriveFileArtifactsFromMessages(messages);
8847
+ if (derived.length > 0) {
8848
+ return {
8849
+ turnId: fromHarness?.turnId ?? "",
8850
+ recap: summaryPref === "show" ? fromHarness?.recap ?? "" : "",
8851
+ artifacts: derived
8852
+ };
8853
+ }
8854
+ }
8768
8855
  if (summaryPref === "hide") return null;
8769
- if (!turnComplete) return fromHarness;
8770
- const derived = deriveFileArtifactsFromMessages(messages);
8771
- if (derived.length === 0) return fromHarness;
8772
- return {
8773
- turnId: fromHarness?.turnId ?? "",
8774
- recap: fromHarness?.recap ?? "",
8775
- artifacts: derived
8776
- };
8856
+ return fromHarness;
8777
8857
  })();
8778
8858
  return /* @__PURE__ */ jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsxs(MessageContent, { children: [
8779
8859
  /* @__PURE__ */ jsx("div", { className: "space-y-2", children: messages.map((message) => {
@@ -8791,10 +8871,11 @@ function SimpleAssistantGroup({
8791
8871
  }
8792
8872
  if (message === tail && tailIsTextOnly && finalText) return null;
8793
8873
  const rawContent = (message.content ?? "").trim();
8794
- const { action, inferredNarration } = stripAndParseNextAction(rawContent);
8874
+ const { action, inferredNarration, cleaned } = stripAndParseNextAction(rawContent);
8795
8875
  const narrationLine = action ? action.body.trim().toLowerCase() === "done" ? null : action.body : inferredNarration;
8876
+ const askBody = hasUserFacingAskContent(message) ? cleaned : null;
8796
8877
  return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8797
- narrationLine && /* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: narrationLine }),
8878
+ askBody ? /* @__PURE__ */ jsx(MessageResponse, { children: askBody }) : narrationLine ? /* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: narrationLine }) : null,
8798
8879
  /* @__PURE__ */ jsx(
8799
8880
  IterationGroup,
8800
8881
  {
@@ -8859,7 +8940,7 @@ function AssistantGroup({
8859
8940
  entries = groupWebSearchEntries(entries);
8860
8941
  for (let i = entries.length - 1; i >= 0; i--) {
8861
8942
  const entry = entries[i];
8862
- if (entry?.kind === "text") {
8943
+ if (entry?.kind === "text" && !hasUserFacingAskContent(entry.msg)) {
8863
8944
  entries[i] = { ...entry, isFinalTurnText: true };
8864
8945
  break;
8865
8946
  }
@@ -8955,7 +9036,10 @@ function ChatThread({
8955
9036
  onViewModeChange
8956
9037
  }) {
8957
9038
  const groups = useMemo(() => groupMessages(messages), [messages]);
8958
- const showWorkingOnIt = useDelayedRunningIndicator(isRunning);
9039
+ const awaitingInput = useMemo(() => isAwaitingUserInput(messages), [messages]);
9040
+ const showWorkingOnIt = useDelayedRunningIndicator(isRunning) && !awaitingInput;
9041
+ const composerDisabled = disabled || awaitingInput;
9042
+ const composerDisabledReason = awaitingInput ? "Answer the question above to continue." : disabledReason;
8959
9043
  const artifactFallbacks = useMemo(() => {
8960
9044
  const fallbacks = {};
8961
9045
  const createArtifactToolCallIds = [];
@@ -9058,12 +9142,12 @@ function ChatThread({
9058
9142
  ] }),
9059
9143
  /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-4xl px-3 sm:px-6 pb-3 sm:pb-5 pt-3", children: [
9060
9144
  retryIndicator && /* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsx(RetryBanner, { indicator: retryIndicator }) }),
9061
- disabled && disabledReason ? /* @__PURE__ */ jsx(
9145
+ composerDisabled && composerDisabledReason ? /* @__PURE__ */ jsx(
9062
9146
  "div",
9063
9147
  {
9064
9148
  className: "rounded border border-line bg-muted/40 px-3 py-2 text-sm text-foreground/60",
9065
9149
  role: "status",
9066
- children: disabledReason
9150
+ children: composerDisabledReason
9067
9151
  }
9068
9152
  ) : /* @__PURE__ */ jsx(
9069
9153
  ChatComposer,
@@ -9071,8 +9155,8 @@ function ChatThread({
9071
9155
  onSend,
9072
9156
  onStop,
9073
9157
  isRunning,
9074
- disabled,
9075
- disabledReason,
9158
+ disabled: composerDisabled,
9159
+ disabledReason: composerDisabledReason,
9076
9160
  tokenUsage,
9077
9161
  onComposerError,
9078
9162
  showBrowser,