Compare commits

...

7 Commits

Author SHA1 Message Date
renovate[bot]
a4c537541e
chore(deps): update rust crate rust-i18n to v4 (#6784)
* chore(deps): update rust crate rust-i18n to v4

* fix: migrate rust-i18n to v4 with Cow-first zero-copy approach

- Adapt to v4 breaking changes: available_locales!() returns Vec<Cow<'static, str>>
- Cache locales in LazyLock<Vec<Cow<'static, str>>> to avoid repeated Vec alloc + sort
- Propagate Cow<'static, str> through resolve/current/system_language APIs
- Fix t! macro args branch: into_owned() + Cow::Owned for type correctness
- Eliminate double resolve in sync_locale (skip redundant set_locale indirection)
- Replace .to_string() with .into_owned() / Cow passthrough in updater.rs

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com>
2026-04-12 11:11:16 +00:00
renovate[bot]
9e32fba13e
chore(deps): update github actions (#6774)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-12 10:15:18 +00:00
renovate[bot]
7a5c314d89
chore(deps): update npm dependencies to v19.2.5 (#6762)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-12 10:15:00 +00:00
HuangTao
c358b917d6
为项目添加 github 的 Provenance 机制 (#6633)
* ci: add github provenance attestations

* ci: disable updater metadata in dev workflow

* ci: add provenance smoke test workflow

* build: fallback to alpha release assets api

* ci: remove signing env from dev workflow

* ci: disable updater artifacts in linux dev validation

* ci: support alpha manual trigger tag input

* ci: remove provenance validation scaffolding

* ci: drop redundant provenance job permissions

* ci: limit provenance to release workflow
2026-04-12 09:50:44 +00:00
Tunglies
749b6c9e30
feat(script): convert script execution to async and add timeout handling 2026-04-12 11:20:28 +08:00
Tunglies
e6a88cf9c9
refactor: improve service manager initialization by reducing lock duration 2026-04-12 11:15:34 +08:00
Tunglies
0f41f1bc8d
refactor: optimize deep_merge function using iterative stack approach 2026-04-12 11:13:17 +08:00
18 changed files with 291 additions and 233 deletions

View File

@ -38,7 +38,7 @@ jobs:
run: bash ./scripts/extract_update_logs.sh run: bash ./scripts/extract_update_logs.sh
shell: bash shell: bash
- uses: pnpm/action-setup@v5.0.0 - uses: pnpm/action-setup@v6.0.0
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@ -102,7 +102,7 @@ jobs:
EOF EOF
- name: Upload Release - name: Upload Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v3
with: with:
tag_name: ${{ env.TAG_NAME }} tag_name: ${{ env.TAG_NAME }}
name: 'Clash Verge Rev ${{ env.TAG_CHANNEL }}' name: 'Clash Verge Rev ${{ env.TAG_CHANNEL }}'
@ -179,7 +179,7 @@ jobs:
echo "OPENSSL_LIB_DIR=$(brew --prefix openssl@3)/lib" >> $GITHUB_ENV echo "OPENSSL_LIB_DIR=$(brew --prefix openssl@3)/lib" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=$(brew --prefix openssl@3)/lib/pkgconfig" >> $GITHUB_ENV echo "PKG_CONFIG_PATH=$(brew --prefix openssl@3)/lib/pkgconfig" >> $GITHUB_ENV
- uses: pnpm/action-setup@v5.0.0 - uses: pnpm/action-setup@v6.0.0
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@ -278,7 +278,7 @@ jobs:
cache-workspace-crates: true cache-workspace-crates: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v5.0.0 uses: pnpm/action-setup@v6.0.0
with: with:
run_install: false run_install: false
@ -379,7 +379,7 @@ jobs:
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
- name: Upload Release - name: Upload Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v3
with: with:
tag_name: ${{ env.TAG_NAME }} tag_name: ${{ env.TAG_NAME }}
name: 'Clash Verge Rev ${{ env.TAG_CHANNEL }}' name: 'Clash Verge Rev ${{ env.TAG_CHANNEL }}'
@ -423,7 +423,7 @@ jobs:
cache-workspace-crates: true cache-workspace-crates: true
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v5.0.0 uses: pnpm/action-setup@v6.0.0
with: with:
run_install: false run_install: false
@ -497,7 +497,7 @@ jobs:
} }
- name: Upload Release - name: Upload Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v3
with: with:
tag_name: ${{ env.TAG_NAME }} tag_name: ${{ env.TAG_NAME }}
name: 'Clash Verge Rev ${{ env.TAG_CHANNEL }}' name: 'Clash Verge Rev ${{ env.TAG_CHANNEL }}'
@ -534,7 +534,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5.0.0 - uses: pnpm/action-setup@v6.0.0
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false

View File

@ -45,7 +45,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false

View File

@ -93,7 +93,7 @@ jobs:
sudo apt-get update sudo apt-get update
sudo apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf sudo apt-get install -y libxslt1.1 libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev patchelf
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
if: github.event.inputs[matrix.input] == 'true' if: github.event.inputs[matrix.input] == 'true'
with: with:

View File

@ -40,7 +40,7 @@ jobs:
- name: Install pnpm - name: Install pnpm
if: steps.check_frontend.outputs.frontend == 'true' if: steps.check_frontend.outputs.frontend == 'true'
uses: pnpm/action-setup@v5 uses: pnpm/action-setup@v6
with: with:
run_install: false run_install: false

View File

@ -82,7 +82,7 @@ jobs:
GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_AWMG_VERSION: ""
GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_INFO_FIREWALL_TYPE: "squid"
GH_AW_COMPILED_STRICT: "true" GH_AW_COMPILED_STRICT: "true"
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with: with:
script: | script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@ -104,7 +104,7 @@ jobs:
sparse-checkout-cone-mode: true sparse-checkout-cone-mode: true
fetch-depth: 1 fetch-depth: 1
- name: Check workflow file timestamps - name: Check workflow file timestamps
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_WORKFLOW_FILE: "pr-ai-slop-review.lock.yml" GH_AW_WORKFLOW_FILE: "pr-ai-slop-review.lock.yml"
with: with:
@ -115,7 +115,7 @@ jobs:
await main(); await main();
- name: Compute current body text - name: Compute current body text
id: sanitized id: sanitized
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with: with:
script: | script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@ -186,7 +186,7 @@ jobs:
GH_AW_PROMPT_EOF GH_AW_PROMPT_EOF
} > "$GH_AW_PROMPT" } > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates - name: Interpolate variables and render templates
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
with: with:
@ -196,7 +196,7 @@ jobs:
const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs');
await main(); await main();
- name: Substitute placeholders - name: Substitute placeholders
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_ACTOR: ${{ github.actor }}
@ -305,7 +305,7 @@ jobs:
id: checkout-pr id: checkout-pr
if: | if: |
github.event.pull_request || github.event.issue.pull_request github.event.pull_request || github.event.issue.pull_request
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
with: with:
@ -653,7 +653,7 @@ jobs:
bash ${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" bash ${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID"
- name: Redact secrets in logs - name: Redact secrets in logs
if: always() if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with: with:
script: | script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@ -677,7 +677,7 @@ jobs:
- name: Ingest agent output - name: Ingest agent output
id: collect_output id: collect_output
if: always() if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
@ -692,7 +692,7 @@ jobs:
await main(); await main();
- name: Parse agent logs for step summary - name: Parse agent logs for step summary
if: always() if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/
with: with:
@ -703,7 +703,7 @@ jobs:
await main(); await main();
- name: Parse MCP Gateway logs for step summary - name: Parse MCP Gateway logs for step summary
if: always() if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with: with:
script: | script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@ -776,7 +776,7 @@ jobs:
ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
- name: Setup threat detection - name: Setup threat detection
if: always() && steps.detection_guard.outputs.run_detection == 'true' if: always() && steps.detection_guard.outputs.run_detection == 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
WORKFLOW_NAME: "PR AI Slop Review" WORKFLOW_NAME: "PR AI Slop Review"
WORKFLOW_DESCRIPTION: "Reviews incoming pull requests for missing issue linkage and high-confidence\nsigns of one-shot AI-generated changes, then posts a maintainer-focused\ncomment when the risk is high enough to warrant follow-up." WORKFLOW_DESCRIPTION: "Reviews incoming pull requests for missing issue linkage and high-confidence\nsigns of one-shot AI-generated changes, then posts a maintainer-focused\ncomment when the risk is high enough to warrant follow-up."
@ -832,7 +832,7 @@ jobs:
- name: Parse threat detection results - name: Parse threat detection results
id: parse_detection_results id: parse_detection_results
if: always() && steps.detection_guard.outputs.run_detection == 'true' if: always() && steps.detection_guard.outputs.run_detection == 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with: with:
script: | script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@ -906,7 +906,7 @@ jobs:
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_ENV" echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_ENV"
- name: Process No-Op Messages - name: Process No-Op Messages
id: noop id: noop
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_NOOP_MAX: "1" GH_AW_NOOP_MAX: "1"
@ -920,7 +920,7 @@ jobs:
await main(); await main();
- name: Record Missing Tool - name: Record Missing Tool
id: missing_tool id: missing_tool
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_NAME: "PR AI Slop Review"
@ -934,7 +934,7 @@ jobs:
- name: Handle Agent Failure - name: Handle Agent Failure
id: handle_agent_failure id: handle_agent_failure
if: always() if: always()
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_NAME: "PR AI Slop Review"
@ -957,7 +957,7 @@ jobs:
await main(); await main();
- name: Handle No-Op Message - name: Handle No-Op Message
id: handle_noop_message id: handle_noop_message
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_NAME: "PR AI Slop Review"
@ -1025,7 +1025,7 @@ jobs:
echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
- name: Process Safe Outputs - name: Process Safe Outputs
id: process_safe_outputs id: process_safe_outputs
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env: env:
GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"

View File

@ -126,7 +126,7 @@ jobs:
EOF EOF
- name: Upload Release - name: Upload Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v3
with: with:
tag_name: ${{ env.TAG_NAME }} tag_name: ${{ env.TAG_NAME }}
name: 'Clash Verge Rev ${{ env.TAG_NAME }}' name: 'Clash Verge Rev ${{ env.TAG_NAME }}'
@ -199,7 +199,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@ -240,6 +240,26 @@ jobs:
args: --target ${{ matrix.target }} args: --target ${{ matrix.target }}
includeUpdaterJson: true includeUpdaterJson: true
- name: Attest Windows bundles
if: matrix.os == 'windows-latest'
uses: actions/attest-build-provenance@v4
with:
subject-path: target/${{ matrix.target }}/release/bundle/nsis/*setup*
- name: Attest macOS bundles
if: matrix.os == 'macos-latest'
uses: actions/attest-build-provenance@v4
with:
subject-path: target/${{ matrix.target }}/release/bundle/dmg/*.dmg
- name: Attest Linux bundles
if: matrix.os == 'ubuntu-22.04'
uses: actions/attest-build-provenance@v4
with:
subject-path: |
target/${{ matrix.target }}/release/bundle/deb/*.deb
target/${{ matrix.target }}/release/bundle/rpm/*.rpm
release-for-linux-arm: release-for-linux-arm:
name: Release Build for Linux ARM name: Release Build for Linux ARM
needs: [check_tag_version] needs: [check_tag_version]
@ -284,7 +304,7 @@ jobs:
node-version: '24.14.1' node-version: '24.14.1'
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v5 uses: pnpm/action-setup@v6
with: with:
run_install: false run_install: false
@ -367,8 +387,15 @@ jobs:
echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
- name: Attest Linux bundles
uses: actions/attest-build-provenance@v4
with:
subject-path: |
target/${{ matrix.target }}/release/bundle/deb/*.deb
target/${{ matrix.target }}/release/bundle/rpm/*.rpm
- name: Upload Release - name: Upload Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v3
with: with:
tag_name: v${{env.VERSION}} tag_name: v${{env.VERSION}}
name: 'Clash Verge Rev v${{env.VERSION}}' name: 'Clash Verge Rev v${{env.VERSION}}'
@ -422,7 +449,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@ -478,8 +505,13 @@ jobs:
Rename-Item $file.FullName $newName Rename-Item $file.FullName $newName
} }
- name: Attest Windows bundles
uses: actions/attest-build-provenance@v4
with:
subject-path: target/${{ matrix.target }}/release/bundle/nsis/*setup*
- name: Upload Release - name: Upload Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v3
with: with:
tag_name: v${{steps.build.outputs.appVersion}} tag_name: v${{steps.build.outputs.appVersion}}
name: 'Clash Verge Rev v${{steps.build.outputs.appVersion}}' name: 'Clash Verge Rev v${{steps.build.outputs.appVersion}}'
@ -507,7 +539,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@ -533,7 +565,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@ -595,7 +627,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false

View File

@ -36,7 +36,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false

View File

@ -17,7 +17,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false
@ -41,7 +41,7 @@ jobs:
with: with:
node-version: '24.14.1' node-version: '24.14.1'
- uses: pnpm/action-setup@v5 - uses: pnpm/action-setup@v6
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false

15
Cargo.lock generated
View File

@ -6261,12 +6261,11 @@ dependencies = [
[[package]] [[package]]
name = "rust-i18n" name = "rust-i18n"
version = "3.1.5" version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fda2551fdfaf6cc5ee283adc15e157047b92ae6535cf80f6d4962d05717dc332" checksum = "21031bf5e6f2c0ae745d831791c403608e99a8bd3776c7e5e5535acd70c3b7ba"
dependencies = [ dependencies = [
"globwalk", "globwalk",
"once_cell",
"regex", "regex",
"rust-i18n-macro", "rust-i18n-macro",
"rust-i18n-support", "rust-i18n-support",
@ -6275,12 +6274,11 @@ dependencies = [
[[package]] [[package]]
name = "rust-i18n-macro" name = "rust-i18n-macro"
version = "3.1.5" version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22baf7d7f56656d23ebe24f6bb57a5d40d2bce2a5f1c503e692b5b2fa450f965" checksum = "51fe5295763b358606f7ca26a564e20f4469775a57ec1f09431249a33849ff52"
dependencies = [ dependencies = [
"glob", "glob",
"once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"rust-i18n-support", "rust-i18n-support",
@ -6292,9 +6290,9 @@ dependencies = [
[[package]] [[package]]
name = "rust-i18n-support" name = "rust-i18n-support"
version = "3.1.5" version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "940ed4f52bba4c0152056d771e563b7133ad9607d4384af016a134b58d758f19" checksum = "69bcc115c8eea2803aa3d85362e339776f4988a0349f2f475af572e497443f6f"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"base62", "base62",
@ -6302,7 +6300,6 @@ dependencies = [
"itertools 0.11.0", "itertools 0.11.0",
"lazy_static", "lazy_static",
"normpath", "normpath",
"once_cell",
"proc-macro2", "proc-macro2",
"regex", "regex",
"serde", "serde",

View File

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
rust-i18n = "3.1.5" rust-i18n = "4.0.0"
sys-locale = "0.3.2" sys-locale = "0.3.2"
[lints] [lints]

View File

@ -1,8 +1,12 @@
use rust_i18n::i18n; use rust_i18n::i18n;
use std::borrow::Cow;
use std::sync::LazyLock;
const DEFAULT_LANGUAGE: &str = "zh"; const DEFAULT_LANGUAGE: &str = "zh";
i18n!("locales", fallback = "zh"); i18n!("locales", fallback = "zh");
static SUPPORTED_LOCALES: LazyLock<Vec<Cow<'static, str>>> = LazyLock::new(|| rust_i18n::available_locales!());
#[inline] #[inline]
fn locale_alias(locale: &str) -> Option<&'static str> { fn locale_alias(locale: &str) -> Option<&'static str> {
match locale { match locale {
@ -14,54 +18,51 @@ fn locale_alias(locale: &str) -> Option<&'static str> {
} }
#[inline] #[inline]
fn resolve_supported_language(language: &str) -> Option<&'static str> { fn resolve_supported_language(language: &str) -> Option<Cow<'static, str>> {
if language.is_empty() { if language.is_empty() {
return None; return None;
} }
let normalized = language.to_lowercase().replace('_', "-"); let normalized = language.to_lowercase().replace('_', "-");
let segments: Vec<&str> = normalized.split('-').collect(); let segments: Vec<&str> = normalized.split('-').collect();
let supported = rust_i18n::available_locales!();
for i in (1..=segments.len()).rev() { for i in (1..=segments.len()).rev() {
let prefix = segments[..i].join("-"); let prefix = segments[..i].join("-");
if let Some(alias) = locale_alias(&prefix) if let Some(alias) = locale_alias(&prefix)
&& let Some(&found) = supported.iter().find(|&&l| l.eq_ignore_ascii_case(alias)) && let Some(found) = SUPPORTED_LOCALES.iter().find(|l| l.eq_ignore_ascii_case(alias))
{ {
return Some(found); return Some(found.clone());
} }
if let Some(&found) = supported.iter().find(|&&l| l.eq_ignore_ascii_case(&prefix)) { if let Some(found) = SUPPORTED_LOCALES.iter().find(|l| l.eq_ignore_ascii_case(&prefix)) {
return Some(found); return Some(found.clone());
} }
} }
None None
} }
#[inline] #[inline]
fn current_language(language: Option<&str>) -> &str { fn current_language(language: Option<&str>) -> Cow<'static, str> {
language language
.as_ref()
.filter(|lang| !lang.is_empty()) .filter(|lang| !lang.is_empty())
.and_then(|lang| resolve_supported_language(lang)) .and_then(resolve_supported_language)
.unwrap_or_else(system_language) .unwrap_or_else(system_language)
} }
#[inline] #[inline]
pub fn system_language() -> &'static str { pub fn system_language() -> Cow<'static, str> {
sys_locale::get_locale() sys_locale::get_locale()
.as_deref() .as_deref()
.and_then(resolve_supported_language) .and_then(resolve_supported_language)
.unwrap_or(DEFAULT_LANGUAGE) .unwrap_or(Cow::Borrowed(DEFAULT_LANGUAGE))
} }
#[inline] #[inline]
pub fn sync_locale(language: Option<&str>) { pub fn sync_locale(language: Option<&str>) {
let language = current_language(language); rust_i18n::set_locale(&current_language(language));
set_locale(language);
} }
#[inline] #[inline]
pub fn set_locale(language: &str) { pub fn set_locale(language: &str) {
let lang = resolve_supported_language(language).unwrap_or(DEFAULT_LANGUAGE); let lang = resolve_supported_language(language).unwrap_or(Cow::Borrowed(DEFAULT_LANGUAGE));
rust_i18n::set_locale(lang); rust_i18n::set_locale(&lang);
} }
#[inline] #[inline]
@ -76,11 +77,11 @@ macro_rules! t {
}; };
($key:expr, $($arg_name:ident = $arg_value:expr),*) => { ($key:expr, $($arg_name:ident = $arg_value:expr),*) => {
{ {
let mut _text = $crate::translate(&$key); let mut _text = $crate::translate(&$key).into_owned();
$( $(
_text = _text.replace(&format!("{{{}}}", stringify!($arg_name)), &$arg_value); _text = _text.replace(&format!("{{{}}}", stringify!($arg_name)), &$arg_value);
)* )*
_text ::std::borrow::Cow::<'static, str>::Owned(_text)
} }
}; };
} }
@ -91,13 +92,13 @@ mod test {
#[test] #[test]
fn test_resolve_supported_language() { fn test_resolve_supported_language() {
assert_eq!(resolve_supported_language("en"), Some("en")); assert_eq!(resolve_supported_language("en").as_deref(), Some("en"));
assert_eq!(resolve_supported_language("en-US"), Some("en")); assert_eq!(resolve_supported_language("en-US").as_deref(), Some("en"));
assert_eq!(resolve_supported_language("zh"), Some("zh")); assert_eq!(resolve_supported_language("zh").as_deref(), Some("zh"));
assert_eq!(resolve_supported_language("zh-CN"), Some("zh")); assert_eq!(resolve_supported_language("zh-CN").as_deref(), Some("zh"));
assert_eq!(resolve_supported_language("zh-Hant"), Some("zhtw")); assert_eq!(resolve_supported_language("zh-Hant").as_deref(), Some("zhtw"));
assert_eq!(resolve_supported_language("jp"), Some("jp")); assert_eq!(resolve_supported_language("jp").as_deref(), Some("jp"));
assert_eq!(resolve_supported_language("ja-JP"), Some("jp")); assert_eq!(resolve_supported_language("ja-JP").as_deref(), Some("jp"));
assert_eq!(resolve_supported_language("fr"), None); assert_eq!(resolve_supported_language("fr"), None);
} }
} }

View File

@ -67,8 +67,8 @@
"monaco-editor": "^0.55.1", "monaco-editor": "^0.55.1",
"monaco-yaml": "^5.4.1", "monaco-yaml": "^5.4.1",
"nanoid": "^5.1.7", "nanoid": "^5.1.7",
"react": "19.2.4", "react": "19.2.5",
"react-dom": "19.2.4", "react-dom": "19.2.5",
"react-error-boundary": "6.1.1", "react-error-boundary": "6.1.1",
"react-hook-form": "^7.72.0", "react-hook-form": "^7.72.0",
"react-i18next": "17.0.2", "react-i18next": "17.0.2",

246
pnpm-lock.yaml generated
View File

@ -10,43 +10,43 @@ importers:
dependencies: dependencies:
'@dnd-kit/core': '@dnd-kit/core':
specifier: ^6.3.1 specifier: ^6.3.1
version: 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 6.3.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@dnd-kit/sortable': '@dnd-kit/sortable':
specifier: ^10.0.0 specifier: ^10.0.0
version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react@19.2.5)
'@dnd-kit/utilities': '@dnd-kit/utilities':
specifier: ^3.2.2 specifier: ^3.2.2
version: 3.2.2(react@19.2.4) version: 3.2.2(react@19.2.5)
'@emotion/react': '@emotion/react':
specifier: ^11.14.0 specifier: ^11.14.0
version: 11.14.0(@types/react@19.2.14)(react@19.2.4) version: 11.14.0(@types/react@19.2.14)(react@19.2.5)
'@emotion/styled': '@emotion/styled':
specifier: ^11.14.1 specifier: ^11.14.1
version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4) version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)
'@juggle/resize-observer': '@juggle/resize-observer':
specifier: ^3.4.0 specifier: ^3.4.0
version: 3.4.0 version: 3.4.0
'@monaco-editor/react': '@monaco-editor/react':
specifier: ^4.7.0 specifier: ^4.7.0
version: 4.7.0(monaco-editor@0.55.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 4.7.0(monaco-editor@0.55.1)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@mui/icons-material': '@mui/icons-material':
specifier: ^7.3.9 specifier: ^7.3.9
version: 7.3.9(@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@types/react@19.2.14)(react@19.2.4) version: 7.3.9(@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)
'@mui/lab': '@mui/lab':
specifier: 7.0.0-beta.17 specifier: 7.0.0-beta.17
version: 7.0.0-beta.17(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 7.0.0-beta.17(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@mui/material': '@mui/material':
specifier: ^7.3.9 specifier: ^7.3.9
version: 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@tanstack/react-query': '@tanstack/react-query':
specifier: ^5.96.1 specifier: ^5.96.1
version: 5.96.2(react@19.2.4) version: 5.96.2(react@19.2.5)
'@tanstack/react-table': '@tanstack/react-table':
specifier: ^8.21.3 specifier: ^8.21.3
version: 8.21.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 8.21.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@tanstack/react-virtual': '@tanstack/react-virtual':
specifier: ^3.13.23 specifier: ^3.13.23
version: 3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 3.13.23(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@tauri-apps/api': '@tauri-apps/api':
specifier: 2.10.1 specifier: 2.10.1
version: 2.10.1 version: 2.10.1
@ -73,7 +73,7 @@ importers:
version: 2.10.1 version: 2.10.1
ahooks: ahooks:
specifier: ^3.9.6 specifier: ^3.9.6
version: 3.9.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 3.9.7(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
cidr-block: cidr-block:
specifier: ^2.3.0 specifier: ^2.3.0
version: 2.3.0 version: 2.3.0
@ -82,7 +82,7 @@ importers:
version: 1.11.20 version: 1.11.20
foxact: foxact:
specifier: ^0.3.0 specifier: ^0.3.0
version: 0.3.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 0.3.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
foxts: foxts:
specifier: ^5.3.0 specifier: ^5.3.0
version: 5.4.0 version: 5.4.0
@ -108,26 +108,26 @@ importers:
specifier: ^5.1.7 specifier: ^5.1.7
version: 5.1.7 version: 5.1.7
react: react:
specifier: 19.2.4 specifier: 19.2.5
version: 19.2.4 version: 19.2.5
react-dom: react-dom:
specifier: 19.2.4 specifier: 19.2.5
version: 19.2.4(react@19.2.4) version: 19.2.5(react@19.2.5)
react-error-boundary: react-error-boundary:
specifier: 6.1.1 specifier: 6.1.1
version: 6.1.1(react@19.2.4) version: 6.1.1(react@19.2.5)
react-hook-form: react-hook-form:
specifier: ^7.72.0 specifier: ^7.72.0
version: 7.72.1(react@19.2.4) version: 7.72.1(react@19.2.5)
react-i18next: react-i18next:
specifier: 17.0.2 specifier: 17.0.2
version: 17.0.2(i18next@26.0.3(typescript@6.0.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@6.0.2) version: 17.0.2(i18next@26.0.3(typescript@6.0.2))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.2)
react-markdown: react-markdown:
specifier: 10.1.0 specifier: 10.1.0
version: 10.1.0(@types/react@19.2.14)(react@19.2.4) version: 10.1.0(@types/react@19.2.14)(react@19.2.5)
react-router: react-router:
specifier: ^7.13.1 specifier: ^7.13.1
version: 7.14.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) version: 7.14.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
rehype-raw: rehype-raw:
specifier: ^7.0.0 specifier: ^7.0.0
version: 7.0.0 version: 7.0.0
@ -3101,10 +3101,10 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'} engines: {node: '>=6'}
react-dom@19.2.4: react-dom@19.2.5:
resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==}
peerDependencies: peerDependencies:
react: ^19.2.4 react: ^19.2.5
react-error-boundary@6.1.1: react-error-boundary@6.1.1:
resolution: {integrity: sha512-BrYwPOdXi5mqkk5lw+Uvt0ThHx32rCt3BkukS4X23A2AIWDPSGX6iaWTc0y9TU/mHDA/6qOSGel+B2ERkOvD1w==} resolution: {integrity: sha512-BrYwPOdXi5mqkk5lw+Uvt0ThHx32rCt3BkukS4X23A2AIWDPSGX6iaWTc0y9TU/mHDA/6qOSGel+B2ERkOvD1w==}
@ -3164,8 +3164,8 @@ packages:
react: '>=16.6.0' react: '>=16.6.0'
react-dom: '>=16.6.0' react-dom: '>=16.6.0'
react@19.2.4: react@19.2.5:
resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
readdirp@4.1.2: readdirp@4.1.2:
@ -4331,29 +4331,29 @@ snapshots:
'@biomejs/cli-win32-x64@2.4.10': '@biomejs/cli-win32-x64@2.4.10':
optional: true optional: true
'@dnd-kit/accessibility@3.1.1(react@19.2.4)': '@dnd-kit/accessibility@3.1.1(react@19.2.5)':
dependencies: dependencies:
react: 19.2.4 react: 19.2.5
tslib: 2.8.1 tslib: 2.8.1
'@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': '@dnd-kit/core@6.3.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies: dependencies:
'@dnd-kit/accessibility': 3.1.1(react@19.2.4) '@dnd-kit/accessibility': 3.1.1(react@19.2.5)
'@dnd-kit/utilities': 3.2.2(react@19.2.4) '@dnd-kit/utilities': 3.2.2(react@19.2.5)
react: 19.2.4 react: 19.2.5
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
tslib: 2.8.1 tslib: 2.8.1
'@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)': '@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react@19.2.5)':
dependencies: dependencies:
'@dnd-kit/core': 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@dnd-kit/core': 6.3.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@dnd-kit/utilities': 3.2.2(react@19.2.4) '@dnd-kit/utilities': 3.2.2(react@19.2.5)
react: 19.2.4 react: 19.2.5
tslib: 2.8.1 tslib: 2.8.1
'@dnd-kit/utilities@3.2.2(react@19.2.4)': '@dnd-kit/utilities@3.2.2(react@19.2.5)':
dependencies: dependencies:
react: 19.2.4 react: 19.2.5
tslib: 2.8.1 tslib: 2.8.1
'@emnapi/core@1.9.2': '@emnapi/core@1.9.2':
@ -4404,17 +4404,17 @@ snapshots:
'@emotion/memoize@0.9.0': {} '@emotion/memoize@0.9.0': {}
'@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4)': '@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5)':
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@emotion/babel-plugin': 11.13.5 '@emotion/babel-plugin': 11.13.5
'@emotion/cache': 11.14.0 '@emotion/cache': 11.14.0
'@emotion/serialize': 1.3.3 '@emotion/serialize': 1.3.3
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.4) '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.5)
'@emotion/utils': 1.4.2 '@emotion/utils': 1.4.2
'@emotion/weak-memoize': 0.4.0 '@emotion/weak-memoize': 0.4.0
hoist-non-react-statics: 3.3.2 hoist-non-react-statics: 3.3.2
react: 19.2.4 react: 19.2.5
optionalDependencies: optionalDependencies:
'@types/react': 19.2.14 '@types/react': 19.2.14
transitivePeerDependencies: transitivePeerDependencies:
@ -4430,16 +4430,16 @@ snapshots:
'@emotion/sheet@1.4.0': {} '@emotion/sheet@1.4.0': {}
'@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4)': '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)':
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@emotion/babel-plugin': 11.13.5 '@emotion/babel-plugin': 11.13.5
'@emotion/is-prop-valid': 1.4.0 '@emotion/is-prop-valid': 1.4.0
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.4) '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.5)
'@emotion/serialize': 1.3.3 '@emotion/serialize': 1.3.3
'@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.4) '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.5)
'@emotion/utils': 1.4.2 '@emotion/utils': 1.4.2
react: 19.2.4 react: 19.2.5
optionalDependencies: optionalDependencies:
'@types/react': 19.2.14 '@types/react': 19.2.14
transitivePeerDependencies: transitivePeerDependencies:
@ -4447,9 +4447,9 @@ snapshots:
'@emotion/unitless@0.10.0': {} '@emotion/unitless@0.10.0': {}
'@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.4)': '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.2.5)':
dependencies: dependencies:
react: 19.2.4 react: 19.2.5
'@emotion/utils@1.4.2': {} '@emotion/utils@1.4.2': {}
@ -4617,70 +4617,70 @@ snapshots:
dependencies: dependencies:
state-local: 1.0.7 state-local: 1.0.7
'@monaco-editor/react@4.7.0(monaco-editor@0.55.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': '@monaco-editor/react@4.7.0(monaco-editor@0.55.1)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies: dependencies:
'@monaco-editor/loader': 1.7.0 '@monaco-editor/loader': 1.7.0
monaco-editor: 0.55.1 monaco-editor: 0.55.1
react: 19.2.4 react: 19.2.5
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
'@mui/core-downloads-tracker@7.3.9': {} '@mui/core-downloads-tracker@7.3.9': {}
'@mui/icons-material@7.3.9(@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@types/react@19.2.14)(react@19.2.4)': '@mui/icons-material@7.3.9(@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)':
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@mui/material': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@mui/material': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
react: 19.2.4 react: 19.2.5
optionalDependencies: optionalDependencies:
'@types/react': 19.2.14 '@types/react': 19.2.14
'@mui/lab@7.0.0-beta.17(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': '@mui/lab@7.0.0-beta.17(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@mui/material': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@mui/material': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@mui/system': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4) '@mui/system': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)
'@mui/types': 7.4.12(@types/react@19.2.14) '@mui/types': 7.4.12(@types/react@19.2.14)
'@mui/utils': 7.3.9(@types/react@19.2.14)(react@19.2.4) '@mui/utils': 7.3.9(@types/react@19.2.14)(react@19.2.5)
clsx: 2.1.1 clsx: 2.1.1
prop-types: 15.8.1 prop-types: 15.8.1
react: 19.2.4 react: 19.2.5
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
optionalDependencies: optionalDependencies:
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.4) '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.5)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4) '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)
'@types/react': 19.2.14 '@types/react': 19.2.14
'@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': '@mui/material@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@mui/core-downloads-tracker': 7.3.9 '@mui/core-downloads-tracker': 7.3.9
'@mui/system': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4) '@mui/system': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)
'@mui/types': 7.4.12(@types/react@19.2.14) '@mui/types': 7.4.12(@types/react@19.2.14)
'@mui/utils': 7.3.9(@types/react@19.2.14)(react@19.2.4) '@mui/utils': 7.3.9(@types/react@19.2.14)(react@19.2.5)
'@popperjs/core': 2.11.8 '@popperjs/core': 2.11.8
'@types/react-transition-group': 4.4.12(@types/react@19.2.14) '@types/react-transition-group': 4.4.12(@types/react@19.2.14)
clsx: 2.1.1 clsx: 2.1.1
csstype: 3.2.3 csstype: 3.2.3
prop-types: 15.8.1 prop-types: 15.8.1
react: 19.2.4 react: 19.2.5
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
react-is: 19.2.4 react-is: 19.2.4
react-transition-group: 4.4.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4) react-transition-group: 4.4.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
optionalDependencies: optionalDependencies:
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.4) '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.5)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4) '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)
'@types/react': 19.2.14 '@types/react': 19.2.14
'@mui/private-theming@7.3.9(@types/react@19.2.14)(react@19.2.4)': '@mui/private-theming@7.3.9(@types/react@19.2.14)(react@19.2.5)':
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@mui/utils': 7.3.9(@types/react@19.2.14)(react@19.2.4) '@mui/utils': 7.3.9(@types/react@19.2.14)(react@19.2.5)
prop-types: 15.8.1 prop-types: 15.8.1
react: 19.2.4 react: 19.2.5
optionalDependencies: optionalDependencies:
'@types/react': 19.2.14 '@types/react': 19.2.14
'@mui/styled-engine@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)': '@mui/styled-engine@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(react@19.2.5)':
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@emotion/cache': 11.14.0 '@emotion/cache': 11.14.0
@ -4688,25 +4688,25 @@ snapshots:
'@emotion/sheet': 1.4.0 '@emotion/sheet': 1.4.0
csstype: 3.2.3 csstype: 3.2.3
prop-types: 15.8.1 prop-types: 15.8.1
react: 19.2.4 react: 19.2.5
optionalDependencies: optionalDependencies:
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.4) '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.5)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4) '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)
'@mui/system@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4)': '@mui/system@7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)':
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@mui/private-theming': 7.3.9(@types/react@19.2.14)(react@19.2.4) '@mui/private-theming': 7.3.9(@types/react@19.2.14)(react@19.2.5)
'@mui/styled-engine': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) '@mui/styled-engine': 7.3.9(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5))(react@19.2.5)
'@mui/types': 7.4.12(@types/react@19.2.14) '@mui/types': 7.4.12(@types/react@19.2.14)
'@mui/utils': 7.3.9(@types/react@19.2.14)(react@19.2.4) '@mui/utils': 7.3.9(@types/react@19.2.14)(react@19.2.5)
clsx: 2.1.1 clsx: 2.1.1
csstype: 3.2.3 csstype: 3.2.3
prop-types: 15.8.1 prop-types: 15.8.1
react: 19.2.4 react: 19.2.5
optionalDependencies: optionalDependencies:
'@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.4) '@emotion/react': 11.14.0(@types/react@19.2.14)(react@19.2.5)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.4))(@types/react@19.2.14)(react@19.2.4) '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.14)(react@19.2.5))(@types/react@19.2.14)(react@19.2.5)
'@types/react': 19.2.14 '@types/react': 19.2.14
'@mui/types@7.4.12(@types/react@19.2.14)': '@mui/types@7.4.12(@types/react@19.2.14)':
@ -4715,14 +4715,14 @@ snapshots:
optionalDependencies: optionalDependencies:
'@types/react': 19.2.14 '@types/react': 19.2.14
'@mui/utils@7.3.9(@types/react@19.2.14)(react@19.2.4)': '@mui/utils@7.3.9(@types/react@19.2.14)(react@19.2.5)':
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@mui/types': 7.4.12(@types/react@19.2.14) '@mui/types': 7.4.12(@types/react@19.2.14)
'@types/prop-types': 15.7.15 '@types/prop-types': 15.7.15
clsx: 2.1.1 clsx: 2.1.1
prop-types: 15.8.1 prop-types: 15.8.1
react: 19.2.4 react: 19.2.5
react-is: 19.2.4 react-is: 19.2.4
optionalDependencies: optionalDependencies:
'@types/react': 19.2.14 '@types/react': 19.2.14
@ -4992,22 +4992,22 @@ snapshots:
'@tanstack/query-core@5.96.2': {} '@tanstack/query-core@5.96.2': {}
'@tanstack/react-query@5.96.2(react@19.2.4)': '@tanstack/react-query@5.96.2(react@19.2.5)':
dependencies: dependencies:
'@tanstack/query-core': 5.96.2 '@tanstack/query-core': 5.96.2
react: 19.2.4 react: 19.2.5
'@tanstack/react-table@8.21.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': '@tanstack/react-table@8.21.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies: dependencies:
'@tanstack/table-core': 8.21.3 '@tanstack/table-core': 8.21.3
react: 19.2.4 react: 19.2.5
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
'@tanstack/react-virtual@3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': '@tanstack/react-virtual@3.13.23(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies: dependencies:
'@tanstack/virtual-core': 3.13.23 '@tanstack/virtual-core': 3.13.23
react: 19.2.4 react: 19.2.5
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
'@tanstack/table-core@8.21.3': {} '@tanstack/table-core@8.21.3': {}
@ -5344,7 +5344,7 @@ snapshots:
agent-base@9.0.0: {} agent-base@9.0.0: {}
ahooks@3.9.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4): ahooks@3.9.7(react-dom@19.2.5(react@19.2.5))(react@19.2.5):
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
'@types/js-cookie': 3.0.6 '@types/js-cookie': 3.0.6
@ -5352,8 +5352,8 @@ snapshots:
intersection-observer: 0.12.2 intersection-observer: 0.12.2
js-cookie: 3.0.5 js-cookie: 3.0.5
lodash: 4.18.1 lodash: 4.18.1
react: 19.2.4 react: 19.2.5
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
react-fast-compare: 3.2.2 react-fast-compare: 3.2.2
resize-observer-polyfill: 1.5.1 resize-observer-polyfill: 1.5.1
screenfull: 5.2.0 screenfull: 5.2.0
@ -5977,14 +5977,14 @@ snapshots:
dependencies: dependencies:
fetch-blob: 3.2.0 fetch-blob: 3.2.0
foxact@0.3.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): foxact@0.3.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5):
dependencies: dependencies:
client-only: 0.0.1 client-only: 0.0.1
event-target-bus: 1.0.0 event-target-bus: 1.0.0
server-only: 0.0.1 server-only: 0.0.1
optionalDependencies: optionalDependencies:
react: 19.2.4 react: 19.2.5
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
foxts@5.4.0: {} foxts@5.4.0: {}
@ -6763,37 +6763,37 @@ snapshots:
punycode@2.3.1: {} punycode@2.3.1: {}
react-dom@19.2.4(react@19.2.4): react-dom@19.2.5(react@19.2.5):
dependencies: dependencies:
react: 19.2.4 react: 19.2.5
scheduler: 0.27.0 scheduler: 0.27.0
react-error-boundary@6.1.1(react@19.2.4): react-error-boundary@6.1.1(react@19.2.5):
dependencies: dependencies:
react: 19.2.4 react: 19.2.5
react-fast-compare@3.2.2: {} react-fast-compare@3.2.2: {}
react-hook-form@7.72.1(react@19.2.4): react-hook-form@7.72.1(react@19.2.5):
dependencies: dependencies:
react: 19.2.4 react: 19.2.5
react-i18next@17.0.2(i18next@26.0.3(typescript@6.0.2))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@6.0.2): react-i18next@17.0.2(i18next@26.0.3(typescript@6.0.2))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@6.0.2):
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
html-parse-stringify: 3.0.1 html-parse-stringify: 3.0.1
i18next: 26.0.3(typescript@6.0.2) i18next: 26.0.3(typescript@6.0.2)
react: 19.2.4 react: 19.2.5
use-sync-external-store: 1.6.0(react@19.2.4) use-sync-external-store: 1.6.0(react@19.2.5)
optionalDependencies: optionalDependencies:
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
typescript: 6.0.2 typescript: 6.0.2
react-is@16.13.1: {} react-is@16.13.1: {}
react-is@19.2.4: {} react-is@19.2.4: {}
react-markdown@10.1.0(@types/react@19.2.14)(react@19.2.4): react-markdown@10.1.0(@types/react@19.2.14)(react@19.2.5):
dependencies: dependencies:
'@types/hast': 3.0.4 '@types/hast': 3.0.4
'@types/mdast': 4.0.4 '@types/mdast': 4.0.4
@ -6802,7 +6802,7 @@ snapshots:
hast-util-to-jsx-runtime: 2.3.6 hast-util-to-jsx-runtime: 2.3.6
html-url-attributes: 3.0.1 html-url-attributes: 3.0.1
mdast-util-to-hast: 13.2.1 mdast-util-to-hast: 13.2.1
react: 19.2.4 react: 19.2.5
remark-parse: 11.0.0 remark-parse: 11.0.0
remark-rehype: 11.1.2 remark-rehype: 11.1.2
unified: 11.0.5 unified: 11.0.5
@ -6811,24 +6811,24 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
react-router@7.14.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): react-router@7.14.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5):
dependencies: dependencies:
cookie: 1.1.1 cookie: 1.1.1
react: 19.2.4 react: 19.2.5
set-cookie-parser: 2.7.2 set-cookie-parser: 2.7.2
optionalDependencies: optionalDependencies:
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
react-transition-group@4.4.5(react-dom@19.2.4(react@19.2.4))(react@19.2.4): react-transition-group@4.4.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5):
dependencies: dependencies:
'@babel/runtime': 7.29.2 '@babel/runtime': 7.29.2
dom-helpers: 5.2.1 dom-helpers: 5.2.1
loose-envify: 1.4.0 loose-envify: 1.4.0
prop-types: 15.8.1 prop-types: 15.8.1
react: 19.2.4 react: 19.2.5
react-dom: 19.2.4(react@19.2.4) react-dom: 19.2.5(react@19.2.5)
react@19.2.4: {} react@19.2.5: {}
readdirp@4.1.2: {} readdirp@4.1.2: {}
@ -7171,9 +7171,9 @@ snapshots:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
use-sync-external-store@1.6.0(react@19.2.4): use-sync-external-store@1.6.0(react@19.2.5):
dependencies: dependencies:
react: 19.2.4 react: 19.2.5
validator@13.15.35: {} validator@13.15.35: {}

View File

@ -294,10 +294,10 @@ impl SilentUpdater {
async fn ask_user_to_install(app_handle: &tauri::AppHandle, version: &str) -> bool { async fn ask_user_to_install(app_handle: &tauri::AppHandle, version: &str) -> bool {
use tauri_plugin_dialog::{DialogExt as _, MessageDialogButtons, MessageDialogKind}; use tauri_plugin_dialog::{DialogExt as _, MessageDialogButtons, MessageDialogKind};
let title = clash_verge_i18n::t!("notifications.updateReady.title").to_string(); let title = clash_verge_i18n::t!("notifications.updateReady.title");
let body = clash_verge_i18n::t!("notifications.updateReady.body").replace("{version}", version); let body = clash_verge_i18n::t!("notifications.updateReady.body").replace("{version}", version);
let install_now = clash_verge_i18n::t!("notifications.updateReady.installNow").to_string(); let install_now = clash_verge_i18n::t!("notifications.updateReady.installNow").into_owned();
let later = clash_verge_i18n::t!("notifications.updateReady.later").to_string(); let later = clash_verge_i18n::t!("notifications.updateReady.later").into_owned();
let (tx, rx) = tokio::sync::oneshot::channel(); let (tx, rx) = tokio::sync::oneshot::channel();

View File

@ -4,13 +4,20 @@ use super::use_lowercase;
use serde_yaml_ng::{self, Mapping, Value}; use serde_yaml_ng::{self, Mapping, Value};
fn deep_merge(a: &mut Value, b: Value) { fn deep_merge(a: &mut Value, b: Value) {
match (a, b) { let mut stack: Vec<(*mut Value, Value)> = vec![(a as *mut Value, b)];
(&mut Value::Mapping(ref mut a), Value::Mapping(b)) => {
for (k, v) in b { while let Some((a_ptr, b)) = stack.pop() {
deep_merge(a.entry(k).or_insert(Value::Null), v); let a = unsafe { &mut *a_ptr };
match (a, b) {
(Value::Mapping(a_map), Value::Mapping(b_map)) => {
for (k, v) in b_map {
let child = a_map.entry(k).or_insert(Value::Null);
stack.push((child as *mut Value, v));
}
} }
(a, b) => *a = b,
} }
(a, b) => *a = b,
} }
} }

View File

@ -303,7 +303,7 @@ async fn collect_profile_items() -> ProfileItems {
} }
} }
fn process_global_items( async fn process_global_items(
mut config: Mapping, mut config: Mapping,
global_merge: ChainItem, global_merge: ChainItem,
global_script: ChainItem, global_script: ChainItem,
@ -319,7 +319,7 @@ fn process_global_items(
if let ChainType::Script(script) = global_script.data { if let ChainType::Script(script) = global_script.data {
let mut logs = vec![]; let mut logs = vec![];
match use_script(script, &config, profile_name) { match use_script(script, config.clone(), profile_name.clone()).await {
Ok((res_config, res_logs)) => { Ok((res_config, res_logs)) => {
exists_keys.extend(use_keys(&res_config)); exists_keys.extend(use_keys(&res_config));
config = res_config; config = res_config;
@ -334,7 +334,7 @@ fn process_global_items(
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn process_profile_items( async fn process_profile_items(
mut config: Mapping, mut config: Mapping,
mut exists_keys: Vec<String>, mut exists_keys: Vec<String>,
mut result_map: HashMap<String, ResultLog>, mut result_map: HashMap<String, ResultLog>,
@ -364,7 +364,7 @@ fn process_profile_items(
if let ChainType::Script(script) = script_item.data { if let ChainType::Script(script) = script_item.data {
let mut logs = vec![]; let mut logs = vec![];
match use_script(script, &config, profile_name) { match use_script(script, config.clone(), profile_name.clone()).await {
Ok((res_config, res_logs)) => { Ok((res_config, res_logs)) => {
exists_keys.extend(use_keys(&res_config)); exists_keys.extend(use_keys(&res_config));
config = res_config; config = res_config;
@ -455,25 +455,26 @@ async fn merge_default_config(
config config
} }
fn apply_builtin_scripts(mut config: Mapping, clash_core: Option<String>, enable_builtin: bool) -> Mapping { async fn apply_builtin_scripts(mut config: Mapping, clash_core: Option<String>, enable_builtin: bool) -> Mapping {
if enable_builtin { if enable_builtin {
ChainItem::builtin() let items: Vec<_> = ChainItem::builtin()
.into_iter() .into_iter()
.filter(|(s, _)| s.is_support(clash_core.as_ref())) .filter(|(s, _)| s.is_support(clash_core.as_ref()))
.map(|(_, c)| c) .map(|(_, c)| c)
.for_each(|item| { .collect();
logging!(debug, Type::Core, "run builtin script {}", item.uid); for item in items {
if let ChainType::Script(script) = item.data { logging!(debug, Type::Core, "run builtin script {}", item.uid);
match use_script(script, &config, &String::from("")) { if let ChainType::Script(script) = item.data {
Ok((res_config, _)) => { match use_script(script, config.clone(), String::from("")).await {
config = res_config; Ok((res_config, _)) => {
} config = res_config;
Err(err) => { }
logging!(error, Type::Core, "builtin script error `{err}`"); Err(err) => {
} logging!(error, Type::Core, "builtin script error `{err}`");
} }
} }
}); }
}
} }
config config
@ -621,7 +622,8 @@ pub async fn enhance() -> (Mapping, HashSet<String>, HashMap<String, ResultLog>)
let profile_name = profile.profile_name; let profile_name = profile.profile_name;
// process globals // process globals
let (config, exists_keys, result_map) = process_global_items(config, global_merge, global_script, &profile_name); let (config, exists_keys, result_map) =
process_global_items(config, global_merge, global_script, &profile_name).await;
// process profile-specific items // process profile-specific items
let (config, exists_keys, result_map) = process_profile_items( let (config, exists_keys, result_map) = process_profile_items(
@ -634,7 +636,8 @@ pub async fn enhance() -> (Mapping, HashSet<String>, HashMap<String, ResultLog>)
merge_item, merge_item,
script_item, script_item,
&profile_name, &profile_name,
); )
.await;
// merge default clash config // merge default clash config
let config = merge_default_config( let config = merge_default_config(
@ -650,7 +653,7 @@ pub async fn enhance() -> (Mapping, HashSet<String>, HashMap<String, ResultLog>)
.await; .await;
// builtin scripts // builtin scripts
let mut config = apply_builtin_scripts(config, clash_core, enable_builtin); let mut config = apply_builtin_scripts(config, clash_core, enable_builtin).await;
config = cleanup_proxy_groups(config); config = cleanup_proxy_groups(config);

View File

@ -1,3 +1,5 @@
use crate::process::AsyncHandler;
use super::use_lowercase; use super::use_lowercase;
use anyhow::{Error, Result}; use anyhow::{Error, Result};
use boa_engine::{Context, JsString, JsValue, Source, native_function::NativeFunction}; use boa_engine::{Context, JsString, JsValue, Source, native_function::NativeFunction};
@ -10,11 +12,25 @@ use std::sync::Arc;
const MAX_OUTPUTS: usize = 1000; const MAX_OUTPUTS: usize = 1000;
const MAX_OUTPUT_SIZE: usize = 1024 * 1024; // 1MB const MAX_OUTPUT_SIZE: usize = 1024 * 1024; // 1MB
const MAX_JSON_SIZE: usize = 10 * 1024 * 1024; // 10MB const MAX_JSON_SIZE: usize = 10 * 1024 * 1024; // 10MB
const MAX_LOOP_ITERATIONS: u64 = 10_000_000;
const SCRIPT_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
// TODO 使用引用改进上下相关处理,避免不必要 Clone pub async fn use_script(script: String, config: Mapping, name: String) -> Result<(Mapping, Vec<(String, String)>)> {
pub fn use_script(script: String, config: &Mapping, name: &String) -> Result<(Mapping, Vec<(String, String)>)> { let handle = AsyncHandler::spawn_blocking(move || use_script_sync(script, &config, &name));
match tokio::time::timeout(SCRIPT_TIMEOUT, handle).await {
Ok(Ok(result)) => result,
Ok(Err(join_err)) => Err(anyhow::anyhow!("script task panicked: {join_err}")),
Err(_elapsed) => Err(anyhow::anyhow!("script execution timed out after {:?}", SCRIPT_TIMEOUT)),
}
}
fn use_script_sync(script: String, config: &Mapping, name: &String) -> Result<(Mapping, Vec<(String, String)>)> {
let mut context = Context::default(); let mut context = Context::default();
context
.runtime_limits_mut()
.set_loop_iteration_limit(MAX_LOOP_ITERATIONS);
let outputs = Arc::new(Mutex::new(vec![])); let outputs = Arc::new(Mutex::new(vec![]));
let total_size = Arc::new(Mutex::new(0usize)); let total_size = Arc::new(Mutex::new(0usize));
@ -189,7 +205,7 @@ fn test_script() {
let config = &serde_yaml_ng::from_str(config).expect("Failed to parse test config YAML"); let config = &serde_yaml_ng::from_str(config).expect("Failed to parse test config YAML");
let (config, results) = let (config, results) =
use_script(script.into(), config, &String::from("")).expect("Script execution should succeed in test"); use_script_sync(script.into(), config, &String::from("")).expect("Script execution should succeed in test");
let _ = serde_yaml_ng::to_string(&config).expect("Failed to serialize config to YAML"); let _ = serde_yaml_ng::to_string(&config).expect("Failed to serialize config to YAML");
let yaml_config_size = std::mem::size_of_val(&config); let yaml_config_size = std::mem::size_of_val(&config);
@ -243,7 +259,7 @@ fn test_memory_limits() {
#[allow(clippy::expect_used)] #[allow(clippy::expect_used)]
let config = &serde_yaml_ng::from_str("test: value").expect("Failed to parse test YAML"); let config = &serde_yaml_ng::from_str("test: value").expect("Failed to parse test YAML");
let result = use_script(script.into(), config, &String::from("")); let result = use_script_sync(script.into(), config, &String::from(""));
// 应该失败或被限制 // 应该失败或被限制
assert!(result.is_ok()); // 会被限制但不会 panic assert!(result.is_ok()); // 会被限制但不会 panic
} }

View File

@ -178,9 +178,11 @@ pub(super) async fn init_service_manager() {
if !is_service_ipc_path_exists() { if !is_service_ipc_path_exists() {
return; return;
} }
if SERVICE_MANAGER.lock().await.init().await.is_ok() { let mut manager = SERVICE_MANAGER.lock().await;
logging_error!(Type::Setup, SERVICE_MANAGER.lock().await.refresh().await); if manager.init().await.is_ok() {
logging_error!(Type::Setup, manager.refresh().await);
} }
drop(manager);
} }
pub(super) async fn init_core_manager() { pub(super) async fn init_core_manager() {