Skip to content

Commit 55bfc7c

Browse files
committed
refac
1 parent 4113b15 commit 55bfc7c

1 file changed

Lines changed: 52 additions & 40 deletions

File tree

backend/open_webui/utils/middleware.py

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,55 @@ def is_opening_code_block(content):
401401
return len(backtick_segments) > 1 and len(backtick_segments) % 2 == 0
402402

403403

404+
_OPENAI_TOOL_DISPLAY_NAMES = {
405+
'web_search_call': 'Web Search',
406+
'file_search_call': 'File Search',
407+
'computer_call': 'Computer Use',
408+
}
409+
410+
411+
def _render_openai_tool_call_handler(item: dict, done: bool) -> str:
412+
"""Render an OpenAI Responses API server-side tool item as a <details> block.
413+
414+
Handles web_search_call, file_search_call, and computer_call items whose
415+
schemas are defined in the openai-python SDK (generated from OpenAPI spec).
416+
"""
417+
item_type = item.get('type', '')
418+
call_id = item.get('id', '')
419+
display_name = _OPENAI_TOOL_DISPLAY_NAMES.get(item_type, item_type)
420+
421+
# Build a short summary of what the tool did
422+
summary = ''
423+
if item_type == 'web_search_call':
424+
action = item.get('action', {})
425+
if isinstance(action, dict):
426+
atype = action.get('type', '')
427+
if atype == 'search':
428+
queries = action.get('queries') or []
429+
query = action.get('query', '')
430+
summary = f'Search: {", ".join(str(q) for q in queries)}' if queries else (f'Search: {query}' if query else '')
431+
elif atype == 'open_page':
432+
summary = f'Open page: {action.get("url", "")}' if action.get('url') else ''
433+
elif atype == 'find_in_page':
434+
summary = f'Find in page: {action.get("pattern", "")}' if action.get('pattern') else ''
435+
elif item_type == 'file_search_call':
436+
queries = item.get('queries', [])
437+
if queries:
438+
summary = f'Queries: {", ".join(str(q) for q in queries)}'
439+
elif item_type == 'computer_call':
440+
action = item.get('action')
441+
actions = item.get('actions')
442+
if isinstance(action, dict):
443+
summary = f'Action: {action.get("type", "unknown")}'
444+
elif isinstance(actions, list) and actions:
445+
summary = f'Actions: {", ".join(a.get("type", "?") for a in actions if isinstance(a, dict))}'
446+
447+
escaped_name = html.escape(display_name)
448+
if done:
449+
return f'<details type="tool_calls" done="true" id="{call_id}" name="{escaped_name}" arguments="">\n<summary>Tool Executed</summary>\n{html.escape(summary)}\n</details>\n'
450+
return f'<details type="tool_calls" done="false" id="{call_id}" name="{escaped_name}" arguments="">\n<summary>Executing...</summary>\n</details>\n'
451+
452+
404453
def serialize_output(output: list) -> str:
405454
"""
406455
Convert OR-aligned output items to HTML for display.
@@ -452,49 +501,12 @@ def serialize_output(output: list) -> str:
452501
# Already handled inline with function_call above
453502
pass
454503

455-
elif item_type in ('web_search_call', 'file_search_call', 'computer_call'):
456-
# OpenAI Responses API built-in server-side tool output items.
457-
# These are emitted when the model uses native tools (web_search,
458-
# file_search, computer_use) through the Responses API. Render as
459-
# collapsible tool call blocks matching the function_call pattern.
504+
elif item_type in _OPENAI_TOOL_DISPLAY_NAMES:
460505
if content and not content.endswith('\n'):
461506
content += '\n'
462-
463-
call_id = item.get('id', '')
464507
status = item.get('status', 'in_progress')
465-
466-
# Derive a human-readable display name
467-
display_names = {
468-
'web_search_call': 'Web Search',
469-
'file_search_call': 'File Search',
470-
'computer_call': 'Computer Use',
471-
}
472-
display_name = display_names.get(item_type, item_type)
473-
474-
# Extract a summary of what the tool did for the details body
475-
summary_text = ''
476-
if item_type == 'web_search_call':
477-
action = item.get('action', {})
478-
if isinstance(action, dict):
479-
query = action.get('query', '')
480-
if query:
481-
summary_text = f'Query: {query}'
482-
elif item_type == 'file_search_call':
483-
queries = item.get('queries', [])
484-
if queries:
485-
summary_text = f'Queries: {", ".join(str(q) for q in queries)}'
486-
elif item_type == 'computer_call':
487-
action = item.get('action', {})
488-
if isinstance(action, dict):
489-
action_type = action.get('type', '')
490-
if action_type:
491-
summary_text = f'Action: {action_type}'
492-
493-
done = status == 'completed' or idx != len(output) - 1
494-
if done:
495-
content += f'<details type="tool_calls" done="true" id="{call_id}" name="{html.escape(display_name)}" arguments="">\n<summary>Tool Executed</summary>\n{html.escape(summary_text)}\n</details>\n'
496-
else:
497-
content += f'<details type="tool_calls" done="false" id="{call_id}" name="{html.escape(display_name)}" arguments="">\n<summary>Executing...</summary>\n</details>\n'
508+
done = status in ('completed', 'failed', 'incomplete') or idx != len(output) - 1
509+
content += _render_openai_tool_call_handler(item, done)
498510

499511
elif item_type == 'reasoning':
500512
reasoning_content = ''

0 commit comments

Comments
 (0)