Commit Graph

202 Commits

Author SHA1 Message Date
xintaofei
273a8cd7ff fix(macos): detect untracked file deletion via Finder as remove event
Finder moves files to Trash (rename) instead of deleting them, which
may be reported as `Modify(Name)` rather than `Remove` by the file
watcher. This caused untracked files to lose their red color without
being removed from the tree. Fix by checking disk existence in the
event batch emitter and promoting the kind to "remove" when a changed
path no longer exists.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 22:11:18 +08:00
xintaofei
268b33d2ee fix(macos): update TRAFFIC_LIGHT_Y 2026-04-13 21:01:20 +08:00
xintaofei
41b28001af fix(frontend,macos): reduce dark mode white flash on window open
Detect dark/light mode before React hydrates to eliminate the visible
white-to-dark flash when opening windows in dark mode.

Frontend:
- Inline script now reads next-themes localStorage key and applies
  .dark class, colorScheme, and backgroundColor on <html> before first
  paint
- Add CSS-only fallback via prefers-color-scheme media query in an
  inline <style> tag that fires before any JS executes

macOS backend:
- Detect system dark mode via `defaults read -g AppleInterfaceStyle`
  (cached with OnceLock) and set native window background color to
  match dark theme in apply_platform_window_style
- Persist user appearance mode preference (dark/light/system) to DB
  alongside zoom level so new windows use the correct background
- Add update_appearance_mode Tauri command; frontend syncs on mount,
  on settings change, and on cross-window storage events

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:15:13 +08:00
xintaofei
e05ae76453 fix(macos): persist zoom level to DB so traffic lights use correct position on launch
Previously the welcome window (or any startup window) always used the
default CURRENT_ZOOM of 100, ignoring the user's saved zoom preference
stored in frontend localStorage. Now update_traffic_light_position also
writes the zoom value to the app_metadata DB, and setup() reads it back
before creating any window.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:10:09 +08:00
xintaofei
17bae372a1 fix(macos): adjust traffic-light Y baseline from 18 to 17 for better vertical alignment
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 09:38:37 +08:00
xintaofei
a763adaf36 feat: stream real-time progress for agent SDK install/upgrade/uninstall
Replace the spinner-only UX with live log output during agent SDK
operations, matching the existing OpenCode plugin install experience.

Backend: emit structured events (started/log/completed/failed) via
EventEmitter during npm install and binary download. npm commands now
run with piped stdio for line-by-line streaming; binary downloads
report chunked progress every 1 MB.

Frontend: subscribe to `app://agent-install` events through a new
`useAgentInstallStream` hook and render a theme-aware log terminal
below the preflight checks panel.

Also fixes the install log container in both agent settings and the
OpenCode plugins modal: auto-scroll no longer shifts the outer page,
and colours now follow the active light/dark theme.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 21:43:54 +08:00
xintaofei
25def31a23 fix(windows): force UTF-8 encoding for all spawned child processes
- Set UTF-8 environment variables (PYTHONUTF8, PYTHONIOENCODING, LANG,
  LC_ALL) on all child processes via process.rs helpers
- Configure PTY terminals per shell flavor: chcp 65001 for cmd.exe,
  [Console]::OutputEncoding for PowerShell, LANG=C.UTF-8 for Git Bash
- Use /K and -NoExit for interactive shells to avoid nested processes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:47:31 +08:00
xintaofei
843cf8df19 feat(macos): set traffic-light position via Tauri builder API and sync with zoom
Use Tauri's native `traffic_light_position()` builder method to position
macOS window controls instead of runtime objc2 calls. A global AtomicU32
tracks the current zoom level so newly created windows reflect the latest
zoom. The frontend syncs zoom changes to the backend via a new
`update_traffic_light_position` command.

- Add `traffic_light_position()` to `apply_platform_window_style` builder
- Add `CURRENT_ZOOM` atomic and `traffic_light_position()` helper
- Register `update_traffic_light_position` Tauri command
- Add `syncTrafficLightPosition` in appearance-provider to sync on zoom
  change, mount, and cross-tab storage events
- Consolidate `ensure_windows_undecorated` calls into `post_window_setup`
- Remove dead `on_window_resized` no-op and its Resized event listener

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:11:40 +08:00
xintaofei
9ab090a2b2 fix(acp): avoid false-positive comment detection on URLs in opencode.json
The naive // and /* check triggered on URLs like https://... inside
string values. Now we only reject the file as JSONC when serde_json
parsing fails AND comment-like sequences are found.
2026-04-12 12:00:47 +08:00
xintaofei
023e4c5514 fix(acp): pin @latest for all plugins and enable button when only floating versions exist
- install_missing_plugins now pins ALL @latest specs (not just newly installed)
- When nothing is missing but @latest exists, the pin-only path runs
- Modal button switches to 'Pin @latest Versions' when no missing plugins
- Added pinVersions i18n key for 10 languages
2026-04-12 11:56:55 +08:00
xintaofei
4397b0eae7 feat(acp): auto-pin @latest plugin specs to installed versions after install
After a successful plugin install, read the actual installed version from
node_modules and replace @latest in opencode.json with the pinned version.
This prevents opencode from hitting the npm registry on every startup.

Also add a preflight warning when @latest specs are detected, guiding
the user to install via the plugin manager to auto-pin.
2026-04-12 11:47:01 +08:00
xintaofei
6459e5286a fix(acp): use XDG paths for opencode config/cache instead of platform-native dirs 2026-04-12 11:31:45 +08:00
xintaofei
21800f25a1 style(acp): fix clippy warnings in opencode_plugins 2026-04-12 10:59:37 +08:00
xintaofei
996945223c feat(acp): add opencode plugin list/install/uninstall commands and routes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 10:21:04 +08:00
xintaofei
8c807b62d3 feat(acp): integrate opencode plugin check into preflight
Add InstallOpencodePlugins variant to FixActionKind and wire
opencode_plugins::check_opencode_plugins into check_binary_environment
so preflight surfaces missing/installed plugin status for OpenCode agents.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 10:15:48 +08:00
xintaofei
0901758937 feat(acp): implement install_missing_plugins and uninstall_plugin
Add concurrency lock (PLUGIN_OP_LOCK), install/uninstall functions with
bun subprocess management, progress event streaming via EventEmitter, and
protected-package guard for @opencode-ai/* internals.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 10:12:34 +08:00
xintaofei
26cf618bd4 feat(acp): add resolve_bun_binary and atomic_rewrite_opencode_json helpers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 10:10:13 +08:00
xintaofei
c5d5f854b5 feat(acp): implement check_opencode_plugins detection
Add check_opencode_plugins() to read ~/.config/opencode/opencode.json,
parse the plugin[] array, and cross-reference against
~/.cache/opencode/node_modules/ to report installed vs. missing plugins.
Also adds opencode_config_path, opencode_cache_dir, and
has_project_opencode_config helpers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 10:08:27 +08:00
xintaofei
8c775d29e7 feat(acp): add opencode_plugins module with types and parse_plugin_spec
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 10:06:25 +08:00
xintaofei
1c1738298b fix(acp): harden session-page connection and localize backend errors
- Session-page connect never triggers download/install; returns
  SdkNotInstalled immediately and prompts the user to install from
  Agent Settings instead
- Binary agents now accept any cached version via
  find_best_cached_binary_for_agent so stale caches still connect
- Bound Initialize handshake with a 60s timeout and convert it to
  AcpError::InitializeTimeout via a sentinel in run_connection
- Spawn background task owns ConnectionManager map insertion and
  removes the entry on exit through an RAII guard that survives
  panics, preventing leaked stale entries
- AcpError gains SdkNotInstalled and InitializeTimeout variants plus
  a stable code() identifier; AcpEvent::Error carries code so the
  frontend can render localized messages by key
- Frontend preflight now runs for all connect sources; error event
  handler switches on code to show translated text for
  initialize_timeout, sdk_not_installed, platform_not_supported,
  process_exited, spawn_failed and download_failed
- Remove ConnectionStatus::Downloading enum variant, all frontend
  branches, and i18n strings; drop obsolete autoLinkFailedTitle,
  autoLinkPreflightFailed, preflightCheckFailedDefault and
  preflightFailedTitle keys across 10 locales
- Add backendErrors.* translations in 10 languages
- Diagnostic logging: always log agent stderr plus binary
  path/size/args/env keys and Initialize timing; gate stdin/stdout
  JSON-RPC tracing behind CODEG_ACP_DEBUG to avoid persisting user
  content into OS log files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 03:36:08 +08:00
xintaofei
5bda7d06e9 fix(experts): handle Windows junction removal when unlinking skill entries 2026-04-11 18:54:21 +08:00
xintaofei
d92cb8d619 chore: bump ACP agent SDK versions in registry 2026-04-11 18:43:49 +08:00
xintaofei
c34eb84caa fix(settings): default to appearance section instead of system
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 17:38:18 +08:00
xintaofei
1bb8624160 fix(chat): restore ~/.agents/skills/ as additional Codex skill dir
Codex CLI also reads skills from ~/.agents/skills/, so include it
alongside ~/.codex/skills/ in the skill storage spec. The Codex dir
stays first so it remains the preferred write target for new links,
while lookup and unlink scan both locations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 09:49:33 +08:00
xintaofei
19979d50d0 fix(chat): use ~/.codex/skills/ for Codex expert symlinks and keep expert button always enabled
Change Codex skill storage to use only ~/.codex/skills/ instead of
~/.agents/skills/, and never disable the expert skills button so users
can always access the empty-state hint. Also fix stale expert list in
conversation window after linking in the separate settings window by
re-fetching on window focus.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:37:31 +08:00
xintaofei
ade59f474c fix(chat): query expert skills via symlinks and use $ prefix for Codex
Expert skills in the chat session were derived by intersecting built-in
experts with ACP availableCommands, which caused Codex experts to never
appear since Codex does not advertise skills through ACP.

- Add `experts_list_for_agent` backend API that checks symlink status
  across all global skill dirs for the given agent type
- Replace availableCommands-based expert filtering with symlink-based
  query, making the settings page the single source of truth
- Use `$` prefix for Codex expert skills while keeping `/` for slash
  commands and other agents' experts
- Disable the expert button when no experts are linked for the agent
- Invalidate per-agent expert cache after link/unlink in settings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:13:42 +08:00
xintaofei
e4eb7f67eb fix(chat): preserve Gemini CLI history sessions on reopen
When reopening a Gemini CLI history session, session/load fails with
"Authentication required" and the fallback session/new overwrites the
DB external_id with a new session ID that has no corresponding file,
causing all historical messages to disappear.

- Skip session/new when session/load returns "Authentication required"
- Add Gemini to the parser fallback so stale external_ids recover via
  folder_path + started_at matching
- Guard externalIdSavedRef for existing conversations to prevent
  session/new from overwriting the persisted external_id
- Only update conversation status on disconnect when user has sent a
  message, avoiding spurious "completed" flips on pure history views

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 22:32:56 +08:00
xintaofei
5b613daded feat(experts): add built-in expert skills with per-agent activation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:17:51 +08:00
xintaofei
0b866eddb4 chore: bump ACP agent SDK (Claude code, OpenCode) versions in registry 2026-04-08 22:11:01 +08:00
xintaofei
923303f516 feat(install): add version detection and upgrade support to install scripts
Add --version flag to codeg-server binary and enhance both install.sh
and install.ps1 with version detection (skip if already up-to-date),
running process stop before upgrade, and post-upgrade restart guidance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 21:53:29 +08:00
xintaofei
94946bbe0c chore: bump ACP agent SDK versions in registry 2026-04-07 12:40:08 +08:00
xintaofei
a3d5335e7f feat(settings): protect model provider deletion and cascade credential updates
- Block deletion of a model provider when it is referenced by any agent,
  returning an error that lists the agent names so the user knows what to unlink first
- When a provider's api_url or api_key is updated, automatically propagate
  the new credentials to all dependent agents: updates env_json in the database
  and patches on-disk config files (Claude Code settings.json, Gemini settings.json,
  Codex auth.json + config.toml, OpenCode auth.json) using the same field names
  and structure as the agent settings UI
- Fix error message display in provider dialogs for both Tauri and web transports,
  which throw plain objects rather than Error instances

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 00:25:01 +08:00
xintaofei
b64976e4d6 feat(settings): refactor agent auth modes and add model provider authentication
- Split env vars and config file persistence into separate save operations
- Add model_provider_id field to agent_setting for tracking selected provider
- Add "Model Provider" auth mode for Claude Code, Codex CLI, and Gemini CLI
- Add "Custom Endpoint" auth mode for Claude Code (previously only official subscription)
- Unify auth mode labels across all three agents (official subscription / custom endpoint / model provider)
- When model provider is selected, fill api_url and api_key into env and config automatically
- Resolve model provider credentials at ACP connect time as a backend fallback
- Clear provider deletion cascades to agent_setting.model_provider_id
- Claude Code writes API credentials to config.env (ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN)
- Codex: switching auth modes patches config.toml instead of clearing it
- Add i18n keys for new auth modes in all 10 supported languages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:10:18 +08:00
xintaofei
ba19299696 feat(settings): add model provider management with full CRUD support
Add a new settings page for managing API model providers (name, API URL,
API key, applicable agent types). Includes database migration, SeaORM
entity, backend CRUD commands/handlers, frontend settings UI with agent
type filter, add/edit/delete dialogs, and i18n support for all 10 locales.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 16:35:14 +08:00
xintaofei
40d0a4b995 fix: disable "auto" config option for Claude Code to prevent errors
Claude Code errors when setting config options to "auto". Strip "auto"
values from config options returned to frontend and skip set requests
with "auto" value for Claude Code agent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 22:54:48 +08:00
xintaofei
ac0d849a7b chore: upgrade sacp to 11.0.0 stable and agent-client-protocol-schema to 0.11
- Upgrade sacp/sacp-tokio from 11.0.0-alpha.1 to 11.0.0 stable
- Upgrade agent-client-protocol-schema from 0.10 to 0.11
- Rebase vendor/sacp-tokio patches (kill_tree, CREATE_NO_WINDOW, stderr
  truncation) onto official 11.0.0 baseline
- Adapt renamed types: FileSystemCapability → FileSystemCapabilities,
  KillTerminalCommandRequest/Response → KillTerminalRequest/Response

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 22:10:15 +08:00
xintaofei
56d6db7866 chore: bump ACP agent SDK versions in registry
Update Claude Code 0.25.0, Codex 0.11.1, Gemini 0.36.0, OpenClaw 2026.4.2, Cline 2.13.0, OpenCode 1.3.13

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 21:01:48 +08:00
xintaofei
858ea9d10a fix: fix terminal not opening in Docker and slim down Docker image
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:59:30 +08:00
xintaofei
efd8e1104f features: add commit and push option to git commit window
- Add split button with dropdown in commit dialog supporting both
  "Commit" and "Commit and Push" actions
- Pass folderId through gitCommit/gitPush API calls so backend emits
  events that the folder window can receive for toast notifications
- Update Tauri git_commit and git_push commands to accept folder_id
  parameter with window label fallback for cross-window compatibility
- Wrap commit page with GitCredentialProvider for push authentication
- Keep commit window open when push fails so user can see the error
- Add i18n translations for all 10 locales

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 16:22:41 +08:00
xintaofei
b2d10fa008 optimize: terminal spawn lifecycle to eliminate output race condition
Move PTY spawn from context layer to view layer so event subscription
happens before spawn, preventing loss of initial terminal output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:55:38 +08:00
xintaofei
d0e0aad525 optimize: WeChat QR code auth flow and channel reliability
- Generate QR code server-side when iLink API returns SPA page URL
  (added qrcode + image crates for PNG generation)
- Strip bot_token from frontend response (new WeixinQrcodeStatusPublic type)
- Add request timeouts and shared HTTP client for QR code endpoints
- Fix TOCTOU race on reply_context double-lock (single lock scope)
- Extract do_send() helper to deduplicate sendmessage logic; resend now
  checks ret field for context expiry instead of HTTP status only
- Cap pending_messages buffer at 50 to prevent unbounded memory growth
- Generate stable X-WECHAT-UIN per backend instance instead of per request
- Extract ILINK_CHANNEL_VERSION constant (was hardcoded in 4 places)
- Add 5-minute client-side QR expiry timeout in frontend dialog
- Track consecutive polling errors and show warning after 3 failures
- Stabilise onAuthSuccess/onClose callback refs to prevent polling restarts
- Replace dead i18n key weixinOpenQrcode with weixinPollError

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 11:22:51 +08:00
xintaofei
0ef36ee918 optimize: WeChat channel message handling and error resilience
- Filter messages by message_type=1 to skip bot echo and prevent loops
- Add voice message support (type=3) with voice-to-text extraction
- Check resend results and re-buffer failed messages to prevent loss
- Handle session expiry (ret=-14) with 30s pause in polling loop
- Use exponential backoff (5s–30s) for network errors instead of fixed 5s

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 00:29:01 +08:00
xintaofei
8050e30a55 features: supports WeChat channel 2026-04-02 00:17:23 +08:00
xintaofei
098c9adb80 optimize: channel tool call details, permission context and stop reason i18n
- Display specific file paths, commands, and patterns in tool call messages
  instead of generic titles (e.g. ">> Read: src/main.rs")
- Show tool call details only on completion to ensure raw_input availability
- Enrich permission request messages with tool details from rawInput
- Localize stop_reason in turn_complete messages for all 10 languages
- Fix UTF-8 byte-slice panic in format_completion for multi-byte content

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 18:28:34 +08:00
xintaofei
ce95148232 fix: truncate_title panic on multi-byte UTF-8 strings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 17:29:01 +08:00
xintaofei
d76dc716e4 optimize: Enhanced session command processing logic 2026-04-01 17:22:56 +08:00
xintaofei
adb5829613 optimize: channel Message Commands — Multilingual Support and Prefixes 2026-04-01 16:22:54 +08:00
xintaofei
05214d09de Merge remote-tracking branch 'origin/botwork' 2026-04-01 15:03:41 +08:00
xintaofei
b98f50340f Feature: Supports remote branch deletion 2026-04-01 12:41:15 +08:00
xintaofei
245151dda2 优化提交代码的处理逻辑,避免一些情况无法提交代码 2026-04-01 11:16:41 +08:00