Skip to content

v1.3.230

Choose a tag to compare

@topcheer topcheer released this 01 Sep 02:11
· 398 commits to main since this release

Release v1.3.230

Note: the v1.3.229 tag was cut from a tree whose desktop release matrix
could not build (details below under "Release Pipeline"); its Release
workflow failed and no 229 artifacts were published. This release carries
the same content plus the pipeline fixes. Mobile 1.3.229 (versionCode
2026090101) did ship and is functionally covered by these notes.

CJK / Input Correctness

  • c766e68: long CJK drafts restored into the composer no longer render
    with the tail clipped — the classic "Chinese chars vanish from the input
    box but appear when sent" bug. composerCursorEnd now syncs the viewport
    (View()) before MoveToEnd(), because the textarea's internal
    repositionView clamps its scroll against the previous content; CJK hits
    this fast since soft-wrap fits only ~7 full-width runes per line at
    narrow widths. History recall (Up arrow) follows the same path now.
  • f03e5bb: web_fetch truncates by runes, not bytes — no more mojibake
    when fetched pages are capped (also stops double-cloning the transport)
  • 369096e: url_expand no longer swallows CJK characters and keeps
    balanced parentheses
  • 2882f0b: hooks panel accepts CJK input with rune-safe backspace;
    save errors are visible

TUI Fixes

  • #1391: shell completion no longer wipes agent cancel state; no shell
    re-entry after completion
  • #1385: first-install onboarding — no sentinel model, no stale
    discovery, no stuck spinner
  • #1389: stdout probe writes real bytes; loadSession acquires the new
    lock before releasing the old one
  • #1365: failed @mentions stay in the message instead of vanishing
  • #1381: lanchat # reply routes to the sender; send errors visible
  • #1362: lanchat DM/broadcast send failures surface instead of fake
    success
  • #1379: IM runtime failure no longer masquerades as success;
    impersonate delete persists
  • #1364: knight adhoc tasks cancelled on exit — no post-exit LLM billing
  • #1363: /knight approve global skills requires --confirm-global
  • #1361: shortenPath requires real path boundaries for prefix matches;
    escape check uses os.PathSeparator
  • #1366: /diff off the event loop with timeout; /diff <file> stat
    keeps the path; /cost reads under session lock
  • #1390: Ctrl+R sidebar toggle syncs all panels like handleResize
  • #1360: identical todo_write after /clear rebuilds the chat card
  • #1388: memory reflection reads only its own key — no cross-memory
    pollution

TUI i18n

  • #1372: ja catalog falls back to enCatalog; format verbs match call sites
  • #1373: ko catalog restores format verbs; help.text translated
  • #1376: zh model-panel error keys; wechat/whatsapp no_bot keys
  • #1374: QQ panel actions hint shows d/e/q keys in all 10 languages
  • #1375: Signal/Twitch QR flow feedback — silent paths now speak

Tool Fixes

  • #1358: write_file records its own writes — no more stale misreport
  • #1356: ExitWorktree --force only when discard_changes authorized
  • #1357: web_search allowed_domains exempt from per-domain dedup cap
  • #1352: DDG result-block regex no longer over-matches structural wrappers
  • #1349: wait_agent wait_seconds capped at 30 minutes like sleep
  • #1359: AtomicWriteFile resolves symlinks — writes the real target,
    keeps the link
  • #1348: warp keystroke failures propagate; ctx threaded through the
    osascript chain

Tunnel / Relay / Desktop

  • #1354: relay resume supersedes the old connection; acks validated for
    ownership and monotonicity — fixes double delivery on mobile network
    switches
  • #1400: tunnel projection cache no longer evicted on save failure; relay
    local-host heuristic explicit
  • #1401: replay comparator strict weak ordering; compact-qualified
    remaining key
  • #1350: trayhelper built into desktop bundles — tray was dead in production
  • #1351: tray shutdown race closed — no ghost icon or orphan helper
  • #1403: tray helper spawn under lock, respawn backoff, listener closed
    on teardown
  • #1355: matrix GetHistoryVisibility fails closed on state fetch errors
  • #1399: wecom create persists IM.Enabled — bot no longer vanishes after
    restart
  • #1369: extpane iterm2 probe timeout; transient failures retry instead
    of permanent dark
  • #1368: extpane compactPreview normalizes before truncating

CI / Infrastructure

  • df8aa1d: the Format job no longer poisons the shared setup-go module
    cache with an empty stub (immutable per key), which forced every run to a
    full network download and turned proxy.golang.org stream errors into three
    spurious red CIs
  • 0ed3a70: relay Dockerfile builder bumped to golang:1.26-alpine to
    match go.mod
  • goroutine protection gate: trayhelper socket-death watcher allowlisted
    with justification (separate-process helper, bounded read loop, respawn
    handled by the main app)

Release Pipeline

  • db5fc47: desktop release matrix builds green again (broken since the
    tray series landed; v1.3.228 Release failed the same way)
    • tray action handlers (show / new-session / quit) were defined only in
      tray_darwin.go while the socket dispatch in tray.go compiles on every
      platform - Windows and Linux builds died on undefined methods. The
      handlers are pure Wails runtime calls and now live in tray.go
    • trayhelper is now built with CGO_ENABLED=1 on darwin: energye/systray's
      darwin backend is Objective-C CGO (Cocoa), so CGO_ENABLED=0 dropped
      every platform symbol and the build failed
  • every fix in this release ships with a regression test pinning the
    contract