260 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
7df77ac6e1 Merge provider thinking controls into local main
The detached worktree carried the verified desktop Thinking fixes, while local main already had one newer memory-path commit. This merge brings the provider/runtime Thinking behavior into main without rewriting the existing main history.

Constraint: Local main is the checked-out integration branch and was ahead of the worktree base
Rejected: Rebase the detached worktree onto main | unnecessary history rewrite for a local integration request
Rejected: Fast-forward main | impossible because main already had newer local commits
Confidence: high
Scope-risk: moderate
Directive: Keep c866adc9 as the feature commit for detailed implementation context
Tested: bun test src/server/__tests__/ws-memory-events.test.ts
Tested: bun run verify before integration on the feature commit
Not-tested: Full verify after the merge commit; merge was conflict-free except automatic conversationService integration
2026-05-15 19:35:49 +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)
02f23d6e3b Keep desktop memory paths aligned with runtime
Desktop memory settings already resolves project memory through the current sanitized project directory, while spawned CLI sessions could compute an older path variant and fail to read indexed memory files. Pin the child runtime to the same memory directory and let memory preview links open related markdown files directly from the rendered panel.

Constraint: Existing memory files may already live under both legacy underscore and current hyphenated project directories.
Rejected: Symlink or merge memory directories | it could mix stale legacy memory entries into the active project index.
Confidence: high
Scope-risk: moderate
Directive: Keep Settings memory discovery and spawned CLI memory context on the same project identity before changing either sanitizer.
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/memory.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run test -- MemorySettings MarkdownRenderer
Tested: cd desktop && bun run build
Tested: Browser smoke on local Vite/server for memory preview link navigation
Not-tested: bun run check:desktop still has pre-existing vite-config color-mix guard failure in desktop/src/theme/globals.css
2026-05-15 19:34:16 +08:00
程序员阿江(Relakkes)
4e969475f2 Improve session project sidebar controls
The session sidebar already uses project grouping, so the change adds header-level project actions instead of replacing project row controls. Sorting and organization choices are persisted through the existing desktop UI preferences file and mirrored into local cache for startup continuity.

Constraint: Keep the existing project tree, drag ordering, pinning, hiding, and Finder project-row actions intact.

Rejected: Replacing project row actions with the header menu | row-level Finder and per-project session actions are still useful and already covered by tests.

Confidence: high

Scope-risk: moderate

Directive: Do not store sidebar organization in global Claude settings; keep it under cc-haha desktop-ui preferences.

Tested: cd desktop && bun run test -- src/components/layout/Sidebar.test.tsx

Tested: bun test src/server/__tests__/desktop-ui-preferences.test.ts

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build
2026-05-15 16:49:18 +08:00
程序员阿江(Relakkes)
5d9d1b009e Persist sidebar project preferences across desktop and H5
Sidebar project ordering, pinning, and hidden-project state must survive
browser access to the same local server, so the UI now stores these
preferences under the cc-haha config directory and keeps localStorage as
a migration/cache fallback.

Constraint: Browser and H5 localStorage is isolated from the Tauri WebView
Rejected: Keep sidebar project preferences only in localStorage | browser sessions would not share state
Rejected: Reuse cc-haha/settings.json | provider and H5 access settings should stay separate
Confidence: high
Scope-risk: moderate
Directive: Keep sidebar hide/remove semantics non-destructive; do not delete transcript files for project removal
Tested: cd desktop && bun run test -- src/components/layout/Sidebar.test.tsx --run
Tested: cd desktop && bun run lint
Tested: bun test src/server/__tests__/desktop-ui-preferences.test.ts
Tested: bun run check:persistence-upgrade
Tested: bun run check:server
2026-05-15 16:30:39 +08:00
程序员阿江(Relakkes)
0e78439f9d Group desktop sessions by project root
The desktop sidebar needed a project-first navigation model that keeps worktree sessions attached to their source project instead of scattering them as separate paths. The UI now renders sessions under project groups with project-level actions and persisted ordering, while the server exposes a logical project root for worktree transcripts.

Constraint: Existing memory directory tree work must remain separate from the session sidebar behavior.

Rejected: Group by raw transcript projectPath | worktree paths fragment the same repository into multiple sidebar projects.

Confidence: high

Scope-risk: moderate

Directive: Keep future sidebar grouping keyed by projectRoot before projectPath so isolated worktrees stay under their source repository.

Tested: cd desktop && bun run test -- src/components/layout/Sidebar.test.tsx

Tested: bun test src/server/__tests__/sessions.test.ts

Tested: git diff --check
2026-05-15 16:01:36 +08:00
程序员阿江(Relakkes)
e292d83282 fix: Prevent cached settings writes from resetting desktop preferences
Desktop settings writes update settings.json through SettingsService, while plugin
state writes use the shared CLI settings cache. Reset the shared cache after a
successful atomic SettingsService write so later plugin updates merge against the
fresh file instead of an older in-memory snapshot.

Constraint: Desktop general settings and plugin state share ~/.claude/settings.json but use different write paths
Rejected: Move plugin writes onto SettingsService | broader API change than needed for this regression
Confidence: high
Scope-risk: narrow
Directive: Keep cache invalidation aligned across all settings.json write paths
Tested: bun test src/server/__tests__/settings.test.ts -t "cached CLI settings"
Tested: bun test src/server/__tests__/settings.test.ts src/server/__tests__/plugins.test.ts
Tested: cd desktop && bun run test -- generalSettings settingsStore pluginsSettings
Tested: bun run check:server
Tested: git diff --check
Not-tested: Full bun run verify still fails on unrelated dirty desktop changed-line coverage and CSS color-mix gate
2026-05-15 10:54:40 +08:00
程序员阿江(Relakkes)
45ec701124 Bring responsive desktop sessions and thinking controls onto main
This merge carries the worktree fix into the local main branch so long multi-session desktop usage keeps rendering cost bounded while DeepSeek follows the shared General Settings Thinking toggle. It preserves running-session behavior and keeps legacy DeepSeek managed env from pinning thinking off after upgrade.

Constraint: User requested the worktree result merged into local main without pushing.
Confidence: high
Scope-risk: moderate
Directive: Keep DeepSeek controlled by the global Thinking setting; do not restore provider-specific disabled-thinking defaults without both toggle-state tests.
Tested: bun test src/server/__tests__/conversations.test.ts -t "global Thinking setting control DeepSeek"
Tested: bun test src/server/__tests__/persistence-upgrade.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/title-service.test.ts src/utils/__tests__/thinking.test.ts src/utils/__tests__/providerManagedEnvCompat.test.ts
Tested: cd desktop && bun run test -- MessageList.test.tsx ContextUsageIndicator.test.tsx
Tested: bun run check:server
2026-05-14 22:42:30 +08:00
程序员阿江(Relakkes)
611f09a1a7 Keep long desktop sessions responsive while honoring thinking controls
Virtualized chat rendering keeps inactive long-running sessions cheap without disconnecting their CLI process, while DeepSeek now relies on the shared Thinking setting instead of a provider-specific disabled-thinking override. Existing legacy DeepSeek managed env is normalized so old local settings do not keep suppressing reasoning output after upgrade.

Constraint: Multiple desktop tabs must keep live sessions running and remain quick to switch without reconnecting.
Rejected: Pause or disconnect hidden sessions | would delay tab switching and interrupt streaming/tool state visibility.
Rejected: Keep DeepSeek disabled-thinking preset | conflicts with the General Settings Thinking control.
Confidence: high
Scope-risk: moderate
Directive: Do not reintroduce provider-specific disabled-thinking defaults for DeepSeek without testing both General Settings toggle states.
Tested: bun test src/server/__tests__/conversations.test.ts -t "global Thinking setting control DeepSeek"
Tested: bun test src/server/__tests__/persistence-upgrade.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/title-service.test.ts src/utils/__tests__/thinking.test.ts src/utils/__tests__/providerManagedEnvCompat.test.ts
Tested: cd desktop && bun run test -- MessageList.test.tsx ContextUsageIndicator.test.tsx
Tested: bun run check:server
2026-05-14 22:42:01 +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)
6b77120515 Align settings resource discovery with runtime
Settings reported false negatives for resources the runtime could load, because the API paths used narrower discovery rules than the execution path. This keeps the Settings surfaces read-only where appropriate while matching runtime visibility for linked skills, version-constrained plugins, and merged MCP sources.

Constraint: Settings MCP list must not actively connect to servers while loading.
Rejected: Add UI-specific fallbacks | would preserve drift between Settings and runtime loaders
Confidence: high
Scope-risk: moderate
Directive: Keep Settings resource listing backed by the same shared loader semantics as runtime discovery.
Tested: bun test src/server/__tests__/skills.test.ts
Tested: bun test src/server/__tests__/plugins.test.ts
Tested: bun test src/server/__tests__/mcp.test.ts
Tested: bun run check:server
Tested: bun run check:coverage
Tested: bun run verify
Not-tested: Live external MCP connector account state
2026-05-13 22:11:24 +08:00
程序员阿江(Relakkes)
f455065997 Merge desktop memory surface into main
This brings the desktop memory worktree onto local main after main advanced with opener, IM, zoom, and autonomous goal work. The conflict resolution keeps both the selected-chat reference imports and memory event settings entrypoint in MessageList, and keeps both open-targets and memory API routes in the server router.

Constraint: main and feat/desktop-memory-surface diverged across desktop chat and server routing.
Constraint: desktop Vitest runs src-tauri tests under Vitest, so the Tauri config test cannot import bun:test.
Rejected: Fast-forward merge | main carried newer local commits not present on the memory branch.
Confidence: high
Scope-risk: moderate
Directive: Keep chat selection references, memory cards, open-target routes, and memory routes together when touching these files.
Tested: bun run check:desktop
Tested: bun run check:server
2026-05-13 21:05:54 +08:00
程序员阿江(Relakkes)
966070d496 Land autonomous goal loop support on main
The /goal slash command was developed and verified in an isolated worktree, while local main has advanced with unrelated desktop fixes. Merge the feature branch rather than rebasing so both lines of local history remain intact.

Constraint: local main contains newer independent commits after the feature base
Rejected: Fast-forward merge | main is not an ancestor of the feature branch
Confidence: high
Scope-risk: moderate
Directive: Keep /goal continuation limits bounded and provider-agnostic when modifying the loop
Tested: bun test src/commands/headless.test.ts src/goals/goalState.test.ts src/goals/goalEvaluator.test.ts
Tested: bun run check:server
Tested: bun run verify
Tested: real DeepSeek v4 pro CLI and desktop /goal validation in /tmp business fixtures
Not-tested: push or remote PR creation
2026-05-13 19:23:47 +08:00
程序员阿江(Relakkes)
07050bb91c Allow packaged opener icons to load
Tauri WebView was allowed to call the desktop sidecar API, but the CSP still blocked image loads from that same local server, so extracted IDE icons degraded to the generic code glyph in packaged builds. macOS detection also trusted command shims before app bundles, which let stale JetBrains Toolbox scripts keep removed IDEs visible.

Constraint: Opener icons are served by the per-run desktop sidecar on localhost or 127.0.0.1

Rejected: Bundle a fixed static icon set | the product should use detected installed application icons across platforms

Rejected: Trust macOS command shims for detection | stale shims survive app removal and make the menu lie

Confidence: high

Scope-risk: narrow

Directive: Keep macOS IDE detection anchored to real app bundles before accepting command shims

Tested: bun test src/server/__tests__/open-target-service.test.ts src/server/__tests__/open-target-api.test.ts desktop/src-tauri/tauri-config.test.ts

Tested: cd desktop && bun run test -- src/api/client.test.ts src/api/openTargets.test.ts src/stores/openTargetStore.test.ts src/components/layout/OpenProjectMenu.test.tsx src/components/layout/TabBar.test.tsx

Tested: cd desktop && bun run lint
2026-05-13 18:42:30 +08:00
程序员阿江(Relakkes)
f9ac6049de Extract project opener icons cross-platform
Windows and Linux need to follow the same product rule as macOS: show icons from the user's installed applications instead of maintaining bundled brand artwork. The opener service now resolves command paths for Windows, walks from launcher scripts to the real IDE executable, extracts associated executable icons through the existing PNG endpoint, and resolves Linux .desktop Icon entries through common XDG application and icon theme locations.

Constraint: Do not redistribute third-party IDE trademark assets in the app bundle.

Constraint: Keep the frontend platform-agnostic by preserving the existing iconUrl contract.

Rejected: Add static per-IDE icon assets | impossible to keep complete and creates unnecessary trademark redistribution risk.

Confidence: medium

Scope-risk: moderate

Directive: Prefer platform installation metadata over bundled brand art when adding more opener targets.

Tested: bun test src/server/__tests__/open-target-service.test.ts src/server/__tests__/open-target-api.test.ts

Tested: cd desktop && bun run test -- src/stores/openTargetStore.test.ts src/components/layout/OpenProjectMenu.test.tsx src/components/layout/TabBar.test.tsx

Tested: cd desktop && bun run lint

Tested: bun run check:server

Not-tested: Native Windows and Linux VM smoke tests for real installed IDE icons
2026-05-13 18:19:35 +08:00
程序员阿江(Relakkes)
c125963346 Recover legacy memory labels from existing paths
Some memory-only project directories have no session JSONL metadata, so the previous label recovery still fell back to reversing sanitizePath(). That reverse mapping is lossy for Chinese characters, spaces, and punctuation, leaving paths rendered with repeated slashes. The memory API now performs a bounded filesystem-guided recovery: it walks only roots whose sanitized prefix can still match the project id and only descends through candidate directories that preserve that prefix match.

Constraint: Do not change the existing ~/.claude/projects/<sanitized>/memory storage layout.

Rejected: Full-home recursive search | too expensive and unnecessary because sanitizePath prefix matching gives a tight traversal boundary.

Confidence: high

Scope-risk: narrow

Directive: Keep project ids as opaque storage keys; recover display labels from real metadata or existing directories first.

Tested: bun test src/server/__tests__/memory.test.ts

Tested: local server curl /api/memory/projects against the real PicTacticAgent legacy memory project
2026-05-13 18:18:02 +08:00
程序员阿江(Relakkes)
1182c5d9c3 Use native app icons for project opener
The first project opener UI used generic code glyphs for every IDE, which made the menu visually noisy and did not match the native desktop expectation. This changes the macOS path to expose transparent PNG icons generated from each detected local .app bundle and renders them directly in the toolbar/menu, falling back to the existing glyph only when an icon cannot be loaded.

Constraint: Do not redistribute third-party IDE trademark assets in the app bundle.

Constraint: Keep icon detection local to already detected open targets and cache only runtime PNG results.

Rejected: Bundling downloaded IDE logos | creates asset maintenance and trademark redistribution risk.

Rejected: Adding simple-icons as a dependency | it is not a faithful desktop app icon source and still requires brand permission checks.

Confidence: high

Scope-risk: narrow

Directive: Prefer local bundle icons on macOS; add curated official assets only as a cross-platform fallback layer.

Tested: bun test src/server/__tests__/open-target-service.test.ts src/server/__tests__/open-target-api.test.ts

Tested: cd desktop && bun run test -- src/stores/openTargetStore.test.ts src/components/layout/OpenProjectMenu.test.tsx src/components/layout/TabBar.test.tsx

Tested: cd desktop && bun run lint

Tested: bun -e openTargetService.getTargetIcon for vscode and finder returned PNG data

Tested: cd desktop && bun run build
2026-05-13 18:09:35 +08:00
程序员阿江(Relakkes)
1e32942eab feat: enable autonomous goal loops from slash commands
Coding sessions need a native way to keep working until a stated completion condition is actually met. This adds a CLI /goal command, goal state and evaluator logic, and a headless-safe command filter so interactive and print-mode runs can both start a goal and continue when the evaluator says more work remains.

Constraint: The evaluator must work with saved third-party provider runtimes that may reject structured output schemas.
Constraint: Completion evidence must come from visible transcript text, not hidden goal prompts or assistant thinking blocks.
Rejected: Implement /goal as a bundled skill only | it would not own the query loop or support native continuation semantics.
Rejected: Expose all local-jsx commands to headless mode | interactive UI commands would become available in print mode.
Confidence: high
Scope-risk: moderate
Directive: Keep /goal evaluator evidence scoped to visible transcript text before adding richer completion signals.
Tested: bun test src/commands/headless.test.ts src/goals/goalState.test.ts src/goals/goalEvaluator.test.ts
Tested: bun run check:server
Tested: bun run verify
Tested: Real provider /goal smoke with MiniMax-M2.7-highspeed, including a two-turn continuation that logged Goal continuation #1 and completed with GOAL_SMOKE_LOOP_DONE.
Not-tested: Durable cross-process goal persistence for resumed sessions.
2026-05-13 18:08:46 +08:00
程序员阿江(Relakkes)
747b94825b Recover real paths for memory project labels
The CLI stores project directories with sanitizePath(), which intentionally replaces every non-alphanumeric byte with '-' for cross-platform safety. That storage key is lossy, so the desktop memory page must not treat it as the only source of display truth. The memory API now prefers the current cwd or the cwd/workDir/projectPath recorded in recent session JSONL files, and only falls back to the lossy reverse mapping when no metadata exists.

Constraint: Keep the existing ~/.claude/projects/<sanitized>/memory layout unchanged for CLI compatibility.

Rejected: Change sanitizePath to preserve Unicode | would break existing transcript and memory directory lookup semantics.

Confidence: high

Scope-risk: narrow

Directive: Treat project ids as storage keys, not user-facing path labels.

Tested: bun test src/server/__tests__/memory.test.ts

Tested: cd desktop && bunx vitest run src/__tests__/memorySettings.test.tsx

Tested: local server curl /api/memory/projects with a Chinese-space project path

Not-tested: bun run check:server still has two unrelated cron scheduler launcher timeout failures in src/server/__tests__/cron-scheduler-launcher.test.ts
2026-05-13 18:03:25 +08:00
程序员阿江(Relakkes)
db7432a39a Add desktop project open targets
Desktop sessions need a fast local escape hatch that opens the same materialized cwd the agent is editing, without showing unavailable IDE choices or persisting detection state. This adds a local open-targets API with silent in-memory detection for common IDEs and platform file managers, then wires a compact Codex-style toolbar menu into the desktop TabBar for active session workdirs.

Constraint: The first version is local IDE/editor and Finder/Explorer/file-manager only, no terminal targets or IDE plugin integration.

Constraint: The opened path must come from the active session workDir so isolated worktrees open the actual agent editing surface.

Rejected: Persisting detected applications | detection is cheap and temporary state avoids stale app inventory.

Rejected: Rendering unavailable IDEs as disabled menu rows | the user asked to show only detected targets and fall back to Finder/Explorer when no IDE is available.

Confidence: high

Scope-risk: moderate

Directive: Keep this path session-workdir based; do not switch it to repository root without proving isolated worktree behavior.

Tested: bun test src/server/__tests__/open-target-service.test.ts src/server/__tests__/open-target-api.test.ts

Tested: cd desktop && bun run test -- src/stores/openTargetStore.test.ts src/components/layout/OpenProjectMenu.test.tsx src/components/layout/TabBar.test.tsx

Tested: cd desktop && bun run lint

Tested: bun run check:desktop

Tested: bun test src/server/__tests__/h5-access-auth.test.ts -t 'allows local desktop H5 access settings under explicit server auth with a valid bearer'

Not-tested: bun run check:server full suite had one unrelated H5 auth integration timeout in the full concurrent run; the timed-out test passed when rerun alone.
2026-05-13 14:56:19 +08:00
程序员阿江(Relakkes)
df9775a6eb Surface project memory where desktop users can act on it
The CLI already emits memory_saved events and stores Markdown memory files, but the desktop app had no usable surface for seeing or editing those writes. This adds a project memory API, a Settings memory editor, chat memory event cards, and routing from /memory or /context into the memory UI.

Constraint: Memory files live under Claude project storage and must remain plain Markdown editable by users.
Rejected: Only expose raw filesystem links | users need an in-app review and edit flow from chat.
Confidence: high
Scope-risk: moderate
Directive: Keep memory storage project-scoped and preserve unknown Markdown content when editing.
Tested: bun test src/server/__tests__/ws-memory-events.test.ts src/server/__tests__/memory.test.ts
Tested: bun run check:server
Tested: bun run check:desktop
Tested: agent-browser E2E for chat memory card, Open Memory navigation, and responsive Markdown editor layout
Not-tested: Live model auto-memory trigger rate with real provider credentials
2026-05-13 14:07:13 +08:00
程序员阿江(Relakkes)
276b67083a Align file mention search with CLI path display
Desktop search results were visually misleading when many directories shared the same basename, because the UI emphasized the basename and the server ranking allowed deep basename matches to outrank direct path-prefix matches. This makes search rows show the insertable relative path and ranks direct path-prefix matches before unrelated same-name directories.

Constraint: Desktop @ file suggestions should match the CLI mental model for path search.

Rejected: Keep basename plus parent-path rows | it hides the distinction between src/, src/hooks/, and desktop/src in the primary text.

Confidence: high

Scope-risk: narrow

Directive: Preserve path-prefix ranking ahead of basename-only matches for directory searches.

Tested: bun test src/server/__tests__/filesystem.test.ts

Tested: cd desktop && bun run test -- FileSearchMenu.test.tsx ChatInput.test.tsx

Tested: bun run check:server

Tested: bun run check:desktop
2026-05-13 10:38:14 +08:00
程序员阿江(Relakkes)
f41e786748 Align desktop file mentions with CLI search
Desktop @ file search was recursively walking the filesystem with a local skip list, which let Python and Node generated directories leak into results and diverged from CLI behavior. Route candidate discovery through the same git-first model: tracked files, untracked files with exclude-standard, and ripgrep fallback for non-git folders, then derive selectable directories from those candidates.

Constraint: Desktop picker must select both files and directories without surfacing ignored project artifacts.
Constraint: No new dependencies; reuse the existing git, ripgrep, settings, and ignore utilities.
Rejected: Maintain a hardcoded directory denylist | it would drift from CLI and miss project-specific ignore rules.
Rejected: Full recursive readdir scanning | it ignores git index semantics and makes large dependency trees visible.
Confidence: high
Scope-risk: moderate
Directive: Keep desktop @ file candidate discovery aligned with src/hooks/fileSuggestions.ts before changing ranking or ignore behavior.
Tested: bun test src/server/__tests__/filesystem.test.ts
Tested: cd desktop && bun run test -- FileSearchMenu.test.tsx ChatInput.test.tsx
Tested: cd desktop && bun run lint && bun run test -- --run && bun run build
Tested: bun run check:server
Tested: bun run check:coverage
Tested: bun run verify
Not-tested: Native Windows/Linux manual UI smoke; path handling relies on cross-platform git/ripgrep wrappers and normalized relative paths.
2026-05-13 10:38:13 +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
546657701
3759588f5b fix: openaiResponsesToAnthropic usage fallback for OpenAI-compatible APIs
Non-streaming adapter only read `output_tokens`/`input_tokens` (Anthropic-style),
but many OpenAI-compatible providers (e.g. Jiutian MoMA) return standard
`completion_tokens`/`prompt_tokens` fields. This caused a null reference
error when reading `output_tokens` from such responses.

The streaming adapter already handles `completion_tokens` correctly, and
the Azure adapter uses the same fallback pattern applied here.

Fixes #383

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 19:02:10 +08:00
程序员阿江(Relakkes)
8d827510db Cover H5 settings surfaces in LAN auth tests
The H5 browser shell can load while deeper Settings tabs still exercise separate API routes. This adds MCP, plugin, and Agents endpoints to the H5 policy and integration matrices so the QR-token path is protected against page-level regressions.\n\nConstraint: H5 must expose existing desktop settings surfaces only after local opt-in and a valid H5 token.\nRejected: Rely on manual browser clicks alone | they missed the stopped-port failure mode and would not guard future regressions.\nConfidence: high\nScope-risk: narrow\nDirective: Add new Settings API surfaces to this H5 matrix when exposing them in the browser UI.\nTested: bun test src/server/__tests__/h5-access-policy.test.ts src/server/__tests__/h5-access-auth.test.ts\nTested: bun run check:server
2026-05-12 17:01:40 +08:00
程序员阿江(Relakkes)
8e184c1edd Enforce H5 opt-in before exposing LAN capabilities
The desktop sidecar can bind on LAN addresses for phone access, so the H5 settings switch must be an authorization boundary for remote capability routes, not only a token-mode toggle. Remote browser API, proxy, websocket, and SDK routes now fail closed while H5 is disabled; local desktop, Tauri, WebUI, adapter, and internal SDK paths remain tokenless. When H5 is enabled, remote API, proxy, and websocket requests must use the H5 token carried by the QR link, and the server API key cannot substitute for that H5 token.

Constraint: Desktop sidecar binds 0.0.0.0 while reporting loopback to local UI.

Constraint: Client-controlled Host and Origin headers cannot prove a local request; the boundary uses Bun requestIP instead.

Constraint: Static H5 shell and /health must still load so browser bootstrap can show a recovery flow.

Rejected: Trust loopback Host headers | LAN clients can spoof Host and Origin.

Rejected: Use ANTHROPIC_API_KEY as a remote H5 credential | it is not the phone pairing token and would weaken the QR-token boundary.

Confidence: high

Scope-risk: moderate

Directive: Do not make h5Enabled=false an open remote state for /api, /proxy, /ws, or /sdk routes.

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

Tested: bun run check:server
2026-05-12 16:25:54 +08:00
程序员阿江(Relakkes)
4ef9729ad6 Keep H5 control local while tightening remote CORS
Remote browser access now needs the H5 token once LAN mode is enabled, but changing that mode remains a local desktop control-plane operation even when deployment auth is explicitly enabled. CORS also no longer treats a non-local same-origin alias as trusted unless it is the configured H5 public origin or allowlisted origin.

Constraint: H5 exposes desktop control surfaces on the LAN and must not let remote browsers enable their own access.

Constraint: Desktop WebView, localhost WebUI, SDK websocket, and IM adapter loopback calls must remain tokenless.

Rejected: Allow authenticated remote control-plane writes under SERVER_AUTH_REQUIRED | violates the local opt-in boundary for H5 exposure.

Confidence: high

Scope-risk: moderate

Directive: Do not relax /api/h5-access mutating endpoints for browser origins without adding a reviewed desktop-only trust signal.

Tested: bun test src/server/__tests__/h5-access-auth.test.ts

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

Tested: bun run check:server
2026-05-12 14:52:02 +08:00
程序员阿江(Relakkes)
e2f299dcb3 Protect remote H5 capability endpoints without breaking local desktop flows
Wire request-scoped H5 auth and CORS decisions through the server so LAN browser API, proxy, and websocket access require the H5 token while loopback desktop, Tauri WebView, local adapter, SDK, and static shell paths keep their existing bootstrap behavior.

Constraint: Task 2 scope is limited to server auth/CORS wiring and the four requested files
Rejected: Global auth toggle for all requests | would incorrectly block loopback desktop and bootstrap asset flows
Directive: Keep static H5 shell and assets tokenless unless the browser-side bootstrap model changes
Confidence: high
Scope-risk: narrow
Tested: bun test src/server/__tests__/h5-access-policy.test.ts src/server/middleware/cors.test.ts
Tested: bun test src/server/__tests__/h5-access-policy.test.ts src/server/__tests__/h5-access-auth.test.ts src/server/middleware/cors.test.ts | h5-access-auth blocked by missing zod dependency in src/server/api/haha-oauth.ts
Tested: LSP diagnostics clean for src/server/index.ts, src/server/middleware/cors.ts, src/server/__tests__/h5-access-auth.test.ts, src/server/middleware/cors.test.ts
Not-tested: h5-access-auth runtime assertions because this checkout is missing zod for haha-oauth imports
2026-05-12 14:33:58 +08:00
程序员阿江(Relakkes)
a5cc7ff0c1 Tighten H5 policy trusted routes
The classifier should not treat every /sdk path as trusted by pathname, because LAN-exposed servers already have a narrower local SDK trust boundary.

Constraint: Desktop local chat, Tauri WebView, loopback adapters, and local SDK routes must remain tokenless.

Rejected: Path-only /sdk trust | a non-local caller could reach the SDK route through a LAN-bound server.

Confidence: high

Scope-risk: narrow

Directive: Keep remote /sdk and hostile-origin loopback requests in the H5/browser bucket unless a dedicated SDK auth layer is verified.

Tested: bun test src/server/__tests__/h5-access-policy.test.ts
2026-05-12 14:26:00 +08:00
程序员阿江(Relakkes)
115e6f3b36 Prepare H5 auth to distinguish browser traffic from trusted local callers
Add a small standalone request classifier and focused server tests so later H5 token enforcement can target LAN/browser requests without changing the current desktop, SDK, or adapter paths.

Constraint: Task scope is limited to a standalone classifier plus tests in two server files
Constraint: Local desktop WebView, loopback integrations, and /sdk routes must remain tokenless for now
Rejected: Integrate the classifier into auth middleware now | this task only introduces the reusable classification seam
Confidence: high
Scope-risk: narrow
Directive: Keep local-trusted and internal-sdk classifications tokenless unless the server auth integration changes with matching regression coverage
Tested: bun test src/server/__tests__/h5-access-policy.test.ts
Tested: per-file TypeScript diagnostics for src/server/h5AccessPolicy.ts and src/server/__tests__/h5-access-policy.test.ts
Not-tested: Full server auth middleware integration
Not-tested: bun run check:server remains red from pre-existing repo dependency and unrelated test failures
2026-05-12 14:20:32 +08:00
程序员阿江(Relakkes)
b0fcbba9f0 Make desktop session cleanup practical at list scale
The sidebar had only single-session deletion, which made stale or noisy
session lists expensive to maintain. This adds a batch-management lane in
the desktop UI and a server endpoint that deletes multiple sessions while
preserving per-session failure reporting and cleanup behavior.

Constraint: Session deletion must preserve existing transcript and adapter cleanup semantics
Constraint: Desktop UI should reuse the shared confirmation dialog instead of introducing a second modal surface
Rejected: Delete all selected sessions through repeated client DELETE calls | weaker partial-failure handling and duplicated cleanup orchestration
Rejected: Use a generic checkmark entry icon | it did not communicate batch deletion clearly enough
Confidence: high
Scope-risk: moderate
Directive: Keep batch deletion routed through the server batch endpoint so rollback and adapter cleanup stay centralized
Tested: bun test src/server/__tests__/sessions.test.ts -t batch-delete
Tested: bun run check:server
Tested: cd desktop && bun run check:desktop
Tested: browser UI smoke for group select, shift range select, delete confirmation, 7/30 day cleanup, Cmd+A filtered selection, and Escape exit
Not-tested: Live provider-backed session generation; this change covers session list management after sessions already exist
2026-05-12 13:42:45 +08:00
程序员阿江(Relakkes)
1597685d37 Keep H5 access open while token auth is paused
The H5 token gate still caused chat startup and runtime failures after the desktop startup hotfix, so the default server path now stays open for browser and LAN access. Explicit auth remains available through SERVER_AUTH_REQUIRED=1 or --auth-required for deployments that intentionally need it.

Constraint: Current H5 token state is blocking active users from normal chat usage

Rejected: Keep automatic remote-host auth with broader client-side token handling | still leaves existing upgraded clients vulnerable to stale or missing token state

Confidence: high

Scope-risk: moderate

Directive: Do not re-enable default H5 token auth without a migration and end-to-end browser chat verification

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

Tested: cd desktop && bun run test src/lib/desktopRuntime.test.ts src/__tests__/generalSettings.test.tsx

Tested: bun run check:server

Tested: bun run check:desktop
2026-05-11 17:59:03 +08:00
程序员阿江(Relakkes)
4501ef2adb Keep desktop sidecar control local after H5 auth
The H5 LAN release made the desktop sidecar bind broadly and require auth for non-localhost hosts. The Tauri WebView still talks to the loopback control URL without an H5 bearer token, so startup requests were rejected before the app could load.

Constraint: Desktop WebView control requests must stay tokenless for the local sidecar.
Rejected: Reuse H5 token bootstrap for Tauri | would add remote-access state to the native app startup path.
Confidence: high
Scope-risk: narrow
Directive: Tauri WebView bypass is limited to loopback control hosts; do not extend it to LAN or public hosts without re-reviewing H5 auth boundaries.
Tested: bun test src/server/__tests__/h5-access-auth.test.ts
Tested: bun run check:server
2026-05-11 13:44:35 +08:00
程序员阿江(Relakkes)
bfe3c8b5e0 Merge H5 LAN URL refresh into main
The detached worktree fix corrects stale private-network H5 public URLs after the desktop server chooses a new ephemeral LAN port. Merge it into local main while leaving unrelated local release edits untouched.

Constraint: Local main already had unrelated unstaged desktop release metadata edits.
Rejected: Broad staging before the merge | would risk committing unrelated local release work.
Confidence: high
Scope-risk: narrow
Tested: bun test src/server/__tests__/h5-access-service.test.ts
Tested: bun run check:server
Not-tested: physical phone browser on local WiFi after merge
2026-05-10 20:48:43 +08:00
程序员阿江(Relakkes)
16112e83f3 fix(desktop): refresh stale H5 LAN URLs
H5 access could keep returning a previously saved private-network URL even after the packaged desktop server moved to a new ephemeral LAN port. The public settings now prefer the current auto-detected LAN URL for local/private stored addresses while preserving explicit public reverse-proxy URLs.

Constraint: Packaged desktop H5 access uses an ephemeral server port and auto-publishes a LAN URL for phones on the same network.
Rejected: Always overwrite stored publicBaseUrl | public reverse-proxy deployments still need manual stable URLs.
Confidence: high
Scope-risk: narrow
Tested: bun test src/server/__tests__/h5-access-service.test.ts
Tested: bun test src/server/__tests__/h5-access-service.test.ts src/server/__tests__/h5-access-api.test.ts src/server/__tests__/h5-access-auth.test.ts
Tested: bun run check:server
Tested: manual LAN smoke with 0.0.0.0:5188 correcting stale 192.168.0.102:5179 to 192.168.0.102:5188
Not-tested: physical phone browser on local WiFi
2026-05-10 20:48:03 +08:00
程序员阿江(Relakkes)
65548d3949 fix(computer-use): use marker file to detect interpreter changes reliably
The previous fix compared the venv's pyvenv.cfg `home` field with the
custom interpreter's directory, but Python's venv module skips the
wrapping venv when the source interpreter is itself in a venv (conda /
pyenv / hand-built venvs — which is the common case). The recorded
`home` then points to the base Python install, not the user-provided
path, causing the comparison to permanently fail and the UI to keep
showing "venv not ready" even right after a successful rebuild.

Switch to a marker file (~/.claude/.runtime/venv-base-interpreter.txt)
that records the exact `config.pythonPath` used at venv creation time.
Status check compares it verbatim with the current config. Falls back
to "match if both empty" when the marker is missing, which preserves
behavior for legacy users who never set a custom path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 20:36:15 +08:00
程序员阿江(Relakkes)
339d0d860d fix(computer-use): rebuild venv when custom Python interpreter changes
The dependency check ignored the custom Python path: it only verified
the global venv's stamp file, so switching to a fresh custom interpreter
still showed deps as installed even though the new interpreter's
environment was empty. Setup also reused the old venv built from a
different base interpreter.

Verify the existing venv via pyvenv.cfg's home field, but only when a
custom path is configured — users without a custom path keep the
original code path untouched, protecting existing installations.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 19:52:12 +08:00
程序员阿江(Relakkes)
775ddb9c51 fix(desktop): make H5 access reachable from LAN
Packaged desktop builds started the sidecar on loopback only, so phones on the same WiFi could not connect to the H5 URL. The server now binds to LAN interfaces while keeping the desktop control URL on loopback, serves the bundled H5 frontend, and reports a LAN public URL when H5 access is enabled.

Constraint: Packaged Tauri resources place ../dist under Contents/Resources/_up_/dist.
Rejected: Bind the desktop control URL to 0.0.0.0 | desktop clients should keep using loopback for local control.
Confidence: high
Scope-risk: moderate
Directive: Keep packaged H5 resource lookup aligned with Tauri resource mapping when changing bundle resources.
Tested: bun run check:server
Tested: cd desktop/src-tauri && cargo test --lib
Tested: cd desktop && bun run test -- desktopRuntime.test.ts generalSettings.test.tsx
Tested: SKIP_INSTALL=1 ./desktop/scripts/build-macos-arm64.sh
Tested: Packaged claude-sidecar smoke served H5 HTML while listening on *:39876
Not-tested: Physical phone browser test on the local WiFi network
2026-05-10 19:41:25 +08:00
程序员阿江(Relakkes)
1aa0774cbf fix: clamp context token display to model context window size
Providers like DeepSeek with 1M context windows can report
input_tokens that, when combined with output_tokens, exceed the
declared context window — causing the UI to show >100% usage.

Add an optional contextWindow parameter to calculateCurrentContextTokenTotal
that clamps the result to the window size. Pass it from analyzeContext
and sessionService where the window size is already available.

Backward compatible: callers that omit the parameter keep existing behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 18:19:57 +08:00
程序员阿江(Relakkes)
eea8ea5cbd fix(desktop): avoid duplicate worktree startup status
Continuing an already materialized worktree session should behave like a normal existing session. The launch path now checks whether the session has already moved into its worktree before showing the startup bubble or passing worktree creation flags again.

Constraint: Existing session metadata can retain repository.worktree after the worktree transcript becomes the active session file
Rejected: Frontend-only suppression | the server could still launch the CLI with duplicate worktree creation flags
Confidence: high
Scope-risk: narrow
Tested: bun run check:server
Tested: bun test src/server/__tests__/conversations.test.ts -t worktree --timeout 30000
Tested: bun test src/server/__tests__/sessions.test.ts -t "newest duplicate session file" --timeout 30000
Not-tested: bun run verify still fails on unrelated desktop Settings.tsx and MessageList.tsx gates from the broader worktree
2026-05-10 12:16:15 +08:00
程序员阿江(Relakkes)
2a6c7dc67a Merge token usage view into local main
Integrate the Token usage settings page on top of the newer local main branch, preserving the existing H5 access router surface while adding the activity stats API route.

Constraint: Local main already contained H5 access router changes after the Token usage worktree base.
Rejected: Prefer either router branch during conflict resolution | both API surfaces are independent and must remain registered.
Confidence: high
Scope-risk: narrow
Directive: Keep h5-access and activity-stats routes registered together in src/server/router.ts.
Tested: Conflict marker scan for src/server/router.ts
Not-tested: Post-merge desktop/server checks pending
2026-05-10 11:38:33 +08:00
程序员阿江(Relakkes)
ace7f7b657 feat: add desktop token usage activity view
Expose local Claude Code CLI transcript usage in Settings so users can inspect recent token consumption and daily activity without leaving the desktop app.

The page uses server-side transcript aggregation for session, message, tool, model-token, and subagent token data. Daily token buckets use assistant message timestamps, and daily session counts use active parent sessions for the same date bucket so resumed sessions and cross-midnight work do not produce token-only days. Cache accounting is bumped to v5 to force recomputation under the corrected daily semantics.

Constraint: Usage data must come from local Claude Code CLI transcripts rather than mock/demo data.
Constraint: Desktop navigation keeps Token usage directly above Diagnostics.
Rejected: Bucket all token usage by session start date | hides resumed-session and cross-midnight consumption from the actual day it was spent.
Confidence: high
Scope-risk: moderate
Directive: Keep daily token and daily session counts on the same date-bucketing semantics.
Tested: bun run check:desktop
Tested: bun run check:server
Tested: Browser verification for Token usage in English and Chinese locale date labels
Not-tested: Full bun run verify quality gate
2026-05-10 11:37:49 +08:00
程序员阿江(Relakkes)
adc8da0167 Enable phone-sized H5 chat access in local desktop builds
Merge the H5 access branch into local main so the desktop app can expose an opt-in browser chat surface with token-gated remote access, mobile chat layout, and full-width bottom sheets for mobile pickers. The merge keeps desktop and Tauri behavior behind runtime checks while preserving local WebUI development bypasses for loopback and private-LAN server targets.

Constraint: H5 is opt-in and local browser development must not require a desktop-generated token
Rejected: Cherry-pick only the final UI commit | it omitted earlier auth, CORS, settings, and H5 token service dependencies
Confidence: high
Scope-risk: moderate
Directive: Keep mobile-only layout branches guarded by browser viewport plus non-Tauri runtime checks
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx src/__tests__/pages.test.tsx src/api/client.test.ts src/api/websocket.test.ts src/components/chat/ChatInput.test.tsx src/components/controls/PermissionModeSelector.test.tsx src/components/layout/AppShell.test.tsx src/components/layout/Sidebar.test.tsx src/components/shared/RepositoryLaunchControls.test.tsx src/hooks/useMobileViewport.test.tsx src/lib/desktopRuntime.test.ts src/pages/ActiveSession.test.tsx src/pages/EmptySession.test.tsx src/stores/settingsStore.test.ts
Tested: bun test src/server/__tests__/h5-access-api.test.ts src/server/__tests__/h5-access-auth.test.ts src/server/__tests__/h5-access-service.test.ts src/server/middleware/cors.test.ts
Tested: git diff --check HEAD^ HEAD
Not-tested: bun run verify full quality gate
Not-tested: mobile Chrome smoke was not rerun after merging into local main
2026-05-10 11:36:52 +08:00
程序员阿江(Relakkes)
5f9faaf01d feat: support H5 mobile chat access
H5 browser use needs to keep local desktop WebUI testing open while giving remote phones a usable chat-first surface. This change scopes browser auth by origin and target host, hides non-chat desktop chrome on H5 mobile, compacts the empty-session composer, and unifies mobile selectors behind a full-width bottom sheet with an explicit close action.

Constraint: Local browser development may bypass H5 auth only for loopback or private LAN server hosts; public or remote hosts still require an H5 token.

Constraint: Mobile H5 scope is chat-first; settings and scheduled-task surfaces stay hidden instead of fully redesigned.

Rejected: Reuse desktop popovers on mobile | hover/anchored dropdown behavior leaves key actions hard to dismiss and cramped on narrow screens.

Rejected: Let any localhost origin bypass remote auth | it would let arbitrary local pages access public H5 servers without a token.

Confidence: medium

Scope-risk: moderate

Directive: Keep future H5 selector popups on MobileBottomSheet unless a selector needs a reviewed custom mobile interaction.

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run test -- src/pages/EmptySession.test.tsx src/components/chat/ChatInput.test.tsx src/lib/desktopRuntime.test.ts src/components/shared/RepositoryLaunchControls.test.tsx src/components/controls/PermissionModeSelector.test.tsx src/components/controls/ModelSelector.test.tsx src/components/shared/DirectoryPicker.test.tsx src/__tests__/pages.test.tsx

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

Tested: Chrome mobile viewport smoke for context, model, permission, project, branch, and worktree bottom sheets with no horizontal overflow.

Not-tested: Full bun run verify quality gate.
2026-05-10 11:30:03 +08:00
程序员阿江(Relakkes)
c45406054b fix: tolerate missing provider usage in fallback responses
Some Anthropic-compatible providers can return successful responses with
missing or partial usage metadata, especially after falling back to
non-streaming requests. Normalize usage at the provider response boundary so
transcript writes, side queries, and cost tracking continue without treating
token accounting as required response content.

Constraint: Third-party Anthropic-compatible providers do not always return complete usage fields.
Rejected: Add provider-specific handling | this is a protocol compatibility issue across proxies and gateways
Confidence: high
Scope-risk: moderate
Directive: Keep provider response normalization vendor-neutral; do not branch on provider names for missing usage fields.
Tested: bun test src/services/api/emptyUsage.test.ts src/utils/__tests__/thinking.test.ts src/server/__tests__/title-service.test.ts src/server/__tests__/conversations.test.ts
Tested: bun run check:server
Tested: bun run check:persistence-upgrade
Tested: git diff --check
Not-tested: Live Shengsuan Cloud provider replay
2026-05-10 10:47:45 +08:00
程序员阿江(Relakkes)
37bdc4e6e7 Protect remote server access with H5-aware auth and CORS
Remote browser access needs an explicit path that preserves localhost desktop behavior while allowing H5 tokens for REST and client websocket upgrades. This keeps the existing synchronous Anthropic auth helper intact, adds async request validation for H5 tokens, and centralizes origin handling so preflight, API, proxy, websocket, and health responses behave consistently.

Constraint: Existing validateAuth(req) must stay synchronous for current tests and callers
Constraint: Default localhost and Tauri desktop behavior must remain unchanged
Rejected: Replacing validateAuth with an async-only API | would break existing sync tests and call sites
Rejected: Allowing wildcard or fallback remote origins | violates the H5 explicit-origin security model
Directive: Restore ProviderService serverPort in server integration tests that call startServer with custom ports to avoid leaking global proxy runtime state
Confidence: high
Scope-risk: moderate
Tested: bun test src/server/__tests__/h5-access-auth.test.ts --timeout 30000
Tested: bun test src/server/__tests__/h5-access-service.test.ts src/server/__tests__/h5-access-api.test.ts src/server/__tests__/settings.test.ts --timeout 30000
Tested: bun test src/server/__tests__/h5-access-auth.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/cron-scheduler-launcher.test.ts --timeout 30000
Tested: bun test src/server/__tests__/e2e/full-flow.test.ts --timeout 30000
Not-tested: Full non-live server gate end-to-end; an attempted broader run was interrupted after uncovering and then fixing a test-side ProviderService port leak
2026-05-09 23:43:29 +08:00
程序员阿江(Relakkes)
3276a19da0 Prevent managed settings races from dropping H5 or provider state
Move cc-haha managed settings writes behind one shared transaction helper so
H5 access mutations and provider settings sync serialize against the same file.
Also treat persisted H5 state without a valid token hash as disabled so origin
allowlists cannot remain active after partial corruption.

Constraint: H5 and provider config both share ~/.claude/cc-haha/settings.json
Rejected: Keep per-service locks | concurrent read-modify-write still drops unrelated fields
Rejected: Only harden isOriginAllowed | corrupted enabled state would still surface as active in settings reads
Confidence: high
Scope-risk: narrow
Directive: Any future writer of cc-haha/settings.json must go through the shared managed settings transaction path
Tested: bun test src/server/__tests__/h5-access-service.test.ts src/server/__tests__/h5-access-api.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/provider-presets.test.ts
Not-tested: Full repo typecheck remains blocked by the existing bun-types/tsconfig environment issue in this worktree
2026-05-09 23:32:39 +08:00
程序员阿江(Relakkes)
e357c978fe Add a durable H5 access control surface for remote browser setup
Persist H5 access state in cc-haha managed settings, expose a narrow server API
for enable/disable/regenerate/verify flows, and keep token responses sanitized
so the raw secret is only returned at generation time.

Constraint: H5 config must live in ~/.claude/cc-haha/settings.json and preserve unknown fields
Rejected: Store raw token for later display | violates hash-only persistence requirement
Confidence: high
Scope-risk: narrow
Directive: Do not move H5 settings into ~/.claude/settings.json or expose tokenHash through the API
Tested: bun test src/server/__tests__/h5-access-service.test.ts src/server/__tests__/h5-access-api.test.ts
Not-tested: Full repo typecheck via tsc is blocked locally by missing bun-types and a TS 6 baseUrl deprecation in the current config
2026-05-09 23:22:55 +08:00
程序员阿江(Relakkes)
da477c2b4b Merge session title sanitation into main
Bring the detached worktree fix onto local main after verifying the title-generation regression path and local quality checks.

Constraint: The worktree commit was based on an older main commit, while local main already contained later chat scroll fixes.
Confidence: high
Scope-risk: moderate
Directive: Keep title sanitation shared across CLI, server, and desktop read paths.
Tested: bun run check:server
Tested: bun run check:desktop
Tested: bun run verify (7 passed, 1 failed on existing aggregate agent-utils coverage baseline)
Not-tested: live model title-generation smoke
2026-05-09 22:34:54 +08:00