Skip to content

v1.3.157

Choose a tag to compare

@topcheer topcheer released this 17 Jul 04:41

ggcode v1.3.157

Highlights

Concurrency safety hardening

  • Broker data race fixed: onCommand/onConnect callback fields were read in Session goroutines without locks while being written by setters. Added callbackMu (RWMutex) with copy-then-call pattern.
  • Nested lock order eliminated: enqueueWithBytes/enqueueSnapshotEvent held outMu while calling SessionID()/AuthorityEpoch() which internally acquire sessionMu.RLock(). Moved reads before lock acquisition to remove the implicit outMu → sessionMu dependency.

Data integrity fixes

  • migrateMessageIDs: WriteString/Close errors were silently ignored — disk-full conditions would lose session data without any error. All write paths now check errors and clean up.
  • backfillIDs/backfillTimestamps: Same write-error ignoring pattern fixed with error checking + Sync().
  • 8 session persistence sites: AppendMetaToDisk errors were silently swallowed (_ =) across sidebar preference, model selection, context window probe, binding state, and async usage recording. All now log via debug.Log.

Crash prevention

  • git commit nil panic: When injecting Co-Authored-By trailer, the shell command was rebuilt with cmd, _, _ = NewShellCommandContext(...) — ignoring the error. If rebuild failed, cmd was nil and subsequent cmd.Dir / configureCommandCancellation(cmd) would panic. Now returns a proper error Result.

Fixes and improvements

Performance

  • emitUsage/emitMetric Lock→RLock: High-frequency read-only callbacks used exclusive Lock(), causing unnecessary contention. Switched to RLock().
  • HandleInbound persistBinding merge: Each inbound IM message wrote binding state to disk twice (once for ChannelID, once for LastInboundMessageID). Merged into a single write.
  • CountTokens capability caching: context.WithTimeout was created on every Add() call even for providers (OpenAI/Gemini) that use pure local estimation. After first probe, local-estimation providers skip context creation entirely. Cache is reset on SetProvider.

User experience

  • Bilingual error messages: UserFacingError always returned Chinese text regardless of interface language. New UserFacingErrorLang(err, lang) provides English equivalents for all 12+ error categories (401/403/429/timeout/network/400/etc.). English TUI users no longer see Chinese errors.
  • Model switch feedback: Selecting a model from the panel silently closed it. Now shows a system message confirming the switch.
  • /help completeness: 15+ slash commands were missing from help output (/retry, /edit, /files, /chat, /nick, /tunnel, /rules, /allow, /inspector, /reflect, /impersonate, /stream, /stats, etc.). Both EN and ZH catalogs updated.
  • /retry hint in errors: Transient error messages (429/timeout/network) now suggest "Type /retry to resend".
  • Keyboard shortcut docs corrected: Ctrl+T was documented as "open tunnel" (actually config scope toggle), Ctrl+N/P descriptions were wrong, and Ctrl+G/Ctrl+\/Esc+Esc/Alt+Up-Down were missing. Both EN and ZH help texts corrected.

Reverted

  • Stream UI throttle (from auto-optimization round): Added 50ms time-based throttle to appendStreamChunk to reduce markdown re-renders. Reverted because it broke assistant message rendering — the existing three-layer cache (SetText dedup → streamRenderCache incremental blocks → CachedItem width cache) already handles this efficiently.

Upgrade notes

  • No breaking changes
  • No config migration required
  • All fixes are backward compatible

Compare

Full changelog