182 Commits

Author SHA1 Message Date
Relakkes Yang
e63db20136 fix: respect manual chat scroll position 2026-04-25 13:59:22 +08:00
Relakkes Yang
f911d9e79d fix: suppress mermaid error overlay 2026-04-25 13:24:26 +08:00
Relakkes Yang
55c5958b55 fix(desktop): stop sidecars before updater install 2026-04-25 13:21:31 +08:00
Relakkes Yang
928be2a4ff fix(desktop): remove install center 2026-04-24 23:05:45 +08:00
程序员阿江(Relakkes)
761031c036 fix: Make desktop MCP tools ready before first turn
Desktop sessions could show MCP configuration in the UI while the CLI SDK child process still started cold on the first user message. Start eligible desktop chat sessions as soon as their websocket is connected, keep init metadata cached but muted, and wait briefly for MCP startup in SDK print mode so turn one sees the tools.

Constraint: Desktop wraps the existing CLI SDK bridge rather than owning MCP startup directly.
Rejected: Prewarm every restored tab | synthetic tabs such as settings would start unnecessary CLI subprocesses.
Confidence: high
Scope-risk: moderate
Directive: Do not remove the synthetic-tab guard without validating restored settings and scheduled-task tabs in the browser.
Tested: bun test src/server/__tests__/conversations.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/mcp.test.ts
Tested: cd desktop && bun run test -- chatStore.test.ts mcpSettings.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: agent-browser E2E new session prewarm plus first message reuse with mock CLI
Not-tested: Full desktop Vitest suite still has pre-existing English-vs-Chinese copy assertion failures.
2026-04-24 17:11:03 +08:00
程序员阿江(Relakkes)
77d2cbfab8 fix: Prevent plugin detail hook mismatch during reload
Plugin actions refresh the selected plugin detail after mutating enabled state. The detail component can enter its loading branch while a plugin is still selected, so every hook must run before that early return.

Constraint: React hook order must stay identical across the detail and loading render paths.
Rejected: Clear the selected plugin before reload | would hide the current context and add UI churn during short refreshes.
Confidence: high
Scope-risk: narrow
Directive: Keep PluginDetail hooks before loading and empty-state returns when adding detail-derived memoization.
Tested: cd desktop && bun run test src/__tests__/pluginsSettings.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Full desktop Vitest suite has pre-existing locale assertion failures unrelated to this plugin fix.
2026-04-24 14:47:17 +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)
773a8a703f Keep desktop chats on the selected provider/model
The desktop model picker now stores a session-scoped provider/model selection instead of relying on the global active provider. That selection is replayed on connect, passed into the CLI startup path, and preserved across turns until the user changes it again.

To make that true end-to-end, the server now restarts the session process when runtime selection changes, injects provider-scoped env for third-party providers, and routes proxy traffic by provider id. The selector UI was also tightened so provider grouping stays visible while the actual model choice remains readable.

Constraint: Different providers can expose the same model id, so chat runtime selection cannot be derived from model id alone
Constraint: A desktop session reuses one CLI subprocess across turns, so runtime changes must restart that process to take effect
Rejected: Keep using Settings active provider as the chat selector | conflates defaults with live session state and breaks overlapping models
Rejected: UI-only runtime switching without server restart | later turns would continue using the old CLI subprocess configuration
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep provider defaults and session runtime overrides separate, and preserve provider-scoped proxy routing when extending model selection surfaces
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test src/stores/chatStore.test.ts
Tested: cd desktop && bun run test src/__tests__/generalSettings.test.tsx
Tested: bun test src/server/__tests__/conversation-service.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts
Tested: bun -e "await import('./src/server/services/titleService.ts'); await import('./src/server/ws/handler.ts')"
Not-tested: Real third-party provider round-trip from the desktop UI against a live upstream account
2026-04-23 13:41:27 +08:00
程序员阿江(Relakkes)
1137c99d5c Clarify how to use shared CLI install commands after desktop setup
The Install Center now spells out the two supported terminal flows after the
bundled launcher is available: keep using `claude` when the official Claude
Code CLI is already installed, or use `claude-haha` otherwise. It also shows
copyable example commands so users understand that Skills, Plugins, and MCP
configuration is shared between both command names.

Constraint: The worktree contains unrelated icon, provider-label, and other UI edits, so this commit stages only the Install Center hint copy and its focused test
Rejected: Leave the launcher status card without command guidance | users would still not know when to use `claude` versus `claude-haha`
Rejected: Duplicate the same explanation in a new settings section | it adds UI weight without improving discoverability over the existing CLI card
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the examples aligned with the real supported command surface; if launcher behavior changes, update both zh/en copy and the InstallCenter test together
Tested: cd desktop && bun x vitest run src/components/settings/InstallCenter.test.tsx; cd desktop && bun run lint
Not-tested: Full desktop production build and manual Settings page click-through after this copy-only follow-up
2026-04-23 12:51:17 +08:00
程序员阿江(Relakkes)
5fea7033e3 Expose the bundled desktop CLI outside the app
The desktop app already shipped a bundled sidecar, but only desktop-managed
sessions could see it. This change installs a `claude-haha` launcher into the
user bin directory, wires PATH setup so new terminals can resolve it, and keeps
desktop installer sessions aligned on the same bundled sidecar resolution path.
The desktop install surface now also reports whether the launcher is ready or
still waiting on a terminal restart.

Constraint: The worktree already contains unrelated icon, docs, and UI changes, so this commit stages only the bundled CLI launcher slice
Rejected: Tell users to install the official Claude CLI separately | it breaks the desktop out-of-box install story
Rejected: Keep the bundled CLI reachable only inside desktop-managed shells | system terminals would still be unable to call the packaged runtime
Rejected: Symlink directly into the app bundle instead of copying to user bin | moving or replacing the app bundle would leave a stale launcher behind
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Proxy-backed non-Anthropic providers still depend on the desktop server; do not assume this launcher makes every provider fully standalone
Tested: bun test src/server/__tests__/desktop-cli-launcher.test.ts src/server/__tests__/settings.test.ts; bun test src/server/__tests__/conversation-service.test.ts; bun test src/utils/shell/bashProvider.test.ts; cd desktop && bun x vitest run sidecars/launcherRouting.test.ts src/components/settings/InstallCenter.test.tsx; cd desktop && bun run lint; cd desktop && bun run build; cargo check --manifest-path desktop/src-tauri/Cargo.toml
Not-tested: Manual packaged desktop app install plus real Terminal/iTerm/PowerShell invocation on fresh macOS and Windows machines
2026-04-23 12:12:49 +08:00
程序员阿江(Relakkes)
90c3db1790 Prevent task-progress updates from corrupting streamed reply formatting
Desktop chat currently reuses one status channel for assistant streaming and
background task progress. When a task update arrived mid-turn, the store
flushed the in-flight markdown into a completed message, which caused the
remaining deltas to render as a second bubble and broke markdown styling.

Keep the reply in streaming state until the turn actually becomes idle, and
lock the behavior with a regression test that injects task progress between
text deltas.

Constraint: Background task progress currently shares the same status channel as assistant streaming
Rejected: Retune markdown renderer styles | would hide the symptom without preserving message integrity
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Do not flush streaming assistant text on non-idle status transitions unless the turn is actually ending
Tested: bun run test src/stores/chatStore.test.ts; bun run lint
Not-tested: Manual desktop UI verification with a live agent session
2026-04-23 12:11:30 +08:00
程序员阿江(Relakkes)
48da5ccbfa Reduce Settings complexity by removing the embedded shell surface
The Settings terminal added a full xterm plus Tauri PTY stack for a job
that is better handled by dedicated install and configuration flows. This
change removes the Settings tab, frontend terminal wiring, Tauri terminal
commands, and the terminal-only dependencies so the desktop settings
surface stays narrower and less fragile.

Constraint: The worktree already contains unrelated desktop icon and UI changes, so this commit stages only the terminal-removal slice
Rejected: Keep a hidden or runtime-only terminal stub | it would still preserve the heavy cross-layer maintenance surface
Rejected: Remove only the Settings tab and leave the Tauri PTY backend | that would leave dead code and unused dependencies behind
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If future install workflows need more power, prefer Settings-native actions and runtime refresh over reintroducing a general shell tab
Tested: bun x vitest run src/__tests__/generalSettings.test.tsx src/__tests__/skillsSettings.test.tsx src/__tests__/pluginsSettings.test.tsx src/__tests__/agentsSettings.test.tsx src/__tests__/mcpSettings.test.tsx src/components/settings/InstallCenter.test.tsx; bun run lint; bun run build; cargo check --manifest-path desktop/src-tauri/Cargo.toml
Not-tested: Manual packaged desktop app click-through after removing the Settings terminal tab
2026-04-23 11:06:32 +08:00
程序员阿江(Relakkes)
376e255b6b feat: add a bundled desktop setup terminal with safer restart handoff
Settings needed a real shell for plugin, MCP, and skill setup without relying on
a globally installed Claude CLI. Add an xterm.js terminal backed by portable-pty,
wire it into the Tauri desktop runtime, and move shell restart handoff to the
new session before old PTY teardown so the UI is less likely to stall behind
child shutdown.

Constraint: The desktop app must inject the bundled CLI into the shell environment instead of requiring a separate global install
Constraint: Restart teardown cannot block the frontend-facing Tauri command path
Rejected: Keep terminal setup inside installer chat only | that flow cannot replace an interactive shell
Rejected: Wait for old PTY shutdown before adopting the new session | it keeps restart vulnerable to hung child teardown
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Preserve new-session handoff before old-session cleanup when changing terminal lifecycle or restart logic
Tested: bunx vitest run src/__tests__/terminalPanel.test.tsx src/components/settings/TerminalPanel.restart.test.tsx; bun run lint; cargo check
Not-tested: Full packaged-app command echo and repeated manual restart behavior still need additional runtime verification
2026-04-22 18:07:09 +08:00
程序员阿江(Relakkes)
467debcd8b feat: add a desktop setup terminal without blocking shell restarts
The desktop Settings flow needed a real shell for bundled CLI setup, but the
restart path could hang behind old PTY teardown. Wire an xterm.js panel to a
portable-pty backend, inject the bundled CLI into the shell bootstrap, and
switch to the new session before cleaning up the previous one so restart work
stays off the frontend critical path.

Constraint: The desktop app must ship its own CLI entrypoint instead of depending on a global Claude install
Constraint: PTY teardown must not block the Tauri invoke path
Rejected: Reuse the install chat for arbitrary shell commands | it does not provide a real interactive PTY
Rejected: Close the old PTY before adopting the new session | it keeps restart vulnerable to hung child shutdown
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep PTY teardown off the invoke path and preserve session handoff ordering when changing terminal lifecycle code
Tested: bunx vitest run src/__tests__/terminalPanel.test.tsx src/components/settings/TerminalPanel.restart.test.tsx; bun run lint; cargo check
Not-tested: End-to-end command echo inside the packaged desktop terminal still needs follow-up runtime verification
2026-04-22 18:06:29 +08:00
程序员阿江(Relakkes)
8c99efca20 Prevent destructive desktop actions from bypassing confirmation
The desktop settings and sidebar still had deletion flows that either used browser-native confirms or deleted immediately. This change consolidates destructive confirmations behind a shared dialog component, applies it to provider deletion, plugin uninstall, adapter unbind, and sidebar session deletion, and adds regression coverage so delete actions require an explicit second confirmation before mutating state.

Constraint: Other in-progress desktop work in the tree had to stay out of this commit
Constraint: Existing MCP and task confirmations needed to keep their current behavior
Rejected: Leave confirmations embedded per-page with browser dialogs | inconsistent UX and easy to regress
Rejected: Add confirmations only to provider deletion | leaves other destructive desktop flows unsafe
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Any new desktop delete, uninstall, or unbind action should use the shared ConfirmDialog instead of browser-native dialogs or one-click deletion
Tested: bun run test src/components/layout/Sidebar.test.tsx src/__tests__/generalSettings.test.tsx; bun run lint
Not-tested: Manual desktop click-through of every destructive action after this refactor
2026-04-22 17:30:59 +08:00
程序员阿江(Relakkes)
d8a44c0a54 Stop provider model selection from inheriting global Claude settings
The desktop provider flow was still mixing provider-managed state with
`~/.claude/settings.json`, which let unrelated tools leak fields like
`ANTHROPIC_REASONING_MODEL` and `model` back into the active provider path.
This change moves the provider JSON editor onto `~/.claude/cc-haha/settings.json`,
routes provider settings through dedicated `/api/providers/settings` endpoints,
and makes model reads/writes under an active provider use the managed cc-haha
settings instead of the global user settings file.

Constraint: Active provider model selection must be isolated from legacy ~/.claude/settings.json
Rejected: Keep merging provider JSON with settingsApi.getUser() | external tools can reintroduce unrelated model fields into the provider flow
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Any future provider-model UI or runtime change should read/write cc-haha managed settings first, not the global user settings file
Tested: bun test src/server/__tests__/provider-presets.test.ts src/server/__tests__/settings.test.ts; cd desktop && bun run lint
Not-tested: Manual desktop provider modal interaction after the cc-haha settings API switch
2026-04-22 17:19:12 +08:00
程序员阿江(Relakkes)
e0142b286b Keep built-in provider presets aligned with vendor-supported model IDs
The provider picker had two separate preset definitions and some defaults had
started to drift from the model IDs vendors document for Claude Code /
Anthropic-compatible usage. This change moves built-in presets to one
server-side JSON source, serves that source through the existing presets API,
and makes the desktop settings page consume the API instead of a duplicated
frontend constant. The preset defaults were then corrected against vendor docs
so the built-in values match documented model IDs and casing.

Constraint: Built-in provider defaults must match official vendor Claude Code or Anthropic docs
Rejected: Keep duplicated frontend and backend preset lists | values and casing drifted independently
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Update src/server/config/providerPresets.json and rerun provider-presets tests before changing built-in provider defaults again
Tested: bun test src/server/__tests__/provider-presets.test.ts; cd desktop && bun run lint
Not-tested: Manual desktop settings UI interaction after fetching presets from the API
2026-04-22 17:06:35 +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)
c4772a097e Make MCP reconnect progress visible in the detail view
The reconnect action could succeed, but the detail and edit views gave almost no page-level feedback beyond the button spinner. Mirror the reconnect lifecycle into the visible status surfaces so users can tell immediately that the request is in flight and whether it settled.

Constraint: Reconnect feedback must be visible without waiting for the list row to refresh
Rejected: Rely on toast only | too late and too easy to miss while staying on the detail page
Rejected: Add a separate transient banner | duplicates the existing status surfaces instead of updating them
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep reconnect state reflected in the page-level status badge and status field, not just the action button
Tested: cd desktop && bun run test -- mcpSettings.test.tsx; cd desktop && bun x tsc --noEmit --ignoreDeprecations 5.0
Not-tested: Manual desktop click-through against a live MCP reconnect
2026-04-22 15:53:27 +08:00
程序员阿江(Relakkes)
49e1367659 fix: avoid blocking MCP list on live health checks
Desktop MCP settings was synchronously probing every configured server from /api/mcp, which made the list page scale with connection latency and surface brittle behavior as installs accumulated more MCPs. Return lightweight snapshot rows from the list API, keep explicit status checks separate, and let the desktop UI refresh status in a constrained background lane while preserving project-aware server identity.

Constraint: MCP list must stay responsive even with many configured servers
Rejected: Probe all servers from the list view without limits | still fans out with server count and can overload slow installs
Rejected: Keep servers permanently unchecked until detail view | misses the desired loading feedback when the MCP page opens
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep /api/mcp as a configuration snapshot endpoint; do not reintroduce per-row live connect work on list load
Tested: bun test src/server/__tests__/mcp.test.ts; cd desktop && bun run test -- mcpSettings.test.tsx; cd desktop && bun x tsc --noEmit --ignoreDeprecations 5.0
Not-tested: Real desktop interaction against an environment with dozens of live MCP servers
2026-04-22 15:34:36 +08:00
程序员阿江(Relakkes)
bef9596ed5 Keep all assistant-side transcript content on one shared content rail
The desktop transcript had drifted into multiple competing left edges.
Assistant bubbles, thinking rows, tool cards, permissions, and standalone
results were using different offsets, which made the timeline feel visually
broken even when the underlying data was correct.

This change removes the ad hoc assistant-side indentation and makes the
assistant output lane follow the same content rail as the composer. The
assistant message component still distinguishes short bubble replies from
markdown-heavy document replies, but both now sit on the same shared left
alignment. Supporting chat blocks were updated to use that same rail so the
whole transcript reads as one coherent column.

Constraint: Assistant transcript content must align with the composer rail, not with local per-block offsets
Rejected: Keep tool/thinking blocks on a separate inset lane | creates multiple left edges and keeps the transcript visually inconsistent
Rejected: Fix only final assistant replies | leaves the rest of the assistant-side timeline misaligned
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Treat the composer rail as the canonical left edge for all assistant-side transcript blocks unless the entire transcript layout is redesigned together
Tested: bun run test src/components/chat/MessageList.test.tsx --run; bun run lint; bun run build
Not-tested: Real Tauri runtime screenshot against a live session after this unified alignment change
2026-04-22 15:30:05 +08:00
程序员阿江(Relakkes)
70fb6c429e Keep desktop transcript and plugin controls readable after layout regressions
Two desktop surfaces regressed in ways that made the app harder to read and operate.
The plugin header compressed summary cards and action buttons too early for the available width,
and the rewind/copied affordances in chat were sharing the same horizontal lane as message bubbles,
which visually broke the expected "user on the right, assistant on the left" transcript structure.

This commit keeps both fixes narrow: the plugin header now delays its split layout and lets summary
cards and controls reflow responsively, while chat message actions live inside each message column so
interaction affordances no longer distort the bubble alignment.

Constraint: Desktop settings and transcript layouts must remain readable in narrower window widths
Rejected: Keep message actions inline with the bubble row | action buttons keep stretching the message lane and blur role alignment
Rejected: Hide rewind and copy entirely until a larger redesign | removes the control instead of fixing the regression
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep transcript actions inside the message column unless a future redesign also redefines bubble alignment rules
Tested: bun run test src/__tests__/pluginsSettings.test.tsx --run; bun run test src/components/chat/MessageList.test.tsx --run; bun run lint; bun run build; agent-browser verification against local mock desktop session
Not-tested: Real Tauri runtime screenshot on a live backend session after these layout changes
2026-04-22 14:55:40 +08:00
Relakkes Yang
0f533efb8d fix: merge split assistant text blocks in desktop chat 2026-04-22 14:32:23 +08:00
程序员阿江(Relakkes)
de736c49f7 Unify plugin capabilities with the desktop management views
Desktop plugin details now route into the shared Skills, Agents, and MCP management surfaces instead of maintaining separate read-only drilldowns. This also extends the desktop/server skill aggregation so plugin-provided skills appear in the shared list, groups MCP entries by source, and preserves detail-view back navigation based on where the user entered the page.

The implementation keeps plugin detail as the high-level capability hub while pushing real inspection into the existing management pages. Disabled plugins no longer expose false navigation paths into shared views, and the agent-browser regression script was expanded to exercise the new end-to-end flows.

Constraint: Shared Agents data only includes enabled plugin agents, so disabled plugins cannot deep-link into agent detail
Rejected: Keep duplicating full Skills/Agents/MCP detail inside Plugin detail | creates divergent UI flows and stale data paths
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: If a detail view can be opened from multiple entry points, keep the return target in store state rather than hardcoding a single back destination
Tested: desktop vitest for plugins/skills/agents/mcp; desktop tsc --noEmit; desktop vite build; server skills API test; agent-browser web regression on plugin->skill/mcp and plugin->agent back navigation
Not-tested: packaged desktop app regression after rebuilding the Tauri bundle
2026-04-22 12:31:57 +08:00
程序员阿江(Relakkes)
28f36da0fd Reduce extension setup friction inside desktop settings
The desktop app already had solid session streaming, permission, and tool-rendering flows, but extension setup still forced users into manual forms or external shell work. This change adds an Install Center in Settings that reuses the session chat pipeline for natural-language installs, adds installer-specific guidance for plugin and skill URLs, and includes an agent-browser E2E script for real UI validation.

Constraint: Must reuse the existing session/chat execution path instead of introducing a second install runtime
Constraint: Plugin installs need real CLI commands while skill installs may come from published install commands on third-party pages
Rejected: Separate terminal-only install surface | duplicates session UX and weakens permission/tool visibility
Rejected: Pure form-based installer expansion | too much friction for plugin, MCP, and skill onboarding
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep installer prompts aligned with the actual CLI install surfaces; do not let the installer fall back to slash-command syntax inside Bash
Tested: cd desktop && bun run lint
Tested: Real UI automation via agent-browser for Telegram plugin install flow through Settings > Install, verified Plugins page shows telegram enabled
Tested: Real UI automation via agent-browser for ui-ux-pro-max skill install flow through Settings > Install, verified ~/.claude/skills/ui-ux-pro-max and Skills page visibility
Not-tested: Full e2e-install-center-agent-browser.sh script as a single uninterrupted green run after the latest stability tweaks
2026-04-22 01:06:57 +08:00
程序员阿江(Relakkes)
6c02904e58 Keep slash-command entry surfaces aligned with MCP desktop management
Merged the desktop MCP management work into local main and retained
existing plugin settings affordances while resolving router and settings-tab
conflicts. The resulting flow keeps MCP settings global-only for speed and
uses slash-command cards to route users into concrete MCP or skill targets.

Constraint: local main already had plugin settings and API routes that had to remain available
Rejected: Favor the worktree version wholesale during merge | would have dropped local plugin tab and router support on main
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep slash-command entry flows and settings tabs additive during future merges; do not collapse MCP and plugin navigation into one another
Tested: Conflict resolution review during merge; source commit 66edded validated with bun test src/server/__tests__/mcp.test.ts; cd desktop && bun run test -- pages.test.tsx mcpSettings.test.tsx; cd desktop && bun x tsc --noEmit --ignoreDeprecations 5.0
Not-tested: Re-running full desktop/manual verification from the merged main worktree after merge completion
Related: 66edded
2026-04-21 23:29:11 +08:00
程序员阿江(Relakkes)
66edded2d7 Make desktop MCP management and slash entry points directly operable
Desktop MCP management now has a working server API, a global-only settings surface,
and slash-command entry points that surface MCP and skills from the composer before
routing users into the right settings view.

Constraint: Project-scoped MCP browsing in settings was too slow and noisy because it scanned multiple workdirs
Rejected: Keep project MCP aggregation on the settings homepage | duplicated entries and poor responsiveness
Rejected: Route /mcp directly on Enter without an intermediate card | removed the user's ability to choose a specific target first
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep settings focused on global MCP; add project-scoped MCP affordances in the chat-context slash surfaces instead of re-expanding the settings homepage
Tested: bun test src/server/__tests__/mcp.test.ts; cd desktop && bun run test -- pages.test.tsx mcpSettings.test.tsx; cd desktop && bun x tsc --noEmit --ignoreDeprecations 5.0
Not-tested: Manual IAB verification after this final commit/merge cycle
2026-04-21 23:28:06 +08:00
程序员阿江(Relakkes)
89911bd6bf Merge commit '375d587' 2026-04-21 23:21:25 +08:00
程序员阿江(Relakkes)
375d587ed1 Expose desktop plugin management through first-class APIs
The desktop app could read plugin-produced skills and agents, but it had no
plugin control plane of its own. This adds a dedicated Settings tab backed by
server-side plugin APIs so installed plugins can be inspected, enabled,
disabled, updated, reloaded, and uninstalled from the WebUI.

The implementation also teaches browser-based desktop dev sessions to honor a
custom backend URL, which made it possible to run isolated worktree ports for
real UI automation. During verification, the long-lived desktop server kept a
stale installed-plugin snapshot after external CLI mutations, so cache clearing
now resets that session-level plugin installation state as well.

Constraint: Desktop WebUI needed an isolated backend URL instead of the hard-coded 127.0.0.1:3456 fallback
Constraint: Reuse existing plugin operations and loaders instead of rebuilding plugin lifecycle logic in the desktop layer
Rejected: Fold plugin management into Skills or Adapters | mixed unrelated lifecycles and hid plugin-specific health/actions
Rejected: Expose only read-only plugin status in desktop | did not satisfy enable-disable-reload-uninstall verification needs
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep desktop plugin actions routed through the shared plugin operation layer and clear installed-plugin session caches when plugin state changes externally
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test -- src/__tests__/pluginsSettings.test.tsx
Tested: bun test src/server/__tests__/plugins.test.ts src/server/__tests__/skills.test.ts
Tested: Browser automation against isolated ports 15120/38456 covering discord plugin list/detail/disable/apply/enable/update/uninstall flows
Not-tested: Full desktop session runtime parity with CLI /reload-plugins AppState refresh beyond the new desktop API path
2026-04-21 23:21:16 +08:00
程序员阿江(Relakkes)
044e9b6cc8 Make desktop rewind restore both transcript state and file checkpoints
The desktop client already had a conversation-level rewind UI concept on the
CLI side, but the web/desktop surface lacked the protocol, session trimming,
and file checkpoint restore path needed to make rewind trustworthy. This change
adds a desktop-specific rewind API, wires the message-level UI affordance and
confirmation modal, enables SDK file checkpointing for desktop sessions, and
covers the restore path with service tests plus a real agent-browser workflow.

Constraint: Desktop sessions run the CLI in SDK/print mode, so file checkpointing had to be enabled explicitly for that path
Constraint: main branch is checked out in a separate worktree, so merge-back must happen from the primary worktree after commit
Rejected: UI-only rewind that only trims local state | would leave persisted transcript and disk state inconsistent after refresh
Rejected: Reuse getLastSessionLog as the sole snapshot source | active rewind must read file-history metadata directly from the session file
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep desktop rewind keyed to persisted user-message order unless the UI model starts carrying stable transcript UUIDs end-to-end
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/sessions.test.ts; desktop MessageList vitest; desktop tsc no-emit; live agent-browser E2E on isolated ports with file edit then rewind
Not-tested: Browser E2E matrix for multi-file and second-edit scenarios is still covered at service-test level rather than full UI level
2026-04-21 21:34:41 +08:00
程序员阿江(Relakkes)
86cd2b8d18 Keep desktop UI icon previews aligned with the packaged app icon
The desktop UI was still rendering the old JPG preview asset, so the empty
state, sidebar, and settings pages continued to show the legacy glow-backed
image even after the packaged app icon was corrected. This switches those UI
surfaces to a PNG generated from the current canonical app icon source so the
in-app preview matches the shipped icon treatment.

Constraint: The desktop UI still referenced a legacy JPG asset with the removed outer glow background
Constraint: There are unrelated staged changes in the worktree, so this commit must stay file-scoped
Rejected: Leave the UI on the JPG asset | keeps showing a stale icon treatment after the packaging fix
Rejected: Revert the packaged icon to match the old JPG | would reintroduce the original square-background problem
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep desktop/public/app-icon.png in sync with desktop/src-tauri/app-icon.svg when the app icon changes
Tested: desktop bun run lint; desktop bun run test
Not-tested: Manual visual pass in the running desktop app after rebuilding the frontend bundle
2026-04-21 18:38:54 +08:00
程序员阿江(Relakkes)
c05eeff644 Restore tab close affordance after drag migration
The pointer-drag rewrite left the tab close control without its hover trigger,
so tabs could still be closed logically but no longer exposed the affordance.
This restores the hover group, trims the close icon to a lighter visual weight,
and adds a regression test to keep close-click behavior from colliding with drag.

Constraint: Tab close must remain compatible with the custom pointer-drag reorder flow
Rejected: Reintroduce a larger hoverable close button | made the tab chrome look visually heavy
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the close control visually subordinate to the tab label and verify drag-click interactions before changing tab hit areas
Tested: cd desktop && bun run test -- TabBar; cd desktop && bun run lint
Not-tested: Full desktop app manual visual QA in Tauri runtime
2026-04-21 18:38:31 +08:00
程序员阿江(Relakkes)
5377eb596f Keep desktop session history and reconnect recovery trustworthy
Desktop session interruptions were leaving two different classes of stale UI
artifacts behind: reconnects could silently lose in-flight output, and history
reloads could replay synthetic interruption or internal command breadcrumbs as
if they were user-facing transcript content. This change rebinds active session
output to the latest client websocket on reconnect, preserves queued outbound
messages across transient disconnects, and filters synthetic transcript entries
before they reach the desktop history API so reloads reconstruct only the
messages users should actually see.

Constraint: Desktop transcript history is shared with CLI JSONL files and must stay compatible with persisted message shapes
Rejected: Hide these artifacts only in React renderers | other transcript consumers would still receive polluted history
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep transcript filtering aligned with real synthetic/internal message shapes before adding new hidden message types
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts
Tested: cd /Users/nanmi/.codex/worktrees/e7ac/claude-code-haha/desktop && bun run test -- websocket.test.ts
Tested: cd /Users/nanmi/.codex/worktrees/e7ac/claude-code-haha/desktop && bun run lint
Not-tested: Manual browser verification of the refreshed session transcript after interrupt on this exact session
2026-04-21 17:55:15 +08:00
程序员阿江(Relakkes)
b7aefc3d01 Make desktop updates less noisy and more truthful
The desktop updater now renders release notes as markdown, avoids fake 0%
progress when the server omits Content-Length, and remembers when the user
has dismissed a specific release prompt so reopening the app does not nag
again for the same version.

Constraint: Existing 0.1.4 clients can receive updater events without total size metadata and users still need a manual update path in About
Rejected: Keep repeating the prompt on every launch | creates avoidable noise after an explicit later decision
Rejected: Global dismiss flag for all future releases | would hide newer versions that should prompt again
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep prompt suppression keyed to availableVersion only; About page visibility and manual update actions must remain available
Tested: bun run test src/stores/updateStore.test.ts src/components/shared/UpdateChecker.test.tsx src/__tests__/generalSettings.test.tsx; bun run lint; manual local updater validation from 0.1.4 to 0.1.5 on /Applications and an extracted v0.1.4 release bundle
Not-tested: Signed and notarized macOS distribution behavior outside this local machine
2026-04-21 01:50:29 +08:00
程序员阿江(Relakkes)
16d716e773 fix: keep completed task lists from leaking into the next turn
Completed desktop task bars were only being dismissed locally, which let the
persisted task list resurface on refresh or bleed into the next user turn.
This wires the existing server-side reset path into the desktop stores and
session flow so a finished task cycle is summarized once, cleared locally,
and removed remotely before the next round starts.

Constraint: Existing task persistence already lives behind the server task-list API and must stay compatible with persisted JSON task files
Rejected: Only hide the completed task bar in UI state | left stale persisted tasks behind and reintroduced them on reload
Rejected: Clear desktop state without a task summary | dropped useful completion context from the chat transcript
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep desktop task dismissal and task-list persistence behavior aligned; do not reintroduce local-only clearing without covering reload and next-turn flows
Tested: `cd desktop && bun run lint`
Tested: `cd desktop && bun run test src/stores/cliTaskStore.test.ts src/stores/chatStore.test.ts src/components/chat/SessionTaskBar.test.tsx src/components/chat/ComputerUsePermissionModal.test.tsx`
Tested: `bun test src/server/__tests__/e2e/business-flow.test.ts --test-name-pattern "Task Lists API"`
Not-tested: Full `bun test src/server/__tests__/e2e/business-flow.test.ts` suite still has unrelated pre-existing failures in Models and Sessions sections
2026-04-21 00:46:29 +08:00
程序员阿江(Relakkes)
7651b24a50 Reduce desktop first-token latency in sdk-url sessions
Desktop-managed sessions were blocking the first visible token on slow or failing
regular MCP connections, which made the UI feel much slower than direct bin runs.
This keeps partial assistant streaming enabled for desktop sessions and moves
regular MCP connection work off the critical path only for sdk-url startup.

Constraint: Desktop sdk-url sessions must preserve chat responsiveness even when local MCP endpoints fail or hang
Rejected: Leave MCP startup fully blocking in sdk-url mode | first visible token stayed several seconds behind direct CLI runs
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep blocking MCP startup for plain -p sessions unless you re-measure first-turn latency and tool availability tradeoffs
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/conversations.test.ts; same-prompt timing comparison for direct bin vs sdk-url session path
Not-tested: Immediate first-turn availability of slow regular MCP tools in desktop sdk-url sessions
2026-04-21 00:41:02 +08:00
程序员阿江(Relakkes)
e78b973e8c Restore sidebar project filter metadata and dropdown layering
The sidebar project filter had regressed to lossy projectPath strings, so the
UI showed broken folder-name fragments and the dropdown could not match the
richer project chooser used in session creation. This switches the sidebar back
to recent-project metadata, renders the filter menu through a portal, and keeps
session filtering behavior unchanged while restoring readable labels and paths.

Constraint: Sidebar filtering still needs to target existing session projectPath values without migrating store shape
Constraint: The desktop sidebar dropdown must escape local stacking and overflow constraints to render reliably
Rejected: Keep deriving labels from sanitized projectPath strings | lost repo names and full paths, causing misleading project choices
Rejected: Rebuild sessionStore around recent-project objects in this fix | broader state migration than needed for the regression
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep sidebar project displays aligned with /api/sessions/recent-projects metadata instead of reintroducing string-splitting fallbacks
Tested: cd desktop && bunx vitest run src/components/layout/ProjectFilter.test.tsx src/components/layout/Sidebar.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Manual desktop visual pass of the repaired dropdown in a live Tauri window
2026-04-20 23:45:53 +08:00
程序员阿江(Relakkes)
0f7494006f Prevent misleading empty @-file menus when filesystem access fails
Desktop @-mentions were collapsing filesystem browse failures into an empty
state, which made /private/tmp aliases on macOS look like real empty
directories. The server now treats /private/tmp as the same temp root as
/tmp on Darwin, and the menu surfaces explicit access/load errors instead of
pretending the directory has no files.

Constraint: Desktop browse/file APIs must stay restricted to approved roots
Constraint: Native macOS pickers and realpath() may canonicalize /tmp to /private/tmp
Rejected: Expanding filesystem access to arbitrary system paths | too broad for this targeted fix
Rejected: Keeping silent empty-state fallback | hides permission and path bugs from users
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep filesystem error states visible in the composer; do not collapse API failures back into empty-directory messaging
Tested: bun test src/server/__tests__/filesystem.test.ts
Tested: cd desktop && bun run test -- FileSearchMenu.test.tsx
Tested: cd desktop && bun run lint
Not-tested: Manual desktop packaging or end-to-end Tauri app run after this patch
2026-04-20 23:07:15 +08:00
程序员阿江(Relakkes)
0d3933c2c9 Keep desktop AskUserQuestion flows from stalling in plan mode
Desktop chat was rendering AskUserQuestion twice: once as an inline question card and again as a generic permission request. That split also dropped the structured answers on the floor because the websocket permission_response shape only carried allow/deny state.

This change keeps AskUserQuestion on the permission pipeline end-to-end. The desktop websocket contract now carries toolUseId and updatedInput, AskUserQuestion submits answers through permission_response, and the generic permission card is suppressed for that tool so the user sees a single question flow.

Constraint: AskUserQuestion answers must round-trip through updatedInput.answers for the CLI tool contract to complete
Rejected: Leave AskUserQuestion as a plain chat reply in desktop | the tool never receives structured answers and the pending approval UI remains stuck
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep AskUserQuestion bound to the permission-response path unless the desktop protocol grows a separate structured elicitation channel
Tested: desktop lint; vitest src/components/chat/AskUserQuestion.test.tsx src/stores/chatStore.test.ts; bun test src/server/__tests__/conversations.test.ts
Not-tested: Manual desktop click-through against a live plan-mode session after bundling
2026-04-20 23:07:15 +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)
febd842557 Keep desktop WebFetch usable on third-party providers
Desktop sessions were failing before the actual fetch because Anthropic's domain preflight can be unreachable on restricted networks, and the next runtime path was missing turndown for HTML-to-Markdown conversion.

This change defaults desktop sessions to skip the preflight unless the user explicitly overrides it, exposes that behavior as a desktop General setting, seeds new settings JSON with the desktop-safe default, and adds regression coverage for both the runtime default and the UI toggle. It also adds the missing turndown dependency so successful fetches can continue through HTML reduction instead of failing at module resolution.

Constraint: Desktop must keep an escape hatch for users who want upstream preflight restored explicitly
Rejected: Force skipWebFetchPreflight globally for every session | would silently change CLI and non-desktop behavior
Rejected: UI-only toggle without runtime default | existing desktop users would still fail until they manually opened settings
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep desktop-specific WebFetch behavior scoped to desktop session detection and explicit user settings; do not broaden it to general CLI flows without separate validation
Tested: bun test src/tools/WebFetchTool/utils.test.ts; cd desktop && bun run lint; cd desktop && bunx vitest run src/__tests__/generalSettings.test.tsx; runtime import verification for turndown via node
Not-tested: End-to-end desktop packaging smoke test against a freshly built DMG/app bundle
2026-04-20 20:53:03 +08:00
程序员阿江(Relakkes)
df8db2c1ff Keep mid-turn follow-up tool activity aligned with the latest user message
The desktop transcript renderer was continuing to inline later nested tool calls under an older parent card even after a new user message had been submitted mid-session. That made the session timeline diverge from CLI behavior, where queued user input becomes the boundary for the next tool round.

This change rebuilds the render model around visible message boundaries so nested tool calls only stay attached to a parent within the same contiguous segment. A regression test now covers the interleaved user-message case.

Constraint: Preserve existing grouped tool rendering for contiguous parent-child tool activity
Rejected: Rework the websocket/session pipeline to synthesize extra transcript events | the bug was in render ordering, not transport semantics
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If mid-turn follow-up prompts change again, validate both render ordering and nested child attachment rules together
Tested: bun run test --run src/components/chat/MessageList.test.tsx; bun run lint
Not-tested: Full desktop app manual session playback against a live running tool turn
2026-04-20 20:42:24 +08:00
程序员阿江(Relakkes)
5f86585c34 Preserve tab reordering without losing title-bar drag fallback
The recent macOS title-bar drag fix marked the entire session tab strip as a
native drag region. That restored window movement in the overlay title area,
but it also intercepted the tab component's own HTML drag events and regressed
manual tab reordering. This narrows the native drag surface to a small gutter
beside the tabs while keeping the explicit empty-space startDragging fallback,
and adds a focused regression test for drag-to-reorder.

Constraint: Must preserve window dragging from non-tab title-bar space on macOS overlay windows
Rejected: Keep the whole tab bar as a drag region | conflicts with tab-level drag-and-drop reordering
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Do not reapply data-tauri-drag-region to the full tab strip unless tab reordering is redesigned around a different drag mechanism
Tested: bun run test -- src/components/layout/TabBar.test.tsx; bun run lint; bun run build
Not-tested: Manual desktop runtime verification after this commit
2026-04-20 20:40:39 +08:00
程序员阿江(Relakkes)
eaa4a8435a Keep CLI task state aligned with the active session
The desktop task bar used a single global task store, but session switches
could leave it pointed at the previous conversation. Re-entering an already
connected session skipped task refresh entirely, and changing task list IDs did
not clear stale tasks before the next fetch resolved.

This change refreshes CLI tasks on every session activation, clears stale task
state immediately when the tracked session changes, and locks that behavior
with regression tests around reconnect and cross-session task isolation.

Constraint: The current desktop task bar architecture uses one shared CLI task store across sessions
Rejected: Per-session task store refactor | too broad for a targeted bug fix
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: If tasks become session-scoped later, re-evaluate the eager refresh in connectToSession before removing it
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test src/stores/chatStore.test.ts src/stores/cliTaskStore.test.ts src/pages/ActiveSession.test.tsx
Not-tested: Manual desktop UI verification against a packaged app build
2026-04-20 20:38:21 +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
e20ccf8093
Merge pull request #99 from NanmiCoder/fix/windows-computer-use-20260420
Fix/windows computer use 20260420
2026-04-20 18:02:30 +08:00
Relakkes Yang
4b513271ee fix: improve windows computer use and desktop rendering 2026-04-20 17:59:42 +08:00