Skip to content

feat(agentapi): stream coalesced tool-call events in SSE chat responses - #99

Open
fepfitra wants to merge 6 commits into
anvie:mainfrom
fepfitra:feat/agentapi-tool-log-clean
Open

feat(agentapi): stream coalesced tool-call events in SSE chat responses#99
fepfitra wants to merge 6 commits into
anvie:mainfrom
fepfitra:feat/agentapi-tool-log-clean

Conversation

@fepfitra

@fepfitra fepfitra commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Problem

The agentapi streaming chat endpoint (/plugin/agentapi/v1/chat/completions with stream: true) only forwards llm_response_chunk and turn_complete events. Streaming clients can show the agent's text but have NO visibility into what the agent is DOING (running bash, editing files, searching the web). Tool execution is a black box during long agent turns.

Fix

Subscribe to the existing tool_executed event stream, coalesce tool calls per session into a 5-second window (mirroring the Telegram channel pattern from PR #95), and emit inline SSE events while the stream is open:

data: {"type":"tool","tool_name":"bash (2x), python (1x)","has_error":false}
  • A 100-tool loop collapses to a handful of lines, not one per call.
  • has_error surfaces failures (client can style them ⚠️).
  • The type: "tool" field distinguishes tool events from normal choices[].delta.content chunks.
  • Cleanup: tool_executed is unsubscribed in the same finally block as the other events.

Verification

python -c 'import ast; ast.parse(...)' — syntax OK. Live-tested after restart: tool calls appear as compact chips in the chat while the agent works.

fepfitra and others added 6 commits August 6, 2026 14:03
Subscribe to tool_executed events, coalesce per session into a 5s window
(mirrors the Telegram channel pattern), and emit inline SSE events like
{"type":"tool","tool_name":"bash (2x)","has_error":false} so
streaming chat clients can show what the agent is doing.
The AgentAPI plugin authenticates via its own Bearer token, but the
global enforce_auth before_request 302s every non-/api path to the
login page — breaking /agentapi/v1/* for token-authenticated clients.
- flush pending coalesced tool events when the turn completes so the
  client sees them before the stream closes (the 5s window may not have
  elapsed)
- actually unsubscribe on_tool_executed in the finally block (was
  leaking, off() mapped every event to on_chunk/on_turn_complete)
The queue loop exits after the sentinel, so a put_nowait'd tool item
would never be consumed — pop the pending entry and yield it inline.
handle_message returns response=None immediately when
message_buffer_seconds > 0 (buffered path). Non-streaming
chat/completions then formatted content:null, breaking clients
that parse choices[0].message.content (e.g. pitura-dashboard:
'could not read agent reply').

When response is empty, poll the session chatlog for the
assistant reply anchored after this message's user row
(120s deadline, 300ms interval).
handle_message returns None for buffered/async agents — the real reply
arrives later via event_stream (llm_response_chunk/turn_complete).
Only enqueue the sentinel when a real response was returned; otherwise
stay subscribed or the reply events are lost (SSE shows only [DONE]).
@fepfitra
fepfitra force-pushed the feat/agentapi-tool-log-clean branch from 9de1ba5 to fd59213 Compare August 6, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant