289 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
4e9c6dbda1 Keep cross-platform tray menu imports available
Linux release builds use MenuBuilder for the shared tray menu, while MenuItemBuilder and SubmenuBuilder are only used in the macOS native menu bar. Gate only the macOS-only imports so Linux builds no longer warn about them and still compile the shared tray path.

Constraint: Linux builds compile the shared tray setup path and require MenuBuilder

Constraint: MenuItemBuilder and SubmenuBuilder are only referenced inside cfg(target_os = "macos")

Rejected: Gate the whole tauri::menu import on macOS | Linux still needs MenuBuilder for tray menu construction

Confidence: high

Scope-risk: narrow

Directive: Do not gate MenuBuilder by platform unless setup_system_tray is also made platform-specific

Tested: cargo fmt --check

Tested: git diff --check

Not-tested: Local Linux cargo check beyond system GTK/WebKit pkg-config setup; GitHub release Linux job is the verification surface
2026-05-05 23:27:26 +08:00
程序员阿江(Relakkes)
49bfaba64f Keep release builds free of CI warnings
Release logs showed two warning classes after the packaging fixes: Linux builds warned about macOS-only menu imports, and tauri-action reported an unknown releaseAssetNamePattern input. Gate the native menu imports to macOS and use the action's supported assetNamePattern input so release logs stay clean and asset naming is actually applied.

Constraint: Linux release builds compile the shared Tauri lib without macOS-only menu usage
Constraint: tauri-action v0 accepts assetNamePattern, not releaseAssetNamePattern
Rejected: Ignore warning-only output | release candidates should not hide real signal behind avoidable warnings
Confidence: high
Scope-risk: narrow
Directive: Keep workflow input names aligned with tauri-action's published action schema
Tested: cargo fmt --check
Tested: cargo check --target aarch64-apple-darwin
Tested: git diff --check
Not-tested: Full GitHub release workflow after retag before pushing
2026-05-05 23:21:22 +08:00
程序员阿江(Relakkes)
97da3ae180 Build macOS notification bridge for the target arch
The macOS notification bridge is compiled by build.rs outside Cargo's Rust target handling. On Apple Silicon, clang defaulted macos_notifications.o to arm64 even when Cargo was building x86_64, so the x64 release job ignored the object and missed the exported notification symbols.

Constraint: The ObjC bridge is linked manually through cargo:rustc-link-arg
Constraint: Release workflow builds both aarch64-apple-darwin and x86_64-apple-darwin from macOS runners
Rejected: Rely on clang default architecture | Apple Silicon defaults arm64 and breaks x86_64 linking
Confidence: high
Scope-risk: narrow
Directive: Keep native ObjC bridge compilation aligned with Cargo TARGET when adding platform bridge files
Tested: cargo fmt --check
Tested: git diff --check
Tested: cargo check --target aarch64-apple-darwin
Tested: cargo build --target x86_64-apple-darwin --release
Tested: file target/x86_64-apple-darwin/release/.../macos_notifications.o reports Mach-O 64-bit object x86_64
Not-tested: Full GitHub release workflow after retag before pushing
2026-05-05 23:04:12 +08:00
程序员阿江(Relakkes)
47e41d68e3 Prepare the desktop 0.2.1 release
This records the user-facing 0.2.1 release notes and aligns the desktop package, Tauri config, Cargo manifest, and lockfile package version so the tag-triggered release workflow can publish the intended build.

Constraint: GitHub Release body is sourced from release-notes/v0.2.1.md in the tagged commit
Constraint: Keep provider and OpenAI login details weak in the release narrative because this release is centered on IM, notifications, context usage, and desktop stability
Rejected: Run scripts/release.ts directly | it creates a generic commit message and tag before review of the release narrative
Confidence: high
Scope-risk: narrow
Directive: Do not tag v0.2.1 from a commit that lacks release-notes/v0.2.1.md or mismatched desktop version files
Tested: bun run scripts/release.ts 0.2.1 --dry
Tested: cargo check
Tested: git diff --check
Not-tested: Live release gate with real provider credentials in this commit step
2026-05-05 22:47:37 +08:00
程序员阿江(Relakkes)
5cc67b725b fix: isolate desktop IM adapter sidecars
Telegram polling stopped consuming updates when all IM adapters were loaded into the same desktop sidecar process. Launch each IM platform as its own sidecar process so Telegram keeps an isolated long-polling consumer while Feishu, WeChat, and DingTalk manage their own SDK loops independently.

Constraint: Telegram Bot API long polling needs one healthy consumer per token and should not share lifecycle with other IM SDKs
Rejected: Keep one combined adapter process | reproduced pending Telegram updates until Telegram was launched alone
Confidence: high
Scope-risk: moderate
Directive: Keep IM adapter process ownership isolated unless cross-platform lifecycle tests prove a merged process is safe
Tested: cargo fmt --check
Tested: cargo check
Tested: bun run check:native
Tested: ./desktop/scripts/build-macos-arm64.sh
Tested: Computer Use launched built app and sent Telegram smoke message with pending_update_count=0
Not-tested: Automated Feishu, WeChat, or DingTalk live message delivery after process split
2026-05-05 22:32:17 +08:00
程序员阿江(Relakkes)
c4d4568783 fix: prevent stale IM adapter sidecars
Telegram long polling can be consumed or disrupted by orphaned adapter sidecar processes left behind after desktop restarts or IM settings refreshes. Kill stale Unix claude-sidecar adapters processes before launching a new managed adapter sidecar so only one Telegram consumer remains active.

Constraint: Telegram Bot API long polling should have a single active consumer for a token
Rejected: Only restart the current tracked child | orphaned sidecars with PPID 1 are outside the tracked Tauri child handle
Confidence: high
Scope-risk: narrow
Directive: Keep adapter sidecar startup single-instance across platforms when adding new IM adapters
Tested: cargo fmt --check
Tested: cargo check
Tested: bun run check:native
Tested: git diff --check
Not-tested: Packaged macOS app relaunch with a real stale sidecar during automated test
2026-05-05 22:20:03 +08:00
程序员阿江(Relakkes)
4ab2ef434e fix: Surface completed desktop agent replies outside the app
Desktop users already receive native notifications for permission prompts, but long-running turns can finish with only a final Markdown reply while the app is out of focus. The completion path now treats a non-empty assistant reply as a notifiable terminal event and reuses the existing desktop notification settings, dedupe, and cooldown behavior.

Constraint: Notification permission must still be controlled by the existing desktopNotificationsEnabled setting and native OS authorization.
Rejected: Send from status idle events | idle is also used by prewarm, clear, stop, and other non-reply transitions.
Rejected: Notify on every message_complete | empty completions and post-stop tail completions would create noisy false positives.
Confidence: high
Scope-risk: narrow
Directive: Keep completion notifications tied to finalized assistant text, not generic idle/status transitions.
Tested: bun run test -- src/stores/chatStore.test.ts
Tested: bun run check:desktop
Not-tested: Manual macOS notification center click-through behavior
2026-05-05 20:58:13 +08:00
程序员阿江(Relakkes)
82c454e4dc Merge commit '5c5255b4926b0c5539f585950ffe9a8a1181544a' 2026-05-05 20:33:33 +08:00
程序员阿江(Relakkes)
5c5255b492 fix: make macOS notification delivery verifiable
Desktop notifications were enabled by default and depended on the Tauri notification plugin for both permission state and delivery. On macOS the plugin reports desktop permission as granted and can hide foreground delivery failures, so authorization prompts could appear in the app without a real system notification.

This moves macOS permission and delivery through a native UserNotifications bridge, keeps notifications opt-in by default, and sends a test notification after successful authorization.

Constraint: Tauri notification plugin desktop permission state is always granted.
Constraint: macOS foreground delivery needs explicit native presentation handling.
Rejected: Keep using the plugin with retries | it still cannot report real macOS permission or delivery failures.
Confidence: high
Scope-risk: moderate
Directive: Do not remove the macOS bridge without verifying foreground banners from an installed app bundle.
Tested: cd desktop && bun run test --run src/lib/desktopNotifications.test.ts src/stores/settingsStore.test.ts src/__tests__/generalSettings.test.tsx src/stores/chatStore.test.ts
Tested: bun run check:desktop
Tested: bun run check:native
Tested: SKIP_INSTALL=1 ./scripts/build-macos-arm64.sh
Tested: codesign --verify --deep --strict --verbose=2 desktop/build-artifacts/macos-arm64/Claude Code Haha.app
Tested: hdiutil verify desktop/build-artifacts/macos-arm64/Claude Code Haha_0.2.0_aarch64.dmg
Tested: Computer Use macOS Settings and Bash authorization notifications, confirmed usernoted displayed banners.
Not-tested: Windows toast delivery on a real installed Windows build.
2026-05-05 20:33:12 +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)
1e5bd47fe6 Merge commit '622b94011ff962fc80f010d98b4dab9132834878' 2026-05-05 19:59:03 +08:00
程序员阿江(Relakkes)
fb90957003 fix: keep empty live contexts pending in desktop composer
A newly opened desktop session can return a live context snapshot before any
prompt content has been counted. When that snapshot is all zeroes, rendering it
as 0% makes the first real context update look like an unexplained jump. The
composer now keeps that empty live snapshot in the pending state while still
using its model metadata.

Constraint: Live context snapshots can be initialized before any user-visible context exists
Rejected: Render 0% for zero-token live snapshots | it repeats the misleading empty-session state
Confidence: high
Scope-risk: narrow
Directive: Do not show numeric context usage for empty zero-token sessions
Tested: cd desktop && bun run test -- pages.test.tsx
Tested: cd desktop && bun run lint
2026-05-05 19:36:18 +08:00
程序员阿江(Relakkes)
71f851d60a fix: clear DingTalk bot credentials through explicit unbind
DingTalk bot unbind was routed through the generic adapter config update,
but undefined credential fields are dropped during JSON serialization. That
left stored Client ID and Secret values intact after clicking the unbind
button. Match the working WeChat path with a dedicated server endpoint and
frontend API call so credential removal is explicit.

Constraint: JSON request bodies cannot preserve undefined fields for generic config clearing
Rejected: Keep using updateConfig with undefined fields | serialized requests omit the fields before the server can clear them
Confidence: high
Scope-risk: narrow
Directive: Keep credential-clearing flows on explicit unbind endpoints rather than relying on partial config merges
Tested: bun test src/server/__tests__/adapters.test.ts
Tested: cd desktop && bun run test src/stores/adapterStore.test.ts
Tested: bun run check:desktop
Tested: bun run check:server
Not-tested: bun run quality:pr is blocked by repository policy requiring allow-cli-core-change approval for the broader branch impact
2026-05-05 19:30:43 +08:00
程序员阿江(Relakkes)
432a58d725 Merge project terminal workflow into local main
Bring the detached worktree terminal improvements into the local main line so desktop sessions can open a bottom terminal in the current project directory and still promote it to a full tab when needed.

Constraint: Local main already contains additional desktop fixes after the worktree base
Confidence: high
Scope-risk: moderate
Tested: bun run check:desktop
Tested: git diff --check
Not-tested: bun run quality:pr is blocked by existing branch policy requiring allow-cli-core-change approval
2026-05-05 19:05:53 +08:00
程序员阿江(Relakkes)
35f9f0d0f8 feat: make project terminals open where users work
Desktop terminal access should behave like an IDE: active project sessions open a bottom panel in the session working directory while keeping a full terminal tab available for dedicated use. The panel has constrained resizing and cleanup so session tab state remains isolated, and terminal guidance points users to the bundled claude-haha command for extension setup.

Constraint: Desktop bundles the user-facing CLI as claude-haha while claude-sidecar remains internal
Rejected: Always opening a standalone terminal tab | loses the current project context and diverges from common IDE behavior
Rejected: Exposing claude-sidecar in terminal guidance | it is an internal launcher, not the supportable user command
Confidence: high
Scope-risk: moderate
Directive: Keep bottom terminals keyed by session id and pass session workDir/projectPath into spawned terminals
Tested: bun run check:desktop
Tested: git diff --check
Tested: Computer Use E2E against built macOS app during implementation
Not-tested: bun run quality:pr is blocked by existing branch policy requiring allow-cli-core-change approval
2026-05-05 19:05:36 +08:00
程序员阿江(Relakkes)
ac342f4bcd Merge commit 'e4f9825bc116e88487d3c479e4e7afc1ec3a34fe' 2026-05-05 18:26:05 +08:00
程序员阿江(Relakkes)
e4f9825bc1 fix: avoid misleading context loading on empty desktop sessions
The desktop composer now treats draft and not-yet-running sessions as pending
until a real CLI context snapshot exists. Context inspection has a lightweight
context-only path so the composer and /context panel do not wait on unrelated
usage or MCP status work, and desktop boot no longer blocks the first shell
render on tab restoration.

Constraint: Empty composer state has no live CLI context to inspect until a session starts
Rejected: Display 0% before live context exists | it implied one user message consumed the fixed prompt/tool baseline
Confidence: high
Scope-risk: moderate
Directive: Do not show numeric context usage without a real context snapshot
Tested: cd desktop && bun run test -- pages.test.tsx
Tested: cd desktop && bun run lint
Tested: bun run check:desktop
Tested: bun run check:server
Tested: Browser reload at http://127.0.0.1:5174 with cleared open-tabs showed pending context and no /inspection request
2026-05-05 18:25:53 +08:00
程序员阿江(Relakkes)
851b33ab70 Merge actionable diagnostics logging into main
Bring the runtime diagnostics worktree back onto local main while preserving the existing local main commits for provider context windows and IM localization.

Constraint: Preserve both independent local main commits and the diagnostics worktree commit.
Confidence: high
Scope-risk: moderate
Directive: Keep diagnostics capture non-blocking and sanitized when modifying this area again.
Tested: merged cleanly on local main after prior check:server, check:desktop, and agent-browser diagnostics export verification
2026-05-05 17:59:46 +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)
dfc7ee6f91 Keep IM adapter labels fully localized
The Chinese settings UI should use localized platform names directly instead of appending English names in parentheses, which made the tabs look visually awkward.

Constraint: Only the Chinese locale needed this presentation adjustment
Confidence: high
Scope-risk: narrow
Reversibility: clean
Tested: cd desktop && bunx vitest run src/i18n/index.test.tsx
Not-tested: Full desktop quality gate, because this is a two-string locale-only change
2026-05-05 17:15:29 +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)
37845e5534 Merge commit '59436ab' 2026-05-04 21:25:55 +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)
472ff73927 Stabilize OpenAI auth PR quality gates
PR 217 combined OpenAI OAuth model options with env-configured provider models, but the picker path returned before appending third-party model aliases. The desktop workspace test also exercised Prism highlighting for every expanded line, which was costly enough to time out on CI runners. The docs job did not need the root React Vite plugin; the desktop package owns that dependency.\n\nConstraint: PR Quality must pass server, desktop, and docs jobs before merge.\nRejected: Increase Vitest timeout | keeps the expensive render path and hides the CI regression.\nRejected: Add root Vite 8 peer dependencies | root only builds VitePress docs; React Vite plugin belongs in desktop/.\nConfidence: high\nScope-risk: narrow\nTested: npm ci --ignore-scripts; npm run docs:build; bun test src/server/__tests__/settings.test.ts src/server/__tests__/conversation-service.test.ts; bun run check:server; bun run check:desktop\nNot-tested: live provider OAuth login
2026-05-04 21:10:08 +08:00
程序员阿江(Relakkes)
59436abf09 Show accurate desktop context usage in composer
Provider model context windows now feed the composer-level context indicator, so users can see current usage without opening slash panels. The indicator refreshes when the session runtime model changes, keeps a stable loading placeholder, and marks estimate fallback data during reconnect or compaction windows.

Constraint: The desktop UI must use the real session inspection API and session-scoped runtime selection instead of mocked or static context values.
Rejected: Keep context details only in /context or /status | the user explicitly wanted an always-visible composer indicator.
Rejected: Reuse stale context after model switches | different provider windows make identical percentages misleading.
Confidence: high
Scope-risk: moderate
Directive: Do not remove the runtimeSelectionKey refresh path without real multi-provider browser verification.
Tested: cd desktop && bun run test -- pages.test.tsx
Tested: bun run check:desktop
Tested: KEEP_ARTIFACTS=1 desktop/scripts/e2e-context-usage-live-agent-browser.sh
Not-tested: Live browser E2E with every configured provider in the committed script; separate agent-browser sweep verified four providers locally.
2026-05-04 21:07:01 +08:00
程序员阿江(Relakkes)
0a82efdcd9 fix: keep desktop permission prompts visible
Desktop notification permission can appear granted while macOS still suppresses a foreground banner, so blocking permission prompts now also request OS-level window attention. The notification sender keeps the native notification path, but prompt callers can ask the window manager for attention when silence would block user progress.

The desktop package also declares the existing qrcode runtime dependency used by AdapterSettings so production desktop builds can resolve that import.

Constraint: Tauri window attention requires an explicit capability grant in packaged builds.
Constraint: macOS may suppress foreground notification banners even when notification APIs report success.
Rejected: Replace native notifications with a custom in-app sound or overlay | the notification feature should stay OS-owned and already has an in-app permission card.
Confidence: high
Scope-risk: narrow
Directive: Keep requestAttention limited to blocking prompts unless another flow truly needs persistent OS attention.
Tested: bun run test -- src/lib/desktopNotifications.test.ts src/stores/chatStore.test.ts
Tested: bun run check:desktop
Tested: bun run check:native
Tested: git diff --check
Not-tested: bun run quality:pr | blocked by existing branch-wide CLI core policy requiring allow-cli-core-change approval
2026-05-04 19:05:04 +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)
2ca5228171 feat: make IM adapter behavior consistent
WeChat and DingTalk were using different pairing, attachment, and response
state paths, which made the new IM channels behave differently from Feishu
and Telegram. Align the shared pairing model, wire inbound media into the
existing attachment bridge, and map platform response capabilities to their
real APIs: WeChat block streaming plus typing, DingTalk AI Card streaming.

Constraint: WeChat iLink exposes typing and block streaming, but no editable message/card streaming API
Constraint: DingTalk streaming depends on the AI Card create/deliver/stream/finalize lifecycle
Rejected: Fake DingTalk typing with standalone markdown | it would add chat noise instead of platform state
Rejected: Auto-pair WeChat after QR login | it bypasses the shared IM pairing model
Confidence: high
Scope-risk: moderate
Directive: Keep WeChat streaming as block-send unless iLink adds editable messages; keep DingTalk streaming on AI Card APIs
Tested: bun run check:adapters; bun run check:server; cd desktop && bun run test src/stores/adapterStore.test.ts; cd desktop && bun run build; bunx tsc -p adapters/tsconfig.json --noEmit; git diff --check
Not-tested: Live WeChat and DingTalk platform smoke with real production credentials
2026-05-03 21:08:12 +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
程序员阿江(Relakkes)
299c50a1e0 fix: hide provider auth env secrets
Provider settings JSON previously masked only values that matched the current form API key. Switching providers or editing stale settings could leave ANTHROPIC_API_KEY visible while ANTHROPIC_AUTH_TOKEN was masked, even though both are sensitive auth env vars.

The settings preview now masks Anthropic API key and auth token fields by key name, restores placeholders from the previous JSON value per field, and strips provider-managed env vars before merging the active provider preview. This keeps historical provider auth values from leaking into the editable JSON surface.

Constraint: Claude Code uses ANTHROPIC_API_KEY for x-api-key auth and ANTHROPIC_AUTH_TOKEN for Bearer auth, so the fix keeps runtime semantics separate from UI redaction.

Rejected: Collapse all providers onto one env var | direct Anthropic and gateway auth paths have different documented headers.

Confidence: high

Scope-risk: narrow

Directive: Treat provider auth env vars as secrets by field name in UI surfaces, not by comparing against the current form API key.

Tested: cd desktop && bun run test -- src/lib/__tests__/providerSettingsJson.test.ts

Tested: cd desktop && bun run lint

Tested: bun run check:desktop

Tested: agent-browser opened DeepSeek provider edit modal and verified Settings JSON shows ANTHROPIC_AUTH_TOKEN as placeholder with no ANTHROPIC_API_KEY entry.
2026-05-03 17:02:56 +08:00
程序员阿江(Relakkes)
8711ba1560 fix: configure provider context windows
Teach provider presets and saved providers to carry per-model context windows so auto-compact uses provider-specific limits instead of a blanket fallback. The desktop provider form now keeps these limits in an advanced context section and syncs the generated settings preview with model changes.

Constraint: Third-party provider APIs do not consistently expose machine-readable model context windows.
Rejected: Keep a single 100K/200K fallback | modern provider windows vary from 128K to 1M+ and the fallback caused late or early compaction.
Confidence: high
Scope-risk: moderate
Directive: Do not change provider compact thresholds without re-running real provider long-context checks.
Tested: bun test src/services/compact/autoCompact.test.ts; bun test src/server/__tests__/provider-presets.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/providers-real.test.ts; bun run check:server; bun run check:desktop; bun run check:policy; bun run check:native; MiniMax/Kimi/DeepSeek live long-context probes; agent-browser provider form flow.
Not-tested: quality:pr policy gate still requires explicit allow-cli-core-change for CLI core edits.
2026-05-03 16:57:08 +08:00
程序员阿江(Relakkes)
fa5fda24d0 feat: notify users when desktop attention is needed
Add native system notifications as a desktop-wide attention channel for permission prompts and scheduled task completion. The implementation keeps notification presentation owned by the OS, adds a user-facing enable switch with permission handling, and lets scheduled tasks choose desktop notifications without routing that channel through IM adapters.

Constraint: Notifications must use OS-native APIs without custom sound playback.
Constraint: Desktop channel is local-only and must not be sent through IM adapter delivery.
Rejected: Browser Notification API | not reliable inside the packaged Tauri desktop runtime.
Rejected: Treat desktop as an IM channel | would leak a local-only channel into server-side adapter sending.
Confidence: high
Scope-risk: moderate
Directive: Keep notification styling at the OS layer; business code should only provide title, body, dedupe, and routing decisions.
Tested: bun run check:desktop
Tested: bun run quality:pr
Tested: Computer Use macOS debug app verification for settings toggle, permission prompt, scheduled task desktop channel, and task-run polling dedupe
Not-tested: Windows and Linux native runtime smoke tests on physical hosts
2026-05-03 16:45:32 +08:00
程序员阿江(Relakkes)
7a5f813601 Prepare the desktop 0.2.0 milestone for release
This release marks the desktop app's shift from a thin CLI wrapper toward a fuller local Coding Agent workspace. It carries the reviewed v0.2.0 release notes, bumps desktop package metadata, and refreshes Cargo.lock from the pinned Tauri stack before publishing the tag-driven GitHub Actions release.

Constraint: GitHub Release body is sourced from release-notes/v0.2.0.md in the tagged commit
Constraint: Desktop releases are built remotely from the pushed v0.2.0 tag
Rejected: Publish as v0.1.10 | the release consolidates several desktop workflow and quality-gate milestones, so v0.2.0 better communicates the scope
Confidence: high
Scope-risk: narrow
Directive: Keep the v0.2.0 tag on this commit unless the release notes or version metadata are changed together
Tested: bun run scripts/release.ts 0.2.0 --dry
Tested: bun run quality:gate --mode release --allow-live --provider-model codingplan:main:codingplan-main --provider-model minimax:main:minimax-main (18 passed, 0 failed, 0 skipped)
2026-05-02 18:11:20 +08:00
Relakkes Yang
9eb7da5377 fix: preserve historical workspace changes on windows 2026-05-02 17:53:24 +08:00
程序员阿江(Relakkes)
0b87fd0f7e Merge commit '071975e0cc007f88e2424dc86d3310992cf1eb41' 2026-05-02 12:42:19 +08:00
程序员阿江(Relakkes)
071975e0cc Improve desktop failure diagnosis with exportable logs
Desktop failures were previously hard to debug from issue reports because server-side and CLI startup details were only partially visible in the UI. This adds a dedicated cc-haha diagnostics store with sanitized structured events, runtime error summaries, a Settings diagnostics view, and an exportable bundle that users can attach to reports.

Constraint: Diagnostic exports must not include chat content, file contents, full environment variables, API keys, bearer tokens, cookies, or OAuth tokens.
Rejected: Export raw server logs | easier to debug but too likely to leak secrets and private workspace data.
Rejected: Keep diagnostics only in transient UI errors | still leaves maintainers unable to diagnose later GitHub issues.
Confidence: high
Scope-risk: moderate
Directive: Do not add raw transcript, prompt, attachment, or environment dumps to diagnostics without a separate privacy review.
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/diagnostics-service.test.ts
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/conversation-service.test.ts
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/conversations.test.ts
Tested: cd desktop && bun run test src/__tests__/diagnosticsSettings.test.tsx --run
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: agent-browser E2E on local server/dev UI for CLI startup failure, provider test failure, diagnostics tab, copy summary, export bundle, and tar/secret scan
Not-tested: Destructive clear-logs button in browser E2E; local deletion was intentionally not clicked.
2026-05-02 12:41:31 +08:00
程序员阿江(Relakkes)
fe303c7a91 Merge session sidebar stability fixes 2026-05-02 12:05:07 +08:00
程序员阿江(Relakkes)
d50268c07c fix: prevent session sidebar stalls and title churn
Large desktop histories were making session discovery parse every JSONL
before pagination, while automatic title updates could still overwrite
manual names during resumed sessions. This keeps listing bounded to the
requested page, preserves custom titles, and blocks deleted placeholder
sessions from being recreated by prewarm startup.

Constraint: Desktop session storage remains JSONL-compatible with the CLI
Rejected: Virtualize the sidebar in this patch | does not fix backend JSONL parsing cost
Rejected: Disable title generation globally | would regress useful titles for unnamed sessions
Confidence: high
Scope-risk: moderate
Directive: Do not reintroduce all-file JSONL parsing on /api/sessions list paths without a heavy-session benchmark
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/title-service.test.ts src/server/__tests__/sessions.test.ts
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/conversations.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: heavy local preview with 240 sessions, 320 messages each, and 40 restored tabs
Not-tested: native packaged desktop runtime under Windows with the same heavy fixture
Related: https://github.com/NanmiCoder/cc-haha/issues/237
Related: https://github.com/NanmiCoder/cc-haha/issues/248
2026-05-02 12:04:51 +08:00
程序员阿江(Relakkes)
b86c7f1ea2 Merge verified DeepSeek provider fix into main
The fix was developed and UI-verified in a detached Codex worktree, then merged locally so main carries the same tested request-shape behavior.

Constraint: User requested local main integration without pushing

Confidence: high

Scope-risk: narrow

Tested: git status before merge was clean

Tested: merged commit verification retained in history

Not-tested: Post-merge full suite
2026-05-02 12:00:35 +08:00
程序员阿江(Relakkes)
a5986eca7e Prevent DeepSeek disabled-thinking effort conflicts
DeepSeek-compatible Anthropic endpoints reject requests that combine an explicit disabled-thinking block with an effort value. The desktop UI can create that shape when users disable thinking and keep medium effort selected, so the request builder now omits effort whenever it will send explicit disabled thinking.

Constraint: DeepSeek-compatible Anthropic endpoints reject disabled thinking with effort

Rejected: Only patch Desktop provider settings | hidden title and side request paths still share the request builder

Confidence: high

Scope-risk: narrow

Directive: Keep explicit disabled-thinking providers from sending effort unless the upstream contract changes

Tested: UI repro on pre-fix DeepSeek provider path reproduced the 400

Tested: desktop/scripts/e2e-deepseek-thinking-ui-agent-browser.sh

Tested: bun test src/utils/__tests__/thinking.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/title-service.test.ts

Tested: git diff --check

Not-tested: Real DeepSeek API key live call
2026-05-02 12:00:22 +08:00
程序员阿江(Relakkes)
1d4d87a55e fix: Prevent light inspector panels in dark theme
The session inspector reused a one-off light palette, so /status, /cost,
and /context could render bright panels inside the dark desktop shell.
This moves the inspector and MCP switch control onto theme-scoped tokens
while preserving the existing light-theme look.

Constraint: Desktop dark mode must keep the existing surface hierarchy and avoid changing global brand colors.
Rejected: Recolor the shared Material palette | too broad for a component-specific regression.
Confidence: high
Scope-risk: narrow
Directive: Keep slash inspector surfaces on semantic theme tokens; do not reintroduce fixed light hex classes.
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test src/__tests__/pages.test.tsx src/__tests__/mcpSettings.test.tsx
Tested: cd desktop && bun run build
Tested: agent-browser screenshots for /status, /usage, /context, and MCP settings on http://127.0.0.1:5184/
2026-05-02 11:46:42 +08:00
程序员阿江(Relakkes)
c13fa75c3b Keep v0.1.9 release builds on a compatible Tauri stack
The release script regenerated Cargo.lock after Tauri 2.11 became available, while the desktop Bun lock still resolves @tauri-apps/api and CLI to 2.10.1. Tauri's build preflight rejects that major/minor mismatch on every platform, so the Rust Tauri release stack is now pinned to the 2.10 combination already used by the previous successful release.

Constraint: v0.1.9 must keep the existing desktop Bun lock and JS Tauri packages at 2.10.1
Constraint: scripts/release.ts runs cargo generate-lockfile during release preparation
Rejected: Upgrade JS @tauri-apps packages during the release fix | larger dependency surface and unnecessary for the failed workflow
Rejected: Pin only the tauri crate | cargo still selected tauri-runtime 2.11.0, causing Rust API type mismatches
Confidence: high
Scope-risk: narrow
Directive: Keep Rust and JS Tauri major/minor versions aligned before moving release tags
Tested: gh run view 25217609687 --log-failed
Tested: cd desktop/src-tauri && cargo generate-lockfile
Tested: cd desktop && bunx tauri build --target aarch64-apple-darwin --config src-tauri/tauri.release-ci.json --no-bundle
Tested: cd desktop/src-tauri && cargo check
Not-tested: Full GitHub Actions matrix after retag
2026-05-01 22:26:18 +08:00
程序员阿江(Relakkes)
388c80a962 Prepare v0.1.9 for desktop release
The release collects the post-v0.1.8 desktop workspace manager work, provider compatibility fixes, WebSearch fallback support, and desktop lifecycle hardening into a tagged GitHub Actions release.

Constraint: GitHub Release body is sourced from release-notes/v0.1.9.md in the tagged commit
Constraint: The release script owns version bumps for desktop/package.json, Tauri config, Cargo.toml, and Cargo.lock
Rejected: Push the script-generated generic release commit | it would violate the repository Lore commit protocol
Confidence: high
Scope-risk: narrow
Directive: Do not move v0.1.9 without rerunning the release preflight and verifying the tag commit contains release-notes/v0.1.9.md
Tested: bun run scripts/release.ts 0.1.9 --dry
Tested: bun run scripts/release.ts 0.1.9
Tested: cd desktop/src-tauri && cargo check
Not-tested: GitHub Actions release workflow before tag push
2026-05-01 22:13:49 +08:00
Relakkes Yang
465e043563 fix: hide blank assistant message bubbles 2026-05-01 22:09:55 +08:00
程序员阿江(Relakkes)
103a6cc42b fix: restore per-turn changed file cards
The chat timeline lost per-turn changed file cards when the visible user message ids did not match persisted transcript ids, and sessions without SDK file-history snapshots had no fallback source for turn changes. Match live cards by stable user-message index when needed and derive checkpoint previews from transcript tool calls when snapshots are absent.

Constraint: Right-side workspace changes already derive from transcript tool calls, so chat checkpoint data must remain consistent with that source.
Rejected: Force a history reload after every turn | would hide the id mismatch but add churn and still not cover transcript-only sessions.
Confidence: high
Scope-risk: moderate
Directive: Keep snapshot checkpoints as the preferred source, and use transcript extraction only as the compatibility fallback.
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: bun test src/server/__tests__/workspace-service.test.ts
Tested: cd desktop && bun run test src/components/chat/MessageList.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test
Tested: git diff --check
Not-tested: Browser E2E against a live model session.
2026-05-01 21:43:17 +08:00