454 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
2f8c2a9a70 fix: resolve first issue 809 batch
Fixes local Batch A from #809+ triage: configurable scheduled task timeout (#809/#846), OpenAI proxy trace request headers (#836), title generation auth strategy (#854), and unresolved parallel tool card settlement (#889).

Tested: bun test src/server/__tests__/cron-scheduler-launcher.test.ts

Tested: bun test src/server/__tests__/title-service.test.ts

Tested: bun test src/server/__tests__/proxy-network-settings.test.ts

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

Tested: bun run check:server

Tested: bun run check:desktop

Not-tested: bun run verify and coverage were not run because this is a local batch checkpoint, not a PR-ready/push-ready handoff.

Confidence: high

Scope-risk: moderate
2026-06-22 22:45:26 +08:00
程序员阿江(Relakkes)
e944db1e2f fix(cli): avoid Anthropic preflight during onboarding
Keep first-run CLI setup local-first by building only local onboarding steps.
Remove the startup preflight that pinged Anthropic/OAuth endpoints before any explicit login or model request.

Fixes #859.

Tested: bun test src/components/onboardingSteps.test.ts
Tested: bun run check:server
Not-tested: bun run verify; check:coverage; check:policy
Confidence: high
Scope-risk: narrow
2026-06-22 22:10:17 +08:00
zhb
eb5a1b0278
优化停止,出现API Error: Stream ended without receiving any events
优化停止,出现API Error: Stream ended without receiving any events
2026-06-21 13:35:52 +08:00
程序员阿江(Relakkes)
9111c0c242 fix(server): close prewarm idle timer race in CLI-startup blind window
#865 added guards against the prewarm_session/user_message concurrency
race, but both keyed on isSessionTurnActive (messageSent===true).
messageSent only flips true after CLI startup completes, so during the
startup window a user turn is registered yet invisible to the guards — the
prewarm idle timer could still arm on, and later fire against, an active
turn, killing the CLI and leaving the UI stuck on "执行中".

- Add hasPendingOrActiveUserTurn() (turn registered regardless of
  messageSent) and use it for both prewarm guards, covering the blind window.
- Structurally disarm the timer when a turn completes (clearPrewarmState in
  bindActiveUserTurnCompletion), so a timer armed by the race never outlives
  the turn regardless of ordering.
- Add test hooks + 3 regression tests: blind-window turn not killed, active
  turn not killed, truly-idle session still reclaimed.
2026-06-20 16:17:08 +08:00
zhb
db1ebabe40
优化客户端几乎同时发送 prewarm_sessionuser_messageclearPrewarmState 什么也没清除,导致kill CLI,客户端永远收不到 status: idle 或 error,页面卡在"执行中"
Added safety checks to prevent prewarm idle timer from interrupting active sessions.
2026-06-19 00:45:57 +08:00
程序员阿江(Relakkes)
348de336e1 fix(streaming): retry transient mid-stream errors instead of failing the turn
Mid-stream api_error/overloaded_error SSE events (e.g. a local provider such
as LM Studio rejecting a malformed tool_call) arrive inside the 200 SSE body,
bypassing withRetry — which only guards stream creation — so they were
surfaced as a terminal API error that ended the turn with no retry.

Add withStreamRetry around queryModel: when an attempt produced zero output
(no tool_use block completed, so query.ts never started a tool — safe w.r.t.
the double-tool-execution hazard, inc-4258), re-establish the stream and retry
up to CLAUDE_STREAM_TRANSIENT_RETRY_MAX times (default 2) before surfacing the
error. Covers both the streaming and non-streaming query wrappers; adds unit
tests for the retry loop and the transient-error classifier.
2026-06-16 22:51:04 +08:00
程序员阿江(Relakkes)
92430ba001 Merge branch 'claude/serene-ptolemy-36ca25': background subagent tool activity (#829) 2026-06-16 16:02:00 +08:00
程序员阿江(Relakkes)
54a8f3107c fix(desktop): support 1M provider context declarations (#814)
Add per-model 1M capability flags for custom providers and persist them through provider settings.
When a model is marked as 1M-capable, runtime env uses the local [1m] marker and the desktop form auto-fills a 1000000-token context window when needed.

Tested: bun test src/server/__tests__/providers.test.ts -t "custom providers can mark main and role models as 1M-capable"
Tested: cd desktop && bun run test -- generalSettings.test.tsx -t "normalizes blank model mappings|saves 1M model declarations"
Tested: bun run check:desktop
Tested: bun run check:server
Not-tested: bun run verify / coverage gates were not run for this scoped local handoff.
Confidence: high
Scope-risk: moderate
2026-06-16 14:03:07 +08:00
程序员阿江(Relakkes)
1c554dc30d fix: stream background subagent tool activity to desktop (#829)
Background (run_in_background) subagents run detached from the main query loop, so their tool_use/tool_result never reached the desktop and their cards stayed on "no tool activity" even after completion. Route the activity through the SDK event queue as agent_tool_activity, re-emitted by the ws handler as tool_use_complete/tool_result tagged with the parent Agent tool_use id, so the UI groups them under the agent card like synchronous subagents.
2026-06-16 14:00:25 +08:00
程序员阿江(Relakkes)
8813dff5b1 Merge branch 'claude/wonderful-burnell-b76630': first-token timeout fix (#826) 2026-06-15 23:35:08 +08:00
程序员阿江(Relakkes)
e7a59592de fix(streaming): honor request timeout while waiting for the first token (#826)
The configured request timeout (API_TIMEOUT_MS) only feeds the SDK client
timeout, which on a streaming request is cleared the moment response headers
arrive. Slow local/3P models return 200 headers fast but spend minutes
prefilling before the first SSE token, so that window was governed by the idle
watchdog (CLAUDE_STREAM_IDLE_TIMEOUT_MS, 240s) -- a separate env users cannot
configure. The configured timeout therefore never applied to slow prefill, so
raising it had no effect (#826, follow-up to #449).

Split the stream watchdog into phases: use a first-token budget (tied to the
user's request timeout via CLAUDE_STREAM_FIRST_TOKEN_TIMEOUT_MS) until the first
chunk arrives, then switch to the shorter mid-stream idle budget. The overall
max-duration cap (#766) still backstops trickling bodies; CLI defaults fall back
to prior behavior.
2026-06-15 23:34:32 +08:00
程序员阿江(Relakkes)
381d5f14e0 fix(provider): default Tool Search for Anthropic providers (#823)
Add a provider-level Tool Search capability that defaults on for native Anthropic Messages providers and writes ENABLE_TOOL_SEARCH through the managed provider env path. Keep OpenAI proxy formats opted out because the proxy transforms do not support Anthropic tool_reference history yet.

Preserve upgrade safety by normalizing missing or stringly typed stored values instead of dropping saved providers.

Tested: bun test src/server/__tests__/provider-runtime-env.test.ts src/server/__tests__/providers.test.ts

Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx --run

Tested: cd desktop && bun run lint

Tested: bun run check:server

Confidence: high

Scope-risk: moderate
2026-06-15 23:29:42 +08:00
程序员阿江(Relakkes)
35aa36c319 fix: honor custom provider context windows (#830)
Persist runtime provider metadata for desktop sessions so context estimates stay tied to the provider that launched the session. Infer a unique saved provider window for older sessions without runtime metadata, and keep Xiaomi MiMo custom providers on thinking-only capability mapping instead of max-effort passthrough.

Tested: bun test src/server/__tests__/conversations.test.ts -t "unique saved provider context window|pass the active provider id|provider model context windows"
Tested: bun test src/server/__tests__/providers.test.ts -t "Xiaomi MiMo custom providers|custom providers declare|model context windows"
Tested: bun test src/server/__tests__/sessions.test.ts src/server/__tests__/searchService.sessions.test.ts src/server/__tests__/ws-memory-events.test.ts
Tested: cd desktop && bun run test -- src/stores/chatStore.test.ts src/stores/providerStore.test.ts src/components/controls/ModelSelector.test.tsx
Not-tested: full bun run verify was not run for this local issue handoff.
Confidence: high
Scope-risk: moderate
2026-06-15 23:21:33 +08:00
程序员阿江(Relakkes)
572eba46f4 fix(desktop): restore session token usage after reopen (#820)
Persist transcript usage through session history so reopened desktop tabs can restore header token counts, and resume elapsed timers when reconnected sessions report active status.

Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: cd desktop && bun run lint
Tested: bun run check:server
Tested: git diff --check
Not-tested: bun run verify and coverage; scoped local handoff, not PR-ready validation.
Confidence: high
Scope-risk: narrow
2026-06-15 23:02:19 +08:00
程序员阿江(Relakkes)
0a7db60394 fix(desktop): hide slash command breadcrumbs on restore (#833)
Tested: bun test src/server/__tests__/ws-memory-events.test.ts
Tested: bun test src/server/__tests__/sessions.test.ts -t "command breadcrumb"
Tested: bun test src/server/__tests__/searchService.sessions.test.ts
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts
Tested: bun run check:desktop
Tested: bun run check:server
Scope-risk: narrow
Confidence: high
2026-06-15 23:00:46 +08:00
程序员阿江(Relakkes)
4b6c855eda fix: handle memory empty state and tool autoscroll (#728 #729)
Tested:
- bun test src/server/__tests__/memory.test.ts
- cd desktop && bun run test -- src/__tests__/memorySettings.test.tsx
- cd desktop && bun run test -- src/components/chat/MessageList.test.tsx -t "active tool input"
- cd desktop && bun run check:desktop
- bun run check:server
2026-06-15 19:46:21 +08:00
程序员阿江(Relakkes)
a4799ae5ea Merge branch 'claude/brave-hofstadter-bc68ae': global session full-text search 2026-06-15 19:08:10 +08:00
程序员阿江(Relakkes)
1a050242b7 feat(search): global session full-text search
Add a Codex-style global search dialog (Cmd+K / sidebar button) that
full-text searches across all session transcripts, replacing the old
title-only sidebar filter.

Backend: rewrite searchService.searchSessions as a two-phase engine —
ripgrep finds candidate files + matched lines, then those lines are
parsed to keep only user/assistant text, re-confirmed against the
cleaned text to drop JSON/UUID/base64 false positives, and windowed into
highlighted snippets. Results carry real session titles (new
sessionService.getSessionTitleAndMeta reusing the list title
precedence), project path, mtime, role and match counts; falls back to a
JS scan when ripgrep is unavailable.

Frontend: new GlobalSearchModal (debounced, stale-response-safe, keyboard
nav, role badges, highlighting, recent-chats empty state); Cmd+K now
opens it; the sidebar input is replaced by a search trigger button.

Tests: 15 backend cases (searchService.sessions) + 12 frontend cases
(GlobalSearchModal); existing Sidebar/pages tests updated for the new
trigger.
2026-06-15 19:06:00 +08:00
程序员阿江(Relakkes)
b5161a4709 fix(desktop): refresh workspace diff previews (#724)
Prefer the live git diff for currently changed workspace files so DIFF previews do not get stuck on stale transcript snapshots. Refresh an existing workspace preview tab when it is opened again instead of only reactivating cached content.

Tested: bun test src/server/__tests__/workspace-service.test.ts
Tested: cd desktop && bun run test src/stores/workspacePanelStore.test.ts --run
Tested: bun run check:server
Tested: bun run check:desktop
Confidence: high
Scope-risk: narrow
2026-06-15 19:03:00 +08:00
程序员阿江(Relakkes)
f793895fb3 fix(streaming): cap overall stream duration to free trickling provider streams (#766)
Third-party gateways can trickle content deltas (e.g. a large tool_use
input_json_delta) just under the idle-watchdog window and never send
message_stop. Each delta resets the idle timer, so the in-kernel watchdog
never fires and the request hangs forever — the desktop shows "running"
with slowly growing tokens and a permanently-pending trace span (#766).

Add an overall-duration watchdog (CLAUDE_STREAM_MAX_DURATION_MS) that is
armed once and never reset by incoming chunks; the desktop injects 600000ms
via buildChildEnv. Orthogonal to the idle watchdog: idle catches a fully
silent stream, this catches an endless trickle that never completes. CLI
default stays 0 (disabled) for backward compatibility.

Verified end-to-end by replaying the issue's real captured SSE against the
actual kernel: trickle hangs without the cap, aborts cleanly with it.
2026-06-15 14:27:03 +08:00
程序员阿江(Relakkes)
84bcdb5f52 fix: restore release gate checks
Keep provider ordering compatible with older desktop store state, keep workspace traversal blocked even when external changed-file roots are registered, and align the quality-contract test with the current AGENTS wording.

Tested: bun test scripts/pr/quality-contract.test.ts

Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx src/__tests__/skillsSettings.test.tsx src/__tests__/pluginsSettings.test.tsx src/__tests__/diagnosticsSettings.test.tsx --run

Tested: bun run check:policy

Tested: bun run check:desktop

Tested: bun test src/server/__tests__/workspace-service.test.ts -t 'does not allow relative traversal'

Tested: bun test src/server/__tests__/sessions.test.ts -t 'workspace/file and tree should reject traversal|workspace/diff should reject traversal' --timeout=20000

Confidence: high

Scope-risk: narrow
2026-06-13 12:09:57 +08:00
程序员阿江(Relakkes)
fc27397205 fix(desktop): anchor output chips and previews on real changed files
Fix four root causes in the desktop preview pipeline, surfaced when the
model writes the files the user pointed it at:

- Output chips guessed paths from prose and could point at a missing file.
  They are now reconciled against the turn's real changed files: a bare
  `index.html` resolves to the `todo-app/index.html` actually written, and
  mentions the turn never changed are dropped.
- A standalone single-page index.html got no browser preview (mistaken for a
  Vite template). It is now only routed to the source view when a
  package.json/vite.config ships in the same change-set.
- Files written outside the session workdir (another folder, or another drive
  on Windows) failed to preview with 'Path is outside workspace'. The turn's
  changed-file directories are registered as filesystem access roots; html
  serves via /local-file and other files via a workdir-relaxed read.
- The visual-selection prompt leaked as a raw bubble on Windows because the
  server-appended '[Image source: ...]' line broke replay dedupe. Replay text
  is now metadata-normalized before comparison (affects any image message).

Adds unit tests for each: htmlPreviewPolicy, assistantOutputTargets
reconciliation, replay dedupe + stripGeneratedImageMetadataLines, filesystem
access roots, and workspace outside-workdir reads.
2026-06-13 11:01:46 +08:00
程序员阿江(Relakkes)
01d8691673 fix(providers): make provider list sortable (#753)
Render provider settings through dnd-kit sortable rows, include official providers in the same order model, and persist providerOrder across server and desktop state.

Tested:

- bun test src/server/__tests__/providers.test.ts src/server/__tests__/persistence-upgrade.test.ts

- cd desktop && bun run test -- --run src/stores/providerStore.test.ts src/__tests__/generalSettings.test.tsx -t "providerStore reorderProviders|Settings > Providers tab"

- cd desktop && bun run lint

- cd desktop && bun run build

- bun run check:persistence-upgrade

Not-tested:

- bun run check:server (broad suite hit environment failures during this run: MCP stdio zshrc timeout, adapter dependency gap at the time, and e2e cascade)

Confidence: high

Scope-risk: moderate
2026-06-13 08:07:36 +08:00
程序员阿江(Relakkes)
ea82c6ec70 fix(trace): record aborted API calls instead of leaving them pending (#766)
When an upstream request was aborted mid-stream (SDK client timeout,
stream idle watchdog, non-streaming fallback timeout, or user
cancellation), the trace fetch hook waited on a clone of the response
body that could hang forever, so the call never left "pending" in the
trace panel — exactly the silent stall that misled the #766 report.

- captureResponseTraceSnapshot reads the body with abort awareness:
  reader.cancel() on abort keeps the partial body, with a 2s grace
  backstop for runtimes where cancel cannot wake a hung read.
- The fetch hook now records an error-state call on abort with the
  abort reason (e.g. the watchdog's stream idle timeout), duration,
  partial response body, and an api_call_aborted event; non-abort
  capture failures also record an error instead of inferring ok, and
  pre-response fetch rejections carry an aborted flag.
- The trace detail panel shows an "Aborted" badge plus guidance for
  aborted calls, and labels the new api_call_aborted phase in all
  locales.

Tested: bun test src/server/__tests__/trace-capture.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run test -- --run && bun run lint
2026-06-12 18:35:18 +08:00
程序员阿江(Relakkes)
67660ab4e5 fix(desktop): surface non-streaming fallback in chat status (#766)
api_retry heartbeats already reach the desktop status bar, but the
streaming-to-non-streaming fallback had no signal at all: the CLI only
flipped an internal flag, and the one-shot fallback response can take
minutes with zero incremental output, so the UI showed a bare spinner
the whole time.

- CLI: yield a {type:'system', subtype:'streaming_fallback', cause}
  message at both fallback sites (stream error/watchdog and 404 stream
  creation), mirroring the existing api_error -> api_retry path through
  query.ts passthrough, QueryEngine SDK output, and the SDK schema.
- Server: translate it to a streaming_fallback ServerMessage;
  unrecognized causes normalize to 'unknown' instead of dropping the
  event.
- Desktop: track it as active-turn state (cleared at the same 12 sites
  as apiRetry; a fallback notice supersedes the stale retry banner) and
  render a neutral pill with the turn timer - expected state, not an
  error, so no amber styling and nothing in the diagnostics panel.
- Retry banner now shows "retrying now" once the countdown elapses
  instead of sticking at "waiting 0s".

With 62241a31 disabling the non-streaming fallback for desktop CLI
sessions, this notice mainly covers the 404 gateway path (which skips
the disable check), callers that re-enable fallback via env, and
non-desktop SDK consumers.

Constraint: Retries and fallbacks are expected states per the
diagnostics severity standard - lightweight active-turn UI only, no
error-panel entries, no transcript persistence.
Tested: bun test src/server/__tests__/ws-memory-events.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run test -- --run
Tested: cd desktop && bun run lint
Not-tested: live provider outage reproduction; verified via unit
coverage of the translation, store lifecycle, and indicator rendering.
2026-06-12 18:32:28 +08:00
程序员阿江(Relakkes)
81599b2af9 fix: recover context meter right after compaction (#743)
The context usage indicator stayed at the pre-compact percentage (e.g.
100%) until the next API response arrived. Two stacked causes:

- The CLI anchors the displayed total to max(local estimate, last API
  usage) so the meter never drops mid-turn — but preserved messages
  (SM-compact / partial compact) still carried the pre-compact usage,
  pinning the meter after compaction. buildPostCompactMessages now
  zeroes token usage on preserved assistant copies, the established
  stale placeholder that getCurrentUsage() skips, covering every
  compaction path in one place. Originals are not mutated, so
  transcript and cost accounting are unaffected.
- Right after compaction the CLI is often still busy, so the
  indicator's refresh timed out ("Request timed out after 30s") and the
  catch kept the stale context on screen with no later retry (auto
  refresh is throttled to 10s and stops once the session goes idle).
  compact_boundary now bumps a per-session compactCount; the indicator
  force-refreshes on that nonce — bypassing the throttle and any
  in-flight request that may still hold pre-compact data — and retries
  once after 5s if the forced refresh fails.

Tested: bun test src/services/compact/
Tested: cd desktop && bun run test -- src/components/chat/ContextUsageIndicator.test.tsx src/stores/chatStore.test.ts
Tested: cd desktop && bun run lint
Confidence: high
Scope-risk: narrow
2026-06-12 17:57:47 +08:00
程序员阿江(Relakkes)
62241a31e5 fix(desktop): stop killing slow provider streams (#766)
Desktop injected a far stricter timeout stack than the terminal CLI, so
healthy-but-slow third-party providers (sensenova/bailian/zhipu) died at
exactly API_TIMEOUT_MS while the UI showed "running" forever:

- API_TIMEOUT_MS is the SDK client's time-to-first-byte budget for
  streaming requests; these gateways send zero bytes (no headers, no
  SSE ping) until prefill finishes, which takes minutes at large
  contexts. Raise the default from 120s to the SDK's own 600s and widen
  the configurable range to 30-1800s.
- Widen the desktop-forced stream watchdog idle window to 240s so
  silent thinking/prefill phases stop tripping the 90s default.
- Disable the non-streaming fallback for desktop CLI sessions: a
  non-streaming request only responds after the FULL generation, so it
  can never finish inside the same budget and loops timeout aborts
  forever while the UI spins (also avoids double tool execution,
  upstream inc-4258). All three knobs respect caller env overrides.

Repro: mock upstream whose SSE stays silent for 150s before a complete
event sequence — terminal env completes; desktop env aborts at exactly
120s (client timeout) or 90s watchdog + non-streaming fallback loop;
the fixed env completes both variants.

Tested: bun test src/server/__tests__/network-settings.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/proxy-network-settings.test.ts
Tested: cd desktop && bun run test -- src/stores/settingsStore.test.ts src/__tests__/generalSettings.test.tsx
Tested: cd desktop && bun run lint
Confidence: high
Scope-risk: medium
2026-06-12 17:57:33 +08:00
程序员阿江(Relakkes)
5cf8c1bb67 fix(desktop): queue active-turn prompts (#755)
Add pending user-message queue controls while a desktop turn is running, replay queued prompts into the transcript when the CLI accepts them, and flush remaining prompts after turn completion.

Tested: cd desktop && bun run test -- src/components/chat/ChatInput.test.tsx
Tested: cd desktop && bun run test -- src/stores/chatStore.test.ts
Tested: bun test src/server/__tests__/ws-memory-events.test.ts
Tested: bun run check:desktop
Not-tested: bun run check:server remains blocked by unrelated E2E CORS preflight expectation, expected 403 but got 204.
Confidence: medium
Scope-risk: moderate
2026-06-12 16:44:52 +08:00
程序员阿江(Relakkes)
90a50eca1c Merge H5 access stability fixes (#767, #764) 2026-06-12 16:37:09 +08:00
程序员阿江(Relakkes)
53d8e7ad77 feat(desktop): stabilize H5 access tokens, ports, and background sessions (#767, #764)
H5 远程访问的三处不稳定来源修复,让手机出门在外也能稳定连接、长任务不丢。

#767 令牌与端口固定:
- 令牌明文持久化到 cc-haha/settings.json,重启后二维码/令牌随时可查、可复制;
  enable 复用现有令牌、disable 保留令牌,仅 regenerate 才轮换。手改 token 字段
  即自定义固定令牌。完整令牌只经 local-trusted 面返回,远端 403。
- 新增可选固定端口 fixedPort,并在未配置时复用上次端口(desktop-server-state.json
  sticky,Electron/Tauri 双壳共享),反向代理/手机书签跨重启不失效;占用时回退随机。

#764 断连不杀正在运行的 CLI:
- 客户端断开时若该会话仍在跑一轮任务,不再 30s 后强杀子进程,而是等任务跑完;
  手机锁屏/切后台时长任务在后台跑完,重连即见结果。
- 空闲清理超时改为可配 disconnectGraceSeconds(H5 访问设置页,默认 30s),
  经 disconnectGraceConfig 同步缓存供 close 处理读取。

server / Electron / Tauri / React 四层 + 五语言 i18n + 配套单测全部覆盖。
2026-06-12 16:37:00 +08:00
程序员阿江(Relakkes)
6b4f7e4733 fix(desktop): expand tilde paths when revealing generated files (#776)
Reveal-in-Explorer/Finder rejected ~-prefixed paths because no layer
expanded the tilde to the home directory. Expand it in the three path
normalization entry points: server validateOpenPath, frontend
resolveAbsolute, and Electron normalizeOpenPath. Tilde expansion is
platform-aware (~\ only on win32, where backslash is a separator).
2026-06-12 16:24:34 +08:00
程序员阿江(Relakkes)
8c99b0f892 feat(providers): support drag-and-drop reordering of the providers list
为服务商列表添加拖拽排序(#753)。复用项目已有的原生 HTML5 拖拽模式(对齐
Sidebar),零新增依赖;通过重排 providers.json 的数组顺序持久化,不引入 order
字段;仅行首手柄可拖,避免与行内操作按钮冲突;采用乐观更新 + 失败回滚。

后端: reorderProviders service、PUT /api/providers/reorder 路由、
ReorderProvidersSchema(校验 orderedIds 为现有 id 的排列)。
前端: providersApi.reorder、store action、Settings 拖拽手柄 UI、中/英/日/韩/繁文案。
测试: 后端 9 用例 + 前端 3 用例。
2026-06-12 16:21:58 +08:00
程序员阿江(Relakkes)
a94e5b641a fix: unify token usage display across desktop and CLI (#757)
Token counts were rendered with five inconsistent formats across the
chat UI (header "181,117 t", in-progress bare "↓ 2514", background
agents "12,345 tokens", compact summary "1.5k", trace "1.2k"), and the
in-progress count was actually stale: the server never set the status
event's tokens field, so the indicator showed the previous turn's value
(hence "first message shows nothing", "sometimes appears, never moves").

- Add shared desktop lib/formatTokenCount; route header, streaming
  indicator, background agents, compact summary, and trace through it.
- Header shows compact "124.3k tokens" with the exact count on hover.
- Add common.tokens i18n key (en/zh/zh-TW/jp/kr).
- Estimate the in-progress count from streamed chars (÷4, mirroring the
  CLI spinner) via a new streamingResponseChars per-session field, reset
  on each send; drop the dead status.tokens/elapsed fields.
- CLI spinner rows use formatTokens to drop the "1.0k" artifact.
2026-06-12 15:25:56 +08:00
程序员阿江(Relakkes)
9238481e86 fix(desktop): trust loopback web dev access
Allow local browser origins such as 127.0.0.1, localhost, and ::1 to use the desktop server without H5 token flow, while keeping LAN and public origins behind H5 access rules. Also make Vite SPA healthcheck fallback to the default loopback backend and document scoped verification expectations.

Tested: bun test src/server/__tests__/h5-access-policy.test.ts
Tested: bun test src/server/__tests__/h5-access-auth.test.ts
Tested: bun test src/server/middleware/cors.test.ts
Tested: cd desktop && bun run test -- src/lib/desktopRuntime.test.ts --run
Tested: git diff --check
Not-tested: bun run verify and coverage were intentionally skipped for this scoped local-dev fix.
Scope-risk: moderate
2026-06-12 12:29:15 +08:00
程序员阿江(Relakkes)
3d02e3a91a fix(proxy): establish OpenAI prompt cache semantics (#789)
Strip the rotating billing attribution line before converting system
prompts to OpenAI Chat/Responses requests, forward a stable
prompt_cache_key derived from the client session, request stream usage
explicitly on Chat streams, and map cached_tokens back to Anthropic
cache_read_input_tokens with exclusive input accounting.
2026-06-12 12:28:26 +08:00
程序员阿江(Relakkes)
d7b8fb032c fix(desktop): preview exit plan approvals (#793)
Show ExitPlanMode approvals as a rendered plan preview in desktop chat,
forward plan feedback and requested prompt permissions through the desktop
WebSocket permission response, and keep permission-mode restoration owned by
the CLI runtime.

Tested: bun run verify
Confidence: high
Scope-risk: moderate
2026-06-12 11:16:31 +08:00
程序员阿江(Relakkes)
58d5221ca1 feat(activity): add plugin and skill usage insights
Add historical tool and skill aggregation to activity stats, compact the token summary, and show Codex-style activity insights with plugin/skill ranking.

Tested: bun test src/utils/__tests__/stats.test.ts
Tested: bun run check:persistence-upgrade
Tested: bun run check:desktop
Not-tested: bun run check:server (previous full run exposed unrelated conversations WebSocket timeouts; focused stats and persistence checks passed)
Confidence: medium
Scope-risk: moderate
2026-06-12 10:41:52 +08:00
程序员阿江(Relakkes)
be4984009c fix(desktop): hide Windows subprocess consoles (#802)
Ensure Electron sidecar launch and Windows taskkill calls hide console windows, and pass the same hidden-window spawn option through desktop CLI and scheduled-task subprocess launches.

Tested: cd desktop && bun test ./electron/services/sidecarManager.test.ts
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/cron-scheduler-launcher.test.ts
Tested: bun run check:native
Tested: bun run check:server
Not-tested: Windows GUI quit smoke
Confidence: medium
Scope-risk: narrow
2026-06-12 10:16:58 +08:00
程序员阿江(Relakkes)
ae32599ba8 fix(trace): stabilize live trace updates
Keep live trace polling sensitive to in-place call changes, scope detail section collapse state by trace session, and expose trace rows with list/button semantics.

Tested: cd desktop && bun run test -- TraceList.test.tsx TraceSession.test.tsx
Tested: cd desktop && bun run lint
Tested: bun test src/server/__tests__/trace-capture.test.ts
Confidence: medium
Scope-risk: narrow
2026-06-12 09:22:13 +08:00
Relakkes Yang
8179a99967 fix: allow mapped-drive workspaces in bypass mode
Mapped Windows drives can resolve to UNC paths before the CLI starts. Treat the UNC prefix as safe only after the target has already been proven to be inside the allowed working directory, while keeping sensitive paths and out-of-workspace UNC writes behind safety checks.

Tested: bun test src\\utils\\permissions\\filesystem.test.ts

Tested: real local app server/WebSocket session with deepseek-v4-pro and --dangerously-skip-permissions wrote through X:\\project without a permission_request.

Not-tested: full check:server is still red on this Windows checkout due pre-existing unrelated failures in shell env, H5/local-file, MCP, FileRead CJK, and a darwin-only expectation.

Confidence: high

Scope-risk: narrow
2026-06-12 09:03:53 +08:00
程序员阿江(Relakkes)
d3d7566f0c refactor(trace): redesign trace UI with LangSmith-style two-pane layout
UI rebuild (desktop):
- TraceSession: replace 3-column layout with two panes — turn-grouped
  timeline tree (draggable splitter, search/filter, keyboard nav) and a
  section-flow detail panel (Response / Messages / System Prompt /
  Tools / Parameters / Raw), collapse state persists across spans
- Render LLM requests/responses semantically: messages as role-colored
  conversation with tool_use/tool_result pairing instead of raw JSON
  dumps; Raw fallback via CodeViewer for legacy truncated records
- TraceList: row-style list with model chips, mono metrics, hover
  actions; content-visibility rows (no virtualization, WebKit-safe)
- i18n synced across zh/en/jp/kr/zh-TW (+25/-55 keys)

Data & capture (server):
- Capture full bodies: preview cap 2048 -> 240k chars, stream cap
  256KB -> 1MB; list API trims previews to keep polling light; new
  GET /api/sessions/:id/trace/calls/:callId returns the full record
- Extract per-call token usage at read time (SSE + JSON + proxy
  wrapped); mtime-keyed read cache for the polling path
- Fix sensitive-key regex redacting *_tokens count fields, which made
  token stats always report 0

Frontend data layer:
- SSE stream reassembly (Anthropic + OpenAI chat) adapted from
  claude-tap (MIT, attribution in THIRD_PARTY_LICENSES.md), request/
  response body parsers, shared formatters, on-demand call detail
  cache; traceViewModel gains tokenUsage/isLifecycleNoise, drops
  fullRaw

Tested:
- bun run check:server (1201 pass)
- bun run check:desktop (lint + 1358 tests + build)
- Chromium walkthrough against real local traces: list, session tree,
  LLM semantic detail (new format), legacy fallback, tool detail
2026-06-11 01:02:51 +08:00
程序员阿江(Relakkes)
e8fcccebf0 fix: defer permission restarts during active turns (#626)
Persist permission mode changes immediately, but defer restart-only permission transitions until the active desktop turn emits its terminal result.

Tested:
- bun test src/server/__tests__/conversations.test.ts -t "should defer bypass permission restarts until the active turn completes"
- bun test src/server/__tests__/conversations.test.ts -t "permission"
- bun run check:server

Scope-risk: narrow
2026-06-11 00:00:11 +08:00
程序员阿江(Relakkes)
0d45439fbe feat(trace): add session trace monitoring (#606)
Tested:
- cd desktop && bun run test -- --run src/pages/TraceList.test.tsx
- bun test src/server/__tests__/trace-capture.test.ts
- bun run check:desktop
- bun run check:server

Scope-risk: broad
2026-06-10 17:13:27 +08:00
程序员阿江(Relakkes)
56661c7967 fix: support desktop output style config (#652)
Fixes #652.

Add desktop/server output style settings APIs and a General Settings picker
that mirrors the Claude CLI outputStyle sources.

Persist active-project choices to .claude/settings.local.json and global
choices to user settings, and route /config to the local settings UI.

Tested:
- bun test src/server/__tests__/settings.test.ts
- cd desktop && bun run test -- src/components/chat/composerUtils.test.ts src/stores/settingsStoreOutputStyle.test.ts src/pages/SettingsOutputStyle.test.tsx
- cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx
- bun run check:desktop
- bun run check:server
- bun run verify

Confidence: high
Scope-risk: moderate
2026-06-10 15:24:37 +08:00
程序员阿江(Relakkes)
e8bf789961 fix(provider): request non-stream OpenAI chat tests (#638)
Ensure custom OpenAI-compatible provider tests explicitly request non-stream responses for both direct connectivity checks and the proxy pipeline. This avoids default SSE responses being parsed as empty JSON by provider validation.

Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "requests non-stream OpenAI Chat responses during provider tests"
Tested: bun test src/server/__tests__/providers.test.ts
Tested: bun test src/server/__tests__/proxy-transform.test.ts
Tested: bun run check:server
Confidence: high
Scope-risk: narrow
2026-06-09 22:16:38 +08:00
程序员阿江(Relakkes)
d3b2f868a9 fix: guard prewarm resume shutdown paths (#611)
Prevent desktop prewarm launches from inheriting interrupted-turn resume state, while leaving explicit user-message startup unchanged. Also stop server-side background schedulers during shutdown so app quit cannot leave scheduled task runners alive.

Tested:

- bun test src/server/__tests__/conversation-service.test.ts

- bun test src/server/__tests__/conversations.test.ts -t "prewarm"

- bun test src/server/__tests__/conversations.test.ts -t "permission"

- bun test src/server/__tests__/diagnostics-service.test.ts -t "keeps fatal startup errors visible on stderr while recording diagnostics"

- bun test desktop/electron/services/windows.test.ts desktop/electron/services/tray.test.ts desktop/electron/services/sidecarManager.test.ts src/server/__tests__/server-shutdown.test.ts

- bun run check:server
2026-06-09 21:44:46 +08:00
程序员阿江(Relakkes)
ddcfa5faae feat(adapters): add WhatsApp linked-device support (#573)
Add a WhatsApp adapter backed by Baileys linked-device auth, plus desktop QR binding UI, server config endpoints, sidecar startup wiring, tests, and documentation.

Constraint: Uses WhatsApp Web linked-device auth, not Meta WhatsApp Business Cloud API.

Tested:
- cd adapters && bun run check:adapters
- bun test src/server/__tests__/adapters.test.ts
- cd desktop && bun run check:desktop
- bun run check:native
- bun run check:persistence-upgrade
- bun run check:docs

Not-tested:
- Live WhatsApp QR pairing, because no WhatsApp account/device was exercised here.
- bun run check:server, because the existing src/server/__tests__/conversations.test.ts timeout still fails independently.

Confidence: medium
Scope-risk: moderate
2026-06-09 21:31:46 +08:00
程序员阿江(Relakkes)
385b996736 fix: defer runtime restarts during active turns (#626)
Avoid killing an in-flight desktop SDK turn when runtime config changes during tool execution. Persist the requested runtime immediately, then restart after the turn emits its terminal result.

Tested:
- bun run check:server
- real provider tool-turn model switch smoke
- bun run check:coverage (changed-line coverage passed; unrelated global lanes still fail)

Scope-risk: narrow
2026-06-09 21:06:24 +08:00
程序员阿江(Relakkes)
a7263cbaf7 fix(agent): avoid concurrent worktree config writes (#572)
Git writes upstream branch config when a worktree starts from origin/main. Use the already-resolved base SHA as the worktree start point so parallel agent worktrees do not race on shared .git/config.

Tested: bun test src/utils/__tests__/worktree.test.ts

Tested: real gpt-5.5 Sub2API run with four worktree-isolated agents

Not-tested: bun run check:server currently fails unrelated WebSocket restart/timeouts

Confidence: high

Scope-risk: narrow
2026-06-09 16:31:55 +08:00
程序员阿江(Relakkes)
892f5e193a fix(desktop): restore permission mode after exiting plan mode (#623)
桌面端用 bypassPermissions 进入计划模式、退出后,权限选择器停留在"计划模式",
导致下一个工具调用又弹权限申请。两层根因都修:

- 回传链路断裂:服务端 WS handler 把 CLI 广播的权限模式变化(status:null +
  permissionMode)当成 thinking 丢弃,桌面端协议也没有承载权限模式的入站消息,
  CLI 恢复后的权限永远同步不到 UI。新增 permission_mode_changed 回传通道,桌面端
  据此校正选择器(只更新本地、不回发避免回环;未知模式忽略)。

- 重启抹掉 prePlanMode:bypass→plan 因策略"切换涉及 bypass 就重启"而重启 CLI,
  新进程直接以 plan 启动、prePlanMode 为空,ExitPlanMode 只能恢复成 default 而非
  bypassPermissions。收窄 needsRestart 为只在"进入 bypass"时重启;从 bypass 切出
  保持进程不变、走进程内 transition,CLI 才会栈存 prePlanMode 并在退出 plan 时
  正确恢复 bypass,与 TUI 行为一致。

测试:服务端 ws-memory-events 新增权限回传 + 重启策略用例;桌面端 chatStore 新增
回传校正 + 防回环 + 未知模式忽略用例。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 22:29:01 +08:00