Replace abort-and-resend with pi's steer command #97

Open
opened 2026-10-01 11:42:09 +08:00 by weiwen · 0 comments
Owner

Problem

A Message Burst that arrives mid-turn aborts the in-flight turn. Evie then drains stdout to the
terminal event, deletes the partial Telegram messages, and sends the new prompt.

ADR 0001 records why: message ordering could not be delegated to pi, so evie built
abort-and-resend instead. CONTEXT.md records the cost under Session: "the aborted partial
stays in pi's session history".

The turn is therefore thrown away, the model re-reads the whole context, and the session history
keeps a dead partial.

What pi offers now

pi's RPC mode has explicit queue commands that did not exist when ADR 0001 was written:

  • steer queues a message. pi delivers it after the current tool calls finish, before the next
    LLM call.
  • follow_up queues a message for delivery after the agent finishes all work.
  • clear_queue returns and removes all pending steer and follow-up messages.
  • set_steering_mode and set_follow_up_mode select "all" or "one-at-a-time" delivery.

Evie sends streaming_behavior: "followUp" on every prompt (src/pi.rs:1403) but never issues
any of these commands. PiCommand models only Prompt and Abort (src/pi.rs:67).

Reference: https://pi.dev/docs/latest/rpc-commands

Proposed change

Send steer for a burst that arrives mid-turn. Keep abort for /clear and for eviction only.

Expected results:

  • The in-flight turn continues instead of restarting.
  • The partial-message deletion path disappears from the burst path.
  • No dead partial enters pi's session history.
  • Token cost drops, because the context is not re-sent.

Sites

  • src/pi.rs:67 PiCommand, needs a Steer variant.
  • src/pi.rs:1386 PiProcess::send_message.
  • src/pi.rs:1826 drain_aborted, still needed for /clear.
  • src/session.rs:1061 SessionManager::abort_turn.
  • src/telegram/mod.rs:1709 aborts the turn and deletes its messages before the new one.
  • src/telegram/mod.rs:1600 abort-and-delete helper, keep for /clear.

Open questions

  1. Does a steered message need its own Snapshot::Start? The current burst path opens a new
    placeholder because the turn restarts. A steered turn does not restart.
  2. What happens to the Stream Buffer when a steer lands mid-stream? The buffer holds a cumulative
    snapshot per message. Confirm that pi emits a message boundary.
  3. Does steer preserve the Message Log high-water mark semantics? The injected delta is computed
    per turn today.
  4. Keep abort-and-resend as a fallback when steer is rejected, or fail the turn?

Answer question 2 against a captured pi-rpc fixture before any code changes.

Context

Raised from a review of whether any agent in llm-agents.nix should replace pi. The conclusion was
to keep pi. This is the highest-value capability evie does not yet use: evie drives 2 of roughly 35
pi RPC commands.

## Problem A Message Burst that arrives mid-turn aborts the in-flight turn. Evie then drains stdout to the terminal event, deletes the partial Telegram messages, and sends the new prompt. ADR 0001 records why: message ordering could not be delegated to pi, so evie built abort-and-resend instead. CONTEXT.md records the cost under **Session**: "the aborted partial stays in pi's session history". The turn is therefore thrown away, the model re-reads the whole context, and the session history keeps a dead partial. ## What pi offers now pi's RPC mode has explicit queue commands that did not exist when ADR 0001 was written: - `steer` queues a message. pi delivers it after the current tool calls finish, before the next LLM call. - `follow_up` queues a message for delivery after the agent finishes all work. - `clear_queue` returns and removes all pending steer and follow-up messages. - `set_steering_mode` and `set_follow_up_mode` select "all" or "one-at-a-time" delivery. Evie sends `streaming_behavior: "followUp"` on every prompt (`src/pi.rs:1403`) but never issues any of these commands. `PiCommand` models only `Prompt` and `Abort` (`src/pi.rs:67`). Reference: <https://pi.dev/docs/latest/rpc-commands> ## Proposed change Send `steer` for a burst that arrives mid-turn. Keep `abort` for `/clear` and for eviction only. Expected results: - The in-flight turn continues instead of restarting. - The partial-message deletion path disappears from the burst path. - No dead partial enters pi's session history. - Token cost drops, because the context is not re-sent. ## Sites - `src/pi.rs:67` `PiCommand`, needs a `Steer` variant. - `src/pi.rs:1386` `PiProcess::send_message`. - `src/pi.rs:1826` `drain_aborted`, still needed for `/clear`. - `src/session.rs:1061` `SessionManager::abort_turn`. - `src/telegram/mod.rs:1709` aborts the turn and deletes its messages before the new one. - `src/telegram/mod.rs:1600` abort-and-delete helper, keep for `/clear`. ## Open questions 1. Does a steered message need its own `Snapshot::Start`? The current burst path opens a new placeholder because the turn restarts. A steered turn does not restart. 2. What happens to the Stream Buffer when a steer lands mid-stream? The buffer holds a cumulative snapshot per message. Confirm that pi emits a message boundary. 3. Does `steer` preserve the Message Log high-water mark semantics? The injected delta is computed per turn today. 4. Keep abort-and-resend as a fallback when `steer` is rejected, or fail the turn? Answer question 2 against a captured pi-rpc fixture before any code changes. ## Context Raised from a review of whether any agent in `llm-agents.nix` should replace pi. The conclusion was to keep pi. This is the highest-value capability evie does not yet use: evie drives 2 of roughly 35 pi RPC commands.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
weiwen/evie#97
No description provided.