Repository navigation
Android: side chats and subagent viewer (android-next#06, port of upstream #899) - #22
Merged
Merged
Conversation
…droid-next#06) The engine-local port of upstream zeron PR zeronsh#899's client half: - mobile-client: NewSession.parent_chat_id (an empty side chat: the parent's host/checkout/sandbox, a sibling of a side chat), the pending-chat overlay carries the parent (a side chat never lists on the front page), fork_side_chat (the engine's ForkSideChat RPC, a side chat's fork lists as its sibling), open_subagent (the spawn chip's doc id, read-only: no markChatSeen, no pill count; the transcript cache persists it for offline reads), SessionSnapshot:: subagents() (the spawn chips are the index), and the running- subagent count overlay feeding the rows' "● N" pill (cleared when a session leaves the registry; the derive folds working side chats in, the zeronsh#899 follow-up). - mobile (FFI): SubagentState/SubagentInfo + SessionHandle.subagents() /is_subagent(), CoreClient.fork_side_chat + open_subagent, NewSession.parentChatId, SessionRow.runningSubagents, and the layout's WidgetKind::SubagentLink — a spawn card whose engine- stamped doc exists becomes a whole-card tap target. - tests: pure subagent derivation/lifecycle tests, the FFI mapping, the link widget, and real-engine side_chats_engine.rs (fork, empty create, live/finished/resumed subagent docs, running counts).
…t + the Arc import A failed edit batch (one block not matching) dropped the SessionHandle half of the subagent surface — only the snapshot method had landed. Also new_session.rs never imported std::sync::Arc.
…_in_background) The user's exact shape, driven through a channel-fed harness: the spawn call's tool result returns at once, the parent turn completes (parks), and the subagent's nested traffic arrives afterwards — sessions.rs routes it before the parked gate, so the doc streams and the chip binds (running dots), then freezes on the agent's Done. Asserts the chip state, the doc id, the tail, the running count, the live open, and the frozen read.
…gine - new_session: import ClientInner (create_side_chat's signature named it without a use). - subagents_of titles a row with subagent_title, a port of the desktop's subagent_tab_title (bare task, description/prompt fallback, 40-char cap), re-exported for the layout's card link. - A read-only subagent core skips the WatchQueue task and refuses sends (InvalidArgument); it never writes the store (no seen marks, no pill). - set_running_subagents removes the entry on 0 instead of storing zeros. - side_chats_engine: Reply::Background was missing from the reply match; the run pushed `request` before reading it (use after move); "mock".into() has no From<&str> for HarnessId; the background stream held a tokio MutexGuard while moving the Arc. The rig now waits for the derived parent row (create_side_chat reads it) and the fork test waits for a COMPLETE reply. The chip tail asserts None: the engine stamps lifecycle only (sessions.rs subagent_chip_update; live tails were rejected). Co-Authored-By: Claude <noreply@anthropic.com>
…like desktop SessionRow.running_subagents defaults to 0 and NewSession.parent_chat_id to None in the generated bindings, so existing Kotlin constructor calls keep compiling. The subagent card link takes its title from the client's subagent_title (the desktop tab title) instead of the chip detail line. Co-Authored-By: Claude <noreply@anthropic.com>
…ipt (android-next#06) WidgetKind.SubagentLink becomes a full-card tap target (a transcript control) that calls TranscriptActions.openSubagent. SubagentRoute opens the doc read-only through CoreClient.openSubagent and binds the layout engine to it: the engine's WatchDocMessages stream, the same one desktop's subagent tab watches, so a claude-code run_in_background subagent keeps streaming after its spawn call resolved and stops once done. The subtitle follows the spawn chip's state; nested cards push another viewer. Co-Authored-By: Claude <noreply@anthropic.com>
…t and Fork (android-next#06) The header's second bar item (badge: '● N' while subagents run, else a quiet count) opens the sheet: Running, Side chats, Finished agents, foldable. The session menu gains New Side Chat (the New Session canvas pushed in side mode: model and effort only, nothing written until the first send, parentChatId on create) and Fork into Side Chat (ForkSideChat, one at a time). Engines older than 0.5.0 get no side-chat entry points. Co-Authored-By: Claude <noreply@anthropic.com>
SessionRowVM carries runningSubagents; the row draws '● N' before the status glyph (upstream zeronsh#899's SessionCell geometry) and speaks it. Co-Authored-By: Claude <noreply@anthropic.com>
… draft (android-next#06) Co-Authored-By: Claude <noreply@anthropic.com>
Conflicts: SessionController keeps engineVersion, sessionRow and harness; SessionScreenRoute.release stops the side chats and disposes the usage filler. SideChatsEntryTest passes #21's onShowAccounts and counts its Account & Usage row (Pin, Copy, side-chat group, Account & Usage, Archive).
serve()'s listener was dropped when rig_with_background returned, so the engine stopped listening and every first call failed with "Engine connection lost" (all five side_chats_engine tests on 1ffe097).
hoangvu12
added a commit
that referenced
this pull request
Oct 15, 2026
The first release with the native Android app (signed arm64-v8a and x86_64 APKs), alongside the desktop and engine: - Android: the 1:1 iOS port on the shared Rust mobile core (PR #19), with context usage always visible, Tailcat pairing, the new logos and notification icon, and in-app updates. - Android: agent accounts - plan usage folded into the context chip, switch and remove Claude/Codex/Cursor logins (PR #21). - Android: side chats and the subagent viewer, including background subagents (PR #22). - Desktop: Tailcat invites as a scannable QR in Settings -> Remote access (PR #20); pairing links as QR codes (in PR #19).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Android: side chats and the subagent viewer. This is android-next#06, which ports upstream zeronsh#899 ("iOS: side chats and subagents", still open) onto Roboco's engine-local core. Nothing goes through zeronsh#899's edge or blob paths.
Behaviour
WatchDocMessagesstream (the same stream desktop's subagent tab uses), freezes when the subagent finishes, and nested cards push another viewer.run_in_backgroundsubagents. The tool result returns immediately and the subagent keeps streaming. The card's dots followsubagent_status.ForkSideChat).Core:
mobile-clientgainsfork_side_chat, side-chat create (parentChatId),subagents_ofandopen_subagent(a read-onlySessionCore). The FFI gainsSubagentInfo/SubagentState,NewSession.parent_chat_id,SessionRow.running_subagentsandWidgetKind::SubagentLink. There are no wire or auth changes.Tests:
mobile-client/tests/side_chats_engine.rsruns against a real engine. It includes the background case: tool result and turn Done first, then nested traffic binds Running and streams into the open viewer, then the nested Done freezes it.SideChatsModelTest,SideChatsSheetTest,SideChatsEntryTest,SubagentLinkTest,RunningAgentsPillTest,SideChatDraftTest.Known gaps:
subagent_tail.Ticket:
.scratch/android-next/issues/06-side-chats-subagents.md