181 Commits

Author SHA1 Message Date
程序员阿江(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)
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)
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)
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)
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)
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)
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)
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)
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
程序员阿江(Relakkes)
179f79b794 fix: sanitize generated session titles
Slash-command and skill prompts can enter the title-generation path as internal XML breadcrumbs. The async title request previously treated that transport metadata as user prose, so a generated ai-title could persist raw command tags and override the normal session title.

This routes title sources and generated title output through a shared sanitizer, preserving user-visible command names and arguments while dropping unrelated internal XML metadata. Desktop fallback title rendering now applies the same cleanup so existing transcripts with bad ai-title entries recover on read.

Constraint: Session titles can be produced by both desktop server logic and the SDK generate_session_title control request.
Rejected: Only clean desktop session display | leaves CLI and remote title generation able to persist bad titles again
Confidence: high
Scope-risk: moderate
Directive: Keep generated-title input and persisted-title readback on the shared sanitizer; do not add a title path that reads command XML directly.
Tested: bun test src/utils/__tests__/sessionTitle.test.ts src/utils/__tests__/sessionTitleText.test.ts
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:27 +08:00
程序员阿江(Relakkes)
50d4679f51 Merge chat scroll recovery into main
Bring the detached worktree fix into the local main line while preserving the newer main behavior that passes session context into interactive chat message blocks.

Constraint: Local main already contains six unpublished commits on top of origin/main
Constraint: Merge conflict only affected MessageList message rendering around sessionId propagation
Rejected: Overwrite main's MessageBlock call shape | would regress AskUserQuestion and permission interactions that need sessionId
Confidence: high
Scope-risk: moderate
Directive: Keep MessageBlock sessionId propagation when editing chat rendering; AskUserQuestion depends on it
Tested: cd desktop && bun run test -- MessageList.test.tsx
Not-tested: Full verify after merge; previous verify remains blocked by agent-utils global coverage baseline
2026-05-09 21:52:31 +08:00
程序员阿江(Relakkes)
6382115de9 fix: keep chat tabs from losing scroll context
Chat sessions need predictable navigation when users switch tabs or read history during streaming. This preserves each session's scroll position, defaults fresh sessions to the latest message, and adds a compact jump-to-latest affordance when auto-follow is paused.

The PR gate also exposed that provider-scoped scheduled tasks must force the sdk-cli entrypoint when launched through the sidecar, so the same change records that runtime contract and its regression assertion.

Constraint: Desktop chat should not force-scroll while the user is reading older messages
Constraint: Scheduled task provider env must not inherit stale parent model runtime values
Rejected: Persist scroll positions in localStorage | session scroll is transient UI state and should not survive app restarts
Confidence: high
Scope-risk: moderate
Directive: Do not remove the sdk-cli entrypoint marker from provider-scoped cron tasks without rerunning the sidecar launcher regression
Tested: cd desktop && bun run test -- MessageList.test.tsx
Tested: cd desktop && bun run lint
Tested: bun test src/server/__tests__/cron-scheduler-launcher.test.ts src/utils/__tests__/themeWords.test.ts
Tested: bun run check:desktop
Tested: bun run check:server
Tested: bun run check:native
Not-tested: bun run verify still fails on pre-existing agent-utils global coverage baseline below threshold
Not-tested: Chrome extension E2E blocked by Codex Chrome Extension communication timeout after plugin diagnostics passed
2026-05-09 21:51:34 +08:00
程序员阿江(Relakkes)
e2b1ac9fd1 fix: launch scheduled tasks with the sdk cli entrypoint
Scheduled task subprocesses should normalize their child environment instead of inheriting a stale parent entrypoint. Setting the default task entrypoint keeps launcher tests and non-OAuth task execution on the SDK CLI path while still allowing the official OAuth environment overlay to provide its desktop-specific entrypoint.

Constraint: Official OAuth tasks intentionally overlay provider-specific environment after the default child task environment is built
Rejected: Preserve parent CLAUDE_CODE_ENTRYPOINT | stale parent values can leak into scheduled task launches
Confidence: high
Scope-risk: narrow
Directive: Keep default task launcher environment deterministic before provider-specific overlays are applied
Tested: bun test src/server/__tests__/cron-scheduler-launcher.test.ts
Tested: bun run check:server
Not-tested: Full verify still blocked by existing agent-utils global coverage baseline
2026-05-09 21:48:06 +08:00
程序员阿江(Relakkes)
f46b0c80cd fix: restore worktree badges from CLI transcript state
Desktop sessions already persist repository launch metadata, but CLI worktree sessions also write native worktree-state entries to the JSONL transcript for resume. Relying only on desktop session-meta leaves reopened or older transcripts vulnerable to losing the footer worktree identity when in-memory state is gone.

This teaches SessionService to recover the latest CLI worktree-state entry and lets git-info use it as a fallback for worktree badge fields. Desktop repository metadata still wins when present because it carries the selected business branch, while the CLI state keeps reopened sessions stable.

Constraint: CLI records worktree state as transcript metadata, not only as cwd.

Rejected: Infer worktree identity only from .claude/worktrees path | path heuristics miss hook-based worktrees and do not carry original cwd or slug.

Confidence: high

Scope-risk: narrow

Directive: Prefer explicit transcript metadata over path guessing for worktree session identity.

Tested: bun test src/server/__tests__/sessions.test.ts --test-name-pattern CLI worktree state

Tested: bun test src/server/__tests__/sessions.test.ts --test-name-pattern worktree-state|worktree identity|git-info

Tested: cd desktop && bun run lint

Tested: git diff --check
2026-05-08 18:29:17 +08:00
程序员阿江(Relakkes)
5f0ddaecb2 fix: keep worktree session metadata after CLI init
Worktree sessions briefly showed the expected footer badge and then reverted because the CLI init path produced a second transcript under the actual worktree cwd. The desktop placeholder still held the repository launch metadata, but the startup cleanup removed that placeholder after writing metadata through a lookup that could target the stale source transcript. The runtime session also kept the launch cwd instead of the init cwd.

This moves session metadata writes to the transcript matching the CLI init cwd, carries repository launch metadata across duplicate session files, and updates the live ConversationService workDir when the init event reports the real cwd.

Constraint: Native CLI worktree creation happens inside the CLI after desktop has already created a placeholder session.

Rejected: Patch the footer to remember the first worktree badge | it would hide stale backend state and leave other session APIs on the source checkout.

Confidence: high

Scope-risk: narrow

Directive: Treat the CLI init cwd as authoritative for active desktop sessions; do not let placeholder cleanup discard repository launch metadata.

Tested: bun test src/server/__tests__/sessions.test.ts --test-name-pattern worktree|git-info|placeholder

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run test -- src/components/shared/ProjectContextChip.test.tsx

Tested: git diff --check
2026-05-08 18:24:16 +08:00
程序员阿江(Relakkes)
95b181dea2 feat: align desktop repository sessions with CLI worktrees
Desktop repository launches now defer isolated worktree creation until the
first user turn so the CLI owns worktree setup, cwd initialization, and
session metadata. The chat UI surfaces the pre-startup Git phase so users see
when a session is creating a worktree or switching a branch before model
output begins.

Constraint: Desktop must preserve the selected source checkout until a user actually sends a message
Constraint: CLI setup is the canonical owner for worktree creation and cwd initialization
Rejected: Create the worktree eagerly in the desktop session picker | it diverges from CLI session startup and creates worktrees before a conversation exists
Confidence: high
Scope-risk: moderate
Directive: Keep repository session startup routed through CLI worktree flags; do not reintroduce eager desktop worktree creation without testing transcript cwd and cleanup behavior
Tested: bun test src/server/__tests__/sessions.test.ts src/server/__tests__/conversation-service.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "worktree startup status"
Tested: cd desktop && bun run test -- src/pages/EmptySession.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: git diff --check
Tested: CLI init-only native worktree smoke from feature/rail
Tested: agent-browser UI flow with MiniMax-M2.7-highspeed in a /tmp repository
2026-05-08 16:46:51 +08:00
程序员阿江(Relakkes)
6e5dd94dad Stop bearer providers from inheriting local API keys
Desktop Anthropic-compatible relay providers use ANTHROPIC_AUTH_TOKEN for
Authorization, but the CLI process can still load a stale ANTHROPIC_API_KEY
from inherited env, original settings, keychain-backed config, or the SDK
constructor fallback. That made Provider Test pass while real sessions sent
both Authorization and x-api-key to relays such as Packy and Shengsuanyun,
which then rejected the request as an invalid token/key.

The client now avoids falling back to a local API key when bearer-token
provider auth is active. Provider-managed auth_token env also writes an empty
ANTHROPIC_API_KEY so cc-haha settings explicitly override stale original
settings during desktop/sidecar startup. Regression tests pin both the SDK
client behavior and the desktop child-env behavior.

Constraint: Anthropic-compatible relay providers can reject mixed Authorization plus x-api-key headers even when direct provider tests pass
Rejected: Treat this as a provider/model-name issue | local proxy captures showed the failing request shape before provider handling
Rejected: Rely only on client.ts fallback suppression | settings/env layering can leave ANTHROPIC_API_KEY populated before the client is constructed
Confidence: high
Scope-risk: moderate
Directive: Bearer-token provider sessions must keep Authorization without inheriting or reintroducing x-api-key from user/global settings
Tested: bun test src/services/api/client.test.ts
Tested: bun test src/server/__tests__/providers.test.ts src/server/__tests__/providers-real.test.ts src/server/__tests__/conversation-service.test.ts
Tested: bun run check:server
Tested: Source and packaged sidecar proxy captures with stale original ANTHROPIC_API_KEY showed Authorization=true and x-api-key=false after the fix
Tested: desktop/scripts/build-macos-arm64.sh
Tested: PackyCodex2ccCustom and 胜算云 packaged-sidecar live calls returned ok
Not-tested: Full manual UI click-through in the rebuilt macOS app window
2026-05-08 15:20:45 +08:00
程序员阿江(Relakkes)
7696e21dc2 Support provider runtimes for scheduled tasks
Scheduled tasks used the model selector in model-only mode, so a task could store a third-party model id without the provider runtime needed to execute it. The desktop task editor now stores the selected provider with the model, and the scheduler injects the same provider-scoped runtime env that desktop sessions use before launching the sidecar.

Constraint: Scheduled tasks run outside an active desktop websocket session, so provider runtime must be serialized on the task itself.
Rejected: Reuse session runtime localStorage for tasks | scheduled executions can run long after the UI session is gone.
Confidence: high
Scope-risk: moderate
Directive: Keep task execution provider env isolated from inherited process env; stale parent ANTHROPIC_* values must not override task provider choices.
Tested: cd desktop && bun run test -- src/components/tasks/NewTaskModal.test.tsx src/components/controls/ModelSelector.test.tsx
Tested: bun test src/server/__tests__/scheduled-tasks.test.ts src/server/__tests__/cron-scheduler-launcher.test.ts
Tested: bun run check:desktop
Tested: bun run check:server
Tested: git diff --check
Not-tested: Live third-party provider API call; covered by sidecar launch integration with provider proxy env.
2026-05-08 09:49:16 +08:00
程序员阿江(Relakkes)
165d914d5a fix: launch scheduled tasks through desktop sidecar
Scheduled task Run Now was still constructing a source checkout Bun command, so packaged desktop builds could try to execute src/entrypoints/cli.tsx from a missing or wrong root. Resolve the same launcher used by the desktop runtime first, and keep the source checkout fallback only for development.

Constraint: Desktop Release tasks must run through the configured sidecar and app root instead of assuming source files exist on disk

Rejected: Retain import.meta.dir path math with broader fallback | still bypasses packaged desktop launcher and repeats the issue root cause

Confidence: high

Scope-risk: narrow

Directive: Do not change scheduled task execution back to direct source CLI invocation without repeating desktop Run Now E2E

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

Tested: bun run check:server

Tested: bun run check:native

Tested: Desktop UI E2E via scheduled task page create task and Run Now with fake sidecar

Not-tested: Full packaged macOS .app click test
2026-05-07 18:32:38 +08:00
程序员阿江(Relakkes)
8b07c16f45 fix: keep startup failures visible in terminals
Diagnostics should capture fatal server failures without replacing the terminal stderr signal that developers rely on during local startup. Fatal uncaught exceptions now print their stack to stderr, persist the diagnostic event, and exit non-zero so repeated server starts expose port conflicts immediately.

Constraint: Startup diagnostics must still write sanitized runtime events for export bundles.
Rejected: Only document checking runtime-errors.log | developers should not lose the standard stderr failure path.
Confidence: high
Scope-risk: narrow
Directive: Do not install process-level exception handlers that swallow fatal startup errors without preserving stderr and non-zero exit behavior.
Tested: bun test src/server/__tests__/diagnostics-service.test.ts
Tested: bun run check:server
Tested: SERVER_PORT=3456 bun run src/server/index.ts returned exit=1 and printed the port-conflict stack while diagnostics recorded the event
2026-05-07 16:50:20 +08:00
程序员阿江(Relakkes)
7fbce35be6 fix: prevent malformed generated session titles
Session titles need to appear immediately, but the async AI title pass can return fenced or escaped JSON fragments. Keep the first-message title path fast, preserve optimistic client titles during background refresh, and only accept structured title responses that parse cleanly.

Constraint: Desktop sessions should stop showing Untitled/New Session after the first user turn.
Rejected: Accept short raw model output as a fallback | malformed JSON fragments are short enough to leak into the UI.
Confidence: high
Scope-risk: moderate
Directive: Do not loosen generated title parsing without regression coverage for fenced, escaped, and truncated JSON responses.
Tested: bun test src/server/__tests__/title-service.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/stores/sessionStore.test.ts src/pages/EmptySession.test.tsx
Tested: agent-browser smoke on http://127.0.0.1:1420/ confirmed sidebar and tab titles update without JSON fragments.
2026-05-07 16:28:08 +08:00
程序员阿江(Relakkes)
7ae885a114 fix: add safe Doctor rescue path for desktop upgrades
Online upgrades can strand users on stale desktop UI state or malformed local persistence. This adds a deny-by-default Doctor path that resets only regenerable desktop UI state, reports protected local files with redacted metadata, and keeps protected repair as a dry-run no-op until a reviewed backup-first flow exists.

Constraint: Chat transcripts, model/provider config, Skills, MCP, IM bindings, adapter sessions, OAuth tokens, plugins, and team/session records are user-owned protected state.
Rejected: Automatically rewrite malformed protected JSON | unsafe without schema-specific migrations and backups.
Rejected: Continue relying only on startup migrations | users need an explicit recovery action after a white screen.
Confidence: high
Scope-risk: moderate
Directive: Keep Doctor repair deny-by-default; do not mutate protected state without an explicit reviewed backup-first manual repair flow.
Tested: bun test src/server/__tests__/doctor-service.test.ts
Tested: cd desktop && bun run test src/components/ErrorBoundary.test.tsx src/lib/doctorRepair.test.ts src/__tests__/diagnosticsSettings.test.tsx src/components/layout/StartupErrorView.test.tsx
Tested: cd desktop && bun run lint
Tested: bun run check:server
Tested: bun run verify (failed only existing agent-utils coverage baseline; changed-lines coverage 97.62%)
Not-tested: Packaged desktop manual Doctor click path.
2026-05-07 00:04:06 +08:00
程序员阿江(Relakkes)
fa47adc33a fix: prevent upgrade crashes from stale persistence
Desktop users can carry provider indexes, managed settings, localStorage state, and native update state from builds that no longer match current readers. This adds startup migrations and recovery paths before server and React state are consumed, plus a persistence upgrade gate so future storage protocol changes ship with old-format fixtures.

Constraint: Existing installs may contain malformed or legacy JSON/localStorage that must not block startup.
Constraint: Local verify should evaluate the current worktree diff rather than unrelated detached-worktree history.
Rejected: Treat invalid persisted state as fatal | reproduces white-screen and startup failure behavior for existing users.
Rejected: Bypass PR policy locally | hides real gate behavior and does not fix detached-worktree false positives.
Confidence: high
Scope-risk: moderate
Directive: Any local JSON, localStorage, or app config shape change must add a migration fixture and keep `bun run check:persistence-upgrade` green.
Tested: bun run check:persistence-upgrade; bun run check:policy; bun run check:desktop; bun run check:server; bun run check:native; bun run verify (9 passed, 1 coverage baseline failure)
Not-tested: Live provider baseline; existing user configs beyond covered fixtures
2026-05-06 23:20:21 +08:00
程序员阿江(Relakkes)
f262ec3029 feat: protect desktop branch launches with worktree isolation
Desktop sessions now resolve repository launch intent before creation, so users can pick a branch, choose whether to isolate it in a worktree, and get stable error messages instead of silent branch-switch failures. The server owns the Git safety checks and session metadata so the UI and real agent runtime agree on the actual working directory.

Constraint: Direct branch switching must not overwrite or hide uncommitted user changes
Constraint: Desktop worktree branches must stay out of normal branch selection and recent-project labels
Rejected: Let the UI call git directly | server-side checks keep session metadata and runtime launch paths consistent
Rejected: Auto-switch dirty checkouts | users need an explicit isolated-worktree choice to protect local edits
Confidence: high
Scope-risk: moderate
Directive: Do not relax dirty-worktree or checked-out-branch guards without adding equivalent business-flow tests
Tested: ALLOW_CLI_CORE_CHANGE=1 bun run quality:pr
Tested: /tmp business-flow script with dirty checkout, checked-out branch, isolated worktree, missing branch, non-git, missing directory, and real LLM session
Tested: agent-browser desktop UI flow across dirty, checked-out, non-git, branch search, recent-project, and Run scenarios
2026-05-06 14:51:46 +08:00
程序员阿江(Relakkes)
147d060004 fix: preserve custom provider thinking settings
Custom providers can point at user-defined model IDs that the CLI cannot
classify by built-in model tables. Declare the existing tier capability
overrides for custom provider roles so explicit thinking and effort settings
survive request construction.

Constraint: Issue #285 reports local proxy logs dropping user-defined model thinking and effort as passthrough with no config.
Rejected: Disable model capability checks globally | would relax behavior for built-in presets and non-custom providers.
Confidence: high
Scope-risk: narrow
Directive: Keep this scoped to custom providers unless each preset has explicit capability semantics.
Tested: bun test src/server/__tests__/providers.test.ts src/server/__tests__/provider-presets.test.ts src/utils/__tests__/thinking.test.ts
Tested: bun run check:server
Tested: bun run quality:pr
Tested: bun run quality:gate --mode baseline --allow-live --provider-model custom:main:custom-main
Tested: agent-browser custom provider UI smoke with request log showing thinking adaptive and effort max
Related: https://github.com/NanmiCoder/cc-haha/issues/285
2026-05-06 11:44:03 +08:00
程序员阿江(Relakkes)
b72bca94e3 fix: wait for sdk socket before context inspection
Desktop context inspection could send get_context_usage while a prewarmed CLI process existed but before the SDK socket was connected. That first control request sat in the pending outbound queue and could time out, leaving the composer spinner or a misleading empty-state context display. The server now waits for the SDK socket before sending control requests, and the UI renders the actual initial context snapshot instead of masking empty active-session data.

Constraint: CLI /context and desktop get_context_usage must stay on the shared collectContextData/analyzeContextUsage path

Rejected: Hide zero-token active snapshots in the component | that masks backend timing bugs and prevents showing real initial system/tool context

Confidence: high

Scope-risk: narrow

Directive: Do not queue control requests before the SDK socket is connected; let user messages keep the pending outbound behavior

Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "not queue control|context-only|prewarmed empty session|structured session inspection"

Tested: cd desktop && bun run test -- pages.test.tsx --test-name-pattern "EmptySession shows draft context|first-paint spinner|empty live session|live context usage|runtime model"

Tested: bun run check:server

Tested: cd desktop && bun run lint

Tested: real dev API prewarmed empty session returned 31,190 / 262,144 (12%) on first context-only inspection and 16ms on repeat

Tested: browser at http://127.0.0.1:5174/ showed 上下文用量 12% for an empty active session
2026-05-05 20:10:04 +08:00
程序员阿江(Relakkes)
1029c9e7bc fix: align transcript context fallback with cli totals
The live desktop context path already routes through the CLI get_context_usage control request and the shared analyzeContextUsage implementation. The offline transcript fallback was still using its own prompt-token-only estimate, so disconnected sessions could report a lower context total than the live /context path. The fallback now reuses the same current-context total helper and includes output tokens as next-turn context.

Constraint: Desktop must still show context estimates when the CLI process is not running

Rejected: Keep transcript fallback prompt-only | it diverges from the live CLI /context total and can drop after responses

Confidence: high

Scope-risk: narrow

Directive: Transcript context fallback must stay aligned with calculateCurrentContextTokenTotal

Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "context-only|structured session inspection|reconstruct Sonnet 4.6 transcript usage"

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

Tested: bun run check:server
2026-05-05 19:52:48 +08:00
程序员阿江(Relakkes)
f2437bf724 feat: Make diagnostics actionable for runtime failures
Diagnostics exports previously preserved only compact summaries, which made user-uploaded issue bundles hard to debug. This records richer sanitized details from server, CLI, SDK, browser, React, and desktop API failure paths while keeping request bodies and secrets out of client-side reports.

Constraint: Diagnostic bundles must be useful for GitHub issues without including chat contents, file contents, full environments, or API keys.
Rejected: Only expand the Settings UI summary | the exported bundle would still miss hidden runtime failures.
Confidence: high
Scope-risk: moderate
Directive: Keep diagnostics write paths best-effort and non-blocking; do not add request-body capture without a redaction review.
Tested: bun test src/server/__tests__/diagnostics-service.test.ts src/server/__tests__/conversation-service.test.ts
Tested: cd desktop && bun run test src/api/client.test.ts src/__tests__/diagnosticsSettings.test.tsx --run
Tested: bun run check:server
Tested: bun run check:desktop
Tested: agent-browser E2E on ports 37652/41752 captured client_unhandled_rejection and exported a redacted tar.gz bundle
2026-05-05 17:57:50 +08:00
程序员阿江(Relakkes)
2459488703 Harden provider auth, adapter paths, and notification retries
This captures the pending worktree fixes before applying them to the
current local main. The changes tighten IM adapter path and credential
handling, preserve retry behavior for failed desktop notifications, and
make Azure/OpenAI provider auth and stop reasons reflect actual runtime
state.

Constraint: Worktree was detached from an older local main with pending uncommitted fixes
Rejected: Merge the detached HEAD directly | would also replay unrelated stale history
Rejected: Leave notification dedupe as fire-and-forget | failed sends consumed retry keys
Confidence: high
Scope-risk: broad
Directive: Keep adapter absolute-path matching constrained to configured work roots
Tested: git diff --check
Not-tested: full quality gate before local main integration
2026-05-04 21:37:30 +08:00
程序员阿江(Relakkes)
8a81636757 Merge Azure OpenAI auth into local main
Remote main already contains PR #217. Local main had provider context-window and auth-strategy work, so this merge keeps both context resolvers and reconciles the desktop Bun lockfile with the merged desktop package manifest. The accidental remote .nvimlog artifact is excluded from the merge result.

Constraint: Local main was 15 commits ahead and 8 commits behind origin/main after PR #217 was merged remotely
Rejected: Fast-forward pull | local main had unpushed commits
Rejected: Keep remote desktop lockfile verbatim | failed bun install --frozen-lockfile against the merged package.json
Confidence: high
Scope-risk: broad
Directive: Keep provider-configured context windows ahead of OpenAI OAuth model windows so explicit user/provider settings win
Tested: bun install --frozen-lockfile; cd desktop && bun install --frozen-lockfile; git diff --check; bun run check:server; bun run check:desktop; ALLOW_CLI_CORE_CHANGE=1 bun run quality:pr
Not-tested: live provider OAuth login with a real OpenAI account
2026-05-04 21:24:22 +08:00
程序员阿江(Relakkes)
f1c5f86b80 feat: keep IM permission approvals consistent
DingTalk can receive interactive card callbacks, but the card UI still depends on a published template, so the adapter now supports a template-backed card path with text commands as the reliable fallback. Telegram and WeChat use the same allow-once, allow-always, and deny semantics so manual authorization behaves the same across platforms.

Constraint: DingTalk button rendering requires an operator-provided interactive card template id
Rejected: Treat the existing AI streaming card template as a permission card | it cannot guarantee visible action buttons
Confidence: high
Scope-risk: moderate
Directive: Do not remove the text approval fallback unless DingTalk card template provisioning is guaranteed
Tested: bun test adapters/common/__tests__/permission.test.ts adapters/dingtalk/__tests__/permission-card.test.ts adapters/telegram/__tests__/telegram.test.ts adapters/common/__tests__/config.test.ts src/server/__tests__/adapters.test.ts
Tested: bunx tsc -p adapters/tsconfig.json --noEmit
Tested: bun run check:adapters
Tested: cd desktop && bun run build
Tested: bun run check:server
Tested: bun run check:docs
Tested: git diff --check
Not-tested: bun run quality:pr is blocked by existing CLI core approval policy; see artifacts/quality-runs/2026-05-03T13-19-56-232Z/report.md
2026-05-04 19:03:36 +08:00
cynicalight
ff40028ae1 fix: desktop and more test 2026-05-04 17:57:03 +08:00
程序员阿江(Relakkes)
6d9aa98022 Support DingTalk IM without blocking on project history
DingTalk uses QR registration to store client credentials, then reuses the existing IM pairing and session bridge. The merged main implementation keeps the existing WeChat QR binding path intact while adding DingTalk as a peer IM platform. The default IM workdir now falls back to the local user working directory so a newly bound chat can start immediately even when recent-project history is empty.

Constraint: Local main already carries WeChat IM, so the merge keeps WeChat config, QR binding, sidecar args, and unbind behavior intact while adding DingTalk.
Rejected: Keep empty defaultProjectDir as project-picker-only | newly bound IM users can hit a dead end with no recent projects.
Confidence: high
Scope-risk: moderate
Directive: Keep IM platform unions synchronized across config, pairing, sidecar args, desktop settings, and docs.
Tested: bun test common/ dingtalk/ wechat/; bun test src/server/__tests__/adapters.test.ts; cd adapters && bunx tsc --noEmit; bun run check:policy; bun run check:server; bun run check:desktop; bun run check:adapters; bun run check:native; bun run check:docs
Not-tested: quality:pr full gate was blocked by existing local main CLI-core diff requiring allow-cli-core-change maintainer approval; live post-fix DingTalk second-message delivery was not repeated after the merge.
2026-05-03 17:56:22 +08:00
程序员阿江(Relakkes)
99b343d6a1 Merge branch 'feat/wechat-im' 2026-05-03 17:42:31 +08:00
程序员阿江(Relakkes)
eb00c0d501 Merge provider auth strategy into main
Bring the provider context-window, auth-secret masking, and explicit auth-strategy worktree commits onto main after local verification. The merge keeps main's notification and docs history intact while preserving the provider fixes as separate commits.

Constraint: main has diverged with local desktop notification and docs commits, so this cannot be fast-forwarded safely.

Confidence: high

Scope-risk: moderate

Directive: Keep provider auth behavior configured through preset authStrategy rather than implicit env-name guesses.

Tested: ALLOW_CLI_CORE_CHANGE=1 bun run quality:pr

Tested: bun run quality:gate --mode baseline --allow-live --provider-model minimax:main:minimax-main

# Conflicts:
#	desktop/src/pages/Settings.tsx
2026-05-03 17:40:18 +08:00
程序员阿江(Relakkes)
a627bb19f2 feat: support WeChat as a first-class IM channel
WeChat needs a QR-paired path instead of bot-token setup, so the adapter layer now includes the iLink protocol calls, desktop pairing UI, server-side bind/unbind APIs, and shared IM command behavior. Empty project history falls back to the user's default work directory so mobile /new works without pre-opening a desktop project.

Constraint: Tencent iLink login returns a URL that the desktop UI must render as a QR image locally
Constraint: IM adapters should keep /new, /projects, status, permission, and default workdir behavior consistent across WeChat, Feishu, and Telegram
Rejected: Require users to paste absolute project paths for first WeChat sessions | mobile onboarding should work from the default user working directory
Confidence: high
Scope-risk: moderate
Directive: Do not change WeChat polling back to overlapping intervals; getupdates is a long-poll endpoint and must remain serialized
Tested: Real WeChat QR scan, inbound /status, outbound reply, and unbind E2E
Tested: bun run check:adapters
Tested: bun run quality:pr
Not-tested: Re-scan live WeChat after the default-workdir fallback tweak; covered by adapter config tests and PR gate
2026-05-03 17:38:08 +08:00
程序员阿江(Relakkes)
a43460f28d fix: honor provider auth env strategy
Provider presets now carry an explicit auth strategy so Anthropic-compatible services can choose the right Claude Code environment shape instead of relying on one global variable. The desktop editor exposes the same strategy, keeps settings.json previews in sync, and applies the strategy to connection tests as well as runtime env sync.

Constraint: Third-party Anthropic-compatible providers do not agree on ANTHROPIC_API_KEY versus ANTHROPIC_AUTH_TOKEN.

Rejected: Force all third-party providers onto one env var | breaks providers that require bearer auth, dual variables, or dummy local auth.

Confidence: high

Scope-risk: moderate

Directive: Add new provider presets with explicit authStrategy; do not infer auth behavior from model names alone.

Tested: bun test src/server/__tests__/providers.test.ts src/server/__tests__/providers-real.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/conversation-service.test.ts

Tested: cd desktop && bun run lint

Tested: ALLOW_CLI_CORE_CHANGE=1 bun run quality:pr

Tested: bun run quality:gate --mode baseline --allow-live --provider-model minimax:main:minimax-main

Tested: agent-browser provider edit flow on http://127.0.0.1:19811

Not-tested: Live successful calls for every third-party provider with real credentials.
2026-05-03 17:34:39 +08:00