@invergent/agent-chat-react 1.5.4 → 1.5.5

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.d.cts CHANGED
@@ -113,6 +113,7 @@ interface AgentChatState {
113
113
  sessionDone: boolean;
114
114
  hadDeltas: boolean;
115
115
  terminal: boolean;
116
+ workspaceRefreshKey: number;
116
117
  }
117
118
  type AgentChatArtifactKind = "markdown" | "table" | "chart" | "html" | "svg";
118
119
  interface AgentChatArtifactMeta {
@@ -315,6 +316,7 @@ interface AgentChatRuntimeApi {
315
316
  isLoadingHistory: boolean;
316
317
  tokenUsage: AgentChatTokenUsage;
317
318
  retryIndicator: AgentChatRetryIndicator | null;
319
+ workspaceRefreshKey: number;
318
320
  send(content: string): Promise<void>;
319
321
  stop(): Promise<void>;
320
322
  retry(): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -113,6 +113,7 @@ interface AgentChatState {
113
113
  sessionDone: boolean;
114
114
  hadDeltas: boolean;
115
115
  terminal: boolean;
116
+ workspaceRefreshKey: number;
116
117
  }
117
118
  type AgentChatArtifactKind = "markdown" | "table" | "chart" | "html" | "svg";
118
119
  interface AgentChatArtifactMeta {
@@ -315,6 +316,7 @@ interface AgentChatRuntimeApi {
315
316
  isLoadingHistory: boolean;
316
317
  tokenUsage: AgentChatTokenUsage;
317
318
  retryIndicator: AgentChatRetryIndicator | null;
319
+ workspaceRefreshKey: number;
318
320
  send(content: string): Promise<void>;
319
321
  stop(): Promise<void>;
320
322
  retry(): Promise<void>;
package/dist/index.js CHANGED
@@ -3307,7 +3307,7 @@ function ClarifyLocked({
3307
3307
  function ArtifactToolBlock({ tc }) {
3308
3308
  const args = parseArgs(tc.args) ?? {};
3309
3309
  const status = effectiveStatus(tc);
3310
- const label = status === "running" ? "Creating artifact\u2026" : status === "error" ? "Tried to create" : "Created";
3310
+ const label = status === "running" ? "Creating artifact\u2026" : status === "error" ? "Creating artifact\u2026" : "Created";
3311
3311
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-sm ", children: [
3312
3312
  /* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: label }),
3313
3313
  args.name && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground truncate", children: args.name })
@@ -5942,14 +5942,17 @@ function TimelineEntryItem({
5942
5942
  ] });
5943
5943
  }
5944
5944
  if (entry.kind === "tool") {
5945
- const failureSummary = effectiveStatus(entry.tc) === "error" ? toolErrorSummary(entry.tc.result) : "";
5945
+ const rawStatus = effectiveStatus(entry.tc);
5946
+ const hideArtifactFailure = rawStatus === "error" && entry.tc.toolName === "create_artifact";
5947
+ const indicatorStatus = hideArtifactFailure ? "running" : rawStatus;
5948
+ const failureSummary = rawStatus === "error" && !hideArtifactFailure ? toolErrorSummary(entry.tc.result) : "";
5946
5949
  return /* @__PURE__ */ jsxs(TimelineItem, { step, children: [
5947
5950
  /* @__PURE__ */ jsxs(TimelineHeader, { children: [
5948
5951
  /* @__PURE__ */ jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
5949
5952
  /* @__PURE__ */ jsx(
5950
5953
  TimelineIndicator,
5951
5954
  {
5952
- className: cn("size-2 border-none", statusColorClass(effectiveStatus(entry.tc)))
5955
+ className: cn("size-2 border-none", statusColorClass(indicatorStatus))
5953
5956
  }
5954
5957
  )
5955
5958
  ] }),
@@ -6007,13 +6010,14 @@ function TimelineEntryItem({
6007
6010
  /* @__PURE__ */ jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
6008
6011
  /* @__PURE__ */ jsx(TimelineIndicator, { className: "size-2 border-none bg-primary animate-pulse" })
6009
6012
  ] }),
6010
- /* @__PURE__ */ jsx(TimelineContent, { children: /* @__PURE__ */ jsx(Shimmer, { duration: 5, className: "text-sm text-foreground", children: "Working on it..." }) })
6013
+ /* @__PURE__ */ jsx(TimelineContent, { children: /* @__PURE__ */ jsx(Shimmer, { duration: 3, spread: 3, className: "text-sm", children: "Working on it..." }) })
6011
6014
  ] });
6012
6015
  }
6013
6016
  function AssistantGroup({
6014
6017
  messages,
6015
6018
  lastGlobalIndex,
6016
6019
  totalMessages,
6020
+ isRunning,
6017
6021
  sessionId,
6018
6022
  onFileSelect,
6019
6023
  onRetry
@@ -6023,6 +6027,15 @@ function AssistantGroup({
6023
6027
  const isLast = i === messages.length - 1 && lastGlobalIndex === totalMessages - 1;
6024
6028
  entries.push(...messageToEntries(messages[i], isLast));
6025
6029
  }
6030
+ const isTailGroup = lastGlobalIndex === totalMessages - 1;
6031
+ const lastEntry = entries[entries.length - 1];
6032
+ const hasRunningTool = entries.some(
6033
+ (e) => e.kind === "tool" && e.tc.status === "running"
6034
+ );
6035
+ const tailMsg = messages[messages.length - 1];
6036
+ if (isTailGroup && isRunning && !hasRunningTool && lastEntry?.kind !== "thinking") {
6037
+ entries.push({ kind: "thinking", key: `${tailMsg.id}-tail-thinking` });
6038
+ }
6026
6039
  const tail = messages[messages.length - 1];
6027
6040
  const showErrorInfo = tail && tail.role === "assistant" && tail.status === "error" && !!tail.errorInfo;
6028
6041
  return /* @__PURE__ */ jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsxs(MessageContent, { children: [
@@ -6146,6 +6159,7 @@ function ChatThread({
6146
6159
  messages: group.messages,
6147
6160
  lastGlobalIndex: group.lastGlobalIndex,
6148
6161
  totalMessages: messages.length,
6162
+ isRunning,
6149
6163
  sessionId,
6150
6164
  onFileSelect,
6151
6165
  onRetry: groupRetry
@@ -6153,7 +6167,7 @@ function ChatThread({
6153
6167
  group.messages[0].id
6154
6168
  );
6155
6169
  }),
6156
- isRunning && messages.length > 0 && messages[messages.length - 1].role === "user" && /* @__PURE__ */ jsx(Message, { from: "assistant", children: /* @__PURE__ */ jsx(MessageContent, { children: /* @__PURE__ */ jsx(Shimmer, { duration: 5, className: "text-sm", children: "Working on it..." }) }) })
6170
+ 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..." }) }) })
6157
6171
  ] }) }),
6158
6172
  /* @__PURE__ */ jsx(ConversationScrollButton, {})
6159
6173
  ] }),
@@ -6842,6 +6856,7 @@ function WorkspacePanel({
6842
6856
  onSelectedPathChange,
6843
6857
  collapsed = false,
6844
6858
  onCollapsedChange,
6859
+ refreshSignal = 0,
6845
6860
  disabled = false
6846
6861
  }) {
6847
6862
  const fileInputRef = useRef(null);
@@ -6921,6 +6936,13 @@ function WorkspacePanel({
6921
6936
  useEffect(() => {
6922
6937
  void fetchTree();
6923
6938
  }, [fetchTree]);
6939
+ useEffect(() => {
6940
+ if (!sessionId || refreshSignal === 0) return;
6941
+ const timer = setTimeout(() => {
6942
+ void fetchTree();
6943
+ }, 300);
6944
+ return () => clearTimeout(timer);
6945
+ }, [refreshSignal, sessionId, fetchTree]);
6924
6946
  useEffect(() => {
6925
6947
  if (!sessionId) {
6926
6948
  setFile(null);
@@ -7261,6 +7283,12 @@ function ConfirmDialog({
7261
7283
  }
7262
7284
 
7263
7285
  // src/runtime/events.ts
7286
+ var WORKSPACE_MUTATING_TOOLS = /* @__PURE__ */ new Set([
7287
+ "terminal",
7288
+ "write_file",
7289
+ "patch",
7290
+ "execute_code"
7291
+ ]);
7264
7292
  var AGENT_CHAT_LISTENED_EVENTS = [
7265
7293
  "user.message",
7266
7294
  "llm.request",
@@ -7309,7 +7337,8 @@ function createInitialAgentChatState(options = {}) {
7309
7337
  lastEventId: 0,
7310
7338
  sessionDone: false,
7311
7339
  hadDeltas: false,
7312
- terminal: false
7340
+ terminal: false,
7341
+ workspaceRefreshKey: 0
7313
7342
  };
7314
7343
  }
7315
7344
  function applyAgentChatEvent(state, event) {
@@ -7371,11 +7400,17 @@ function applyAgentChatEvent(state, event) {
7371
7400
  return applyLlmThinking(nextState, event);
7372
7401
  case "tool.call":
7373
7402
  return applyToolCall(nextState, event);
7374
- case "tool.result":
7375
- return withMessages(
7376
- nextState,
7377
- applyToolResult(nextState.messages, event.data)
7378
- );
7403
+ case "tool.result": {
7404
+ const toolCallId = stringValue(event.data.tool_call_id);
7405
+ const toolName = findToolNameById(nextState.messages, toolCallId);
7406
+ const messages = applyToolResult(nextState.messages, event.data);
7407
+ const mutatesWorkspace = toolName !== null && WORKSPACE_MUTATING_TOOLS.has(toolName);
7408
+ return {
7409
+ ...nextState,
7410
+ messages,
7411
+ workspaceRefreshKey: mutatesWorkspace ? nextState.workspaceRefreshKey + 1 : nextState.workspaceRefreshKey
7412
+ };
7413
+ }
7379
7414
  case "harness.wake":
7380
7415
  case "llm.request":
7381
7416
  return nextState.terminal ? nextState : { ...nextState, isRunning: true };
@@ -7815,6 +7850,14 @@ function hasUserAfterIndex(messages, idx) {
7815
7850
  }
7816
7851
  return false;
7817
7852
  }
7853
+ function findToolNameById(messages, toolCallId) {
7854
+ if (!toolCallId) return null;
7855
+ for (let i = messages.length - 1; i >= 0; i--) {
7856
+ const tc = messages[i]?.toolCalls?.find((c) => c.id === toolCallId);
7857
+ if (tc) return tc.toolName;
7858
+ }
7859
+ return null;
7860
+ }
7818
7861
  function findLatestConsultExpertCall(messages) {
7819
7862
  for (let i = messages.length - 1; i >= 0; i--) {
7820
7863
  const msg = messages[i];
@@ -8065,6 +8108,7 @@ function useAgentChatRuntime({
8065
8108
  isLoadingHistory: state.isLoadingHistory,
8066
8109
  tokenUsage: state.tokenUsage,
8067
8110
  retryIndicator: state.retryIndicator,
8111
+ workspaceRefreshKey: state.workspaceRefreshKey,
8068
8112
  send,
8069
8113
  stop,
8070
8114
  retry,
@@ -8150,6 +8194,7 @@ function AgentChat({
8150
8194
  onSelectedPathChange: setWorkspacePath,
8151
8195
  collapsed: workspaceCollapsed,
8152
8196
  onCollapsedChange: setWorkspaceCollapsed,
8197
+ refreshSignal: runtime.workspaceRefreshKey,
8153
8198
  disabled
8154
8199
  }
8155
8200
  )
@@ -8254,6 +8299,7 @@ function TreeNodeRow({
8254
8299
  const hasChildren = entry.children.length > 0;
8255
8300
  const isActive = entry.id === activeSessionId;
8256
8301
  const isRunning = entry.status === "active";
8302
+ const isSubAgent = entry.parentId != null;
8257
8303
  const title = entry.title ?? "New session";
8258
8304
  const subtitle = [
8259
8305
  entry.model ?? "default",
@@ -8293,7 +8339,7 @@ function TreeNodeRow({
8293
8339
  /* @__PURE__ */ jsx("div", { className: "text-sm truncate", children: title }),
8294
8340
  /* @__PURE__ */ jsx("div", { className: "text-xs text-faint truncate", children: subtitle })
8295
8341
  ] }),
8296
- isRunning && canStop && /* @__PURE__ */ jsx(
8342
+ isRunning && canStop && isSubAgent && /* @__PURE__ */ jsx(
8297
8343
  "button",
8298
8344
  {
8299
8345
  type: "button",