Files
orca/mobile/src
Brennan BensonandClaude ca2cdc0ad9 feat(native-chat): answer /context in chat view for OpenClaude and OMP (#22294)
* feat(native-chat): answer /context in chat view for Claude

Over a terminal-backed chat, Claude's /context paints a grid only the hidden
terminal sees and records nothing in the transcript, so the chat showed
nothing. The chat host now answers it itself: the transcript decoder keeps
each assistant response's API usage and model, and the composer replies with
the same estimate the CLI statusline shows (input + cache tokens against the
model's window) instead of typing the command into the PTY. The command is
also listed in the curated Claude catalog so the slash menu offers it.

* fix(native-chat): only state a /context window the host can establish

The /context answer sized the window from the transcript's model id, which
never carries the [1m] suffix, so a 1M session read as 200k (e.g. 450k / 200k,
225%). The window now comes from the session's tracked model resolved through
the host CLI's own model listing (the resolvedModel field the list_models probe
already returned), and only a [1m] id that matches the model the transcript
last answered with is sized; anything else reports the used figure alone.

Also:
- Offer /context only in the desktop terminal-backed composer; the shared
  catalog is mobile's too, and mobile cannot answer it.
- Answer a typed /context even with images attached, as the picker does, and
  keep the attachments armed instead of sending them to the terminal.
- Report nothing until a response lands after a /compact or /clear sent from
  the chat, instead of the pre-compaction size.

* test(native-chat): pin resolvedModel through Claude model discovery

* fix(native-chat): say /context is unavailable when the host never reports usage

A host that predates usage decoding, or a scraped view, decodes Claude's
replies without a model or usage, so the chat promised an answer after the
next response that would never come. Once the agent has answered and no
answer names its model, say usage is not available for this session.

* feat(native-chat): answer /context for OMP instead of Claude

Claude and Codex answer /context themselves in the structured chat lane, so
the terminal-backed Claude answer, its [1m] window rule, and the resolved-model
plumbing through the model listing go away.

OMP's /context only paints a panel inside its TUI. The OMP decoder now keeps
the provider, model and usage of each reply (none for aborted or errored
replies, which OMP's own gauge skips) and turns compaction rows into the
existing compaction boundary. The OMP model listing keeps each model's
context window, and the chat answers /context from the last reply's prompt
size against the window of the provider/model that served it.

* feat(native-chat): show OpenClaude's own /context report in chat

OpenClaude writes its /context grid to the transcript as a
<local-command-stdout> row, which the chat hid as harness noise. The live
message preparation now turns the stdout row that answers an opted-in command
(/context for OpenClaude) into command output with the ANSI colors stripped,
and the notice row renders command output in monospace so the grid keeps its
columns. Replies to other local commands stay hidden, and Claude is not opted
in. OpenClaude's slash menu now lists /context; Claude's does not.

* test(native-chat): pin OpenClaude /context output through live message preparation

* test(native-chat): pin the OMP context window through model discovery

* test(native-chat): pin monospace rendering of command output

* test(native-chat): restore the notice row suite the command-output test replaced

The previous commit rewrote NativeChatNoticeRow.test.tsx wholesale, deleting
main's compaction, tone, plan, provider-notice and old-reader coverage. Restore
it and pin monospace command output through the message row instead.

* fix(mobile): keep OpenClaude /context off mobile, which cannot show its report

The shared slash catalog now lists /context for OpenClaude because the desktop
chat surfaces its transcript reply. Mobile's transcript fold does not, so the
command did nothing there. Mobile now offers the catalog minus commands answered
only by a surfaced reply, which returns its OpenClaude menu and send
classification to main's behavior.

* refactor(native-chat): drop the unread estimated flag from context usage

Left from the earlier design; the answer text states the estimate itself.

* fix(native-chat): keep /model replies hidden after an OpenClaude /context

Skill surfacing ran first and rewrote non-catalog envelopes such as /model into
plain user text, so command-output pairing no longer saw them. A later /model
reply then paired with the earlier /context envelope and appeared in the chat.
Pair outputs against the raw envelopes before skill surfacing.

* fix(native-chat): word the OMP /context answer for a compacted session and show it as an aside

After a compaction the agent has already answered, so the unknown-usage
line now promises the next response instead. The host answer is one
sentence, so it draws as the muted line it replaces rather than a
monospace grid. The provider/model selector now comes from one helper
shared by the OMP listing parser and the answer, and new tests drive
real OpenClaude and OMP transcript lines through the decoders.

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor(native-chat): pair command replies by row link and declare /context replies on the catalog

A `<local-command-stdout>` row now answers the command row its `parentUuid`
names, carried on decoded messages as the optional `parentId`, instead of the
newest command row at or before its timestamp. A reply with no loaded linked
row (older host, command outside the tail window) stays hidden.

How each agent's `/context` is answered is declared once, as `reply` on its
catalog row (`composer` for OMP, `transcript` for OpenClaude). The slash menu,
the composer's answer, the transcript surfacing and the mobile catalog all
derive from it, and both send paths share one intercept. Mobile no longer lists
OMP `/context`, which did nothing there.

* perf(native-chat): skip command-output surfacing for agents that declare no transcript reply

Every Claude-format row now carries its parent link, so once a session holds any
local-command reply (/model, /compact) the surfacing pass built a map of every
message on each live update and changed nothing for agents like Claude. Agents
whose catalog declares no transcript reply now return before the scan.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-05 11:57:25 -07:00
..