feat: add turn admission hook#214
Conversation
6b1602b to
8deff5c
Compare
frostming
left a comment
There was a problem hiding this comment.
Not complete reviewed yet. I think we should first resolve the fundamental design choice.
b492bde to
9f1ea2c
Compare
There was a problem hiding this comment.
I thought of another important issue that needs to be discussed. Since bub allows parallel agent runs within a single session, steering should actually be done on a per-thread(forked tape) basis rather than per-session. We can call the unit that shares the tape a "session," and call a running agent loop a "thread."
For example, if threads A and B are running simultaneously, when a steering message is sent, you need to know which thread it belongs to. Based on this, I think the data structure needs to be modified.
|
@frostming That makes sense, and it matches the concern I mentioned earlier: this PR currently treats steering as session-scoped, but there is an unresolved question around whether steering should target a session, an active turn, or a forked tape/thread. I am not sure My current leaning is to keep admission as the place that makes a message available as steering input, while leaving selection/consumption to the I think it may be worth discussing how |
|
I think a short online discussion would be more appropriate. Can you share with your time slot for this, and we can organize one. cc @PsiACE |
9f1ea2c to
6bb94fc
Compare
|
Thanks for the discussion. My understanding of the agreed direction is:
cc: @PsiACE @frostming |
|
I updated the PR description to match the discussed direction and the current |
Motivation
ChannelManagercurrently schedules each inbound channel message as a new turn immediately. The default concurrent behavior is simple, but plugins do not have a hook to decide whether the next message for an already-active session should be processed now, queued as follow-up input, dropped, or offered to the running turn as steering input.This PR adds an optional scheduling decision point while keeping the default behavior unchanged.
Design
Add a new first-result hook:
Nonemeans no decision; if every implementation returnsNone, Bub keeps the current default concurrent scheduling behavior.AdmitDecision.actionsupports four literal actions:"process": schedule immediately"drop": discard explicitly"follow_up": queue as follow-up input after the active turn finishes"steer": enqueue as steering input for model hooks to consume viastate["_runtime_steering"]SteeringBufferis exposed torun_modelas a thin runtime API. For now it supports destructive consumption only:get_nowait()for one message anddrain_nowait()for all currently queued steering messages.Undrained steering messages are promoted to the front of the follow-up queue when the active turn finishes, preserving FIFO order.
Scope
ChannelManagerpath; directprocess_inbound()calls are unaffectedadmit_messagedoes not route messages to a specific forked tape/thread; steering selection and consumption are left to therun_model/ agent loop implementation"drop"explicitlyVerification
uv run pytest -quv run ruff check .uv run mypy src