Skip to content

user_input wire event lacks a turn/task id — consumers can't attribute it (cancel-guard, cross-client reconciliation) #379

Description

@luizParreira

Summary

The user_input event carries no turn/task identity, so a consumer cannot attribute it to a specific turn. This breaks two things for any multi-client consumer: cancel-guard attribution, and cross-client turn reconciliation.

Where the identity is lost

  • src/serve/http_types.rs:222AgentEventPayload::UserInput { event_id, sequence, timestamp_ms, text }. Those four fields are the entire payload. One hop earlier, src/runtime_boundary.rs lowers LegacyAgentEvent::UserInput { thread_id, content } into this — the thread_id (the SESSION id, not a turn id) is dropped, and there was never a turn/task id to begin with.
  • src/grpc/agent.rs:6303user_input is explicitly NOT forwarded on the live gRPC stream (if let AgentEventPayload::UserInput { .. } = payload { return None; }). It reaches a reconnecting/reloading client only through GetSessionEvents as opaque JSON with those same four fields.

Consumer damage (observed in bipa-app/bip)

The desktop renderer runs a cancel guard: after a user stops a turn, late frames from the stopped turn are dropped until a NEW turn starts. A turn can start on ANOTHER frontend (multi-client), so the renderer must clear the guard when a genuinely-new user_input arrives — but it can only compare SEQUENCE to the guard, because there is no turn id. That works in every state except one: a user cancel that landed before the turn's first sequenced frame (guard armed at 0), where the canceled turn's OWN delayed user_input (sequence >= 1) is indistinguishable from a new turn's. The renderer resolves this conservatively (keeps the guard, so it never un-cancels the turn the user stopped), at the cost of a genuine remote turn on that narrow state staying filtered until the next local send. See bipa-app/bip#603 and ENG-9215.

Ask

Stamp a turn identifier — the root task id / turn number that already exists internally — onto the user_input wire event, threaded http_types.rs:222 -> grpc/agent.rs -> the JSON a client reads back. Then a consumer can compare turn ids instead of sequences and the ambiguity disappears, for cancel attribution and for any cross-client turn reconciliation.

Same family as #377 (the wire dropping identity a consumer needs). Either issue closing would help; this one is independent of the re-mint fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions