akseljoonas HF Staff commited on
Commit
b22c5f3
Β·
1 Parent(s): f765eb4

fix: properly close SDK message on error, show tool errorText

Browse files
agent/core/agent_loop.py CHANGED
@@ -240,6 +240,7 @@ class Handlers:
240
  # Agentic loop - continue until model doesn't call tools or max iterations is reached
241
  iteration = 0
242
  final_response = None
 
243
 
244
  while iteration < max_iterations:
245
  # ── Cancellation check: before LLM call ──
@@ -517,11 +518,12 @@ class Handlers:
517
  data={"error": str(e) + "\n" + traceback.format_exc()},
518
  )
519
  )
 
520
  break
521
 
522
  if session.is_cancelled:
523
  await session.send_event(Event(event_type="interrupted"))
524
- else:
525
  await session.send_event(
526
  Event(
527
  event_type="turn_complete",
 
240
  # Agentic loop - continue until model doesn't call tools or max iterations is reached
241
  iteration = 0
242
  final_response = None
243
+ errored = False
244
 
245
  while iteration < max_iterations:
246
  # ── Cancellation check: before LLM call ──
 
518
  data={"error": str(e) + "\n" + traceback.format_exc()},
519
  )
520
  )
521
+ errored = True
522
  break
523
 
524
  if session.is_cancelled:
525
  await session.send_event(Event(event_type="interrupted"))
526
+ elif not errored:
527
  await session.send_event(
528
  Event(
529
  event_type="turn_complete",
eval/hf_agent_connector.py CHANGED
@@ -30,7 +30,7 @@ class AgentResponseGenerator:
30
  returns the assistant's final message.
31
  """
32
 
33
- def __init__(self, config_path: str | Path, max_iterations: int = 10) -> None:
34
  self.config_path = _resolve_project_path(config_path)
35
  self.config: Config = load_config(str(self.config_path))
36
  self.max_iterations = max_iterations
 
30
  returns the assistant's final message.
31
  """
32
 
33
+ def __init__(self, config_path: str | Path, max_iterations: int = 300) -> None:
34
  self.config_path = _resolve_project_path(config_path)
35
  self.config: Config = load_config(str(self.config_path))
36
  self.max_iterations = max_iterations
frontend/src/components/Chat/ToolCallGroup.tsx CHANGED
@@ -371,13 +371,14 @@ export default function ToolCallGroup({ tools, approveTools }: ToolCallGroupProp
371
  const displayName = toolDisplayMap[tool.toolCallId] || tool.toolName;
372
 
373
  if (tool.toolName === 'hf_jobs' && args?.script) {
374
- const hasOutput = (tool.state === 'output-available' || tool.state === 'output-error') && tool.output;
 
375
  const scriptContent = getEditedScript(tool.toolCallId) || String(args.script);
376
  setPanel(
377
  {
378
  title: displayName,
379
  script: { content: scriptContent, language: 'python' },
380
- ...(hasOutput ? { output: { content: String(tool.output), language: 'markdown' } } : {}),
381
  parameters: { tool_call_id: tool.toolCallId },
382
  },
383
  hasOutput ? 'output' : 'script',
@@ -389,9 +390,10 @@ export default function ToolCallGroup({ tools, approveTools }: ToolCallGroupProp
389
 
390
  const inputSection = args ? { content: JSON.stringify(args, null, 2), language: 'json' } : undefined;
391
 
392
- if ((tool.state === 'output-available' || tool.state === 'output-error') && tool.output) {
 
393
  let language = 'text';
394
- const content = String(tool.output);
395
  if (content.trim().startsWith('{') || content.trim().startsWith('[')) language = 'json';
396
  else if (content.includes('```')) language = 'markdown';
397
 
 
371
  const displayName = toolDisplayMap[tool.toolCallId] || tool.toolName;
372
 
373
  if (tool.toolName === 'hf_jobs' && args?.script) {
374
+ const jobOutput = tool.output ?? (tool.state === 'output-error' ? (tool as Record<string, unknown>).errorText : undefined);
375
+ const hasOutput = (tool.state === 'output-available' || tool.state === 'output-error') && jobOutput;
376
  const scriptContent = getEditedScript(tool.toolCallId) || String(args.script);
377
  setPanel(
378
  {
379
  title: displayName,
380
  script: { content: scriptContent, language: 'python' },
381
+ ...(hasOutput ? { output: { content: String(jobOutput), language: 'markdown' } } : {}),
382
  parameters: { tool_call_id: tool.toolCallId },
383
  },
384
  hasOutput ? 'output' : 'script',
 
390
 
391
  const inputSection = args ? { content: JSON.stringify(args, null, 2), language: 'json' } : undefined;
392
 
393
+ const outputText = tool.output ?? (tool.state === 'output-error' ? (tool as Record<string, unknown>).errorText : undefined);
394
+ if ((tool.state === 'output-available' || tool.state === 'output-error') && outputText) {
395
  let language = 'text';
396
+ const content = String(outputText);
397
  if (content.trim().startsWith('{') || content.trim().startsWith('[')) language = 'json';
398
  else if (content.includes('```')) language = 'markdown';
399
 
frontend/src/lib/sse-chat-transport.ts CHANGED
@@ -94,6 +94,9 @@ function createEventToChunkStream(sideChannel: SideChannelCallbacks): TransformS
94
  break;
95
 
96
  case 'shutdown':
 
 
 
97
  sideChannel.onShutdown();
98
  break;
99
 
@@ -243,8 +246,10 @@ function createEventToChunkStream(sideChannel: SideChannelCallbacks): TransformS
243
 
244
  case 'error': {
245
  const errorMsg = (event.data?.error as string) || 'Unknown error';
 
 
 
246
  sideChannel.onError(errorMsg);
247
- controller.enqueue({ type: 'error', errorText: errorMsg });
248
  sideChannel.onProcessingDone();
249
  break;
250
  }
 
94
  break;
95
 
96
  case 'shutdown':
97
+ endTextPart(controller);
98
+ controller.enqueue({ type: 'finish-step' });
99
+ controller.enqueue({ type: 'finish', finishReason: 'stop' });
100
  sideChannel.onShutdown();
101
  break;
102
 
 
246
 
247
  case 'error': {
248
  const errorMsg = (event.data?.error as string) || 'Unknown error';
249
+ endTextPart(controller);
250
+ controller.enqueue({ type: 'finish-step' });
251
+ controller.enqueue({ type: 'finish', finishReason: 'error' });
252
  sideChannel.onError(errorMsg);
 
253
  sideChannel.onProcessingDone();
254
  break;
255
  }