14 Commits

Author SHA1 Message Date
程序员阿江(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)
f497a08453 Clear stale ChatGPT OAuth fallback links
Manual authorization links now behave as transient recovery state: a fresh login clears older URLs, a successful copy clears the exposed URL before polling, and logged-in status defensively drops any stale manual link.

Constraint: OAuth authorization URLs should not survive beyond the active recovery action.

Rejected: Keep the copy button after a successful copy | that leaves an expired authorization URL visible after later auth state changes.

Confidence: high

Scope-risk: narrow

Tested: cd desktop && bun run test -- src/components/settings/ChatGPTOfficialLogin.test.tsx src/stores/hahaOpenAIOAuthStore.test.ts

Tested: cd desktop && bun run test -- src/components/settings/ChatGPTOfficialLogin.test.tsx src/stores/hahaOpenAIOAuthStore.test.ts src/__tests__/generalSettings.test.tsx --testNamePattern "ChatGPT|OpenAI OAuth|Providers tab|ChatGPTOfficialLogin|hahaOpenAIOAuthStore"

Tested: cd desktop && bun run lint

Tested: git diff --check
2026-05-19 00:05:59 +08:00
程序员阿江(Relakkes)
d2ff9d0c00 Preserve ChatGPT OAuth fallback authorization links
When the desktop shell cannot open a browser, the ChatGPT OAuth component keeps the transient authorization URL available for copy and starts polling after that explicit fallback action.

Constraint: OAuth authorization URLs are transient UI state and must not be persisted.

Rejected: Tell users to find the URL in server logs | the desktop flow does not expose those logs as the recovery surface.

Confidence: high

Scope-risk: narrow

Tested: cd desktop && bun run test -- src/components/settings/ChatGPTOfficialLogin.test.tsx src/stores/hahaOpenAIOAuthStore.test.ts

Tested: cd desktop && bun run test -- src/components/settings/ChatGPTOfficialLogin.test.tsx src/stores/hahaOpenAIOAuthStore.test.ts src/__tests__/generalSettings.test.tsx --testNamePattern "ChatGPT|OpenAI OAuth|Providers tab|ChatGPTOfficialLogin|hahaOpenAIOAuthStore"

Tested: cd desktop && bun run lint

Tested: git diff --check
2026-05-19 00:04:11 +08:00
程序员阿江(Relakkes)
83ee4c09ec Add desktop ChatGPT OAuth controls
The desktop app now has a dedicated OpenAI OAuth API client and store mirroring the existing Claude Official flow. The component uses the existing browser-open plus polling pattern and never exposes token material to the UI.

Constraint: OAuth status responses must not return token bodies

Rejected: Reuse Claude OAuth store | the status shape and endpoint differ

Confidence: high

Scope-risk: narrow

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

Tested: git diff --check
2026-05-18 23:53:11 +08:00
Relakkes Yang
928be2a4ff fix(desktop): remove install center 2026-04-24 23:05:45 +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)
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)
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)
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)
d83efc1b04 Prevent desktop OAuth sessions from drifting out of sync
Desktop auth was reporting stale local token files as logged in, could inherit a parent OAuth token after logout, and kept polling even when browser launch failed. This change validates stored tokens through the refresh path, clears inherited OAuth env before spawning the CLI, fetches subscription metadata on initial login, and moves polling start until after the browser opens. Regression tests cover the server and desktop store paths.

Constraint: Desktop CLI must bypass macOS Keychain by injecting env OAuth when available
Rejected: Keep status endpoint file-based only | reports expired sessions as logged in
Confidence: high
Scope-risk: moderate
Directive: Official desktop auth state must be derived from ensureFreshTokens rather than oauth.json presence alone
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/haha-oauth-service.test.ts src/server/__tests__/haha-oauth-api.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test
Not-tested: Manual end-to-end desktop OAuth flow against the live provider
2026-04-18 01:45:18 +08:00
程序员阿江(Relakkes)
8ae68c1805 fix(desktop): ClaudeOfficialLogin — i18n、错误反馈、冗余清理
Code review follow-ups on ae5437a:
- I1: 使用 useTranslation 替代硬编码中文, 新增 settings.claudeOfficialLogin.* 双语 key
- I2: shellOpen 失败时 console.error + 写入 store.error, 不再静默吞
- M1: disabled={isLoading || false} → disabled={isLoading}
- M2: onClick={() => logout()} → onClick={logout}
- M3: 首次 fetchStatus 失败时显示 error 而非永远 "加载中…"

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

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

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 20:28:29 +08:00