Skip to content

v1.3.87

Choose a tag to compare

@topcheer topcheer released this 27 Jun 13:39
· 6069 commits to main since this release

v1.3.87

LAN Chat Agent Availability + Desktop UX Improvements + Session Robustness

New Features

LAN Chat agent availability — The lanchat tool's list output now includes
an agent_busy field for each participant, indicating whether that node's agent
is currently processing a task. This allows LLMs to make informed routing decisions
when delegating work across instances.

  • AgentBusy field added to Participant struct, propagated via presence exchange
  • Hub.SetAgentBusy(bool) method — called automatically when agent runs start/end
  • Wired in TUI (startAgent/handleAgentDone), Desktop (sendMessageData/completion)
  • Tool Description() updated to guide LLMs: "prefer idle agents (agent_busy=false)"
  • Presence rebroadcast on state change so peers learn immediately

TUI session auto-selection — When ggcode tui starts without --resume,
it now iterates through all workspace sessions (newest-first) and loads the first
unlocked one. Previously it only tried the single most recent session and fell back
to the interactive picker if that was locked.

  • With N sessions and N+1 instances starting sequentially: each instance gets a
    different session; the last creates a new one.
  • Store.ListForWorkspace(workspace) added to session.Store interface.

Desktop identity editor — Click your nickname in the ChatView top bar to edit
your LAN Chat nickname, role, and team via a modal dialog. Previously the desktop
had no UI for editing identity — only the LanChatView sidebar had a basic prompt().

Desktop markdown rendering for LAN Chat messages — Agent-to-agent LAN Chat
messages now render as formatted markdown in both TUI and Desktop, instead of raw
source text. Regular user input remains plain text.

Desktop sidebar default hidden — Session list sidebar is now collapsed by
default on startup. Click the sidebar toggle in the NavRail to open it.

Bug Fixes

Tool call reconciliation — Unpaired tool_use blocks in conversation history
(caused by crashes, interruptions, or session restoration) now get matching
tool_result entries with a "cancelled" status automatically. This prevents LLM
API errors from providers that require every tool_use to have a tool_result.

  • ContextManager.ReconcileToolCalls() — handles session restore and runtime
    interruption scenarios
  • Orphan tool_result blocks (whose tool_id has no matching tool_use) are removed
  • Called from RestoreSessionIntoAgent() and at the start of RunStreamWithContent()

LAN Chat agent message deduplication — Agent-directed messages (@agent) no
longer cause duplicate rendering, persistence, or event emission.

  • Hub: skips persistMessage() for agent-directed DMs (session JSONL is the
    source of truth)
  • Hub: skips onMessage callback for agent-directed DMs (avoids duplicate
    system message + agent loop injection)
  • TUI: skips system message rendering for agent-directed DMs (already rendered
    as user message via agent loop)
  • Desktop: skips lanchat:message event emission for agent-directed DMs

Desktop session self-lock fix — The session list no longer shows the current
session as "locked". ListSessions now skips the lock check for the session held
by the current process (ChatBridge.CurrentSessionID()), since TryAcquireSessionLock
would fail on our own flock.

Desktop startup session history — The desktop app now renders session history
on startup. Previously, EnsureSession() ran in Go startup() before the React
frontend mounted, so the session:changed event was lost. Now the frontend polls
GetCurrentSessionID() 500ms after mount to sync state.

Desktop locked session protection — Locked sessions in the sidebar show a lock
icon, appear dimmed, and cannot be clicked. A toast informs the user that the
session is held by another instance.

Improvements

LAN Chat tool definition clarity — Restructured the lanchat tool description
and parameter docs to clearly distinguish the three messaging scopes:

  • send = DM one participant (requires to=<node_id>)
  • send_team = broadcast to a team (requires team=<name>)
  • broadcast = broadcast to ALL participants (no to or team)

Debug log noise reduction — mDNS lookup logs and layout calculation logs are
now gated behind debug.IsVerbose(), reducing log spam in normal operation.