46 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
b6aeaf0109 feat: add skill marketplace preview flow
Tested: bun test src/server/__tests__/skill-market.test.ts
Tested: cd desktop && bun run test -- SkillCenter.test.tsx skillMarketStore.test.ts generalSettings.test.ts ComputerUseSettings.test.ts --run
Tested: cd desktop && bun run test -- persistenceMigrations.test.ts --run
Tested: bun run check:desktop
Tested: real browser smoke for Skill Vetter across white, light, and dark themes
Not-tested: live install of an uninstalled marketplace skill to disk
Confidence: medium
Scope-risk: moderate
2026-07-03 23:34:19 +08:00
程序员阿江(Relakkes)
ce2c908161 fix(desktop): prevent duplicate terminal lines (#964)
Ensure terminal runtimes are started through a single in-flight start, invalidate stale async starts on destroy, and load xterm base styles before app globals while hiding helper/accessibility layers in the terminal host.

Tested: cd desktop && bun run check:desktop
2026-07-03 18:28:39 +08:00
程序员阿江(Relakkes)
6818db34fb fix(desktop): overhaul touch-H5 interaction (#780)
Mark <html data-touch-h5> before first paint when the bundle runs in a
phone browser (no Electron host + coarse pointer) and scope every
mobile-only fix under it, so desktop shells and desktop browsers are
untouched:

- raise form controls to 16px and cap the iOS viewport scale, so
  focusing the composer no longer zooms the page and never zooms back
- disable content-visibility paint skipping on transcript/trace rows
  there (long-press selection on iOS WebKit jumps or drops selections
  when they extend into skipped rows); halve the virtualization
  thresholds on touch as the replacement paint bound for long sessions
- size the app shell to visualViewport so the composer rides the soft
  keyboard instead of being covered, snap back WebKit's keyboard pan,
  and keep the transcript tail pinned while the container shrinks
- pad the shell with safe-area insets (viewport-fit=cover) and drop the
  bottom inset while the keyboard is up
- keep message action bars (copy/branch) always visible on touch since
  hover never fires there; kill the WKWebView tap flash and body
  rubber-banding
- move the two inline content-visibility styles (trace message blocks,
  trace list rows) to classes so the touch scope can reach them

Tested: cd desktop && npx vitest run (1474 tests)
Tested: cd desktop && npx tsc --noEmit && npx vite build
Tested: Playwright chromium smoke against the built dist - desktop
context unchanged, iPhone/WeChat and Android contexts get the marker,
viewport lock, 16px controls, visible action bars and selectable rows
2026-06-13 09:16:37 +08:00
程序员阿江(Relakkes)
2f243fe920 fix(desktop): stabilize Windows settings toggles (#788, #791)
Prevent Settings General checkbox focus/reflow from using off-row sr-only inputs, close stale native preview views when leaving session pages, and avoid Windows notification enable-time smoke side effects.

Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx --reporter verbose
Tested: cd desktop && bun run test -- src/components/layout/ContentRouter.test.tsx --reporter verbose
Tested: cd desktop && bun run test -- src/lib/desktopNotifications.test.ts --reporter verbose
Tested: cd desktop && bun run lint
Tested: bun run check:desktop
Confidence: medium
Scope-risk: narrow
2026-06-12 10:53:02 +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)
c97bd55a57 fix(desktop): restore native window dragging (#770 #796)
Remove the Windows renderer-side drag delta fallback and keep frameless window movement on Electron app-region handling. Reject drag movement payloads on the legacy IPC channel so window drags cannot mutate bounds through repeated setPosition calls.

Tested: cd desktop && bun run test --run src/hooks/useElectronWindowDragRegions.test.tsx electron/ipc/capabilities.test.ts src/lib/desktopHost/electronHost.test.ts
Tested: bun run check:desktop
Tested: bun run check:native
Confidence: high
Scope-risk: narrow
2026-06-12 10:39:36 +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 Yang
98b79ce51a fix: restore Windows custom desktop chrome
Use frameless Electron chrome only on Windows and remove the native Windows application menu so the packaged app matches the previous Tauri-style desktop surface.

Add a Windows-only manual drag fallback for desktop drag regions, while excluding tab reorder targets and preserving macOS/Linux native chrome and menu behavior.

Tested: cd desktop && bun run test --run electron/services/menu.test.ts electron/services/windows.test.ts src/hooks/useElectronWindowDragRegions.test.tsx src/components/layout/TabBar.test.tsx src/components/layout/Sidebar.test.tsx src/lib/desktopHost/electronHost.test.ts electron/ipc/capabilities.test.ts

Tested: cd desktop && SKIP_INSTALL=1 bun run build:windows-x64

Tested: Computer Use Windows packaged app smoke verified no native menu, custom controls, drag regions, tab reorder, close-to-background, and deepseek-v4-pro provider response FINAL_WINDOWS_ELECTRON_REAL_PROVIDER_OK.

Not-tested: full bun run verify.

Constraint: keep custom frameless behavior scoped to win32 so macOS and Linux native chrome paths remain intact.

Confidence: high

Scope-risk: moderate
2026-06-03 23:24:30 +08:00
程序员阿江(Relakkes)
f567236330 fix(desktop): improve activity summary layout
Use container queries for the activity summary grid so the Token usage panel responds to its own width instead of the full desktop viewport. This prevents loose medium-width layouts and over-compressed five-column cards when the settings page is shown with sidebars.

Tested:
- cd desktop && bun run test -- src/pages/ActivitySettings.test.tsx --run --reporter=verbose --pool=forks --maxWorkers=1 --minWorkers=1
- cd desktop && bun run test -- src/theme/globals.test.ts --run --reporter=verbose --pool=forks --maxWorkers=1 --minWorkers=1
- bun run check:desktop
- Electron smoke at 1180px and 900px against the local dev server

Not-tested:
- Coverage report; this is a presentation-only desktop UI change.

Confidence: high
Scope-risk: narrow
2026-06-03 18:28:17 +08:00
程序员阿江(Relakkes)
7e737cb4aa fix(desktop): restore tab bar window dragging
Electron handles custom draggable chrome through CSS app-region rules, not the old runtime startDragging path. Mark the tab strip and empty scroll gutter as native drag regions while keeping tab items and controls explicitly no-drag so tab reordering and close/tool buttons keep receiving pointer events.

Constraint: Electron drag regions swallow pointer events unless interactive children are marked no-drag
Rejected: Keep calling startDragging from the empty gutter | Electron desktopHost does not expose that as the active migration path
Confidence: high
Scope-risk: narrow
Directive: Do not mark tab items themselves as drag regions without revalidating tab reorder behavior
Tested: cd desktop && bun run test src/components/layout/TabBar.test.tsx --run
Tested: cd desktop && bun run lint
Tested: bun run check:desktop
2026-06-03 12:42:14 +08:00
程序员阿江(Relakkes)
81845fbc49 fix: finalize Electron migration boundaries
Complete the Electron replacement boundary before merging by removing the renderer-side Tauri host fallback, tightening H5/browser access so only desktop navigation is tokenless, and moving desktop release publication to a tag-driven GitHub Actions matrix with a single final publish job.

Constraint: H5/browser capability access must not gain tokenless access through localhost or retired Tauri origins

Constraint: Desktop release artifacts must be built by GitHub Actions from version tags, not treated as local build outputs

Rejected: Keep localhost browser origins trusted for convenience | local browser contexts can access loopback services and must use the H5 token path

Rejected: Publish from each matrix job | partial releases can be created before all platforms finish

Confidence: high

Scope-risk: broad

Directive: Do not reintroduce Tauri origins or localhost browser origins into the trusted desktop origin set without a reviewed security design

Tested: bun test src/server/__tests__/h5-access-policy.test.ts src/server/__tests__/h5-access-auth.test.ts src/server/__tests__/diagnostics-service.test.ts src/server/middleware/cors.test.ts

Tested: bun test scripts/pr/release-workflow.test.ts scripts/release-update-metadata.test.ts

Tested: bun run check:desktop

Tested: bun run check:native

Tested: git diff --check

Not-tested: bun run check:server is blocked by expired quarantine entries server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
2026-06-02 22:42:53 +08:00
程序员阿江(Relakkes)
386a41e606 feat(desktop): enable Electron migration path
Introduce the Electron desktop shell alongside the existing React renderer and local Bun server boundary. The migration keeps the DesktopHost contract explicit across Tauri, Electron, and browser runtimes while adding Electron main/preload services for dialogs, shell, notifications, updates, tray/window lifecycle, terminal, preview WebContentsView, app mode, and release/package validation.

The commit also carries the latest local main desktop command updates, including agent slash entries and hidden-by-default markdown thinking details, so the packaged Electron build matches the current main UX surface.

Constraint: React renderer, local Bun server, REST/WebSocket, and sidecar boundaries must remain reusable during the migration
Constraint: macOS dev packages are ad-hoc signed and cannot prove Developer ID notarization or Gatekeeper release launch
Rejected: Browser-only smoke validation | it cannot exercise native dialogs, keychain prompts, notification behavior, or packaged app startup
Confidence: medium
Scope-risk: broad
Directive: Do not remove Tauri host support until signed Electron release artifacts pass native OS smoke on macOS, Windows, and Linux
Tested: bun run check:desktop
Tested: cd desktop && bun run check:electron
Tested: CSC_IDENTITY_AUTO_DISCOVERY=false bun run electron📦dir
Tested: bun run test:package-smoke --platform macos --package-kind dir --artifacts-dir desktop/build-artifacts/electron
Tested: Computer Use read packaged Electron app window at desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app
Not-tested: Developer ID signed/notarized Gatekeeper launch
Not-tested: Real OS notification click-to-session action
Not-tested: Windows and Linux packaged app smoke on real hosts
2026-06-01 22:43:16 +08:00
程序员阿江(Relakkes)
9b3e58b60b perf(desktop): skip off-screen paint on non-virtualized transcript rows (WebKit)
WebKit (Tauri WKWebView) paints complex message DOM ~2x slower than Blink and stutters during scroll. Add content-visibility:auto + contain-intrinsic-size to fully-mounted (non-virtualized) rows so the engine skips off-screen rows without unmounting or re-measuring them.

Measured with Playwright WebKit on the reported laggy 79-message session (main): worst frame 279ms -> 18ms, jank 2 -> 0. Virtualization was ruled out — it made WebKit *worse* (tanstack 12-24fps) due to scroll-time measureElement/re-render cost.

Only non-virtualized rows get the class (no ResizeObserver); virtualized window items stay free of content-visibility to avoid the zero-height measurement regression. Tests guard both directions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 17:42:30 +08:00
程序员阿江(Relakkes)
3b1b96022f feat: add activity profile and themed usage heatmap
Add a local profile surface to the desktop token usage page, including avatar
persistence, display-name editing, cumulative usage metrics, and daily, weekly,
and cumulative heatmap views. Align heatmap color ramps and hover treatment with
the supported white, warm, and dark desktop themes.

Constraint: User profile data must stay local under cc-haha desktop preferences.
Rejected: Keep a separate profile edit panel | the requested design favors a compact profile header with modal editing.
Rejected: Use a blue heatmap ramp | it conflicted with the app theme palettes.
Confidence: high
Scope-risk: moderate
Tested: bun run check:desktop
Tested: bun test src/server/__tests__/desktop-ui-preferences.test.ts
Tested: bun run check:persistence-upgrade
Tested: bun run check:coverage
Not-tested: Full bun run verify
2026-05-31 17:42:30 +08:00
程序员阿江(Relakkes)
d9d0d20782 fix: repair desktop theme rendering for markdown #636
Dark-mode Markdown text was still inheriting Tailwind Typography's default prose color, so normal and italic text could render dark while strong text used the app theme token.

Map markdown prose variables to the desktop theme tokens, move code-viewer hover and line-number styling onto theme tokens, and make Mermaid/Diff rendering follow the active app theme. Write/Edit/tool result and workspace render paths were audited; their core code and diff surfaces already use theme tokens, with the DiffViewer theme handoff tightened here.

Constraint: Mermaid theme customization requires the base theme and concrete color values, so CSS theme tokens are resolved to hex before rendering.

Rejected: Add per-element prose utility overrides only | misses Tailwind Typography defaults for quotes, counters, tables, and future prose elements

Confidence: high

Scope-risk: moderate

Directive: Keep markdown, code, diff, and diagram colors routed through shared desktop theme tokens; do not reintroduce fixed light backgrounds in chat renderers.

Tested: cd desktop && bun run test -- --run src/theme/globals.test.ts src/components/markdown/MarkdownRenderer.test.tsx src/components/chat/CodeViewer.test.tsx src/components/chat/MermaidRenderer.test.tsx src/components/chat/DiffViewer.test.tsx src/components/chat/chatBlocks.test.tsx src/components/workspace/WorkspacePanel.test.tsx

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build

Tested: git diff --check

Not-tested: Full Tauri live desktop session with real provider output; browser broad-audit screenshot capture timed out, but computed colors were captured for all three themes.
2026-05-31 17:42:09 +08:00
程序员阿江(Relakkes)
41d1cb5c00 feat(desktop): browser loading indicator (progress bar + spinner) with timeout fallback
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 17:40:46 +08:00
程序员阿江(Relakkes)
4fce6014a6 fix: preserve Shiki code rendering with legacy fallback
Code blocks should keep the richer Shiki rendering in modern WebUI while avoiding the old WebKit startup crash path by loading Shiki lazily and falling back to Prism only when the runtime cannot safely parse or execute it.

Constraint: Issue #461 is triggered by older Safari/WebKit parsing modern RegExp syntax during startup.
Rejected: Replace Shiki entirely with Prism | visual quality regressed for normal WebUI usage.
Confidence: high
Scope-risk: moderate
Directive: Keep Shiki out of the startup path unless macOS 12 WebView compatibility is re-verified.
Tested: cd desktop && bun run test -- --run src/components/chat/CodeViewer.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: Real WebUI smoke on http://127.0.0.1:1420/ verified six code blocks rendered with data-highlight-engine=shiki.
Not-tested: Physical macOS 12 WebView runtime.
Related: https://github.com/NanmiCoder/cc-haha/issues/461
2026-05-22 17:55:33 +08:00
Relakkes Yang
3c3030fddf fix: recover legacy Windows session workdirs 2026-05-18 13:13:12 +08:00
程序员阿江(Relakkes)
390c18d82c Let desktop users attach files by dropping them into the composer
A user-requested drag target should reuse the existing attachment pipeline instead
of creating a second upload path. The composer now handles browser DataTransfer
drops and Tauri native drag-drop events, while keeping desktop attachments
path-only so large files are not serialized into chat payloads. The fallback
/goal metadata is also aligned with the existing desktop command surface because
the desktop gate exercises that menu while validating composer behavior.

Constraint: Desktop attachments must remain path-only to avoid inflated websocket payloads
Rejected: Read dropped desktop files with FileReader | would reintroduce large inline data payloads
Confidence: high
Scope-risk: moderate
Directive: Do not replace the Tauri drag-drop path conversion with data URLs without rerunning payload-size regression coverage
Tested: cd desktop && bun run test -- --run src/lib/composerAttachments.test.ts src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: bun run check:desktop
Tested: agent-browser overlay and dropped-chip smoke at http://127.0.0.1:1421/?serverUrl=http%3A%2F%2F127.0.0.1%3A3456
Tested: bun run verify
Not-tested: Finder-to-packaged-.app manual drag smoke
2026-05-16 13:18:59 +08:00
程序员阿江(Relakkes)
7dc0b59784 Refine goal UI around memory theme tokens
Goal status needed to read like persistent agent state, not a success alert. Reuse the Memory surface language and expose goal-specific aliases so the visual treatment follows each supported desktop theme.\n\nConstraint: Must keep /goal visible in both active-session chrome and transcript events.\nRejected: Continue using success tokens | they made the UI look like a warning/success card and clashed with white/dark themes.\nConfidence: high\nScope-risk: narrow\nTested: cd desktop && bun run test -- --run src/pages/ActiveSession.test.tsx src/components/chat/MessageList.test.tsx src/theme/globals.test.ts\nTested: cd desktop && bun run lint\nTested: cd desktop && bun run build\nTested: Chrome screenshot fixture for light, white, and dark goal UI tokens.
2026-05-16 01:49:38 +08:00
程序员阿江(Relakkes)
8e8e596817 Bring Settings zoom drift fix onto local main
The local main checkout already had a merge in progress for the Settings zoom synchronization fix. The conflict content in globals.css was resolved in the working tree, so this commit records that existing merge before landing the chat scroll fix.

Constraint: main had an existing MERGE_HEAD before the chat scroll landing
Confidence: medium
Scope-risk: narrow
Directive: Do not conflate this merge commit with the chat scroll fix; it only completes the pre-existing Settings zoom merge
Tested: Not run in this step
Not-tested: Settings zoom regression suite after recording the existing merge
2026-05-15 19:37:04 +08:00
程序员阿江(Relakkes)
c279643cce Prevent Settings zoom controls from drifting
Settings and keyboard zoom controls were able to diverge because the slider only committed on release and captured pointer events around the native range control. The slider now commits through the shared zoom store as it changes, while the range keeps its native drag behavior.

The full desktop gate also enforces Safari 15 compatibility for startup CSS, so the remaining memory theme color-mix tokens were replaced with static equivalents.

Constraint: macOS 12 Safari 15 WebView cannot rely on CSS color-mix in startup-critical desktop CSS
Rejected: Commit Settings zoom only on pointer release | leaves shortcut state and slider state temporarily out of sync
Confidence: high
Scope-risk: narrow
Directive: Keep Settings slider, reset, and keyboard shortcuts routed through the shared uiZoom/appZoom state
Tested: bun run check:desktop
Tested: agent-browser Settings zoom smoke against local Vite plus server
Not-tested: Packaged Tauri app manual drag on macOS hardware
2026-05-15 19:36:14 +08:00
程序员阿江(Relakkes)
c866adc951 Honor desktop thinking controls for provider streams
Desktop sessions must treat the global Thinking toggle as the source of truth across active CLI sessions, title generation, and provider-compatible request bodies. DeepSeek-style streams can start with reasoning blocks before text, so the WebSocket bridge now keeps the UI in thinking state until text content actually starts.

Constraint: DeepSeek and MiniMax use Anthropic-compatible surfaces but expose thinking behavior through provider-specific request and stream shapes
Rejected: Keep provider-specific disabled-thinking env defaults | stale defaults kept overriding the user's global Thinking setting
Rejected: Treat every non-tool stream block as text | reasoning-only startup blocks created a blank streaming gap before the visible thinking bubble
Confidence: high
Scope-risk: moderate
Directive: Do not change thinking stream state transitions without replaying reasoning-before-text provider events
Tested: bun test src/server/__tests__/ws-memory-events.test.ts
Tested: bun run check:server
Tested: bun run verify
Not-tested: Live DeepSeek provider smoke with real quota
2026-05-15 19:35:12 +08:00
程序员阿江(Relakkes)
20035d0fd8 Keep zoom CSS compatibility test scoped
The local main branch already contains memory theme tokens that use color-mix, so the Safari compatibility assertion should cover the startup-sensitive zoom slider CSS block instead of the entire stylesheet.

Constraint: Existing main theme tokens intentionally include color-mix for non-zoom surfaces.
Rejected: Remove the Safari compatibility assertion | the zoom slider still needs coverage for WebView-safe CSS.
Confidence: high
Scope-risk: narrow
Tested: bunx vitest run src/__tests__/generalSettings.test.tsx src/theme/globals.test.ts
Not-tested: Full bun run verify
2026-05-14 23:27:18 +08:00
程序员阿江(Relakkes)
57e66f0019 Merge desktop zoom settings polish into main
Bring the verified settings zoom interaction cleanup from the desktop worktree onto local main while preserving the existing main history.

Constraint: Local main already contains unrelated desktop commits after the worktree base.
Confidence: high
Scope-risk: narrow
Tested: bunx vitest run src/__tests__/generalSettings.test.tsx src/theme/globals.test.ts
Tested: browser smoke verified dark-theme order and slider visibility at localhost:5174
Not-tested: Full bun run verify after merge
2026-05-14 23:25:43 +08:00
程序员阿江(Relakkes)
1f0c888a13 Stabilize desktop zoom settings interaction
The settings zoom slider is a secondary desktop preference, so it now previews drag movement locally before committing the app zoom on release and sits below system notifications. The shortcut hint also spells out reset behavior, and the dark theme slider thumb uses stronger contrast tokens so it stays visible while dragging.

Constraint: Desktop zoom changes affect the full application surface and should not update continuously during pointer drag.
Rejected: Keep zoom directly under theme selection | the control is low-frequency and was visually dominating General settings.
Confidence: high
Scope-risk: narrow
Tested: bunx vitest run src/__tests__/generalSettings.test.tsx src/theme/globals.test.ts
Tested: browser smoke verified dark-theme order and slider visibility at localhost:5174
Not-tested: Full bun run verify
2026-05-14 23:25:20 +08:00
程序员阿江(Relakkes)
667b86303f Prevent memory activity from clashing with desktop themes
Memory tool activity inherited the global warm brand treatment, which made the new desktop memory surface feel detached from white and dark themes. The component now uses memory-specific tokens with a quieter teal family, and the sidebar settings dock is made opaque so scrolling sessions cannot show through it.

Constraint: Desktop memory activity must remain readable across light, white, and dark themes without reusing the classic warm brand surface
Rejected: Keep using color-mix with --color-brand | preserves the original warm tint mismatch in white theme
Confidence: high
Scope-risk: narrow
Directive: Keep memory activity colors on memory-specific tokens instead of generic brand tokens
Tested: cd desktop && bun run test src/components/chat/MessageList.test.tsx --run
Tested: cd desktop && bun run test src/components/layout/Sidebar.test.tsx --run
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: Browser smoke screenshots for light, white, and dark memory activity previews
2026-05-14 23:13:02 +08:00
程序员阿江(Relakkes)
e070c4a0d0 Make upgrade failures diagnosable without deleting user state
Desktop startup can fail before React mounts on older WebViews, so an HTML-level watchdog now renders startup diagnostics even when the module bundle never reaches the app code. Persistent provider migration now imports legacy root provider config into cc-haha-owned storage without deleting the old source file, and plugin marketplace cleanup refuses obvious corrupted cache roots or outside paths.

Constraint: User explicitly accepted the current reviewed state for landing despite remaining review concerns.

Constraint: Global ~/.claude state is user-owned and protected; automatic repair must avoid deleting shared config, transcripts, skills, MCP, plugins, OAuth, adapters, and teams.

Rejected: Tell users to delete ~/.claude or ~/.claude/cc-haha | unsafe because it can destroy user-owned Claude state and still may not fix WebView compatibility failures.

Confidence: medium

Scope-risk: moderate

Directive: Do not weaken protected-path checks; future deletion paths should validate real paths and symlink behavior before recursive rm.

Tested: bun test src/utils/plugins/installedPluginsManager.test.ts src/utils/plugins/marketplaceManager.test.ts

Tested: bun run check:server

Tested: cd desktop && bun run test -- --run src/main.test.tsx index-html.test.ts vite-config.test.ts src/theme/globals.test.ts

Tested: cd desktop && bun run build

Tested: bun run check:coverage

Not-tested: live macOS 12/Safari 15 WKWebView startup on an affected machine.

Not-tested: H5 diagnostic URL redaction and symlink-escape hardening are known follow-up risks from review.
2026-05-14 18:04:47 +08:00
程序员阿江(Relakkes)
f1e3f4bd20 Preserve activity stats contrast across desktop themes
The activity heatmap was reusing broad primary and inverse tokens whose
meaning changes by theme. The usage tooltip became unreadable in dark mode,
and nearby status badges referenced semantic container tokens that were not
available in every theme. This introduces activity-specific theme tokens and
locks the token surface with focused regression coverage.

Constraint: Desktop supports light, white, and dark themes from globals.css
Rejected: Change global primary or inverse tokens | broader blast radius across unrelated controls
Confidence: high
Scope-risk: narrow
Directive: Keep activity heatmap colors behind activity-specific tokens before changing palette behavior
Tested: cd desktop && bun run test ActivitySettings.test.tsx globals.test.ts
Tested: bun run check:desktop
Tested: Browser smoke on dark Token usage tooltip at http://127.0.0.1:5179
Not-tested: Native packaged app visual smoke
2026-05-13 18:48:00 +08:00
程序员阿江(Relakkes)
a381bf0412 Make pure white theme complete across desktop surfaces
The pure white appearance option needed to avoid warm-theme leakage while preserving the existing warm classic brand theme. This adds the white theme mode, keeps local browser startup from reusing stale H5 server URLs in dev, and moves visible legacy warm surfaces onto theme tokens.

Constraint: H5 server auth policy, CORS policy, SDK routes, adapter routes, and IM access paths must not change for a visual theme fix
Rejected: Rename the original light theme to pure white | the original theme is a warm classic palette, not a neutral white workspace
Confidence: high
Scope-risk: moderate
Directive: Keep structural white-theme borders neutral; reserve the warm brand color for selected states, primary actions, and small accents
Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx src/lib/desktopRuntime.test.ts src/lib/persistenceMigrations.test.ts src/stores/uiStore.test.ts src/stores/settingsStore.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: bun test src/server/__tests__/settings.test.ts src/server/__tests__/h5-access-policy.test.ts src/server/__tests__/h5-access-auth.test.ts src/server/middleware/cors.test.ts
Tested: Browser smoke at http://127.0.0.1:5173 with data-theme=white, no H5 token prompt, /status inspector visible, inspector border #DDE3EA
Not-tested: Full bun run verify gate
2026-05-13 10:38:13 +08:00
程序员阿江(Relakkes)
cc9bcb2017 Make H5 chat usable on phone-sized browsers
The browser H5 surface now switches to a phone-oriented shell: the sidebar becomes a closed-by-default drawer, chat stays primary, workspace and terminal panels stay off the mobile chat surface, composer controls use larger touch targets, and mobile menus avoid desktop-only widths and keyboard hints. Desktop and Tauri sidebar behavior remain on the existing store-driven path.

Constraint: H5 is personal/team browser access layered on the existing desktop web UI, so the normal desktop app must keep its current layout behavior.

Rejected: Share the global sidebarOpen default for mobile first paint | it can flash the drawer open before effects run on a phone.

Confidence: high

Scope-risk: moderate

Directive: Keep mobile-only layout branching behind useMobileViewport() && !isTauriRuntime() unless a future task explicitly redesigns the native desktop shell.

Tested: cd desktop && bunx vitest run src/hooks/useMobileViewport.test.tsx src/components/layout/AppShell.test.tsx src/components/layout/Sidebar.test.tsx src/pages/ActiveSession.test.tsx src/components/chat/ChatInput.test.tsx src/components/controls/PermissionModeSelector.test.tsx

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build
2026-05-10 01:11:24 +08:00
程序员阿江(Relakkes)
1d4d87a55e fix: Prevent light inspector panels in dark theme
The session inspector reused a one-off light palette, so /status, /cost,
and /context could render bright panels inside the dark desktop shell.
This moves the inspector and MCP switch control onto theme-scoped tokens
while preserving the existing light-theme look.

Constraint: Desktop dark mode must keep the existing surface hierarchy and avoid changing global brand colors.
Rejected: Recolor the shared Material palette | too broad for a component-specific regression.
Confidence: high
Scope-risk: narrow
Directive: Keep slash inspector surfaces on semantic theme tokens; do not reintroduce fixed light hex classes.
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test src/__tests__/pages.test.tsx src/__tests__/mcpSettings.test.tsx
Tested: cd desktop && bun run build
Tested: agent-browser screenshots for /status, /usage, /context, and MCP settings on http://127.0.0.1:5184/
2026-05-02 11:46:42 +08:00
程序员阿江(Relakkes)
e1474b5c30 Improve dark model selection contrast
The model selector reused the light-theme primary fixed surface for selected rows, which made dark mode render a pale block with poor text contrast. This gives the selector its own selected-row tokens so dark mode can keep a low-luminance surface while light mode preserves the existing look.

Constraint: Keep the fix scoped to desktop theme tokens and the existing selector component
Rejected: Change primary-fixed globally | too broad because other components rely on that token semantics
Confidence: high
Scope-risk: narrow
Directive: Do not point selected model rows back to primary-fixed without checking dark-mode contrast
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: git diff --check
Not-tested: Browser screenshot capture blocked by an existing Chrome DevTools profile instance
2026-04-28 16:38:16 +08:00
程序员阿江(Relakkes)
6d40b2befa fix: Keep desktop chats on selected provider runtimes
Desktop sessions can switch provider and model while a CLI subprocess is already alive, so the server now serializes runtime restarts and marks provider-managed launches to prevent stale settings env from overriding the selected provider. Provider settings also write API key env consistently and clear stale managed keys before syncing.

This includes the related desktop/docs brand asset refresh and keeps the desktop locale default in Chinese, with tests updated to match the current provider semantics.

Constraint: Session-scoped model selection must win over cc-haha/settings.json and inherited ANTHROPIC_* values.
Rejected: Store the selected model as a global provider activeModel | chat runtime selection is per session.
Confidence: high
Scope-risk: moderate
Directive: Do not remove CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST without validating Desktop provider switching against stale settings env.
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/conversations.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/providers-real.test.ts
Tested: cd desktop && bun run test src/stores/settingsStore.test.ts
Tested: cd desktop && bun run lint
Tested: git diff --check
Not-tested: Full desktop production package/signing.
2026-04-24 13:24:31 +08:00
程序员阿江(Relakkes)
f911b16ada Merge host terminal support into post-release test branch
The detached worktree implementation adds a Settings terminal for command-based setup flows. The merge keeps the target branch's current adapter/runtime dependencies while adding the new portable-pty backend, xterm frontend, UTF-8 output handling, and host-shell environment propagation.

Constraint: Target branch had newer desktop dependency changes, including anyhow in the Tauri crate.
Constraint: Existing uncommitted work in the main worktree had to stay out of this merge commit.
Rejected: Fast-forward the checked-out branch under a dirty worktree | would risk mixing unrelated local changes into the branch state.
Confidence: high
Scope-risk: moderate
Directive: Treat the terminal as host-shell integration; keep PATH and UTF-8 locale handling together when changing startup behavior.
Tested: cargo fmt --check
Tested: cargo test --lib
Tested: cargo check
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test src/pages/TerminalSettings.test.tsx
Tested: git diff --check
Not-tested: Rebuilt macOS DMG from the target branch after merge.
2026-04-24 09:38:02 +08:00
程序员阿江(Relakkes)
0c58a9f36f Give desktop users a real terminal for command-based setup
Some setup flows end in a shell command instead of a natural-language install path, so Settings now exposes a host PTY terminal backed by portable-pty and xterm. The terminal inherits the user's login-shell environment, forces a UTF-8 locale when needed, and preserves split UTF-8 output so Chinese paths render correctly.

Constraint: Desktop GUI apps do not inherit the user's interactive shell PATH on macOS.
Constraint: Command output may split UTF-8 characters across PTY reads.
Rejected: Use Tauri shell commands only | users need an interactive PTY for copy-pasted install flows.
Rejected: Ask users to edit shell profiles | terminal setup should work out of the box.
Confidence: high
Scope-risk: moderate
Directive: Keep terminal startup tied to host environment checks; do not bundle runtimes to solve PATH issues.
Tested: cargo fmt --check; cargo test --lib; cargo check; cd desktop && bun run lint; cd desktop && bun run test src/pages/TerminalSettings.test.tsx; cd desktop && bun run build; cd desktop && bun run build:macos-arm64
Tested: Computer Use verified npm is available in the built macOS app terminal and Chinese output renders after UTF-8 decoding fix.
Not-tested: Native Windows/Linux package runtime validation.
2026-04-24 09:36:00 +08:00
程序员阿江(Relakkes)
7d1e2a2ee4 Reduce sidebar control clutter in session navigation
The project filter and session search were competing for the same narrow vertical lane in the desktop sidebar. This change merges them into a single search surface, keeps project scoping available through an embedded trigger, and trims the surrounding control chrome so the sidebar reads like one cohesive tool instead of stacked widgets.

Constraint: Sidebar filtering behavior and existing project dropdown logic had to remain intact
Constraint: This commit must exclude unrelated in-progress desktop and server changes in the worktree
Rejected: Keep separate project and search controls with smaller spacing | still wastes vertical space and keeps the visual split
Rejected: Move project filtering into a second modal flow | adds friction to a frequent navigation task
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep project scoping embedded in the search lane unless session discovery changes materially
Tested: bun run test src/components/layout/ProjectFilter.test.tsx src/components/layout/Sidebar.test.tsx src/__tests__/pages.test.tsx; bun run lint; bun run build
Not-tested: Manual dark-theme screenshot pass after the final integrated layout change
2026-04-22 17:00:53 +08:00
程序员阿江(Relakkes)
870cfe8b74 Make desktop tab reordering independent of native HTML drag events
The tab strip was relying on browser drag-and-drop, which worked in the web UI
but did not reliably start inside the macOS overlay title bar in the packaged
Tauri desktop app. This switches tab reordering to a pointer-driven interaction
that computes insertion positions directly, keeps the drag indicator behavior,
and preserves the separate window-drag fallback for non-tab title-bar space.

Constraint: Must work inside the macOS overlay title bar where native window hit-testing interferes with browser drag events
Rejected: Keep tuning draggable/drop handling | web behavior stayed fine while desktop never consistently entered the drag sequence
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep tab reordering on explicit pointer handling unless the title-bar architecture changes away from overlay hit-testing
Tested: bun run test -- src/components/layout/TabBar.test.tsx; bun run lint; bun run build
Not-tested: Manual packaged desktop app verification after this commit
2026-04-20 23:07:15 +08:00
程序员阿江(Relakkes)
c70da2459d Ship desktop code blocks that render reliably in the macOS release build
The desktop app was still falling back to raw text in release builds for some
fenced code blocks, which left bash snippets visually wrong and too heavy for
chat use. This change switches the Shiki path to the JavaScript regex engine,
restores tighter code-block defaults for chat, and bumps the desktop app
version to 0.1.4 for the release artifacts.

Constraint: The packaged Tauri app must render markdown code blocks consistently without relying on WebView WASM behavior
Constraint: Chat code blocks should stay compact and should not show line numbers unless a caller explicitly requests them
Rejected: Keep tuning fallback-only CSS | did not address the packaged highlighter path failing to initialize
Rejected: Leave line numbers on by default | too noisy for assistant replies and bash snippets
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: If code blocks regress again, inspect the highlighter engine path before adjusting chat spacing CSS
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test CodeViewer.test.tsx MarkdownRenderer.test.tsx Sidebar.test.tsx
Tested: cd desktop && bun run build:macos-arm64
Not-tested: Windows packaged build after the engine switch
2026-04-20 18:39:11 +08:00
程序员阿江(Relakkes)
03112f7152 Make desktop sidebar collapse recoverable without stealing focus
The desktop shell now owns sidebar collapse state, the collapsed rail keeps a
visible recovery affordance, and keyboard search expands the sidebar before
focusing. The UI work also smooths the width transition so the main chat area
can take over without the previous abrupt cutover.

Constraint: The desktop app must keep a recovery path visible in narrow layouts on macOS and Windows
Constraint: Existing sidebar behavior needed regression coverage before further UI work
Rejected: Fully hide the sidebar at 0 width | recovery affordance became too fragile for this iteration
Rejected: Keep boxed restore controls in the collapsed rail | visually heavy and easy to misplace
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep the collapsed rail width and the inner sidebar panel width in sync or expand controls will be clipped again
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test Sidebar.test.tsx
Not-tested: Full desktop manual pass across every app screen after the final icon/layout tweaks
2026-04-20 18:14:01 +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
fb011588f9 fix: correct windows tab bar overflow alignment 2026-04-19 17:56:42 +08:00
程序员阿江(Relakkes)
41fb22790a feat: self-host fonts to eliminate Google CDN dependency
Replace Google Fonts CDN links with locally hosted woff2 files to avoid
FOUT/FOIT on slow networks and ensure the app works in regions where
Google is blocked. Material Symbols uses font-display: block to prevent
raw icon text from flashing on load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 22:30:18 +08:00
程序员阿江(Relakkes)
f81fe41797 feat: migrate code blocks to shiki for VS Code-quality syntax highlighting
Replace prism-react-renderer with shiki/react-shiki in CodeViewer for
dramatically better tokenization (50+ TextMate scopes vs ~15 Prism tokens).
Custom warm-code theme with improved comment contrast (#5C6B7A, ~5:1 ratio)
and warm off-white background (#FDFCF9). Update DiffViewer to use matching
warm color palette with CSS variables instead of hardcoded GitHub colors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 21:24:14 +08:00
程序员阿江(Relakkes)
8cc38f6979 chore: delete highlightCode.ts, remove hljs CSS, fix test for new DiffViewer
- Deleted desktop/src/components/chat/highlightCode.ts (no longer needed)
- Removed all .hljs-* CSS rules from globals.css
- Updated chatBlocks test for react-diff-viewer-continued (doesn't render
  diff content in jsdom, so test verifies component mounting instead)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 22:29:52 +08:00
程序员阿江(Relakkes)
993b96cd39 Stabilize the desktop transcript so long agent sessions stay readable
The desktop app now keeps the composer stable while turns are active,
reduces low-signal tool noise in the transcript, restores project context
under the composer after session creation, and relies on the CLI's own
permission requests instead of injecting broader desktop-side Bash asks.

This also brings in the supporting desktop app source tree and the server
routes/session metadata needed for git info, filesystem browsing, session
resume, slash commands, and SDK-backed permission bridging so the UI can
operate as a coherent feature instead of a partial patch.

Constraint: Desktop transcript needs to stay usable during long multi-tool sessions without hiding file-change diffs
Constraint: Permission prompts must mirror CLI behavior closely enough that read-only commands do not get desktop-only prompts
Rejected: Keep rendering Read/Bash bodies inline | too noisy and unlike the intended transcript model
Rejected: Commit only the touched desktop files | would leave the newly introduced desktop app incomplete in git history
Confidence: medium
Scope-risk: broad
Reversibility: messy
Directive: Treat non-writing tools as summary-first transcript events; do not re-expand them by default without validating the UX against long sessions
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test -- --run
Tested: bun test src/server/__tests__/conversations.test.ts
Not-tested: Manual visual regression against the exact screenshots in a live desktop session
Not-tested: Full root TypeScript check (repository still has unrelated extracted-native parse failures)
2026-04-06 20:37:44 +08:00