fix(pi): capture isIdle before awaiting reportSession to avoid stale ctx throws - #2194
fix(pi): capture isIdle before awaiting reportSession to avoid stale ctx throws#2194ccharname wants to merge 1 commit into
Conversation
…ctx throws session_start awaited reportSession() (up to ~2s of socket retries) before reading ctx.isIdle(). If the session is replaced/reloaded during that window (ctx.newSession/fork/switchSession/reload), the captured extension ctx is invalidated and the post-await access throws 'extension ctx is stale', which can kill the agent pane process under Node's unhandled rejection default. Read isIdle synchronously before the await.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe ChangesSession state capture
Estimated code review effort: 2 (Simple) | ~5 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Greptile SummaryThe PR moves the pi integration's
Confidence Score: 4/5The PR should not merge until a superseded session_start handler is prevented from overwriting and publishing the replacement session's activity state. Independent asynchronous session reports can complete out of order, and the older handler unconditionally commits its pre-await snapshot to shared state after it resumes. Files Needing Attention: src/integration/assets/pi/herdr-agent-state.ts
|
| Filename | Overview |
|---|---|
| src/integration/assets/pi/herdr-agent-state.ts | The synchronous context read avoids the stale-context exception, but the delayed unconditional assignment can publish superseded session state when reports complete out of order. |
Sequence Diagram
sequenceDiagram
participant O as Old session_start
participant N as New session_start
participant S as Shared agent state
O->>O: Capture old isIdle
O->>O: Await reportSession
N->>N: Capture new isIdle
N->>N: Await reportSession
N->>S: Set and publish new state
O->>S: Resume, overwrite and publish old state
Reviews (1): Last reviewed commit: "fix(pi): capture isIdle before awaiting ..." | Re-trigger Greptile
| // A reload can replace this extension mid-run without emitting another agent_start. | ||
| agentActive = ctx?.isIdle?.() === false; | ||
| agentActive = wasActive; |
There was a problem hiding this comment.
|
i can't repro a case where session gets replaced between |
Problem
The pi integration's
session_starthandler awaitedreportSession()(up to ~2s of socket retries) before readingctx.isIdle():If the session is replaced/reloaded during that window (
ctx.newSession()/ctx.fork()/ctx.switchSession()/ctx.reload()), pi invalidates the captured extension ctx and the post-await access throwsThis extension ctx is stale after session replacement or reload. Because the throw happens inside an async event handler, it surfaces as an unhandled promise rejection — which by default terminates the process on modern Node, killing the agent pane.Fix
Read
isIdlesynchronously before the await; the value cannot change across the report since a replacement emits a freshsession_starton the new runtime anyway:Verification
bun test src/integration/assets/herdr-agent-state.test.ts— 14/14 pass, including the reload-preserves-state and replacement-report tests.