id: NVIM-ISSUE-9MP5JYUO
type: issue
title: Session status never fetches or publishes model, context, and cost
specs:
NVIM-SPEC-GMWDCMJZ
Session status never fetches or publishes model, context, and cost
Symptom
A pivi session surfaces none of the rich Pi status a user sees in Pi's own interface: model, thinking level, context usage percent, token counts, and accumulated cost. Only connection, run, tool, queue, and error states appear.
"Status also exposes available model, thinking, session, context, usage, and extension-status data."
"Status changes redraw native status surfaces and emit a semantic event."
Consumers reading vim.g.pivi can never show model, context, or cost, so a user-built statusline is starved of the data the spec promises to publish.
Scope note: cwd, git branch, and editor version from the user's Pi TUI statusline are out of scope. The native-integration invariant makes pivi a producer of session status, not the owner of a statusline; those fields belong to the user's own statusline, not to pivi's published state.
Generality
The fix must not depend on the reporter's specific Pi extensions.
Core fields (model, thinking, context usage, cost, token counts) come from core Pi RPC get_state and get_session_stats, present for any Pi configuration.
The extra segments in the reporter's TUI line (tokens/s, credit balance, rate-limit window) are extension widgets delivered generically through setStatus / setWidget, keyed by an arbitrary string. dialog.lua already stores them by key and emits PiviActivity; nothing references a named extension, and the path works with zero extensions and with arbitrary ones.
Required: the published status snapshot is the single generic source that merges core fields with whatever extensions contributed by key, so a consumer reads one place. Today extension status/widget entries live only in dialog.lua tables and a separate PiviActivity event, decoupled from vim.g.pivi.sessions[name] and not scoped per session.
Surface
Pi's status is multi-segment and renders across multiple rows in the TUI; setWidget even delivers widgetLines as an array, so the data is inherently multi-line. A Neovim statusline (and winbar) is a single line. pivi therefore must not collapse status into one lossy statusline string as its only output.
pivi publishes structured per-field data plus multi-line widget arrays as data; the consumer owns the surface (a statusline segment, winbar, tabline, or a dedicated multi-line status buffer or float).
A compact single-line summary stays available for the trivial statusline case, but is a convenience over the structured data, never a replacement for it.
pivi's own winbar shows at most a compact subset; full multi-line detail belongs to the structured data and to an optional richer surface, not to the one winbar line.
Evidence
The reducers for the two status-bearing RPC responses exist but are never driven:
status.reduce_state (folds get_state: model, thinking, session) has no live caller. session.refresh issues get_state and is exported as self.refresh, but nothing ever calls it: no command, no lifecycle event, no poll.
status.reduce_stats (folds get_session_stats: context usage, cost) has no caller at all; it is dead code.
command.luasubcommands.session does request get_session_stats, but only prints a one-off notify; it neither folds the result into cached status nor publishes it.
publish.session_status forwards model, thinking, session, context, but omits cost and any token breakdown, so even a populated reducer would not reach consumers in full.
Net effect: the published status carries only event-derived fields (connection, run, tool, queue, compacting, retry, error). The fields that require a request, model/thinking/context/usage/cost, stay nil for the entire run.
sequenceDiagram
participant Pi
participant session as pivi.session
participant status as pivi.status (reducer)
participant publish as pivi.publish
participant consumer as user statusline
Pi-->>session: event stream (agent/tool/queue)
session->>status: reduce(event)
status->>publish: connection/run/tool/queue only
Note over session,status: get_state / get_session_stats never requested
Note over status: reduce_state, reduce_stats never called
publish-->>consumer: vim.g.pivi without model/context/cost
consumer-->>consumer: nothing to show
Expected
Model, thinking, session, context usage, and cost populate cached status during a normal run, refreshed on the events that change them and at settle, for any Pi configuration.
publish.session_status forwards the full set, including cost and token usage, plus generic extension status and widget entries merged by key, through vim.g.pivi and the semantic User PiviStatus event.
Published status is structured per-field data with multi-line widget arrays preserved; the single-line summary remains a convenience, not the only output.
Status evaluation still performs no RPC; refreshes are triggered by run lifecycle, not by consumers reading the variable.
Reproduction
Start a session and submit a prompt that calls a model.
Inspect vim.g.pivi.sessions[<name>] during and after the run.
Observe model, thinking, context, and cost remain nil; only connection/run/tool/queue/error are present.
---
id: NVIM-ISSUE-9MP5JYUO
type: issue
title: Session status never fetches or publishes model, context, and cost
specs:
- NVIM-SPEC-GMWDCMJZ
---
# Session status never fetches or publishes model, context, and cost
## Symptom
A pivi session surfaces none of the rich Pi status a user sees in Pi's own interface: model, thinking level, context usage percent, token counts, and accumulated cost. Only connection, run, tool, queue, and error states appear.
## Impact
Violates the transport-and-status contract of [NVIM-SPEC-GMWDCMJZ](../../specs/NVIM-SPEC-GMWDCMJZ-pivi-native-neovim-integration/index.md):
- "Status also exposes available model, thinking, session, context, usage, and extension-status data."
- "Status changes redraw native status surfaces and emit a semantic event."
Consumers reading `vim.g.pivi` can never show model, context, or cost, so a user-built statusline is starved of the data the spec promises to publish.
Scope note: cwd, git branch, and editor version from the user's Pi TUI statusline are out of scope. The native-integration invariant makes pivi a producer of session status, not the owner of a statusline; those fields belong to the user's own statusline, not to pivi's published state.
## Generality
The fix must not depend on the reporter's specific Pi extensions.
- Core fields (model, thinking, context usage, cost, token counts) come from core Pi RPC `get_state` and `get_session_stats`, present for any Pi configuration.
- The extra segments in the reporter's TUI line (tokens/s, credit balance, rate-limit window) are extension widgets delivered generically through `setStatus` / `setWidget`, keyed by an arbitrary string. `dialog.lua` already stores them by key and emits `PiviActivity`; nothing references a named extension, and the path works with zero extensions and with arbitrary ones.
- Required: the published status snapshot is the single generic source that merges core fields with whatever extensions contributed by key, so a consumer reads one place. Today extension status/widget entries live only in `dialog.lua` tables and a separate `PiviActivity` event, decoupled from `vim.g.pivi.sessions[name]` and not scoped per session.
## Surface
Pi's status is multi-segment and renders across multiple rows in the TUI; `setWidget` even delivers `widgetLines` as an array, so the data is inherently multi-line. A Neovim `statusline` (and `winbar`) is a single line. pivi therefore must not collapse status into one lossy statusline string as its only output.
- pivi publishes structured per-field data plus multi-line widget arrays as data; the consumer owns the surface (a statusline segment, winbar, tabline, or a dedicated multi-line status buffer or float).
- A compact single-line `summary` stays available for the trivial statusline case, but is a convenience over the structured data, never a replacement for it.
- pivi's own winbar shows at most a compact subset; full multi-line detail belongs to the structured data and to an optional richer surface, not to the one winbar line.
## Evidence
The reducers for the two status-bearing RPC responses exist but are never driven:
- `status.reduce_state` (folds `get_state`: model, thinking, session) has no live caller. `session.refresh` issues `get_state` and is exported as `self.refresh`, but nothing ever calls it: no command, no lifecycle event, no poll.
- `status.reduce_stats` (folds `get_session_stats`: context usage, cost) has no caller at all; it is dead code.
- `command.lua` `subcommands.session` does request `get_session_stats`, but only prints a one-off `notify`; it neither folds the result into cached status nor publishes it.
- `publish.session_status` forwards `model`, `thinking`, `session`, `context`, but omits `cost` and any token breakdown, so even a populated reducer would not reach consumers in full.
Net effect: the published status carries only event-derived fields (connection, run, tool, queue, compacting, retry, error). The fields that require a request, model/thinking/context/usage/cost, stay `nil` for the entire run.
```mermaid
sequenceDiagram
participant Pi
participant session as pivi.session
participant status as pivi.status (reducer)
participant publish as pivi.publish
participant consumer as user statusline
Pi-->>session: event stream (agent/tool/queue)
session->>status: reduce(event)
status->>publish: connection/run/tool/queue only
Note over session,status: get_state / get_session_stats never requested
Note over status: reduce_state, reduce_stats never called
publish-->>consumer: vim.g.pivi without model/context/cost
consumer-->>consumer: nothing to show
```
## Expected
- Model, thinking, session, context usage, and cost populate cached status during a normal run, refreshed on the events that change them and at settle, for any Pi configuration.
- `publish.session_status` forwards the full set, including cost and token usage, plus generic extension status and widget entries merged by key, through `vim.g.pivi` and the semantic `User PiviStatus` event.
- Published status is structured per-field data with multi-line widget arrays preserved; the single-line `summary` remains a convenience, not the only output.
- Status evaluation still performs no RPC; refreshes are triggered by run lifecycle, not by consumers reading the variable.
## Reproduction
1. Start a session and submit a prompt that calls a model.
2. Inspect `vim.g.pivi.sessions[<name>]` during and after the run.
3. Observe `model`, `thinking`, `context`, and `cost` remain `nil`; only connection/run/tool/queue/error are present.