Commit Graph

7262 Commits

Author SHA1 Message Date
Pleasure1234
ca133e33b1 fix: correct minor bugs across image-preview, provider-config, mini-apps, painting, notes, and selector (#16343)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: Pleasurecruise <3196812536@qq.com>
2026-06-24 23:02:01 +08:00
槑囿脑袋
2099f0a109 feat(web-search): default providers and route Jina to its China mirror (#16331)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-06-24 23:01:27 +08:00
jd
1ae8c2d9a2 fix(topic): insert new conversations at top (#16337)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-24 23:00:47 +08:00
Asurada
bc50274f35 fix(provider-registry): correct text-only model capabilities (#16153)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
2026-06-24 22:57:59 +08:00
SuYao
bc281f198f fix(sub-window): draw OS window controls on frameless Win/Linux sub-windows (#16351)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-24 22:02:12 +08:00
亢奋猫
f68244e9d9 ci(translator): speed up GitHub content translation workflow (#16348)
Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-06-24 20:54:44 +08:00
fullex
44a5be94d3 perf(binary-manager): build isolated mise env lazily off the startup path
onInit() eagerly built the isolated mise env, which blocks on a region
lookup (regionService.isInChina, for China mirror selection) whose cache
is cold on every launch. That network round-trip sat on the Background-
phase path that gates allReady(), for a value only ever consumed by
runMise() (install/reconcile/remove/search) — none of which runs during
init.

Defer the build to the first runMise() and memoize the in-flight promise
so concurrent first callers share a single build and a single region
lookup; a failed build is not cached, allowing a later retry. The lookup
now happens lazily, after the app is ready, where the mirror env is
actually needed.

Add tests covering the lazy behavior and concurrent-first-call dedup.

Also pin the Vitest timezone to UTC so date-bucketing tests are
deterministic on non-UTC dev machines.
2026-06-24 04:55:59 -07:00
fullex
787e9e8bdf refactor(ipc): split errors module into directory for per-domain error codes
Move src/shared/ipc/errors.ts to src/shared/ipc/errors/index.ts so each migrated domain can host its own error-code map as a sibling errors/<domain>.ts — value-importable by both processes and zod-free. The @shared/ipc/errors barrel path is unchanged, so every importer and test resolves identically (typecheck + IPC tests green).

Document the IpcErrorCode usage convention that previously lived only in code comments: the framework-code single source of truth, the open (string & {}) tail for domain codes, where domain codes belong (errors/, not schemas/, since the renderer may only import type from schemas), and why they are imported directly rather than aggregated through a barrel.
2026-06-24 04:38:38 -07:00
Gu JiaMing
02b2185482 feat(migration-v2-window): redesign V2 migration window (#16314)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Pleasurecruise <3196812536@qq.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
2026-06-24 19:23:22 +08:00
fullex
dfae61317a refactor(region-service): replace ipService util with cached RegionService
Promote the classless `utils/ipService.ts` (which wore a `*Service` suffix
despite holding no class) into a real `services/RegionService.ts` singleton.
Egress-country detection now caches through CacheService with a TTL backstop
and invalidates on proxy changes — the cache is keyed on ProxyManager's
applied-proxy key, since the detected country reflects the egress IP. Concurrent
detections are deduped via single-flight.

- Add RegionService (getCountry/isInChina) with unit tests
- Expose ProxyManager.appliedProxyKey for cache invalidation
- Route BinaryManager, CodeCliService, AppUpdaterService, TesseractRuntimeService
  and the App_GetIpCountry IPC handler through RegionService
- Update consumer test mocks to the new module
2026-06-24 04:02:30 -07:00
亢奋猫
9872e599ba feat(settings): add provider model delete actions (#16094)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-06-24 17:11:18 +08:00
LiuVaayne
efecdd5007 refactor(binary-manager): unify CLI binary acquisition behind mise-backed BinaryManager (#15184)
### What this PR does

**Before this PR**, Cherry Studio managed external CLI binaries through
five uncoordinated mechanisms — each requiring its own download script,
IPC channel, and on-disk layout:

| Mechanism | Where it lived | How it worked |
|---|---|---|
| rtk extraction | `src/main/utils/rtk.ts` + `AgentBootstrapService` |
Copies bundled binary to `~/.cherrystudio/bin/` |
| OpenClaw installer | `resources/scripts/install-openclaw.js` |
Downloads from GitHub/mirror with custom extraction |
| CodeCliService | `src/main/services/CodeCliService.ts` | `bun install
-g` to `~/.cherrystudio/install/global/` |
| ripgrep | `node_modules/@anthropic-ai/claude-agent-sdk/vendor/` |
Vendored, hardcoded path in `FileStorage` |
| (old) MiseService | `src/main/services/MiseService.ts` | Bundled mise
+ `mise use -g` |

**After this PR**, a single `BinaryManager` lifecycle service owns all
third-party CLI binary acquisition. It wraps
[mise](https://mise.jdx.dev) as the only acquisition backend (no custom
`BinaryBackend` interface — mise's polyglot grammar already covers
`npm:`, `pipx:`, `github:`, registry entries). Tools install into an
isolated environment under `~/.cherrystudio/mise/` so user-level mise
installs are never touched. `uv`, `bun`, `rg`, and mise itself ship
bundled at build time for instant first-run availability; everything
else flows through mise on demand.

<img width=\"1304\" height=\"714\" alt=\"BinaryManager settings UI\"
src=\"https://github.com/user-attachments/assets/7a4b78ab-5aa2-4e97-9ab7-134b20a4d78d\"
/>
<img width=\"1165\" height=\"748\" alt=\"Three-state managed vs bundled
vs not-installed\"
src=\"https://github.com/user-attachments/assets/a0dcfb7d-8bc3-4acd-b563-0fc04d99e252\"
/>
<img width=\"523\" height=\"328\" alt=\"Custom tool dialog\"
src=\"https://github.com/user-attachments/assets/90c3ee95-7f2a-4daf-a334-f20de6ff5ca2\"
/>

Fixes #15183. Addresses #15370.

### Why we need it and why it was done in this way

Adding a new managed CLI tool should be a one-line preset entry — not 4+
files of bespoke download/extract/IPC code. mise is a mature polyglot
tool manager that already speaks the backends Cherry needs.

**Tradeoffs made:**
- **mise bundled at build time** (~15 MB per platform) rather than
downloaded at first run — faster first-run UX, no chicken-and-egg on a
fresh install.
- **Fully isolated mise environment** (\`HOME\`/\`XDG_*\`/\`MISE_*\` all
relocated under \`feature.binaries.data\`) — Cherry never reads or
writes the user's own \`~/.config/mise/\` or \`~/.local/share/mise/\`.
- **No custom \`BinaryBackend\` interface.** mise's grammar (\`npm:\`,
\`pipx:\`, \`github:\`, registry) is already polyglot; wrapping it would
be a shallow seam that re-implements what mise owns. Removing this
abstraction makes consumers simpler (deletion test passes).
- **Auth-token policy: opt-in only.** Ambient \`GITHUB_TOKEN\` /
\`GH_TOKEN\` are not forwarded into mise's process env. Users who hit
GitHub's unauthenticated 60 req/hr API limit can set
\`CHERRY_GITHUB_TOKEN\` to raise it to 5000 req/hr without consenting to
share their general shell token.
- **China mirror auto-detection.** \`isUserInChina()\` toggles
\`NPM_CONFIG_REGISTRY=registry.npmmirror.com\` +
\`PIP_INDEX_URL=pypi.tuna.tsinghua.edu.cn\` for every npm/pipx backend
transparently.

**Alternatives considered:**
- *Keep per-tool install scripts.* Doesn't scale — each new tool is 4+
files of duplicated logic.
- *Use mise from user's \`PATH\`.* Would depend on user having mise
installed and could conflict with their config.
- *Custom \`BinaryBackend\` abstraction.* Shallow wrapper over mise's
grammar; no second backend in sight; deletion test passes.

**Scope (what's in / what's out):**
- **In:** uv, bun, ripgrep, claude-code, openclaw, gh, opencode,
gemini-cli, lark, kimi-cli, qwen-code, iflow-cli, github-copilot-cli —
anything mise can install as a single relocatable binary.
- **Out:** \`OvmsManager\` (multi-file server provisioning, hardware
detection, generated config); Tesseract OCR data (not a binary; lives
with \`OvOcrService\`).

### Breaking changes

None at the user-facing layer. v2 data is throwaway per CLAUDE.md, so
the preference-key rename (\`feature.mise.*\` → \`feature.binaries.*\`)
intentionally ships without a migrator.

### Special notes for your reviewer

**Architecture & docs**
- \`docs/references/binary-manager/README.md\` — scope criterion,
persisted/contract surface, bundled-vs-mise state contract, China mirror
behavior, \`CHERRY_GITHUB_TOKEN\` opt-in, adding a new managed binary.
- \`CLAUDE.md\` adds a \`**MUST READ**\` link next to Lifecycle / Window
Manager / Data / Paths.
- The mise-shim-wins-over-\`cherry.bin\` precedence rule is documented
in the README's "State contract" section.

**Code orientation**
- \`src/main/services/BinaryManager.ts\` — the lifecycle service. Wraps
mise via \`runMise()\`; isolated env in \`buildIsolatedEnv()\`; bundled
extraction with atomic tmp+rename; per-tool try/catch so a single
failure can't abort init; \`isManagedBinaryReady()\` verifies the
resolved file is executable (not just that mise thinks it's installed).
- \`packages/shared/data/presets/binary-tools.ts\` —
\`PREDEFINED_BINARY_TOOLS\` registry; \`tool\` field is a mise spec.
-
\`src/renderer/src/pages/settings/McpSettings/EnvironmentDependencies.tsx\`
— three-state UI (\`managed\` / \`bundled\` / \`not-installed\`) backed
by \`Binary_GetState\` + \`Binary_ProbeBundled\`.
- \`scripts/download-binaries.js\` — build-time downloader for mise / uv
/ bun / rg (HTTPS + sha256-verified, archive-aware extraction).

**Migration**
- \`OpenClawService.install()\` is now two lines delegating to
\`BinaryManager\` — \`install-openclaw.js\` is gone.
- \`CodeCliService\` no longer uses \`bun install -g\`; the
\`BUN_INSTALL\` / \`~/.cherrystudio/install/global/\` path is removed.
- \`FileStorage.getRipgrepBinaryPath()\` now resolves via
\`getBinaryPath('rg')\`; the vendored SDK rg is no longer used.
- \`extractRtkBinaries\` + the \`AgentBootstrapService\` call are
deleted. \`rtkRewrite()\` degrades gracefully when rtk is absent;
\`rtkAvailable\` caches with a 60s TTL so install-via-mise takes effect
without restart.

**Multi-round review**
Two adversarial review rounds against this branch (Bug Hunter / Security
/ Architecture / Correctness) ran during development; both rounds'
High-severity findings are addressed in commits \`70afde6af\` and
\`1d864439d\`. R3 known follow-ups (architecture duplications in
\`CodeCliService\`'s switch statements, etc.) are tracked as Medium and
intentionally deferred.

### Checklist

- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: Leaves binary acquisition meaningfully cleaner than
before (five mechanisms → one)
- [x] Upgrade: v2 data is throwaway; no migrator needed and the absence
is intentional
- [x] Documentation: \`docs/references/binary-manager/README.md\` +
\`CLAUDE.md\` Architecture section
- [x] Self-review: Two multi-perspective review rounds against the
branch; all Highs addressed

### Release note

\`\`\`release-note
NONE
\`\`\`

---------

Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: Vaayne Liu <vaayne@macos.shared>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
2026-06-24 15:15:25 +08:00
jd
4042751f6e fix(chat-message-list): stabilize pin-to-top and bottom-follow scrolling (#16328)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-24 13:56:01 +08:00
Asurada
6291a153e5 fix(settings): align initial language selector with active UI language (#15960) 2026-06-24 13:55:00 +08:00
Pleasure1234
0d4edb3455 refactor(paths): route main-process service paths through application.getPath (#16310)
Signed-off-by: Pleasurecruise <3196812536@qq.com>
2026-06-24 13:54:29 +08:00
槑囿脑袋
f938422c7d feat(knowledge): add custom chunk strategy and separator (#16298)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-06-24 13:54:10 +08:00
槑囿脑袋
1668a73637 feat(knowledge): recover knowledge bases that lose their embedding model during v2 migration (#16308)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-06-24 13:52:52 +08:00
github-actions[bot]
d45335cb1f 🤖 Daily Auto I18N Sync: Jun 24, 2026 (#16324)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
2026-06-24 10:25:19 +08:00
jd
7610c9ab82 fix(painting): omit request size for the 'auto' sentinel so the server picks dimensions (#16311)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-24 10:24:55 +08:00
SuYao
6d5269b126 refactor(global-search): re-add the search panel (inverse of #16284) (#16285)
Co-authored-by: jdzhang <625013594@qq.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: jdzhang <625013594@qq.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-23 23:56:34 +08:00
SuYao
5472d5ecbc refactor(chat): re-add the history records page (inverse of #16281) (#16282)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: jdzhang <625013594@qq.com>
Co-authored-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
Co-authored-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
Co-authored-by: fullex <0xfullex@gmail.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
Signed-off-by: kangfenmao <kangfenmao@qq.com>
Signed-off-by: jdzhang <625013594@qq.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-23 23:30:03 +08:00
fullex
42a5b6320f docs(shared-layer): note Cache schema registry carve-out to cross-process rule 2026-06-23 06:39:01 -07:00
fullex
4dc36fa20f feat(power): elevate PowerMonitorService into a system power hub
Rename PowerMonitorService -> PowerService and relocate it to
src/main/core/power/, turning the shutdown-only service into a complete,
self-contained power hub:

- Typed power events (suspend/resume/lock/unlock/power-source) with
  suspend/resume + power-source de-duplication; lock/unlock pass-through.
- Bounded, cross-platform shutdown barrier: preventDefault on macOS/Linux,
  blockShutdown via a minimal hidden window on Windows; handlers run under a
  5s hard timeout, then the app quits through the normal quit flow.
- Best-effort, ref-counted sleep prevention: preventSleep(reason) returns a
  Disposable and never throws (the provider degrades internally). The OS
  blocker engages only while a hold is held AND the user enabled
  app.power.prevent_sleep_when_busy. JobManager is the first registrant,
  acquiring a hold per execution attempt.

Add the app.power.prevent_sleep_when_busy preference (v2-only, no v1 source)
and a Settings -> General toggle. Service phase moved Background -> WhenReady.
2026-06-23 06:29:23 -07:00
SuYao
32a6666bb3 chore(chat-page): scaffold chat component tree (#14997)
Co-authored-by: jdzhang <625013594@qq.com>
Co-authored-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
Co-authored-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: kangfenmao <kangfenmao@qq.com>
Signed-off-by: jdzhang <625013594@qq.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-23 20:31:49 +08:00
fullex
793d33ab51 refactor(logger): derive renderer window source from index.html meta
Renderer windows set their logger source inline via initWindowSource() in
entryPoint.tsx, which had to execute before any import-time log or the source
fell back to 'UNKNOWN'. ESM hoists imports above statements, so this ordering
was fragile and applied inconsistently across windows.

LoggerService now derives the source at construction from a
<meta name="logger-window-source"> tag in each window's index.html. The meta
is parsed before any module script runs, so the source is set before any
import-time log -- no ordering rules in entryPoint.tsx. initWindowSource() is
kept as an explicit override for documentless contexts (workers, tests) and
takes precedence over the derived value.

- Add resolveWindowSourceFromMeta() and derivedWindow with
  explicit > derived > UNKNOWN precedence; export the LoggerService class
- Declare the meta in all 7 window index.html files (source strings unchanged)
- Drop the 7 inline initWindowSource() calls and the subWindow initLogger.ts
  module; keep the worker's explicit initWindowSource('Worker')
- Update windows/README.md and docs/guides/logging.md
- Add LoggerService unit tests
2026-06-22 22:11:01 -07:00
槑囿脑袋
752c5e6912 fix(knowledge): park items interrupted mid-indexing at failed instead of stranding them (#16296)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-06-23 12:28:51 +08:00
槑囿脑袋
f0b226b615 cleanup(knowledge): remove dead code and unify duplicated paths (#16294)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-06-23 11:34:06 +08:00
槑囿脑袋
785cef8a04 feat(knowledge-ui): paginate data-source items (#16288)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-06-23 11:33:50 +08:00
github-actions[bot]
6af62d642b 🤖 Daily Auto I18N Sync: Jun 23, 2026 (#16302)
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
2026-06-23 10:24:12 +08:00
SuYao
e19f7cbc06 feat(chat): carve the v2 chat shell/orchestration layer onto main (#16272)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-06-22 23:34:47 +08:00
fullex
25fe3343fc docs(data): add canonical pagination guide and wire references
Pagination docs were scattered across api-types.md (types + cursor
semantics), data-api-in-renderer.md (hooks), data-api-in-main.md (offset
example + keyset note), api-design-guidelines.md (query params), and
data-ordering-guide.md (cache shapes + determinism), with no single
discoverable home for the offset-vs-cursor model.

Add docs/references/data/data-pagination-guide.md as the canonical hub
(mirrors data-ordering-guide.md): two modes, four-layer quickstart, wire
contract, server impl (offset + keyset cursor + multi-band caveat),
renderer consumption, FTS pagination, gotchas, and a see-also map. Other
docs keep their authoritative slice and link to the guide; the migrated
conceptual prose is removed from api-types.md to avoid duplication.

Also fix two pre-existing broken anchors found while verifying links
(database-patterns withWriteTx; ordering guide section number).
2026-06-22 06:41:27 -07:00
Gu JiaMing
02b1373218 fix(file-processing): route image OCR through file processing (#16125)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
Signed-off-by: 顾家铭 <gujiaming@gujiamingdeMacBook-Pro.local>
2026-06-22 21:21:27 +08:00
Gu JiaMing
5543521730 fix(page-side-panel): scope non-mac app shell portal (#16074)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Pleasurecruise <3196812536@qq.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
2026-06-22 21:12:40 +08:00
SuYao
f3c01c1686 fix(ai-claude-code): read MCP tools from cache on agent/chat start, never block (#16258)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-22 21:11:59 +08:00
fullex
79f5eb31b6 refactor(data-api): extract shared keyset-cursor ordering util
Consolidate the per-service <key>:<id> cursor codec and the keyset
WHERE/ORDER BY tuple into services/utils/keysetCursor.ts. keysetOrdering
derives the WHERE predicate and the matching ORDER BY from one direction
spec, so the two cannot drift apart and silently skip/repeat rows.

Migrate TranslateHistory, AgentSession, AgentSessionMessage (list), and
Painting to the shared util; delegate ftsSearch's codec to parseCursor /
encodeCursor while keeping its 422-throw policy. Harden Painting's cursor
from a single key to a defensive (orderKey, id) tuple.
2026-06-22 06:10:44 -07:00
SuYao
3d0910c673 feat(chat-composer): carve the v2 composer onto main (additive, dormant) (#16260)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-22 19:29:08 +08:00
fullex
bfb3de16da fix(job): exclude in-flight jobs from startup recovery (#16291)
Startup recovery (runStartupRecovery) runs ~60s after boot and reset every running row to pending (retry/singleton) or cancelled it (abandon/cancelRequested) without checking whether the row was a job the current process was still executing. A job enqueued during the 60s quiet window and still running when the sweep fired was therefore reset and re-dispatched — running its handler twice for one enqueue — or cancelled mid-flight. All recovery:'retry' handlers (file-processing, knowledge, image-generation, agent.task) are affected; #16125 (Translate OCR via File Processing) made it frequently reproducible.

Source fix: thread an isJobInFlight predicate (backed by JobManager.inFlightExecuted) into runStartupRecovery and filter in-flight rows out at the top of the per-type loop, above every strategy and the cancelRequested override. cancel() already owns in-flight cancellation, so excluding these rows from all branches is safe.

Defense-in-depth guard: spawnExecute now skips (warn) a jobId already present in inFlightExecuted — an idempotency invariant against any future re-dispatch path double-running a job. It does not fail the job (the original execution still finalizes it once), hence warn not error.

Tests: focused runStartupRecovery unit cases (retry / cancelRequested / singleton / abandon in-flight exclusion), an end-to-end no-double-dispatch integration test, and a spawnExecute idempotency smoke test. Job-and-scheduler docs updated.
2026-06-22 03:31:06 -07:00
槑囿脑袋
0745ca9997 fix(knowledge-migration): correctness & Windows file-lock fixes for v1→v2 KB migration (#16237)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: eeee0717 <chentao020717Work@outlook.com>
2026-06-22 18:10:30 +08:00
SuYao
d04d38063a feat(settings): carve the v2 settings pages onto main (#16269)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: 亢奋猫 <kangfenmao@qq.com>
Co-authored-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-22 16:11:54 +08:00
SuYao
1a5c6cd796 feat(knowledge): carve the v2 knowledge page onto main (#16268)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-22 12:34:53 +08:00
SuYao
3c2c03f1a1 feat(translate): carve the v2 translate page onto main (#16263)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: gujiaming <52187003+AtomsH4@users.noreply.github.com>
2026-06-22 12:34:32 +08:00
SuYao
0276f00de1 feat(mini-apps): carve the v2 mini-apps page onto main (#16264)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-22 12:34:09 +08:00
SuYao
4267638f6a feat(launchpad): carve the v2 launchpad page onto main (#16265)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-22 12:33:38 +08:00
SuYao
b7640b00b9 feat(code): carve the v2 code CLI page onto main (#16267)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: jd <59188306+zhangjiadi225@users.noreply.github.com>
2026-06-22 12:33:18 +08:00
Phantom
ba7174fe04 chore(i18n): add i18next-cli extraction and lint tooling (#16220)
Signed-off-by: icarus <eurfelux@gmail.com>
2026-06-21 21:12:14 +08:00
SuYao
ad3ebf6c5a fix(routing): register the /app/launchpad route so Launchpad stops 404-ing (#16255)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-21 21:03:30 +08:00
SuYao
1f41a5168a feat(chat): carve the v2 message renderer onto the foundation layer (#16229)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-21 20:44:55 +08:00
SuYao
16ebe2443c feat(ai-provider): route provider HTTP through proxy-aware net.fetch (#16207)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com>
Signed-off-by: suyao <sy20010504@gmail.com>
2026-06-21 18:11:47 +08:00
fullex
1fc8664e34 chore(deps): upgrade electron 41.2.1 to 41.8.0
Bump Electron within the same Chromium 146 milestone. Picks up
backported security fixes (CVE-2026-6296..6363 and later batches),
a browser-process crash fix for webContents.reload()/render-process-gone,
and a macOS auto-update fix. No breaking changes; no app code changes.
Node.js updated to v24.16.0.
2026-06-21 02:37:16 -07:00
fullex
32112c5346 fix(lifecycle): converge Analytics & Selection toggles via createLatestReconciler
Analytics and Selection drove activate/deactivate with fire-and-forget
`void activate()/void deactivate()`, relying on BaseService's shared
`_activating` guard, which drops (not coalesces) an opposing toggle that
lands mid-transition — leaving the final state diverged from the user's
latest choice.

- Analytics: the async onDeactivate (`await client.destroy()`) holds the
  `_activating` window open across real I/O time, so a re-enable arriving
  during teardown was dropped and analytics stayed silent. Self-hold a
  latest-wins reconciler keyed on desired-vs-actual; it re-reads the
  desired state after the deactivation settles and re-activates.
- Selection: the deferred startup warm-up (`setImmediate(activate)`)
  activated unconditionally even if the feature was disabled before the
  timer fired. Route the warm-up through the reconciler so the deferred
  request is level-triggered and honours a disable landing in the gap.

Both self-hold the reconciler (BaseService core unchanged) and are never
disposed (construct-once field, restart-safe). QuickAssistant is not
migrated: its onActivate/onDeactivate are synchronous (run-to-completion),
so the race is unreachable.

Follow-up to #16233 (createLatestReconciler + ApiGateway migration).
2026-06-20 22:40:05 -07:00