akseljoonas HF Staff commited on
Commit
78f0201
·
1 Parent(s): 555a204

feat: resolve sandbox file paths and show tool description in status

Browse files

- Extract resolve_sandbox_script utility in sandbox_tool.py to detect
file paths and read content from sandbox via cat
- Resolve script paths before sending approval_required event so the
frontend receives actual file content for display and editing
- Show tool description arg in status chip and activity bar instead of
generic "running" / "Running bash" text

frontend/src/components/Chat/ActivityStatusBar.tsx CHANGED
@@ -21,7 +21,7 @@ function statusLabel(status: ActivityStatus): string {
21
  switch (status.type) {
22
  case 'thinking': return 'Thinking';
23
  case 'streaming': return 'Writing';
24
- case 'tool': return TOOL_LABELS[status.toolName] || `Running ${status.toolName}`;
25
  case 'waiting-approval': return 'Waiting for approval';
26
  default: return '';
27
  }
 
21
  switch (status.type) {
22
  case 'thinking': return 'Thinking';
23
  case 'streaming': return 'Writing';
24
+ case 'tool': return status.description || TOOL_LABELS[status.toolName] || `Running ${status.toolName}`;
25
  case 'waiting-approval': return 'Waiting for approval';
26
  default: return '';
27
  }
frontend/src/components/Chat/ToolCallGroup.tsx CHANGED
@@ -496,7 +496,9 @@ export default function ToolCallGroup({ tools, approveTools }: ToolCallGroupProp
496
  const displayState = isPending && localDecision
497
  ? (localDecision.approved ? 'input-available' : 'output-denied')
498
  : state;
499
- const label = statusLabel(displayState as ToolPartState);
 
 
500
 
501
  // Parse job metadata from hf_jobs output and store
502
  const jobUrlFromStore = tool.toolName === 'hf_jobs' ? getJobUrl(tool.toolCallId) : undefined;
@@ -546,7 +548,7 @@ export default function ToolCallGroup({ tools, approveTools }: ToolCallGroupProp
546
  whiteSpace: 'nowrap',
547
  }}
548
  >
549
- {toolDisplayMap[tool.toolCallId] || String((tool.input as Record<string, unknown>)?.description || '') || tool.toolName}
550
  </Typography>
551
 
552
  {/* Status chip (non hf_jobs, or hf_jobs without final status) */}
 
496
  const displayState = isPending && localDecision
497
  ? (localDecision.approved ? 'input-available' : 'output-denied')
498
  : state;
499
+ const baseLabel = statusLabel(displayState as ToolPartState);
500
+ const toolDescription = (tool.input as Record<string, unknown>)?.description as string | undefined;
501
+ const label = baseLabel ? (toolDescription || baseLabel) : null;
502
 
503
  // Parse job metadata from hf_jobs output and store
504
  const jobUrlFromStore = tool.toolName === 'hf_jobs' ? getJobUrl(tool.toolCallId) : undefined;
 
548
  whiteSpace: 'nowrap',
549
  }}
550
  >
551
+ {toolDisplayMap[tool.toolCallId] || tool.toolName}
552
  </Typography>
553
 
554
  {/* Status chip (non hf_jobs, or hf_jobs without final status) */}
frontend/src/hooks/useAgentChat.ts CHANGED
@@ -195,8 +195,8 @@ export function useAgentChat({ sessionId, isActive, onReady, onError, onSessionD
195
  onStreaming: () => {
196
  if (isActiveRef.current) setActivityStatus({ type: 'streaming' });
197
  },
198
- onToolRunning: (toolName: string) => {
199
- if (isActiveRef.current) setActivityStatus({ type: 'tool', toolName });
200
  },
201
  }),
202
  // sessionId is the only real dependency — Zustand setters are stable
 
195
  onStreaming: () => {
196
  if (isActiveRef.current) setActivityStatus({ type: 'streaming' });
197
  },
198
+ onToolRunning: (toolName: string, description?: string) => {
199
+ if (isActiveRef.current) setActivityStatus({ type: 'tool', toolName, description });
200
  },
201
  }),
202
  // sessionId is the only real dependency — Zustand setters are stable
frontend/src/lib/ws-chat-transport.ts CHANGED
@@ -35,7 +35,7 @@ export interface SideChannelCallbacks {
35
  /** Called when assistant text starts streaming */
36
  onStreaming: () => void;
37
  /** Called when a tool starts running (non-plan) */
38
- onToolRunning: (toolName: string) => void;
39
  }
40
 
41
  // ---------------------------------------------------------------------------
@@ -499,7 +499,7 @@ export class WebSocketChatTransport implements ChatTransport<UIMessage> {
499
  this.enqueue({ type: 'tool-input-start', toolCallId, toolName, dynamic: true });
500
  this.enqueue({ type: 'tool-input-available', toolCallId, toolName, input: args, dynamic: true });
501
 
502
- this.sideChannel.onToolRunning(toolName);
503
  this.sideChannel.onToolCallPanel(toolName, args as Record<string, unknown>);
504
  break;
505
  }
 
35
  /** Called when assistant text starts streaming */
36
  onStreaming: () => void;
37
  /** Called when a tool starts running (non-plan) */
38
+ onToolRunning: (toolName: string, description?: string) => void;
39
  }
40
 
41
  // ---------------------------------------------------------------------------
 
499
  this.enqueue({ type: 'tool-input-start', toolCallId, toolName, dynamic: true });
500
  this.enqueue({ type: 'tool-input-available', toolCallId, toolName, input: args, dynamic: true });
501
 
502
+ this.sideChannel.onToolRunning(toolName, (args as Record<string, unknown>)?.description as string | undefined);
503
  this.sideChannel.onToolCallPanel(toolName, args as Record<string, unknown>);
504
  break;
505
  }
frontend/src/store/agentStore.ts CHANGED
@@ -41,7 +41,7 @@ export interface LLMHealthError {
41
  export type ActivityStatus =
42
  | { type: 'idle' }
43
  | { type: 'thinking' }
44
- | { type: 'tool'; toolName: string }
45
  | { type: 'waiting-approval' }
46
  | { type: 'streaming' };
47
 
 
41
  export type ActivityStatus =
42
  | { type: 'idle' }
43
  | { type: 'thinking' }
44
+ | { type: 'tool'; toolName: string; description?: string }
45
  | { type: 'waiting-approval' }
46
  | { type: 'streaming' };
47