182 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
bd7a27bb30 fix: keep the desktop window draggable when session tabs fill the title bar
The macOS desktop build could lose its draggable gutter on the right side of
the tab bar once multiple session tabs consumed the native overlay title area.
This adds a Tauri window-drag fallback for clicks on the tab strip's empty
space while preserving tab and control interactions, and locks that behavior
with focused regression tests.

Constraint: Must preserve tab clicks, close buttons, and overflow controls while restoring drag behavior
Rejected: Rework the title bar layout around a dedicated spacer | larger UI diff for a narrow hit-testing bug
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep drag fallback limited to true empty gutter hits; do not trigger it from interactive tab descendants
Tested: bun run test src/components/layout/TabBar.test.tsx; bun run lint; bun run build; manual macOS app verification
Not-tested: Windows runtime drag behavior was not manually exercised after this change
Related: #92
2026-04-20 15:50:35 +08:00
程序员阿江(Relakkes)
efcf7af988 Cut desktop release 0.1.3 with empty-session slash discovery
The empty-session composer now loads user and project slash commands
before the first turn instead of falling back to the built-in list,
which keeps the packaged desktop app aligned with the web UI. This
commit also bumps the desktop release version metadata to 0.1.3 so the
release workflow publishes the correct artifacts.

Constraint: Desktop release automation is triggered by semantic version tags and reads the version from desktop release metadata
Rejected: Tagging v0.1.3 without a release commit | would publish stale 0.1.2 metadata and miss the slash-command fix
Confidence: high
Scope-risk: narrow
Directive: Keep EmptySession slash-command loading aligned with ChatInput so packaged and web entry flows do not diverge again
Tested: cd desktop && bun run test -- --run src/__tests__/pages.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Full GitHub Actions release-desktop workflow after tag push
2026-04-20 14:55:39 +08:00
程序员阿江(Relakkes)
921a352517 Integrate desktop skill discovery and empty-session composer fixes into main
This merges the detached-worktree desktop fixes back into main, preserving the
existing Computer Use modal changes on main while bringing over the project
skill discovery fallback, skills settings cwd-awareness, sidebar tab cleanup,
and the empty-session hero composer styling.

Constraint: Main already carried newer desktop session UI changes that had to be preserved during merge resolution
Rejected: Abort the merge and cherry-pick individual files | unnecessary once the only conflict was isolated to ActiveSession.tsx
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: When merging detached-worktree desktop branches into main, keep ActiveSession conflict resolution additive so session overlays and composer variants survive together
Tested: bun test src/server/__tests__/sessions.test.ts; cd desktop && bun run test -- --run src/__tests__/skillsSettings.test.tsx src/components/layout/Sidebar.test.tsx src/__tests__/pages.test.tsx src/pages/ActiveSession.test.tsx; cd desktop && bun run lint
Not-tested: Manual post-merge GUI verification in the local main worktree app bundle
2026-04-20 13:37:57 +08:00
程序员阿江(Relakkes)
261a85ab76 Restore desktop project-skill discovery and align empty-session composer
The desktop app previously lost project-level skills in two places: the
settings browser only queried user skills, and the slash-command picker for a
fresh session depended on CLI init state that does not exist before the first
turn. This change makes the skills APIs cwd-aware, falls back to project skill
loading before CLI init, syncs sidebar session deletion with open tabs, and
aligns the empty-session composer styling so the pre-message session UI stays
consistent.

Constraint: Fresh desktop sessions need slash-command discovery before the CLI websocket emits system/init
Constraint: Only repository code should be committed; build artifacts, installs, and /tmp smoke fixtures stay out of git
Rejected: Rebuild slash-command listings from full getCommands() in the sessions API | introduced auth-gated command dependencies unrelated to local skill discovery
Rejected: Unify EmptySession and ChatInput into one full component now | higher regression risk for normal chat interactions than a visual-only hero variant
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep pre-message skill discovery keyed to session workDir so project-level .claude/skills remain visible before the first turn
Tested: bun test src/server/__tests__/sessions.test.ts; cd desktop && bun run test -- --run src/__tests__/skillsSettings.test.tsx src/components/layout/Sidebar.test.tsx src/__tests__/pages.test.tsx src/pages/ActiveSession.test.tsx; cd desktop && bun run lint
Not-tested: Manual desktop smoke test against the rebuilt .app bundle in the local GUI
2026-04-20 13:36:19 +08:00
程序员阿江(Relakkes)
4bd30052ff Merge branch 'codex/computer-use-desktop-fixes' 2026-04-20 12:12:17 +08:00
程序员阿江(Relakkes)
5cd6b5d07b Prevent desktop Computer Use from stalling on missing approvals and unstable text input
Desktop sessions were missing a visible request_access approval path and could
mis-detect their own app window as an unapproved frontmost target, which caused
Computer Use clicks to fail even after opening the intended app. On macOS, text
entry was also split across inconsistent clipboard and keystroke paths, making
Electron inputs unreliable for Chinese and short strings.

This change adds a desktop approval bridge over the existing session websocket,
renders a dedicated desktop approval modal, threads the real desktop bundle id
into the Computer Use executor, and switches macOS clipboard typing onto the
native pasteboard plus system paste shortcut path. It also makes tool error
results expandable in the desktop chat UI so frontmost-gate failures are fully
visible during debugging.

Constraint: Desktop sessions run the CLI over the SDK websocket path, so Ink tool JSX dialogs are not visible there
Constraint: macOS IME and Electron text inputs are unreliable with pyautogui.write and generic hotkey synthesis
Rejected: Reuse CLI setToolJSX dialogs in desktop mode | no transport for mid-call Ink UI over the SDK bridge
Rejected: Keep shell pbcopy/pbpaste for clipboard typing | inconsistent with NSPasteboard path and less reliable for Chinese text
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep desktop Computer Use approvals and macOS text-entry behavior on a single bridge/path; avoid reintroducing separate CLI-only and desktop-only codepaths for the same action
Tested: python3 -m unittest runtime/test_helpers.py
Tested: bun test src/utils/computerUse/permissions.test.ts src/server/__tests__/conversation-service.test.ts
Tested: cd desktop && bun run test ComputerUsePermissionModal chatStore
Tested: cd desktop && bun run test chatBlocks
Tested: cd desktop && bun run lint
Not-tested: End-to-end manual Computer Use interaction against a live Electron target app on macOS
2026-04-20 12:12:02 +08:00
程序员阿江(Relakkes)
76823047f4 Add a switchable dark theme for the desktop workspace
This introduces a persisted light/dark appearance setting, maps the desktop shell onto semantic theme tokens, and reworks the highest-traffic chat/settings surfaces so the new dark mode is usable without regressing the original light theme.

The same pass tightens markdown rendering for chat replies by improving inline code, table overflow handling, and safe external-link behavior so dark-mode content stays legible in real conversations.

Constraint: Preserve the existing light theme while adding a user-selectable dark theme in Settings > General
Constraint: Avoid introducing new dependencies for styling or markdown handling
Rejected: Replacing the light palette with a single dual-purpose palette | would risk broad visual regressions across the existing desktop UI
Rejected: Implementing dark mode only for shell chrome | leaves chat markdown, diffs, and permission flows visually broken
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: New desktop UI should use semantic theme variables instead of hard-coded color literals so both themes stay aligned
Tested: bun run lint; bun run test; bun run build; browser review of theme switching, provider/permission states, and chat surfaces
Not-tested: Prototype-style pages with remaining hard-coded colors (scheduled/session control mock surfaces) were not fully normalized in this change
2026-04-20 10:23:19 +08:00
Relakkes Yang
3735ee803f fix: allow dismissing completed session tasks 2026-04-19 18:27:21 +08:00
Relakkes Yang
fb011588f9 fix: correct windows tab bar overflow alignment 2026-04-19 17:56:42 +08:00
程序员阿江(Relakkes)
45e4e447fa Enable signed desktop self-updates for release testing
The desktop app already had Tauri updater plumbing, but the
release pipeline was not emitting signed updater artifacts and
the UI exposed only a thin auto-check path. This change restores
a working updater release path, rotates to a new updater public
key, and adds a shared update flow with manual check/install
controls for testing.

Constraint: Original updater private key is unavailable, so a new public key had to be embedded and old installs cannot trust new signatures
Constraint: Must not add new dependencies or require main-branch rollout before validation
Rejected: Keep the old pubkey and skip signing | would leave release builds unable to publish valid updater artifacts
Rejected: Add a manual download fallback flow | user explicitly deferred that work
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Preserve the new updater private key and password outside the repo; losing them again will break future in-app updates for installed builds
Tested: desktop unit test for updater store; desktop TypeScript no-emit; desktop production build
Not-tested: end-to-end updater install against a real GitHub Release on this branch
2026-04-19 16:54:45 +08:00
程序员阿江(Relakkes)
b7396e4f65 Expose raw CLI startup details in desktop error cards so Windows failures are diagnosable
The chat UI translated CLI startup failures to a generic localized string and
hid the server-provided detail entirely. That made remote Windows debugging
guesswork even when the backend had already captured the real stderr payload.

This change keeps the localized summary but renders the raw startup detail
underneath when it differs, and adds a regression test covering the Git Bash
missing case.

Constraint: Windows Server repro is happening remotely, so the immediate value is better diagnostics rather than guessing a root cause locally
Rejected: Leave the generic translation only | obscures actionable stderr and slows every remote repro cycle
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: For translated startup errors, preserve backend detail somewhere visible unless it duplicates the summary
Tested: cd desktop && bunx vitest run src/components/chat/MessageList.test.tsx
Tested: cd desktop && bun run lint
Not-tested: Full desktop interaction flow on Windows Server 2022
Related: GitHub issue #62
2026-04-19 14:12:22 +08:00
程序员阿江(Relakkes)
e0b74cecae Restore Windows custom titlebar controls so desktop builds can manage the window again
The Windows desktop shell was rendering custom minimize, maximize, and close
buttons without the Tauri capabilities those commands require. The app was also
starting with decorated windows and then trying to disable decorations at
runtime, which is a weaker setup than the platform-specific config Tauri
expects for custom chrome.

This change grants the missing window permissions, moves Windows and macOS
window chrome settings into platform-specific Tauri config files, removes the
runtime decoration toggle, and adds a regression test that proves the custom
controls invoke the Tauri window API.

Constraint: Windows build validation will happen on the remote branch instead of this macOS workspace
Rejected: Keep runtime set_decorations(false) on Windows | leaves window chrome behavior dependent on post-start native mutation
Rejected: Ship only the capability fix | lower-risk hotfix, but it preserves the fragile cross-platform window config
Confidence: medium
Scope-risk: narrow
Reversibility: clean
Directive: Keep custom titlebar behavior in config and capabilities; avoid moving Windows decoration changes back into runtime setup
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test
Not-tested: Native Windows click/drag behavior on an actual packaged build from this local machine
Related: GitHub issue #62
2026-04-19 13:59:31 +08:00
程序员阿江(Relakkes)
c444e439b3 chore: update cluade model name 2026-04-18 17:52:55 +08:00
程序员阿江(Relakkes)
9d29d8e32c Keep desktop replies stable across turns and fix OAuth callback routing
The desktop chat store was dropping the previous assistant draft when a new user turn began because streaming text was cleared before it was flushed into message history. At the same time, the desktop OAuth flow was using an unregistered /api/haha-oauth/callback redirect URI, which caused provider authorization failures. This change flushes visible assistant drafts before starting a new turn, restores the OAuth redirect to the registered localhost callback, and adds a root callback handler while keeping the legacy API callback path compatible.

Constraint: The OAuth provider only accepts the registered localhost /callback redirect URI
Rejected: Keep the desktop-specific /api/haha-oauth/callback path | provider rejects unsupported redirect URIs
Rejected: Rely on message_complete to persist visible assistant text | next user turn can begin before that event arrives
Confidence: high
Scope-risk: moderate
Directive: Any UI-visible assistant draft must be flushed into messages before a new user turn resets streaming state
Tested: bun test src/server/__tests__/haha-oauth-service.test.ts src/server/__tests__/haha-oauth-api.test.ts src/server/__tests__/conversation-service.test.ts
Tested: cd desktop && bun run test src/stores/chatStore.test.ts
Tested: cd desktop && bun run lint
Not-tested: Manual end-to-end desktop OAuth login after reinstall
2026-04-18 17:01:53 +08:00
程序员阿江(Relakkes)
d83efc1b04 Prevent desktop OAuth sessions from drifting out of sync
Desktop auth was reporting stale local token files as logged in, could inherit a parent OAuth token after logout, and kept polling even when browser launch failed. This change validates stored tokens through the refresh path, clears inherited OAuth env before spawning the CLI, fetches subscription metadata on initial login, and moves polling start until after the browser opens. Regression tests cover the server and desktop store paths.

Constraint: Desktop CLI must bypass macOS Keychain by injecting env OAuth when available
Rejected: Keep status endpoint file-based only | reports expired sessions as logged in
Confidence: high
Scope-risk: moderate
Directive: Official desktop auth state must be derived from ensureFreshTokens rather than oauth.json presence alone
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/haha-oauth-service.test.ts src/server/__tests__/haha-oauth-api.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test
Not-tested: Manual end-to-end desktop OAuth flow against the live provider
2026-04-18 01:45:18 +08:00
程序员阿江(Relakkes)
4b4567bb80 fix(desktop): Official 卡片微调 — cursor-pointer 跟 hover 同步, 登录区加 top padding
Code review follow-ups on 33df639:
- cursor-pointer 从 inner header 挪回 outer div, 跟 hover border 保持同一元素, 避免
  hover 到卡片 border 区域时 cursor 先恢复默认再变 pointer
- login section pt-2 → pt-3, 跟下方内容留足视觉呼吸

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 20:37:31 +08:00
程序员阿江(Relakkes)
33df639c04 feat(desktop): embed ClaudeOfficialLogin into Claude Official card
- Official 卡片改成 flex-col 布局,原 header 内容包在可点击 row
- 激活状态下在 header 下方展示 <ClaudeOfficialLogin> (login / logout button)
- 未激活状态保持原"点击整块切换"UX 不变

Card root 不再带 onClick 以免 login/logout button 的 click 冒泡触发切换。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 20:35:07 +08:00
程序员阿江(Relakkes)
8ae68c1805 fix(desktop): ClaudeOfficialLogin — i18n、错误反馈、冗余清理
Code review follow-ups on ae5437a:
- I1: 使用 useTranslation 替代硬编码中文, 新增 settings.claudeOfficialLogin.* 双语 key
- I2: shellOpen 失败时 console.error + 写入 store.error, 不再静默吞
- M1: disabled={isLoading || false} → disabled={isLoading}
- M2: onClick={() => logout()} → onClick={logout}
- M3: 首次 fetchStatus 失败时显示 error 而非永远 "加载中…"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 20:33:08 +08:00
程序员阿江(Relakkes)
ae5437af43 feat(desktop): add ClaudeOfficialLogin component
未登录时显示引导文案 + 登录按钮(点击 Tauri shell.open 打开浏览器)。
已登录时显示 subscription type + 登出按钮。Polling 由 store 驱动,
浏览器完成 OAuth 后 2s 内 UI 自动更新。

使用 Tailwind + CSS custom properties 对齐项目现有组件风格。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 20:28:29 +08:00
程序员阿江(Relakkes)
e9ae8c93ae fix(desktop): haha-oauth store — logout 停 polling + recursive setTimeout 避免 overlap
Code review follow-ups on f10396e:
- logout() 首行调 stopPolling, 避免登出后 poll timer 还在跑
- setInterval 改为 recursive setTimeout, fetchStatus >2s 时不会产生 parallel 请求

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 20:26:47 +08:00
程序员阿江(Relakkes)
f10396e5bf feat(desktop): frontend API client + zustand store for haha OAuth
- api/hahaOAuth.ts: start/status/logout 3 个方法,基于现有 api client
- stores/hahaOAuthStore.ts: 状态管理 + 2s 间隔轮询 /status

port 从 getBaseUrl() 动态 parse,避免 Tauri 每次启动端口变化时失效。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 20:21:15 +08:00
程序员阿江(Relakkes)
ec3be47108 fix(desktop): provider 激活后联动重置聊天页 currentModel
切换模型供应商后聊天页底部选择器仍显示上一个 model, 要手动点一下才切过去。
根因: settings.json 的 model 字段 (explicit current model) 不会在
activateProvider/activateOfficial 时被清除, 但新 provider 的模型列表里
往往没这个旧 id, ModelSelector 就卡在"显示旧名字 + radio 不选中"的状态。

providerStore.activateProvider 成功后主动 setModel(provider.models.main)
+ settingsStore.fetchAll() 刷新 availableModels / currentModel。
activateOfficial 对应重置到 'claude-opus-4-6' (与后端 DEFAULT_MODEL 一致)。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 19:45:02 +08:00
程序员阿江(Relakkes)
0b4c742d55 fix(desktop): 修复桌面端多个渲染和权限问题
1. 修复 Tauri CSP 导致 Emotion CSS-in-JS 样式失效的问题
   - Tauri 编译时自动给 style-src 添加 nonce,使 unsafe-inline 失效
   - 添加 dangerousDisableAssetCspModification 阻止 Tauri 修改 style-src
   - 解决 DiffViewer 背景色/缩进等样式丢失

2. 修复 CodeViewer 代码块内容不显示的问题
   - react-shiki 异步加载 WASM 期间返回 null,代码区域空白
   - 添加 CodeArea 组件,纯文本 fallback + MutationObserver 检测加载完成

3. 修复 Bypass 权限模式切换不生效的问题
   - CLI 的 bypassPermissions 需要启动时带 --dangerously-skip-permissions
   - 运行中切换被 CLI 静默拒绝,前端不知情
   - 改为重启 CLI 子进程以正确的参数启动

4. 修复 stream_event tool input JSON 解析失败时 DiffViewer 不渲染
   - content_block_stop 的 JSON parse 失败时暂存到 pendingToolBlocks
   - 由后续 assistant 消息补发完整的 tool input
2026-04-16 10:50:02 +08:00
程序员阿江(Relakkes)
ec436986c5 feat(computer-use): 添加 Windows 平台支持
Computer Use 原本仅限 macOS,现在扩展支持 Windows:
- 新增 win_helper.py,用 win32gui/psutil/pyperclip/screeninfo 替代 macOS 专有 API
- 服务端按平台选择 helper 脚本、venv 路径 (bin→Scripts)、Python 命令 (python3→python)
- 前端权限区域仅在 macOS 上显示,Windows 无需 TCC 权限
- 跨平台测试验证两个 helper 的命令集和协议一致性

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 10:03:27 +08:00
Relakkes Yang
5d243b657a feat(desktop): Windows 自定义标题栏 & 服务端改进
- Windows 上隐藏原生菜单栏和窗口装饰,前端渲染自定义窗口控制按钮(最小化/最大化/关闭)
- macOS 保持原生菜单栏不变(条件编译)
- Sidebar 在 Windows 上不再添加 macOS 红绿灯的额外顶部间距
- 新增 Windows 构建脚本和 NSIS 安装钩子
- 服务端 CORS、会话服务、对话服务改进及测试补充

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 21:29:35 +08:00
程序员阿江(Relakkes)
5016bc0049 chore: 移除启动时自动检测认证并跳转设置页的逻辑 2026-04-15 14:43:32 +08:00
程序员阿江(Relakkes)
5fdf50436c test: 更新测试用例适配 provider 隔离与新 API
- providers-real.test.ts 重写适配 ModelMapping 对象格式
- e2e 测试适配 cc-haha/settings.json 路径
- settings.test.ts 验证写入隔离
- models.ts 小调整
2026-04-15 14:19:04 +08:00
程序员阿江(Relakkes)
0e60cadb13 chore(desktop): 构建改进与 UI 完善
- build-sidecars.ts macOS 编译后自动 ad-hoc codesign
- build-macos-arm64.sh 构建流程优化
- tauri.conf.json 配置更新
- i18n 中英文翻译补充
- Settings 页面与 uiStore 调整
2026-04-15 14:18:55 +08:00
程序员阿江(Relakkes)
166fe5b676 fix: Computer Use 点击功能修复
- ensureRuntimeFiles() 改为始终同步源文件而非仅缺失时复制
- pre-authorized apps 增加 tier: 'full',与现有 allowedApps 合并而非替换
- normalizeOsPermissions() 将 screenRecording: null 视为非阻塞
- config 路径改为 cc-haha/computer-use-config.json
- mac_helper.py 改进鼠标点击与坐标处理
2026-04-15 14:18:37 +08:00
程序员阿江(Relakkes)
b002447436 fix: provider 隔离与 Claude 官方认证修复
- provider 配置写入 ~/.claude/cc-haha/settings.json,不再污染原版 settings.json
- 子进程 env 剥离 PROVIDER_ENV_KEYS,防止残留 key 传递
- bin/claude-haha 在 CC_HAHA_SKIP_DOTENV=1 时用 --env-file=/dev/null 阻止 Bun 自动加载 .env
- managedEnv.ts 增加 getCcHahaSettingsEnv() 读取隔离配置
- 新增 /api/providers/auth-status 端点,启动时检测认证状态
- AppShell 启动时无认证则跳转 provider 设置页
2026-04-15 14:18:25 +08:00
程序员阿江(Relakkes)
23b31b397a Prevent local team sessions from dropping members and stalling adapters
This bundles the pending desktop/server team-session fixes with the local adapter recovery changes already in the worktree. The team path now keeps teammate membership stable under concurrent spawns, surfaces real teammate identities in the desktop UI, and allows direct interaction with member transcripts. The adapter changes recover automatically when stale thinking signatures invalidate an existing session.

Constraint: Team config writes can happen concurrently while multiple reviewers spawn in parallel

Constraint: Desktop member views must follow mailbox/transcript semantics rather than hijacking teammate runtime sessions

Rejected: Keep relying on config.json alone for member discovery | in-process teammates can be lost after concurrent writes

Rejected: Open teammate sessionIds as normal desktop sessions | would attach a second CLI instead of the running teammate

Confidence: medium

Scope-risk: moderate

Reversibility: clean

Directive: Preserve locked team-file mutation for any future teammate registration path and keep teammate labels sourced from member names before agent types

Tested: bun test src/server/__tests__/teams.test.ts src/server/__tests__/team-watcher.test.ts

Tested: cd desktop && bun run test --run src/stores/chatStore.test.ts src/pages/ActiveSession.test.tsx

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build

Not-tested: Manual end-to-end validation against a live Agent Teams run in the desktop app
2026-04-14 17:27:07 +08:00
程序员阿江(Relakkes)
9eb3be4b11 perf: optimize recent projects loading with parallel git queries and caching
目录选择器每次打开都串行执行大量 git 子进程导致卡顿,现改为并行查询 + 前后端双层 30s 缓存,选择新目录时自动失效缓存。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:02:35 +08:00
程序员阿江(Relakkes)
8888e1c3fb chore: comprehensive code review fixes — security, perf, leaks, quality, docs
- security: XSS sanitization with DOMPurify in Markdown/Mermaid/PermissionDialog;
  path whitelist in filesystem API; fake keys in test/config files
- perf: fine-grained Zustand selectors in Sidebar/StatusBar/ContentRouter;
  50ms throttle on streaming deltas; React.memo + useMemo in MessageList;
  useRef for frequent keyboard shortcut state; AbortController 30s timeout
- leaks: WS session TTL timers (5-min cleanup on close); batch splice for
  sdkMessages/stderrLines; folderPath validation in cronScheduler
- quality: optimistic update rollback in settingsStore; error state in
  providerStore/teamStore; i18n for all hardcoded English strings
- docs: desktop architecture and features docs updated; VitePress nav fixed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 22:27:17 +08:00
程序员阿江(Relakkes)
301e0c3a33 feat(desktop): route macOS native About menu to in-app Settings page
Replace the default macOS about dialog with a custom menu that emits
a Tauri event, navigating to the Settings > About tab within the React app.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 20:30:57 +08:00
程序员阿江(Relakkes)
bd604429ec feat(desktop): add About page in settings with app info and author links
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 16:12:46 +08:00
程序员阿江(Relakkes)
8617a4b9c9 feat: scheduled task IM notification + UI fixes
- Add notification config to CronTask (enabled + channels)
- New notificationService: push task results to Feishu/Telegram on completion
- Feishu uses Schema 2.0 interactive card for proper Markdown rendering
- Telegram uses Bot API sendMessage with Markdown parse mode
- NewTaskModal: notification toggle + channel checkboxes with config validation
- Fix: API layer now passes notification field through on task creation
- Fix: View conversation button uses tabStore instead of legacy setActiveView
- Fix: bypass permission dialog shows selected folder path instead of ~

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:42:44 +08:00
程序员阿江(Relakkes)
8c54c48514 ui(desktop): enlarge default window to 1440×960 and show welcome hero on empty session tabs
14" MacBook-friendly default size (was 1280×800). New session tabs now display
the same icon + title welcome screen as the landing page until the first message.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:15:33 +08:00
程序员阿江(Relakkes)
bfafd26fb6 fix: batch resolve 5 issues from Feishu bug tracker
- fix(desktop): Settings Agents/Skills page layout overflow at narrow widths
  Shift header grid breakpoint md→xl, summary cards sm→3col, add min-w-0/truncate

- fix(desktop): TabBar tab style — remove border-r separators, use bg-only active state
  Drop ::after indicator and inter-tab borders; active tab distinguished by surface bg

- feat(desktop): IM Adapters page — horizontal tabs with Feishu first, Telegram second
  Replace vertical stack with tablist; add ImTabButton with aria-selected + focus-visible

- fix(server): bundled IM session cwd resolves to / instead of selected project
  Root cause: preload.ts chdir(CALLER_DIR) inherits '/' from Tauri-spawned sidecar.
  Fix: pin CALLER_DIR and PWD to session workDir in conversationService spawn env.
  Add diagnostic logs at sessionService, ws/handler, and conversationService.

- fix(feishu): StreamingCard shows duplicate "thinking" indicators
  Merge static loading element into streaming_content; renderedText() controls state.

- test(adapters): add 5 ImageBlockWatcher edge-case unit tests (reset, relative path,
  multi-image chunk, malformed data URI)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 13:36:14 +08:00
程序员阿江(Relakkes)
3e3c2bc116 experiment(desktop): auto-spawn adapter sidecar on launch + restart on save
Wires the new claude-sidecar adapters mode into the actual desktop UX:

* On app launch, Tauri main process now spawns the adapter sidecar right
  after the server sidecar comes up. The sidecar reads ~/.claude/adapters.json
  and connects whichever of Feishu / Telegram has credentials configured;
  if neither does, it warns + skips + exits cleanly (treated as expected).
* When the user saves credentials in the existing AdapterSettings page,
  the frontend store invokes restart_adapters_sidecar after the PUT
  /api/adapters succeeds. Tauri kills the old child and spawns a new one,
  which picks up the fresh config and establishes the WebSocket connection
  to Feishu / Telegram immediately — no app restart needed.

End-to-end behavior is now: install app → open → configure credentials in
settings → click save → IM bot is live.

Implementation
==============

* desktop/src-tauri/capabilities/default.json: replace the stale
  binaries/claude-server allowlist with binaries/claude-sidecar across
  shell:allow-execute, shell:allow-spawn, plus a new shell:allow-kill
  entry needed for the restart path. (P2 changed externalBin to
  claude-sidecar but missed updating capabilities, which is why the prior
  bundle worked at all in dev mode but would have failed in production.)

* desktop/src-tauri/src/lib.rs:
  - new AdapterState that holds an Option<CommandChild>
  - start_adapters_sidecar() spawns `claude-sidecar adapters --feishu --telegram`
    with ADAPTER_SERVER_URL env var pointing at the dynamic server port
    (converted http://→ws:// since WsBridge does `new WebSocket(url)`
    directly without protocol translation)
  - spawn_and_track_adapters_sidecar() handles spawn + state insertion
  - stop_adapters_sidecar() kills + clears state
  - new #[tauri::command] restart_adapters_sidecar that calls stop+spawn
  - sidecar Terminated events are info-logged, not treated as errors,
    so the credential-missing path doesn't show up as a crash
  - setup() spawns the adapter sidecar after server startup completes
  - RunEvent::Exit cleanup also kills adapter sidecar

* desktop/src/stores/adapterStore.ts: after every successful PUT
  /api/adapters, dynamic-import @tauri-apps/api/core and call
  invoke('restart_adapters_sidecar'). Wrapped in try/catch so non-Tauri
  test environments fall through quietly. Triggers on every config
  change (including pairing code generation, paired-user removal) by
  design — keeps the rule simple and guarantees any save takes effect.

* desktop/src/pages/AdapterSettings.tsx: removed the stale "Server URL"
  text input. The field defaulted to ws://127.0.0.1:3456 but the actual
  server uses a dynamic port chosen at startup. Even when filled in
  correctly, loadConfig() in adapters/common/config.ts gives env var
  priority over file value, so this UI control had zero effect inside
  the desktop app. Standalone-mode adapter users can still edit the
  field directly in adapters.json if they need to.

Bundle size: unchanged at 88 MB .app / 37 MB DMG. The Rust changes
add only a few KB to the desktop main binary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 00:55:44 +08:00
程序员阿江(Relakkes)
fc7d6d487c fix(desktop): collapse session task bar by default
Task card was expanded by default and overlapped the main chat area
whenever todos appeared. Start collapsed and reset expanded state on
clearTasks so new sessions also begin collapsed; users can click the
header to expand when needed.
2026-04-11 11:42:16 +08:00
程序员阿江(Relakkes)
635a966c3e fix(desktop): unblock rollout with reliable session and IM flows
This folds together the desktop-side fixes needed before broader rollout.
Session resume no longer deadlocks waiting on init, Mermaid and inline image
output render inside chat, task and sub-agent state stay visible during
execution, local build/release paths are safer, and Feishu/Telegram now expose
lightweight mobile commands (/help, /status, /clear) without adding a new
adapter-specific protocol.

Constraint: Desktop releases must publish updater artifacts from non-draft GitHub releases
Constraint: IM commands need short, phone-friendly responses and low operational complexity
Rejected: Add a dedicated IM command API surface | re-used existing slash commands and session/task REST endpoints to keep adapters thin
Rejected: Wait for task_update push events in WebUI | added low-risk polling because the current frontend ignores that event path
Confidence: medium
Scope-risk: broad
Reversibility: clean
Directive: Keep IM command replies terse and mobile-first, and merge local fallback slash commands when server-provided lists are partial
Tested: cd desktop && bun x vitest run src/components/chat/MermaidRenderer.test.tsx src/components/markdown/MarkdownRenderer.test.tsx
Tested: cd desktop && bun x vitest run src/components/chat/composerUtils.test.ts src/pages/ActiveSession.test.tsx src/stores/chatStore.test.ts
Tested: cd desktop && bun run lint
Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "SDK init arrives only after the first user turn" --timeout 60000
Tested: cd adapters && bun test common/ feishu/ telegram/
Tested: cd adapters && bunx tsc --noEmit
Not-tested: Full GitHub Actions release run on all three desktop platforms
Not-tested: Local DMG packaging end-to-end on Apple Silicon
Not-tested: Real Feishu/Telegram device sessions against a live adapter process
2026-04-10 16:41:59 +08:00
程序员阿江(Relakkes)
7983cce478 feat(desktop): add CI/CD release pipeline, auto-updater, and installation guide
- Add GitHub Actions workflow for 5-platform builds (macOS ARM/x64, Linux x64/ARM64, Windows x64)
- Integrate tauri-plugin-updater with signing key and UpdateChecker UI component
- Add version management release script (scripts/release.ts)
- Add installation guide with Gatekeeper/SmartScreen bypass instructions
2026-04-10 11:00:46 +08:00
程序员阿江(Relakkes)
98a24f99b4 feat(proxy): add multi-protocol proxy for OpenAI-compatible providers
Add a protocol-translating reverse proxy that allows using OpenAI-compatible
API providers (DeepSeek, OpenRouter, Groq, etc.) with Claude Code.

The proxy intercepts Anthropic Messages API requests from the CLI, transforms
them to OpenAI Chat Completions or Responses API format, forwards to the
upstream provider, and transforms streaming/non-streaming responses back.

Key features:
- Request transform: Anthropic Messages → OpenAI Chat/Responses
- Response transform: OpenAI → Anthropic (streaming SSE + non-streaming)
- Provider-agnostic reasoning support (reasoning_content, thinking_blocks,
  reasoning fields from DeepSeek, OpenAI o-series, GLM-5, Groq, etc.)
- Event queue pattern for correct Anthropic SSE event ordering
- Two-step test: ① connectivity check ② full proxy pipeline validation
- Desktop UI: API format selector, two-step test results display
- License attribution for cc-switch (MIT, Jason Young)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 00:33:26 +08:00
程序员阿江(Relakkes)
85969318b9 refactor(desktop): remove i18n from spinner verbs, use English only
Drop Chinese spinner verb array and locale-based selection. StreamingIndicator
now uses English status verbs directly without going through the i18n system.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:56:55 +08:00
程序员阿江(Relakkes)
276169015c fix(desktop): add subtle border separator between tabs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:14:57 +08:00
程序员阿江(Relakkes)
739b353a89 fix(desktop): show message Copy button on hover at bottom-right
Move the Copy button from always-visible below messages to the
bottom-right side of each message bubble, only appearing on hover.
Reduces visual clutter in chat conversations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:04:05 +08:00
程序员阿江(Relakkes)
6085447277 fix(desktop): swap session in-place when switching workDir on empty session
Instead of close tab → delete session → create session → open tab (which
causes visual flicker and tab jumping), create the new session first then
replace the tab's sessionId in-place via a new replaceTabSession method.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:17:55 +08:00
程序员阿江(Relakkes)
211226c7a1 feat(agents): update API types, store, i18n, and tests for new agent model
- Update AgentDefinition type with agentType, source, isActive, modelDisplay fields
- Refactor agentStore to support activeAgents/allAgents with cwd parameter
- Add i18n strings for agent browser UI (source labels, summary, status)
- Update server agents API with serialization helpers and override resolution
- Update tests to match new agent data structure

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 16:45:51 +08:00
程序员阿江(Relakkes)
db005e5e98 fix(desktop): improve Agents/Skills layout and rendering
- Agent list items: replace dot with colored smart_toy icon, bold name
- Agent description: use MarkdownRenderer for rich text support
- Remove max-width constraints on Agent/Skill containers for responsive layout
- Dynamically switch grid columns based on visible group count (single group fills full width)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 16:43:24 +08:00
程序员阿江(Relakkes)
5911388626 fix(skills): polish desktop browser layout and rendering
Improve the desktop Skills browser so SKILL.md metadata renders cleanly and the settings view uses space like a real document browser. Add coverage for the new detail, markdown, and i18n behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 14:59:33 +08:00