Skip to content

fix(tools): carry the parked reply text in the WithOnPark callback#59

Merged
mudler merged 1 commit into
mainfrom
fix/onpark-carries-reply
Jun 9, 2026
Merged

fix(tools): carry the parked reply text in the WithOnPark callback#59
mudler merged 1 commit into
mainfrom
fix/onpark-carries-reply

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

Problem

The no-tool reply the model produces right before a park gate is recorded in the fragment, but embedders have no way to read it at park time: WithOnPark fires with no arguments.

nib worked around this by capturing the reasoning callback as "the reply that preceded the park" — but toolSelection fires that callback with resp.ReasoningContent (reasoning tokens, empty for most models), not the reply text, which travels separately as results.message. The result: any answer the model produces at a park boundary (e.g. the reply to a user follow-up injected while a detached sub-agent keeps the run parked) exists in the fragment but is never surfaced — to the user it looks like the injected message was silently ignored.

Fix

WithOnPark(func())WithOnPark(func(reply string)):

  • at the agents-still-running park gate, the callback receives the no-tool reply text recorded in the fragment just before the loop blocks;
  • at the sink-state park gate it receives "" (the reply is produced by the sink state after the loop, so there is no text yet).

TestExecuteTools_OnParkOnResumeFire now also asserts the parked reply is carried.

This is a signature change to an option introduced in #49; updating the only known consumer (nib) alongside.

🤖 Generated with Claude Code

The no-tool reply the model produces right before a park gate was only
recorded inside the fragment; embedders had no way to read it at park
time. nib worked around this by capturing the reasoning callback, but
toolSelection fires that callback with resp.ReasoningContent (reasoning
tokens, empty for most models), not the reply text — so parked replies
(e.g. the answer to a mid-run injected user message) were silently
dropped by the UI.

WithOnPark now passes the assistant reply text that preceded the park:
the no-tool reply at the agents-still-running gate, or "" at the
sink-state gate where the reply is produced after the loop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mudler mudler merged commit bf4010d into main Jun 9, 2026
2 of 3 checks passed
mudler added a commit to mudler/nib that referenced this pull request Jun 9, 2026
…w-ups (#31)

Two bugs made a message queued during a backgrounded sub-agent look
ignored:

1. Parked replies were invisible. The TUI surfaces a parked run's reply
   via OnParked, which captured cogito's reasoning callback as "the
   reply that preceded the park" — but that callback carries reasoning
   tokens (empty for most models), not the reply text. Any answer the
   model produced at a park boundary (e.g. to a follow-up injected while
   a detached agent kept the run alive) existed in the fragment but was
   never rendered. cogito's WithOnPark now passes the parked reply
   (mudler/cogito#59); the session forwards it and drops the lastReply
   hack.

2. End-of-run drain discarded unconsumed follow-ups. A queue entry
   released into the live run while its final LLM call was in flight
   was echoed to the transcript but never consumed — SendMessage's
   deferred channel drain silently threw it away. The session now
   tracks user-typed injections (InjectUser) and hands unconsumed ones
   back (TakeUndelivered); the TUI re-dispatches them as fresh turns
   ahead of the queue, without a second echo. System notices
   (shell-job completions, wake-ups) are still dropped by the drain so
   stale notices can't re-trigger finished work.

Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

2 participants