@invergent/agent-chat-react 2.4.12 → 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.cjs CHANGED
@@ -8256,6 +8256,20 @@ function ArtifactRow({
8256
8256
  // src/components/chat/chat-thread.tsx
8257
8257
  init_utils();
8258
8258
  var WORKING_ON_IT_DELAY_MS = 250;
8259
+ function hasUserFacingAskContent(msg) {
8260
+ return !!msg.toolCalls?.some((tc) => tc.toolName === "ask_user_question");
8261
+ }
8262
+ function isAwaitingUserInput(messages) {
8263
+ for (let i = messages.length - 1; i >= 0; i--) {
8264
+ const m = messages[i];
8265
+ if (m.role === "user") return false;
8266
+ if (m.role !== "assistant") continue;
8267
+ return !!m.toolCalls?.some(
8268
+ (tc) => tc.toolName === "ask_user_question" && tc.status === "running"
8269
+ );
8270
+ }
8271
+ return false;
8272
+ }
8259
8273
  function messageToEntries(msg, isLast, artifactFallbacks) {
8260
8274
  if (msg.role === "system") {
8261
8275
  if (msg.systemKind === "skill_invoked") {
@@ -8280,6 +8294,14 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
8280
8294
  version
8281
8295
  }];
8282
8296
  }
8297
+ if (msg.systemKind === "browser_marker" || msg.systemKind === "browser_marker_warning") {
8298
+ return [{
8299
+ kind: "browser_marker",
8300
+ key: msg.id,
8301
+ content: msg.content,
8302
+ warning: msg.systemKind === "browser_marker_warning"
8303
+ }];
8304
+ }
8283
8305
  return [];
8284
8306
  }
8285
8307
  const entries = [];
@@ -8296,12 +8318,22 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
8296
8318
  });
8297
8319
  }
8298
8320
  if (hasContent && hasToolCalls) {
8299
- entries.push({
8300
- kind: "narration",
8301
- key: `${msg.id}-narration`,
8302
- text: msg.content,
8303
- isStreaming: isStreaming && !effectiveHasContent
8304
- });
8321
+ if (hasUserFacingAskContent(msg)) {
8322
+ entries.push({
8323
+ kind: "text",
8324
+ key: `${msg.id}-text`,
8325
+ content: msg.content,
8326
+ isStreaming: false,
8327
+ msg
8328
+ });
8329
+ } else {
8330
+ entries.push({
8331
+ kind: "narration",
8332
+ key: `${msg.id}-narration`,
8333
+ text: msg.content,
8334
+ isStreaming: isStreaming && !effectiveHasContent
8335
+ });
8336
+ }
8305
8337
  }
8306
8338
  if (hasToolCalls) {
8307
8339
  for (const tc of msg.toolCalls) {
@@ -8465,6 +8497,23 @@ function OrphanSystemMarker({
8465
8497
  }
8466
8498
  );
8467
8499
  }
8500
+ if (message.systemKind === "browser_marker" || message.systemKind === "browser_marker_warning") {
8501
+ const warning = message.systemKind === "browser_marker_warning";
8502
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8503
+ "div",
8504
+ {
8505
+ className: cn(
8506
+ "my-2 flex items-center gap-2 px-4 text-xs",
8507
+ warning ? "text-amber-600" : "text-foreground/60"
8508
+ ),
8509
+ role: warning ? "alert" : "status",
8510
+ children: [
8511
+ warning ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "size-3.5 shrink-0", "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-2 rounded-full bg-foreground/30" }),
8512
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: message.content })
8513
+ ]
8514
+ }
8515
+ );
8516
+ }
8468
8517
  if (message.systemKind === "error" && message.errorInfo) {
8469
8518
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto my-2 w-full max-w-4xl", children: /* @__PURE__ */ jsxRuntime.jsx(ErrorMessage, { errorInfo: message.errorInfo, onRetry }) });
8470
8519
  }
@@ -8565,6 +8614,36 @@ function TimelineEntryItem({
8565
8614
  if (entry.kind === "narration") {
8566
8615
  return /* @__PURE__ */ jsxRuntime.jsx(NarrationEntry, { entry, step });
8567
8616
  }
8617
+ if (entry.kind === "browser_marker") {
8618
+ return /* @__PURE__ */ jsxRuntime.jsxs(TimelineItem, { step, children: [
8619
+ /* @__PURE__ */ jsxRuntime.jsxs(TimelineHeader, { children: [
8620
+ /* @__PURE__ */ jsxRuntime.jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
8621
+ /* @__PURE__ */ jsxRuntime.jsx(
8622
+ TimelineIndicator,
8623
+ {
8624
+ className: cn(
8625
+ "size-2 border-none",
8626
+ entry.warning ? "bg-amber-500" : "bg-foreground/30"
8627
+ )
8628
+ }
8629
+ )
8630
+ ] }),
8631
+ /* @__PURE__ */ jsxRuntime.jsx(TimelineContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(
8632
+ "div",
8633
+ {
8634
+ className: cn(
8635
+ "flex items-center gap-1.5 py-1 text-sm",
8636
+ entry.warning ? "text-amber-600" : "text-foreground/60"
8637
+ ),
8638
+ role: entry.warning ? "alert" : "status",
8639
+ children: [
8640
+ entry.warning && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "size-3.5 shrink-0", "aria-hidden": true }),
8641
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: entry.content })
8642
+ ]
8643
+ }
8644
+ ) })
8645
+ ] });
8646
+ }
8568
8647
  if (entry.kind === "skill_invoked") {
8569
8648
  return /* @__PURE__ */ jsxRuntime.jsxs(TimelineItem, { step, children: [
8570
8649
  /* @__PURE__ */ jsxRuntime.jsxs(TimelineHeader, { children: [
@@ -8944,13 +9023,13 @@ function IterationGroup({
8944
9023
  }) {
8945
9024
  const summary = message.iterationSummary?.summary;
8946
9025
  const [open, setOpen] = react.useState(false);
9026
+ const askCall = (message.toolCalls ?? []).find(
9027
+ (tc) => tc.toolName === "ask_user_question"
9028
+ );
9029
+ if (askCall) {
9030
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-1 py-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(AskUserQuestionToolBlock, { tc: askCall }) });
9031
+ }
8947
9032
  if (isIterationLive(message)) {
8948
- const askCall = (message.toolCalls ?? []).find(
8949
- (tc) => tc.toolName === "ask_user_question" && tc.status === "running"
8950
- );
8951
- if (askCall) {
8952
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-1 py-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(AskUserQuestionToolBlock, { tc: askCall }) });
8953
- }
8954
9033
  const label2 = liveIterationLabel(message);
8955
9034
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-0.5 text-sm", children: /* @__PURE__ */ jsxRuntime.jsx(Shimmer, { duration: 3, spread: 3, className: "text-sm", children: label2 }) });
8956
9035
  }
@@ -9009,6 +9088,14 @@ function deriveFileArtifactsFromMessages(messages) {
9009
9088
  const seen = /* @__PURE__ */ new Set();
9010
9089
  const out = [];
9011
9090
  for (const msg of messages) {
9091
+ if (msg.role === "system") {
9092
+ if (msg.systemKind !== "artifact") continue;
9093
+ const { artifactId, name } = unpackArtifactMeta(msg.systemMeta, msg.content);
9094
+ if (!artifactId || seen.has(`artifact:${artifactId}`)) continue;
9095
+ seen.add(`artifact:${artifactId}`);
9096
+ out.push({ kind: "artifact", label: name, ref: artifactId });
9097
+ continue;
9098
+ }
9012
9099
  if (msg.role !== "assistant" || !msg.toolCalls) continue;
9013
9100
  for (const tc of msg.toolCalls) {
9014
9101
  const status = effectiveStatus(tc);
@@ -9028,16 +9115,6 @@ function deriveFileArtifactsFromMessages(messages) {
9028
9115
  });
9029
9116
  continue;
9030
9117
  }
9031
- if (tc.toolName === "create_artifact") {
9032
- const name = typeof args.name === "string" ? args.name : "";
9033
- if (!name || seen.has(`artifact:${name}`)) continue;
9034
- seen.add(`artifact:${name}`);
9035
- out.push({
9036
- kind: "artifact",
9037
- label: name,
9038
- ref: name
9039
- });
9040
- }
9041
9118
  }
9042
9119
  }
9043
9120
  return out;
@@ -9063,15 +9140,18 @@ function SimpleAssistantGroup({
9063
9140
  if (fromHarness && fromHarness.artifacts.length > 0) {
9064
9141
  return fromHarness;
9065
9142
  }
9143
+ if (turnComplete) {
9144
+ const derived = deriveFileArtifactsFromMessages(messages);
9145
+ if (derived.length > 0) {
9146
+ return {
9147
+ turnId: fromHarness?.turnId ?? "",
9148
+ recap: summaryPref === "show" ? fromHarness?.recap ?? "" : "",
9149
+ artifacts: derived
9150
+ };
9151
+ }
9152
+ }
9066
9153
  if (summaryPref === "hide") return null;
9067
- if (!turnComplete) return fromHarness;
9068
- const derived = deriveFileArtifactsFromMessages(messages);
9069
- if (derived.length === 0) return fromHarness;
9070
- return {
9071
- turnId: fromHarness?.turnId ?? "",
9072
- recap: fromHarness?.recap ?? "",
9073
- artifacts: derived
9074
- };
9154
+ return fromHarness;
9075
9155
  })();
9076
9156
  return /* @__PURE__ */ jsxRuntime.jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsxRuntime.jsxs(MessageContent, { children: [
9077
9157
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: messages.map((message) => {
@@ -9089,10 +9169,11 @@ function SimpleAssistantGroup({
9089
9169
  }
9090
9170
  if (message === tail && tailIsTextOnly && finalText) return null;
9091
9171
  const rawContent = (message.content ?? "").trim();
9092
- const { action, inferredNarration } = stripAndParseNextAction(rawContent);
9172
+ const { action, inferredNarration, cleaned } = stripAndParseNextAction(rawContent);
9093
9173
  const narrationLine = action ? action.body.trim().toLowerCase() === "done" ? null : action.body : inferredNarration;
9174
+ const askBody = hasUserFacingAskContent(message) ? cleaned : null;
9094
9175
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
9095
- narrationLine && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: narrationLine }),
9176
+ askBody ? /* @__PURE__ */ jsxRuntime.jsx(MessageResponse, { children: askBody }) : narrationLine ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground", children: narrationLine }) : null,
9096
9177
  /* @__PURE__ */ jsxRuntime.jsx(
9097
9178
  IterationGroup,
9098
9179
  {
@@ -9157,7 +9238,7 @@ function AssistantGroup({
9157
9238
  entries = groupWebSearchEntries(entries);
9158
9239
  for (let i = entries.length - 1; i >= 0; i--) {
9159
9240
  const entry = entries[i];
9160
- if (entry?.kind === "text") {
9241
+ if (entry?.kind === "text" && !hasUserFacingAskContent(entry.msg)) {
9161
9242
  entries[i] = { ...entry, isFinalTurnText: true };
9162
9243
  break;
9163
9244
  }
@@ -9253,7 +9334,10 @@ function ChatThread({
9253
9334
  onViewModeChange
9254
9335
  }) {
9255
9336
  const groups = react.useMemo(() => groupMessages(messages), [messages]);
9256
- const showWorkingOnIt = useDelayedRunningIndicator(isRunning);
9337
+ const awaitingInput = react.useMemo(() => isAwaitingUserInput(messages), [messages]);
9338
+ const showWorkingOnIt = useDelayedRunningIndicator(isRunning) && !awaitingInput;
9339
+ const composerDisabled = disabled || awaitingInput;
9340
+ const composerDisabledReason = awaitingInput ? "Answer the question above to continue." : disabledReason;
9257
9341
  const artifactFallbacks = react.useMemo(() => {
9258
9342
  const fallbacks = {};
9259
9343
  const createArtifactToolCallIds = [];
@@ -9356,12 +9440,12 @@ function ChatThread({
9356
9440
  ] }),
9357
9441
  /* @__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: [
9358
9442
  retryIndicator && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsx(RetryBanner, { indicator: retryIndicator }) }),
9359
- disabled && disabledReason ? /* @__PURE__ */ jsxRuntime.jsx(
9443
+ composerDisabled && composerDisabledReason ? /* @__PURE__ */ jsxRuntime.jsx(
9360
9444
  "div",
9361
9445
  {
9362
9446
  className: "rounded border border-line bg-muted/40 px-3 py-2 text-sm text-foreground/60",
9363
9447
  role: "status",
9364
- children: disabledReason
9448
+ children: composerDisabledReason
9365
9449
  }
9366
9450
  ) : /* @__PURE__ */ jsxRuntime.jsx(
9367
9451
  ChatComposer,
@@ -9369,8 +9453,8 @@ function ChatThread({
9369
9453
  onSend,
9370
9454
  onStop,
9371
9455
  isRunning,
9372
- disabled,
9373
- disabledReason,
9456
+ disabled: composerDisabled,
9457
+ disabledReason: composerDisabledReason,
9374
9458
  tokenUsage,
9375
9459
  onComposerError,
9376
9460
  showBrowser,