fix: dispose failed planning startup agents#1176
Conversation
📝 WalkthroughWalkthroughWhen the first AI response cannot be parsed, the session is deleted/unpersisted, the agent session's optional dispose is awaited and errors are warned, and the agent reference is cleared; tests add a regression ensuring the planning route returns HTTP 500 without calling process.exit. A separate test widens a Linux AppImage filename expectation. ChangesAI Agent Cleanup on Unparsable Response
Release workflow artifact test
Sequence Diagram(s)sequenceDiagram
participant Client
participant PlanningRoute
participant getFirstQuestionFromAgent
participant SessionStore
participant AgentSession
Client->>PlanningRoute: POST /planning/start
PlanningRoute->>getFirstQuestionFromAgent: request first question
getFirstQuestionFromAgent->>AgentSession: receive unparsable response
getFirstQuestionFromAgent->>SessionStore: delete session & unpersist
getFirstQuestionFromAgent->>AgentSession: await dispose?.()
getFirstQuestionFromAgent->>PlanningRoute: return error (HTTP 500)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Greptile SummaryThis PR fixes a resource leak in the non-streaming planning startup path by disposing the AI agent when JSON parsing exhausts all retries before a first question is obtained. Without the fix, a malformed or empty AI response left the underlying model/transport handles alive in the long-running dashboard process.
Confidence Score: 5/5Safe to merge — the change is a narrow, well-tested bug fix that prevents agent handle leaks on a specific failure path without altering the happy path. The disposal logic mirrors the already-proven cleanupInMemorySession pattern, is wrapped in a try/catch so a dispose failure cannot mask the original error, and is covered by a direct regression test that checks all three observable effects (error response, no process.exit, dispose called once). The unrelated test change in the desktop package is a minor regex loosening with no production impact. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant Route as POST /api/planning/start
participant createSession as createSession()
participant getFirstQ as getFirstQuestionFromAgent()
participant Agent as AI Agent
Route->>createSession: call with initialPlan
createSession->>Agent: createFnAgent(...)
Agent-->>createSession: agentResult (session.agent set)
createSession->>getFirstQ: await getFirstQuestionFromAgent(session, initialPlan)
getFirstQ->>Agent: session.prompt(message)
Agent-->>getFirstQ: empty / unparsable response
loop up to MAX_PARSE_RETRIES
getFirstQ->>Agent: prompt("respond with valid JSON")
Agent-->>getFirstQ: still unparsable
end
note over getFirstQ: parsed === undefined
getFirstQ->>getFirstQ: sessions.delete(session.id)
getFirstQ->>getFirstQ: unpersistSession(session.id)
getFirstQ->>Agent: session.dispose?.() [best-effort]
getFirstQ->>getFirstQ: "session.agent = undefined"
getFirstQ-->>createSession: throw Error("Failed to get first question from AI")
createSession-->>Route: 500 API error (no process.exit, no handle leak)
Reviews (3): Last reviewed commit: "fix: dispose failed planning startup age..." | Re-trigger Greptile |
ad746cb to
ad45f7b
Compare
ad45f7b to
5f3e344
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/desktop/src/__tests__/release-workflow.test.ts (1)
38-38: ⚡ Quick winConsider asserting the specific suffix that electron-builder produces.
The workflow accepts both
x64andx86_64suffixes, but according to the actual workflow file, electron-builder consistently producesx86_64for AppImage artifacts. Additionally, this creates an inconsistency with Line 37, which usestoContainfor the arm64 variant.Suggested refinement for precision and consistency
expect(workflow).toContain("Fusion-*-linux-arm64.AppImage"); - expect(workflow).toMatch(/Fusion-\*-linux-(x64|x86_64)\.AppImage/); + expect(workflow).toContain("Fusion-*-linux-x86_64.AppImage"); expect(workflow).toContain("name: fusion-desktop-linux");If there's a specific reason to accept both variants (e.g., the two workflow files use different suffixes), consider adding a comment explaining why the alternation is necessary.
As per coding guidelines, prefer narrow seams and targeted assertions in tests. As per relevant code snippet
.github/workflows/release.yml:299-321, the workflow comment states "electron-builder names the x64 AppImage with the x86_64 arch suffix" and uses the glob patternFusion-*-linux-x86_64.AppImage.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/desktop/src/__tests__/release-workflow.test.ts` at line 38, The test assertion allowlisting both `x64` and `x86_64` is too permissive; update the regex in the assertion that references `expect(workflow).toMatch(/Fusion-\*-linux-(x64|x86_64)\.AppImage/);` to match the exact suffix electron-builder produces (use `x86_64` only) so it becomes consistent with the workflow and the arm64 assertion on the previous line; if there is a deliberate reason to accept both suffixes, add a brief inline comment explaining that rationale instead of widening the regex.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/desktop/src/__tests__/release-workflow.test.ts`:
- Line 38: The test assertion allowlisting both `x64` and `x86_64` is too
permissive; update the regex in the assertion that references
`expect(workflow).toMatch(/Fusion-\*-linux-(x64|x86_64)\.AppImage/);` to match
the exact suffix electron-builder produces (use `x86_64` only) so it becomes
consistent with the workflow and the arm64 assertion on the previous line; if
there is a deliberate reason to accept both suffixes, add a brief inline comment
explaining that rationale instead of widening the regex.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 33f74a24-294c-48c3-aece-54ce83ebe344
📒 Files selected for processing (3)
packages/dashboard/src/__tests__/routes-planning.test.tspackages/dashboard/src/planning.tspackages/desktop/src/__tests__/release-workflow.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/dashboard/src/tests/routes-planning.test.ts
- packages/dashboard/src/planning.ts
Summary
Verification
Summary by CodeRabbit
Bug Fixes
Tests