Skip to content

v1.3.167

Choose a tag to compare

@topcheer topcheer released this 20 Jul 05:08

v1.3.167

Critical Fixes

Cron Scheduler Crash

  • fix(cron): double mutex unlock in timer callback causes panic crash (98b935ca)
    • Recurring cron jobs silently stopped firing after the first execution due to a double-unlock panic in the timer callback. The defer s.mu.Unlock() added for TOCTOU protection conflicted with existing manual unlock calls, causing sync: unlock of unlocked mutex panic. The recover() caught the panic but the goroutine exited without rescheduling.

Mobile Sync Overlay on Every Message

  • fix(relay): close slow client connection on send buffer drop to prevent ordinal gaps (8993fda0)
    • Relay's sendRaw had a 2s timeout that silently dropped live-forward events when the mobile client's send buffer was full. Dropped events created ordinal gaps that triggered full-screen "Syncing with relay" overlays on every message. Now closes the slow client's WebSocket connection (code 1013) so it reconnects and resumes from its last ACKed cursor.
  • fix(mobile): relay sync overlay — barrier ordinal check missing _resumeCompleted guard (2e7488b9)
    • The active_session barrier ordinal check triggered sync overlay even after initial sync was complete. Added !_resumeCompleted guard so it only shows during initial connect.
  • fix(mobile): gap recovery relaySync overlay after resume completes (e8eba2ac)
    • Gap recovery path (_scheduleGapRecovery and _runScheduledGapRecovery) also triggered sync overlay without checking _resumeCompleted. Added the same guard to both call sites.

Concurrency & Race Condition Fixes

  • fix(mcp): c.closed data race — bool to atomic.Bool (6d6548cb)
    • Abort() wrote c.closed without holding c.mu while sendRequest/sendNotification read it under c.mu. Changed to atomic.Bool.
  • fix(im): WeCom and Mattermost WebSocket concurrent writes without mutex (df7e0042)
    • Heartbeat goroutines and Send/TriggerTyping goroutines wrote to the same WebSocket concurrently, causing gorilla/websocket panic. Same pattern as Discord (fixed in ac99cab5). Added writeMu sync.Mutex.
  • fix(a2a): CancelTask races with execute completion (d8a1080e)
    • CancelTask's Canceled state was silently overwritten by execute()'s Completed when they raced. Added terminal state guard in updateStatus().
  • fix(session): runMaintenance saveIndex without cross-process lock loses entries (b708030a)
    • runMaintenance called saveIndex without holding the cross-process flock. If another process (Desktop + CLI) appended to the index during maintenance, the new entry was overwritten. Now acquires flock, reloads index, and merges.
  • fix(context): tokenCountLocked called after mu.Unlock in ApplyCompactResult (df231351)
    • ApplyCompactResult called tokenCountLocked() after releasing mu, racing with concurrent Add/RecordUsage. Reused the value computed under lock.
  • fix(debug): cleanupStaleLogs runs before defaultLogDir is set + liveSink data race (c48b04f6)
    • Stale log cleanup silently did nothing because defaultLogDir was assigned after cleanupStaleLogs() was called. Also fixed liveSink read without lock racing with SetLiveSink.

Provider Fixes

  • fix(openai): usage leaks across retry attempts (844fca81)
    • var usage *TokenUsage declared outside the retry loop retained failed attempt's stats. Reset to nil at the start of each attempt. Same pattern as Gemini (fixed in 922135df).
  • fix(gemini): retryDelay double-call shows wrong wait time (2197ceda)
    • retryDelay() with ±25% jitter was called twice — once for display, once for sleep — showing incorrect wait times. Stored to variable. Same pattern as Anthropic (fixed in 3c3aa53a).

Browser Automation

  • fix(browser): 7 functions missing CDP timeout protection can hang indefinitely (d25c01a9)
    • doExtract, doScreenshot, doEvaluate, doLinks, doScroll, doBack, doContent used bare tab.ctx (no deadline). Chrome stall (JS infinite loop, page never loads) caused permanent hang. Added context.WithTimeout matching the pattern of 11 other functions.

Security

  • fix(permission): notebook_edit bypasses sandbox (cfdcbe9d)
    • extractFilePaths didn't recognize notebook_path as a path field, so sandbox checks were silently skipped. notebook_edit could write .ipynb files outside the workspace in bypass/autopilot modes.

Other Fixes

  • fix(tui): handle SIGHUP for graceful shutdown on terminal close (0577dc9a)
    • SIGHUP (terminal close, SSH disconnect, display sleep) killed the process immediately without saving session. Now sends tea.QuitMsg for graceful shutdown.
  • fix: auth exchangeCode wraps wrong error, pollDeviceToken swallows unmarshal, issuerURL race, sleep blocks cancel (4629ab0a)
  • fix: knight Stop() doesn't wait for runLoop exit (8eee9787)
  • fix: swarm handleMessage blocks forever on ReplyTo channel (098ef360)
  • fix: ACP Close() doesn't wait for readLoop exit (8d34846d)
  • fix: lanchat UDP path data race in nick change (fa773e14)
  • fix: cron timer panic crash + deleted job revival, a2a multi-turn messages + artifacts race (9f665da0)
  • fix: Discord adapter WebSocket concurrent writes without mutex (ac99cab5)
  • fix: keys.env parent directory created with 0755 instead of 0700 (5f33a852)
  • fix: Copilot SetImpersonatedUA data race, Gemini usage leaks across retries (922135df)
  • fix: verify.go uses Unix-only syscall causing Windows cross-compile failure (6ce5b994)
  • fix: edit_file anchored path misjudges indent style (01dc7590)
  • fix: stripAnsiForChat swallows text after non-SGR escapes, git tools byte-truncate UTF-8 (5eae86e5)
  • fix: RecordUsage undercounts Anthropic CacheWrite, Summarize stale system prompt TOCTOU (f1c13193)
  • fix: MultiFileWrite uses non-atomic os.WriteFile (1ac836eb)
  • fix: MCP Abort doesn't kill process group or mark closed (2e0cb897)
  • fix: multi_file_write and notebook_edit bypass sandbox path checks (54b3d4a8)
  • fix: ACP DeliverResponse blocks readLoop on duplicate JSON-RPC responses (d03b7ed5)
  • fix: verify CombinedOutput hangs on timeout, swarm data races (cd79741c)
  • fix: swarm executeTask swallows RunStream error (f27603f5)
  • fix: Anthropic stream body leak, both providers send Done after Error (d2f36c52)
  • fix: updateIndex overwrites corrupt index with single entry (4388d2b8)
  • fix: adaptive_cap self-deadlock, context manager version race (94fa4ba3)
  • fix: Anthropic Chat missing retry, copilot UA data race, retry delay double-call (3c3aa53a)
  • fix: project memory dynamic loader disabled by premature SetProjectMemoryFiles (77b9460b)
  • fix: MCP uninstall stale entries in 4 missed callers (392fd43f)