feat: live progress updates during orchestrator tool loop
The thinking bubble now shows real-time status instead of a static spinner: ⚡ Round 1 — thinking… ⚡ Round 1 — web_search ⚡ Round 2 — thinking… ⚡ Generating response… Implementation: async on_progress callback passed from _run_job into both orchestrators (_run_from_messages / _run_from_contents). Callback writes to job["progress"] under the jobs lock; poll responses include the field; app.js displays it in the thinking bubble when present. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,7 @@ async def run(
|
||||
max_risk: str | None = None,
|
||||
risk_whitelist: list[str] | None = None,
|
||||
risk_blacklist: list[str] | None = None,
|
||||
on_progress=None, # async (str) -> None; called with live status updates
|
||||
) -> OrchestratorResult:
|
||||
"""
|
||||
Run a tool-enabled task using an OpenAI-compatible API.
|
||||
@@ -117,6 +118,7 @@ async def run(
|
||||
confirm_allow=_confirm_allow,
|
||||
confirm_deny=_confirm_deny,
|
||||
starting_round=0,
|
||||
on_progress=on_progress,
|
||||
)
|
||||
|
||||
if checkpoint:
|
||||
@@ -307,6 +309,7 @@ async def _run_from_messages(
|
||||
confirm_deny: frozenset,
|
||||
starting_round: int = 0,
|
||||
tool_list: list[str] | None = None,
|
||||
on_progress=None,
|
||||
) -> tuple[str, OrchestrateCheckpoint | None]:
|
||||
"""
|
||||
Run the OpenAI ReAct loop from the current messages state.
|
||||
@@ -323,6 +326,8 @@ async def _run_from_messages(
|
||||
est = _estimate_tokens(messages)
|
||||
logger.info("OpenAI orchestrator round %d / %d model=%s ~%d tokens",
|
||||
round_num + 1, effective_limit, model_name, est)
|
||||
if on_progress:
|
||||
await on_progress(f"Round {round_num + 1} — thinking…")
|
||||
|
||||
call_kwargs: dict = {"model": model_name, "messages": messages}
|
||||
if active_tools:
|
||||
@@ -373,6 +378,8 @@ async def _run_from_messages(
|
||||
pending_tools.append({"name": name, "args": args_parsed, "tool_call_id": tc.id})
|
||||
logger.info("Tool %s blocked — confirmation required", name)
|
||||
else:
|
||||
if on_progress:
|
||||
await on_progress(f"Round {round_num + 1} — {name}")
|
||||
result_str = await _execute_tool(name, tc.function.arguments, user_role, tool_list)
|
||||
logger.info("Tool %s → %d chars", name, len(result_str))
|
||||
executed_results.append({"name": name, "args": args_parsed, "result": result_str, "tool_call_id": tc.id})
|
||||
@@ -415,6 +422,8 @@ async def _run_from_messages(
|
||||
return final_response, checkpoint
|
||||
|
||||
else:
|
||||
if on_progress:
|
||||
await on_progress("Generating response…")
|
||||
final_response = msg.content or ""
|
||||
logger.info(
|
||||
"OpenAI orchestrator done after %d round(s). Tools used: %d",
|
||||
|
||||
Reference in New Issue
Block a user