akseljoonas HF Staff commited on
Commit
c68afb6
Β·
1 Parent(s): dd8076b

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

Browse files
agent/core/agent_loop.py CHANGED
@@ -232,6 +232,7 @@ class Handlers:
232
  # Agentic loop - continue until model doesn't call tools or max iterations is reached
233
  iteration = 0
234
  final_response = None
 
235
 
236
  while iteration < max_iterations:
237
  # ── Cancellation check: before LLM call ──
@@ -509,11 +510,12 @@ class Handlers:
509
  data={"error": str(e) + "\n" + traceback.format_exc()},
510
  )
511
  )
 
512
  break
513
 
514
  if session.is_cancelled:
515
  await session.send_event(Event(event_type="interrupted"))
516
- else:
517
  await session.send_event(
518
  Event(
519
  event_type="turn_complete",
 
232
  # Agentic loop - continue until model doesn't call tools or max iterations is reached
233
  iteration = 0
234
  final_response = None
235
+ errored = False
236
 
237
  while iteration < max_iterations:
238
  # ── Cancellation check: before LLM call ──
 
510
  data={"error": str(e) + "\n" + traceback.format_exc()},
511
  )
512
  )
513
+ errored = True
514
  break
515
 
516
  if session.is_cancelled:
517
  await session.send_event(Event(event_type="interrupted"))
518
+ elif not errored:
519
  await session.send_event(
520
  Event(
521
  event_type="turn_complete",
eval/hf_agent_connector.py CHANGED
@@ -29,7 +29,7 @@ class AgentResponseGenerator:
29
  returns the assistant's final message.
30
  """
31
 
32
- def __init__(self, config_path: str | Path, max_iterations: int = 10) -> None:
33
  self.config_path = _resolve_project_path(config_path)
34
  self.config: Config = load_config(str(self.config_path))
35
  self.max_iterations = max_iterations
 
29
  returns the assistant's final message.
30
  """
31
 
32
+ def __init__(self, config_path: str | Path, max_iterations: int = 300) -> None:
33
  self.config_path = _resolve_project_path(config_path)
34
  self.config: Config = load_config(str(self.config_path))
35
  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
  }