Repository navigation
Show "Pi isn't signed in" in native chat before the first send - #26743
Conversation
A Pi chat whose agent started with no model to use now says so in the existing availability notice, and the next send replaces that agent so a sign-in made since takes effect.
…ted Pi A Pi's start verdict ends with that Pi: the notice now re-reads when the host starts or stops the chat's agent, and a Pi whose process already exited reports nothing.
…art or stop The notice steps aside while the newest send was refused for the same reason, and the chat re-reads its verdict whenever its agent starts or stops, dropping an answer read before.
…reen Uses the host's send order and the chat's rendered delivery lines, so a deleted returned card or a trimmed row brings the sign-in notice back.
Review summaryVerdict: ready from review. Five read-only review rounds on this branch (approach and diff), plus three hidden-window QA runs with the real Pi 1.1.0. What was checked
Findings and outcomes
Each fix was ablated (reverting it fails exactly its new test). Not verified: Windows, Linux, paired remote hosts, mobile. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (17)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review. 📝 WalkthroughWalkthroughPi sessions now expose startup unavailability through the session adapter and catalog response. The renderer rereads the catalog when provider-running state changes. Availability notices also account for the newest rejected send and its journal line. Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to No actionable issue remains that needs to be resolved before merging. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
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 |
…ain) Rebuilds #26561 on main now that #26416 is squash-merged. Same change as before, re-applied onto what main has since: - Every adapter answers acquire at spawn and reports `started` on protocol readiness with its real handle (Claude initialize, Codex thread, ACP session new/load plus restore, Pi session file plus restore). No bridge, no per-adapter phase or Stop opt-outs. - Picks made while starting are intents applied model then effort before the start is accepted; rewind, goal, rewind recovery and compact wait for a proven start outside the session queue. - One Stop rule: Stop ends the session for every agent (Codex: interrupt, up to 2 s for the turn to end, then close). - Orchestration worker starts share one deadline; a send's answer copies its row; a re-attach during start keeps the start wait. Integrated with main: - ACP: the subagent-stop probe, child-work delivery and new/loaded origin move into the handshake; the sign-in rule (#26544) classifies a failed handshake; acpAgentName stays in acp-structured-agent-definitions. - Codex: the session journal translator and account kind (#26407) reach the start step. - Pi: the start choice (#26821) and the signed-out verdict (#26743) are read in Pi's start, so both exist when `started` is reported; commands follow. - openWithAgent keeps main's pre-agent check and replay rule. - A report with no model drops the saved one, as #26587 decided. - The renderer re-reads a start's sign-in verdict once the start is proven.
The gap it closed exists only for a desktop app built between #26743 and this change; no released app shows the Pi notice yet, and the first send still says not signed in. Not worth a held read on every agent's start.
ELI5
If Pi has no sign-in at all, a new Pi chat used to open as if everything was fine. You only found out when your first message failed. Now the chat tells you up front, in the same notice Codex chats already show: "Sign in to Pi by running
piand using/loginon the computer running this chat." And once you sign in, your next message in that same chat goes through on the first try.What Changed
What you see (Pi native chat, nothing signed in):
The other agents, before the first send: Claude already shows a sign-in line as the chat opens, Codex already shows this notice, and Grok already fails to start with its sign-in line (checked with real Grok 1.0.50 in a throwaway home: it refuses to open a session when signed out). None of that changes. OpenCode has nothing to show: without a login it keeps its free models usable, so a signed-out OpenCode can still chat (from its source). OMP stays quiet, see "Differences" below.
Mechanism. Every native chat starts its agent as soon as the chat opens. When a fully signed-out Pi starts, its own model list is empty and it keeps a placeholder model, so every prompt that Pi takes will fail as "not signed in". Orca already reads that list at start. Now:
startUnavailable(sessionId): "not signed in" when its running Pi started with no model, nothing once that Pi has exited or closed. It lives and dies with that one Pi process; nothing is stored.agentSession.modelCatalog, which the chat already reads for its notice) carries it as the existingunavailablefield when the catalog itself has no reason. Only for a read naming that chat and its own agent.Why
The fact already exists inside the running chat: Pi's own start says it has no model. Reading it there costs nothing, uses the chat's real folder, environment and extensions (Pi reads project-level settings), and is the same process the next send would use. The alternatives were weaker:
Unknown stays quiet: no running Pi, an older host, or an unreachable host shows nothing. The execution host decides (paired remote hosts run the same code); a client only displays it.
Differences from the common pattern
enabledModelsallow-list excludes every model it has a login for (OMP 17.0.5 source and a throwaway-home run: no model option either way). An up-front "Sign in to OMP." would be wrong for the second case, and OMP's first-send failure already shows OMP's own words.Linked Issue
Follow-up to #26544, which listed "no sign-in check before the first send" as a temporary difference. Requested by @BrennanKB5.
Visual Proof
Hidden-window QA on macOS with the real Pi 1.1.0 in throwaway home folders and a local fake model server (no real account; "signing in" = writing that server's key into the throwaway Pi folder). Real config files unchanged (hashed before and after).
820277c2077)piand using/loginon the computer running this chat."The model picker reads
unknown/unknownfor a signed-out Pi in both builds: that is Pi's own placeholder model name, unchanged here. The empty-composer Send arrow is disabled only because the composer is empty, as for any chat.Testing
Automated, on macOS, under Node (
node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts): 395 test files / 4155 tests passed at the final commit: all ofsrc/main/pi, all ofsrc/renderer/src/components/native-chat, and the host tests for the signed-out restart, the adapter router, the idle sweep, the model-list RPC handler and Pi client capability. New or changed tests:src/main/pi/rpc-session-adapter.test.ts: a Pi that started with an empty model list (the exact shape the captured Pi 1.0.4 signed-out session returns) reports "not signed in"; nothing once its process exited (even while its output still drains) or it closed.src/main/runtime/rpc/methods/structured-agent-session-options-read.test.ts: the model-list answer carries a Pi chat's start verdict; the catalog's own reason wins; another agent's read never gets it; quiet when the start said nothing.src/main/native-chat/agent-session-wire/structured-agent-session-signed-out-child.test.ts: on the real host test rig, the next send after a signed-out start goes to a new agent; only a "not signed in" start counts, never a starting child.src/renderer/src/components/native-chat/use-host-model-catalog-upgrade.unavailable.test.tsx: the chat re-reads when its agent stops or starts, and drops a signed-out answer read before the stop.src/renderer/src/components/native-chat/use-native-chat-availability-notice.test.tsx: the notice steps aside only while the newest send's own line is on screen and loaded, by the host's send order; it comes back when that line is gone or a later send exists.Ablations: reverting each production piece fails exactly its new test (the Pi start read, the exited-process check, the RPC merge, the restart check, the re-read on agent start/stop, the "line on screen" and "row loaded" checks, the send order).
pnpm tc:node,pnpm tc:webandorca-ci-checks(23/23, including typecheck) passed.Live, macOS, hidden windows (driven over CDP; no desktop input), real Pi 1.1.0 in throwaway home folders with a local fake model server, no real account: the scenarios in Visual Proof passed on the final commit, plus a signed-in-from-the-start chat showing no notice and a normal reply (earlier commit of this PR). The same checks on the base build produced the "before" column. Not run: Windows, Linux, paired remote hosts, mobile.
Review
A read-only reviewer ran five rounds on this branch, judging the approach as well as the diff. Every finding was fixed with a regression test, or shown unreachable:
The reviewer also judged the design: the verdict belongs to one running Pi, so keeping it there (not a separate check, not the shared per-account model catalog) gives it the right lifetime, and the restart is needed either way.
Agent skill upstream boundary
Notes
No new wire fields or opcodes:
unavailableis an existing optional field of the model-list answer, which older clients already read (they will show the same notice for Pi). Older hosts never set it for Pi, so nothing changes there. No new UI surface, strings or settings. Windows, Linux and paired remote hosts use the same code paths but were not run.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred): lint/typecheck viaorca-ci-checks, targeted tests above; full suite and build left to CI