1094 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
d7eef0ea51 fix(release): align Linux package smoke artifacts
Match Electron Builder Linux output by accepting linux-*-unpacked directories,
treating AppImage blockmaps as optional, and validating release asset names
against the generated x86_64/amd64 and arm64 artifacts.

Tested: bun test scripts/quality-gate/package-smoke/index.test.ts
Tested: bun test scripts/pr/release-workflow.test.ts scripts/quality-gate/package-smoke/index.test.ts
Tested: bun run check:policy
Tested: bun run check:native
Tested: bun run verify
Confidence: high
Scope-risk: moderate
2026-06-03 20:19:07 +08:00
程序员阿江(Relakkes)
79d8468580 fix(release): add Linux deb package metadata
Ensure Electron Builder has the project URL and maintainer metadata required by Linux deb targets, and lock the fields with release workflow coverage.

Tested: bun test scripts/pr/release-workflow.test.ts
Tested: bun run check:policy
Tested: bun run check:native
Tested: bun run verify
Confidence: high
Scope-risk: narrow
2026-06-03 19:55:10 +08:00
程序员阿江(Relakkes)
12c67f7137 chore(git-hooks): make pre-push checks non-blocking
Replace the local pre-push quality gate with a reminder-only hook, keep manual quality commands documented, and update the contract test to prevent reintroducing a blocking push gate.

Tested: bash .git/hooks/pre-push </dev/null
Tested: bun test scripts/git-hooks/install.test.ts scripts/pr/quality-contract.test.ts
Tested: bun run check:policy
Tested: bun run check:docs
Tested: git diff --check
Confidence: high
Scope-risk: narrow
2026-06-03 19:22:14 +08:00
程序员阿江(Relakkes)
e8bc9e9342 fix(server): avoid fixed test server ports
Use OS-assigned ports for server integration tests and publish the actual Bun server port after startup, preventing local port collisions from failing server checks.

Tested: bun test src/server/__tests__/e2e/business-flow.test.ts
Tested: bun test src/server/__tests__/e2e/full-flow.test.ts src/server/__tests__/conversations.test.ts src/server/__tests__/tasks.test.ts src/server/__tests__/haha-openai-oauth-api.test.ts
Tested: bun run check:server
Confidence: high
Scope-risk: narrow
2026-06-03 19:22:05 +08:00
程序员阿江(Relakkes)
f567236330 fix(desktop): improve activity summary layout
Use container queries for the activity summary grid so the Token usage panel responds to its own width instead of the full desktop viewport. This prevents loose medium-width layouts and over-compressed five-column cards when the settings page is shown with sidebars.

Tested:
- cd desktop && bun run test -- src/pages/ActivitySettings.test.tsx --run --reporter=verbose --pool=forks --maxWorkers=1 --minWorkers=1
- cd desktop && bun run test -- src/theme/globals.test.ts --run --reporter=verbose --pool=forks --maxWorkers=1 --minWorkers=1
- bun run check:desktop
- Electron smoke at 1180px and 900px against the local dev server

Not-tested:
- Coverage report; this is a presentation-only desktop UI change.

Confidence: high
Scope-risk: narrow
2026-06-03 18:28:17 +08:00
程序员阿江(Relakkes)
eaa940ab90 fix(desktop): restore sidebar titlebar dragging
The sidebar title area also needs to participate in Electron's CSS app-region chrome. Mark only the sidebar title/header region as draggable and keep the full sidebar body out of the drag region so session rows, search controls, and project actions remain normal interactions.

Constraint: Electron window dragging is driven by CSS app-region regions after the migration
Rejected: Keep the sidebar-wide startDragging mouse handler | Electron does not use that as the active drag path and it misses the left title gap
Confidence: high
Scope-risk: narrow
Directive: Keep sidebar body interactions outside the drag region unless a real titlebar affordance is added there
Tested: cd desktop && bun run test src/components/layout/Sidebar.test.tsx --run
Tested: bun run check:desktop
2026-06-03 16:38:00 +08:00
程序员阿江(Relakkes)
aed3e7d038 fix(release): restore quarantine quality gates
Separate quarantine review enforcement from server and coverage file selection so expired review dates fail only the governance lane.

Refresh stale server quarantine suites and keep only the live provider test quarantined for non-live PR gates.

Tested: bun run check:policy
Tested: bun run check:server
Tested: bun run check:coverage
Tested: bun run verify
Tested: git diff --check
Confidence: high
Scope-risk: moderate
2026-06-03 15:11:47 +08:00
程序员阿江(Relakkes)
9322d9aba3 chore(desktop): leave notification permission code unchanged
Drop the explanatory comment added earlier - notifications work as-is, so the
notification service stays byte-for-byte identical to main.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:17:14 +08:00
程序员阿江(Relakkes)
7e1e1b4ae6 fix(desktop): add a conservative Content-Security-Policy
Adds a CSP meta tag that hardens default-src/object-src/base-uri while keeping
script/style 'unsafe-inline'+'unsafe-eval' (Emotion CSS-in-JS injects runtime
<style> tags, the startup watchdog is inline, shiki/mermaid/Vite use eval) and a
permissive connect-src (localhost sidecar + ws + https) so renderer fetches and
dev HMR keep working. Needs a runtime smoke on dev + packaged builds before any
tightening.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:17:14 +08:00
程序员阿江(Relakkes)
7a882d1858 fix(desktop): forward Windows PowerShell choice to agent sidecar
- serverRuntime injects CLAUDE_CODE_POWERSHELL_PATH from the user's chosen shell
  (readDesktopTerminalConfig + resolveDesktopTerminalShell) on Windows, so the
  agent PowerShellTool honors the same shell as the UI terminal. Best-effort:
  never blocks startup, never overrides an explicit env var, only forwards
  pwsh/powershell selections (not cmd/custom). Regression from the Tauri build.
- document that notificationPermissionState reflects OS capability, not macOS
  authorization (no Electron API exists; the 'failed' lifecycle is the real
  signal) instead of calling the non-existent systemPreferences.getNotificationSettings

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:17:13 +08:00
程序员阿江(Relakkes)
f070d16d38 fix(desktop): kill sidecars synchronously on quit to avoid orphans
killSidecar gains a sync flag (spawnSync taskkill on Windows); serverRuntime
stopAll threads it through; before-quit now shuts down synchronously so the
Windows taskkill completes before the process exits.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:17:13 +08:00
程序员阿江(Relakkes)
ef87589923 fix(desktop): set Windows AppUserModelID and guard window navigation
- applyWindowsAppUserModelId() so Windows attributes toast notifications to the
  app (kept in sync with build.appId via a test); no-op on macOS/Linux
- main window: setWindowOpenHandler denies uncontrolled popups, routes http(s)
  links to the system browser; intentionally no will-navigate guard so dev HMR
  reloads keep working
- preview view: denies popups + blocks non-http(s) navigation (file:/custom
  schemes) while allowing in-page http(s) browsing

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:17:13 +08:00
程序员阿江(Relakkes)
85cf04e305 fix(desktop): make macOS signing+notarization explicit and Windows signing optional
- mac.notarize=true + hardenedRuntime + entitlements so a signed CI release
  actually notarizes (gatekeeper smoke + Squirrel.Mac auto-update need it)
- entitlements grant disable-library-validation for the Bun sidecar/node-pty
- local unsigned build passes -c.mac.notarize=false so electron:package still
  works without an Apple account
- release signing-preflight now hard-requires only the Apple secrets; Windows
  cert is optional (unsigned NSIS still auto-updates, just SmartScreen warning)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:17:13 +08:00
程序员阿江(Relakkes)
303f2bdf0e fix(desktop): resolve social media icons via publicAssetPath
Bare absolute paths like /icons/bilibili.svg failed under Electron's
file:// protocol. Route them through publicAssetPath so they resolve
against the relative base URL, matching the GitHub and app icons.
2026-06-03 13:50:42 +08:00
程序员阿江(Relakkes)
65fcc4f37d chore: ignore electron desktop build output
The Electron packaging output directory is generated locally and should stay out of source control alongside the existing desktop build output ignores.

Constraint: desktop/electron-dist/ is local build output, not a product source artifact.
Confidence: high
Scope-risk: narrow
Tested: git check-ignore -v desktop/electron-dist/
Tested: git diff --check
2026-06-03 12:43:08 +08:00
程序员阿江(Relakkes)
7e737cb4aa fix(desktop): restore tab bar window dragging
Electron handles custom draggable chrome through CSS app-region rules, not the old runtime startDragging path. Mark the tab strip and empty scroll gutter as native drag regions while keeping tab items and controls explicitly no-drag so tab reordering and close/tool buttons keep receiving pointer events.

Constraint: Electron drag regions swallow pointer events unless interactive children are marked no-drag
Rejected: Keep calling startDragging from the empty gutter | Electron desktopHost does not expose that as the active migration path
Confidence: high
Scope-risk: narrow
Directive: Do not mark tab items themselves as drag regions without revalidating tab reorder behavior
Tested: cd desktop && bun run test src/components/layout/TabBar.test.tsx --run
Tested: cd desktop && bun run lint
Tested: bun run check:desktop
2026-06-03 12:42:14 +08:00
程序员阿江(Relakkes)
349955dbf2 fix: route agent slash through normal chat (#653)
/agent should behave like a normal session prompt that tells the main model to use the selected Agent tool. The previous forked command path buffered the subagent run behind local command output and forced desktop clients to wait for command completion instead of seeing the normal Agent interaction stream.

Constraint: Desktop /agent must preserve ordinary chat/session semantics and still require /agent <agent> <prompt>.
Rejected: Keep slash_agent SDK event bridging | it preserves the separate forked execution path instead of fixing the product flow.
Confidence: high
Scope-risk: moderate
Directive: Do not move /agent back to context: fork without proving the desktop normal Agent tool stream still works.
Tested: bun test src/commands/agent.test.ts src/utils/processUserInput/processSlashCommand.test.ts src/server/__tests__/ws-memory-events.test.ts
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx
Tested: git diff --check
Not-tested: bun run check:server is blocked before source checks by expired quarantine entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
2026-06-03 11:41:12 +08:00
程序员阿江(Relakkes)
54f3c00414 fix(desktop): stabilize chat selection references (#351)
The chat reference action was still tied too closely to message-local
mouseup timing, and the floating fixed-position control stayed inside
virtualized message DOM. In Electron Chromium that made multi-line ranges
race selection settlement and let transformed ancestors offset the button
away from the viewport position we calculated.

This reads settled document selections after pointerup/selectionchange,
portals the action to document.body, and prefers right-side placement for
multi-line selections.

Constraint: Electron Chromium selectionchange can settle after message-local mouse events
Rejected: Keep the popover inside the message node | transformed/virtualized ancestors offset fixed positioning in real browser layout
Confidence: high
Scope-risk: narrow
Directive: Keep chat selection actions portaled; do not reparent under virtualized message rows without browser-coordinate verification
Tested: cd desktop && bun run test -- src/components/chat/MessageList.test.tsx
Tested: bun run check:desktop
Tested: Playwright Chromium smoke for multi-line selection, single-line selection, and outside-click dismissal on local desktop harness
2026-06-03 11:39:18 +08:00
程序员阿江(Relakkes)
0ebb0582b0 fix: stream agent slash progress to desktop (#653)
The desktop /agent slash path runs before the normal query loop, so the old implementation waited for the forked command to finish and only surfaced the final local-command stdout. Emit foreground slash-agent task events from /agent, drain SDK events while QueryEngine waits for pre-query slash processing, and allow those current-turn events through the WebSocket pre-send mute gate.

Constraint: /agent is a forked slash command that does not produce ordinary assistant deltas until its final stdout is synthesized.

Rejected: Frontend-only loading state | would not expose real forked-agent progress or tool/tool-result updates.

Confidence: high

Scope-risk: moderate

Directive: Keep slash_agent task events scoped to /agent; ordinary slash command stdout and /goal event handling should remain on the existing local-command paths.

Tested: bun test src/QueryEngine.test.ts src/utils/processUserInput/processSlashCommand.test.ts src/server/__tests__/ws-memory-events.test.ts

Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx

Not-tested: bun run check:server is blocked by expired quarantine review entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
2026-06-03 11:25:36 +08:00
程序员阿江(Relakkes)
f060d20b3b fix: keep generated session titles in user language
Async title refresh runs after assistant output, so provider prompts can be biased by assistant language and English title examples. The title language now resolves from the first meaningful user message before consulting the response-language fallback, then retries once when a generated title violates that language.

Constraint: Desktop response-language settings still control assistant prose, not automatic title metadata when the first user message has a clear language
Rejected: Follow response-language setting for every generated title | Chinese sessions flip to English when replies are configured in English
Rejected: Persist mismatched generated titles after retry failure | preserves a bad UX over the safer first-message placeholder
Confidence: high
Scope-risk: moderate
Directive: Do not change automatic title language precedence without re-testing image/text first-turn sessions and English-response-language sessions
Tested: bun test src/server/__tests__/title-service.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts -t "refreshes the first-turn AI title"
Tested: git diff --check
Tested: real MiniMax-M3 /tmp session 58a47fcd-6f9d-4685-bc73-f9317e3f330e with temporary response language english; assistant replied English and final aiTitle was 标题语言验证
Not-tested: bun run check:server blocked before tests by expired quarantine entries server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
2026-06-03 11:22:29 +08:00
程序员阿江(Relakkes)
be51b4cbc8 fix: generate session titles after assistant turns
Desktop title generation previously upgraded the first sidebar title from the raw user prompt before assistant output existed. That made image-plus-text sessions vulnerable to keeping a title based only on the user's initial wording. This moves polished title generation to completed turns, reuses the CLI title prompt and transcript extractor, and routes title calls through the configured haiku model with a retry when disabled thinking is rejected.

Constraint: The first user message still needs an immediate placeholder title so the sidebar is responsive.
Rejected: Generate the AI title before assistant output | image-derived context is only available after the assistant turn completes.
Confidence: high
Scope-risk: moderate
Directive: Keep polished automatic titles tied to completed transcript turns, not pre-response user prompts.
Tested: bun test src/server/__tests__/title-service.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts -t "refreshes the first-turn AI title"
Tested: git diff --check
Tested: Real MiniMax-M3 /tmp session f89073ed-3467-492a-b63c-e1886c146a3a with image attachment wrote ai-title "Validate session title generation"
Not-tested: bun run check:server is blocked by existing expired quarantine manifest entries
2026-06-03 10:06:34 +08:00
程序员阿江(Relakkes)
950590ca5d fix: set MiniMax-M3 default context to 1m
MiniMax's official M3 model page and release notes describe M3 as supporting up to a 1M-token context window with a guaranteed minimum of 512K. Keep the built-in MiniMax preset aligned with that official default instead of inheriting the older 204.8K MiniMax generation limit.

Constraint: Official MiniMax M3 docs state the M3 API supports up to 1M tokens context window.
Rejected: Keep 204800 and rely on manual provider overrides | that makes the built-in MiniMax preset wrong for new users.
Confidence: high
Scope-risk: narrow
Directive: Do not copy MiniMax-M2.7's 204.8K window onto MiniMax-M3 without re-checking official M3 docs.
Related: https://www.minimax.io/models/text/m3
Related: https://www.minimax.io/blog/minimax-m3
Tested: git diff --check
Tested: bun test src/server/__tests__/provider-presets.test.ts src/server/__tests__/providers-real.test.ts src/server/__tests__/provider-runtime-env.test.ts src/server/__tests__/providers.test.ts src/utils/__tests__/context.test.ts
Not-tested: bun run check:server blocked before execution by expired quarantine entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
2026-06-03 10:05:47 +08:00
程序员阿江(Relakkes)
247da5072f fix: use provider context windows for transcript estimates
Desktop chat can fall back to persisted transcript estimates when live inspection context is unavailable. That path previously only used built-in model windows, so custom provider settings such as MiniMax-M3 with a 1,000,000-token window still displayed the default 200,000-token estimate. Resolve transcript context windows from the session or active provider runtime env first, then fall back to built-ins.

Constraint: Provider model context windows are stored in provider runtime env, not always in the server process env.
Rejected: Change the built-in MiniMax-M3 window to 1,000,000 | upstream preset correctly keeps MiniMax-M3 at 204,800 by default, while user overrides must remain provider-specific.
Confidence: high
Scope-risk: moderate
Directive: Keep transcript estimates aligned with session/provider runtime env before consulting built-in model defaults.
Tested: git diff --check
Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "active provider model context windows|Sonnet 4.6 transcript usage|low-trust media"
Tested: bun test src/server/__tests__/provider-presets.test.ts src/server/__tests__/provider-runtime-env.test.ts src/server/__tests__/providers.test.ts src/utils/__tests__/context.test.ts src/utils/__tests__/contextBudget.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/provider-runtime-env.test.ts src/utils/__tests__/context.test.ts src/utils/__tests__/contextBudget.test.ts
Not-tested: bun run check:server blocked before execution by expired quarantine entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
2026-06-03 10:00:52 +08:00
程序员阿江(Relakkes)
8716faf2c1 merge: integrate MiniMax-M3 preset baseline
Remote main includes PR #694, which updates the MiniMax preset to MiniMax-M3 and removes deprecated built-in MiniMax context-window entries. Merge that provider baseline before applying the transcript context-window estimate fix so the local line keeps upstream provider defaults.

Constraint: Remote main advanced independently with PR #694 while local main carried unreleased commits.
Rejected: Reset local main to origin/main | would discard local-only main commits.
Confidence: high
Scope-risk: moderate
Directive: Preserve MiniMax-M3 provider preset changes when touching provider context-window logic.
Tested: bun test src/server/__tests__/conversations.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/provider-runtime-env.test.ts src/utils/__tests__/context.test.ts src/utils/__tests__/contextBudget.test.ts
Not-tested: bun run check:server blocked by expired quarantine entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
2026-06-03 10:00:33 +08:00
程序员阿江(Relakkes)
358b2c50be fix(desktop): restore chat selection references (#351)
Chat selection references could miss drag gestures that ended outside the
message bubble after the Electron migration. The chat transcript now tracks
selection gestures at the document pointer-up boundary and repositions the
shared selection action near the selected text with above-then-right placement.

Constraint: Electron/WebView selection ranges are not always stable during the message-local mouseup event
Rejected: Add a new selection popover system | the existing shared selection hook already covers chat and workspace dismissal behavior
Confidence: high
Scope-risk: narrow
Directive: Keep chat and workspace selection popovers on the shared positioning/dismissal hook unless their behavior intentionally diverges
Tested: bun run test -- src/components/chat/MessageList.test.tsx -t "selected-message action"
Tested: bun run test -- src/components/chat/MessageList.test.tsx
Tested: bun run check:desktop
Tested: in-app browser smoke at http://127.0.0.1:5181/ with zero console errors
Not-tested: Packaged Electron manual drag selection smoke
Related: #351
2026-06-03 09:48:23 +08:00
程序员阿江(Relakkes)
959e177cdf fix: keep agent slash selection editable before send (#653)
Selecting a concrete /agent entry from the composer suggestions should prepare the command and leave focus in the editor so the user can type the required prompt. The Enter send shortcut still applies after the suggestion menu is closed, and exact non-agent slash commands keep their existing direct execution path when they remain highlighted.

Constraint: The desktop composer supports configurable Enter vs Ctrl/Cmd+Enter sending.
Rejected: Special-case only /agent entries | the highlighted suggestion should consistently win while the menu is open.
Confidence: high
Scope-risk: narrow
Directive: Keep ChatInput and EmptySession slash-key handling aligned with shared send shortcut behavior.
Tested: cd desktop && bun run test -- --run src/components/chat/composerUtils.test.ts src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: bun run check:desktop
Not-tested: Live backend agent-list integration beyond mocked desktop composer coverage.
2026-06-03 09:30:16 +08:00
程序员阿江(Relakkes)
3f1312d40d fix(desktop): prevent macOS menu-bar artifacts on external displays
Electron was showing the main BrowserWindow before renderer load completed, so macOS could paint a blank window surface behind the menu bar. Persisted y=0 window state could also restore the titlebar under the menu-bar work area on external displays. Delay the initial show until the renderer entry is loaded, clamp restored macOS bounds into the display workArea, skip the macOS status-bar tray, and unhide the app before focusing restored windows.

Constraint: macOS external displays expose menu-bar and status-item chrome differently from Windows and Linux.
Rejected: Remove the native application menu | it would break expected macOS menu behavior without fixing the pre-load window surface.
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce pre-load main-window show without validating macOS external-display menu-bar rendering.
Tested: cd desktop && bun test electron/services/windows.test.ts electron/services/tray.test.ts electron/services/singleInstance.test.ts electron/services/menu.test.ts
Tested: bun run check:desktop
Tested: bun run check:native
Tested: git diff --check
Not-tested: Live dual-external-monitor screenshot smoke.
2026-06-03 09:06:05 +08:00
程序员阿江-Relakkes
1c231d71ab
Merge pull request #694 from octo-patch/feature/upgrade-minimax-m3
feat(provider): upgrade minimax preset to MiniMax-M3
2026-06-02 23:52:48 +08:00
程序员阿江(Relakkes)
000cfd4e9e Merge branch 'feat/electron-migration-main-sync-2392' 2026-06-02 22:45:40 +08:00
程序员阿江(Relakkes)
81845fbc49 fix: finalize Electron migration boundaries
Complete the Electron replacement boundary before merging by removing the renderer-side Tauri host fallback, tightening H5/browser access so only desktop navigation is tokenless, and moving desktop release publication to a tag-driven GitHub Actions matrix with a single final publish job.

Constraint: H5/browser capability access must not gain tokenless access through localhost or retired Tauri origins

Constraint: Desktop release artifacts must be built by GitHub Actions from version tags, not treated as local build outputs

Rejected: Keep localhost browser origins trusted for convenience | local browser contexts can access loopback services and must use the H5 token path

Rejected: Publish from each matrix job | partial releases can be created before all platforms finish

Confidence: high

Scope-risk: broad

Directive: Do not reintroduce Tauri origins or localhost browser origins into the trusted desktop origin set without a reviewed security design

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

Tested: bun test scripts/pr/release-workflow.test.ts scripts/release-update-metadata.test.ts

Tested: bun run check:desktop

Tested: bun run check:native

Tested: git diff --check

Not-tested: bun run check:server is blocked by expired quarantine entries server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
2026-06-02 22:42:53 +08:00
程序员阿江(Relakkes)
16f4137954 fix(desktop): stabilize Electron proxy and fullscreen handling
Electron desktop runs network-sensitive OpenAI OAuth token exchange in the sidecar process, so the sidecar now receives system proxy env derived from Electron's cross-platform proxy resolver and the OAuth token client uses the existing proxy fetch options. General manual proxy settings also document and preserve authenticated proxy URLs.

The macOS fullscreen black-screen path is addressed by avoiding native fullscreen Spaces for app fullscreen toggles and by leaving fullscreen before hiding or closing the window.

Constraint: Electron packaged apps may not inherit shell HTTPS_PROXY env when launched from Finder.
Constraint: Manual authenticated proxies must remain standard HTTP(S) proxy URLs for Bun/undici compatibility.
Rejected: Store proxy username and password as separate fields | would require new secret-storage semantics and migration beyond this bugfix.
Rejected: Use native macOS fullscreen Spaces for the desktop app | reproduced black-screen behavior when hiding/closing from fullscreen.
Confidence: high
Scope-risk: moderate
Directive: Do not remove sidecar proxy env injection without retesting OpenAI OAuth from a packaged app launched outside a shell.
Tested: bun test src/services/openaiAuth/client.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts
Tested: bun test src/server/__tests__/network-settings.test.ts
Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx --run
Tested: cd desktop && bun run check:electron
Tested: git diff --check
Not-tested: bun run check:server blocked by expired quarantine entries server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
Not-tested: live OpenAI OAuth through a corporate authenticated proxy
2026-06-02 21:37:35 +08:00
程序员阿江(Relakkes)
232855fe77 fix(desktop): serve packaged H5 shell from Electron builds
Electron's sidecar runs outside app.asar, so H5 static files must be available as normal unpacked files. Point the sidecar at the unpacked renderer dist and keep a server fallback for stale app.asar-style paths.

Constraint: Packaged Bun sidecars cannot read app.asar paths with ordinary fs stat calls.
Rejected: Serve H5 from app.asar directly | the external sidecar is not Electron and does not get asar filesystem support.
Confidence: high
Scope-risk: narrow
Directive: Keep package-smoke checking app.asar.unpacked/dist/index.html before changing asarUnpack or H5 dist paths.
Tested: bun test src/server/__tests__/h5-access-auth.test.ts src/server/__tests__/h5-access-policy.test.ts
Tested: bun test desktop/electron/services/sidecarManager.test.ts scripts/quality-gate/package-smoke/index.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run check:electron
Tested: git diff --check
Tested: SKIP_INSTALL=1 SIGN_BUILD=0 MAC_TARGETS=dmg desktop/scripts/build-macos-arm64.sh
Tested: packaged sidecar curl /?serverUrl=...&h5Token=... returned HTTP 200
Not-tested: Gatekeeper notarization for the local ad-hoc DMG
2026-06-01 23:32:56 +08:00
octo-patch
709a792911 feat(provider): upgrade minimax preset to MiniMax-M3
Add MiniMax-M3 as the new default for the minimax provider preset and
remove deprecated M2.5/M2.1/M2 entries. MiniMax-M2.7 and the highspeed
variant are kept for users who pinned the previous generation.

Updated places:
- providerPresets.json: default models -> M3, modelContextWindows trimmed
- modelContextWindows.ts: built-in window list mirrors the new set
- provider-presets / providers-real / thinking tests updated to assert
  the new default
- .env.example and third-party docs (zh + en) recommend M3
- scripts/repro-issue-247-real.ts default model bumped to M3

Co-Authored-By: Octopus <liyuan851277048@icloud.com>
2026-06-01 23:28:29 +08:00
程序员阿江(Relakkes)
386a41e606 feat(desktop): enable Electron migration path
Introduce the Electron desktop shell alongside the existing React renderer and local Bun server boundary. The migration keeps the DesktopHost contract explicit across Tauri, Electron, and browser runtimes while adding Electron main/preload services for dialogs, shell, notifications, updates, tray/window lifecycle, terminal, preview WebContentsView, app mode, and release/package validation.

The commit also carries the latest local main desktop command updates, including agent slash entries and hidden-by-default markdown thinking details, so the packaged Electron build matches the current main UX surface.

Constraint: React renderer, local Bun server, REST/WebSocket, and sidecar boundaries must remain reusable during the migration
Constraint: macOS dev packages are ad-hoc signed and cannot prove Developer ID notarization or Gatekeeper release launch
Rejected: Browser-only smoke validation | it cannot exercise native dialogs, keychain prompts, notification behavior, or packaged app startup
Confidence: medium
Scope-risk: broad
Directive: Do not remove Tauri host support until signed Electron release artifacts pass native OS smoke on macOS, Windows, and Linux
Tested: bun run check:desktop
Tested: cd desktop && bun run check:electron
Tested: CSC_IDENTITY_AUTO_DISCOVERY=false bun run electron📦dir
Tested: bun run test:package-smoke --platform macos --package-kind dir --artifacts-dir desktop/build-artifacts/electron
Tested: Computer Use read packaged Electron app window at desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app
Not-tested: Developer ID signed/notarized Gatekeeper launch
Not-tested: Real OS notification click-to-session action
Not-tested: Windows and Linux packaged app smoke on real hosts
2026-06-01 22:43:16 +08:00
程序员阿江(Relakkes)
335082582e fix(desktop): keep thinking details hidden by default
Thinking markdown should remain available only after the user opens the disclosure. The prior preview mounted markdown content while collapsed, which made internal thinking occupy visible transcript space by default.

Constraint: Thinking content must stay behind the existing disclosure while preserving markdown rendering after expansion
Rejected: Ten-line collapsed markdown preview | still exposes thinking content in the normal chat flow
Confidence: high
Scope-risk: narrow
Directive: Do not render ThinkingBlock content while aria-expanded=false; keep MarkdownRenderer inside the expanded branch
Tested: cd desktop && bun run test -- chatBlocks.test.tsx
Tested: bun run check:desktop
Tested: git diff --check
Not-tested: Live desktop visual smoke with a real provider transcript
Related: #660
2026-06-01 22:08:18 +08:00
程序员阿江(Relakkes)
4589ef67f3 feat: surface agent selection without slash namespace collisions (#653)
Desktop users need a direct way to pick an installed Agent from slash completion while preserving the existing command and skill namespace. Add /agent <agent> <prompt> as the single execution surface and render active agents as namespaced completion rows.

Constraint: Existing slash command names and ordering must remain authoritative.
Rejected: Register each Agent as a top-level /<agent> command | would collide with built-in commands, skills, and future custom commands.
Confidence: high
Scope-risk: moderate
Tested: bun run verify
2026-06-01 21:55:38 +08:00
程序员阿江(Relakkes)
46ca911d1a fix: preserve readable large image inputs
Large screenshots were being treated like oversized text payloads,
which pushed readable images through an aggressive resize/compression
path before the model saw them. The image path now preserves images
that already fit API byte and dimension limits, prefers lossless or
high-quality compression when only bytes are too large, and only
downscales by vision pixel budget when the image would exceed the
Read token budget.

Constraint: Fixes pasted/read image failures reported in #615 and #677 while preserving screenshot readability requested in #663
Rejected: Always resize to 2048px | would unnecessarily degrade screenshots that already fit provider limits
Rejected: Continue estimating image budget from base64 text length | image blocks are billed/read as vision pixels, not text payload
Confidence: high
Scope-risk: moderate
Directive: Do not lower fallback JPEG quality or long-edge limits without revalidating real screenshot OCR/vision tasks
Tested: bun test src/utils/__tests__/imageResizer.test.ts src/server/__tests__/conversation-attachments.test.ts
Tested: bun run check:server
Tested: bun run check:coverage (changed-line coverage 95.25%; adapters/desktop coverage lanes failed from existing non-target issues)
Tested: GPT-5.5 Read smoke on 1394x4404, 4096x2304, and 7900x900 images
Not-tested: Real resize/re-encode branch in this source worktree because optional sharp/native image processor is not installed locally
Related: #615
Related: #677
Related: #663
2026-06-01 20:28:05 +08:00
程序员阿江(Relakkes)
a1f28507b2 fix: honor Windows pwsh for agent commands (#665)
Desktop terminal settings previously only controlled the UI terminal, so Windows sessions could show pwsh while agent PowerShell detection still fell back to Windows PowerShell 5.1. The sidecar now receives a narrow PowerShell-only override and the runtime resolves pwsh through PSHOME and standard Windows paths before falling back.

Fixes #665.

Constraint: Windows terminal shell selection must not make cmd, Git Bash, or arbitrary custom shells drive PowerShellTool execution
Rejected: Reuse the full terminal shell path for agent tools | would couple UI terminal behavior to tool execution and could route non-PowerShell shells into PowerShell detection
Confidence: medium
Scope-risk: moderate
Directive: Keep agent command shell selection narrower than terminal UI shell selection unless the permission/parser model is updated with it
Tested: bun test src/utils/shell/powershellDetection.test.ts; cd desktop/src-tauri && cargo test agent_powershell_override --lib; bun run check:native; bun run check:server; git diff --check
Not-tested: Live Windows desktop smoke with installed pwsh
Related: #665
(cherry picked from commit ecd813b9d2aebfb8d8b6d196170177eec969a6de)
2026-06-01 20:14:22 +08:00
程序员阿江(Relakkes)
264b24a462 fix: make provider tests match chat model normalization (#620)
Provider connectivity checks and proxy validation are API boundaries, but they kept the user-facing context suffix in the model id while the chat runtime already strips it. Normalize these paths so MiMo-style models with [1m] test the same model that sessions send.

Constraint: [1m]/[2m] are client-side context markers and upstream APIs may reject them
Rejected: Strip suffixes when saving provider config | would change the user-visible model selection instead of only the API boundary
Confidence: high
Scope-risk: narrow
Directive: Keep all provider API boundaries aligned with normalizeModelStringForAPI before sending requests upstream
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "normalizes context-window suffixes"
Tested: bun test src/server/__tests__/providers.test.ts
Tested: bun run check:server
Tested: git diff --check
Not-tested: Live MiMo API call; no provider credential was used
Related: #620
2026-06-01 20:03:53 +08:00
程序员阿江(Relakkes)
c793eefee9 feat(desktop): make thinking summaries readable as markdown
Support #660 by reusing the existing desktop markdown renderer for thinking content while keeping collapsed previews bounded to the first ten source lines and a ten-line visual cap.

Constraint: Issue #660 requests markdown-rendered thinking summaries with a ten-line collapsed preview and click-to-expand full content
Rejected: Keep the old single-line plaintext preview | it loses markdown structure and hides useful context
Confidence: high
Scope-risk: narrow
Directive: Keep ThinkingBlock on MarkdownRenderer instead of duplicating markdown parsing behavior
Tested: cd desktop && bun run test -- chatBlocks.test.tsx
Tested: bun run check:desktop
Not-tested: Live desktop visual smoke with a real provider transcript
Related: #660
2026-06-01 17:06:49 +08:00
程序员阿江(Relakkes)
eb5ba2cbdf fix: prevent Feishu reply fallback duplicates (#671)
Feishu CardKit reply sends can fail after the platform has already accepted the message. Reusing one outbound UUID across the initial reply send and the create fallback keeps the fallback idempotent instead of risking a second visible message.

Constraint: Feishu im.message.reply and im.message.create both accept uuid idempotency keys

Rejected: Removing the create fallback entirely | would regress CardKit create/send fallback behavior when the original reply truly did not land

Confidence: high

Scope-risk: narrow

Directive: Keep reply fallback sends on the same outbound UUID; do not regenerate it per API attempt

Tested: bun test feishu/__tests__/streaming-card.test.ts

Tested: bun test feishu/__tests__/cardkit.test.ts feishu/__tests__/streaming-card.test.ts

Tested: cd adapters && bun run test:feishu

Tested: bun run check:adapters

Tested: cd adapters && bunx tsc --noEmit
2026-06-01 16:55:41 +08:00
程序员阿江(Relakkes)
d075276a17 fix: prevent idle tabs showing active during prewarm (#681)
Desktop reconnects can attach a normal output callback while a session prewarm is still pending. CLI startup status then reaches the renderer and marks restored idle tabs as running even though no user turn is active.

Treat pending prewarm like completed prewarm and bind metadata-only output until a real user turn claims the session.

Constraint: Prewarm still needs init and slash-command metadata without streaming UI status.\nRejected: Filter status in TabBar | leaves other clients and sidebar state exposed to the stale activity signal.\nConfidence: high\nScope-risk: narrow\nTested: bun test src/server/__tests__/websocket-handler.test.ts\nTested: bun test src/server/__tests__/conversations.test.ts -t prewarm\nTested: bun run check:server\nNot-tested: Manual desktop restart visual smoke
2026-06-01 16:53:11 +08:00
程序员阿江(Relakkes)
e9e4f3e1e5 fix: dismiss chat selection bubble on scroll (#672)
The chat add-to-session popover is anchored to viewport coordinates, so it can float over unrelated messages after the transcript scrolls. The shared selection-popover dismissal hook now treats captured scroll as a dismissal signal, matching the existing outside-click behavior and clearing the stale text selection.\n\nConstraint: Desktop selection popovers are owned by message/workspace child components, not by the transcript scroll container.\nRejected: Thread scroll state through every selectable message | would re-render message rows during scroll for a global dismissal concern.\nConfidence: high\nScope-risk: narrow\nDirective: Keep selection popover dismissal centralized unless a future menu needs scroll persistence explicitly.\nTested: bun run test -- src/components/chat/MessageList.test.tsx -t "dismisses the selected-message action when the message list scrolls"\nTested: bun run test -- src/components/chat/MessageList.test.tsx\nTested: bun run check:desktop
2026-06-01 16:48:25 +08:00
程序员阿江(Relakkes)
80b2e98f8d fix: preserve composer state for browser screenshots (#678)
Browser screenshot capture reused composer prefill, which replaced local draft text and remained queued after the composer consumed it. The fix keeps rewind-style prefill as replacement while letting Browser screenshots append as one-shot composer attachments.

Constraint: Screenshot events can arrive while the chat composer is unmounted during Settings navigation.

Rejected: Store browser screenshots only in composerDraft | mounted composers would not update immediately.

Confidence: high

Scope-risk: narrow

Directive: Keep Browser screenshot capture on append mode; replacement prefill is for rewind-style composer restoration.

Tested: bun run test -- ChatInput.test.tsx previewEvents.test.ts --run

Tested: bun run check:desktop

Not-tested: Live Windows desktop/Tauri screenshot click
2026-06-01 16:48:03 +08:00
程序员阿江(Relakkes)
92b01565a3 fix: stop rejecting common tall screenshots in Read
Common desktop screenshots can be taller than the old 2000px local resize threshold while still fitting provider request limits. Align the local image dimension cap with the Claude Vision API rejection threshold so Read and desktop attachments pass through already-small screenshots, while oversized or unprocessable images still use the existing fallback paths.

Constraint: Claude Vision API allows image dimensions up to 8000px and still has a 5MB base64 image payload limit
Rejected: Keep 2000px as a client-side hard limit | it rejects common screenshots that providers can handle
Confidence: high
Scope-risk: narrow
Related: #615
Related: #677
Tested: bun test tests/imageResizer.test.ts
Tested: bun test tests/imageResizer.test.ts tests/mediaRecoveryAndEstimation.test.ts src/services/api/errors.test.ts src/server/__tests__/proxy-transform.test.ts
Tested: bun test src/server/__tests__/conversation-attachments.test.ts tests/imageResizer.test.ts
Tested: bun run check:server
2026-06-01 16:45:20 +08:00
程序员阿江(Relakkes)
aa3cba3334 fix: recover stale auth and sockets in desktop chats (#658, #651)
Desktop official OAuth sessions inject a token into a long-lived CLI process to avoid OS credential prompts. After Windows sleep/wake that env token can become stale, so the server now pushes a refreshed token before each resumed user turn and the CLI clears its OAuth cache when the env token changes.

The retry path also disables keep-alive after ECONNRESET/EPIPE by default, matching the stale pooled-socket failure mode reported on #651.

Constraint: Real Win11 sleep/wake cannot be physically reproduced in this macOS worktree

Rejected: Restart the CLI before every user turn | would add latency and discard useful process continuity

Confidence: medium

Scope-risk: moderate

Directive: Keep official OAuth env-token updates paired with CLI-side OAuth cache invalidation

Tested: bun test src/server/__tests__/conversation-service.test.ts --timeout 30000

Tested: bun test src/cli/__tests__/structuredIO.test.ts --timeout 30000

Tested: bun test src/services/api/withRetry.test.ts --timeout 30000

Tested: bun run check:server

Tested: git diff --check

Not-tested: Real Win11 sleep/wake with Claude official OAuth

Not-tested: External ccswitch reqwest pool reset path when the reset is hidden behind the proxy

Related: #658

Related: #651
2026-06-01 16:36:33 +08:00
程序员阿江(Relakkes)
ebc78befbe fix: avoid static previews for frontend index HTML
Project entry HTML often only mounts a dev-server app, while built output can be served statically. The desktop open-with policy now only offers the in-app browser for static HTML candidates, and preview-fs rewrites built HTML root-relative assets under the workspace preview path.

Constraint: Frontend project index.html needs a dev server instead of preview-fs static serving
Rejected: Treat every .html file as browser-previewable | project entry HTML can render blank or with missing assets
Confidence: high
Scope-risk: moderate
Tested: cd desktop && bun run check:desktop
Tested: bun run check:server
Tested: git diff --check
Not-tested: bun run verify was intentionally stopped at user request
v0.3.2
2026-06-01 03:16:52 +08:00
程序员阿江(Relakkes)
d222b47cc4 fix: keep desktop preview shutdown from orphaning tool processes
The desktop app can quit while a preview-driven Bash task is still running npm/vite. Bash commands are spawned as detached process groups, so killing only the CLI or shell process can leave descendant dev servers alive and make later app launches look stuck.

This gives the CLI enough shutdown budget to run cleanup, lets the native sidecar wait long enough for that server cleanup, kills detached Bash process groups before the existing tree-kill fallback, and closes the native preview WebView instead of hiding it on workbench unmount.

Constraint: CLI gracefulShutdown has a 5s failsafe, so outer desktop shutdown windows must not SIGKILL it after 2-3s
Rejected: Treat the browser preview as the dev-server owner | it only opens URLs and does not spawn npm/vite
Confidence: high
Scope-risk: moderate
Directive: Do not shorten desktop/server shutdown windows below the CLI cleanup budget without reproducing BashTool background-task teardown
Tested: bun test src/utils/ShellCommand.test.ts src/server/__tests__/conversation-service.test.ts
Tested: cd desktop && bun run test -- --run src/components/browser/BrowserSurface.test.tsx src/components/workbench/WorkbenchPanel.webview.test.tsx
Tested: cd desktop && bun run lint
Tested: bun run check:server
Tested: SKIP_INSTALL=1 ./desktop/scripts/build-macos-arm64.sh
Tested: Opened canonical app and generated DMG app; both showed visible/frontmost window and left no app/sidecar/vite processes after quit
Not-tested: Notarized release install path
2026-06-01 02:51:22 +08:00
程序员阿江(Relakkes)
4d6b1855bf release: prepare v0.3.2
Prepare the desktop release metadata and concise release notes while keeping
tagging and release publishing for a later step. The staged local build-script
updates keep desktop commands on checked-in local toolchain paths and avoid
rewriting preview-agent output when the built content is unchanged.

The persistence-upgrade gate now runs the focused desktop Vitest migration
suite in non-watch mode, matching the broader desktop quality lane and avoiding
pre-push termination during release preparation.

Constraint: Release publishing is intentionally deferred per request
Constraint: Desktop release metadata must keep package, Tauri config, Cargo metadata, and Cargo.lock aligned
Confidence: medium
Scope-risk: moderate
Directive: Do not tag v0.3.2 until release dry-run and final release verification are rerun on the release candidate
Tested: bun run scripts/release.ts 0.3.2 --dry
Tested: cd desktop && bun run lint
Tested: bun run check:persistence-upgrade
Tested: git diff --check
Not-tested: Full bun run verify
2026-06-01 02:30:01 +08:00
程序员阿江(Relakkes)
4b3eb16347 fix: prevent orphaned desktop CLI sidecars
Packaged desktop shutdown was killing the server sidecar with SIGKILL on Unix, which skipped server-side cleanup for CLI subprocesses spawned by active chat sessions. The native layer now gives sidecars a SIGTERM grace window, and the server waits for active CLI sessions to exit before completing signal-driven shutdown.

Constraint: Tauri shell CommandChild::kill maps to SIGKILL on Unix.
Rejected: Only clean stale processes on next launch | leaves user-owned sessions and sockets in an unknown state after every unclean app exit.
Confidence: high
Scope-risk: moderate
Directive: Do not replace the SIGTERM grace path with direct CommandChild::kill without rechecking packaged-app process-tree shutdown.
Tested: bun test src/server/__tests__/conversation-service.test.ts
Tested: bun run check:server
Tested: bun run check:native
Tested: git diff --check
Not-tested: Fresh DMG install plus manual quit/reopen process-tree smoke.
2026-06-01 02:21:46 +08:00