mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-04 06:02:08 +08:00
fbc4b516b81d689f60e4c6e94811aec2b11ecfc0
34
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ed0b801573 |
fix(service): unify installation and safe sidecar handoff
Delegate service and core installation to Service IPC so replacement uses one elevation. Share fallback occupancy checks and retain the execution guard until the Sidecar exits. Track missing approved cores and start refusals as unavailable, and show when no core is running. Build matching service tools from the local IPC dependency and pass both core executables through the Dev installer. |
||
|
|
b7197f6f4b | fix(windows): fall back to sidecar after confirmed service failure | ||
|
|
2a7972fa5b |
fix(core): drain sidecar events before readiness probe to avoid start… (#7966)
* fix(core): drain sidecar events before readiness probe to avoid startup stall * refactor(core): simplify core readiness generation handling * docs: update Changelog.md |
||
|
|
9a879dd8d8 |
fix(service): fall back to elevated sidecar on path permission rejection
Preserve TUN settings and restore proxy operation after fallback. Deliver fallback notices after UI subscription and stop retrying deterministic bundle refusals. Publish fallback state atomically and avoid conflicting service startup notifications. |
||
|
|
bea03e1a09 |
fix: preserve custom TUN fields and sync service provider caches
Limit GUI authority to saved TUN fields while preserving custom overrides. Sync provider caches after service startup, reloads and updates. Publish copies atomically with session, runtime and cache metadata checks. |
||
|
|
8812923eda |
perf(enhance): cut fixed config-generation cost
Every settings toggle reparsed the profile and chain files, ran four Boa interpreters, serialized the runtime config twice, and re-ran mihomo -t over bytes the core had just accepted. Builtin and template scripts now run without Boa, custom scripts bind the config through JSON.parse and take ownership instead of per-script clones, the config serializes once, and mihomo -t is skipped unless the bytes, core build, or geo assets changed. Heavy parses and serializations moved to spawn_blocking. Large-subscription toggles drop from hundreds of milliseconds to ~140ms with no new retained state. |
||
|
|
380d03cb97 |
fix(macos): discard a core cache the current user cannot write (#7883)
* fix(macos): discard a core cache the current user cannot write * docs(changelog): add the unwritable core cache fix * docs: update changelog to include Linux in cache.db ownership fix --------- Co-authored-by: oomeow <oomeow@outlook.com> |
||
|
|
2f370d6490 |
refactor(log): in-place writer lifecycle and span-based core observability (#7889)
* refactor(log): migrate logging to tracing-estuary pipeline Swap flexi_logger + clash-verge-logger wiring for the tracing-estuary crate: buffered file sink with explicit panic/exit drains, live level switching, and tokio-trace/chrome-trace behind crate features. AsyncLogger moves in-house (VecDeque ring); file format and rotation stay unchanged. * fix(log): reset sidecar writer in place and re-pin service-ipc v2.6.7 Rebuilding the sidecar FileLogWriter on config changes leaked flexi's unstoppable flusher thread plus an fd each time; the writer is now flushed and reset in place, matching what the service crate does. get_clash_logs_by_service drops the CompactString conversion layer now that service-ipc v2.6.7 returns plain Vec<String>, and AsyncLogger is renamed LogRing to match. * refactor(log): span-based observability and log noise cleanup Instrument spans carry the structure flat lines never could: the core-start spine (mode, readiness/owner generations, pid, config file), proxy apply and clear routes with guard generations, service IPC sessions with refusal codes and outcomes, profile-switch terminal outcomes, subscription fetch strategies, core upgrades with per-proxy version probes, backup flows, timer tasks, config generation uids, and the startup setup flow; running-mode changes emit one guarded transition event each. ~90 hand-written noise lines are gone or demoted (entry+success pairs, polled getter echoes, phase brackets, window sub-steps, platform install chatter); errors keep their anyhow chain, operation name, and item id, and swallowed retry results surface per attempt. |
||
|
|
807f9a206d | chore: trim excessive comments | ||
|
|
c5b641e421 | fix: make profile deletion rollback-safe | ||
|
|
1599ca0e09 | fix: add context to file-not-found errors (#7665) | ||
|
|
3d8d7731e1 |
fix: node selection persistence (#7620)
* fix(core): put the user's node choices back when the core starts mihomo restores the node picked in each group from the `cache.db` it keeps in the directory it was started against. The app relied on that entirely, and it does not hold: `profile.store-selected` comes from a merge template a user is free to replace, and a service older than the durable runtime generation starts every core in a directory nothing has ever run in. Both end the same way — every `select` group falls back to the first entry in its `proxies:` list. The app already knows better. It records each selection in the profile, and `activate_selected_nodes` already reconciles that record against the running core — it was only ever called when switching profiles, never when a core came up. Call it from the three places a core process becomes ready. Repeat calls supersede each other, so no coordination is needed between the start paths. That makes the profile authoritative, which turns any selection it does not know about into one the next start silently undoes. The chain proxy moved a group without recording it, so recording is now one shared hook that both it and the proxy list go through. Restoration is spawned, not awaited: it polls the core until its groups are readable, and a start must not wait for that. * fix(tray): record the node the tray switched to Restoring the profile's selections when a core starts made the profile authoritative, which turns any selection it never learned about into one the next start silently undoes. The proxy list and the chain proxy both record; the tray did not. So switching node from the tray survived only until the next restart, and then reverted to whatever the profile last knew — a regression the restoration itself introduced, and only for the tray. `record_selected_node` is the backend counterpart of the frontend's `useRecordSelection`. Failing to record does not fail the switch: the core is already on the new node by then, and reporting the switch as failed would be wrong. It is logged instead. * fix(core): restoring selections must not prune what the core has not loaded Putting the profile's selections back when a core starts reused the reconciliation written for profile switches, and that one also *repairs*: a record whose group is absent from two snapshots a second apart is dropped, and the reduced list is written to profiles.yaml. After a profile switch the configuration is loaded, so absence is evidence. After a core start it is not — a provider-backed group can be empty or missing for seconds — and a record pruned on that evidence is gone for good, because the provider finishing later cannot bring it back. Restoring now keeps the records and only applies what it can match; pruning stays with the caller entitled to conclude it. The restore is also asynchronous: it reads the profile, polls the core until its groups are readable, then puts its selections. A choice the user makes inside that window is newer than what it captured, so letting it finish pushed the core back to the older node while the profile already held the newer one. Recording a selection now supersedes any activation in flight — from the tray, and from the UI and chain proxy through `patch_profile`. * fix(core): activate the selections of the profile that is actually running The activation worker read the profiles draft. A profile switch stages its target there before validating it, so a switch that fails — leaving the previous profile running — could still have handed an activation the rejected profile's selections, which it would then apply to whichever same-named groups the running profile has. Reading the committed state removes the window. The switch that succeeds commits before it activates, so nothing changes for that caller; what changes is that a restore running at core start can no longer observe a switch that never happened. * fix(core): stop a restoration from undoing a choice made while it runs Two gaps in making the profile authoritative, both found by adversarial review of the commits that introduced it. A restoration reads the profile's selections once, then polls the core until its groups can be read — seconds, on a cold start. A selection made inside that window is newer than what the restoration is carrying, and nothing told the restoration so: it went on to apply the older choice over the user's. The UI accepted the new node and traffic snapped back to the old one, with the profile and the running core then disagreeing. Recording a selection now abandons any restoration still in flight, through the same generation counter every other superseding caller uses. The other gap is the home card in global mode, which passed `skipConfigSave` and so recorded nothing. That was harmless while nothing re-applied the profile; now it means the next start undoes the choice. It was the only caller that ever set the flag, so the flag is gone rather than flipped — a parameter whose one use was a bug is not worth keeping. * fix(core): wait for the selections that can be put back, keep trying for the rest Two gaps in restoring the profile's selections when a core starts, both found by adversarial review. Restoring re-checked once, a second later, and stopped. That is enough after a profile switch, which happens with the configuration already loaded. A core start is the opposite case: a provider-backed group is present but empty until its provider finishes loading, and a `select` can fail while the core is still settling. Neither produces an activation, so the restore reported success having applied nothing and the group stayed on the first entry of its `proxies:` list — the outcome restoring exists to prevent. It now keeps looking, on a deadline, at what the core is actually on rather than at what it managed to send. Restoring was also spawned, and the caller enables the system proxy the moment the start returns — so traffic could be pointed at a core still on the wrong node. The first pass is now awaited, bounded, and the rest keeps settling in the background: a core that will not answer delays a start rather than blocking it, because being proxied through the wrong node beats not being proxied at all. TUN is deliberately not covered, and cannot be by anything here: it is configured in the core's own file, so it carries traffic from the moment the process starts. What puts a TUN user on the right node from the first packet is the core's own `cache.db`, which is why the service keeps an owner's runtime generation across restarts. `supersede_selected_activation` and `cancel_selected_node_activation` were the same function under two names, added independently for the same reason, and `patch_profile` called both. One survives, called once, after the profile is written — the only placement that needs to exist, since an activation that read the older profile is cancelled by it and one starting afterwards reads the newer one. * fix(core): record a selection by naming it, not by resending the list Recording a node selection sent the whole selection list, built from the profile the frontend had rendered. Two selections made before that list refreshed were therefore built from the same stale snapshot, and the later write dropped the earlier group's choice. Since a core start re-applies whatever the profile holds, the dropped one came back on the next restart — the profile and the running core disagreeing, in the direction the user would least expect. The tray already avoided this, because it went through `record_selected_node`, which merges one group into the profile inside `with_data_modify`. Exposing that as a command and pointing the frontend at it leaves one way to record a selection instead of two, and removes the list from the wire: what a caller knows is the group and the node, and that is now all it says. `useRecordSelection` no longer reads the profile at all, which also makes it stable across renders rather than changing identity whenever the profile does. * test(core): make every way of declining to stage answer for itself `CoreRestarted` was added to `StageRejection` upstream and reached production without a test. It inherited the right verdict — every `RestartRequired` is matched together — but nothing said so, and nothing would have noticed if it had inherited the wrong one. The list of rejections now goes through a wrapper whose `match` is exhaustive, so the next variant added upstream fails to compile here. That is the part worth having: it does not prove the list is complete, but it does mean nobody can add a way to decline without being sent to this test to say what it should lead to. * build(deps): pin the service protocol to v2.6.1 The pin tracked `feat/stage-runtime` because the protocol change it carried had no tag yet. It has one now, and a branch pin makes the build irreproducible: an upstream force-push silently changes what this compiles against. v2.6.1 carries the runtime generation an owner keeps across restarts, which is what lets the core hold on to the `cache.db` its node selections and fake-ip leases live in. The protocol itself is untouched — epoch, revision and both compatibility floors are byte-identical to v2.6.0 — so this is a fix release in both directions: an older service still works with this app, and this app still works with an older service, only without the durable generation. The lockfile change is the two lines that name it. Reaching for `cargo update -p` instead re-resolved a subtree and quietly downgraded `windows-sys`, `windows-core` and `getrandom` along the way. |
||
|
|
b71a1e4ec5 |
refactor: mihomo ipc (#7601)
* refactor: mihomo ipc request * refactor: remove redundant write locks and await on mihomo handle * fix(rule): handle non-string types in ProviderButton labels * refactor: handle non-string value types in RuleItem component * refactor(tauri): remove unnecessary await in get_base_config call * chore: update tauri-plugin-mihomo deps * refactor: rename ConnectionId to WsConnectionId * chore: update tauri-plugin-mihomo-api dependency reference * chore(config): use Proxy::default in profile test initialization |
||
|
|
c90de1355e |
refactor: core runstate (#7602)
* refactor(core): introduce core::runstate as the owner of Run State
"Is the Service available?" had five caches and three predicates, and
prepare_startup consulted all three within thirty lines. This lands the
foundation for collapsing that, with no behaviour change: the old owners
now delegate into one store.
The state model splits observation from intent. Five of ServiceStatus's
ten variants were never observations — cmd/service.rs passed
ServiceStatus::InstallRequired as the "which operation do you want"
argument — which is why narrowing to ServiceInstallState had to be lossy.
ServiceHealth now records what we saw, PendingAction records what the
session asked for, and ServiceStatus::from_run_state flattens the pair
for call sites that still expect the single slot.
Reads differ only in freshness: state() is cached, settled() waits for an
in-flight privileged operation, probe() forces IPC. What an answer means
lives on the snapshot (service_usable, tun_capable), so callers stop
writing their own formulas — the tray now asks tun_capable() instead of
recomputing "admin or ready".
Effects sit behind RunStateEnv with two adapters, RealEnv and FakeEnv.
That retires the seven tests that hand-built a private ServiceManager
struct literal, and makes the probe and detection paths testable for the
first time.
Two distinctions are now explicit rather than incidental:
- A single failed probe is not an observation and leaves confirmed
health intact; exhausting a poll's whole retry budget is one and
records unavailable. Both are tested, protecting
|
||
|
|
23dda47641 |
feat: add launch guard and secure multi-user service ownership (#7569)
* feat(service): isolate macOS launch and owner runtime * ci(windows): run owner security tests * chore(deps): use kode-bridge v0.4.1 tag * fix(macos): classify installed service state * fix(macos): classify marked unavailable service * fix(macos): gate core startup on service migration * fix(macos): scope service init to supported platforms * feat(macos): prompt before migrating installed service * fix(macos): shorten sidecar IPC path * build(service): pin helper protocol and artifacts * fix(core): require confirmed service and sidecar readiness * fix(macos): harden launch roots and singleton state * fix(ui): refresh migration state before restart * fix(macos): linearize service migration lifecycle * fix(ui): keep service migration state fresh * feat(service): track authenticated owner sessions * fix(service): preserve newer owner sessions * feat(macos): route service proxy changes through helper * fix(macos): serialize service proxy guard * fix(macos): close service proxy owner lifecycle * fix(macos): close remaining proxy stop races * fix(app): do not cancel controlled service stop * fix(lifecycle): keep controlled updates cancellation-safe * fix(macos): stage dev core for service * test(macos): exercise staged core cleanup * fix(dev): await controlled macOS exit * chore: update changelog * fix(macos): recover sidecar after service install failure Allow the existing sidecar to continue when service installation leaves the manager in InstallRequired, then settle the session state as SidecarAllowed. Show neutral status text while the migration dialog waits for its final state. * fix(macos): stage dev service tools before elevation * fix(macos): localize launch guard prompts * fix(service): address cross-platform integration issues * feat: support seamless service migration * fix: pass Windows service installer path safely * fix(prebuild): derive service release from Cargo dependency * fix(dev): preserve service installation state * fix: resolve clippy warnings in service lifecycle |
||
|
|
6e9288437f |
Related to #6759 (windows): ensure sidecar process dies with the main app (#6853)
* fix(windows): ensure sidecar process dies with the main app * chore: fix clippy lints * chore: fix TS2307 error on commit. chore: Undo the changes about package.json and pnpm-lock.yaml * Fix formatting errors caused by merging. 刚刚的合并让原本的函数少了个结尾括号 * fix(windows): close process handle after assigning sidecar to job object * fix(windows): sidecar Job Object 错误改为向上传播并补充测试 将 job 创建逻辑抽为返回 Result<OwnedHandle> 的独立函数,任一 Win32 调用失败时 终止已 spawn 的子进程并返回 Err,不再静默降级。句柄由裸 isize 改为 OwnedHandle, 借助 RAII 自动关闭。新增 Windows 单元测试,覆盖 KILL_ON_JOB_CLOSE 生命周期 及无效 PID 的失败路径。 --------- Co-authored-by: wonfen <96291150+wonfen@users.noreply.github.com> |
||
|
|
1112f0730d |
fix(core): improve service startup and cleanup reliability
Wait longer for slow Windows service startup, then hand off from sidecar to service when it becomes ready. Retry service core startup during the handoff window, and clean up root-owned macOS service core/IPC leftovers before uninstalling the service. |
||
|
|
425096e8af |
chore(deps): lock file maintenance cargo dependencies (#6167)
* chore(deps): lock file maintenance cargo dependencies * chore: run cargo upgrade and cargo update * chore: fix clippy --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Slinetrac <realakayuki@gmail.com> |
||
|
|
421bbd090e | feat: reconfig log dynamically (#5724) | ||
|
|
cceb0a6eb4 |
fix(permissions): manage umask for sidecar process in CoreManager on Unix
Co-authored-by: KaguraNaku <97681505+KaguraNaku@users.noreply.github.com> |
||
|
|
2ca8e6716d | style: adjust rustfmt max_width to 120 | ||
|
|
9388b73c1f |
fix: upgrade mihomo core failed (#5646)
* fix: upgrade mihomo core failed * fix: upgrade core failed when run core by service * fix: app freeze when restart core on windows * deps: bump clash-verge-rev-ipc version lock --------- Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com> |
||
|
|
108a05ce96 | refactor: replace CommandChildGuard with CommandChild and simplify related methods | ||
|
|
0866b93175 |
feat(logging): introduce clash-verge-logging crate for management (#5486)
* feat(logging): introduce clash-verge-logging crate for management - Added a new crate `clash-verge-logging` with dependencies on `log`, `tokio`, `compact_str`, and `flexi_logger`. - Implemented logging types and macros for structured logging across the application. - Replaced existing logging imports with the new `clash_verge_logging` crate in various modules. - Updated logging functionality to support different logging types and error handling. - Refactored code to improve logging consistency and maintainability. * fix(logging): update import paths for clash_verge_logging in linux.rs and dns.rs * fix(logging): update import statement for clash_verge_logging in windows.rs |
||
|
|
a6cb903fe6 | refactor: simplify function return types and remove unnecessary wraps | ||
|
|
4eeb883464 | refactor: update imports to use as _ for unused identifiers across multiple files | ||
|
|
69a706b438 | refactor: streamline error handling and resource management in various modules | ||
|
|
2287ea5f0b |
Refactor configuration access to use latest_arc() instead of latest_ref()
- Updated multiple instances in the codebase to replace calls to latest_ref() with latest_arc() for improved performance and memory management. - This change affects various modules including validate, enhance, feat (backup, clash, config, profile, proxy, window), utils (draft, i18n, init, network, resolve, server). - Ensured that all references to configuration data are now using the new arc-based approach to enhance concurrency and reduce cloning overhead. refactor: update imports to explicitly include ClashInfo and Config in command files |
||
|
|
4babc72754 | feat: integrate arc-swap for improved concurrency in CoreManager and Hotkey(onMac) management | ||
|
|
f4de4738f1 | refactor(logger): replace ClashLogger with CLASH_LOGGER and update log handling; improve log retrieval and management | ||
|
|
2a7ccb5bde | refactor(core): optimize RunningMode handling and improve state management | ||
|
|
a05ea64bcd |
perf: utilize smartstring for string handling (#5149)
* perf: utilize smartstring for string handling - Updated various modules to replace standard String with smartstring::alias::String for improved performance and memory efficiency. - Adjusted string manipulations and conversions throughout the codebase to ensure compatibility with the new smartstring type. - Enhanced readability and maintainability by using `.into()` for conversions where applicable. - Ensured that all instances of string handling in configuration, logging, and network management leverage the benefits of smartstring. * fix: replace wrap_err with stringify_err for better error handling in UWP tool invocation * refactor: update import path for StringifyErr and adjust string handling in sysopt * fix: correct import path for CmdResult in UWP module * fix: update argument type for execute_sysproxy_command to use std::string::String * fix: add missing CmdResult import in UWP platform module * fix: improve string handling and error messaging across multiple files * style: format code for improved readability and consistency across multiple files * fix: remove unused file |
||
|
|
ef3f8e1839 | style: clean up whitespace and improve code formatting across multiple files | ||
|
|
0e933597f5 | refactor: streamline SWR configuration and improve error handling in AppDataProvider |