Previously LANG/LC_ALL were only set on Windows, so git stderr was
localized on macOS/Linux and substring checks for English messages
(e.g. 'unknown revision or path not in the working tree') silently
failed — empty-repo/missing-branch cases surfaced as red error
banners in the Git log panel instead of rendering as empty lists.
Reintroduce a local not-a-git-repo fallback state in the git log panel so non-repo errors still render the dedicated empty state when workspace state streaming is degraded.
Improve git repository preflight classification by distinguishing missing paths, permission issues, and non-directory targets before checking .git presence.
Add not_a_git_repository to the frontend AppErrorCode union for explicit typed handling.
Consolidate `.git` presence detection into a shared `git_repo` module used by both the workspace state watcher and the command preflight helper, replacing duplicated local definitions.
Introduce `AppErrorCode::NotAGitRepository` (HTTP 422) and preflight eleven frontend-callable git commands (log, status, list-branches, diff, diff-with-branch, show-diff, show-file, push-info, list-remotes, list-all-branches, commit-branches) so non-git folders short-circuit with a structured error instead of leaking locale-dependent git stderr.
Frontend `isNotAGitRepoError` checks the error code first and falls back to a multi-language regex list centralized in `src/i18n/git-error-patterns.ts`, covering the nine languages git actually translates into.
Wire the git log panel to `workspaceState.isGitRepo` rather than a local cached flag, so running `git init` or deleting `.git` externally propagates through the watcher and refreshes the panel automatically.
- Replace hardcoded "Claude Code" in agent_responding with each session's actual AgentType label; store agent_type on ActiveSession and populate it in both task-start and resume paths
- Remove silent ClaudeCode fallback in resolve_agent_type; /task now prompts the user to pick an agent when none is selected and the folder has no default
- Move session command strings out of session_commands.rs into i18n.rs with full 10-language coverage (en/zh-CN/zh-TW/ja/ko/es/de/fr/pt/ar)
- Fix French accent and wrap Latin agent name with Arabic bidi isolates (FSI/PDI) for consistent rendering across Telegram/Lark/WeiXin clients
- Release the bridge lock before the get_lang DB lookup in the content_delta flush path to avoid cross-session contention
- Log unknown agent_type fallback in conversation_service::parse_agent_type for observability
Reconcile the cached is_git_repo flag against the filesystem on every watch flush so `git init` or deletion of .git is reflected immediately: sync the stored flag, drop stale git_snapshot data when the repo goes away, emit a meta delta when presence flips without any data change, and mark the event as requires_resync so the frontend re-fetches the snapshot to pick up the new flag.
Replace the title-bar branch polling interval with a self-adjusting setTimeout chain that backs off to 60s when get_git_branch returns null or throws and drops back to 10s once a branch is detected, so branches created externally recover within one slow tick without hammering the backend on non-git folders.
Gate git refresh on .git presence so file churn in non-git workspaces no longer produces endless resync_hint events, and silently log tree/git refresh errors during watch flushing instead of flagging requires_resync, which turned transient failures into self-reinforcing loops.
Degrade gracefully when the filesystem watcher fails to attach (e.g. permission denied, inotify quota): keep the initial snapshot, surface a degraded flag, and expose a store-level restart that the banner uses to retry attachment after the root cause is fixed.
Propagate is_git_repo through the snapshot so the git log and changes tabs render a dedicated "Not a Git repository" empty state instead of raw git stderr with a useless retry button.
Stop polling get_git_branch from the title bar once it returns null and re-arm on visibility change.
Add translations for the new banner, empty-state, and retry keys across all ten locales.
- Persist user-supplied access token and last-used port in app_metadata, falling back to defaults when unset
- Atomically guard concurrent starts via compare_exchange with RAII rollback of the running flag
- Wrap token and port persistence in a single SeaORM transaction to prevent partial writes
- Classify bind errors (port in use, permission denied, address unavailable, invalid address) into stable i18n keys
- Localize start-failure messages across all 10 supported languages
- Codex: decouple active_agent_count decrement from close_agent target
parsing and reset counter on turn_context to prevent main assistant
messages from being swallowed when close_agent events are malformed
- Codex: use exact filename match with separator-aware fallback and
sorted candidates for deterministic subagent session file resolution
- Codex/OpenCode: truncate subagent tool call previews to 500 chars
- OpenCode: batch-load all subagent tool calls in a single SQL query
instead of per-task N+1 queries to avoid slow detail page loads
- Streaming: restrict positional child grouping fallback to in-progress
agents only, preventing top-level tool calls from being incorrectly
folded into completed Agent cards
- Tests: update Claude context window assertions to match 1M default
Refactor cleanAgentOutput to a sequential non-recursive pipeline: unwrap
JSON containers first, then strip task_id session lines, then extract
<task_result> content. Also apply cleaning to in-progress agent output
during streaming, not just completed results.
Forward the previously-dropped `locations` and `meta` fields from ACP
SDK ToolCall/ToolCallUpdate events through to the frontend. The meta
field carries `claudeCode.parentToolUseId` which enables precise
parent-child matching for concurrent Agent tool calls during streaming.
- Forward locations/meta in Rust AcpEvent types and connection handlers
- Use parentToolUseId for exact agent→child mapping, with position-based
fallback for agents that don't provide it (Codex, OpenCode)
- Replace `any` types with proper ToolCallMeta / unknown types
- Add runtime guards for meta field parsing (defensive against
unexpected shapes from different agents)
- Cache inferLiveToolName results per tool_call_id to avoid redundant
computation across Phase 1 and Phase 2
- Lazy-construct agentStats only when children exist
Support Agent card rendering during live streaming responses for Claude
Code, Codex CLI, and OpenCode. Previously Agent cards only rendered for
loaded/historical messages parsed from the DB.
- Fix tool name inference: subagent_type in input now returns "agent"
instead of "task"; add spawn_agent/wait_agent/close_agent aliases
- Group sub-agent tool calls inside parent Agent cards during streaming
using position-based heuristic (ACP SDK lacks parent_id tracking)
- Clean raw Agent output (JSON content blocks, XML task_result wrappers)
- Emit agent_stats with nested tool calls so AgentToolCallPart renders
child execution inline, matching the loaded message appearance
Transform OpenCode "task" tool calls with subagent_type into unified
Agent card display: rewrite as "Agent" tool with subagent_type, prompt,
description, and model; compute duration from time fields; query
sub-agent session parts from SQLite for nested tool call lists; extract
<task_result> content to strip preamble noise from agent output; guard
Streamdown code plugin against unsupported Shiki language identifiers
(e.g. "##", "function") in fenced code blocks from tool output.
Transform Codex spawn_agent/wait_agent/close_agent into unified Agent
card display: rewrite spawn_agent as "Agent" tool with subagent_type,
prompt, and description; correlate final results from wait_agent and
close_agent outputs; parse sub-agent session JSONL files for nested
tool call lists; suppress intermediate status messages during agent
execution; clean exec_command output to show only the command and its
result.
Render Agent/Explore/Plan tool calls in a visually distinct collapsible
container with colored left border, replacing the generic tool card. Parse
subagent JSONL transcripts from {sessionId}/subagents/ to extract and
display the actual tool calls (Bash, Read, Grep, etc.) the subagent
executed, reusing the existing ToolCallPart for consistent appearance.
- Add AgentToolCallPart component with collapsible body, prompt section,
execution stats, and nested tool call list via render prop injection
- Add AgentExecutionStats and AgentToolCall types (Rust + TypeScript)
- Parse toolUseResult.agentId to locate and read subagent JSONL files
- Validate agentId against path traversal before filesystem access
- Pass agentStats through adapter for both ID-matched and positional
tool result pairing
- Strip agentStats in nested render to prevent recursive Agent expansion
- Add i18n keys for agent UI labels across all 10 languages
The upstream Codex.Color icon from @lobehub/icons renders an SVG with a
white background rectangle, which appears as a white square on dark
backgrounds. Replace it with a custom CodexColorIcon that renders only
the logo path with its original gradient fill, and adjust the viewBox to
better fit the content area.
Replace lexicographic sort with numeric (major, minor, patch) sort
across all 7 version-directory sort sites in find_node_bin_dir.
Lexicographic sort incorrectly orders v20.9 > v20.11 (because '9' > '1')
which could select an older Node.js version and cause agent preflight
failures for version-gated agents like OpenClaw (requires >=22.12.0).
- Fix thread safety: replace #[tokio::main] in codeg_server with manual
runtime construction so set_var runs before any worker threads exist
- Fix nvm alias branch: sort matched candidates (read_dir order is
undefined) and skip non-numeric aliases like lts/* that cannot be
resolved without full nvm evaluation
- Fix HOME missing: accept Option<&Path> for home so env-var-only
discovery (NVM_HOME, VOLTA_HOME, FNM_DIR, etc.) still works in
Docker / systemd environments without HOME set
- Refactor resolve_dir to accept an env var chain, eliminating all
inline Option chains for fnm, nvm-windows, mise, and scoop
Expand find_node_bin_dir to support 9 version managers / installation
methods across macOS, Linux, and Windows:
- nvm (Unix): fix alias duplicate candidates, skip symbolic aliases
like lts/* that cannot be resolved without full nvm evaluation
- nvm-windows: detect via %NVM_SYMLINK% and %NVM_HOME% with correct
directory layout (node.exe directly in version dir, no bin/)
- fnm: use platform-correct defaults (%APPDATA%/fnm on Windows,
$XDG_DATA_HOME/fnm on Unix) instead of hardcoded Unix path
- volta: validate that a concrete Node image exists before adding
the shim directory, preventing cryptic errors when volta is
installed but no Node version has been set
- asdf (Unix): $ASDF_DATA_DIR or ~/.asdf/installs/nodejs/
- mise/rtx (cross-platform): $MISE_DATA_DIR with XDG fallback
- n (Unix): $N_PREFIX or /usr/local/n/versions/node/
- Homebrew (macOS): /opt/homebrew and /usr/local prefixes
- Scoop (Windows): nodejs-lts and nodejs app detection
Also improve production readiness:
- Document thread-safety requirements for set_var (unsafe in ed. 2024)
- Add warning log when HOME is unset (Docker / minimal containers)
- Clarify FNM_MULTISHELL_PATH scope (server binary only, not GUI)
- Note lexicographic sort limitation for semver edge cases
softprops/action-gh-release defaults draft to false, which publishes
the release prematurely before the publish-release job runs. Switch to
gh release upload which only uploads assets without modifying release
state, avoiding both the premature publish and the duplicate draft
release issues caused by the GitHub API not returning drafts via
getReleaseByTag.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- feat(settings): add ChatGPT OAuth device code login for Codex CLI, allowing users to log in with their ChatGPT account directly from the agent settings page without leaving the app.
- feat(chat): stream partial tool output during live agent response so running tools (e.g. bash stdout) render in real time instead of appearing blank until completion.
- fix(ui): sharpen dialog rendering with flex centering and stronger ring to eliminate subpixel blur on non-retina displays.
- chore(acp): bump bundled agent versions in registry.
-----------------------------
# 发布版本 0.8.8
- 功能(设置):为 Codex CLI 新增 ChatGPT OAuth 设备码登录,用户可直接在代理设置页面使用 ChatGPT 账号登录,无需切换到终端操作;
- 功能(聊天):实时流式显示工具执行中的部分输出(如 Bash 标准输出),不再等到工具完成后才渲染内容;
- 修复(界面):优化对话框渲染,使用 flex 居中替代 translate 居中并加强边框环,消除非 Retina 屏幕上的亚像素模糊问题;
- 维护(ACP):更新注册表中内置代理的版本号。
Add OAuth device code flow for Codex CLI official subscription auth,
allowing users to log in with their ChatGPT account directly from the
agent settings page without using the terminal.
- Backend: two new endpoints (codex_request_device_code, codex_poll_device_code)
that handle the OpenAI OAuth device code flow and return tokens to frontend
- Frontend: login UI with verification URL, copyable user code, polling status,
15-minute timeout, and auto-save via existing persistEnv/persistConfig path
- Auth.json written in Codex CLI compatible format (nested tokens, account_id,
last_refresh) so codex-acp can use OAuth tokens directly
- Show logged-in status and re-login option when tokens are present
- Remove auth.json textarea from Codex settings UI
- i18n: all 10 languages updated with new login-related keys
Replace translate-based centering with a grid place-items-center wrapper
to eliminate half-pixel subpixel blur on non-retina displays. Strengthen
the content border by switching from ring-foreground/5 to ring-border
and adding shadow-2xl for a clearer visual boundary.
Live tool calls that produce output while running (e.g. streaming bash
stdout from Codex) now render their partial output in real time instead
of appearing blank until the tool completes. The tool card keeps its
running visual state — spinner and 24KB tail truncation — while chunks
arrive, and transitions to the completed state once the final status
lands. A WeakMap keyed on the ACP reducer's chunks-array identity
memoizes the joined output so repeated renders don't re-run O(n) string
concatenation.