Skip to content

All fixes are implemented and verified. Here's what each issue was an…#48

Merged
BotCoder254 merged 1 commit into
mainfrom
attachment
Jul 5, 2026
Merged

All fixes are implemented and verified. Here's what each issue was an…#48
BotCoder254 merged 1 commit into
mainfrom
attachment

Conversation

@BotCoder254

@BotCoder254 BotCoder254 commented Jul 5, 2026

Copy link
Copy Markdown
Owner

…d what changed:

The handler is correctly registered at HEAD (voiceHandlers.ts:42, wired last in ipc/index.ts:72, window created after registration — no race, no duplicate channels). The channel was added in your latest commit, and the errors came from a stale main-process build: Vite hot-reloads the renderer/preload, but the running main process kept the old bundle without the handler. The fresh npm start I ran booted cleanly with the handler registered. Related cleanup: the misleading [WARN] voice: worker exited with code 0 after an intentional idle shutdown now logs as info (expectedExit flag in VoiceManager.ts); a real crash still warns.

Added the \0 rejection to the per-path loop in attachmentHandlers.ts:56, matching the guards already in fsHandlers/workspaceHandlers. Note this was defense-in-depth, not an exploitable bypass — AttachmentManager.stageOne already rejects NUL bytes before touching the filesystem, and pasted filenames are neutralized by sanitizeName.

That message is generated inside the Agent SDK when the CLI dies with a pending error result; the diagnostic means the resumed transcript ends in a tool_use with no tool_result (a prior run was killed mid-tool-call). Since Limboo always resumes the stored SDK session, the session failed the same way on every turn. Two fixes:

  • AgentManager.ts now detects this error in runWithRecovery, drops the corrupted sdk_session_id (new forgetSdkSession), logs a "starting a fresh SDK session" recovery diagnostic, and retries once — your chat history in Limboo is untouched; only the SDK-side conversation restarts.

  • Updated @anthropic-ai/claude-agent-sdk 0.3.195 → 0.3.201, which includes upstream fixes for the "tool_use ids without tool_result blocks" resume bugs.

  • npx vite build --config vite.renderer.config.mts — built clean in 30.7s.

  • npm run lint — no findings.

  • Booted the app (npm start): main/preload/voice-worker all rebuilt, Limboo main process ready, workspace + search indexed, zero errors in the log; test instance shut down cleanly afterward.

Sources: electron#26495 — "No handler registered" from stale builds, Claude stop reasons — tool_use must be followed by tool_result, Claude Code changelog — tool_use/resume fixes.

Summary

Type of change

  • Bug fix
  • New feature
  • Refactor / internal change
  • Documentation
  • Build / CI / tooling

Architectural reasoning

Verification

  • npm run lint passes
  • npx vite build --config vite.renderer.config.mts passes
  • App still starts with npm start (for main/preload changes)
  • Manual testing steps described below

Security checklist (if touching main process)

  • All renderer-supplied IPC inputs are validated in the main process
  • SQL uses bound parameters only
  • Any spawned process uses argv arrays (no shell: true)
  • Renderer-supplied paths are guarded against traversal
  • No weakening of contextIsolation / sandbox / CSP / navigation lockdown

Documentation and changelog

  • Updated the relevant page(s) under docs/
  • Added a CHANGELOG.md entry (if user-facing)
  • Screenshots attached (for UI changes)

Theme discipline (for UI changes)

  • Uses design tokens only (no off-palette hex, no dark: variants, no gradients)

Note

Low Risk
Changes are localized recovery, logging, IPC validation, and a patch-level SDK bump; agent retry is bounded to one resume drop per run.

Overview
Fixes three reliability and hardening issues.

Agent: When a resumed Claude SDK session fails because the transcript ends in tool_use without a matching tool_result (e.g. a prior run was killed mid-tool), runWithRecovery now detects that error pattern, clears the stored sdk_session_id via new forgetSdkSession, logs a recovery diagnostic, and retries once with a fresh SDK session. Limboo’s own chat transcript is unchanged. @anthropic-ai/claude-agent-sdk is bumped 0.3.197 → 0.3.201 in the lockfile.

Voice: Intentional worker shutdown (idle timer or dispose) sets an expectedExit flag so exit code 0 is logged at info instead of warn, while real crashes still warn and can trigger restart.

Attachments: attachmentAddPaths rejects paths containing NUL (\0) in the IPC handler, aligned with other path handlers.

Reviewed by Cursor Bugbot for commit 8ef8a69. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Bug Fixes
    • Improved path validation when adding attachments by rejecting invalid path strings that contain null characters.
    • Made session recovery more resilient by automatically retrying with a fresh session when a corrupted resume is detected.
    • Reduced noisy error logging for voice worker shutdowns, so normal shutdowns are treated as expected instead of crashes.

…d what changed:

The handler is correctly registered at HEAD ([voiceHandlers.ts:42](src/main/ipc/voiceHandlers.ts:42), wired last in [ipc/index.ts:72](src/main/ipc/index.ts:72), window created after registration — no race, no duplicate channels). The channel was added in your latest commit, and the errors came from a **stale main-process build**: Vite hot-reloads the renderer/preload, but the running main process kept the old bundle without the handler. The fresh `npm start` I ran booted cleanly with the handler registered. Related cleanup: the misleading `[WARN] voice: worker exited with code 0` after an *intentional* idle shutdown now logs as info (`expectedExit` flag in [VoiceManager.ts](src/main/managers/voice/VoiceManager.ts)); a real crash still warns.

Added the `\0` rejection to the per-path loop in [attachmentHandlers.ts:56](src/main/ipc/attachmentHandlers.ts:56), matching the guards already in `fsHandlers`/`workspaceHandlers`. Note this was defense-in-depth, not an exploitable bypass — `AttachmentManager.stageOne` already rejects NUL bytes before touching the filesystem, and pasted filenames are neutralized by `sanitizeName`.

That message is generated *inside* the Agent SDK when the CLI dies with a pending error result; the diagnostic means the **resumed transcript ends in a `tool_use` with no `tool_result`** (a prior run was killed mid-tool-call). Since Limboo always resumes the stored SDK session, the session failed the same way on every turn. Two fixes:
- [AgentManager.ts](src/main/managers/AgentManager.ts) now detects this error in `runWithRecovery`, drops the corrupted `sdk_session_id` (new `forgetSdkSession`), logs a "starting a fresh SDK session" recovery diagnostic, and retries once — your chat history in Limboo is untouched; only the SDK-side conversation restarts.
- Updated `@anthropic-ai/claude-agent-sdk` 0.3.195 → **0.3.201**, which includes upstream fixes for the "tool_use ids without tool_result blocks" resume bugs.

- `npx vite build --config vite.renderer.config.mts` — built clean in 30.7s.
- `npm run lint` — no findings.
- Booted the app (`npm start`): main/preload/voice-worker all rebuilt, `Limboo main process ready`, workspace + search indexed, zero errors in the log; test instance shut down cleanly afterward.

Sources: [electron#26495 — "No handler registered" from stale builds](electron/electron#26495), [Claude stop reasons — tool_use must be followed by tool_result](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons), [Claude Code changelog — tool_use/resume fixes](https://claudefa.st/blog/guide/changelog).

@amazon-q-developer amazon-q-developer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resilience improvements in this PR are correctly implemented and address real issues:

Null-byte path validation (attachmentHandlers.ts) - Blocks path traversal attempts via null bytes, closing a security gap
Corrupted resume self-healing (AgentManager.ts) - Automatically recovers from corrupted SDK transcripts instead of entering a crash loop
Clean shutdown tracking (VoiceManager.ts) - Distinguishes expected worker exits from crashes for accurate logging

All changes are working correctly with no blocking issues.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds three unrelated fixes: null-byte rejection in attachment path validation, corrupted SDK resume detection with automatic session-drop recovery in AgentManager, and an expectedExit flag in VoiceManager to distinguish intentional worker shutdowns from crashes during exit logging.

Changes

Attachment Path Validation

Layer / File(s) Summary
Reject null-byte paths
src/main/ipc/attachmentHandlers.ts
Adds a guard in the attachmentAddPaths handler to throw an error when a path contains a null character, alongside existing string/length checks.

AgentManager Resume Corruption Recovery

Layer / File(s) Summary
Corrupted resume detection and self-healing
src/main/managers/AgentManager.ts
runWithRecovery tracks a resumeDropped flag, detects resume errors indicating an unfinished tool_use, deletes the stored sdk_session_id once via a new forgetSdkSession helper, and retries with a fresh SDK session.

VoiceManager Worker Exit Tracking

Layer / File(s) Summary
Track intentional shutdowns via expectedExit
src/main/managers/voice/VoiceManager.ts
Adds an expectedExit flag reset on worker fork and set before idle-timeout and dispose shutdown requests, used in the exit handler to log clean exits at info level versus warn for unexpected exits.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AgentManager
  participant SDK
  participant Persistence

  AgentManager->>SDK: resume session with sdk_session_id
  SDK-->>AgentManager: error (unfinished tool_use)
  AgentManager->>AgentManager: check resumeDropped flag
  alt not yet dropped
    AgentManager->>Persistence: forgetSdkSession(sessionId)
    Persistence-->>AgentManager: sdk_session_id deleted
    AgentManager->>AgentManager: continue retry loop
    AgentManager->>SDK: start fresh session
  end
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is vague and reads like a summary intro rather than a specific description of the code changes. Rename it to clearly state the main changes, such as the voice worker shutdown logging, AgentManager recovery fix, and IPC path validation.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch attachment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@BotCoder254 BotCoder254 merged commit 440b63b into main Jul 5, 2026
3 of 11 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@src/main/managers/voice/VoiceManager.ts`:
- Around line 54-55: The worker lifecycle in VoiceManager still allows
ensureWorker() to reuse an existing worker after shutdown has already been
requested, which can attach new capture/TTS work to a process that is about to
exit. Update the worker state handling around expectedExit and the shutdown path
so that a pending idle shutdown marks the worker as unavailable, and ensure
ensureWorker() either reforks or refuses reuse once shutdown has been requested.
Also make sure the resulting exit is not treated as a normal expectedExit if new
work was still pending.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 64e74d30-89b8-4b15-9ab7-1d0d27b68096

📥 Commits

Reviewing files that changed from the base of the PR and between 60222a9 and 8ef8a69.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • src/main/ipc/attachmentHandlers.ts
  • src/main/managers/AgentManager.ts
  • src/main/managers/voice/VoiceManager.ts

Comment on lines +54 to +55
/** Set when WE asked the worker to shut down, so its exit is not a crash. */
private expectedExit = false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant files and symbols first
ast-grep outline src/main/managers/voice/VoiceManager.ts --view expanded
printf '\n--- worker outline ---\n'
ast-grep outline src/main/voice/worker.ts --view expanded

# Show the relevant sections with line numbers
printf '\n--- VoiceManager.ts relevant lines ---\n'
sed -n '390,460p' src/main/managers/voice/VoiceManager.ts
printf '\n--- VoiceManager.ts idle/dispose lines ---\n'
sed -n '630,690p' src/main/managers/voice/VoiceManager.ts
printf '\n--- worker.ts shutdown handling ---\n'
sed -n '410,450p' src/main/voice/worker.ts

Repository: BotCoder254/limboo

Length of output: 10529


Guard against reusing a worker after shutdown is requested

ensureWorker() still treats the current worker as usable while an idle shutdown is already in flight, so new capture/TTS work can attach to a process that is about to exit. That exit is also counted as expectedExit, which hides the failure as a clean shutdown instead of a warning. Track a pending-shutdown state or refork before reusing the worker after shutdown has been requested.

🤖 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 `@src/main/managers/voice/VoiceManager.ts` around lines 54 - 55, The worker
lifecycle in VoiceManager still allows ensureWorker() to reuse an existing
worker after shutdown has already been requested, which can attach new
capture/TTS work to a process that is about to exit. Update the worker state
handling around expectedExit and the shutdown path so that a pending idle
shutdown marks the worker as unavailable, and ensure ensureWorker() either
reforks or refuses reuse once shutdown has been requested. Also make sure the
resulting exit is not treated as a normal expectedExit if new work was still
pending.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant