Repository navigation
feat(native-chat): render Muse transcripts - #22998
clichedmoog wants to merge 1 commit into
Conversation
c5fbb5d to
876e11a
Compare
876e11a to
b57dad8
Compare
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 📝 WalkthroughWalkthroughThe change adds Muse as a supported native chat transcript agent. It locates Muse session files by session ID, decodes supported transcript records into native chat messages, and routes Muse transcripts through the transcript readers and legacy journal import. Tests cover agent eligibility, file resolution, and transcript decoding. Priority: ➖ Normal Severity of issue fixed: Medium Merge Risk: 🟡 Moderate · up to Muse messages stored in retained frames can be missing from native chat transcripts and journal imports. Handle those records before merging. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to Locally stored conversations become available through more chat views. Existing location and readability controls limit access, but the link between a session and its owner has not been fully established. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
Full details: Linked Issues checkExplanation PR
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Advanced
Run ID: 9ce2b63a-0c73-4d0d-8503-2129297285f9
📒 Files selected for processing (13)
mobile/src/session/mobile-native-chat-eligibility.test.tssrc/main/ai-vault/session-scanner-muse-parser.tssrc/main/native-chat/agent-session-journal/journal-legacy-import.tssrc/main/native-chat/session-file-resolver.test.tssrc/main/native-chat/session-file-resolver.tssrc/main/native-chat/transcript-line-decoders-muse.tssrc/main/native-chat/transcript-line-decoders.muse.test.tssrc/main/native-chat/transcript-line-decoders.tssrc/main/native-chat/transcript-reader.tssrc/main/native-chat/transcript-tail-reader.tssrc/renderer/src/components/settings/NativeChatSupportedAgents.test.tsxsrc/shared/native-chat-agent-support.test.tssrc/shared/native-chat-agent-support.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
There was a problem hiding this comment.
Important
Muse batches real conversation records inside retained_frame envelopes, and the new decoder discards those whole lines — assistant text and question cards will silently vanish from the chat view and live tail. Fix before merge; details inline.
Reviewed changes
- Support gate —
musejoinsNativeChatTranscriptAgent,NATIVE_CHAT_SUPPORTED_AGENT_LIST,resolveNativeChatTranscriptAgent, andnativeChatRequiresLocalTranscript(native-chat-agent-support.ts), so Muse joins grok/omp behind the local-transcript gate. - Decoder — new stateless
decodeMuseTranscriptLine(transcript-line-decoders-muse.ts) mapping user intent, assistant text, tool calls/results, question cards/answers, and a cancelled terminal into turns. - Resolver — id-based
resolveMuseSessionFilematching the parent-directory session id throughmuseSessionIdFromFilePath, plus amuseSessionsDiroverride. - Wiring — threaded through the full reader, the live tailer, and the journal legacy import;
museTimestampMsexported from the ai-vault parser and reused. - Tests — decoder, resolver, shared support, settings chip, and mobile eligibility cases updated/added.
ℹ️ User turns without a user_intent record are not decoded
The decoder reads only runtime.user_intent.accepted for user turns, but the ai-vault Muse parser keeps run :: started.prompt as an explicit fallback "for logs missing intent records" (session-scanner-muse-parser.ts:76-91, foldUserTurn's skipIfDuplicate). If those logs exist, the native chat view drops those user turns. The author rejected a naive add because a stateless decoder cannot dedupe the pair and would double-render intent-carrying turns — a real constraint, so this is a scope call worth confirming rather than a required fix.
Technical details
# `run.started.prompt` fallback
## Affected sites
- `src/main/native-chat/transcript-line-decoders-muse.ts:47-52` — only `runtime.user_intent.accepted` yields a user turn.
- `src/main/ai-vault/session-scanner-muse-parser.ts:186-189` — `foldSessionEvent` folds `started.prompt` as the fallback and relies on `foldUserTurn`'s dedupe (`:103-116`) to avoid double-counting.
## Open questions for the human
- Do real Muse logs ever carry a turn whose only user text is `run.started.prompt`? If not, the omission is harmless; if legacy logs do, the journal legacy import will render those sessions missing their prompt.DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

ELI5
Muse sessions now open in Orca's chat view (desktop toggle and mobile) instead of staying a raw terminal, like Claude, Codex, Grok and OMP already do.
What Changed
musetoNATIVE_CHAT_SUPPORTED_AGENT_LISTand the transcript-agent resolution. Muse joins grok/omp in requiring a locally readable transcript: its hook reportstranscript_path: null, so under Model-A SSH there is no owning-host file to read.decodeMuseTranscriptLineover~/.local/share/muse/sessions/YYYY/MM/DD/<uuid>/session.jsonl:user_intent.accepted(refill blocks,model_messagesfallback) -> user turnassistant_message_committed-> assistant textassistant_tool_calls_committed/tool_result_batch_committed-> tool turns (args JSON parsed, output kept raw)user_input_prompt_requested/settled-> question card / user replyterminal-> the shared interrupted rowretained_frame/retained_markerenvelopes) skips, never throws.resolveMuseSessionsDir(XDG-aware). A subagent log nests one level deeper, so its parent dir is the child id — a parent id can never match a child log.museTimestampMs(now exported) for the microsecond-to-millisecond conversion.Why
#22216 made Muse a first-class agent but left its conversation as a terminal: native chat renders each agent's own JSONL transcript and Muse had no decoder. This follows the same path #11523 (omp) established.
Alternatives considered:
run :: started.promptas a user-turn fallback — rejected; main logs always carryuser_intent, and folding both double-renders (the AI Vault parser already dedupes this pair).Linked Issue
Fixes #22990
Visual Proof
Desktop dev build on macOS (Settings > Experimental > Native Chat on), same Muse session:
Tables, code blocks, and file links render; the composer has no model/effort pill yet (follow-up, see below).
Note: the mobile toggle (
Switch to chat view) cannot appear until the next companion release — the support list is compiled into the mobile binary, so the current TestFlight build still carries the pre-change list. No mobile code changes are needed beyond this PR: the next companion build picks up the shared gate automatically (covered by the mobile eligibility test).Follow-ups kept out of this PR per the single-topic rule: a live-terminal effort picker for Muse (
midSessioncommand driving/effort; the catalog choices already exist for workers). A model picker is not possible — Muse has no model-listing command (#22383).Testing
Decoder (10 tests), resolver (2), shared agent-support, settings chips, and mobile eligibility cases. Also verified against 8,295 lines of real local Muse logs: 359 decoded (user 9 / assistant 178 / tool 171 / system 1), zero thrown, zero empty turns.
pnpm tc,oxlintandoxfmtclean on all touched files; neighboring suites pass (transcript reader, tail reader, turn lifecycle, muse vault scanner, mobile eligibility). Tested on macOS only.Full
pnpm testlocally: 89,211 passed; the only failures also fail on cleanmainwithout this change (missing Playwright browsers, macOS bash 3.2set -ubehavior in skill-recipe-shell, real-CLI handshake, pty timing) plus one self-pollution case (the suite's owntests/e2e/.cross-version-checkouts/tripping the env-writer ratchet on reruns; passes once removed). No failure is caused by this change.AI Disclosure
Written with AI assistance (Muse Code, Meta Muse Spark); verified with the repo's own test suites plus the real-log decode run above.
Review
AI self-review summary (per CONTRIBUTING):
museSessionIdFromFilePath(basename/dirname) andresolveMuseSessionsDir(join/homedir/XDG_DATA_HOME), already used cross-platform by the AI Vault scanner and the usage provider. No new platform assumptions. Tested on macOS only; the date-sharded log layout is what Muse writes on all three platforms.transcript_path: null(see themuse-eventsfixture), so under Model-A SSH the chat view refuses instead of reading a wrong disk — same as grok/omp. Local and runtime-owned SSH paths are unchanged.satisfies neverexhaustiveness gate still holds. Renderer and mobile need no code changes (generic predicates). No changes to hook, usage, or account systems.argsgo throughJSON.parsein try/catch (raw string fallback) — no eval.Agent skill upstream boundary
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)