oc_chat
Loading...
Searching...
No Matches
oc_ui.presenter_base.Presenter Class Reference
Inheritance diagram for oc_ui.presenter_base.Presenter:
[legend]
Collaboration diagram for oc_ui.presenter_base.Presenter:
[legend]

Public Member Functions

AbstractContextManager turn (self)
None start_turn (self)
None end_turn (self)
None show_waiting (self)
None show_reasoning (self, str text)
None show_content (self, str text)
None show_tool_call (self, str name, str arguments)
None show_tool_progress (self, str name)
None show_tool_result (self, str name, object result)
None show_usage (self, dict usage)
None show_iteration_stat (self, "IterationStat" stat)
None show_turn_summary (self, int prompt, int completion, int total, int iterations, int tool_calls, int|None prompt_cached=None, *, float|None cache_hit_pct=None, int|None cache_saved_tokens=None, object performance_stats=None, str|None model=None, float|None context_used_pct=None, int|None duration_ms=None, object turn_cost=None)
None show_welcome (self, ChatSession session)
None show_available_models (self, dict models)
None show_session_list (self, list sessions, str|None current_name=None)
None show_help (self, dict command_help, list[str]|None tools=None)
None show_compressed (self)
None show_error (self, str msg)
None show_info (self, str msg)
SpinnerHandle spinner_start (self, str label)
None spinner_stop (self, SpinnerHandle handle)
None show_activity (self, str label, str detail="", *, str tone="info")
None show_session_start (self)
None show_interrupt_notice (self, str stage)
None bind_status (self, Callable[[], StatusBarState|None] provider)

Detailed Description

Abstract base class for all OC Chat terminal presenters.

Implementations: :class:`~oc_ui.terminal.presenter.ConsolePresenter`
(always available); ``RichPresenter`` (Phase 1, optional dep);
``TextualPresenter`` (Phase 3).

Lifecycle (per chat turn):

    presenter.start_turn()
    with presenter.turn():
        presenter.show_waiting()
        # … streaming events: show_reasoning / show_content / show_tool_*
    presenter.show_turn_summary(...)
    presenter.end_turn()

Definition at line 119 of file presenter_base.py.

Member Function Documentation

◆ bind_status()

None oc_ui.presenter_base.Presenter.bind_status ( self,
Callable[[], StatusBarState | None] provider )
Register the late-binding status-snapshot provider for this presenter.

*provider* is a zero-arg callable a presenter invokes AT RENDER TIME
to obtain the current :class:`~oc_ui.terminal.statusline.StatusBarState`
(or ``None`` when no snapshot is available yet). It MUST NOT be a
closure that captures a ``ChatSession`` object — sessions are
replaced at runtime (``/session new`` / ``clear``) — it should read
current state (e.g. off a ``Context``) fresh on every call. Called
via :func:`~oc_chat.core.commands.refresh_presenter_bindings` on
every session-mutation path, alongside ``bind_session``. The base
implementation is a no-op — appropriate for :class:`ConsolePresenter`
and any presenter with no persistent chrome to refresh.

Reimplemented in oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 411 of file presenter_base.py.

◆ end_turn()

None oc_ui.presenter_base.Presenter.end_turn ( self)

◆ show_activity()

None oc_ui.presenter_base.Presenter.show_activity ( self,
str label,
str detail = "",
* ,
str tone = "info" )
Render a compact one-line state update for a non-streaming lane.

Plan 188 T2 surfaces state the loop ALREADY produces but never
showed: the pending-approval lane (``permission_decision``), the
sub-agent lane (``subagent_started`` / ``subagent_completed``) —
both fed by the :mod:`oc_chat.core.presenter_events` bus
subscriber — and plan progress, fed presenter-side from the
planner singleton (see :mod:`oc_ui.terminal.activity`).

*label* names the lane (``"approval"`` / ``"sub-agent"`` /
``"plan"``); *detail* is the already-formatted body; *tone* is one
of :data:`~oc_ui.terminal.activity.TONES` and selects styling
only — an unknown tone must render neutral, never raise.

No new event kind and no bus semantic change: this hook renders
existing signal (synthesis §2 — observability, not control).

Reimplemented in oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 333 of file presenter_base.py.

Here is the caller graph for this function:

◆ show_available_models()

None oc_ui.presenter_base.Presenter.show_available_models ( self,
dict models )

◆ show_compressed()

None oc_ui.presenter_base.Presenter.show_compressed ( self)

◆ show_content()

None oc_ui.presenter_base.Presenter.show_content ( self,
str text )

◆ show_error()

None oc_ui.presenter_base.Presenter.show_error ( self,
str msg )

◆ show_help()

None oc_ui.presenter_base.Presenter.show_help ( self,
dict command_help,
list[str] | None tools = None )
Display the ``/help`` listing of commands (and optionally agent tools).

*command_help* maps verb → usage string (the ``COMMAND_HELP``
registry).  *tools* is the sorted list of registered agent-tool
names; ``None`` skips the tools section.

Reimplemented in oc_chat.benchmarks.presenter.BenchmarkPresenter, oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 279 of file presenter_base.py.

◆ show_info()

None oc_ui.presenter_base.Presenter.show_info ( self,
str msg )

◆ show_interrupt_notice()

None oc_ui.presenter_base.Presenter.show_interrupt_notice ( self,
str stage )
Announce a Ctrl+C stage — called FROM THE SIGNAL HANDLER.

*stage* is ``"cancel"`` (first press: a stop-confirmation is now
pending at the turn's next safe checkpoint; nothing is cancelled
yet and the in-flight tool keeps running) or ``"force"`` (second
press: hard interrupt). Any other value is ignored.

**Signal-safety contract.** This runs inside
:func:`oc_chat.main._o3_sigint_handler`, so an implementation must
do at most ONE short write and must never block, prompt, or raise.
The default writes the notice to ``stderr`` — which is exactly
what the handler did inline before plan 188, so presenters that do
not override this keep byte-identical behaviour; the point of the
hook is that the presenter which OWNS the terminal (Rich, with a
live region) gets to choose the stream.

Reimplemented in oc_ui.terminal.logging_presenter.LoggingPresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 380 of file presenter_base.py.

◆ show_iteration_stat()

None oc_ui.presenter_base.Presenter.show_iteration_stat ( self,
"IterationStat" stat )
Render a timestamped per-iteration analytics stat line.

Called once per ReAct iteration with a structured
:class:`IterationStat` record.  Implementations may print
a compact one-liner, write JSON to a file, or both.

Reimplemented in oc_chat.benchmarks.presenter.BenchmarkPresenter, oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 208 of file presenter_base.py.

◆ show_reasoning()

None oc_ui.presenter_base.Presenter.show_reasoning ( self,
str text )

◆ show_session_list()

None oc_ui.presenter_base.Presenter.show_session_list ( self,
list sessions,
str | None current_name = None )
Display the list of saved sessions for ``/session list``.

*sessions* is the return value of :func:`oc_chat.core.persistence.list_sessions`.
Plain console: a hand-padded text table.  Rich: a styled
``rich.table.Table`` with proper column sizing and overflow.

Reimplemented in oc_chat.benchmarks.presenter.BenchmarkPresenter, oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 270 of file presenter_base.py.

◆ show_session_start()

None oc_ui.presenter_base.Presenter.show_session_start ( self)
Draw the ``start @ <time>`` rule that opens the session.

Plan 218 P1 element 1: the REPL's first prompt used to float in
unbounded space — the first horizontal rule only appeared once the
user had already pressed Enter. Emitting a rule at session start
means every prompt echo, including the first, sits inside a
bounded region, which is what makes the three-space turn indent
read as containment rather than as a stray margin.

Called once by :func:`oc_chat.main.main`, after the welcome banner
and the pre-turn notices and before the REPL loop. Terminal
presenters draw their existing rule; the base implementation is a
no-op — appropriate for headless, JSON-lines and recording
presenters that have no rules to draw.

Reimplemented in oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 359 of file presenter_base.py.

◆ show_tool_call()

None oc_ui.presenter_base.Presenter.show_tool_call ( self,
str name,
str arguments )

◆ show_tool_progress()

None oc_ui.presenter_base.Presenter.show_tool_progress ( self,
str name )
Indicate that a tool is currently executing.

Plain presenters typically no-op.  Rich/textual presenters show a
spinner that is replaced by :meth:`show_tool_result` when the tool
finishes.

Reimplemented in oc_chat.benchmarks.presenter.BenchmarkPresenter, oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 181 of file presenter_base.py.

◆ show_tool_result()

None oc_ui.presenter_base.Presenter.show_tool_result ( self,
str name,
object result )

◆ show_turn_summary()

None oc_ui.presenter_base.Presenter.show_turn_summary ( self,
int prompt,
int completion,
int total,
int iterations,
int tool_calls,
int | None prompt_cached = None,
* ,
float | None cache_hit_pct = None,
int | None cache_saved_tokens = None,
object performance_stats = None,
str | None model = None,
float | None context_used_pct = None,
int | None duration_ms = None,
object turn_cost = None )
Render the aggregated turn-level summary.

Plan 134 C2: *cache_hit_pct* is the cache-hit ratio (label it
``cache-hit:`` — NOT ``ctx:``). *context_used_pct* is the real
context-window saturation (main-loop prompt high-water ÷ the model's
window), already computed by the caller; *model* names the window.
Presenters render what they're given and do no config/caps lookup.

Plan 147 D1: *duration_ms* is the real wall-clock turn duration,
computed by the caller directly from a turn-start monotonic
timestamp (never derived from :class:`~oc_ui.terminal.input.TurnStats`
finish-turn state — see the summary-ordering pin). ``None`` when the
caller has no timing available (e.g. a synthetic/test turn).

Plan 188 T4: *turn_cost* is a
:class:`~oc_chat.core.turn_cost.TurnCost` — the modelled USD spend
plus the price table's provenance — or ``None``. Typed as ``object``
for the same reason as *performance_stats*: presenters read it
duck-typed and ``oc_ui`` never imports ``oc_chat.core`` at module
load. ``None`` means the turn could NOT be priced honestly (unknown
model, unaccounted cache split, separately-billed reasoning) and
presenters MUST then render no cost at all — a missing line is the
designed outcome, not a degraded one, and rendering ``$0.00`` in its
place would be exactly the false line T4 forbids.

Reimplemented in oc_chat.benchmarks.presenter.BenchmarkPresenter, oc_ui.terminal.enhanced_presenter.EnhancedPresenter, oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 216 of file presenter_base.py.

◆ show_usage()

None oc_ui.presenter_base.Presenter.show_usage ( self,
dict usage )
Render per-iteration usage stats.

Plan 134 C1: terminal presenters render this ONLY in ``--verbose``
mode (the render is gated, not the event). The structured usage signal
is preserved elsewhere — ``react_loop`` records it and
``LoggingPresenter`` tees it to its JSONL log unconditionally before
delegating — so quiet mode loses only the on-screen line.

Reimplemented in oc_chat.benchmarks.presenter.BenchmarkPresenter, oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 196 of file presenter_base.py.

◆ show_waiting()

None oc_ui.presenter_base.Presenter.show_waiting ( self)
Indicate the request is in flight before any tokens arrive.

Should be cleared automatically by the first reasoning/content
chunk.  Plain presenters print a transient line; rich presenters
show an animated spinner.

Reimplemented in oc_chat.benchmarks.presenter.BenchmarkPresenter, oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 158 of file presenter_base.py.

◆ show_welcome()

◆ spinner_start()

SpinnerHandle oc_ui.presenter_base.Presenter.spinner_start ( self,
str label )
Start an animated progress spinner with the given label.

Used by long-running operations (slow tool dispatch, sub-loop
provider calls) to indicate liveness so users don't wonder if the
app has hung. Returns a :class:`SpinnerHandle` the caller passes
back to :meth:`spinner_stop`. The base implementation is a no-op
returning a handle with ``status=None`` — appropriate for plain
console, headless CI, and tests; :class:`RichPresenter` overrides
with a real animated spinner.

Reimplemented in oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 304 of file presenter_base.py.

◆ spinner_stop()

None oc_ui.presenter_base.Presenter.spinner_stop ( self,
SpinnerHandle handle )
Stop the spinner identified by *handle*.

Idempotent — safe to call multiple times on the same handle (e.g.
once on first-chunk arrival and again in a ``finally`` block).
The base implementation is a no-op (handle's ``status`` is
``None`` by default).

Reimplemented in oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 317 of file presenter_base.py.

◆ start_turn()

None oc_ui.presenter_base.Presenter.start_turn ( self)

◆ turn()

AbstractContextManager oc_ui.presenter_base.Presenter.turn ( self)
Return a context manager wrapping the streaming portion of a turn.

Plain presenters return a no-op contextmanager.  Streaming
presenters use this to open a Live region on ``__enter__`` and
commit it (or clear it) on ``__exit__``.

Reimplemented in oc_chat.benchmarks.presenter.BenchmarkPresenter, oc_ui.terminal.logging_presenter.LoggingPresenter, oc_ui.terminal.presenter.ConsolePresenter, and oc_ui.terminal.rich_presenter.RichPresenter.

Definition at line 139 of file presenter_base.py.


The documentation for this class was generated from the following file: