From b20fdc9b9632330bb6bc189c757520a06a3f307f Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Tue, 13 Oct 2026 17:13:00 +0800 Subject: [PATCH 01/25] perf(runtime): cap tokio workers at 4 The cap of 8 was a conservative pick from 8ccb0b9a; that commit's own setup benchmark had the 4-worker / 8-blocking row as the best config: 639.3ms avg / 645.5ms max setup time and 22.1 avg threads, ahead of the adopted 8-worker row (650.1ms / 662.4ms, 26.0 threads). Startup parallelism is unaffected in practice: the setup join! polls cooperatively on one task, and CPU work (validation, script eval, YAML parse) runs on the spawn_blocking pool, which keeps its 8-thread cap through the existing 2x invariant. A 12h live session showed the 8 idle workers accumulating under 0.5s CPU total, so four parked stacks (~0.4MB dirty) are pure overhead. --- src-tauri/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 659b574b8..eb0af3195 100755 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -16,7 +16,7 @@ fn main() -> ExitCode { #[cfg(not(all(feature = "perf-harness", target_os = "macos")))] fn main() -> ExitCode { let default_parallelism = std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1); - let worker_limit = std::cmp::min(default_parallelism, 8); + let worker_limit = std::cmp::min(default_parallelism, 4); let blocking_limit = 2 * worker_limit; #[allow(clippy::unwrap_used)] From d4287970bc7dbe3430c9a33bf2922e355c92c0be Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Tue, 13 Oct 2026 17:43:42 +0800 Subject: [PATCH 02/25] perf(tray): cache speed-text attributes and derive width arithmetically Every traffic refresh rebuilt the attributed-string dictionary (font, color, paragraph style, baseline number, dict) and ran a CoreText layout via NSAttributedString::size() just to size the status item, although both depend only on the button height and the glyph advance. The dictionary and the monospaced per-glyph advance (measured once through the same layout engine with a "0" probe) are now cached keyed by button height, and the width is computed as longest-line length times the advance. The speed charset is pure ASCII on a monospaced font, so the arithmetic width matched the layout width exactly (max deviation 0.000pt over 2000 realistic samples). Standalone A/B over 43,200 updates (12h at 1 Hz), same hot path: | variant | mean | p95 | phys_footprint after | | --- | ---: | ---: | ---: | | rebuild + layout (old) | 6.89us | 7.8us | 19.8MB | | cached attrs | 4.71us | 5.0us | 7.8MB | | cached + arithmetic width | 0.27us | 0.3us | 6.0MB | The retained-memory delta is malloc-zone fragmentation from the churn, which this removes at the source. --- src-tauri/src/utils/tray_speed.rs | 44 +++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/src-tauri/src/utils/tray_speed.rs b/src-tauri/src/utils/tray_speed.rs index 8223ea3fc..c3bda426e 100644 --- a/src-tauri/src/utils/tray_speed.rs +++ b/src-tauri/src/utils/tray_speed.rs @@ -27,8 +27,12 @@ const TRAY_STATUS_ITEM_EXTRA_WIDTH: f64 = 30.0; const TRAY_STATUS_ITEM_MIN_LENGTH: f64 = 58.0; const NS_VARIABLE_STATUS_ITEM_LENGTH: f64 = -1.0; +/// (button_height, mono_advance, attributes). +type CachedAttrs = (f64, f64, Retained>); + thread_local! { static LAST_DISPLAY_STR: RefCell = const { RefCell::new(String::new()) }; + static CACHED_ATTRS: RefCell> = const { RefCell::new(None) }; } fn format_tray_speed(up: u64, down: u64) -> String { @@ -74,8 +78,26 @@ fn create_attributed_string( } } -fn status_item_length_for_speed(attr_str: &NSAttributedString) -> f64 { - (attr_str.size().width.ceil() + TRAY_STATUS_ITEM_EXTRA_WIDTH).max(TRAY_STATUS_ITEM_MIN_LENGTH) +/// Attributes and per-glyph advance, rebuilt only when the button height changes. +fn cached_attributes(button_height: f64) -> (f64, Retained>) { + CACHED_ATTRS.with(|cache| { + if let Some((height, advance, attrs)) = cache.borrow().as_ref() + && *height == button_height + { + return (*advance, attrs.clone()); + } + let attrs = build_attributes(button_height); + let probe = NSString::from_str("0"); + let advance = create_attributed_string(&probe, Some(&attrs)).size().width; + *cache.borrow_mut() = Some((button_height, advance, attrs.clone())); + (advance, attrs) + }) +} + +/// Longest line times the monospaced advance; matches `size().width` for the ASCII-only speed text. +fn arithmetic_width(text: &str, advance: f64) -> f64 { + let glyphs = text.split('\n').map(str::len).max().unwrap_or(0) as f64; + glyphs * advance } fn sync_click_target_frame(button: &NSStatusBarButton) { @@ -89,7 +111,7 @@ fn sync_click_target_frame(button: &NSStatusBarButton) { } /// `with_inner_tray_icon` should run this on the main thread; fail safely if it does not. -fn apply_status_item_attributed_title(status_item: &NSStatusItem, text: &NSString, show_speed: bool) { +fn apply_status_item_attributed_title(status_item: &NSStatusItem, text: &str, show_speed: bool) { let Some(mtm) = MainThreadMarker::new() else { logging!(warn, Type::Tray, "托盘速率富文本设置跳过:非主线程调用"); return; @@ -97,17 +119,19 @@ fn apply_status_item_attributed_title(status_item: &NSStatusItem, text: &NSStrin let Some(button) = status_item.button(mtm) else { return; }; + let ns_string = NSString::from_str(text); let attr_str = if show_speed { - let attrs = build_attributes(button.bounds().size.height); + let (advance, attrs) = cached_attributes(button.bounds().size.height); let attrs: &NSDictionary = &attrs; - let attr_str = create_attributed_string(text, Some(attrs)); - let length = status_item_length_for_speed(&attr_str); + let attr_str = create_attributed_string(&ns_string, Some(attrs)); + let width = arithmetic_width(text, advance); + let length = (width.ceil() + TRAY_STATUS_ITEM_EXTRA_WIDTH).max(TRAY_STATUS_ITEM_MIN_LENGTH); if status_item.length() != length { status_item.setLength(length); } attr_str } else { - create_attributed_string(text, None) + create_attributed_string(&ns_string, None) }; button.setAttributedTitle(&attr_str); sync_click_target_frame(&button); @@ -121,8 +145,7 @@ pub fn set_speed_attributed_title(status_item: &NSStatusItem, up: u64, down: u64 return; } *last = speed_text; - let ns_string = NSString::from_str(last.as_str()); - apply_status_item_attributed_title(status_item, &ns_string, true); + apply_status_item_attributed_title(status_item, last.as_str(), true); }); } @@ -130,7 +153,6 @@ pub fn clear_speed_attributed_title(status_item: &NSStatusItem) { LAST_DISPLAY_STR.with(|last| { last.borrow_mut().clear(); }); - let empty = NSString::from_str(""); status_item.setLength(NS_VARIABLE_STATUS_ITEM_LENGTH); - apply_status_item_attributed_title(status_item, &empty, false); + apply_status_item_attributed_title(status_item, "", false); } From c6b51171a1db9b75a4270d78944e132293dbdd83 Mon Sep 17 00:00:00 2001 From: susu-Sugar Date: Wed, 14 Oct 2026 16:52:11 +0000 Subject: [PATCH 03/25] fix(backup): keep WebDAV password masked (#8291) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(backup): keep WebDAV password masked * fix(eslint): Clean unused imports Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> --------- Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> Co-authored-by: susu-Sugar <214122492+susu-Sugar@users.noreply.github.com> Co-authored-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> --- .../setting/mods/backup-config-viewer.tsx | 36 +++---------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/src/components/setting/mods/backup-config-viewer.tsx b/src/components/setting/mods/backup-config-viewer.tsx index dd4972628..c0ce70c10 100644 --- a/src/components/setting/mods/backup-config-viewer.tsx +++ b/src/components/setting/mods/backup-config-viewer.tsx @@ -1,20 +1,11 @@ -import Visibility from '@mui/icons-material/Visibility' -import VisibilityOff from '@mui/icons-material/VisibilityOff' -import { - TextField, - Button, - Grid, - Stack, - IconButton, - InputAdornment, -} from '@mui/material' +import { Button, Grid, Stack, TextField } from '@mui/material' import { useLockFn } from 'ahooks' -import { useState, useRef, memo, useEffect } from 'react' +import { memo, useEffect, useRef } from 'react' import { useForm } from 'react-hook-form' import { useTranslation } from 'react-i18next' import { useVerge } from '@/hooks/use-verge' -import { saveWebdavConfig, createWebdavBackup } from '@/services/cmds' +import { createWebdavBackup, saveWebdavConfig } from '@/services/cmds' import { mutate } from '@/services/mutate' import { errorDetail, showNotice } from '@/services/notice-service' import { @@ -43,7 +34,6 @@ export const BackupConfigViewer = memo( const { t } = useTranslation() const { verge, mutateVerge } = useVerge() const { webdav_url, webdav_username, webdav_password } = verge || {} - const [showPassword, setShowPassword] = useState(false) const usernameRef = useRef(null) const passwordRef = useRef(null) const urlRef = useRef(null) @@ -68,10 +58,6 @@ export const BackupConfigViewer = memo( const webdavStatus = getWebdavStatus(webdavSignature) const shouldAutoInit = webdavStatus !== 'failed' - const handleClickShowPassword = () => { - setShowPassword((prev) => !prev) - } - useEffect(() => { if (!webdav_url || !webdav_username || !webdav_password) { return @@ -215,7 +201,7 @@ export const BackupConfigViewer = memo( - - {showPassword ? : } - - - ), - }, - }} /> From 476ddb63c3d63bd47b57cc5dd820509a894285b3 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Fri, 16 Oct 2026 00:33:38 +0800 Subject: [PATCH 04/25] fix(proxy): revalidate proxy view when expanding a group Badge values for freshly expanded rows seed from the cached proxy view. Results that reach the core without a frontend event (tray group test, provider health checks) are absent from that snapshot until the next poll, so measured delays only appeared after another interaction such as switching nodes forced a refetch. Route head state patches through a wrapper that revalidates the view on open transitions, matching how the group test already refreshes. --- Changelog.md | 5 +++-- src/components/proxy/proxy-groups.tsx | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Changelog.md b/Changelog.md index a37b4132c..310e376f8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,8 +3,9 @@
🐞 修复问题 -- 修复通过 URL 导入订阅时,即使导入的订阅并非当前使用的订阅,也会重新加载当前配置的问题 -- 修复「首页」网站测速失败后卡片一直显示测试中的问题 +- 修复通过 URL 导入订阅时,即使导入的订阅并非当前使用的订阅,也会重新加载当前配置 +- 修复 首页 网站测速失败后卡片一直显示测试中 +- 修复 代理 页展开分组后不显示最新测速结果,需切换节点才刷新 **🐧 Linux** diff --git a/src/components/proxy/proxy-groups.tsx b/src/components/proxy/proxy-groups.tsx index 0b4fa96b1..ac86975c5 100644 --- a/src/components/proxy/proxy-groups.tsx +++ b/src/components/proxy/proxy-groups.tsx @@ -44,6 +44,7 @@ import { ProxyGroupNavigator, } from './proxy-group-navigator' import { ProxyRender } from './proxy-render' +import type { HeadState } from './use-head-state' import { PROXY_GROUP_HEADER_SENSORS, useProxyGroupHeaderLayout, @@ -90,11 +91,11 @@ function useProxyRenderState( ) { const { verge } = useVerge() const { proxyView } = useProxiesData() - const { renderList, onProxies, onHeadState } = useRenderList( - mode, - isChainMode, - activeSelectedGroup, - ) + const { + renderList, + onProxies, + onHeadState: setListHeadState, + } = useRenderList(mode, isChainMode, activeSelectedGroup) const scrollPositionKey = useMemo( () => isChainMode @@ -103,6 +104,14 @@ function useProxyRenderState( [activeSelectedGroup, isChainMode, mode], ) + const onHeadState = useCallback( + (groupName: string, patch: Partial) => { + if (patch.open) onProxies() + setListHeadState(groupName, patch) + }, + [onProxies, setListHeadState], + ) + const timeout = verge?.default_latency_timeout || 10000 const handleCheckAll = useStableCallback( From dc5a8a5ff443c020a3dec79c2b46bc1f55411d95 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 16 Oct 2026 06:25:50 +0000 Subject: [PATCH 05/25] chore(deps): update node.js to v24.22.0 (#8324) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/devcontainer.json | 2 +- .github/workflows/autobuild.yml | 10 +++++----- .github/workflows/cross_check.yaml | 2 +- .github/workflows/dev.yml | 2 +- .github/workflows/frontend-check.yml | 4 ++-- .github/workflows/release.yml | 12 ++++++------ .github/workflows/signpath-test.yml | 2 +- .github/workflows/telegram-notify.yml | 2 +- .github/workflows/updater.yml | 4 ++-- .tool-versions | 2 +- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 27de2822c..74d20b0cb 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ "features": { "ghcr.io/devcontainers/features/node:2": { - "version": "24.21.0", + "version": "24.22.0", "pnpmVersion": "12.11.2" }, "ghcr.io/devcontainers/features/rust:1": { diff --git a/.github/workflows/autobuild.yml b/.github/workflows/autobuild.yml index 49dd85ae2..46cd15c33 100644 --- a/.github/workflows/autobuild.yml +++ b/.github/workflows/autobuild.yml @@ -51,7 +51,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - name: Install dependencies run: pnpm install --frozen-lockfile @@ -185,7 +185,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' cache: 'pnpm' - name: Pnpm Cache @@ -282,7 +282,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' cache: 'pnpm' - name: Pnpm Cache @@ -426,7 +426,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' cache: 'pnpm' - name: Pnpm Cache @@ -524,7 +524,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6.1.0 name: Install pnpm diff --git a/.github/workflows/cross_check.yaml b/.github/workflows/cross_check.yaml index 83289f20e..3a57d9a77 100644 --- a/.github/workflows/cross_check.yaml +++ b/.github/workflows/cross_check.yaml @@ -43,7 +43,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6 name: Install pnpm diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 36ef5baab..6ea3005c9 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -103,7 +103,7 @@ jobs: if: github.event.inputs[matrix.input] == 'true' uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' cache: 'pnpm' - name: Pnpm Cache diff --git a/.github/workflows/frontend-check.yml b/.github/workflows/frontend-check.yml index 937f9c89b..eb02eab42 100644 --- a/.github/workflows/frontend-check.yml +++ b/.github/workflows/frontend-check.yml @@ -52,7 +52,7 @@ jobs: - uses: actions/setup-node@v7 if: steps.check_frontend.outputs.frontend == 'true' with: - node-version: '24.21.0' + node-version: '24.22.0' cache: 'pnpm' - name: Restore pnpm cache @@ -138,7 +138,7 @@ jobs: - uses: actions/setup-node@v7 if: steps.check_inputs.outputs.contract == 'true' with: - node-version: '24.21.0' + node-version: '24.22.0' cache: 'pnpm' - run: pnpm install --frozen-lockfile diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d2191eeb2..3ed9f2629 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -230,7 +230,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -331,7 +331,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - name: Install pnpm uses: pnpm/action-setup@v6 @@ -466,7 +466,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -547,7 +547,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -573,7 +573,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -638,7 +638,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6 name: Install pnpm diff --git a/.github/workflows/signpath-test.yml b/.github/workflows/signpath-test.yml index 6d8c0c864..71d6bbc6c 100644 --- a/.github/workflows/signpath-test.yml +++ b/.github/workflows/signpath-test.yml @@ -28,7 +28,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - name: Install pnpm uses: pnpm/action-setup@v6 diff --git a/.github/workflows/telegram-notify.yml b/.github/workflows/telegram-notify.yml index f8d296324..782466afa 100644 --- a/.github/workflows/telegram-notify.yml +++ b/.github/workflows/telegram-notify.yml @@ -34,7 +34,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6 name: Install pnpm diff --git a/.github/workflows/updater.yml b/.github/workflows/updater.yml index c610dfdd3..f773f64b8 100644 --- a/.github/workflows/updater.yml +++ b/.github/workflows/updater.yml @@ -15,7 +15,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -39,7 +39,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.21.0' + node-version: '24.22.0' - uses: pnpm/action-setup@v6 name: Install pnpm diff --git a/.tool-versions b/.tool-versions index 25be9ef6d..1de534f8f 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -nodejs 24.21.0 +nodejs 24.22.0 pnpm 12.11.2 rust 1.99.0 From 089635c8bfef4d339fbc309fa1209e8ad203b344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9D=A4=E6=98=AF=E7=BA=B1=E9=9B=BE=E9=85=B1=E5=93=9F?= =?UTF-8?q?=EF=BD=9E?= <49941141+Dragon1573@users.noreply.github.com> Date: Fri, 16 Oct 2026 12:11:40 +0000 Subject: [PATCH 06/25] ci(workflows): bump `gh-aw` from 0.89.21 to 0.92.0 (#8330) - Bump `gh-aw` from 0.89.21 to 0.92.0 - Switch from `pull_request_target` to `pull_request` for CI security - Set `permissions.copilot-requests` to `none` for suppressing compilation info --- .github/agents/agentic-workflows.md | 24 +- .github/aw/actions-lock.json | 6 +- .github/skills/agentic-workflows/SKILL.md | 13 +- .github/workflows/copilot-setup-steps.yml | 2 +- .github/workflows/pr-ai-slop-review.lock.yml | 483 +++++++++++++------ .github/workflows/pr-ai-slop-review.md | 3 +- 6 files changed, 359 insertions(+), 172 deletions(-) diff --git a/.github/agents/agentic-workflows.md b/.github/agents/agentic-workflows.md index 08c6d9a24..782161f83 100644 --- a/.github/agents/agentic-workflows.md +++ b/.github/agents/agentic-workflows.md @@ -21,7 +21,7 @@ This is a **dispatcher agent** that routes your request to the appropriate speci - **Creating new workflows**: Routes to `create` prompt - **Updating existing workflows**: Routes to `update` prompt -- **Debugging workflows**: Routes to `debug` prompt +- **Diagnosis, patching, and active debugging**: Routes to `debug-agentic-workflow` for the local-first strategy, evidence triage and live gates - **Upgrading workflows**: Routes to `upgrade-agentic-workflows` prompt - **Creating report-generating workflows**: Routes to `report` prompt — consult this whenever the workflow posts status updates, audits, analyses, or any structured output as issues, discussions, or comments - **Creating shared components**: Routes to `create-shared-agentic-workflow` prompt @@ -31,6 +31,7 @@ This is a **dispatcher agent** that routes your request to the appropriate speci - **CLI commands and triggering workflows**: Routes to `cli-commands` guide — consult this whenever the user asks how to run, compile, debug, or manage workflows from the command line, or when they need the MCP tool equivalent of a `gh aw` command - **Reducing token consumption / cost optimization**: Routes to `token-optimization` guide — consult this whenever the user asks how to reduce token usage, lower costs, speed up workflows, or measure the impact of prompt changes with experiments - **Choosing workflow architectures and design patterns**: Routes to `patterns` guide — consult this whenever the user asks for strategy, architecture, operating models, or pattern selection for agentic workflows +- **Git-backed work queues**: Routes to `work-queue` instructions for producers, dispatchers, workers, observers, deployment and recovery Workflows may optionally include: @@ -47,7 +48,8 @@ Workflows may optionally include: ## Problems This Solves - **Workflow Creation**: Design secure, validated agentic workflows with proper triggers, tools, and permissions -- **Workflow Debugging**: Analyze logs, identify missing tools, investigate failures, and fix configuration issues +- **Diagnosis and Patching**: Analyze evidence and produce regression-backed fixes without requiring live runs +- **Active Debugging**: Run bounded edit/test/run/audit loops where permitted, stopping on dispatch 403 responses - **Version Upgrades**: Migrate workflows to new gh-aw versions, apply codemods, fix breaking changes - **Component Design**: Create reusable shared workflow components that wrap MCP servers @@ -83,11 +85,14 @@ When you interact with this agent, it will: - "Update the PR reviewer to use discussions instead of issues" - "Improve the prompt for the weekly-research workflow" -### Debug Workflow +### Diagnose, Patch, or Debug a Workflow **Load when**: User needs to investigate, audit, debug, or understand a workflow, troubleshoot issues, analyze logs, or fix errors **Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/debug-agentic-workflow.md` +The shared strategy distinguishes diagnosis/patching from permitted active debug +loops using explicit live gates and includes existing-run evidence triage. + **Use cases**: - "Why is this workflow failing?" - "Analyze the logs for workflow X" @@ -180,6 +185,15 @@ When you interact with this agent, it will: ## Instructions +### Work Queue + +For queue design, deployment, inspection or recovery, load +`https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/work-queue.md`. +Also load it after the primary create/update/debug/upgrade prompt whenever a +workflow uses `tools.work-queue`. Load linked developer docs and specifications +only when needed; do not substitute lightweight WorkQueueOps backlog guidance +for the Git-backed protocol. + When a user interacts with you: 1. **Identify the task type** from the user's request @@ -196,7 +210,7 @@ gh aw init # Generate the lock file for a workflow gh aw compile [workflow-name] -# Trigger a workflow on demand (preferred over gh workflow run) +# Only where permitted and human-validated under debug-agentic-workflow.md: gh aw run # interactive input collection gh aw run --ref main # run on a specific branch @@ -229,5 +243,5 @@ gh aw compile --validate - Follow security best practices: minimal permissions, explicit network access, no template injection - **Network configuration**: Use ecosystem identifiers (`node`, `python`, `go`, etc.) or explicit FQDNs in `network.allowed`. Bare shorthands like `npm` or `pypi` are **not** valid. See `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/network.md` for the full list of valid ecosystem identifiers and domain patterns. - **Single-file output**: When creating a workflow, produce exactly **one** workflow `.md` file. Do not create separate documentation files (architecture docs, runbooks, usage guides, etc.). If documentation is needed, add a brief `## Usage` section inside the workflow file itself. -- **Triggering runs**: Always use `gh aw run ` to trigger a workflow on demand — not `gh workflow run .lock.yml`. `gh aw run` handles workflow resolution by short name, input parsing and validation, and correct run-tracking for agentic workflows. Use `--ref ` to run on a specific branch. +- **Triggering runs**: Only where permitted and human-validated under `debug-agentic-workflow.md`, prefer `gh aw run ` over `gh workflow run .lock.yml` for workflow resolution, input validation and run-tracking. Use the reviewed remote ref; explicit no-dispatch rules override user requests. - **CLI commands reference**: For a complete guide on all `gh aw` commands and their MCP tool equivalents (for restricted environments), see `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/cli-commands.md` diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index 4bb203545..4b988e9dc 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -5,10 +5,10 @@ "version": "v9.0.0", "sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3" }, - "github/gh-aw-actions/setup@v0.89.21": { + "github/gh-aw-actions/setup@v0.92.0": { "repo": "github/gh-aw-actions/setup", - "version": "v0.89.21", - "sha": "924af5fdc64061cfbf66fb584c8b07e2ac230c60" + "version": "v0.92.0", + "sha": "458b269006dcf88e3b5496b6fbecabe4b9a0f954" } }, "containers": { diff --git a/.github/skills/agentic-workflows/SKILL.md b/.github/skills/agentic-workflows/SKILL.md index 4c983cc5a..328ca1dae 100644 --- a/.github/skills/agentic-workflows/SKILL.md +++ b/.github/skills/agentic-workflows/SKILL.md @@ -1,6 +1,6 @@ --- name: agentic-workflows -description: Route gh-aw workflow design/create/debug/upgrade requests to the right prompts. +description: Route gh-aw design, creation, diagnosis, patching, active debugging, and upgrade requests to the right strategies. --- # Agentic Workflows Router @@ -19,6 +19,7 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/agent-runtime-instructions.md` - `.github/aw/agentic-chat.md` - `.github/aw/agentic-workflows-mcp.md` +- `.github/aw/analyzing-runs.md` - `.github/aw/asciicharts.md` - `.github/aw/campaign.md` - `.github/aw/charts-trending.md` @@ -31,6 +32,8 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/create-agentic-workflow.md` - `.github/aw/create-shared-agentic-workflow.md` - `.github/aw/debug-agentic-workflow.md` +- `.github/aw/debug-model-engine-misconfiguration.md` +- `.github/aw/debug-security-review.md` - `.github/aw/dependabot.md` - `.github/aw/deployment-status.md` - `.github/aw/designer-mappings.md` @@ -46,6 +49,7 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/instructions.md` - `.github/aw/intent.md` - `.github/aw/jobs.md` +- `.github/aw/ledger.md` - `.github/aw/linter-workflows.md` - `.github/aw/llms.md` - `.github/aw/loop.md` @@ -87,6 +91,7 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/update-agentic-workflow.md` - `.github/aw/upgrade-agentic-workflows.md` - `.github/aw/visual-regression.md` +- `.github/aw/work-queue.md` - `.github/aw/workflow-constraints.md` - `.github/aw/workflow-editing.md` - `.github/aw/workflow-patterns.md` @@ -96,7 +101,8 @@ After loading the matching workflow prompt or skill, follow it directly: - Create new workflows: `.github/aw/create-agentic-workflow.md` - Configure or add declarative engines: `.github/aw/configure-agentic-engine.md` - Update existing workflows: `.github/aw/update-agentic-workflow.md` -- Debug, audit, or investigate workflows: `.github/aw/debug-agentic-workflow.md` +- Diagnose, patch, audit, or actively debug workflows: `.github/aw/debug-agentic-workflow.md` (local-first strategy, evidence triage and live gates) +- AWF model/endpoint 400s, silent cross-family sub-agent failures, `model: auto` failures, install-step 404s after a version pin, or questions about version fields: go directly to [Model and engine misconfiguration](../../aw/debug-agentic-workflow.md#model-and-engine-misconfiguration) before suggesting model changes. - Upgrade workflows and fix deprecations: `.github/aw/upgrade-agentic-workflows.md` - Create shared components or MCP wrappers: `.github/aw/create-shared-agentic-workflow.md` - Create report-generating workflows: `.github/aw/report.md` @@ -105,8 +111,11 @@ After loading the matching workflow prompt or skill, follow it directly: - Render compact markdown charts: `.github/aw/asciicharts.md` - Map CLI commands to MCP usage: `.github/aw/cli-commands.md` - Choose workflow architecture and patterns: `.github/aw/patterns.md` +- Design, deploy, inspect or recover a Git-backed work queue: `.github/aw/work-queue.md` - Optimize token usage and cost: `.github/aw/token-optimization.md` - Design long-running multi-agent research workflows: `.github/aw/multi-agent-research.md` - Add skills or agent plugins requested by the user (`skills:` / `plugins:` frontmatter, never on-the-fly installs): `.github/aw/skills.md` When the task involves OTEL, OTLP, traces, observability backends, or telemetry-driven analysis, also read and follow `skills/otel-queries/SKILL.md` after loading the matching workflow prompt or skill. + +When creating, updating, diagnosing or upgrading a workflow that uses `tools.work-queue`, also load `.github/aw/work-queue.md` after the primary prompt. Load deployment docs, operator reference or specification only when that task needs them. diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 2f100bac7..dcd816ab1 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -31,6 +31,6 @@ jobs: with: persist-credentials: false - name: Install gh-aw extension - uses: github/gh-aw-actions/setup-cli@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 + uses: github/gh-aw-actions/setup-cli@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 with: version: v0.89.15 diff --git a/.github/workflows/pr-ai-slop-review.lock.yml b/.github/workflows/pr-ai-slop-review.lock.yml index f6ea859e3..3c8b20384 100644 --- a/.github/workflows/pr-ai-slop-review.lock.yml +++ b/.github/workflows/pr-ai-slop-review.lock.yml @@ -1,6 +1,6 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"8296ef86aad04ad225d29c7fe51dd18dfa50f258c46e8bd24e443193cc6f80fc","body_hash":"e7b165b458a07108c2e6bfe6f4ed61f5659ce81512691dda091165d5966ee732","compiler_version":"v0.89.21","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.87"}} -# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_DEFAULT_OTLP_ENDPOINT","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"924af5fdc64061cfbf66fb584c8b07e2ac230c60","version":"v0.89.21"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.28.23","digest":"sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.28.23@sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23","digest":"sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23@sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.28.23","digest":"sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.28.23@sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.25","digest":"sha256:9be0a86220e807a0ecc89e53d7453468f7a53fbc6b3d1efd2299025ffe01d086","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.25@sha256:9be0a86220e807a0ecc89e53d7453468f7a53fbc6b3d1efd2299025ffe01d086"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e","pinned_image":"ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e"},{"image":"ghcr.io/github/github-mcp-server:v1.12.2","digest":"sha256:508a0857ec762b1ab1cece29193345b501fab1dd9d1228a7b617062954cecac6","pinned_image":"ghcr.io/github/github-mcp-server:v1.12.2@sha256:508a0857ec762b1ab1cece29193345b501fab1dd9d1228a7b617062954cecac6"}],"has_pull_request_target":true,"mcp_servers":[{"name":"github","tools":["get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","issue_read","list_issue_types","list_issues","list_pull_requests","pull_request_read","search_issues","search_pull_requests"]},{"name":"safeoutputs","tools":["add_comment","add_labels","missing_data","missing_tool","noop","remove_labels"]}]} -# This file was automatically generated by gh-aw (v0.89.21). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a74d6cb119bde6904af2788245fd44d6229de228ba92dc5bafa7e86705bed626","body_hash":"e7b165b458a07108c2e6bfe6f4ed61f5659ce81512691dda091165d5966ee732","compiler_version":"v0.92.0","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.96"}} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_DEFAULT_OTLP_ENDPOINT","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"9000827ccba6bdab643e8b6fd33ac0654aef8333","version":"v8.0.2"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"949feb2413d6458794dcd2491c4babbbce0c15c1","version":"v7.1.0"},{"repo":"actions/upload-artifact","sha":"cf430e030ddbb5b0abf93d22962f4752f3646cd9","version":"v7.0.2"},{"repo":"github/gh-aw-actions/setup","sha":"458b269006dcf88e3b5496b6fbecabe4b9a0f954","version":"v0.92.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.28.57","digest":"sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.28.57@sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57","digest":"sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57@sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.28.57","digest":"sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.28.57@sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.31","digest":"sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.31@sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e","pinned_image":"ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e"},{"image":"ghcr.io/github/github-mcp-server:v2.0.2","digest":"sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796","pinned_image":"ghcr.io/github/github-mcp-server:v2.0.2@sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796"}],"has_pull_request":true,"mcp_servers":[{"name":"github","tools":["get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","issue_read","list_issue_types","list_issues","list_pull_requests","pull_request_read","search_issues","search_pull_requests"]},{"name":"safeoutputs","tools":["add_comment","add_labels","missing_data","missing_tool","noop","remove_labels","report_incomplete"]}],"threat_detection":{"mode":"enabled"}} +# This file was automatically generated by gh-aw (v0.92.0). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # # ___ _ _ # / _ \ | | (_) @@ -37,24 +37,23 @@ # # Custom actions used: # - actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 -# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 -# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) -# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 -# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 -# - github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 +# - actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 +# - actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 +# - github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.28.23@sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2 -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23@sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64 -# - ghcr.io/github/gh-aw-firewall/squid:0.28.23@sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0 -# - ghcr.io/github/gh-aw-mcpg:v0.4.25@sha256:9be0a86220e807a0ecc89e53d7453468f7a53fbc6b3d1efd2299025ffe01d086 +# - ghcr.io/github/gh-aw-firewall/agent:0.28.57@sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57@sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc +# - ghcr.io/github/gh-aw-firewall/squid:0.28.57@sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac +# - ghcr.io/github/gh-aw-mcpg:v0.4.31@sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf # - ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e -# - ghcr.io/github/github-mcp-server:v1.12.2@sha256:508a0857ec762b1ab1cece29193345b501fab1dd9d1228a7b617062954cecac6 +# - ghcr.io/github/github-mcp-server:v2.0.2@sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796 name: "PR AI Slop Review" on: - pull_request_target: + pull_request: types: - opened - synchronize @@ -70,10 +69,11 @@ on: inputs: aw_context: default: "" - description: "Agent caller context (used internally by Agentic Workflows)." + description: "Agent caller context (Reserved for Agentic Workflows)." required: false type: string +# Jobs receive only their explicitly declared permissions. permissions: {} concurrency: @@ -92,9 +92,14 @@ env: jobs: activation: + name: activation needs: pre_activation - if: needs.pre_activation.outputs.activated == 'true' + if: > + needs.pre_activation.outputs.activated == 'true' && ((github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id) && + ((github.event_name != 'pull_request' && github.event_name != 'pull_request_review') || github.event.pull_request.stack == null || + github.event.pull_request.stack.position == github.event.pull_request.stack.size)) runs-on: ubuntu-slim + # Permissions for the activation job (workflow permissions default to none). permissions: actions: read contents: read @@ -102,9 +107,11 @@ jobs: GH_AW_MAX_DAILY_AI_CREDITS: "5000" GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} outputs: + aw_context: ${{ steps.generate_aw_info.outputs.aw_context }} body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" + daily_ai_credits_estimated: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_estimated || '' }} daily_ai_credits_exceeded: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_exceeded == 'true' }} daily_ai_credits_guardrail_error: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_error || '' }} daily_ai_credits_guardrail_status: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_status || '' }} @@ -124,7 +131,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 + uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -134,9 +141,10 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.87" - GH_AW_INFO_AWF_VERSION: "v0.28.23" + GH_AW_INFO_VERSION: "1.0.96" + GH_AW_INFO_AWF_VERSION: "v0.28.57" GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Generate agentic run info @@ -145,16 +153,16 @@ jobs: GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }} - GH_AW_INFO_VERSION: "1.0.87" - GH_AW_INFO_AGENT_VERSION: "1.0.87" - GH_AW_INFO_CLI_VERSION: "v0.89.21" + GH_AW_INFO_VERSION: "1.0.96" + GH_AW_INFO_AGENT_VERSION: "1.0.96" + GH_AW_INFO_CLI_VERSION: "v0.92.0" GH_AW_INFO_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]' GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.28.23" + GH_AW_INFO_AWF_VERSION: "v0.28.57" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_INFO_AGENT_RUNTIME: "" @@ -210,13 +218,13 @@ jobs: - name: Publish daily AIC scan observations if: always() && env.GH_AW_MAX_DAILY_AI_CREDITS != '' continue-on-error: true - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: aic-usage-scan-v2 path: /tmp/gh-aw/agentic-workflow-usage-scan-v2.jsonl overwrite: true if-no-files-found: ignore - retention-days: 3 + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '3' }} - name: Validate COPILOT_GITHUB_TOKEN secret id: validate-secret run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default @@ -233,6 +241,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false + ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_review' || github.event_name == 'pull_request_review_comment') && github.event.pull_request != null && github.event.pull_request.base.sha || github.sha }} sparse-checkout: | .github .agents @@ -265,7 +274,7 @@ jobs: - name: Check compile-agentic version uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_COMPILED_VERSION: "v0.89.21" + GH_AW_COMPILED_VERSION: "v0.92.0" GH_AW_BLOCKED_VERSION_REPORT_AS_ISSUE: "false" GH_AW_WORKFLOW_NAME: "PR AI Slop Review" with: @@ -298,19 +307,19 @@ jobs: GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl - GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}" - GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} - GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} - GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} - GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} + GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"safe_outputs_mcp_transport_prompt.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}],\"system_item_count\":12}" + GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }} + GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} GH_AW_PROMPT_CONTENT_0000: "\n" - GH_AW_PROMPT_CONTENT_0001: "\nTools: add_comment, add_labels, remove_labels(max:2), missing_tool, missing_data, noop\n" + GH_AW_PROMPT_CONTENT_0001: "\nTools: add_comment, add_labels, remove_labels(max:2), missing_tool, missing_data, noop(max:2)\n" GH_AW_PROMPT_CONTENT_0002: "\n" - GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n" + GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_7C248226__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_C19C384F__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_76DF9333__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_77C1A4D2__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n" GH_AW_PROMPT_CONTENT_0004: "\n" GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/pr-ai-slop-review.md}}\n" with: @@ -324,6 +333,10 @@ jobs: env: GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt GH_AW_ENGINE_ID: "copilot" + GH_AW_SUB_AGENT_DIR: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.md" + GH_AW_SKILL_DIR: ".github/skills" + GH_AW_SKILL_EXT: "/SKILL.md" with: script: | const path = require('path'); @@ -336,10 +349,10 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt - GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} - GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} - GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} - GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} + GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }} + GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} @@ -359,10 +372,10 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { - GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, - GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, - GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A, - GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE, + GH_AW_EXPR_76DF9333: process.env.GH_AW_EXPR_76DF9333, + GH_AW_EXPR_77C1A4D2: process.env.GH_AW_EXPR_77C1A4D2, + GH_AW_EXPR_7C248226: process.env.GH_AW_EXPR_7C248226, + GH_AW_EXPR_C19C384F: process.env.GH_AW_EXPR_C19C384F, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, @@ -381,20 +394,34 @@ jobs: GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt run: | bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Inventory installed skills + if: success() || failure() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_SKILL_DIR: ".github/skills" + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'skill_inventory.cjs')); + await main(); - name: Upload info artifact if: success() || failure() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: info path: /tmp/gh-aw/aw_info.json if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} - name: Stage prompt files for artifact upload run: | mkdir -p /tmp/gh-aw/aw-prompts cp -a "${RUNNER_TEMP}/gh-aw/aw-prompts/." /tmp/gh-aw/aw-prompts/ - name: Upload activation artifact if: success() || failure() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: activation include-hidden-files: true @@ -402,20 +429,26 @@ jobs: /tmp/gh-aw/aw_info.json /tmp/gh-aw/models.json /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw-prompts/system.txt + /tmp/gh-aw/aw-prompts/user.txt /tmp/gh-aw/aw-prompts/prompt-template.txt /tmp/gh-aw/aw-prompts/prompt-import-tree.json /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/base /tmp/gh-aw/.github/agents /tmp/gh-aw/.github/skills + /tmp/gh-aw/skill_inventory.json if-no-files-found: ignore - retention-days: 1 + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '1' }} agent: + name: agent needs: activation if: needs.activation.outputs.daily_ai_credits_exceeded != 'true' runs-on: ubuntu-latest + # Permissions for the agent job (workflow permissions default to none). permissions: + copilot-requests: none issues: read pull-requests: read timeout-minutes: 60 @@ -432,6 +465,7 @@ jobs: GH_AW_PR_HEAD_BASE_SHA: "" GH_AW_PR_HEAD_REPO: "" GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} + GH_AW_TARGET_REPO_SLUG: "" GH_AW_WORKFLOW_ID_SANITIZED: praislopreview outputs: agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} @@ -447,6 +481,7 @@ jobs: missing_model_pricing_error: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_error || 'false' }} missing_model_pricing_model_name: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_model_name || '' }} model: ${{ needs.activation.outputs.model }} + model_endpoint_mismatch_error: ${{ steps.detect-agent-errors.outputs.model_endpoint_mismatch_error || 'false' }} model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -458,7 +493,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 + uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -467,9 +502,10 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.87" - GH_AW_INFO_AWF_VERSION: "v0.28.23" + GH_AW_INFO_VERSION: "1.0.96" + GH_AW_INFO_AWF_VERSION: "v0.28.57" GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Set runtime paths id: set-runtime-paths env: @@ -500,7 +536,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Download activation artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: activation path: /tmp/gh-aw @@ -508,12 +544,12 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" env: GH_HOST: github.com - GH_AW_COMPILED_VERSION: v0.89.21 + GH_AW_COMPILED_VERSION: v0.92.0 - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.23 --rootless + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.57 --rootless - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} @@ -544,7 +580,7 @@ jobs: run: "node <<'NODE'\nconst fs = require('fs');\nconst harnessPath = `${process.env.RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs`;\nconst harness = fs.readFileSync(harnessPath, 'utf8');\nconst quotaBranch = [\n ' if (isQuotaExceeded) {',\n ' log(`attempt ${attempt + 1}: Copilot quota exceeded — not retrying`);',\n ' return { action: \"stop\" };',\n ' }',\n].join('\\n');\nconst nonBlockingQuotaBranch = [\n ' let quotaErrorMsg = null;',\n ' if (isQuotaExceeded) {',\n ' log(`attempt ${attempt + 1}: Copilot quota exceeded — not retrying`);',\n ' quotaErrorMsg = { action: \"stop\" };',\n ' }',\n ' if (/\\\\b429\\\\b|Too Many Requests/i.test(result.output)) {',\n ' log(`attempt ${attempt + 1}: Copilot quota unavailable — exiting 0`);',\n ' quotaErrorMsg = { action: \"stop\", exitCode: 0 };',\n ' }',\n ' if (quotaErrorMsg) {',\n ' return quotaErrorMsg;',\n ' }',\n].join('\\n');\n\nif (harness.split(quotaBranch).length !== 2) {\n throw new Error('Unexpected Copilot quota branch; re-audit the gh-aw upgrade');\n}\nfs.writeFileSync(harnessPath, harness.replace(quotaBranch, nonBlockingQuotaBranch));\nNODE" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.23@sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2 ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23@sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64 ghcr.io/github/gh-aw-firewall/squid:0.28.23@sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0 ghcr.io/github/gh-aw-mcpg:v0.4.25@sha256:9be0a86220e807a0ecc89e53d7453468f7a53fbc6b3d1efd2299025ffe01d086 ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e ghcr.io/github/github-mcp-server:v1.12.2@sha256:508a0857ec762b1ab1cece29193345b501fab1dd9d1228a7b617062954cecac6 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.57@sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57@sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc ghcr.io/github/gh-aw-firewall/squid:0.28.57@sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac ghcr.io/github/gh-aw-mcpg:v0.4.31@sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e ghcr.io/github/github-mcp-server:v2.0.2@sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796 - name: Prepare Safe Outputs Directories run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" @@ -555,7 +591,7 @@ jobs: env: GH_AW_FILE_ROOT: "${{ runner.temp }}/gh-aw" GH_AW_FILE_CONFIG: "{\"files\":[{\"path\":\"safeoutputs/config.json\",\"content_env\":\"GH_AW_SAFE_OUTPUTS_CONFIG\"}]}" - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1},\"add_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":1},\"create_report_incomplete_issue\":{},\"mentions\":{\"enabled\":false},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"remove_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":2},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1},\"add_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":1},\"create_report_incomplete_issue\":{},\"mentions\":{\"enabled\":false},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"remove_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":2},\"report_incomplete\":{}}" with: script: | const path = require('path'); @@ -570,7 +606,7 @@ jobs: { "description_suffixes": { "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading.", - "add_labels": " CONSTRAINTS: Maximum 1 label(s) can be added. Only these labels are allowed: [\"ai-slop:high\" \"ai-slop:med\"].", + "add_labels": " CONSTRAINTS: Maximum 1 add_labels call(s) allowed. Maximum 10 label(s) per call. Only these labels are allowed: [\"ai-slop:high\" \"ai-slop:med\"].", "remove_labels": " CONSTRAINTS: Maximum 2 label(s) can be removed. Only these labels can be removed: [ai-slop:high ai-slop:med]." }, "repo_params": {}, @@ -685,7 +721,7 @@ jobs: } }, "noop": { - "defaultMax": 1, + "defaultMax": 2, "fields": { "message": { "required": true, @@ -740,6 +776,9 @@ jobs: - name: Start MCP Gateway id: start-mcp-gateway env: + GH_AW_GUARD_APPROVAL_LABELS: ${{ steps.parse-guard-vars.outputs.approval_labels }} + GH_AW_GUARD_BLOCKED_USERS: ${{ steps.parse-guard-vars.outputs.blocked_users }} + GH_AW_GUARD_TRUSTED_USERS: ${{ steps.parse-guard-vars.outputs.trusted_users }} GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST: ${{ vars.GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST || 'true' }} GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_CONFIG_PATH }} @@ -773,22 +812,23 @@ jobs: export GH_AW_PR_HEAD_BASE_PR_NUMBER="${GH_AW_PR_HEAD_BASE_PR_NUMBER:-}" export GH_AW_PR_HEAD_BASE_REF="${GH_AW_PR_HEAD_BASE_REF:-}" export GH_AW_PR_HEAD_REPO="${GH_AW_PR_HEAD_REPO:-}" + export GH_AW_TARGET_REPO_SLUG="${GH_AW_TARGET_REPO_SLUG:-}" export DEBUG="*" export GH_AW_ENGINE="copilot" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') source "${RUNNER_TEMP}/gh-aw/actions/resolve_docker_socket_gid.sh" - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_AGENT_ID -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_PR_HEAD_BASE_BRANCH -e GH_AW_PR_HEAD_BASE_SHA -e GH_AW_PR_HEAD_BASE_REPO -e GH_AW_PR_HEAD_BASE_PR_NUMBER -e GH_AW_PR_HEAD_BASE_REF -e GH_AW_PR_HEAD_REPO -e GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GH_AW_SINK_VISIBILITY -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e RUNNER_TEMP -e RUNNER_TOOL_CACHE -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.4.25' + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_AGENT_ID -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_TARGET_REPO_SLUG -e GH_AW_PR_HEAD_BASE_BRANCH -e GH_AW_PR_HEAD_BASE_SHA -e GH_AW_PR_HEAD_BASE_REPO -e GH_AW_PR_HEAD_BASE_PR_NUMBER -e GH_AW_PR_HEAD_BASE_REF -e GH_AW_PR_HEAD_REPO -e GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GH_AW_SINK_VISIBILITY -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e RUNNER_TEMP -e RUNNER_TOOL_CACHE -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -e GH_AW_GUARD_APPROVAL_LABELS -e GH_AW_GUARD_BLOCKED_USERS -e GH_AW_GUARD_TRUSTED_USERS -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.4.31@sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf' mkdir -p "$HOME/.copilot" GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_7ff34e101789c0b6_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_293a804dd05fb938_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v1.12.2", + "container": "ghcr.io/github/github-mcp-server:v2.0.2", "env": { "GITHUB_FEATURES": "fields_param", "GITHUB_HOST": "${GITHUB_SERVER_URL}", @@ -798,11 +838,11 @@ jobs: }, "guard-policies": { "allow-only": { - "approval-labels": ${{ steps.parse-guard-vars.outputs.approval_labels }}, - "blocked-users": ${{ steps.parse-guard-vars.outputs.blocked_users }}, + "approval-labels": ${GH_AW_GUARD_APPROVAL_LABELS}, + "blocked-users": ${GH_AW_GUARD_BLOCKED_USERS}, "min-integrity": "unapproved", "repos": "all", - "trusted-users": ${{ steps.parse-guard-vars.outputs.trusted_users }} + "trusted-users": ${GH_AW_GUARD_TRUSTED_USERS} } } }, @@ -823,6 +863,7 @@ jobs: "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", "GH_AW_SAFE_OUTPUTS_CONFIG_PATH": "\${GH_AW_SAFE_OUTPUTS_CONFIG_PATH}", "GH_AW_SAFE_OUTPUTS_TOOLS_PATH": "\${GH_AW_SAFE_OUTPUTS_TOOLS_PATH}", + "GH_AW_TARGET_REPO_SLUG": "\${GH_AW_TARGET_REPO_SLUG}", "GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST": "\${GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST}", "GH_AW_PR_HEAD_BASE_BRANCH": "\${GH_AW_PR_HEAD_BASE_BRANCH}", "GH_AW_PR_HEAD_BASE_SHA": "\${GH_AW_PR_HEAD_BASE_SHA}", @@ -861,7 +902,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_7ff34e101789c0b6_EOF + GH_AW_MCP_CONFIG_293a804dd05fb938_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -879,12 +920,25 @@ jobs: const { main } = require(path.join(actionsDir, 'mount_mcp_as_cli.cjs')); await main(); - name: Clean credentials - continue-on-error: true - run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + bash "${RUNNER_TEMP}/gh-aw/actions/verify_git_credentials.sh" - name: Audit pre-agent workspace id: pre_agent_audit continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" + - name: Log GitHub rate limits at agent start + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs')); + await fetchAndLogRateLimit(github, 'agent_start', true); - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): @@ -892,9 +946,10 @@ jobs: run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt + gh_aw_exit_code=0 trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; rm -f "$HOME/.copilot/settings.json"; if [ "$gh_aw_exit_code" -ne 0 ]; then echo "::error::Agent execution exited with code $gh_aw_exit_code"; fi' EXIT mkdir -p "$HOME/.copilot" - printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json" + printf '%s' '{"builtInAgents":{"rubberDuck":false},"enabledFeatureFlags":{"EXTENSIONS":false}}' > "$HOME/.copilot/settings.json" export XDG_CONFIG_HOME="$HOME" export GH_AW_MCP_CONFIG="$HOME/.copilot/mcp-config.json" GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)" @@ -915,7 +970,7 @@ jobs: export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" (umask 177 && touch /tmp/gh-aw/agent-stdio.log) # shellcheck disable=SC2016 - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.28.23/awf-config.schema.json","network":{"allowDomains":["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","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","s.symcb.com","s.symcd.com","security.ubuntu.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"],"isolation":true,"topologyAttach":["awmg-mcpg"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":12,"maxCacheMisses":5,"maxAiCredits":60,"models":{"agent":["sonnet-6x","gpt-6","gpt-5.4","gpt-5.5","gpt-5.6","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"auto":["copilot/auto","large"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex","kimi"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"detection":["small"],"evals":["small"],"fable":["copilot/*fable*","anthropic/*fable*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-3.6-flash":["copilot/gemini-3.6*flash*","google/gemini-3.6*flash*","gemini/gemini-3.6*flash*"],"gemini-3.7-flash":["copilot/gemini-3.7*flash*","google/gemini-3.7*flash*","gemini/gemini-3.7*flash*"],"gemini-3.8-flash":["copilot/gemini-3.8*flash*","google/gemini-3.8*flash*","gemini/gemini-3.8*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-omni":["copilot/gemini-omni*","google/gemini-omni*","gemini/gemini-omni*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.1":["copilot/gpt-5.1*","openai/gpt-5.1*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"gpt-5.6":["copilot/gpt-5.6*","openai/gpt-5.6*"],"gpt-6":["copilot/gpt-6*","openai/gpt-6*"],"grok":["copilot/*grok*","openai/*grok*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"image-generation":["copilot/gpt-image*","openai/gpt-image*","openai/chatgpt-image*","copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","google/imagen*"],"kimi":["copilot/kimi*","openai/kimi*"],"kiwi":["copilot/kiwi*","openai/kiwi*"],"large":["sonnet","gpt-6","gpt-5-pro","gpt-5","gemini-pro"],"lyria":["google/lyria*","gemini/lyria*","copilot/lyria*"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mai-code-1-flash-picker":["copilot/MAI-Code-1-Flash-picker*","copilot/mai-code-1-flash-picker*","openai/MAI-Code-1-Flash-picker*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"raptor-mini":["copilot/raptor*","openai/raptor*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-5*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*","anthropic/*sonnet-5*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"veo":["google/veo*","gemini/veo*"],"vision":["copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.28.23,squid=sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0,agent=sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2,api-proxy=sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64,cli-proxy=sha256:9e31a6e518eba44652b9ae94ce55c3b6958e06290c3b81b08de4174751bb439a"},"logging":{"proxyLogsDir":"/tmp/gh-aw/sandbox/firewall/logs","auditDir":"/tmp/gh-aw/sandbox/firewall/audit"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.28.57/awf-config.schema.json","network":{"allowDomains":["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","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","s.symcb.com","s.symcd.com","security.ubuntu.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"],"isolation":true,"topologyAttach":["awmg-mcpg"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":12,"maxCacheMisses":5,"maxAiCredits":60,"models":{"agent":["sonnet-6x","gpt-6","gpt-5.4","gpt-5.5","gpt-5.6","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"auto":["copilot/auto","large"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex","kimi"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"detection":["small"],"evals":["small"],"fable":["copilot/*fable*","anthropic/*fable*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-3.6-flash":["copilot/gemini-3.6*flash*","google/gemini-3.6*flash*","gemini/gemini-3.6*flash*"],"gemini-3.7-flash":["copilot/gemini-3.7*flash*","google/gemini-3.7*flash*","gemini/gemini-3.7*flash*"],"gemini-3.8-flash":["copilot/gemini-3.8*flash*","google/gemini-3.8*flash*","gemini/gemini-3.8*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-omni":["copilot/gemini-omni*","google/gemini-omni*","gemini/gemini-omni*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.1":["copilot/gpt-5.1*","openai/gpt-5.1*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"gpt-5.6":["copilot/gpt-5.6*","openai/gpt-5.6*"],"gpt-6":["copilot/gpt-6*","openai/gpt-6*"],"grok":["copilot/*grok*","openai/*grok*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"image-generation":["copilot/gpt-image*","openai/gpt-image*","openai/chatgpt-image*","copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","google/imagen*"],"kimi":["copilot/kimi*","openai/kimi*"],"kiwi":["copilot/kiwi*","openai/kiwi*"],"large":["sonnet","gpt-6","gpt-5-pro","gpt-5","gemini-pro"],"lyria":["google/lyria*","gemini/lyria*","copilot/lyria*"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mai-code-1-flash-picker":["copilot/MAI-Code-1-Flash-picker*","copilot/mai-code-1-flash-picker*","openai/MAI-Code-1-Flash-picker*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"raptor-mini":["copilot/raptor*","openai/raptor*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-5*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*","anthropic/*sonnet-5*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"veo":["google/veo*","gemini/veo*"],"vision":["copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.28.57,squid=sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac,agent=sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a,api-proxy=sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc,cli-proxy=sha256:4584f030659ee51958223a3c6156e8119c6a94affbfcd92ce75f204702c52641"},"logging":{"proxyLogsDir":"/tmp/gh-aw/sandbox/firewall/logs","auditDir":"/tmp/gh-aw/sandbox/firewall/audit"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST="" @@ -944,24 +999,26 @@ jobs: GH_AW_AWF_LOG_FILE=/tmp/gh-aw/agent-stdio.log \ GH_AW_AWF_ATTEMPT_LOG_NAME=copilot \ bash "${RUNNER_TEMP}/gh-aw/actions/run_awf_with_startup_retries.sh" -- \ - awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' + awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_ENGINE_STEP_TIMEOUT_MINUTES:+--agent-timeout "$GH_AW_ENGINE_STEP_TIMEOUT_MINUTES"} ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --deny-tool workflow --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' env: AWF_REFLECT_ENABLED: 1 COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }} + GH_AW_ENGINE_STEP_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }} GH_AW_LLM_PROVIDER: github GH_AW_MAX_TURNS: 12 GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }} - GH_AW_VERSION: v0.89.21 + GH_AW_VERSION: v0.92.0 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS: false GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -974,6 +1031,19 @@ jobs: GIT_COMMITTER_NAME: github-actions[bot] RUNNER_TEMP: ${{ runner.temp }} TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} + - name: Log GitHub rate limits at agent end + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs')); + await fetchAndLogRateLimit(github, 'agent_end', true); - name: Detect agent errors if: always() id: detect-agent-errors @@ -1127,35 +1197,49 @@ jobs: - name: Upload agent output fallback artifact if: always() continue-on-error: true - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: agent-output-fallback path: | /tmp/gh-aw/agent_output.json /tmp/gh-aw/safeoutputs.jsonl /tmp/gh-aw/agent_execution.json + /tmp/gh-aw/agent_execution_exit_code.txt /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/agent_usage.json + /tmp/gh-aw/agent/model-endpoint-mismatch.json /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl + /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/model-routing.jsonl /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl + /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/model-routing.jsonl /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl + /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/model-routing.jsonl if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} - name: Upload agent artifacts if: always() continue-on-error: true - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/agent_execution.json + /tmp/gh-aw/agent_execution_exit_code.txt + /tmp/gh-aw/agent-session.jsonl + /tmp/gh-aw/agent-errors.jsonl + /tmp/gh-aw/aw-prompts/user.txt + /tmp/gh-aw/aw-prompts/system.txt + /tmp/gh-aw/skill_inventory.json /tmp/gh-aw/sandbox/agent/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent_usage.json + /tmp/gh-aw/runtime/aw_info.json /tmp/gh-aw/agent_usage.jsonl + /tmp/gh-aw/agent/model-endpoint-mismatch.json /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/pre-agent-audit.txt /tmp/gh-aw/github_rate_limits.jsonl @@ -1170,8 +1254,10 @@ jobs: /tmp/gh-aw/sandbox/firewall/audit/ /tmp/gh-aw/sandbox/firewall/awf-reflect.json if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} conclusion: + name: conclusion needs: - activation - agent @@ -1183,6 +1269,7 @@ jobs: needs.activation.outputs.secret_verification_result == 'failed' || needs.activation.outputs.daily_ai_credits_exceeded == 'true' || needs.activation.outputs.daily_ai_credits_guardrail_status == 'structural_error' || needs.activation.outputs.daily_ai_credits_guardrail_status == 'transient_error') runs-on: ubuntu-slim + # Permissions for the conclusion job (workflow permissions default to none). permissions: actions: read issues: write @@ -1195,13 +1282,14 @@ jobs: GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} outputs: incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + noop_comment_body: ${{ steps.noop.outputs.noop_comment_body }} noop_message: ${{ steps.noop.outputs.noop_message }} tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 + uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1210,13 +1298,14 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.87" - GH_AW_INFO_AWF_VERSION: "v0.28.23" + GH_AW_INFO_VERSION: "1.0.96" + GH_AW_INFO_AWF_VERSION: "v0.28.57" GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Download agent output artifact id: download-agent-output continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: pattern: "{agent,agent-output-fallback}" merge-multiple: true @@ -1230,10 +1319,17 @@ jobs: if [ -f "/tmp/gh-aw/agent_output.json" ]; then echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" fi + - name: Restore runtime model metadata + if: always() + run: | + if [ -f /tmp/gh-aw/runtime/aw_info.json ]; then cp /tmp/gh-aw/runtime/aw_info.json /tmp/gh-aw/aw_info.json; fi + - name: Warn if threat detection produced no verdict + if: always() && needs.detection.result != 'skipped' && (needs.detection.outputs.detection_reason == 'agent_failure' || needs.detection.outputs.detection_reason == 'parse_error' || needs.detection.outputs.detection_conclusion == '') + run: echo "::warning::Threat detection produced no security verdict. Review the detection job logs before trusting the agent outputs." - name: Download detection artifact id: download-detection-artifact continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: detection path: /tmp/gh-aw/threat-detection/ @@ -1241,77 +1337,21 @@ jobs: id: download-safe-outputs-manifest if: always() continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: pattern: safe-outputs-items merge-multiple: true path: /tmp/gh-aw/ - - name: Collect usage artifact files - if: always() - continue-on-error: true - run: bash "${RUNNER_TEMP}/gh-aw/actions/collect_usage_artifact_files.sh" - - name: Upload usage artifact - id: upload-usage-artifact - if: always() - continue-on-error: true - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: usage - path: | - /tmp/gh-aw/usage/aw_info.json - /tmp/gh-aw/usage/aw-info.jsonl - /tmp/gh-aw/usage/agent_usage.json - /tmp/gh-aw/usage/agent_usage.jsonl - /tmp/gh-aw/usage/detection_usage.jsonl - /tmp/gh-aw/usage/evals.jsonl - /tmp/gh-aw/usage/graders/grader_manifest.json - /tmp/gh-aw/usage/graders/grader_results.json - /tmp/gh-aw/usage/github_rate_limits.jsonl - /tmp/gh-aw/usage/agent/token_usage.jsonl - /tmp/gh-aw/usage/agent/execution.json - /tmp/gh-aw/usage/detection/token_usage.jsonl - /tmp/gh-aw/usage/detection/execution.json - /tmp/gh-aw/usage/evals/token_usage.jsonl - /tmp/gh-aw/usage/evals/execution.json - /tmp/gh-aw/usage/activity/summary.json - if-no-files-found: ignore - - name: Wait before retrying usage artifact upload - if: always() && steps.upload-usage-artifact.outcome == 'failure' - run: sleep 10 - - name: Retry upload usage artifact - id: upload-usage-artifact-retry - if: always() && steps.upload-usage-artifact.outcome == 'failure' - continue-on-error: true - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: usage - path: | - /tmp/gh-aw/usage/aw_info.json - /tmp/gh-aw/usage/aw-info.jsonl - /tmp/gh-aw/usage/agent_usage.json - /tmp/gh-aw/usage/agent_usage.jsonl - /tmp/gh-aw/usage/detection_usage.jsonl - /tmp/gh-aw/usage/evals.jsonl - /tmp/gh-aw/usage/graders/grader_manifest.json - /tmp/gh-aw/usage/graders/grader_results.json - /tmp/gh-aw/usage/github_rate_limits.jsonl - /tmp/gh-aw/usage/agent/token_usage.jsonl - /tmp/gh-aw/usage/agent/execution.json - /tmp/gh-aw/usage/detection/token_usage.jsonl - /tmp/gh-aw/usage/detection/execution.json - /tmp/gh-aw/usage/evals/token_usage.jsonl - /tmp/gh-aw/usage/evals/execution.json - /tmp/gh-aw/usage/activity/summary.json - if-no-files-found: ignore - overwrite: true - name: Process no-op messages id: noop uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_NOOP_MAX: "1" + GH_AW_NOOP_MAX: "2" GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/pr-ai-slop-review.md" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_REPORT_AS_ISSUE: "false" @@ -1355,6 +1395,8 @@ jobs: GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/pr-ai-slop-review.md" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1372,6 +1414,8 @@ jobs: GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/pr-ai-slop-review.md" + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1400,11 +1444,14 @@ jobs: GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }} GH_AW_AIC: ${{ needs.agent.outputs.aic }} GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} + GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }} GH_AW_MAX_AI_CREDITS: "60" + GH_AW_DEFAULT_CHECKOUT_USES_TRIGGER_REF: "false" GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} + GH_AW_MODEL_ENDPOINT_MISMATCH_ERROR: ${{ needs.agent.outputs.model_endpoint_mismatch_error }} GH_AW_HTTP_400_RESPONSE_ERROR: ${{ needs.agent.outputs.http_400_response_error }} GH_AW_MAX_CACHE_MISSES_EXCEEDED: ${{ needs.agent.outputs.max_cache_misses_exceeded }} GH_AW_MISSING_MODEL_PRICING_ERROR: ${{ needs.agent.outputs.missing_model_pricing_error }} @@ -1418,6 +1465,7 @@ jobs: GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }} GH_AW_DAILY_AI_CREDITS_GUARDRAIL_ERROR: ${{ needs.activation.outputs.daily_ai_credits_guardrail_error }} GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }} + GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }} GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }} GH_AW_DAILY_AI_CREDITS_CONTINUE_ON_ERROR: "false" GH_AW_GROUP_REPORTS: "false" @@ -1443,6 +1491,8 @@ jobs: GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/pr-ai-slop-review.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_JOB_RESULTS: ${{ toJSON(needs) }} + GH_AW_JOB_DISPLAY_NAMES: "{\"activation\":\"Activation\",\"agent\":\"Agent\",\"check_token_telemetry\":\"Check token telemetry\",\"conclusion\":\"Conclusion\",\"detection\":\"Detection\",\"evals\":\"Evaluations\",\"pre_activation\":\"Pre-activation\",\"push_evals_state\":\"Push evaluations state\",\"push_experiments_state\":\"Push experiments state\",\"push_ledger_changes\":\"Push ledger changes\",\"push_repo_memory\":\"Push repository memory\",\"safe_outputs\":\"Safe outputs\",\"send_slack_message\":\"Send Slack message\",\"unlock\":\"Unlock\",\"update_cache_memory\":\"Update cache memory\",\"update_drive_memory\":\"Update drive memory\",\"upload_assets\":\"Upload assets\",\"upload_code_coverage\":\"Upload code coverage\",\"upload_code_scanning_sarif\":\"Upload code scanning results\"}" GH_AW_REPORT_FAILED_JOBS: "true" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1453,13 +1503,109 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require(path.join(actionsDir, 'report_failed_jobs.cjs')); await main(); + - name: Collect usage artifact files + if: always() + continue-on-error: true + env: + GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }} + GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} + GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/collect_usage_artifact_files.sh" + - name: Generate usage activity summary and unified session + if: always() + continue-on-error: true + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }} + GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }} + GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }} + GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }} + GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }} + with: + script: | + const path = require('path'); + const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); + const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require(path.join(actionsDir, 'generate_usage_artifacts.cjs')); + await main(); + - name: Upload usage artifact + id: upload-usage-artifact + if: always() + continue-on-error: true + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw_session.jsonl + /tmp/gh-aw/usage/aw_info.json + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.json + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/evals.jsonl + /tmp/gh-aw/usage/graders/grader_manifest.json + /tmp/gh-aw/usage/graders/grader_results.json + /tmp/gh-aw/usage/github_rate_limits.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/agent/model-routing.jsonl + /tmp/gh-aw/usage/agent/execution.json + /tmp/gh-aw/usage/detection/token_usage.jsonl + /tmp/gh-aw/usage/detection/execution.json + /tmp/gh-aw/usage/detection/detection_result.json + /tmp/gh-aw/usage/evals/token_usage.jsonl + /tmp/gh-aw/usage/evals/execution.json + /tmp/gh-aw/usage/experiment/state.jsonl + /tmp/gh-aw/usage/experiment/state.json + /tmp/gh-aw/usage/experiment/assignments.json + /tmp/gh-aw/usage/activity/summary.json + if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} + - name: Wait before retrying usage artifact upload + if: always() && steps.upload-usage-artifact.outcome == 'failure' + run: sleep 10 + - name: Retry upload usage artifact + id: upload-usage-artifact-retry + if: always() && steps.upload-usage-artifact.outcome == 'failure' + continue-on-error: true + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw_session.jsonl + /tmp/gh-aw/usage/aw_info.json + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.json + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/evals.jsonl + /tmp/gh-aw/usage/graders/grader_manifest.json + /tmp/gh-aw/usage/graders/grader_results.json + /tmp/gh-aw/usage/github_rate_limits.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/agent/model-routing.jsonl + /tmp/gh-aw/usage/agent/execution.json + /tmp/gh-aw/usage/detection/token_usage.jsonl + /tmp/gh-aw/usage/detection/execution.json + /tmp/gh-aw/usage/detection/detection_result.json + /tmp/gh-aw/usage/evals/token_usage.jsonl + /tmp/gh-aw/usage/evals/execution.json + /tmp/gh-aw/usage/experiment/state.jsonl + /tmp/gh-aw/usage/experiment/state.json + /tmp/gh-aw/usage/experiment/assignments.json + /tmp/gh-aw/usage/activity/summary.json + if-no-files-found: ignore + overwrite: true + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} detection: + name: detection needs: - activation - agent if: always() && needs.agent.result != 'skipped' runs-on: ubuntu-latest + # Permissions for the detection job (workflow permissions default to none). permissions: contents: read timeout-minutes: 10 @@ -1473,7 +1619,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 + uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1482,19 +1628,20 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.87" - GH_AW_INFO_AWF_VERSION: "v0.28.23" + GH_AW_INFO_VERSION: "1.0.96" + GH_AW_INFO_AWF_VERSION: "v0.28.57" GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Download activation artifact continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: activation path: /tmp/gh-aw - name: Download agent output artifact id: download-agent-output continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: pattern: "{agent,agent-output-fallback}" merge-multiple: true @@ -1527,7 +1674,7 @@ jobs: rm -rf /tmp/gh-aw/sandbox/firewall/logs rm -rf /tmp/gh-aw/sandbox/firewall/audit - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.23@sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2 ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23@sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64 ghcr.io/github/gh-aw-firewall/squid:0.28.23@sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.57@sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57@sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc ghcr.io/github/gh-aw-firewall/squid:0.28.57@sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac - name: Check if detection needed id: detection_guard if: always() @@ -1575,9 +1722,9 @@ jobs: mkdir -p /tmp/gh-aw/threat-detection touch /tmp/gh-aw/threat-detection/detection.log - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.23 --rootless + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.57 --rootless - name: Setup Node.js - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: '24' package-manager-cache: false @@ -1585,7 +1732,7 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" env: GH_HOST: github.com - GH_AW_COMPILED_VERSION: v0.89.21 + GH_AW_COMPILED_VERSION: v0.92.0 - name: Install threat-detect binary id: threat_detect_install if: always() && steps.detection_guard.outputs.run_detection == 'true' @@ -1610,10 +1757,11 @@ jobs: GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_TIMEOUT_MINUTES: 10 - GH_AW_VERSION: v0.89.21 + GH_AW_VERSION: v0.92.0 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS: false GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} GITHUB_SERVER_URL: ${{ github.server_url }} @@ -1655,7 +1803,7 @@ jobs: if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then GH_AW_MAX_AI_CREDITS="400" fi - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.28.23/awf-config.schema.json\",\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.28.23,squid=sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0,agent=sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2,api-proxy=sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64,cli-proxy=sha256:9e31a6e518eba44652b9ae94ce55c3b6958e06290c3b81b08de4174751bb439a\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.28.57/awf-config.schema.json\",\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.28.57,squid=sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac,agent=sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a,api-proxy=sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc,cli-proxy=sha256:4584f030659ee51958223a3c6156e8119c6a94affbfcd92ce75f204702c52641\",\"agentTimeout\":10},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST="" @@ -1674,8 +1822,8 @@ jobs: fi fi # shellcheck disable=SC1003,SC2016,SC2086 - awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --mount /tmp/gh-aw:/tmp/gh-aw:rw --mount /tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw --log-level info --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && threat-detect --engine copilot --output /tmp/gh-aw/threat-detection/detection_result.json /tmp/gh-aw/threat-detection' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --mount /tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && threat-detect --engine copilot --output /tmp/gh-aw/threat-detection/detection_result.json /tmp/gh-aw/threat-detection' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log - name: Render detection log if: always() && steps.detection_guard.outputs.run_detection == 'true' continue-on-error: true @@ -1702,6 +1850,7 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_TOKEN_USAGE_SUMMARY_TITLE: Threat Detection Token Usage + GH_AW_PHASE: detection GH_AW_AGENT_USAGE_PATH: /tmp/gh-aw/threat-detection/detection_usage.json GH_AW_AGENT_USAGE_JSONL_PATH: /tmp/gh-aw/threat-detection/detection_usage.jsonl GH_AW_WRITE_EMPTY_USAGE: "true" @@ -1715,7 +1864,7 @@ jobs: await main(); - name: Upload threat detection artifact if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: detection path: | @@ -1726,6 +1875,7 @@ jobs: /tmp/gh-aw/threat-detection/sandbox/firewall/logs/ /tmp/gh-aw/threat-detection/sandbox/firewall/audit/ if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} - name: Conclude threat detection id: detection_conclusion if: always() @@ -1739,6 +1889,11 @@ jobs: bash "${RUNNER_TEMP}/gh-aw/actions/conclude_threat_detection.sh" /tmp/gh-aw/threat-detection/detection_result.json pre_activation: + name: pre_activation + if: > + (github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id) && + ((github.event_name != 'pull_request' && github.event_name != 'pull_request_review') || github.event.pull_request.stack == null || + github.event.pull_request.stack.position == github.event.pull_request.stack.size) runs-on: ubuntu-slim env: GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} @@ -1751,16 +1906,17 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 + uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.87" - GH_AW_INFO_AWF_VERSION: "v0.28.23" + GH_AW_INFO_VERSION: "1.0.96" + GH_AW_INFO_AWF_VERSION: "v0.28.57" GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Check skip-roles id: check_skip_roles uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -1792,12 +1948,14 @@ jobs: await main(); safe_outputs: + name: safe_outputs needs: - activation - agent - detection if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' runs-on: ubuntu-slim + # Permissions for the safe_outputs job (workflow permissions default to none). permissions: issues: write pull-requests: write @@ -1836,7 +1994,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 + uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1845,15 +2003,16 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.87" - GH_AW_INFO_AWF_VERSION: "v0.28.23" + GH_AW_INFO_VERSION: "1.0.96" + GH_AW_INFO_AWF_VERSION: "v0.28.57" GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Download agent output artifact id: download-agent-output continue-on-error: true - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: pattern: "{agent,agent-output-fallback}" merge-multiple: true @@ -1880,24 +2039,27 @@ jobs: id: process_safe_outputs uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: + GH_AW_JOB_CHECK_RUN_ID: ${{ job.check_run_id }} GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} + GH_AW_MENTIONS_GITHUB_TOKEN: ${{ github.token }} GH_AW_ALLOWED_DOMAINS: "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,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,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1},\"add_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":1},\"create_report_incomplete_issue\":{},\"mentions\":{\"enabled\":false},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"remove_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":2},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1},\"add_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":1},\"create_report_incomplete_issue\":{},\"mentions\":{\"enabled\":false},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"remove_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":2},\"report_incomplete\":{}}" + GH_AW_GITHUB_TOKEN_SOURCE: ${{ secrets.GH_AW_GITHUB_TOKEN != '' && 'pat' || 'github_actions' }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | const path = require('path'); const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); - setupGlobals(core, github, context, exec, io, getOctokit); + setupGlobals(core, github, context, exec, io, getOctokit, process.env.GH_AW_GITHUB_TOKEN_SOURCE); const { main } = require(path.join(actionsDir, 'process_safe_outputs.cjs')); await main(); - name: Upload Safe Outputs Items if: always() - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: safe-outputs-items path: | @@ -1905,3 +2067,4 @@ jobs: /tmp/gh-aw/temporary-id-map.json /tmp/gh-aw/safe-output-errors.json if-no-files-found: ignore + retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} diff --git a/.github/workflows/pr-ai-slop-review.md b/.github/workflows/pr-ai-slop-review.md index 63c8799c7..dd392e6b9 100644 --- a/.github/workflows/pr-ai-slop-review.md +++ b/.github/workflows/pr-ai-slop-review.md @@ -8,7 +8,7 @@ on: roles: all skip-roles: [admin, maintainer, write] skip-bots: [dependabot, renovate] - pull_request_target: + pull_request: # reopened is intentionally excluded: reopens carry no new implementation # evidence (the rerun-stability policy handles them), and a manual # workflow_dispatch remains available when a re-review is wanted. @@ -26,6 +26,7 @@ max-daily-ai-credits: 5000 permissions: issues: read pull-requests: read + copilot-requests: none pre-agent-steps: - name: Make Copilot quota exhaustion non-blocking From f38ceae3fb6c95426413fc195869205ab239d040 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Sat, 17 Oct 2026 08:10:16 +0800 Subject: [PATCH 07/25] fix(profiles): restore single switch error toast and refetch after busy patchProfiles entered the mutate funnel without errorNotice:false, so a failed switch toasted twice. On busy the cached current profile was left untouched, so a discarded switch draft could poison later clicks on the target profile. Refetch on every non-valid outcome. --- src/hooks/use-profiles.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/hooks/use-profiles.ts b/src/hooks/use-profiles.ts index 2ebbd3c2a..f07fd4ce0 100644 --- a/src/hooks/use-profiles.ts +++ b/src/hooks/use-profiles.ts @@ -51,6 +51,7 @@ export const useProfiles = () => { try { const result = await mutate(() => patchProfilesConfig(value), { id: 'patch-profiles-config', + errorNotice: false, onFulfilled: (outcome) => { if (outcome.status === 'valid') { void setCacheData(profilesQueryKey, (current) => @@ -60,12 +61,8 @@ export const useProfiles = () => { }, }) - if (!result.ok) { - // Backend Busy keeps local state untouched, as before. - return result.value - } const outcome = result.value - if (outcome.status !== 'valid' && outcome.status !== 'busy') { + if (outcome.status !== 'valid') { await mutateProfiles() } return outcome From e014b913d285f15813b7fc71f469f07780cb655f Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Sat, 17 Oct 2026 09:14:57 +0800 Subject: [PATCH 08/25] fix(profile): close switching-flag leak window and drop duplicate busy notice The switching flag was released by a defer registered inside perform_config_update, so a panic during the write-lock wait or the draft edit could leave it stuck set. Register the defer right after the CAS. Skip the generic validation notice for busy switch outcomes; the frontend already shows its own busy toast. --- src-tauri/src/cmd/profile.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src-tauri/src/cmd/profile.rs b/src-tauri/src/cmd/profile.rs index 8c20504e8..3448d1502 100644 --- a/src-tauri/src/cmd/profile.rs +++ b/src-tauri/src/cmd/profile.rs @@ -282,7 +282,9 @@ async fn handle_validation_failure( ) -> CmdResult { logging!(warn, Type::Cmd, "配置验证失败: {}", outcome); discard_and_restore(current_profile).await?; - handle_validation_notice(&outcome, ValidationNoticeTarget::Runtime, "运行时配置"); + if !matches!(outcome, ValidationOutcome::Busy) { + handle_validation_notice(&outcome, ValidationNoticeTarget::Runtime, "运行时配置"); + } Ok(outcome) } @@ -311,9 +313,6 @@ async fn perform_config_update( current_value: Option<&String>, current_profile: Option<&String>, ) -> CmdResult { - defer! { - CURRENT_SWITCHING_PROFILE.store(false, Ordering::Release); - } let update_result = run_profile_config_update_transition(|| CoreManager::global().update_config_forced()).await; match update_result { @@ -409,6 +408,9 @@ pub async fn patch_profiles_config(profiles: ProfileSelection) -> CmdResult Date: Sat, 17 Oct 2026 10:32:15 +0800 Subject: [PATCH 09/25] perf(frontend): hoist notice table and skip no-op loading updates The notice handler table was rebuilt on every notice event; build it once at module scope. withLoading returned a new state even when the loading set was unchanged, re-rendering store consumers for nothing. --- src/services/notice-handlers.ts | 423 ++++++++++++++++---------------- src/store/app-state.ts | 1 + 2 files changed, 208 insertions(+), 216 deletions(-) diff --git a/src/services/notice-handlers.ts b/src/services/notice-handlers.ts index c87c5a9f2..669853a4c 100644 --- a/src/services/notice-handlers.ts +++ b/src/services/notice-handlers.ts @@ -32,230 +32,221 @@ export const forgetShownStartupError = () => { * type makes a backend status without a frontend entry a compile error (and * contract regeneration keeps the union in sync). */ +const handlers: Record< + NoticeStatus, + (msg: string, navigate: NavigateFunction) => void +> = { + info: (msg) => { + if (msg) showNotice.info(msg) + }, + 'import_sub_url::ok': (_msg, navigate) => { + // 空 msg 传入,我们不希望导致 后端-前端-后端 死循环,这里只做提醒。 + // 未来细分事件通知时,可以考虑传入订阅 ID 或其他标识符 + // navigate("/profile", { state: { current: msg } }); + navigate('/profile') + showNotice.success( + 'shared.feedback.notifications.importSubscriptionSuccess', + ) + }, + 'import_sub_url::error': (msg, navigate) => { + navigate('/profile') + showNotice.error(msg) + }, + 'set_config::error': (msg) => showNotice.error(msg), + 'core_start::error': () => { + const read = ++startupErrorReads + void getCoreStartupError() + .then(async (failure) => { + if (read < settledStartupErrorRead) return + settledStartupErrorRead = read + if (!failure) { + shownStartupError = null + return + } + const window = getCurrentWindow() + const [visible, minimized] = await Promise.all([ + window.isVisible(), + window.isMinimized(), + ]) + const shown = `${failure.kind}:${failure.detail}` + if ( + read === settledStartupErrorRead && + visible && + !minimized && + shownStartupError !== shown + ) { + shownStartupError = shown + showNotice.error( + failure.kind === 'serviceCoreStopped' + ? 'settings.feedback.errors.clash.serviceCoreStopped' + : 'settings.feedback.errors.clash.startFailed', + failure.detail, + ) + } + }) + .catch((error) => { + console.error('Failed to read the pending core startup error', error) + }) + }, + 'service_core::repair_required': () => { + void takeServiceRepairNotice() + .then((pending) => { + if (pending) { + requestService({ reason: 'serviceLocationRefused' }) + } + }) + .catch((error) => { + console.error('Failed to read the pending service repair notice', error) + }) + }, + 'service_core::app_data_not_owned': () => { + void takeServiceOwnerNotice() + .then((command) => { + if (command) { + if (shownOwnerNotice !== null) hideNotice(shownOwnerNotice) + shownOwnerNotice = showNotice.warning( + 'settings.feedback.notifications.clashService.appDataNotOwned', + { command }, + 0, + ) + } + }) + .catch((error) => { + console.error('Failed to read the pending service owner notice', error) + }) + }, + 'service_core::sidecar_fallback': () => { + void takeServiceFallbackNotice() + .then((notice) => { + if (notice?.kind === 'coreRejected') { + showNotice.warning( + 'settings.feedback.notifications.clashService.permissionFallback', + { reason: notice.reason }, + 0, + ) + } else if (notice?.kind === 'notAutoStarted') { + requestService({ reason: 'serviceNotAutoStarted' }) + } else if (notice) { + showNotice.warning( + 'settings.feedback.notifications.clashService.sidecarFallback', + ) + } + }) + .catch((error) => { + console.error( + 'Failed to read the pending service fallback notice', + error, + ) + }) + }, + 'dns_override::auto_disabled': () => { + void takeDnsOverrideNotice() + .then((pending) => { + if (pending) { + showNotice.info('settings.modals.dns.protection.autoDisabled') + } + }) + .catch((error) => { + console.error('Failed to read the pending DNS override notice', error) + }) + }, + 'enhance::discarded_keys': () => { + void takeDiscardedKeysNotice() + .then((keys) => { + if (keys) { + showNotice.warning('profiles.page.feedback.notices.discardedKeys', { + keys, + }) + } + }) + .catch((error) => { + console.error('Failed to read the pending discarded keys notice', error) + }) + }, + 'tun_mode::auto_disabled': () => + showNotice.info( + 'settings.sections.system.notifications.tunMode.autoDisabled', + ), + 'tun_mode::auto_disable_failed': () => + showNotice.error( + 'settings.sections.system.notifications.tunMode.autoDisableFailed', + ), + 'app_restart::core_stop_failed': (msg) => + showNotice.error( + 'layout.feedback.errors.restartCoreStopFailed', + msg || undefined, + ), + 'app_quit::core_stop_failed': (msg) => + showNotice.error( + 'layout.feedback.errors.quitCoreStopFailed', + msg || undefined, + ), + update_with_clash_proxy: (msg) => + showNotice.success( + 'settings.feedback.notifications.updater.withClashProxySuccess', + msg, + ), + update_failed_even_with_clash: (msg) => + showNotice.error( + 'settings.feedback.notifications.updater.withClashProxyFailed', + msg, + ), + 'reactivate_profiles::error': (msg) => showNotice.error(msg), + update_failed: (msg) => showNotice.error(msg), + 'config_validate::boot_error': (msg) => + showNotice.error('shared.feedback.validation.config.bootFailed', msg), + 'config_validate::error': (msg) => + showNotice.error('shared.feedback.validation.config.failed', msg), + 'config_validate::process_terminated': () => + showNotice.error('shared.feedback.validation.config.processTerminated'), + 'config_validate::script_error': (msg) => + showNotice.error('shared.feedback.validation.script.fileError', msg), + 'config_validate::script_syntax_error': (msg) => + showNotice.error('shared.feedback.validation.script.syntaxError', msg), + 'config_validate::script_missing_main': (msg) => + showNotice.error('shared.feedback.validation.script.missingMain', msg), + 'config_validate::file_not_found': (msg) => + showNotice.error('shared.feedback.validation.script.fileNotFound', msg), + 'config_validate::yaml_syntax_error': (msg) => + showNotice.error('shared.feedback.validation.yaml.syntaxError', msg), + 'config_validate::yaml_read_error': (msg) => + showNotice.error('shared.feedback.validation.yaml.readError', msg), + 'config_validate::yaml_mapping_error': (msg) => + showNotice.error('shared.feedback.validation.yaml.mappingError', msg), + 'config_validate::merge_syntax_error': (msg) => + showNotice.error('shared.feedback.validation.merge.syntaxError', msg), + 'config_validate::merge_mapping_error': (msg) => + showNotice.error('shared.feedback.validation.merge.mappingError', msg), + 'config_core::change_success': (msg) => + showNotice.success( + 'settings.feedback.notifications.clash.changeSuccess', + msg, + ), + 'config_core::change_error': (msg) => + showNotice.error('settings.feedback.notifications.clash.changeFailed', msg), + 'mixed_port::fallback': (msg) => { + const [oldPort, newPort] = msg.split(',') + showNotice.info('settings.modals.clashPort.messages.automaticFallback', { + oldPort, + newPort, + }) + }, + 'mixed_port::fallback_error': (msg) => + showNotice.error( + 'settings.modals.clashPort.messages.automaticFallbackFailed', + { error: msg }, + ), +} + export const handleNoticeMessage = ( status: string, msg: string, t: TranslateFunction, navigate: NavigateFunction, ) => { - const handlers: Record void> = { - info: () => { - if (msg) showNotice.info(msg) - }, - 'import_sub_url::ok': () => { - // 空 msg 传入,我们不希望导致 后端-前端-后端 死循环,这里只做提醒。 - // 未来细分事件通知时,可以考虑传入订阅 ID 或其他标识符 - // navigate("/profile", { state: { current: msg } }); - navigate('/profile') - showNotice.success( - 'shared.feedback.notifications.importSubscriptionSuccess', - ) - }, - 'import_sub_url::error': () => { - navigate('/profile') - showNotice.error(msg) - }, - 'set_config::error': () => showNotice.error(msg), - 'core_start::error': () => { - const read = ++startupErrorReads - void getCoreStartupError() - .then(async (failure) => { - if (read < settledStartupErrorRead) return - settledStartupErrorRead = read - if (!failure) { - shownStartupError = null - return - } - const window = getCurrentWindow() - const [visible, minimized] = await Promise.all([ - window.isVisible(), - window.isMinimized(), - ]) - const shown = `${failure.kind}:${failure.detail}` - if ( - read === settledStartupErrorRead && - visible && - !minimized && - shownStartupError !== shown - ) { - shownStartupError = shown - showNotice.error( - failure.kind === 'serviceCoreStopped' - ? 'settings.feedback.errors.clash.serviceCoreStopped' - : 'settings.feedback.errors.clash.startFailed', - failure.detail, - ) - } - }) - .catch((error) => { - console.error('Failed to read the pending core startup error', error) - }) - }, - 'service_core::repair_required': () => { - void takeServiceRepairNotice() - .then((pending) => { - if (pending) { - requestService({ reason: 'serviceLocationRefused' }) - } - }) - .catch((error) => { - console.error( - 'Failed to read the pending service repair notice', - error, - ) - }) - }, - 'service_core::app_data_not_owned': () => { - void takeServiceOwnerNotice() - .then((command) => { - if (command) { - if (shownOwnerNotice !== null) hideNotice(shownOwnerNotice) - shownOwnerNotice = showNotice.warning( - 'settings.feedback.notifications.clashService.appDataNotOwned', - { command }, - 0, - ) - } - }) - .catch((error) => { - console.error( - 'Failed to read the pending service owner notice', - error, - ) - }) - }, - 'service_core::sidecar_fallback': () => { - void takeServiceFallbackNotice() - .then((notice) => { - if (notice?.kind === 'coreRejected') { - showNotice.warning( - 'settings.feedback.notifications.clashService.permissionFallback', - { reason: notice.reason }, - 0, - ) - } else if (notice?.kind === 'notAutoStarted') { - requestService({ reason: 'serviceNotAutoStarted' }) - } else if (notice) { - showNotice.warning( - 'settings.feedback.notifications.clashService.sidecarFallback', - ) - } - }) - .catch((error) => { - console.error( - 'Failed to read the pending service fallback notice', - error, - ) - }) - }, - 'dns_override::auto_disabled': () => { - void takeDnsOverrideNotice() - .then((pending) => { - if (pending) { - showNotice.info('settings.modals.dns.protection.autoDisabled') - } - }) - .catch((error) => { - console.error('Failed to read the pending DNS override notice', error) - }) - }, - 'enhance::discarded_keys': () => { - void takeDiscardedKeysNotice() - .then((keys) => { - if (keys) { - showNotice.warning('profiles.page.feedback.notices.discardedKeys', { - keys, - }) - } - }) - .catch((error) => { - console.error( - 'Failed to read the pending discarded keys notice', - error, - ) - }) - }, - 'tun_mode::auto_disabled': () => - showNotice.info( - 'settings.sections.system.notifications.tunMode.autoDisabled', - ), - 'tun_mode::auto_disable_failed': () => - showNotice.error( - 'settings.sections.system.notifications.tunMode.autoDisableFailed', - ), - 'app_restart::core_stop_failed': () => - showNotice.error( - 'layout.feedback.errors.restartCoreStopFailed', - msg || undefined, - ), - 'app_quit::core_stop_failed': () => - showNotice.error( - 'layout.feedback.errors.quitCoreStopFailed', - msg || undefined, - ), - update_with_clash_proxy: () => - showNotice.success( - 'settings.feedback.notifications.updater.withClashProxySuccess', - msg, - ), - update_failed_even_with_clash: () => - showNotice.error( - 'settings.feedback.notifications.updater.withClashProxyFailed', - msg, - ), - 'reactivate_profiles::error': () => showNotice.error(msg), - update_failed: () => showNotice.error(msg), - 'config_validate::boot_error': () => - showNotice.error('shared.feedback.validation.config.bootFailed', msg), - 'config_validate::error': () => - showNotice.error('shared.feedback.validation.config.failed', msg), - 'config_validate::process_terminated': () => - showNotice.error('shared.feedback.validation.config.processTerminated'), - 'config_validate::script_error': () => - showNotice.error('shared.feedback.validation.script.fileError', msg), - 'config_validate::script_syntax_error': () => - showNotice.error('shared.feedback.validation.script.syntaxError', msg), - 'config_validate::script_missing_main': () => - showNotice.error('shared.feedback.validation.script.missingMain', msg), - 'config_validate::file_not_found': () => - showNotice.error('shared.feedback.validation.script.fileNotFound', msg), - 'config_validate::yaml_syntax_error': () => - showNotice.error('shared.feedback.validation.yaml.syntaxError', msg), - 'config_validate::yaml_read_error': () => - showNotice.error('shared.feedback.validation.yaml.readError', msg), - 'config_validate::yaml_mapping_error': () => - showNotice.error('shared.feedback.validation.yaml.mappingError', msg), - 'config_validate::merge_syntax_error': () => - showNotice.error('shared.feedback.validation.merge.syntaxError', msg), - 'config_validate::merge_mapping_error': () => - showNotice.error('shared.feedback.validation.merge.mappingError', msg), - 'config_core::change_success': () => - showNotice.success( - 'settings.feedback.notifications.clash.changeSuccess', - msg, - ), - 'config_core::change_error': () => - showNotice.error( - 'settings.feedback.notifications.clash.changeFailed', - msg, - ), - 'mixed_port::fallback': () => { - const [oldPort, newPort] = msg.split(',') - showNotice.info('settings.modals.clashPort.messages.automaticFallback', { - oldPort, - newPort, - }) - }, - 'mixed_port::fallback_error': () => - showNotice.error( - 'settings.modals.clashPort.messages.automaticFallbackFailed', - { error: msg }, - ), - } - const handler = handlers[status as NoticeStatus] if (handler) { - handler() + handler(msg, navigate) } else { console.warn(`未处理的通知状态: ${status}`) } diff --git a/src/store/app-state.ts b/src/store/app-state.ts index c0e143308..ad2fe6cd1 100644 --- a/src/store/app-state.ts +++ b/src/store/app-state.ts @@ -66,6 +66,7 @@ const withLoading = ( next.delete(uid) } } + if (next.size === state.profileUpdates.loading.size) return state return { ...state, profileUpdates: { ...state.profileUpdates, loading: next }, From 8f00096a9f8b36996c3440a47113cfdf1f1dfa85 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:40:05 +0800 Subject: [PATCH 10/25] chore(deps): group Tauri npm and Cargo updates into a single PR Add a packageRule that pulls @tauri-apps/* packages and tauri/tauri-* crates out of the generic npm and cargo groups into one shared "tauri" group, so frontend and backend halves of a Tauri upgrade are validated together. Pin tauri-plugin-mihomo by rev instead of branch so Renovate tracks it: branch-pinned git dependencies are skipped with skipReason git-dependency and never produce updates. With the rev pin the plugin joins the tauri group via digest updates. The rev is the commit already locked in Cargo.lock, so resolution is unchanged. --- Cargo.lock | 2 +- renovate.json | 5 +++++ src-tauri/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32c453c88..d1af5de8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7492,7 +7492,7 @@ dependencies = [ [[package]] name = "tauri-plugin-mihomo" version = "0.6.0" -source = "git+https://github.com/clash-verge-rev/tauri-plugin-mihomo?branch=main#7a03d16f4d39b1bb885b7babe66b9e153e34b615" +source = "git+https://github.com/clash-verge-rev/tauri-plugin-mihomo?rev=7a03d16f4d39b1bb885b7babe66b9e153e34b615#7a03d16f4d39b1bb885b7babe66b9e153e34b615" dependencies = [ "arc-swap", "clashmap", diff --git a/renovate.json b/renovate.json index edc0f4167..60b6615ee 100644 --- a/renovate.json +++ b/renovate.json @@ -45,6 +45,11 @@ "matchManagers": ["npm"], "groupName": "npm dependencies" }, + { + "description": "Update Tauri npm packages and Cargo crates together so frontend and backend stay in sync", + "matchPackageNames": ["@tauri-apps/**", "tauri", "tauri-*"], + "groupName": "tauri" + }, { "description": "Group all GitHub Actions updates into a single PR", "matchManagers": ["github-actions"], diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a6b6a53fe..f8b2fe11b 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -96,7 +96,7 @@ backon = { version = "1.6.0", features = ["tokio-sleep"] } tauri-plugin-http = "2.8.0" tracing = { workspace = true } tauri-plugin-devtools = { version = "2.2.2", optional = true } -tauri-plugin-mihomo = { git = "https://github.com/clash-verge-rev/tauri-plugin-mihomo", branch = "main" } +tauri-plugin-mihomo = { git = "https://github.com/clash-verge-rev/tauri-plugin-mihomo", rev = "7a03d16f4d39b1bb885b7babe66b9e153e34b615" } async-trait = "0.1.92" clash_verge_service_ipc = { git = "https://github.com/clash-verge-rev/clash-verge-service-ipc.git", tag = "v2.7.6", version = "2.7.6", features = [ "client", From b238175f189a134668c2c40c9a72dcf6a69f5dfc Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:53:14 +0800 Subject: [PATCH 11/25] chore(deps): add @wdio/tauri-service to the tauri update group The WebdriverIO Tauri service pairs with the Tauri stack it drives, so its updates belong with the coordinated Tauri npm and Cargo upgrades rather than the generic npm group. --- renovate.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 60b6615ee..2a8fa3fb8 100644 --- a/renovate.json +++ b/renovate.json @@ -47,7 +47,12 @@ }, { "description": "Update Tauri npm packages and Cargo crates together so frontend and backend stay in sync", - "matchPackageNames": ["@tauri-apps/**", "tauri", "tauri-*"], + "matchPackageNames": [ + "@tauri-apps/**", + "@wdio/tauri-service", + "tauri", + "tauri-*" + ], "groupName": "tauri" }, { From 3b7bfa10fd9ab85a119de3d2dcc9e72330e3fa7a Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Sat, 17 Oct 2026 13:01:03 +0800 Subject: [PATCH 12/25] chore(deps): label the tauri group PR Tag the coordinated Tauri update PR with a dedicated tauri label so it stands out from the generic dependency groups. --- renovate.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 2a8fa3fb8..ec7f97412 100644 --- a/renovate.json +++ b/renovate.json @@ -53,7 +53,8 @@ "tauri", "tauri-*" ], - "groupName": "tauri" + "groupName": "tauri", + "addLabels": ["tauri"] }, { "description": "Group all GitHub Actions updates into a single PR", From cef66cd745ef29aa98e219ffb083b62e13c959e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9D=A4=E6=98=AF=E7=BA=B1=E9=9B=BE=E9=85=B1=E5=93=9F?= =?UTF-8?q?=EF=BD=9E?= <49941141+Dragon1573@users.noreply.github.com> Date: Sat, 17 Oct 2026 09:04:27 +0000 Subject: [PATCH 13/25] chore(deps): update dependency pnpm to v12.14.0 (#8340) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/devcontainer.json | 2 +- .tool-versions | 2 +- package.json | 2 +- pnpm-lock.yaml | 122 ++++++++++++++++---------------- 4 files changed, 64 insertions(+), 64 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 74d20b0cb..12501e20e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,7 +5,7 @@ "features": { "ghcr.io/devcontainers/features/node:2": { "version": "24.22.0", - "pnpmVersion": "12.11.2" + "pnpmVersion": "12.14.0" }, "ghcr.io/devcontainers/features/rust:1": { "version": "1.99.0", diff --git a/.tool-versions b/.tool-versions index 1de534f8f..6fbf12b85 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ nodejs 24.22.0 -pnpm 12.11.2 +pnpm 12.14.0 rust 1.99.0 diff --git a/package.json b/package.json index 9ef745150..37020b947 100644 --- a/package.json +++ b/package.json @@ -146,5 +146,5 @@ ] }, "type": "module", - "packageManager": "pnpm@12.11.2" + "packageManager": "pnpm@12.14.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ceac328bc..dc18da919 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,153 +7,153 @@ importers: configDependencies: {} packageManagerDependencies: pnpm: - specifier: 12.11.2 - version: 12.11.2 + specifier: 12.14.0 + version: 12.14.0 packages: - '@pnpm/exe.android-arm64@12.11.2': - resolution: {integrity: sha512-owLw13OfPkEoY+hLBNeeG+dCFhywr7q2d/EHPz4mNL2RhKnv8gNwMARkjkiDQu234aItVwFNDeGnmQXm+ikkAg==} + '@pnpm/exe.android-arm64@12.14.0': + resolution: {integrity: sha512-+iSh7x21C3A2hqc+Z0ZmbKTcn6YNlzrXM142PsnQH/dLj0DYxFzoBvc6XAnL/yfQ5nnH2ebBiRj/zVxr61fZbQ==} cpu: [arm64] os: [android] - '@pnpm/exe.android-x64@12.11.2': - resolution: {integrity: sha512-GYPkVebl4iokOA/4MPSpGoUVfFlsth7uqOCe1XiaiM23LAdvUOMJBObqHJijr89ZqjwHm9pO6vO45GRwJ2U2qA==} + '@pnpm/exe.android-x64@12.14.0': + resolution: {integrity: sha512-qT+0LqEr2wBVaxcG2T8cX/R8SSRz2Rvpp8nRR4fh8tnGUZRch87gFmsHUAoSQh7w6j1h0qTjrA384j4xi8frvw==} cpu: [x64] os: [android] - '@pnpm/exe.darwin-arm64@12.11.2': - resolution: {integrity: sha512-n9M4On66y8FDxUAKgMO1FXt0qihyG4e+56p3/F0uo8Bx9KplW8BwKVnXigzCJ8aNM6sVVPkOE6M9XXbeVIxnZA==} + '@pnpm/exe.darwin-arm64@12.14.0': + resolution: {integrity: sha512-tnrdUB8ecJoehuKKqi1YHCBVl61xtJ9XVGcx5EviC6fWO4DeGI8GtXrjvJxDBM3nuVjJeWistgsUp/N142x4sw==} cpu: [arm64] os: [darwin] - '@pnpm/exe.darwin-x64@12.11.2': - resolution: {integrity: sha512-oSW7n3sBT0c0cyk4kj10T2Y6Mpm+OFEiCAWozgX039tdoI6yqJF1uaFD3sw7ugLdu6VV3+uY0pa1TUZIPdxDWA==} + '@pnpm/exe.darwin-x64@12.14.0': + resolution: {integrity: sha512-vlBfGkruqQRsEHTW43cPwpYd7QlbIJ//cvpAdb3bVXkI8SgTPoXhCnc05m+ZNiPrrEkBsX/t7KHw9aXpkzPm3Q==} cpu: [x64] os: [darwin] - '@pnpm/exe.freebsd-x64@12.11.2': - resolution: {integrity: sha512-qbzc3KoDpa/Lkf8vs3jnDe6dUUbso+6eLIyssYFMiliLpYNxn8dirk11YoNnOQcdHVB50v5RFls1Yid6ttT5pg==} + '@pnpm/exe.freebsd-x64@12.14.0': + resolution: {integrity: sha512-Qg5rxBrGYl6Tfso+EyygPf84fY1Fzy55E/0or+iuYKtnf0vc0MlHJfVIlT7pBukMRntQHRik7hUi0Z4s7AlJsw==} cpu: [x64] os: [freebsd] - '@pnpm/exe.linux-arm64-musl@12.11.2': - resolution: {integrity: sha512-uMEYDwKRktGwANubQ+kYCwmhNwg3Ik6qK89ahsbQ5cP30R/5FVJb/T99vr9XRUBC/A7mZI6eeT92oyVas9ACyg==} + '@pnpm/exe.linux-arm64-musl@12.14.0': + resolution: {integrity: sha512-DRIe4yQkXBGA/PhVJdzlbnllxBdAtnMMvTVLLcGpsK5FvJz9kxD2Hyxtn68ovmNkVX06f6p45cQwfm3wx2jn1A==} cpu: [arm64] os: [linux] libc: [musl] - '@pnpm/exe.linux-arm64@12.11.2': - resolution: {integrity: sha512-6e8ZAQUwFXAWHHHv5FesWqf/kEK04wuitBv5f/gxzkC0DiBfaixr+f+6JQede8SF4Ji5LcMwVFJbzAtffpWxEg==} + '@pnpm/exe.linux-arm64@12.14.0': + resolution: {integrity: sha512-7joGShZ44Nk3WpNU+60JoOPjCXlgxhJAq11S2UiVtwCUDgTer1yTPPfxGW8pxaD6046actYLIYDbZNlubHWs0A==} cpu: [arm64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-ppc64@12.11.2': - resolution: {integrity: sha512-Ui8A4nepkVupx2VpuFfysEluMvWK6gTB5rgVts7Ss/+8dj0RD28x3F/seNeH/zSypgC6yKdV6qsKVQh/uffTuQ==} + '@pnpm/exe.linux-ppc64@12.14.0': + resolution: {integrity: sha512-gSoryn7ySdXd//gjgf3MvvA8ZerJayaSbuMZMtAWq4vb2/wlVEgpl0Kvqt54y58TRj533Qjq2txKgnxd4JyoAQ==} cpu: [ppc64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-riscv64@12.11.2': - resolution: {integrity: sha512-i1yLdQ5bu+wjQ+srtFoJAaY2gN/+oXHFdjul4llCeoDxHE0rTIG3R41NhHfCjyFPW4+CpbBT58933CL9sMOCnA==} + '@pnpm/exe.linux-riscv64@12.14.0': + resolution: {integrity: sha512-EMjew1H9WqQ7pL+tYqCPwiuB+0PeCiJRV7fyWeuFw0wwYUajFBjcaPO3IGAVu9sdmJDU+e+HYv/Zey6aKae0Vw==} cpu: [riscv64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-s390x@12.11.2': - resolution: {integrity: sha512-YS1/lhPjjTsN4QL50VaFZKRa3Uc/bDnhE8eKbJMFvuX06UuFS5YaiDg04APoZdfVSGqTfX27QAg7rfLMSWaqxA==} + '@pnpm/exe.linux-s390x@12.14.0': + resolution: {integrity: sha512-shYOj/SFoXD35fHe0pWr2JofwSXulC0BnEIXLj2QokDi0EF//AfKsui35yKIkTEl+s2VJybc3PO4iJNhKIj5Qw==} cpu: [s390x] os: [linux] libc: [glibc] - '@pnpm/exe.linux-x64-musl@12.11.2': - resolution: {integrity: sha512-7eIxQR05fvJxCujUSKp5KTtehJ7QqrgqP/HD1+BcB/SaV2Be4XI1PEHiOgA1zxsiMIeMvTF6E4G4dYHrFjeXRg==} + '@pnpm/exe.linux-x64-musl@12.14.0': + resolution: {integrity: sha512-btZiZ2Ot0llKK1ndSfA5i3IRX7/S0VrmzseNH/BJ4c+Cady+S81H6vvU1zByggHMyqQhC8OgxO5PiIY7D9bH0Q==} cpu: [x64] os: [linux] libc: [musl] - '@pnpm/exe.linux-x64@12.11.2': - resolution: {integrity: sha512-FK7QKe24AYgppJwO3mpooYptduuvIGqKJPi5ac7MdnWkjUy46JBfYhCW0grnkWKC8YOf0x+vGviuQqJEj3SpQQ==} + '@pnpm/exe.linux-x64@12.14.0': + resolution: {integrity: sha512-F6K8e/jWxiuEYJaQtRRUG9ynBSTEHa+t7Lf86MKuOO5UA7WVVMbi+oB8nY6iKW++ncWS2yG6T9faXZGxqNsfoQ==} cpu: [x64] os: [linux] libc: [glibc] - '@pnpm/exe.win32-arm64@12.11.2': - resolution: {integrity: sha512-PCTjVDdJb6VvraZxrEeFv6EqEA0hhIsAySx28e95J2Tqpi88hLpgOXgNqV0vpxq9A+b8GLQfyk/D+1UlJPv/YQ==} + '@pnpm/exe.win32-arm64@12.14.0': + resolution: {integrity: sha512-DOjlkVB6TtTKeAAe0hNZXn5S7YqESmo1Z6SGbR4BZNQ4isRg31XVHjX2RFTbY8gnZq68IwzyLmPqlEjMmYxofg==} cpu: [arm64] os: [win32] - '@pnpm/exe.win32-x64@12.11.2': - resolution: {integrity: sha512-8sgX86OvRjJ3yZs/TvGR2L31wH9ScPZ+f+geKI3ikuB0RRiK3i4LlTRO8OXN6pdRqj8epMde4312MCjj7JsJdA==} + '@pnpm/exe.win32-x64@12.14.0': + resolution: {integrity: sha512-/LSX6mew/sLf08XqcjemuklNKf1K/Ftpgj4//hK/HKzI2dKbmxDB27a/2OaQ5a0O3/3OFzlssXDziZsi+yVBwQ==} cpu: [x64] os: [win32] - pnpm@12.11.2: - resolution: {integrity: sha512-JaUWUqGWeFr18ovabf6NxYLr76SsHRgCIc4TkCMcX7dmN4IupLbkYzznSs3LCnf3Ja8RutOBd/3t2u6BipVcuQ==} + pnpm@12.14.0: + resolution: {integrity: sha512-wYum2HmT09Fky16JSPMrLAbuhUSH4GzY2GeBNC+z5btGNDZwNHEehoArqpw3vqkGzhkprQjXCITJfYAd8TOJpg==} engines: {node: '>=18.*'} hasBin: true snapshots: - '@pnpm/exe.android-arm64@12.11.2': + '@pnpm/exe.android-arm64@12.14.0': optional: true - '@pnpm/exe.android-x64@12.11.2': + '@pnpm/exe.android-x64@12.14.0': optional: true - '@pnpm/exe.darwin-arm64@12.11.2': + '@pnpm/exe.darwin-arm64@12.14.0': optional: true - '@pnpm/exe.darwin-x64@12.11.2': + '@pnpm/exe.darwin-x64@12.14.0': optional: true - '@pnpm/exe.freebsd-x64@12.11.2': + '@pnpm/exe.freebsd-x64@12.14.0': optional: true - '@pnpm/exe.linux-arm64-musl@12.11.2': + '@pnpm/exe.linux-arm64-musl@12.14.0': optional: true - '@pnpm/exe.linux-arm64@12.11.2': + '@pnpm/exe.linux-arm64@12.14.0': optional: true - '@pnpm/exe.linux-ppc64@12.11.2': + '@pnpm/exe.linux-ppc64@12.14.0': optional: true - '@pnpm/exe.linux-riscv64@12.11.2': + '@pnpm/exe.linux-riscv64@12.14.0': optional: true - '@pnpm/exe.linux-s390x@12.11.2': + '@pnpm/exe.linux-s390x@12.14.0': optional: true - '@pnpm/exe.linux-x64-musl@12.11.2': + '@pnpm/exe.linux-x64-musl@12.14.0': optional: true - '@pnpm/exe.linux-x64@12.11.2': + '@pnpm/exe.linux-x64@12.14.0': optional: true - '@pnpm/exe.win32-arm64@12.11.2': + '@pnpm/exe.win32-arm64@12.14.0': optional: true - '@pnpm/exe.win32-x64@12.11.2': + '@pnpm/exe.win32-x64@12.14.0': optional: true - pnpm@12.11.2: + pnpm@12.14.0: optionalDependencies: - '@pnpm/exe.android-arm64': 12.11.2 - '@pnpm/exe.android-x64': 12.11.2 - '@pnpm/exe.darwin-arm64': 12.11.2 - '@pnpm/exe.darwin-x64': 12.11.2 - '@pnpm/exe.freebsd-x64': 12.11.2 - '@pnpm/exe.linux-arm64': 12.11.2 - '@pnpm/exe.linux-arm64-musl': 12.11.2 - '@pnpm/exe.linux-ppc64': 12.11.2 - '@pnpm/exe.linux-riscv64': 12.11.2 - '@pnpm/exe.linux-s390x': 12.11.2 - '@pnpm/exe.linux-x64': 12.11.2 - '@pnpm/exe.linux-x64-musl': 12.11.2 - '@pnpm/exe.win32-arm64': 12.11.2 - '@pnpm/exe.win32-x64': 12.11.2 + '@pnpm/exe.android-arm64': 12.14.0 + '@pnpm/exe.android-x64': 12.14.0 + '@pnpm/exe.darwin-arm64': 12.14.0 + '@pnpm/exe.darwin-x64': 12.14.0 + '@pnpm/exe.freebsd-x64': 12.14.0 + '@pnpm/exe.linux-arm64': 12.14.0 + '@pnpm/exe.linux-arm64-musl': 12.14.0 + '@pnpm/exe.linux-ppc64': 12.14.0 + '@pnpm/exe.linux-riscv64': 12.14.0 + '@pnpm/exe.linux-s390x': 12.14.0 + '@pnpm/exe.linux-x64': 12.14.0 + '@pnpm/exe.linux-x64-musl': 12.14.0 + '@pnpm/exe.win32-arm64': 12.14.0 + '@pnpm/exe.win32-x64': 12.14.0 --- lockfileVersion: '9.0' From a3cc58013bc02326fb607604c1bb3acc47378a1e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 17 Oct 2026 09:55:28 +0000 Subject: [PATCH 14/25] chore(deps): update rust toolchain to v1.99.1 (#8341) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/devcontainer.json | 2 +- .github/workflows/autobuild.yml | 10 +++++----- .github/workflows/dev.yml | 4 ++-- .github/workflows/release.yml | 12 ++++++------ .github/workflows/signpath-test.yml | 2 +- .tool-versions | 2 +- rust-toolchain.toml | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 12501e20e..bdc7220f7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,7 +8,7 @@ "pnpmVersion": "12.14.0" }, "ghcr.io/devcontainers/features/rust:1": { - "version": "1.99.0", + "version": "1.99.1", "profile": "default" }, "ghcr.io/devcontainers/features/git:1": {}, diff --git a/.github/workflows/autobuild.yml b/.github/workflows/autobuild.yml index 46cd15c33..bd4454978 100644 --- a/.github/workflows/autobuild.yml +++ b/.github/workflows/autobuild.yml @@ -154,7 +154,7 @@ jobs: - name: Install Rust Stable uses: dtolnay/rust-toolchain@master with: - toolchain: '1.99.0' + toolchain: '1.99.1' targets: ${{ matrix.target }} - name: Add Rust Target @@ -206,7 +206,7 @@ jobs: - name: Add Rust Target run: | - rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }} + rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }} rustup target list --installed echo "Rust target ${{ matrix.target }} installed." @@ -257,7 +257,7 @@ jobs: - name: Install Rust Stable uses: dtolnay/rust-toolchain@master with: - toolchain: '1.99.0' + toolchain: '1.99.1' targets: ${{ matrix.target }} - name: Add Rust Target @@ -347,7 +347,7 @@ jobs: - name: Add Rust Target run: | - rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }} + rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }} rustup target list --installed echo "Rust target ${{ matrix.target }} installed." @@ -454,7 +454,7 @@ jobs: - name: Add Rust Target run: | - rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }} + rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }} rustup target list --installed echo "Rust target ${{ matrix.target }} installed." diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 6ea3005c9..e7d0b0148 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -74,7 +74,7 @@ jobs: - name: Install Rust Stable if: github.event.inputs[matrix.input] == 'true' - uses: dtolnay/rust-toolchain@1.99.0 + uses: dtolnay/rust-toolchain@1.99.1 - name: Rust Cache uses: Swatinem/rust-cache@v2 @@ -129,7 +129,7 @@ jobs: if: github.event.inputs[matrix.input] == 'true' run: | # Ensure cross target is installed for the pinned toolchain; fallback without explicit toolchain if needed - rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }} + rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }} rustup target list --installed echo "Rust target ${{ matrix.target }} installed." diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3ed9f2629..97edf94bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -204,7 +204,7 @@ jobs: - name: Install Rust Stable uses: dtolnay/rust-toolchain@master with: - toolchain: '1.99.0' + toolchain: '1.99.1' targets: ${{ matrix.target }} - name: Add Rust Target @@ -244,7 +244,7 @@ jobs: - name: Add Rust Target run: | - rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }} + rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }} rustup target list --installed echo "Rust target ${{ matrix.target }} installed." @@ -311,7 +311,7 @@ jobs: - name: Install Rust Stable uses: dtolnay/rust-toolchain@master with: - toolchain: '1.99.0' + toolchain: '1.99.1' targets: ${{ matrix.target }} - name: Add Rust Target @@ -389,7 +389,7 @@ jobs: - name: Add Rust Target run: | - rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }} + rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }} rustup target list --installed echo "Rust target ${{ matrix.target }} installed." @@ -446,7 +446,7 @@ jobs: - name: Install Rust Stable uses: dtolnay/rust-toolchain@master with: - toolchain: '1.99.0' + toolchain: '1.99.1' targets: ${{ matrix.target }} - name: Add Rust Target @@ -487,7 +487,7 @@ jobs: - name: Add Rust Target run: | - rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }} + rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }} rustup target list --installed echo "Rust target ${{ matrix.target }} installed." diff --git a/.github/workflows/signpath-test.yml b/.github/workflows/signpath-test.yml index 71d6bbc6c..4f091646c 100644 --- a/.github/workflows/signpath-test.yml +++ b/.github/workflows/signpath-test.yml @@ -22,7 +22,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@master with: - toolchain: '1.99.0' + toolchain: '1.99.1' targets: x86_64-pc-windows-msvc - name: Install Node diff --git a/.tool-versions b/.tool-versions index 6fbf12b85..b422ea8d4 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ nodejs 24.22.0 pnpm 12.14.0 -rust 1.99.0 +rust 1.99.1 diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 099ed62f9..9ec55b3b6 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.99.0" +channel = "1.99.1" components = ["rustfmt", "clippy"] From b729e59650f6b56db34c21974ddb30a845bc277e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9D=A4=E6=98=AF=E7=BA=B1=E9=9B=BE=E9=85=B1=E5=93=9F?= =?UTF-8?q?=EF=BD=9E?= <49941141+Dragon1573@users.noreply.github.com> Date: Sat, 17 Oct 2026 11:04:13 +0000 Subject: [PATCH 15/25] Revert "ci(workflows): bump `gh-aw` from 0.89.21 to 0.92.0 (#8330)" (#8343) This reverts commit 089635c8bfef4d339fbc309fa1209e8ad203b344. --- .github/agents/agentic-workflows.md | 24 +- .github/aw/actions-lock.json | 6 +- .github/skills/agentic-workflows/SKILL.md | 13 +- .github/workflows/copilot-setup-steps.yml | 2 +- .github/workflows/pr-ai-slop-review.lock.yml | 483 ++++++------------- .github/workflows/pr-ai-slop-review.md | 3 +- 6 files changed, 172 insertions(+), 359 deletions(-) diff --git a/.github/agents/agentic-workflows.md b/.github/agents/agentic-workflows.md index 782161f83..08c6d9a24 100644 --- a/.github/agents/agentic-workflows.md +++ b/.github/agents/agentic-workflows.md @@ -21,7 +21,7 @@ This is a **dispatcher agent** that routes your request to the appropriate speci - **Creating new workflows**: Routes to `create` prompt - **Updating existing workflows**: Routes to `update` prompt -- **Diagnosis, patching, and active debugging**: Routes to `debug-agentic-workflow` for the local-first strategy, evidence triage and live gates +- **Debugging workflows**: Routes to `debug` prompt - **Upgrading workflows**: Routes to `upgrade-agentic-workflows` prompt - **Creating report-generating workflows**: Routes to `report` prompt — consult this whenever the workflow posts status updates, audits, analyses, or any structured output as issues, discussions, or comments - **Creating shared components**: Routes to `create-shared-agentic-workflow` prompt @@ -31,7 +31,6 @@ This is a **dispatcher agent** that routes your request to the appropriate speci - **CLI commands and triggering workflows**: Routes to `cli-commands` guide — consult this whenever the user asks how to run, compile, debug, or manage workflows from the command line, or when they need the MCP tool equivalent of a `gh aw` command - **Reducing token consumption / cost optimization**: Routes to `token-optimization` guide — consult this whenever the user asks how to reduce token usage, lower costs, speed up workflows, or measure the impact of prompt changes with experiments - **Choosing workflow architectures and design patterns**: Routes to `patterns` guide — consult this whenever the user asks for strategy, architecture, operating models, or pattern selection for agentic workflows -- **Git-backed work queues**: Routes to `work-queue` instructions for producers, dispatchers, workers, observers, deployment and recovery Workflows may optionally include: @@ -48,8 +47,7 @@ Workflows may optionally include: ## Problems This Solves - **Workflow Creation**: Design secure, validated agentic workflows with proper triggers, tools, and permissions -- **Diagnosis and Patching**: Analyze evidence and produce regression-backed fixes without requiring live runs -- **Active Debugging**: Run bounded edit/test/run/audit loops where permitted, stopping on dispatch 403 responses +- **Workflow Debugging**: Analyze logs, identify missing tools, investigate failures, and fix configuration issues - **Version Upgrades**: Migrate workflows to new gh-aw versions, apply codemods, fix breaking changes - **Component Design**: Create reusable shared workflow components that wrap MCP servers @@ -85,14 +83,11 @@ When you interact with this agent, it will: - "Update the PR reviewer to use discussions instead of issues" - "Improve the prompt for the weekly-research workflow" -### Diagnose, Patch, or Debug a Workflow +### Debug Workflow **Load when**: User needs to investigate, audit, debug, or understand a workflow, troubleshoot issues, analyze logs, or fix errors **Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/debug-agentic-workflow.md` -The shared strategy distinguishes diagnosis/patching from permitted active debug -loops using explicit live gates and includes existing-run evidence triage. - **Use cases**: - "Why is this workflow failing?" - "Analyze the logs for workflow X" @@ -185,15 +180,6 @@ loops using explicit live gates and includes existing-run evidence triage. ## Instructions -### Work Queue - -For queue design, deployment, inspection or recovery, load -`https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/work-queue.md`. -Also load it after the primary create/update/debug/upgrade prompt whenever a -workflow uses `tools.work-queue`. Load linked developer docs and specifications -only when needed; do not substitute lightweight WorkQueueOps backlog guidance -for the Git-backed protocol. - When a user interacts with you: 1. **Identify the task type** from the user's request @@ -210,7 +196,7 @@ gh aw init # Generate the lock file for a workflow gh aw compile [workflow-name] -# Only where permitted and human-validated under debug-agentic-workflow.md: +# Trigger a workflow on demand (preferred over gh workflow run) gh aw run # interactive input collection gh aw run --ref main # run on a specific branch @@ -243,5 +229,5 @@ gh aw compile --validate - Follow security best practices: minimal permissions, explicit network access, no template injection - **Network configuration**: Use ecosystem identifiers (`node`, `python`, `go`, etc.) or explicit FQDNs in `network.allowed`. Bare shorthands like `npm` or `pypi` are **not** valid. See `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/network.md` for the full list of valid ecosystem identifiers and domain patterns. - **Single-file output**: When creating a workflow, produce exactly **one** workflow `.md` file. Do not create separate documentation files (architecture docs, runbooks, usage guides, etc.). If documentation is needed, add a brief `## Usage` section inside the workflow file itself. -- **Triggering runs**: Only where permitted and human-validated under `debug-agentic-workflow.md`, prefer `gh aw run ` over `gh workflow run .lock.yml` for workflow resolution, input validation and run-tracking. Use the reviewed remote ref; explicit no-dispatch rules override user requests. +- **Triggering runs**: Always use `gh aw run ` to trigger a workflow on demand — not `gh workflow run .lock.yml`. `gh aw run` handles workflow resolution by short name, input parsing and validation, and correct run-tracking for agentic workflows. Use `--ref ` to run on a specific branch. - **CLI commands reference**: For a complete guide on all `gh aw` commands and their MCP tool equivalents (for restricted environments), see `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/cli-commands.md` diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index 4b988e9dc..4bb203545 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -5,10 +5,10 @@ "version": "v9.0.0", "sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3" }, - "github/gh-aw-actions/setup@v0.92.0": { + "github/gh-aw-actions/setup@v0.89.21": { "repo": "github/gh-aw-actions/setup", - "version": "v0.92.0", - "sha": "458b269006dcf88e3b5496b6fbecabe4b9a0f954" + "version": "v0.89.21", + "sha": "924af5fdc64061cfbf66fb584c8b07e2ac230c60" } }, "containers": { diff --git a/.github/skills/agentic-workflows/SKILL.md b/.github/skills/agentic-workflows/SKILL.md index 328ca1dae..4c983cc5a 100644 --- a/.github/skills/agentic-workflows/SKILL.md +++ b/.github/skills/agentic-workflows/SKILL.md @@ -1,6 +1,6 @@ --- name: agentic-workflows -description: Route gh-aw design, creation, diagnosis, patching, active debugging, and upgrade requests to the right strategies. +description: Route gh-aw workflow design/create/debug/upgrade requests to the right prompts. --- # Agentic Workflows Router @@ -19,7 +19,6 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/agent-runtime-instructions.md` - `.github/aw/agentic-chat.md` - `.github/aw/agentic-workflows-mcp.md` -- `.github/aw/analyzing-runs.md` - `.github/aw/asciicharts.md` - `.github/aw/campaign.md` - `.github/aw/charts-trending.md` @@ -32,8 +31,6 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/create-agentic-workflow.md` - `.github/aw/create-shared-agentic-workflow.md` - `.github/aw/debug-agentic-workflow.md` -- `.github/aw/debug-model-engine-misconfiguration.md` -- `.github/aw/debug-security-review.md` - `.github/aw/dependabot.md` - `.github/aw/deployment-status.md` - `.github/aw/designer-mappings.md` @@ -49,7 +46,6 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/instructions.md` - `.github/aw/intent.md` - `.github/aw/jobs.md` -- `.github/aw/ledger.md` - `.github/aw/linter-workflows.md` - `.github/aw/llms.md` - `.github/aw/loop.md` @@ -91,7 +87,6 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/update-agentic-workflow.md` - `.github/aw/upgrade-agentic-workflows.md` - `.github/aw/visual-regression.md` -- `.github/aw/work-queue.md` - `.github/aw/workflow-constraints.md` - `.github/aw/workflow-editing.md` - `.github/aw/workflow-patterns.md` @@ -101,8 +96,7 @@ After loading the matching workflow prompt or skill, follow it directly: - Create new workflows: `.github/aw/create-agentic-workflow.md` - Configure or add declarative engines: `.github/aw/configure-agentic-engine.md` - Update existing workflows: `.github/aw/update-agentic-workflow.md` -- Diagnose, patch, audit, or actively debug workflows: `.github/aw/debug-agentic-workflow.md` (local-first strategy, evidence triage and live gates) -- AWF model/endpoint 400s, silent cross-family sub-agent failures, `model: auto` failures, install-step 404s after a version pin, or questions about version fields: go directly to [Model and engine misconfiguration](../../aw/debug-agentic-workflow.md#model-and-engine-misconfiguration) before suggesting model changes. +- Debug, audit, or investigate workflows: `.github/aw/debug-agentic-workflow.md` - Upgrade workflows and fix deprecations: `.github/aw/upgrade-agentic-workflows.md` - Create shared components or MCP wrappers: `.github/aw/create-shared-agentic-workflow.md` - Create report-generating workflows: `.github/aw/report.md` @@ -111,11 +105,8 @@ After loading the matching workflow prompt or skill, follow it directly: - Render compact markdown charts: `.github/aw/asciicharts.md` - Map CLI commands to MCP usage: `.github/aw/cli-commands.md` - Choose workflow architecture and patterns: `.github/aw/patterns.md` -- Design, deploy, inspect or recover a Git-backed work queue: `.github/aw/work-queue.md` - Optimize token usage and cost: `.github/aw/token-optimization.md` - Design long-running multi-agent research workflows: `.github/aw/multi-agent-research.md` - Add skills or agent plugins requested by the user (`skills:` / `plugins:` frontmatter, never on-the-fly installs): `.github/aw/skills.md` When the task involves OTEL, OTLP, traces, observability backends, or telemetry-driven analysis, also read and follow `skills/otel-queries/SKILL.md` after loading the matching workflow prompt or skill. - -When creating, updating, diagnosing or upgrading a workflow that uses `tools.work-queue`, also load `.github/aw/work-queue.md` after the primary prompt. Load deployment docs, operator reference or specification only when that task needs them. diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index dcd816ab1..2f100bac7 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -31,6 +31,6 @@ jobs: with: persist-credentials: false - name: Install gh-aw extension - uses: github/gh-aw-actions/setup-cli@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 + uses: github/gh-aw-actions/setup-cli@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 with: version: v0.89.15 diff --git a/.github/workflows/pr-ai-slop-review.lock.yml b/.github/workflows/pr-ai-slop-review.lock.yml index 3c8b20384..f6ea859e3 100644 --- a/.github/workflows/pr-ai-slop-review.lock.yml +++ b/.github/workflows/pr-ai-slop-review.lock.yml @@ -1,6 +1,6 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"a74d6cb119bde6904af2788245fd44d6229de228ba92dc5bafa7e86705bed626","body_hash":"e7b165b458a07108c2e6bfe6f4ed61f5659ce81512691dda091165d5966ee732","compiler_version":"v0.92.0","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.96"}} -# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_DEFAULT_OTLP_ENDPOINT","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"9000827ccba6bdab643e8b6fd33ac0654aef8333","version":"v8.0.2"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"949feb2413d6458794dcd2491c4babbbce0c15c1","version":"v7.1.0"},{"repo":"actions/upload-artifact","sha":"cf430e030ddbb5b0abf93d22962f4752f3646cd9","version":"v7.0.2"},{"repo":"github/gh-aw-actions/setup","sha":"458b269006dcf88e3b5496b6fbecabe4b9a0f954","version":"v0.92.0"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.28.57","digest":"sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.28.57@sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57","digest":"sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57@sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.28.57","digest":"sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.28.57@sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.31","digest":"sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.31@sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e","pinned_image":"ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e"},{"image":"ghcr.io/github/github-mcp-server:v2.0.2","digest":"sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796","pinned_image":"ghcr.io/github/github-mcp-server:v2.0.2@sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796"}],"has_pull_request":true,"mcp_servers":[{"name":"github","tools":["get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","issue_read","list_issue_types","list_issues","list_pull_requests","pull_request_read","search_issues","search_pull_requests"]},{"name":"safeoutputs","tools":["add_comment","add_labels","missing_data","missing_tool","noop","remove_labels","report_incomplete"]}],"threat_detection":{"mode":"enabled"}} -# This file was automatically generated by gh-aw (v0.92.0). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"8296ef86aad04ad225d29c7fe51dd18dfa50f258c46e8bd24e443193cc6f80fc","body_hash":"e7b165b458a07108c2e6bfe6f4ed61f5659ce81512691dda091165d5966ee732","compiler_version":"v0.89.21","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.87"}} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_DEFAULT_OTLP_ENDPOINT","GH_AW_DEFAULT_OTLP_HEADERS","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"924af5fdc64061cfbf66fb584c8b07e2ac230c60","version":"v0.89.21"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.28.23","digest":"sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.28.23@sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23","digest":"sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23@sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.28.23","digest":"sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.28.23@sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.25","digest":"sha256:9be0a86220e807a0ecc89e53d7453468f7a53fbc6b3d1efd2299025ffe01d086","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.25@sha256:9be0a86220e807a0ecc89e53d7453468f7a53fbc6b3d1efd2299025ffe01d086"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e","pinned_image":"ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e"},{"image":"ghcr.io/github/github-mcp-server:v1.12.2","digest":"sha256:508a0857ec762b1ab1cece29193345b501fab1dd9d1228a7b617062954cecac6","pinned_image":"ghcr.io/github/github-mcp-server:v1.12.2@sha256:508a0857ec762b1ab1cece29193345b501fab1dd9d1228a7b617062954cecac6"}],"has_pull_request_target":true,"mcp_servers":[{"name":"github","tools":["get_pull_request","get_pull_request_comments","get_pull_request_diff","get_pull_request_files","get_pull_request_review_comments","get_pull_request_reviews","get_pull_request_status","issue_read","list_issue_types","list_issues","list_pull_requests","pull_request_read","search_issues","search_pull_requests"]},{"name":"safeoutputs","tools":["add_comment","add_labels","missing_data","missing_tool","noop","remove_labels"]}]} +# This file was automatically generated by gh-aw (v0.89.21). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # # ___ _ _ # / _ \ | | (_) @@ -37,23 +37,24 @@ # # Custom actions used: # - actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 -# - actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 +# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 -# - actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 -# - actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 -# - github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) +# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 +# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# - github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 # # Container images used: -# - ghcr.io/github/gh-aw-firewall/agent:0.28.57@sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a -# - ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57@sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc -# - ghcr.io/github/gh-aw-firewall/squid:0.28.57@sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac -# - ghcr.io/github/gh-aw-mcpg:v0.4.31@sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf +# - ghcr.io/github/gh-aw-firewall/agent:0.28.23@sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2 +# - ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23@sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64 +# - ghcr.io/github/gh-aw-firewall/squid:0.28.23@sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0 +# - ghcr.io/github/gh-aw-mcpg:v0.4.25@sha256:9be0a86220e807a0ecc89e53d7453468f7a53fbc6b3d1efd2299025ffe01d086 # - ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e -# - ghcr.io/github/github-mcp-server:v2.0.2@sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796 +# - ghcr.io/github/github-mcp-server:v1.12.2@sha256:508a0857ec762b1ab1cece29193345b501fab1dd9d1228a7b617062954cecac6 name: "PR AI Slop Review" on: - pull_request: + pull_request_target: types: - opened - synchronize @@ -69,11 +70,10 @@ on: inputs: aw_context: default: "" - description: "Agent caller context (Reserved for Agentic Workflows)." + description: "Agent caller context (used internally by Agentic Workflows)." required: false type: string -# Jobs receive only their explicitly declared permissions. permissions: {} concurrency: @@ -92,14 +92,9 @@ env: jobs: activation: - name: activation needs: pre_activation - if: > - needs.pre_activation.outputs.activated == 'true' && ((github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id) && - ((github.event_name != 'pull_request' && github.event_name != 'pull_request_review') || github.event.pull_request.stack == null || - github.event.pull_request.stack.position == github.event.pull_request.stack.size)) + if: needs.pre_activation.outputs.activated == 'true' runs-on: ubuntu-slim - # Permissions for the activation job (workflow permissions default to none). permissions: actions: read contents: read @@ -107,11 +102,9 @@ jobs: GH_AW_MAX_DAILY_AI_CREDITS: "5000" GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} outputs: - aw_context: ${{ steps.generate_aw_info.outputs.aw_context }} body: ${{ steps.sanitized.outputs.body }} comment_id: "" comment_repo: "" - daily_ai_credits_estimated: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_estimated || '' }} daily_ai_credits_exceeded: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_exceeded == 'true' }} daily_ai_credits_guardrail_error: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_error || '' }} daily_ai_credits_guardrail_status: ${{ steps.daily-ai-credits-workflow-guardrail.outputs.daily_ai_credits_guardrail_status || '' }} @@ -131,7 +124,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 + uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -141,10 +134,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.96" - GH_AW_INFO_AWF_VERSION: "v0.28.57" + GH_AW_INFO_VERSION: "1.0.87" + GH_AW_INFO_AWF_VERSION: "v0.28.23" GH_AW_INFO_ENGINE_ID: "copilot" - GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Generate agentic run info @@ -153,16 +145,16 @@ jobs: GH_AW_INFO_ENGINE_ID: "copilot" GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }} - GH_AW_INFO_VERSION: "1.0.96" - GH_AW_INFO_AGENT_VERSION: "1.0.96" - GH_AW_INFO_CLI_VERSION: "v0.92.0" + GH_AW_INFO_VERSION: "1.0.87" + GH_AW_INFO_AGENT_VERSION: "1.0.87" + GH_AW_INFO_CLI_VERSION: "v0.89.21" GH_AW_INFO_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" GH_AW_INFO_STAGED: "false" GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]' GH_AW_INFO_FIREWALL_ENABLED: "true" - GH_AW_INFO_AWF_VERSION: "v0.28.57" + GH_AW_INFO_AWF_VERSION: "v0.28.23" GH_AW_INFO_AWMG_VERSION: "" GH_AW_INFO_FIREWALL_TYPE: "squid" GH_AW_INFO_AGENT_RUNTIME: "" @@ -218,13 +210,13 @@ jobs: - name: Publish daily AIC scan observations if: always() && env.GH_AW_MAX_DAILY_AI_CREDITS != '' continue-on-error: true - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: aic-usage-scan-v2 path: /tmp/gh-aw/agentic-workflow-usage-scan-v2.jsonl overwrite: true if-no-files-found: ignore - retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '3' }} + retention-days: 3 - name: Validate COPILOT_GITHUB_TOKEN secret id: validate-secret run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh" COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default @@ -241,7 +233,6 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_review' || github.event_name == 'pull_request_review_comment') && github.event.pull_request != null && github.event.pull_request.base.sha || github.sha }} sparse-checkout: | .github .agents @@ -274,7 +265,7 @@ jobs: - name: Check compile-agentic version uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_COMPILED_VERSION: "v0.92.0" + GH_AW_COMPILED_VERSION: "v0.89.21" GH_AW_BLOCKED_VERSION_REPORT_AS_ISSUE: "false" GH_AW_WORKFLOW_NAME: "PR AI Slop Review" with: @@ -307,19 +298,19 @@ jobs: GH_AW_ACTIONS_DIR: ${{ runner.temp }}/gh-aw/actions GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl - GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"safe_outputs_mcp_transport_prompt.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}],\"system_item_count\":12}" - GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} - GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }} - GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} - GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_PROMPT_CONFIG: "{\"items\":[{\"content_env\":\"GH_AW_PROMPT_CONTENT_0000\"},{\"file\":\"xpia.md\"},{\"file\":\"temp_folder_prompt.md\"},{\"file\":\"markdown.md\"},{\"file\":\"safe_outputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0001\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0002\"},{\"file\":\"mcp_cli_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0003\"},{\"file\":\"github_mcp_tools_with_safeoutputs_prompt.md\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0004\"},{\"content_env\":\"GH_AW_PROMPT_CONTENT_0005\"}]}" + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} GH_AW_PROMPT_CONTENT_0000: "\n" - GH_AW_PROMPT_CONTENT_0001: "\nTools: add_comment, add_labels, remove_labels(max:2), missing_tool, missing_data, noop(max:2)\n" + GH_AW_PROMPT_CONTENT_0001: "\nTools: add_comment, add_labels, remove_labels(max:2), missing_tool, missing_data, noop\n" GH_AW_PROMPT_CONTENT_0002: "\n" - GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_7C248226__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_C19C384F__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_76DF9333__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_77C1A4D2__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n" + GH_AW_PROMPT_CONTENT_0003: "\nThe following GitHub context information is available for this workflow:\n{{#if github.actor}}\n- **actor**: __GH_AW_GITHUB_ACTOR__\n{{/if}}\n{{#if github.repository}}\n- **repository**: __GH_AW_GITHUB_REPOSITORY__\n{{/if}}\n{{#if github.workspace}}\n- **workspace**: __GH_AW_GITHUB_WORKSPACE__\n{{/if}}\n{{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}\n- **issue-number**: #__GH_AW_EXPR_802A9F6A__\n{{/if}}\n{{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}\n- **discussion-number**: #__GH_AW_EXPR_1A3A194A__\n{{/if}}\n{{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}\n- **pull-request-number**: #__GH_AW_EXPR_463A214A__\n{{/if}}\n{{#if github.event.comment.id || github.aw.context.comment_id}}\n- **comment-id**: __GH_AW_EXPR_FF1D34CE__\n{{/if}}\n{{#if github.run_id}}\n- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__\n{{/if}}\n\n\n" GH_AW_PROMPT_CONTENT_0004: "\n" GH_AW_PROMPT_CONTENT_0005: "{{#runtime-import .github/workflows/pr-ai-slop-review.md}}\n" with: @@ -333,10 +324,6 @@ jobs: env: GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt GH_AW_ENGINE_ID: "copilot" - GH_AW_SUB_AGENT_DIR: ".github/agents" - GH_AW_SUB_AGENT_EXT: ".agent.md" - GH_AW_SKILL_DIR: ".github/skills" - GH_AW_SKILL_EXT: "/SKILL.md" with: script: | const path = require('path'); @@ -349,10 +336,10 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt - GH_AW_EXPR_76DF9333: ${{ github.event.pull_request.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'pull_request' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} - GH_AW_EXPR_77C1A4D2: ${{ github.event.comment.id || fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').comment_id }} - GH_AW_EXPR_7C248226: ${{ github.event.issue.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'issue' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} - GH_AW_EXPR_C19C384F: ${{ github.event.discussion.number || (fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_type == 'discussion' && fromJSON(steps.generate_aw_info.outputs.aw_context || '{}').item_number) }} + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} GH_AW_GITHUB_ACTOR: ${{ github.actor }} GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} @@ -372,10 +359,10 @@ jobs: return await substitutePlaceholders({ file: process.env.GH_AW_PROMPT, substitutions: { - GH_AW_EXPR_76DF9333: process.env.GH_AW_EXPR_76DF9333, - GH_AW_EXPR_77C1A4D2: process.env.GH_AW_EXPR_77C1A4D2, - GH_AW_EXPR_7C248226: process.env.GH_AW_EXPR_7C248226, - GH_AW_EXPR_C19C384F: process.env.GH_AW_EXPR_C19C384F, + GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, + GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, + GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A, + GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE, GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, @@ -394,34 +381,20 @@ jobs: GH_AW_PROMPT: ${{ runner.temp }}/gh-aw/aw-prompts/prompt.txt run: | bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" - - name: Inventory installed skills - if: success() || failure() - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - env: - GH_AW_SKILL_DIR: ".github/skills" - with: - script: | - const path = require('path'); - const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); - const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require(path.join(actionsDir, 'skill_inventory.cjs')); - await main(); - name: Upload info artifact if: success() || failure() - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: info path: /tmp/gh-aw/aw_info.json if-no-files-found: ignore - retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} - name: Stage prompt files for artifact upload run: | mkdir -p /tmp/gh-aw/aw-prompts cp -a "${RUNNER_TEMP}/gh-aw/aw-prompts/." /tmp/gh-aw/aw-prompts/ - name: Upload activation artifact if: success() || failure() - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: activation include-hidden-files: true @@ -429,26 +402,20 @@ jobs: /tmp/gh-aw/aw_info.json /tmp/gh-aw/models.json /tmp/gh-aw/aw-prompts/prompt.txt - /tmp/gh-aw/aw-prompts/system.txt - /tmp/gh-aw/aw-prompts/user.txt /tmp/gh-aw/aw-prompts/prompt-template.txt /tmp/gh-aw/aw-prompts/prompt-import-tree.json /tmp/gh-aw/github_rate_limits.jsonl /tmp/gh-aw/base /tmp/gh-aw/.github/agents /tmp/gh-aw/.github/skills - /tmp/gh-aw/skill_inventory.json if-no-files-found: ignore - retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '1' }} + retention-days: 1 agent: - name: agent needs: activation if: needs.activation.outputs.daily_ai_credits_exceeded != 'true' runs-on: ubuntu-latest - # Permissions for the agent job (workflow permissions default to none). permissions: - copilot-requests: none issues: read pull-requests: read timeout-minutes: 60 @@ -465,7 +432,6 @@ jobs: GH_AW_PR_HEAD_BASE_SHA: "" GH_AW_PR_HEAD_REPO: "" GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} - GH_AW_TARGET_REPO_SLUG: "" GH_AW_WORKFLOW_ID_SANITIZED: praislopreview outputs: agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} @@ -481,7 +447,6 @@ jobs: missing_model_pricing_error: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_error || 'false' }} missing_model_pricing_model_name: ${{ steps.detect-agent-errors.outputs.missing_model_pricing_model_name || '' }} model: ${{ needs.activation.outputs.model }} - model_endpoint_mismatch_error: ${{ steps.detect-agent-errors.outputs.model_endpoint_mismatch_error || 'false' }} model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }} output: ${{ steps.collect_output.outputs.output }} output_types: ${{ steps.collect_output.outputs.output_types }} @@ -493,7 +458,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 + uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -502,10 +467,9 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.96" - GH_AW_INFO_AWF_VERSION: "v0.28.57" + GH_AW_INFO_VERSION: "1.0.87" + GH_AW_INFO_AWF_VERSION: "v0.28.23" GH_AW_INFO_ENGINE_ID: "copilot" - GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Set runtime paths id: set-runtime-paths env: @@ -536,7 +500,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} - name: Download activation artifact - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: activation path: /tmp/gh-aw @@ -544,12 +508,12 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" env: GH_HOST: github.com - GH_AW_COMPILED_VERSION: v0.92.0 + GH_AW_COMPILED_VERSION: v0.89.21 - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.57 --rootless + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.23 --rootless - name: Determine automatic lockdown mode for GitHub MCP Server id: determine-automatic-lockdown - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) env: GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} @@ -580,7 +544,7 @@ jobs: run: "node <<'NODE'\nconst fs = require('fs');\nconst harnessPath = `${process.env.RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs`;\nconst harness = fs.readFileSync(harnessPath, 'utf8');\nconst quotaBranch = [\n ' if (isQuotaExceeded) {',\n ' log(`attempt ${attempt + 1}: Copilot quota exceeded — not retrying`);',\n ' return { action: \"stop\" };',\n ' }',\n].join('\\n');\nconst nonBlockingQuotaBranch = [\n ' let quotaErrorMsg = null;',\n ' if (isQuotaExceeded) {',\n ' log(`attempt ${attempt + 1}: Copilot quota exceeded — not retrying`);',\n ' quotaErrorMsg = { action: \"stop\" };',\n ' }',\n ' if (/\\\\b429\\\\b|Too Many Requests/i.test(result.output)) {',\n ' log(`attempt ${attempt + 1}: Copilot quota unavailable — exiting 0`);',\n ' quotaErrorMsg = { action: \"stop\", exitCode: 0 };',\n ' }',\n ' if (quotaErrorMsg) {',\n ' return quotaErrorMsg;',\n ' }',\n].join('\\n');\n\nif (harness.split(quotaBranch).length !== 2) {\n throw new Error('Unexpected Copilot quota branch; re-audit the gh-aw upgrade');\n}\nfs.writeFileSync(harnessPath, harness.replace(quotaBranch, nonBlockingQuotaBranch));\nNODE" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.57@sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57@sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc ghcr.io/github/gh-aw-firewall/squid:0.28.57@sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac ghcr.io/github/gh-aw-mcpg:v0.4.31@sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e ghcr.io/github/github-mcp-server:v2.0.2@sha256:ffced0d76e77428532a2ced185516992d77fd146d69eec2f244e6237d1a97796 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.23@sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2 ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23@sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64 ghcr.io/github/gh-aw-firewall/squid:0.28.23@sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0 ghcr.io/github/gh-aw-mcpg:v0.4.25@sha256:9be0a86220e807a0ecc89e53d7453468f7a53fbc6b3d1efd2299025ffe01d086 ghcr.io/github/gh-aw-node@sha256:bac2192f6374d6262116399b34fc5e143d576f82719e90a18261cae7480f4d4e ghcr.io/github/github-mcp-server:v1.12.2@sha256:508a0857ec762b1ab1cece29193345b501fab1dd9d1228a7b617062954cecac6 - name: Prepare Safe Outputs Directories run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" @@ -591,7 +555,7 @@ jobs: env: GH_AW_FILE_ROOT: "${{ runner.temp }}/gh-aw" GH_AW_FILE_CONFIG: "{\"files\":[{\"path\":\"safeoutputs/config.json\",\"content_env\":\"GH_AW_SAFE_OUTPUTS_CONFIG\"}]}" - GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1},\"add_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":1},\"create_report_incomplete_issue\":{},\"mentions\":{\"enabled\":false},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"remove_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":2},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1},\"add_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":1},\"create_report_incomplete_issue\":{},\"mentions\":{\"enabled\":false},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"remove_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":2},\"report_incomplete\":{}}" with: script: | const path = require('path'); @@ -606,7 +570,7 @@ jobs: { "description_suffixes": { "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading.", - "add_labels": " CONSTRAINTS: Maximum 1 add_labels call(s) allowed. Maximum 10 label(s) per call. Only these labels are allowed: [\"ai-slop:high\" \"ai-slop:med\"].", + "add_labels": " CONSTRAINTS: Maximum 1 label(s) can be added. Only these labels are allowed: [\"ai-slop:high\" \"ai-slop:med\"].", "remove_labels": " CONSTRAINTS: Maximum 2 label(s) can be removed. Only these labels can be removed: [ai-slop:high ai-slop:med]." }, "repo_params": {}, @@ -721,7 +685,7 @@ jobs: } }, "noop": { - "defaultMax": 2, + "defaultMax": 1, "fields": { "message": { "required": true, @@ -776,9 +740,6 @@ jobs: - name: Start MCP Gateway id: start-mcp-gateway env: - GH_AW_GUARD_APPROVAL_LABELS: ${{ steps.parse-guard-vars.outputs.approval_labels }} - GH_AW_GUARD_BLOCKED_USERS: ${{ steps.parse-guard-vars.outputs.blocked_users }} - GH_AW_GUARD_TRUSTED_USERS: ${{ steps.parse-guard-vars.outputs.trusted_users }} GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST: ${{ vars.GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST || 'true' }} GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_CONFIG_PATH }} @@ -812,23 +773,22 @@ jobs: export GH_AW_PR_HEAD_BASE_PR_NUMBER="${GH_AW_PR_HEAD_BASE_PR_NUMBER:-}" export GH_AW_PR_HEAD_BASE_REF="${GH_AW_PR_HEAD_BASE_REF:-}" export GH_AW_PR_HEAD_REPO="${GH_AW_PR_HEAD_REPO:-}" - export GH_AW_TARGET_REPO_SLUG="${GH_AW_TARGET_REPO_SLUG:-}" export DEBUG="*" export GH_AW_ENGINE="copilot" MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') source "${RUNNER_TEMP}/gh-aw/actions/resolve_docker_socket_gid.sh" - export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_AGENT_ID -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_TARGET_REPO_SLUG -e GH_AW_PR_HEAD_BASE_BRANCH -e GH_AW_PR_HEAD_BASE_SHA -e GH_AW_PR_HEAD_BASE_REPO -e GH_AW_PR_HEAD_BASE_PR_NUMBER -e GH_AW_PR_HEAD_BASE_REF -e GH_AW_PR_HEAD_REPO -e GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GH_AW_SINK_VISIBILITY -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e RUNNER_TEMP -e RUNNER_TOOL_CACHE -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -e GH_AW_GUARD_APPROVAL_LABELS -e GH_AW_GUARD_BLOCKED_USERS -e GH_AW_GUARD_TRUSTED_USERS -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.4.31@sha256:dbec0f2ddef6adf83b7764019323096e3e5cc0f3886255f6320555b7fe2a7caf' + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network bridge -p 127.0.0.1:'"${MCP_GATEWAY_PORT}"':'"${MCP_GATEWAY_PORT}"' --name awmg-mcpg --add-host host.docker.internal:host-gateway --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_AGENT_ID -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_PR_HEAD_BASE_BRANCH -e GH_AW_PR_HEAD_BASE_SHA -e GH_AW_PR_HEAD_BASE_REPO -e GH_AW_PR_HEAD_BASE_PR_NUMBER -e GH_AW_PR_HEAD_BASE_REF -e GH_AW_PR_HEAD_REPO -e GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GH_AW_SINK_VISIBILITY -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e RUNNER_TEMP -e RUNNER_TOOL_CACHE -e MCP_GATEWAY_ALLOWED_MOUNT_ROOTS -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -e OTEL_EXPORTER_OTLP_HEADERS -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw -v '"${RUNNER_TEMP}"'/gh-aw/safeoutputs:'"${RUNNER_TEMP}"'/gh-aw/safeoutputs:rw ghcr.io/github/gh-aw-mcpg:v0.4.25' mkdir -p "$HOME/.copilot" GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_293a804dd05fb938_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_7ff34e101789c0b6_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { "type": "stdio", - "container": "ghcr.io/github/github-mcp-server:v2.0.2", + "container": "ghcr.io/github/github-mcp-server:v1.12.2", "env": { "GITHUB_FEATURES": "fields_param", "GITHUB_HOST": "${GITHUB_SERVER_URL}", @@ -838,11 +798,11 @@ jobs: }, "guard-policies": { "allow-only": { - "approval-labels": ${GH_AW_GUARD_APPROVAL_LABELS}, - "blocked-users": ${GH_AW_GUARD_BLOCKED_USERS}, + "approval-labels": ${{ steps.parse-guard-vars.outputs.approval_labels }}, + "blocked-users": ${{ steps.parse-guard-vars.outputs.blocked_users }}, "min-integrity": "unapproved", "repos": "all", - "trusted-users": ${GH_AW_GUARD_TRUSTED_USERS} + "trusted-users": ${{ steps.parse-guard-vars.outputs.trusted_users }} } } }, @@ -863,7 +823,6 @@ jobs: "GH_AW_SAFE_OUTPUTS": "\${GH_AW_SAFE_OUTPUTS}", "GH_AW_SAFE_OUTPUTS_CONFIG_PATH": "\${GH_AW_SAFE_OUTPUTS_CONFIG_PATH}", "GH_AW_SAFE_OUTPUTS_TOOLS_PATH": "\${GH_AW_SAFE_OUTPUTS_TOOLS_PATH}", - "GH_AW_TARGET_REPO_SLUG": "\${GH_AW_TARGET_REPO_SLUG}", "GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST": "\${GH_AW_POLICY_ALLOW_CREATE_PULL_REQUEST}", "GH_AW_PR_HEAD_BASE_BRANCH": "\${GH_AW_PR_HEAD_BASE_BRANCH}", "GH_AW_PR_HEAD_BASE_SHA": "\${GH_AW_PR_HEAD_BASE_SHA}", @@ -902,7 +861,7 @@ jobs: } } } - GH_AW_MCP_CONFIG_293a804dd05fb938_EOF + GH_AW_MCP_CONFIG_7ff34e101789c0b6_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true @@ -920,25 +879,12 @@ jobs: const { main } = require(path.join(actionsDir, 'mount_mcp_as_cli.cjs')); await main(); - name: Clean credentials - run: | - bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" - bash "${RUNNER_TEMP}/gh-aw/actions/verify_git_credentials.sh" + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" - name: Audit pre-agent workspace id: pre_agent_audit continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" - - name: Log GitHub rate limits at agent start - continue-on-error: true - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - with: - github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const path = require('path'); - const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); - const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); - setupGlobals(core, github, context, exec, io, getOctokit); - const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs')); - await fetchAndLogRateLimit(github, 'agent_start', true); - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): @@ -946,10 +892,9 @@ jobs: run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt - gh_aw_exit_code=0 trap 'gh_aw_exit_code=$?; mkdir -p /tmp/gh-aw >/dev/null 2>&1 || true; printf "%s" "$gh_aw_exit_code" > /tmp/gh-aw/agent_execution_exit_code.txt || true; rm -f "$HOME/.copilot/settings.json"; if [ "$gh_aw_exit_code" -ne 0 ]; then echo "::error::Agent execution exited with code $gh_aw_exit_code"; fi' EXIT mkdir -p "$HOME/.copilot" - printf '%s' '{"builtInAgents":{"rubberDuck":false},"enabledFeatureFlags":{"EXTENSIONS":false}}' > "$HOME/.copilot/settings.json" + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json" export XDG_CONFIG_HOME="$HOME" export GH_AW_MCP_CONFIG="$HOME/.copilot/mcp-config.json" GH_AW_COPILOT_SRC="$(command -v copilot 2>/dev/null || true)" @@ -970,7 +915,7 @@ jobs: export COPILOT_API_KEY="$COPILOT_DUMMY_BYOK" (umask 177 && touch /tmp/gh-aw/agent-stdio.log) # shellcheck disable=SC2016 - printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.28.57/awf-config.schema.json","network":{"allowDomains":["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","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","s.symcb.com","s.symcd.com","security.ubuntu.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"],"isolation":true,"topologyAttach":["awmg-mcpg"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":12,"maxCacheMisses":5,"maxAiCredits":60,"models":{"agent":["sonnet-6x","gpt-6","gpt-5.4","gpt-5.5","gpt-5.6","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"auto":["copilot/auto","large"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex","kimi"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"detection":["small"],"evals":["small"],"fable":["copilot/*fable*","anthropic/*fable*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-3.6-flash":["copilot/gemini-3.6*flash*","google/gemini-3.6*flash*","gemini/gemini-3.6*flash*"],"gemini-3.7-flash":["copilot/gemini-3.7*flash*","google/gemini-3.7*flash*","gemini/gemini-3.7*flash*"],"gemini-3.8-flash":["copilot/gemini-3.8*flash*","google/gemini-3.8*flash*","gemini/gemini-3.8*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-omni":["copilot/gemini-omni*","google/gemini-omni*","gemini/gemini-omni*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.1":["copilot/gpt-5.1*","openai/gpt-5.1*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"gpt-5.6":["copilot/gpt-5.6*","openai/gpt-5.6*"],"gpt-6":["copilot/gpt-6*","openai/gpt-6*"],"grok":["copilot/*grok*","openai/*grok*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"image-generation":["copilot/gpt-image*","openai/gpt-image*","openai/chatgpt-image*","copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","google/imagen*"],"kimi":["copilot/kimi*","openai/kimi*"],"kiwi":["copilot/kiwi*","openai/kiwi*"],"large":["sonnet","gpt-6","gpt-5-pro","gpt-5","gemini-pro"],"lyria":["google/lyria*","gemini/lyria*","copilot/lyria*"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mai-code-1-flash-picker":["copilot/MAI-Code-1-Flash-picker*","copilot/mai-code-1-flash-picker*","openai/MAI-Code-1-Flash-picker*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"raptor-mini":["copilot/raptor*","openai/raptor*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-5*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*","anthropic/*sonnet-5*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"veo":["google/veo*","gemini/veo*"],"vision":["copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.28.57,squid=sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac,agent=sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a,api-proxy=sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc,cli-proxy=sha256:4584f030659ee51958223a3c6156e8119c6a94affbfcd92ce75f204702c52641"},"logging":{"proxyLogsDir":"/tmp/gh-aw/sandbox/firewall/logs","auditDir":"/tmp/gh-aw/sandbox/firewall/audit"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' '{"$schema":"https://github.com/github/gh-aw-firewall/releases/download/v0.28.23/awf-config.schema.json","network":{"allowDomains":["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","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","s.symcb.com","s.symcd.com","security.ubuntu.com","ts-crl.ws.symantec.com","ts-ocsp.ws.symantec.com","www.googleapis.com"],"isolation":true,"topologyAttach":["awmg-mcpg"]},"apiProxy":{"enabled":true,"enableTokenSteering":true,"maxRuns":12,"maxCacheMisses":5,"maxAiCredits":60,"models":{"agent":["sonnet-6x","gpt-6","gpt-5.4","gpt-5.5","gpt-5.6","gpt-5.3","gemini-pro","any"],"antigravity":["copilot/antigravity*","google/antigravity*","gemini/antigravity*"],"any":["copilot/*","anthropic/*","openai/*","google/*","gemini/*"],"auto":["copilot/auto","large"],"claude":["agent"],"codex":["agent"],"coding":["copilot/gpt-5*codex*","openai/gpt-5*codex*","gpt-5-codex","kimi"],"computer-use":["copilot/*computer-use*","google/*computer-use*","gemini/*computer-use*","openai/*computer-use*"],"copilot":["agent"],"deep-research":["copilot/deep-research*","copilot/o3-deep-research*","copilot/o4-mini-deep-research*","google/deep-research*","gemini/deep-research*","openai/o3-deep-research*","openai/o4-mini-deep-research*"],"detection":["small"],"evals":["small"],"fable":["copilot/*fable*","anthropic/*fable*"],"gemini":["agent"],"gemini-3-flash":["copilot/gemini-3*flash*","google/gemini-3*flash*","gemini/gemini-3*flash*"],"gemini-3-pro":["copilot/gemini-3*pro*","google/gemini-3*pro*","google/nano-banana*","gemini/gemini-3*pro*"],"gemini-3.1-flash":["copilot/gemini-3.1*flash*","google/gemini-3.1*flash*","gemini/gemini-3.1*flash*"],"gemini-3.1-pro":["copilot/gemini-3.1*pro*","google/gemini-3.1*pro*","gemini/gemini-3.1*pro*"],"gemini-3.5-flash":["copilot/gemini-3.5*flash*","google/gemini-3.5*flash*","gemini/gemini-3.5*flash*"],"gemini-3.6-flash":["copilot/gemini-3.6*flash*","google/gemini-3.6*flash*","gemini/gemini-3.6*flash*"],"gemini-3.7-flash":["copilot/gemini-3.7*flash*","google/gemini-3.7*flash*","gemini/gemini-3.7*flash*"],"gemini-3.8-flash":["copilot/gemini-3.8*flash*","google/gemini-3.8*flash*","gemini/gemini-3.8*flash*"],"gemini-flash":["copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"],"gemini-flash-lite":["copilot/gemini-*flash*lite*","google/gemini-*flash*lite*","gemini/gemini-*flash*lite*"],"gemini-omni":["copilot/gemini-omni*","google/gemini-omni*","gemini/gemini-omni*"],"gemini-pro":["copilot/gemini-*pro*","google/gemini-*pro*","gemini/gemini-*pro*"],"gemma":["copilot/gemma*","google/gemma*","gemini/gemma*"],"gpt-5":["copilot/gpt-5*","openai/gpt-5*"],"gpt-5-codex":["copilot/gpt-5*codex*","openai/gpt-5*codex*"],"gpt-5-mini":["copilot/gpt-5*mini*","openai/gpt-5*mini*"],"gpt-5-nano":["copilot/gpt-5*nano*","openai/gpt-5*nano*"],"gpt-5-pro":["copilot/gpt-5*pro*","openai/gpt-5*pro*"],"gpt-5.1":["copilot/gpt-5.1*","openai/gpt-5.1*"],"gpt-5.2":["copilot/gpt-5.2*","openai/gpt-5.2*"],"gpt-5.3":["copilot/gpt-5.3*","openai/gpt-5.3*"],"gpt-5.4":["copilot/gpt-5.4*","openai/gpt-5.4*"],"gpt-5.5":["copilot/gpt-5.5*","openai/gpt-5.5*"],"gpt-5.6":["copilot/gpt-5.6*","openai/gpt-5.6*"],"gpt-6":["copilot/gpt-6*","openai/gpt-6*"],"grok":["copilot/*grok*","openai/*grok*"],"haiku":["copilot/*haiku*","anthropic/*haiku*"],"image-generation":["copilot/gpt-image*","openai/gpt-image*","openai/chatgpt-image*","copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","google/imagen*"],"kimi":["copilot/kimi*","openai/kimi*"],"kiwi":["copilot/kiwi*","openai/kiwi*"],"large":["sonnet","gpt-6","gpt-5-pro","gpt-5","gemini-pro"],"lyria":["google/lyria*","gemini/lyria*","copilot/lyria*"],"mai-code":["copilot/MAI-Code*","copilot/mai-code*","openai/MAI-Code*"],"mai-code-1-flash-picker":["copilot/MAI-Code-1-Flash-picker*","copilot/mai-code-1-flash-picker*","openai/MAI-Code-1-Flash-picker*"],"mini":["haiku","gpt-5-mini","gpt-5-nano","gemini-flash-lite"],"nano-banana":["copilot/nano-banana*","google/nano-banana*","gemini/nano-banana*"],"opus":["copilot/*opus*","anthropic/*opus*"],"opusplan":["opus?effort=high"],"raptor-mini":["copilot/raptor*","openai/raptor*"],"reasoning":["copilot/o1*","copilot/o3*","copilot/o4*","openai/o1*","openai/o3*","openai/o4*"],"robotics":["copilot/*robotics*","google/*robotics*","gemini/*robotics*"],"small":["mini"],"small-agent":["haiku","gpt-5-mini","gemini-flash"],"sonnet":["copilot/*sonnet*","anthropic/*sonnet*"],"sonnet-6x":["copilot/*sonnet-4.5*","copilot/*sonnet-4.6*","copilot/*sonnet-5*","copilot/*sonnet-4-5-*","anthropic/*sonnet-4-5-*","copilot/*sonnet-4-6*","anthropic/*sonnet-4-6*","anthropic/*sonnet-5*"],"summarization":["haiku","gpt-5-mini","gemini-flash-lite","mini"],"veo":["google/veo*","gemini/veo*"],"vision":["copilot/gemini-*image*","google/gemini-*image*","gemini/gemini-*image*","copilot/gemini-*flash*","google/gemini-*flash*","gemini/gemini-*flash*"]}},"container":{"imageTag":"0.28.23,squid=sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0,agent=sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2,api-proxy=sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64,cli-proxy=sha256:9e31a6e518eba44652b9ae94ce55c3b6958e06290c3b81b08de4174751bb439a"},"logging":{"proxyLogsDir":"/tmp/gh-aw/sandbox/firewall/logs","auditDir":"/tmp/gh-aw/sandbox/firewall/audit"}}' > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST="" @@ -999,26 +944,24 @@ jobs: GH_AW_AWF_LOG_FILE=/tmp/gh-aw/agent-stdio.log \ GH_AW_AWF_ATTEMPT_LOG_NAME=copilot \ bash "${RUNNER_TEMP}/gh-aw/actions/run_awf_with_startup_retries.sh" -- \ - awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_ENGINE_STEP_TIMEOUT_MINUTES:+--agent-timeout "$GH_AW_ENGINE_STEP_TIMEOUT_MINUTES"} ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --deny-tool workflow --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' + awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_AGENT_ID --mount /tmp/gh-aw:/tmp/gh-aw:rw --log-level info --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" "${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs" "${RUNNER_TEMP}/gh-aw/bin/copilot" --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-all-tools --allow-all-paths --add-dir "${GITHUB_WORKSPACE}" --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt' env: AWF_REFLECT_ENABLED: 1 COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_DUMMY_BYOK: dummy-byok-key-for-offline-mode COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'auto' }} - GH_AW_ENGINE_STEP_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }} GH_AW_LLM_PROVIDER: github GH_AW_MAX_TURNS: 12 GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_TIMEOUT_MINUTES: ${{ fromJSON(vars.GH_AW_DEFAULT_TIMEOUT_MINUTES || '20') }} - GH_AW_VERSION: v0.92.0 + GH_AW_VERSION: v0.89.21 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows - GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS: false GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_REF_NAME: ${{ github.ref_name }} @@ -1031,19 +974,6 @@ jobs: GIT_COMMITTER_NAME: github-actions[bot] RUNNER_TEMP: ${{ runner.temp }} TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} - - name: Log GitHub rate limits at agent end - if: always() - continue-on-error: true - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - with: - github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - script: | - const path = require('path'); - const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); - const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); - setupGlobals(core, github, context, exec, io, getOctokit); - const { fetchAndLogRateLimit } = require(path.join(actionsDir, 'github_rate_limit_logger.cjs')); - await fetchAndLogRateLimit(github, 'agent_end', true); - name: Detect agent errors if: always() id: detect-agent-errors @@ -1197,49 +1127,35 @@ jobs: - name: Upload agent output fallback artifact if: always() continue-on-error: true - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: agent-output-fallback path: | /tmp/gh-aw/agent_output.json /tmp/gh-aw/safeoutputs.jsonl /tmp/gh-aw/agent_execution.json - /tmp/gh-aw/agent_execution_exit_code.txt /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/agent_usage.json - /tmp/gh-aw/agent/model-endpoint-mismatch.json /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl - /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/model-routing.jsonl /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl - /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/model-routing.jsonl /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl - /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/model-routing.jsonl if-no-files-found: ignore - retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} - name: Upload agent artifacts if: always() continue-on-error: true - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: agent path: | /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/agent_execution.json - /tmp/gh-aw/agent_execution_exit_code.txt - /tmp/gh-aw/agent-session.jsonl - /tmp/gh-aw/agent-errors.jsonl - /tmp/gh-aw/aw-prompts/user.txt - /tmp/gh-aw/aw-prompts/system.txt - /tmp/gh-aw/skill_inventory.json /tmp/gh-aw/sandbox/agent/logs/ /tmp/gh-aw/redacted-urls.log /tmp/gh-aw/mcp-logs/ /tmp/gh-aw/proxy-logs/ !/tmp/gh-aw/proxy-logs/proxy-tls/ /tmp/gh-aw/agent_usage.json - /tmp/gh-aw/runtime/aw_info.json /tmp/gh-aw/agent_usage.jsonl - /tmp/gh-aw/agent/model-endpoint-mismatch.json /tmp/gh-aw/agent-stdio.log /tmp/gh-aw/pre-agent-audit.txt /tmp/gh-aw/github_rate_limits.jsonl @@ -1254,10 +1170,8 @@ jobs: /tmp/gh-aw/sandbox/firewall/audit/ /tmp/gh-aw/sandbox/firewall/awf-reflect.json if-no-files-found: ignore - retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} conclusion: - name: conclusion needs: - activation - agent @@ -1269,7 +1183,6 @@ jobs: needs.activation.outputs.secret_verification_result == 'failed' || needs.activation.outputs.daily_ai_credits_exceeded == 'true' || needs.activation.outputs.daily_ai_credits_guardrail_status == 'structural_error' || needs.activation.outputs.daily_ai_credits_guardrail_status == 'transient_error') runs-on: ubuntu-slim - # Permissions for the conclusion job (workflow permissions default to none). permissions: actions: read issues: write @@ -1282,14 +1195,13 @@ jobs: GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} outputs: incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} - noop_comment_body: ${{ steps.noop.outputs.noop_comment_body }} noop_message: ${{ steps.noop.outputs.noop_message }} tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} total_count: ${{ steps.missing_tool.outputs.total_count }} steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 + uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1298,14 +1210,13 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.96" - GH_AW_INFO_AWF_VERSION: "v0.28.57" + GH_AW_INFO_VERSION: "1.0.87" + GH_AW_INFO_AWF_VERSION: "v0.28.23" GH_AW_INFO_ENGINE_ID: "copilot" - GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Download agent output artifact id: download-agent-output continue-on-error: true - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: "{agent,agent-output-fallback}" merge-multiple: true @@ -1319,17 +1230,10 @@ jobs: if [ -f "/tmp/gh-aw/agent_output.json" ]; then echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" fi - - name: Restore runtime model metadata - if: always() - run: | - if [ -f /tmp/gh-aw/runtime/aw_info.json ]; then cp /tmp/gh-aw/runtime/aw_info.json /tmp/gh-aw/aw_info.json; fi - - name: Warn if threat detection produced no verdict - if: always() && needs.detection.result != 'skipped' && (needs.detection.outputs.detection_reason == 'agent_failure' || needs.detection.outputs.detection_reason == 'parse_error' || needs.detection.outputs.detection_conclusion == '') - run: echo "::warning::Threat detection produced no security verdict. Review the detection job logs before trusting the agent outputs." - name: Download detection artifact id: download-detection-artifact continue-on-error: true - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: detection path: /tmp/gh-aw/threat-detection/ @@ -1337,21 +1241,77 @@ jobs: id: download-safe-outputs-manifest if: always() continue-on-error: true - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: safe-outputs-items merge-multiple: true path: /tmp/gh-aw/ + - name: Collect usage artifact files + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/collect_usage_artifact_files.sh" + - name: Upload usage artifact + id: upload-usage-artifact + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw_info.json + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.json + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/evals.jsonl + /tmp/gh-aw/usage/graders/grader_manifest.json + /tmp/gh-aw/usage/graders/grader_results.json + /tmp/gh-aw/usage/github_rate_limits.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/agent/execution.json + /tmp/gh-aw/usage/detection/token_usage.jsonl + /tmp/gh-aw/usage/detection/execution.json + /tmp/gh-aw/usage/evals/token_usage.jsonl + /tmp/gh-aw/usage/evals/execution.json + /tmp/gh-aw/usage/activity/summary.json + if-no-files-found: ignore + - name: Wait before retrying usage artifact upload + if: always() && steps.upload-usage-artifact.outcome == 'failure' + run: sleep 10 + - name: Retry upload usage artifact + id: upload-usage-artifact-retry + if: always() && steps.upload-usage-artifact.outcome == 'failure' + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw_info.json + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.json + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/evals.jsonl + /tmp/gh-aw/usage/graders/grader_manifest.json + /tmp/gh-aw/usage/graders/grader_results.json + /tmp/gh-aw/usage/github_rate_limits.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/agent/execution.json + /tmp/gh-aw/usage/detection/token_usage.jsonl + /tmp/gh-aw/usage/detection/execution.json + /tmp/gh-aw/usage/evals/token_usage.jsonl + /tmp/gh-aw/usage/evals/execution.json + /tmp/gh-aw/usage/activity/summary.json + if-no-files-found: ignore + overwrite: true - name: Process no-op messages id: noop uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} - GH_AW_NOOP_MAX: "2" + GH_AW_NOOP_MAX: "1" GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/pr-ai-slop-review.md" - GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} GH_AW_NOOP_REPORT_AS_ISSUE: "false" @@ -1395,8 +1355,6 @@ jobs: GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/pr-ai-slop-review.md" - GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1414,8 +1372,6 @@ jobs: GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/pr-ai-slop-review.md" - GH_AW_ENGINE_ID: "copilot" - GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | @@ -1444,14 +1400,11 @@ jobs: GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }} GH_AW_AIC: ${{ needs.agent.outputs.aic }} GH_AW_THREAT_DETECTION_AIC: ${{ needs.detection.outputs.aic }} - GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }} GH_AW_MAX_AI_CREDITS: "60" - GH_AW_DEFAULT_CHECKOUT_USES_TRIGGER_REF: "false" GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} - GH_AW_MODEL_ENDPOINT_MISMATCH_ERROR: ${{ needs.agent.outputs.model_endpoint_mismatch_error }} GH_AW_HTTP_400_RESPONSE_ERROR: ${{ needs.agent.outputs.http_400_response_error }} GH_AW_MAX_CACHE_MISSES_EXCEEDED: ${{ needs.agent.outputs.max_cache_misses_exceeded }} GH_AW_MISSING_MODEL_PRICING_ERROR: ${{ needs.agent.outputs.missing_model_pricing_error }} @@ -1465,7 +1418,6 @@ jobs: GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }} GH_AW_DAILY_AI_CREDITS_GUARDRAIL_ERROR: ${{ needs.activation.outputs.daily_ai_credits_guardrail_error }} GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }} - GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }} GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }} GH_AW_DAILY_AI_CREDITS_CONTINUE_ON_ERROR: "false" GH_AW_GROUP_REPORTS: "false" @@ -1491,8 +1443,6 @@ jobs: GH_AW_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/pr-ai-slop-review.md" GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - GH_AW_JOB_RESULTS: ${{ toJSON(needs) }} - GH_AW_JOB_DISPLAY_NAMES: "{\"activation\":\"Activation\",\"agent\":\"Agent\",\"check_token_telemetry\":\"Check token telemetry\",\"conclusion\":\"Conclusion\",\"detection\":\"Detection\",\"evals\":\"Evaluations\",\"pre_activation\":\"Pre-activation\",\"push_evals_state\":\"Push evaluations state\",\"push_experiments_state\":\"Push experiments state\",\"push_ledger_changes\":\"Push ledger changes\",\"push_repo_memory\":\"Push repository memory\",\"safe_outputs\":\"Safe outputs\",\"send_slack_message\":\"Send Slack message\",\"unlock\":\"Unlock\",\"update_cache_memory\":\"Update cache memory\",\"update_drive_memory\":\"Update drive memory\",\"upload_assets\":\"Upload assets\",\"upload_code_coverage\":\"Upload code coverage\",\"upload_code_scanning_sarif\":\"Upload code scanning results\"}" GH_AW_REPORT_FAILED_JOBS: "true" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} @@ -1503,109 +1453,13 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require(path.join(actionsDir, 'report_failed_jobs.cjs')); await main(); - - name: Collect usage artifact files - if: always() - continue-on-error: true - env: - GH_AW_DETECTION_JOB_RESULT: ${{ needs.detection.result }} - GH_AW_DETECTION_CONCLUSION: ${{ needs.detection.outputs.detection_conclusion }} - GH_AW_DETECTION_REASON: ${{ needs.detection.outputs.detection_reason }} - run: bash "${RUNNER_TEMP}/gh-aw/actions/collect_usage_artifact_files.sh" - - name: Generate usage activity summary and unified session - if: always() - continue-on-error: true - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - env: - GH_AW_DAILY_AI_CREDITS_GUARDRAIL_STATUS: ${{ needs.activation.outputs.daily_ai_credits_guardrail_status }} - GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }} - GH_AW_DAILY_AI_CREDITS_TOTAL: ${{ needs.activation.outputs.daily_ai_credits_total }} - GH_AW_DAILY_AI_CREDITS_ESTIMATED: ${{ needs.activation.outputs.daily_ai_credits_estimated }} - GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }} - with: - script: | - const path = require('path'); - const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); - const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require(path.join(actionsDir, 'generate_usage_artifacts.cjs')); - await main(); - - name: Upload usage artifact - id: upload-usage-artifact - if: always() - continue-on-error: true - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 - with: - name: usage - path: | - /tmp/gh-aw/usage/aw_session.jsonl - /tmp/gh-aw/usage/aw_info.json - /tmp/gh-aw/usage/aw-info.jsonl - /tmp/gh-aw/usage/agent_usage.json - /tmp/gh-aw/usage/agent_usage.jsonl - /tmp/gh-aw/usage/detection_usage.jsonl - /tmp/gh-aw/usage/evals.jsonl - /tmp/gh-aw/usage/graders/grader_manifest.json - /tmp/gh-aw/usage/graders/grader_results.json - /tmp/gh-aw/usage/github_rate_limits.jsonl - /tmp/gh-aw/usage/agent/token_usage.jsonl - /tmp/gh-aw/usage/agent/model-routing.jsonl - /tmp/gh-aw/usage/agent/execution.json - /tmp/gh-aw/usage/detection/token_usage.jsonl - /tmp/gh-aw/usage/detection/execution.json - /tmp/gh-aw/usage/detection/detection_result.json - /tmp/gh-aw/usage/evals/token_usage.jsonl - /tmp/gh-aw/usage/evals/execution.json - /tmp/gh-aw/usage/experiment/state.jsonl - /tmp/gh-aw/usage/experiment/state.json - /tmp/gh-aw/usage/experiment/assignments.json - /tmp/gh-aw/usage/activity/summary.json - if-no-files-found: ignore - retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} - - name: Wait before retrying usage artifact upload - if: always() && steps.upload-usage-artifact.outcome == 'failure' - run: sleep 10 - - name: Retry upload usage artifact - id: upload-usage-artifact-retry - if: always() && steps.upload-usage-artifact.outcome == 'failure' - continue-on-error: true - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 - with: - name: usage - path: | - /tmp/gh-aw/usage/aw_session.jsonl - /tmp/gh-aw/usage/aw_info.json - /tmp/gh-aw/usage/aw-info.jsonl - /tmp/gh-aw/usage/agent_usage.json - /tmp/gh-aw/usage/agent_usage.jsonl - /tmp/gh-aw/usage/detection_usage.jsonl - /tmp/gh-aw/usage/evals.jsonl - /tmp/gh-aw/usage/graders/grader_manifest.json - /tmp/gh-aw/usage/graders/grader_results.json - /tmp/gh-aw/usage/github_rate_limits.jsonl - /tmp/gh-aw/usage/agent/token_usage.jsonl - /tmp/gh-aw/usage/agent/model-routing.jsonl - /tmp/gh-aw/usage/agent/execution.json - /tmp/gh-aw/usage/detection/token_usage.jsonl - /tmp/gh-aw/usage/detection/execution.json - /tmp/gh-aw/usage/detection/detection_result.json - /tmp/gh-aw/usage/evals/token_usage.jsonl - /tmp/gh-aw/usage/evals/execution.json - /tmp/gh-aw/usage/experiment/state.jsonl - /tmp/gh-aw/usage/experiment/state.json - /tmp/gh-aw/usage/experiment/assignments.json - /tmp/gh-aw/usage/activity/summary.json - if-no-files-found: ignore - overwrite: true - retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} detection: - name: detection needs: - activation - agent if: always() && needs.agent.result != 'skipped' runs-on: ubuntu-latest - # Permissions for the detection job (workflow permissions default to none). permissions: contents: read timeout-minutes: 10 @@ -1619,7 +1473,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 + uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1628,20 +1482,19 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.96" - GH_AW_INFO_AWF_VERSION: "v0.28.57" + GH_AW_INFO_VERSION: "1.0.87" + GH_AW_INFO_AWF_VERSION: "v0.28.23" GH_AW_INFO_ENGINE_ID: "copilot" - GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Download activation artifact continue-on-error: true - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: activation path: /tmp/gh-aw - name: Download agent output artifact id: download-agent-output continue-on-error: true - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: "{agent,agent-output-fallback}" merge-multiple: true @@ -1674,7 +1527,7 @@ jobs: rm -rf /tmp/gh-aw/sandbox/firewall/logs rm -rf /tmp/gh-aw/sandbox/firewall/audit - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.57@sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a ghcr.io/github/gh-aw-firewall/api-proxy:0.28.57@sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc ghcr.io/github/gh-aw-firewall/squid:0.28.57@sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.28.23@sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2 ghcr.io/github/gh-aw-firewall/api-proxy:0.28.23@sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64 ghcr.io/github/gh-aw-firewall/squid:0.28.23@sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0 - name: Check if detection needed id: detection_guard if: always() @@ -1722,9 +1575,9 @@ jobs: mkdir -p /tmp/gh-aw/threat-detection touch /tmp/gh-aw/threat-detection/detection.log - name: Install AWF binary - run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.57 --rootless + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh" v0.28.23 --rootless - name: Setup Node.js - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: '24' package-manager-cache: false @@ -1732,7 +1585,7 @@ jobs: run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" env: GH_HOST: github.com - GH_AW_COMPILED_VERSION: v0.92.0 + GH_AW_COMPILED_VERSION: v0.89.21 - name: Install threat-detect binary id: threat_detect_install if: always() && steps.detection_guard.outputs.run_detection == 'true' @@ -1757,11 +1610,10 @@ jobs: GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_TIMEOUT_MINUTES: 10 - GH_AW_VERSION: v0.92.0 + GH_AW_VERSION: v0.89.21 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows - GITHUB_COPILOT_PROMPT_MODE_EXTENSIONS: false GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_REF_NAME: ${{ github.ref_name }} GITHUB_SERVER_URL: ${{ github.server_url }} @@ -1803,7 +1655,7 @@ jobs: if [[ ! "$GH_AW_MAX_AI_CREDITS" =~ ^[0-9]+$ ]]; then GH_AW_MAX_AI_CREDITS="400" fi - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.28.57/awf-config.schema.json\",\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.28.57,squid=sha256:be808c16b535ebabd070eebe086fe6bffd5bb86b2e5fe8e5cdad30068eb9c0ac,agent=sha256:a9861b2fad1d29c586bbbf98840a61056e30e2720d8d9ec2c0def9049566bd8a,api-proxy=sha256:f2925ff32dc972a5d8b90a7785b6ca68052efd2575fe896556ac457e22e86dcc,cli-proxy=sha256:4584f030659ee51958223a3c6156e8119c6a94affbfcd92ce75f204702c52641\",\"agentTimeout\":10},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.28.23/awf-config.schema.json\",\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-6\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-3.7-flash\":[\"copilot/gemini-3.7*flash*\",\"google/gemini-3.7*flash*\",\"gemini/gemini-3.7*flash*\"],\"gemini-3.8-flash\":[\"copilot/gemini-3.8*flash*\",\"google/gemini-3.8*flash*\",\"gemini/gemini-3.8*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"gpt-6\":[\"copilot/gpt-6*\",\"openai/gpt-6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-6\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.28.23,squid=sha256:02ffc56dd40158223064ef03a78c2d9717473c93723b4e403d455ea6f0b09ae0,agent=sha256:2c78aaba1c108e130e2d6d01e4f2cca334ea04c53e6f258913ac34173fe7e3b2,api-proxy=sha256:c15c3d1208df10c5b588a3657be53742aa982ae0909d1eb1812525268794ca64,cli-proxy=sha256:9e31a6e518eba44652b9ae94ce55c3b6958e06290c3b81b08de4174751bb439a\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST="" @@ -1822,8 +1674,8 @@ jobs: fi fi # shellcheck disable=SC1003,SC2016,SC2086 - awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_AW_OTLP_ALL_HEADERS --exclude-env GH_AW_OTLP_ENDPOINTS --exclude-env OTEL_EXPORTER_OTLP_ENDPOINT --exclude-env OTEL_EXPORTER_OTLP_HEADERS --mount /tmp/gh-aw:/tmp/gh-aw:rw --mount /tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw --log-level info --session-state-dir /tmp/gh-aw/sandbox/agent/session-state --skip-pull \ - -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr "\n" ":")"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && threat-detect --engine copilot --output /tmp/gh-aw/threat-detection/detection_result.json /tmp/gh-aw/threat-detection' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --mount /tmp/gh-aw:/tmp/gh-aw:rw --mount /tmp/gh-aw/threat-detection:/tmp/gh-aw/threat-detection:rw --log-level info --skip-pull \ + -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/bin:$PATH" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; GH_AW_TOOL_BINS="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')"; GH_AW_TOOL_BINS="${GH_AW_TOOL_BINS%:}"; export PATH="$PATH${GH_AW_TOOL_BINS:+:}$GH_AW_TOOL_BINS"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && threat-detect --engine copilot --output /tmp/gh-aw/threat-detection/detection_result.json /tmp/gh-aw/threat-detection' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log - name: Render detection log if: always() && steps.detection_guard.outputs.run_detection == 'true' continue-on-error: true @@ -1850,7 +1702,6 @@ jobs: uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: GH_AW_TOKEN_USAGE_SUMMARY_TITLE: Threat Detection Token Usage - GH_AW_PHASE: detection GH_AW_AGENT_USAGE_PATH: /tmp/gh-aw/threat-detection/detection_usage.json GH_AW_AGENT_USAGE_JSONL_PATH: /tmp/gh-aw/threat-detection/detection_usage.jsonl GH_AW_WRITE_EMPTY_USAGE: "true" @@ -1864,7 +1715,7 @@ jobs: await main(); - name: Upload threat detection artifact if: always() - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: detection path: | @@ -1875,7 +1726,6 @@ jobs: /tmp/gh-aw/threat-detection/sandbox/firewall/logs/ /tmp/gh-aw/threat-detection/sandbox/firewall/audit/ if-no-files-found: ignore - retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} - name: Conclude threat detection id: detection_conclusion if: always() @@ -1889,11 +1739,6 @@ jobs: bash "${RUNNER_TEMP}/gh-aw/actions/conclude_threat_detection.sh" /tmp/gh-aw/threat-detection/detection_result.json pre_activation: - name: pre_activation - if: > - (github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id) && - ((github.event_name != 'pull_request' && github.event_name != 'pull_request_review') || github.event.pull_request.stack == null || - github.event.pull_request.stack.position == github.event.pull_request.stack.size) runs-on: ubuntu-slim env: GH_AW_RUNTIME_FEATURES: ${{ vars.GH_AW_RUNTIME_FEATURES }} @@ -1906,17 +1751,16 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 + uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.96" - GH_AW_INFO_AWF_VERSION: "v0.28.57" + GH_AW_INFO_VERSION: "1.0.87" + GH_AW_INFO_AWF_VERSION: "v0.28.23" GH_AW_INFO_ENGINE_ID: "copilot" - GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Check skip-roles id: check_skip_roles uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -1948,14 +1792,12 @@ jobs: await main(); safe_outputs: - name: safe_outputs needs: - activation - agent - detection if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success' runs-on: ubuntu-slim - # Permissions for the safe_outputs job (workflow permissions default to none). permissions: issues: write pull-requests: write @@ -1994,7 +1836,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0 + uses: github/gh-aw-actions/setup@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -2003,16 +1845,15 @@ jobs: env: GH_AW_SETUP_WORKFLOW_NAME: "PR AI Slop Review" GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/pr-ai-slop-review.lock.yml@${{ github.ref }} - GH_AW_INFO_VERSION: "1.0.96" - GH_AW_INFO_AWF_VERSION: "v0.28.57" + GH_AW_INFO_VERSION: "1.0.87" + GH_AW_INFO_AWF_VERSION: "v0.28.23" GH_AW_INFO_ENGINE_ID: "copilot" - GH_AW_SETUP_AW_CONTEXT: ${{ inputs.aw_context }} - name: Mask OTLP telemetry headers run: bash "${RUNNER_TEMP}/gh-aw/actions/mask_otlp_headers.sh" - name: Download agent output artifact id: download-agent-output continue-on-error: true - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: "{agent,agent-output-fallback}" merge-multiple: true @@ -2039,27 +1880,24 @@ jobs: id: process_safe_outputs uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_JOB_CHECK_RUN_ID: ${{ job.check_run_id }} GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} - GH_AW_MENTIONS_GITHUB_TOKEN: ${{ github.token }} GH_AW_ALLOWED_DOMAINS: "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,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,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1},\"add_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":1},\"create_report_incomplete_issue\":{},\"mentions\":{\"enabled\":false},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":2,\"report-as-issue\":\"false\"},\"remove_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":2},\"report_incomplete\":{}}" - GH_AW_GITHUB_TOKEN_SOURCE: ${{ secrets.GH_AW_GITHUB_TOKEN != '' && 'pat' || 'github_actions' }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1},\"add_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":1},\"create_report_incomplete_issue\":{},\"mentions\":{\"enabled\":false},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"false\"},\"remove_labels\":{\"allowed\":[\"ai-slop:high\",\"ai-slop:med\"],\"max\":2},\"report_incomplete\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | const path = require('path'); const actionsDir = path.join(process.env.RUNNER_TEMP, 'gh-aw', 'actions'); const { setupGlobals } = require(path.join(actionsDir, 'setup_globals.cjs')); - setupGlobals(core, github, context, exec, io, getOctokit, process.env.GH_AW_GITHUB_TOKEN_SOURCE); + setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require(path.join(actionsDir, 'process_safe_outputs.cjs')); await main(); - name: Upload Safe Outputs Items if: always() - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: safe-outputs-items path: | @@ -2067,4 +1905,3 @@ jobs: /tmp/gh-aw/temporary-id-map.json /tmp/gh-aw/safe-output-errors.json if-no-files-found: ignore - retention-days: ${{ vars.GH_AW_DEFAULT_ARTIFACT_RETENTION_DAYS || '0' }} diff --git a/.github/workflows/pr-ai-slop-review.md b/.github/workflows/pr-ai-slop-review.md index dd392e6b9..63c8799c7 100644 --- a/.github/workflows/pr-ai-slop-review.md +++ b/.github/workflows/pr-ai-slop-review.md @@ -8,7 +8,7 @@ on: roles: all skip-roles: [admin, maintainer, write] skip-bots: [dependabot, renovate] - pull_request: + pull_request_target: # reopened is intentionally excluded: reopens carry no new implementation # evidence (the rerun-stability policy handles them), and a manual # workflow_dispatch remains available when a re-review is wanted. @@ -26,7 +26,6 @@ max-daily-ai-credits: 5000 permissions: issues: read pull-requests: read - copilot-requests: none pre-agent-steps: - name: Make Copilot quota exhaustion non-blocking From 396d343a3ad55305987ff833f81c859e35a20345 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 17 Oct 2026 13:40:23 +0000 Subject: [PATCH 16/25] chore(deps): update npm dependencies (#8335) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 10 +- pnpm-lock.yaml | 500 +++++++++++++++++++++++++------------------------ 2 files changed, 257 insertions(+), 253 deletions(-) diff --git a/package.json b/package.json index 37020b947..2146e126f 100644 --- a/package.json +++ b/package.json @@ -75,11 +75,11 @@ "monaco-yaml": "^5.5.1", "nanoid": "^6.0.1", "qrcode.react": "^4.2.0", - "react": "19.3.0", - "react-dom": "19.3.0", + "react": "19.3.1", + "react-dom": "19.3.1", "react-error-boundary": "6.1.6", "react-hook-form": "^7.88.0", - "react-i18next": "17.0.15", + "react-i18next": "17.0.19", "react-markdown": "10.1.0", "react-router": "^8.4.0", "rehype-raw": "^7.0.0", @@ -123,7 +123,7 @@ "https-proxy-agent": "^9.1.0", "husky": "^9.1.7", "jiti": "^2.7.0", - "knip": "6.39.0", + "knip": "6.41.0", "lint-staged": "^17.5.1", "sass": "^1.104.1", "tar": "^7.5.22", @@ -133,7 +133,7 @@ "vite": "^8.3.0", "vite-plugin-svgr": "^5.2.0", "vitest": "^5.0.1", - "webdriverio": "10.0.0", + "webdriverio": "10.0.2", "ws": "8.22.0" }, "lint-staged": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dc18da919..0a6847b9d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -177,28 +177,28 @@ importers: version: 0.5.0 '@dnd-kit/react': specifier: ^0.5.0 - version: 0.5.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + version: 0.5.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1) '@emotion/react': specifier: ^11.14.0 - version: 11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) + version: 11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) '@emotion/styled': specifier: ^11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) + version: 11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) '@juggle/resize-observer': specifier: ^3.4.0 version: 3.4.0 '@monaco-editor/react': specifier: ^4.7.0 - version: 4.7.0(monaco-editor@0.57.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + version: 4.7.0(monaco-editor@0.57.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) '@mui/icons-material': specifier: ^9.4.0 - version: 9.4.0(@mui/material@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(@types/react@19.3.0)(react@19.3.0) + version: 9.4.0(@mui/material@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@types/react@19.3.0)(react@19.3.1) '@mui/material': specifier: ^9.4.0 - version: 9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + version: 9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) '@tanstack/react-virtual': specifier: ^3.14.13 - version: 3.14.13(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + version: 3.14.13(react-dom@19.3.1(react@19.3.1))(react@19.3.1) '@tauri-apps/api': specifier: 2.12.1 version: 2.12.1 @@ -222,7 +222,7 @@ importers: version: 2.13.1 ahooks: specifier: ^3.10.0 - version: 3.10.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + version: 3.10.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1) cidr-block: specifier: ^2.3.0 version: 2.3.0 @@ -234,7 +234,7 @@ importers: version: 1.11.23 foxact: specifier: ^0.3.12 - version: 0.3.12(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + version: 0.3.12(react-dom@19.3.1(react@19.3.1))(react@19.3.1) foxts: specifier: ^5.9.1 version: 5.9.1 @@ -261,28 +261,28 @@ importers: version: 6.0.1 qrcode.react: specifier: ^4.2.0 - version: 4.2.0(react@19.3.0) + version: 4.2.0(react@19.3.1) react: - specifier: 19.3.0 - version: 19.3.0 + specifier: 19.3.1 + version: 19.3.1 react-dom: - specifier: 19.3.0 - version: 19.3.0(react@19.3.0) + specifier: 19.3.1 + version: 19.3.1(react@19.3.1) react-error-boundary: specifier: 6.1.6 - version: 6.1.6(@types/react@19.3.0)(react@19.3.0) + version: 6.1.6(@types/react@19.3.0)(react@19.3.1) react-hook-form: specifier: ^7.88.0 - version: 7.88.0(react@19.3.0) + version: 7.88.0(react@19.3.1) react-i18next: - specifier: 17.0.15 - version: 17.0.15(i18next@26.4.2(typescript@6.0.3))(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + specifier: 17.0.19 + version: 17.0.19(i18next@26.4.2(typescript@6.0.3))(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(typescript@6.0.3) react-markdown: specifier: 10.1.0 - version: 10.1.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) + version: 10.1.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) react-router: specifier: ^8.4.0 - version: 8.4.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + version: 8.4.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1) rehype-raw: specifier: ^7.0.0 version: 7.0.0 @@ -294,7 +294,7 @@ importers: version: 4.0.1(supports-color@7.2.0) swr: specifier: ^2.5.1 - version: 2.5.1(react@19.3.0) + version: 2.5.1(react@19.3.1) tauri-plugin-mihomo-api: specifier: github:clash-verge-rev/tauri-plugin-mihomo#main version: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/7a03d16f4d39b1bb885b7babe66b9e153e34b615 @@ -343,7 +343,7 @@ importers: version: 6.1.1(vite@8.3.0(@types/node@24.13.6)(esbuild@0.28.2)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1)) '@wdio/tauri-service': specifier: 1.4.0 - version: 1.4.0(expect-webdriverio@5.7.0)(supports-color@7.2.0)(webdriverio@10.0.0(supports-color@7.2.0)(yauzl@2.10.0)) + version: 1.4.0(expect-webdriverio@5.7.0)(supports-color@7.2.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) adm-zip: specifier: ^0.6.1 version: 0.6.1 @@ -402,8 +402,8 @@ importers: specifier: ^2.7.0 version: 2.7.0 knip: - specifier: 6.39.0 - version: 6.39.0 + specifier: 6.41.0 + version: 6.41.0 lint-staged: specifier: ^17.5.1 version: 17.5.1 @@ -432,8 +432,8 @@ importers: specifier: ^5.0.1 version: 5.0.1(@types/node@24.13.6)(vite@8.3.0(@types/node@24.13.6)(esbuild@0.28.2)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1)) webdriverio: - specifier: 10.0.0 - version: 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + specifier: 10.0.2 + version: 10.0.2(supports-color@7.2.0)(yauzl@2.10.0) ws: specifier: 8.22.0 version: 8.22.0 @@ -1599,124 +1599,124 @@ packages: '@octokit/types@18.0.0': resolution: {integrity: sha512-l6bAF43PNxkJp6g+W4PjoUSSkxHomXw2nOum5CTftJz1NlV3vu93NImgOYtLf6CbBUb5j+fiuzW0PPQ5JTSvZA==} - '@oxc-parser/binding-android-arm-eabi@0.150.0': - resolution: {integrity: sha512-oQef2Zu4Prz1KLKznz3HqZzU9uVoA5PMoDZuuLmqms7hKmKSAPzlaMnLllJq3t+rgKmfJJ2siPrpZfFrW06btw==} + '@oxc-parser/binding-android-arm-eabi@0.153.0': + resolution: {integrity: sha512-BcWu25dMwMjHpaDCEidmpAi7rGg1qZoihJeUUH9bD55pVZ0z4Wa5CQgqSTo0R41H81oozisQKW3WqvAN2m77IQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxc-parser/binding-android-arm64@0.150.0': - resolution: {integrity: sha512-B6ofpoFiAUwIZ0MJ2IgHPvZK8FAtL4qzSZRwOkAKIfxEobE1mQC8nDdiFZj7pUaJiVUVCsfkMsBJKedzO8rZvA==} + '@oxc-parser/binding-android-arm64@0.153.0': + resolution: {integrity: sha512-9l5rdp2DhRqVriBHsNpu5cEf+hizZ4B58rt93HzyQEBUgZiC6qe2oFpaAAnXGCxHGnQExI1s7S2G0QhFacUZ6w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxc-parser/binding-darwin-arm64@0.150.0': - resolution: {integrity: sha512-J+9IHKzx/bSz1JetOfD4zKXSK9sOm4/a7+0qomJODcTL6JsRXGeV/ZdkAPSIDydfFmWzYCraMlQEosSZEyBYkQ==} + '@oxc-parser/binding-darwin-arm64@0.153.0': + resolution: {integrity: sha512-EcpsyRXHhENDpekpG4QNaSZj2F/BAz4Gh4o89zZwNss86R8KyRSQ6sXbAj74Xyeb4z3j/yBZZ6joQZhraIWyfw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxc-parser/binding-darwin-x64@0.150.0': - resolution: {integrity: sha512-v6IPfcAcSYrBWXV5Tce1DmxDMXLhEYpIIWiRFPJopgCVscZdLaV4MRQOUxvL3usQlw+yrwYOjBFB9IwBx+jUiQ==} + '@oxc-parser/binding-darwin-x64@0.153.0': + resolution: {integrity: sha512-hlj80HUQy07/2lYp6rmxH+3u+H2ik3rjLR52CUdPApxmZCNxASDUf/+ykTzAHS/fehftmVMATKvPaWmuLHuasg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxc-parser/binding-freebsd-x64@0.150.0': - resolution: {integrity: sha512-AoR/4jD02HET0KO0yNT4nbTE+XJUxiO9jB1X/ycEjUE3WrIJ3IjV/Vf+gskhWLcqqeXfvNnkDtBR7epllAm88A==} + '@oxc-parser/binding-freebsd-x64@0.153.0': + resolution: {integrity: sha512-fWRcv2pMSh1qtez46MOu8vuUJ5fiaQZPHSphbWulbL7SHBMKfRgZl2PzjXZYQJbq7NEXyXbgIuIuUm+/Rmkv8w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxc-parser/binding-linux-arm-gnueabihf@0.150.0': - resolution: {integrity: sha512-A/hycCFjLUrCmLoL5O/vBp40ohlaXO1Ta3v5hqYZxicYFs129wZmgZJggcW4mYGYbZebQLhup+N8JjeQl8qwyw==} + '@oxc-parser/binding-linux-arm-gnueabihf@0.153.0': + resolution: {integrity: sha512-paZeUK1GXShl/bOJQET1/8AQxayFeuN4SIWAkgTRxE7ZQwv9uYSB2n0648smygP22N7jcI3zxAm0Z+ALNiIKxg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-musleabihf@0.150.0': - resolution: {integrity: sha512-pbqahg1Pkz7J4RKmXm30s/iQu99hv64ayXCu8P4p75HcEH5azOdR4eGqiB6lFGkFR3mMpzaYsSKLkS8oJbjmeQ==} + '@oxc-parser/binding-linux-arm-musleabihf@0.153.0': + resolution: {integrity: sha512-qFPp5NwMf4K1C0O+DCVGmcbOaYyYAq98Rvv9p4VSfb777iUwlJCqMUxf6QG9N5f5ls4TEX6LitOZHi+6GL6rYQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm64-gnu@0.150.0': - resolution: {integrity: sha512-HV11aRbBQGwqv8bEo+K/6qr88uB4fEe1mhXncMhlVCrj+WpBSraxrUzHaPVmeQRU6x6x8v/3DuCbbo93rpp+fw==} + '@oxc-parser/binding-linux-arm64-gnu@0.153.0': + resolution: {integrity: sha512-oufEhZCX7saeo27Logra8cvBR1jQ/yw2zUI2hHmWw3qA/XYqEW31FOvLQBv7DWN32NjVdlcaP11WBBZTJo4k9g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-arm64-musl@0.150.0': - resolution: {integrity: sha512-k6pVkJqALwtEuP4zukVhGRhdIy4+ofChUIUUsAHHyqDZlNsknmel3JjbggrJiWGaes6h/dIcWmEXsKW4SmK9oQ==} + '@oxc-parser/binding-linux-arm64-musl@0.153.0': + resolution: {integrity: sha512-zXYzuAqng85h6+LI3iRm0zeMLX1/K2z41ZAMWxVRgt0D10VvZUaV5q+TEB46KDhoKBpdexoTLC6QoB/EiP2oqQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-parser/binding-linux-ppc64-gnu@0.150.0': - resolution: {integrity: sha512-tEFg39mw/rHO5n8GK2DR4ZMFfsPQZtnQIPbsIpjoQRomJc/2tRfsCSmCT6gNit+NZGoeJG5aH9ATDH5bf0WnoQ==} + '@oxc-parser/binding-linux-ppc64-gnu@0.153.0': + resolution: {integrity: sha512-J7+NLwLEzdkKM9cKyPHH/AjXXstWOs98KYgLrPPnO4N9MO8EZRBfPNnBcS3S67uMOBkRpUmCl2FhRnWdQ5CbBA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-gnu@0.150.0': - resolution: {integrity: sha512-0JO7IFkoek6HqV589Menx3hJySNXi6quRhO4tq2P7kpEHKEXoDATnoPVUpn5B7gDH2KLkdo751N0uIrGJFCTCw==} + '@oxc-parser/binding-linux-riscv64-gnu@0.153.0': + resolution: {integrity: sha512-sD0K11GQTLWylln54nPMMTtgmBbQrR5It/vMpZpy/fogiw8O2AvIE+9LuWUXddrWk9zvFIHGRcSgFn4IHOfoYg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-musl@0.150.0': - resolution: {integrity: sha512-7XPzREnyAS5wHU9aB+49Uaqgoo1gVCklHc3DRlc3fJy2tXD/eAJFN1QFz/crj+Ulup5P1+axNREF+/RGaB/IRA==} + '@oxc-parser/binding-linux-riscv64-musl@0.153.0': + resolution: {integrity: sha512-7L66uql2BhvSz51LwfExjOdn6et/ydTiQxl23VApdKzJhTc3TczA1Qt6VR/UcvlQrL2ZbytIJb447vh7p5wmUw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-parser/binding-linux-s390x-gnu@0.150.0': - resolution: {integrity: sha512-7n7ZxcbRWDFaTdyj8M8p0O9OfzoMKm8O6syBAIgcSutbOALq0Bb9G52Me+XH0anMLZV+NgXc726gqgG2q39vcQ==} + '@oxc-parser/binding-linux-s390x-gnu@0.153.0': + resolution: {integrity: sha512-hXV3T7mNyrPR19rbPYkglkQJtoM/UNo/xwbZeeqdAxEg8PXgb4LXXuxPpGgI4bzRRCWwLUxdDSS58xIyC2u1TA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-gnu@0.150.0': - resolution: {integrity: sha512-Vx0GSA9ZCRTUiczoEQnIIyXkMvtEY8uc6IiwLQtMe5ci2sXPqjrry0Ek5fsPP1k2kCzkML3ow9UOOEgnEDi7Bw==} + '@oxc-parser/binding-linux-x64-gnu@0.153.0': + resolution: {integrity: sha512-Da8Vqs1xdtoDYtEjmozD7wGgJeLBQkMbR0WUBECOSxodyX5DXy8ySlvJWbukyO2Q0+TM9EK+4LT6tbq0jCg4hQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-musl@0.150.0': - resolution: {integrity: sha512-ii4/9m3viDLssMnfXU7/Pni/3nYplApuGayceX4qsVGaqqQJCx3tHIH9M/HWIeSty5i8LjS21zPYT6lVIkwLxw==} + '@oxc-parser/binding-linux-x64-musl@0.153.0': + resolution: {integrity: sha512-zGAPxNTIIw6X5WyTRscIFE/oDjpdNtrrl32ing6NOXdGjzRucadnxBilexLdeYQ9YxixF93GujpXyQ0jw7ddSg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxc-parser/binding-openharmony-arm64@0.150.0': - resolution: {integrity: sha512-ZtoxX5rez36ZWkwtiEhjkCPnlTPoQ2I7lIL0IYZ1yjxMYohbvoOjBmUIZzrf9W/HouONq0omIfTeCWEY+R380w==} + '@oxc-parser/binding-openharmony-arm64@0.153.0': + resolution: {integrity: sha512-GoHzpqP5XyPIp9DHokoEdCp+K4UPl/h1neFj1uXnUB3pJYyOQ7NOhFVOttNUgCGcj2eywAvu5cRivTOSq4S10g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxc-parser/binding-win32-arm64-msvc@0.150.0': - resolution: {integrity: sha512-VqeRb5JX/bKYBrff7TUDvJyKY0914UzuCkuXIGxJS4FUmvMNfqkCbc7Sq90iMz9DlmAtlggwaBYQ9eg3h3ltiw==} + '@oxc-parser/binding-win32-arm64-msvc@0.153.0': + resolution: {integrity: sha512-xGcy12tO9k7zFbeyQzEuilfWfQpyRq23/fLPfN3wjSWuWv58k46fQT1hsO1KFNykZuVGW9xSJE/z592TmAoSDA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxc-parser/binding-win32-ia32-msvc@0.150.0': - resolution: {integrity: sha512-EPqJfeZ4Pgg2BJSsCV8GozxV0FDltRzpVtGVa1r2noJu1iu+opOw3gtBWXwIo9odCT/MdFfyHxdy0/CRqs3OqA==} + '@oxc-parser/binding-win32-ia32-msvc@0.153.0': + resolution: {integrity: sha512-o1ykUjWncvXX6N5a4KebgLjtD8zRui+f1llMhSGoSC9oP2KOqapRpdwmZ3NcNG0axFouwVKmhGBjd+IhA8BksA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxc-parser/binding-win32-x64-msvc@0.150.0': - resolution: {integrity: sha512-n5YMzbqwPQqozbkrexi0lNZrUz5cnPHalYpFWe6Dau7AmKIWNo+y24IwzDuZEQtEdUHuKhXmMMih/MPjOI+CMw==} + '@oxc-parser/binding-win32-x64-msvc@0.153.0': + resolution: {integrity: sha512-gxQz7G96Up136fd+2zWrP+o6FYGs9NO4Dyv55IoeJFJUDwLFHcLYY11hhA5wQKs0HoM57Q8esQ3nEVhnCdsjAQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -1724,6 +1724,9 @@ packages: '@oxc-project/types@0.150.0': resolution: {integrity: sha512-rDS5/31E9HfPl/CIzGrn0DOlvBbXFseQ5URJ9sYMfstbKLD/c6Gm9vmRzRGDdAXyOIL4zmO37lc9RIwYqVruZw==} + '@oxc-project/types@0.153.0': + resolution: {integrity: sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==} + '@oxc-resolver/binding-android-arm-eabi@11.24.2': resolution: {integrity: sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==} cpu: [arm] @@ -2563,8 +2566,8 @@ packages: '@vscode/l10n@0.0.18': resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==} - '@wdio/config@10.0.0': - resolution: {integrity: sha512-g0xaQxKJM5hIhZBW05Ivs7vZi/txB+UcWeoiuzNl0/fS5rvQYvofnYlROvCBKeEdf72ooIRtfkRnW8nKQ97P+A==} + '@wdio/config@10.0.1': + resolution: {integrity: sha512-n6elHE4ItKAtr4lwAaWIh/sAFuEFhyesLM27i5l9IWBJEK6VECdt0Pigj/4vUD2tliOoBtsWxphSW4oiNFXotg==} engines: {node: '>=22.19.0'} '@wdio/globals@9.29.1': @@ -2603,8 +2606,8 @@ packages: tsx: optional: true - '@wdio/protocols@10.0.0': - resolution: {integrity: sha512-426ENC79fH7N4ggoGRHhZBY/exkdHAndbBiXcs9pQkzGP356H8C7VkQUx8g78m4k1TUC0RhOl8Se8VE0Mutpqw==} + '@wdio/protocols@10.0.2': + resolution: {integrity: sha512-ewuQuu+niq/ZpV1TLn904nDA4F9n4LLu9X1U8Juwwm1ahq09dpEP8lEytDnpaD0f21uIx//mFBKmBAjSexMdEA==} engines: {node: '>=22.19.0'} '@wdio/repl@10.0.0': @@ -2625,16 +2628,16 @@ packages: peerDependencies: webdriverio: ^9.0.0 - '@wdio/types@10.0.0': - resolution: {integrity: sha512-qUJbKEHjsN0PuC3S2r7Gy9wYtbChmX+PYghKGHYQhjyH9P9t+sWhSPQWUBk3S+IUTYT1f+Z4VbF+5FmvlHL6Lg==} + '@wdio/types@10.0.1': + resolution: {integrity: sha512-HGP9lAYXCsLAXzugfT4khCh7tYByWOMIxZHCG+tUvgmpwNzi6lfIsxyIlWownXK1wYJUpk6tkDBX/iXwN+q0lg==} engines: {node: '>=22.19.0'} '@wdio/types@9.30.1': resolution: {integrity: sha512-umKQDbSmu3/ucUsIA5UUTK5gCWnClyVpWz3fC39044rCXQ3zCd1a3GoJibbAITKiwnPFf2yU3LvTa+C78sh9Lg==} engines: {node: '>=18.20.0'} - '@wdio/utils@10.0.0': - resolution: {integrity: sha512-Ta3wq+u83DT0Vnz1QcuqkagBSwWBnTg8LCIQmDO6DGkMIiHXJrhUMfz6ibrlMJPslt4g0P/Ri5wm7WkJXo9HXw==} + '@wdio/utils@10.0.1': + resolution: {integrity: sha512-aYvTtF+7IYsvkFdXdu32Q2vexEaXYK79R1wLTnAXrT2Q7fp0oCDL0UgBx8Jgo5Tn98ZLWx4JlUeZsDRAIkV4Zw==} engines: {node: '>=22.19.0'} '@zip.js/zip.js@2.16.0': @@ -3505,9 +3508,9 @@ packages: resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} - formatly@0.7.1: - resolution: {integrity: sha512-ESuCEJE0SGgabl9q+zABI8LhJDmF+8nhpuqDzuM48HfJ9QTD5o6PqFJDFZY7w6f8xsh5lixuj5nJsQNvYOWvKQ==} - engines: {node: '>=18.3.0'} + formatly@0.11.4: + resolution: {integrity: sha512-TeCC10lP8KCgoX+Fe5lryILIT0/Dy+nP0OSVnsuB5CwXoLuOdqxCYlPFF1inR8S/zTy1ec7TjhS2TeRKWzzImA==} + engines: {node: '>=18.14.0'} hasBin: true foxact@0.3.12: @@ -3863,8 +3866,8 @@ packages: keyv@5.6.0: resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==} - knip@6.39.0: - resolution: {integrity: sha512-Y7g6Ve1ATMox1u1v+gx3z9LTlvzVLTJISm/LVn9TgBU4qc7OoC63AWGO8qCFPVDDdaqlYdXkDDvvO1METBfTRw==} + knip@6.41.0: + resolution: {integrity: sha512-DrhQlIuV6xScd5Q+WTF1znd1w41QzxFGCtAHXCajsH/ndGMotHoNYbdXbuFtzW3mIOmniHtZ7zCtvnQkUmJtQQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -4279,8 +4282,8 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - oxc-parser@0.150.0: - resolution: {integrity: sha512-zwajKw1GUa57IOdafIS7/yOObGF2NihwIfZfs5yJTRprMSkiwhWOc/k+n8bwnUPbHr2/XsjfBO8KyTPaW3VpWg==} + oxc-parser@0.153.0: + resolution: {integrity: sha512-cEnpyyV1OJRXv++SFNw0z8i+2o/cr88rVLaOYJafELDoHM5yHvCAbwGRLvxuany6SNLcbblSMUyZaGzH+quSYg==} engines: {node: ^20.19.0 || >=22.12.0} oxc-resolver@11.24.2: @@ -4432,10 +4435,10 @@ packages: query-selector-shadow-dom@1.0.1: resolution: {integrity: sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==} - react-dom@19.3.0: - resolution: {integrity: sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==} + react-dom@19.3.1: + resolution: {integrity: sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==} peerDependencies: - react: ^19.3.0 + react: ^19.3.1 react-error-boundary@6.1.6: resolution: {integrity: sha512-CDXPnXDGyFIbkwaaJ6u+xgsRmJhSi6YdgUDW1vnyKHfXp1a9pfAlM+ZET2CDu80/A+8iRcmXN0NSY9BCCoWP5A==} @@ -4455,8 +4458,8 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-i18next@17.0.15: - resolution: {integrity: sha512-7uYpx/oBkesLto7cOzOmfITlUBaXHCAcFahmgETMfWr8nbbWRRnVGvz8wsH/xpbNcyoH+NpCcnOQEqWPMO6/hw==} + react-i18next@17.0.19: + resolution: {integrity: sha512-BRHqiqOfW4J/LBVtbBFHoBoZm/Ez2/tkHPitYtn0CSpkYhEaEAsZMPsg7hZlomu30UJYQ6ZKiP3pwa3QnxGvQw==} peerDependencies: i18next: '>= 26.2.0' react: '>= 16.8.0' @@ -4502,8 +4505,8 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' - react@19.3.0: - resolution: {integrity: sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==} + react@19.3.1: + resolution: {integrity: sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==} engines: {node: '>=0.10.0'} readable-stream@2.3.8: @@ -4654,8 +4657,8 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - smol-toml@1.8.0: - resolution: {integrity: sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==} + smol-toml@1.9.1: + resolution: {integrity: sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ==} engines: {node: '>= 18'} snake-case@3.0.4: @@ -4877,8 +4880,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - unbash@4.0.11: - resolution: {integrity: sha512-FoSOKV7NEofQSkAefMVHam4ZPKYMxjAydxiV72UFEDNV/YofxjGfiZ2A9pZjdL/lRJzTjcu4PABo1JYJX8N5iQ==} + unbash@5.1.0: + resolution: {integrity: sha512-YVGyy4XqoZ2AVgHjVdL9cchMSurlXFHWviORa8RiU/Bnol4ooW5Lpyur/5XmbgDdyCKxymmgsEQsLGBMIJ/Agg==} engines: {node: '>=14'} undici-types@6.21.0: @@ -5096,12 +5099,12 @@ packages: web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - webdriver@10.0.0: - resolution: {integrity: sha512-EyMSQjY+Nq9mAUTCzzW1hjarwHNJWtCBRtGSZkiTcdJdFZ6siKF0Z01hHJFVkF1Xm+aCkFxD1atm1S2cNxCQxA==} + webdriver@10.0.2: + resolution: {integrity: sha512-q2eKiapaOyCH2QfVykBjrYznQiL4gjmGakTYVzQqq3Ycqpd2VPOMSkmbxGHFo8+CpO628QwvpxgKvAxA3hpDaA==} engines: {node: '>=22.19.0'} - webdriverio@10.0.0: - resolution: {integrity: sha512-DiDflg731z/b+qg4EmVAGihMJSWhHJYhlwrS6Q1uSFqL4c48+xHDj9VjhQr7sFzZ/MBJySjGZfMBGyjP7p547Q==} + webdriverio@10.0.2: + resolution: {integrity: sha512-o+T+DXwsn2e0niAmz9PWUMDwE/8R06euZ4O85faB6fGG9X/uVOom8sloIH+SYc1tI0fjcI34sU9hptrQj9fDdQ==} engines: {node: '>=22.19.0'} peerDependencies: puppeteer-core: '>=24 <26' @@ -5986,13 +5989,13 @@ snapshots: '@dnd-kit/abstract': 0.5.0 tslib: 2.8.1 - '@dnd-kit/react@0.5.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@dnd-kit/react@0.5.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': dependencies: '@dnd-kit/abstract': 0.5.0 '@dnd-kit/dom': 0.5.0 '@dnd-kit/state': 0.5.0 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) tslib: 2.8.1 '@dnd-kit/state@0.5.0': @@ -6064,17 +6067,17 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0)': + '@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0)': dependencies: '@babel/runtime': 7.29.7 '@emotion/babel-plugin': 11.13.5(supports-color@7.2.0) '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.3.0) + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.3.1) '@emotion/utils': 1.4.2 '@emotion/weak-memoize': 0.4.0 hoist-non-react-statics: 3.3.2 - react: 19.3.0 + react: 19.3.1 optionalDependencies: '@types/react': 19.3.0 transitivePeerDependencies: @@ -6090,16 +6093,16 @@ snapshots: '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0)': + '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0)': dependencies: '@babel/runtime': 7.29.7 '@emotion/babel-plugin': 11.13.5(supports-color@7.2.0) '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) + '@emotion/react': 11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.3.0) + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.3.1) '@emotion/utils': 1.4.2 - react: 19.3.0 + react: 19.3.1 optionalDependencies: '@types/react': 19.3.0 transitivePeerDependencies: @@ -6107,9 +6110,9 @@ snapshots: '@emotion/unitless@0.10.0': {} - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.3.0)': + '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.3.1)': dependencies: - react: 19.3.0 + react: 19.3.1 '@emotion/utils@1.4.2': {} @@ -6409,54 +6412,54 @@ snapshots: dependencies: state-local: 1.0.7 - '@monaco-editor/react@4.7.0(monaco-editor@0.57.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@monaco-editor/react@4.7.0(monaco-editor@0.57.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': dependencies: '@monaco-editor/loader': 1.7.0 monaco-editor: 0.57.0 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) '@mui/core-downloads-tracker@9.4.0': {} - '@mui/icons-material@9.4.0(@mui/material@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(@types/react@19.3.0)(react@19.3.0)': + '@mui/icons-material@9.4.0(@mui/material@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@types/react@19.3.0)(react@19.3.1)': dependencies: '@babel/runtime': 7.29.7 - '@mui/material': 9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) - react: 19.3.0 + '@mui/material': 9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: 19.3.1 optionalDependencies: '@types/react': 19.3.0 - '@mui/material@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@mui/material@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': dependencies: '@babel/runtime': 7.29.7 '@mui/core-downloads-tracker': 9.4.0 - '@mui/system': 9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0) + '@mui/system': 9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1) '@mui/types': 9.4.0(@types/react@19.3.0) - '@mui/utils': 9.4.0(@types/react@19.3.0)(react@19.3.0) + '@mui/utils': 9.4.0(@types/react@19.3.0)(react@19.3.1) '@popperjs/core': 2.11.8 '@types/react-transition-group': 4.4.12(@types/react@19.3.0) clsx: 2.1.1 csstype: 3.2.3 prop-types: 15.8.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) react-is: 19.3.0 - react-transition-group: 4.4.5(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react-transition-group: 4.4.5(react-dom@19.3.1(react@19.3.1))(react@19.3.1) optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) + '@emotion/react': 11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) '@types/react': 19.3.0 - '@mui/private-theming@9.4.0(@types/react@19.3.0)(react@19.3.0)': + '@mui/private-theming@9.4.0(@types/react@19.3.0)(react@19.3.1)': dependencies: '@babel/runtime': 7.29.7 - '@mui/utils': 9.4.0(@types/react@19.3.0)(react@19.3.0) + '@mui/utils': 9.4.0(@types/react@19.3.0)(react@19.3.1) prop-types: 15.8.1 - react: 19.3.0 + react: 19.3.1 optionalDependencies: '@types/react': 19.3.0 - '@mui/styled-engine@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(react@19.3.0)': + '@mui/styled-engine@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(react@19.3.1)': dependencies: '@babel/runtime': 7.29.7 '@emotion/cache': 11.14.0 @@ -6464,25 +6467,25 @@ snapshots: '@emotion/sheet': 1.4.0 csstype: 3.2.3 prop-types: 15.8.1 - react: 19.3.0 + react: 19.3.1 optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) + '@emotion/react': 11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) - '@mui/system@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)': + '@mui/system@9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)': dependencies: '@babel/runtime': 7.29.7 - '@mui/private-theming': 9.4.0(@types/react@19.3.0)(react@19.3.0) - '@mui/styled-engine': 9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(react@19.3.0) + '@mui/private-theming': 9.4.0(@types/react@19.3.0)(react@19.3.1) + '@mui/styled-engine': 9.4.0(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(react@19.3.1) '@mui/types': 9.4.0(@types/react@19.3.0) - '@mui/utils': 9.4.0(@types/react@19.3.0)(react@19.3.0) + '@mui/utils': 9.4.0(@types/react@19.3.0)(react@19.3.1) clsx: 2.1.1 csstype: 3.2.3 prop-types: 15.8.1 - react: 19.3.0 + react: 19.3.1 optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0) + '@emotion/react': 11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0))(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0) '@types/react': 19.3.0 '@mui/types@9.4.0(@types/react@19.3.0)': @@ -6491,14 +6494,14 @@ snapshots: optionalDependencies: '@types/react': 19.3.0 - '@mui/utils@9.4.0(@types/react@19.3.0)(react@19.3.0)': + '@mui/utils@9.4.0(@types/react@19.3.0)(react@19.3.1)': dependencies: '@babel/runtime': 7.29.7 '@mui/types': 9.4.0(@types/react@19.3.0) '@types/prop-types': 15.7.15 clsx: 2.1.1 prop-types: 15.8.1 - react: 19.3.0 + react: 19.3.1 react-is: 19.3.0 optionalDependencies: '@types/react': 19.3.0 @@ -6575,65 +6578,67 @@ snapshots: dependencies: '@octokit/openapi-types': 29.0.1 - '@oxc-parser/binding-android-arm-eabi@0.150.0': + '@oxc-parser/binding-android-arm-eabi@0.153.0': optional: true - '@oxc-parser/binding-android-arm64@0.150.0': + '@oxc-parser/binding-android-arm64@0.153.0': optional: true - '@oxc-parser/binding-darwin-arm64@0.150.0': + '@oxc-parser/binding-darwin-arm64@0.153.0': optional: true - '@oxc-parser/binding-darwin-x64@0.150.0': + '@oxc-parser/binding-darwin-x64@0.153.0': optional: true - '@oxc-parser/binding-freebsd-x64@0.150.0': + '@oxc-parser/binding-freebsd-x64@0.153.0': optional: true - '@oxc-parser/binding-linux-arm-gnueabihf@0.150.0': + '@oxc-parser/binding-linux-arm-gnueabihf@0.153.0': optional: true - '@oxc-parser/binding-linux-arm-musleabihf@0.150.0': + '@oxc-parser/binding-linux-arm-musleabihf@0.153.0': optional: true - '@oxc-parser/binding-linux-arm64-gnu@0.150.0': + '@oxc-parser/binding-linux-arm64-gnu@0.153.0': optional: true - '@oxc-parser/binding-linux-arm64-musl@0.150.0': + '@oxc-parser/binding-linux-arm64-musl@0.153.0': optional: true - '@oxc-parser/binding-linux-ppc64-gnu@0.150.0': + '@oxc-parser/binding-linux-ppc64-gnu@0.153.0': optional: true - '@oxc-parser/binding-linux-riscv64-gnu@0.150.0': + '@oxc-parser/binding-linux-riscv64-gnu@0.153.0': optional: true - '@oxc-parser/binding-linux-riscv64-musl@0.150.0': + '@oxc-parser/binding-linux-riscv64-musl@0.153.0': optional: true - '@oxc-parser/binding-linux-s390x-gnu@0.150.0': + '@oxc-parser/binding-linux-s390x-gnu@0.153.0': optional: true - '@oxc-parser/binding-linux-x64-gnu@0.150.0': + '@oxc-parser/binding-linux-x64-gnu@0.153.0': optional: true - '@oxc-parser/binding-linux-x64-musl@0.150.0': + '@oxc-parser/binding-linux-x64-musl@0.153.0': optional: true - '@oxc-parser/binding-openharmony-arm64@0.150.0': + '@oxc-parser/binding-openharmony-arm64@0.153.0': optional: true - '@oxc-parser/binding-win32-arm64-msvc@0.150.0': + '@oxc-parser/binding-win32-arm64-msvc@0.153.0': optional: true - '@oxc-parser/binding-win32-ia32-msvc@0.150.0': + '@oxc-parser/binding-win32-ia32-msvc@0.153.0': optional: true - '@oxc-parser/binding-win32-x64-msvc@0.150.0': + '@oxc-parser/binding-win32-x64-msvc@0.153.0': optional: true '@oxc-project/types@0.150.0': {} + '@oxc-project/types@0.153.0': {} + '@oxc-resolver/binding-android-arm-eabi@11.24.2': optional: true @@ -6897,11 +6902,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/react-virtual@3.14.13(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + '@tanstack/react-virtual@3.14.13(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': dependencies: '@tanstack/virtual-core': 3.17.11 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) '@tanstack/virtual-core@3.17.11': {} @@ -7304,11 +7309,11 @@ snapshots: '@vscode/l10n@0.0.18': {} - '@wdio/config@10.0.0(supports-color@7.2.0)(yauzl@2.10.0)': + '@wdio/config@10.0.1(supports-color@7.2.0)(yauzl@2.10.0)': dependencies: '@wdio/logger': 10.0.0 - '@wdio/types': 10.0.0 - '@wdio/utils': 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + '@wdio/types': 10.0.1 + '@wdio/utils': 10.0.1(supports-color@7.2.0)(yauzl@2.10.0) deepmerge-ts: 8.0.2 glob: 10.5.0 import-meta-resolve: 4.2.0 @@ -7318,10 +7323,10 @@ snapshots: - supports-color - yauzl - '@wdio/globals@9.29.1(expect-webdriverio@5.7.0)(webdriverio@10.0.0(supports-color@7.2.0)(yauzl@2.10.0))': + '@wdio/globals@9.29.1(expect-webdriverio@5.7.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0))': dependencies: - expect-webdriverio: 5.7.0(@wdio/globals@9.29.1)(@wdio/logger@9.29.1)(webdriverio@10.0.0(supports-color@7.2.0)(yauzl@2.10.0)) - webdriverio: 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + expect-webdriverio: 5.7.0(@wdio/globals@9.29.1)(@wdio/logger@9.29.1)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) + webdriverio: 10.0.2(supports-color@7.2.0)(yauzl@2.10.0) '@wdio/logger@10.0.0': dependencies: @@ -7362,12 +7367,12 @@ snapshots: esbuild: 0.28.2 find-up-simple: 1.0.1 json5: 2.2.3 - smol-toml: 1.8.0 + smol-toml: 1.9.1 yaml: 2.9.1 transitivePeerDependencies: - supports-color - '@wdio/protocols@10.0.0': {} + '@wdio/protocols@10.0.2': {} '@wdio/repl@10.0.0': dependencies: @@ -7389,9 +7394,9 @@ snapshots: easy-table: 1.2.0 pretty-ms: 9.3.1 - '@wdio/tauri-service@1.4.0(expect-webdriverio@5.7.0)(supports-color@7.2.0)(webdriverio@10.0.0(supports-color@7.2.0)(yauzl@2.10.0))': + '@wdio/tauri-service@1.4.0(expect-webdriverio@5.7.0)(supports-color@7.2.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0))': dependencies: - '@wdio/globals': 9.29.1(expect-webdriverio@5.7.0)(webdriverio@10.0.0(supports-color@7.2.0)(yauzl@2.10.0)) + '@wdio/globals': 9.29.1(expect-webdriverio@5.7.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) '@wdio/logger': 9.29.1 '@wdio/native-core': 1.2.0(supports-color@7.2.0) '@wdio/native-spy': 1.3.0 @@ -7402,13 +7407,13 @@ snapshots: debug: 4.4.3(supports-color@7.2.0) get-port: 7.2.0 tslib: 2.8.1 - webdriverio: 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + webdriverio: 10.0.2(supports-color@7.2.0)(yauzl@2.10.0) transitivePeerDependencies: - expect-webdriverio - supports-color - tsx - '@wdio/types@10.0.0': + '@wdio/types@10.0.1': dependencies: '@types/node': 22.20.5 @@ -7416,12 +7421,12 @@ snapshots: dependencies: '@types/node': 20.19.43 - '@wdio/utils@10.0.0(supports-color@7.2.0)(yauzl@2.10.0)': + '@wdio/utils@10.0.1(supports-color@7.2.0)(yauzl@2.10.0)': dependencies: '@puppeteer/browsers': 3.2.3(yauzl@2.10.0) '@types/split2': 4.2.3 '@wdio/logger': 10.0.0 - '@wdio/types': 10.0.0 + '@wdio/types': 10.0.1 aria-query: 5.3.2 decamelize: 6.0.1 deepmerge-ts: 8.0.2 @@ -7464,14 +7469,14 @@ snapshots: agent-base@9.0.0: {} - ahooks@3.10.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0): + ahooks@3.10.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1): dependencies: '@babel/runtime': 7.29.7 dayjs: 1.11.23 js-cookie: 3.0.8 lodash: 4.18.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) react-fast-compare: 3.2.2 resize-observer-polyfill: 1.5.1 screenfull: 5.2.0 @@ -8326,15 +8331,15 @@ snapshots: expect-type@1.4.0: {} - expect-webdriverio@5.7.0(@wdio/globals@9.29.1)(@wdio/logger@9.29.1)(webdriverio@10.0.0(supports-color@7.2.0)(yauzl@2.10.0)): + expect-webdriverio@5.7.0(@wdio/globals@9.29.1)(@wdio/logger@9.29.1)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)): dependencies: '@vitest/snapshot': 4.1.11 - '@wdio/globals': 9.29.1(expect-webdriverio@5.7.0)(webdriverio@10.0.0(supports-color@7.2.0)(yauzl@2.10.0)) + '@wdio/globals': 9.29.1(expect-webdriverio@5.7.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) '@wdio/logger': 9.29.1 deep-eql: 5.0.2 expect: 30.5.2 jest-matcher-utils: 30.5.2 - webdriverio: 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + webdriverio: 10.0.2(supports-color@7.2.0)(yauzl@2.10.0) expect@30.5.2: dependencies: @@ -8414,19 +8419,19 @@ snapshots: hasown: 2.0.4 mime-types: 2.1.35 - formatly@0.7.1: + formatly@0.11.4: dependencies: fd-package-json: 2.0.0 package-manager-detector: 1.8.0 - foxact@0.3.12(react-dom@19.3.0(react@19.3.0))(react@19.3.0): + foxact@0.3.12(react-dom@19.3.1(react@19.3.1))(react@19.3.1): dependencies: client-only: 0.0.1 event-target-bus: 1.1.0 server-only: 0.0.1 optionalDependencies: - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) foxts@5.9.1: dependencies: @@ -8824,19 +8829,18 @@ snapshots: dependencies: '@keyv/serialize': 1.1.1 - knip@6.39.0: + knip@6.41.0: dependencies: - fdir: 6.5.0(picomatch@4.0.7) - formatly: 0.7.1 + formatly: 0.11.4 get-tsconfig: 4.14.3 jiti: 2.7.0 - oxc-parser: 0.150.0 + oxc-parser: 0.153.0 oxc-resolver: 11.24.2 picomatch: 4.0.7 - smol-toml: 1.8.0 + smol-toml: 1.9.1 strip-json-comments: 5.0.3 tinyglobby: 0.2.17 - unbash: 4.0.11 + unbash: 5.1.0 yaml: 2.9.1 zod: 4.6.5 @@ -9434,29 +9438,29 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - oxc-parser@0.150.0: + oxc-parser@0.153.0: dependencies: - '@oxc-project/types': 0.150.0 + '@oxc-project/types': 0.153.0 optionalDependencies: - '@oxc-parser/binding-android-arm-eabi': 0.150.0 - '@oxc-parser/binding-android-arm64': 0.150.0 - '@oxc-parser/binding-darwin-arm64': 0.150.0 - '@oxc-parser/binding-darwin-x64': 0.150.0 - '@oxc-parser/binding-freebsd-x64': 0.150.0 - '@oxc-parser/binding-linux-arm-gnueabihf': 0.150.0 - '@oxc-parser/binding-linux-arm-musleabihf': 0.150.0 - '@oxc-parser/binding-linux-arm64-gnu': 0.150.0 - '@oxc-parser/binding-linux-arm64-musl': 0.150.0 - '@oxc-parser/binding-linux-ppc64-gnu': 0.150.0 - '@oxc-parser/binding-linux-riscv64-gnu': 0.150.0 - '@oxc-parser/binding-linux-riscv64-musl': 0.150.0 - '@oxc-parser/binding-linux-s390x-gnu': 0.150.0 - '@oxc-parser/binding-linux-x64-gnu': 0.150.0 - '@oxc-parser/binding-linux-x64-musl': 0.150.0 - '@oxc-parser/binding-openharmony-arm64': 0.150.0 - '@oxc-parser/binding-win32-arm64-msvc': 0.150.0 - '@oxc-parser/binding-win32-ia32-msvc': 0.150.0 - '@oxc-parser/binding-win32-x64-msvc': 0.150.0 + '@oxc-parser/binding-android-arm-eabi': 0.153.0 + '@oxc-parser/binding-android-arm64': 0.153.0 + '@oxc-parser/binding-darwin-arm64': 0.153.0 + '@oxc-parser/binding-darwin-x64': 0.153.0 + '@oxc-parser/binding-freebsd-x64': 0.153.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.153.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.153.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.153.0 + '@oxc-parser/binding-linux-arm64-musl': 0.153.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.153.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.153.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.153.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.153.0 + '@oxc-parser/binding-linux-x64-gnu': 0.153.0 + '@oxc-parser/binding-linux-x64-musl': 0.153.0 + '@oxc-parser/binding-openharmony-arm64': 0.153.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.153.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.153.0 + '@oxc-parser/binding-win32-x64-msvc': 0.153.0 oxc-resolver@11.24.2: optionalDependencies: @@ -9604,38 +9608,38 @@ snapshots: dependencies: hookified: 2.2.0 - qrcode.react@4.2.0(react@19.3.0): + qrcode.react@4.2.0(react@19.3.1): dependencies: - react: 19.3.0 + react: 19.3.1 query-selector-shadow-dom@1.0.1: {} - react-dom@19.3.0(react@19.3.0): + react-dom@19.3.1(react@19.3.1): dependencies: - react: 19.3.0 + react: 19.3.1 scheduler: 0.28.0 - react-error-boundary@6.1.6(@types/react@19.3.0)(react@19.3.0): + react-error-boundary@6.1.6(@types/react@19.3.0)(react@19.3.1): dependencies: - react: 19.3.0 + react: 19.3.1 optionalDependencies: '@types/react': 19.3.0 react-fast-compare@3.2.2: {} - react-hook-form@7.88.0(react@19.3.0): + react-hook-form@7.88.0(react@19.3.1): dependencies: - react: 19.3.0 + react: 19.3.1 - react-i18next@17.0.15(i18next@26.4.2(typescript@6.0.3))(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(typescript@6.0.3): + react-i18next@17.0.19(i18next@26.4.2(typescript@6.0.3))(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(typescript@6.0.3): dependencies: '@babel/runtime': 7.29.7 html-parse-stringify: 4.0.1 i18next: 26.4.2(typescript@6.0.3) - react: 19.3.0 - use-sync-external-store: 1.7.0(react@19.3.0) + react: 19.3.1 + use-sync-external-store: 1.7.0(react@19.3.1) optionalDependencies: - react-dom: 19.3.0(react@19.3.0) + react-dom: 19.3.1(react@19.3.1) typescript: 6.0.3 react-is@16.13.1: {} @@ -9644,7 +9648,7 @@ snapshots: react-is@19.3.0: {} - react-markdown@10.1.0(@types/react@19.3.0)(react@19.3.0)(supports-color@7.2.0): + react-markdown@10.1.0(@types/react@19.3.0)(react@19.3.1)(supports-color@7.2.0): dependencies: '@types/hast': 3.0.5 '@types/mdast': 4.0.4 @@ -9653,7 +9657,7 @@ snapshots: hast-util-to-jsx-runtime: 2.3.6(supports-color@7.2.0) html-url-attributes: 3.0.1 mdast-util-to-hast: 13.2.1 - react: 19.3.0 + react: 19.3.1 remark-parse: 11.0.0(supports-color@7.2.0) remark-rehype: 11.1.2 unified: 11.0.5 @@ -9662,24 +9666,24 @@ snapshots: transitivePeerDependencies: - supports-color - react-router@8.4.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0): + react-router@8.4.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1): dependencies: '@remix-run/route-pattern': 0.22.1 cookie-es: 3.1.1 - react: 19.3.0 + react: 19.3.1 optionalDependencies: - react-dom: 19.3.0(react@19.3.0) + react-dom: 19.3.1(react@19.3.1) - react-transition-group@4.4.5(react-dom@19.3.0(react@19.3.0))(react@19.3.0): + react-transition-group@4.4.5(react-dom@19.3.1(react@19.3.1))(react@19.3.1): dependencies: '@babel/runtime': 7.29.7 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 19.3.0 - react-dom: 19.3.0(react@19.3.0) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) - react@19.3.0: {} + react@19.3.1: {} readable-stream@2.3.8: dependencies: @@ -9859,7 +9863,7 @@ snapshots: slash@3.0.0: {} - smol-toml@1.8.0: {} + smol-toml@1.9.1: {} snake-case@3.0.4: dependencies: @@ -9972,11 +9976,11 @@ snapshots: svg-parser@2.1.0: {} - swr@2.5.1(react@19.3.0): + swr@2.5.1(react@19.3.1): dependencies: dequal: 2.0.3 - react: 19.3.0 - use-sync-external-store: 1.7.0(react@19.3.0) + react: 19.3.1 + use-sync-external-store: 1.7.0(react@19.3.1) systemjs@6.15.1: {} @@ -10080,7 +10084,7 @@ snapshots: typescript@6.0.3: {} - unbash@4.0.11: {} + unbash@5.1.0: {} undici-types@6.21.0: {} @@ -10177,9 +10181,9 @@ snapshots: urlpattern-polyfill@10.1.0: {} - use-sync-external-store@1.7.0(react@19.3.0): + use-sync-external-store@1.7.0(react@19.3.1): dependencies: - react: 19.3.0 + react: 19.3.1 userhome@1.0.1: {} @@ -10280,15 +10284,15 @@ snapshots: web-namespaces@2.0.1: {} - webdriver@10.0.0(supports-color@7.2.0)(yauzl@2.10.0): + webdriver@10.0.2(supports-color@7.2.0)(yauzl@2.10.0): dependencies: '@types/node': 22.20.5 '@types/ws': 8.18.1 - '@wdio/config': 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + '@wdio/config': 10.0.1(supports-color@7.2.0)(yauzl@2.10.0) '@wdio/logger': 10.0.0 - '@wdio/protocols': 10.0.0 - '@wdio/types': 10.0.0 - '@wdio/utils': 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + '@wdio/protocols': 10.0.2 + '@wdio/types': 10.0.1 + '@wdio/utils': 10.0.1(supports-color@7.2.0)(yauzl@2.10.0) deepmerge-ts: 8.0.2 https-proxy-agent: 7.0.6(supports-color@7.2.0) undici: 8.11.2 @@ -10300,16 +10304,16 @@ snapshots: - utf-8-validate - yauzl - webdriverio@10.0.0(supports-color@7.2.0)(yauzl@2.10.0): + webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0): dependencies: '@types/node': 22.20.5 '@types/sinonjs__fake-timers': 8.1.5 - '@wdio/config': 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + '@wdio/config': 10.0.1(supports-color@7.2.0)(yauzl@2.10.0) '@wdio/logger': 10.0.0 - '@wdio/protocols': 10.0.0 + '@wdio/protocols': 10.0.2 '@wdio/repl': 10.0.0 - '@wdio/types': 10.0.0 - '@wdio/utils': 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + '@wdio/types': 10.0.1 + '@wdio/utils': 10.0.1(supports-color@7.2.0)(yauzl@2.10.0) archiver: 8.0.0 aria-query: 5.3.2 cheerio: 1.2.0 @@ -10324,7 +10328,7 @@ snapshots: rgb2hex: 0.2.5 serialize-error: 12.0.0 urlpattern-polyfill: 10.1.0 - webdriver: 10.0.0(supports-color@7.2.0)(yauzl@2.10.0) + webdriver: 10.0.2(supports-color@7.2.0)(yauzl@2.10.0) transitivePeerDependencies: - bare-abort-controller - bare-buffer From 79657119452b8202a4f1daf64acb12e7cf093080 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 17 Oct 2026 16:14:23 +0000 Subject: [PATCH 17/25] chore(deps): update cargo dependencies (#8323) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update cargo dependencies * chore(deps): revert dependency rfd to 0.16.0 Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> --------- Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> --- Cargo.lock | 63 ++++++++++--------- Cargo.toml | 4 +- .../Cargo.toml | 2 +- src-tauri/Cargo.toml | 10 +-- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1af5de8a..3c2f85631 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1138,7 +1138,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml_ng", - "sha2 0.11.0", + "sha2 0.11.1", "smartstring", "socket2", "specta", @@ -1175,7 +1175,7 @@ dependencies = [ "windows-service", "windows-sys 0.61.2", "winreg 0.56.0", - "zip 9.0.1", + "zip 9.0.4", ] [[package]] @@ -1247,7 +1247,7 @@ dependencies = [ "once_cell", "serde", "serde_json", - "sha2 0.11.0", + "sha2 0.11.1", "strum", "strum_macros", "sysproxy", @@ -1462,9 +1462,12 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.4.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" +checksum = "9eb6feb175df65d0a3ccd3e73484e940d0ac664e8034f0519fd49a93db3071d9" +dependencies = [ + "rustversion", +] [[package]] name = "cookie" @@ -3951,9 +3954,9 @@ checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c" [[package]] name = "libc" -version = "0.2.190" +version = "0.2.191" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" +checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a" [[package]] name = "libdbus-sys" @@ -4048,11 +4051,11 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "lzma-rust2" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde178a3caf126c440fa15628147772d8ee590a39477d711353fbe2e58a73a5b" +checksum = "7277c9742229dc25243236d578b6471a798c554512c6f6a04365ec2e87c2a3bb" dependencies = [ - "sha2 0.11.0", + "sha2 0.11.1", ] [[package]] @@ -5343,9 +5346,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppmd-rust" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24" +checksum = "196a7c80b9a7652aba7cc070827516c2abe4ccdf53d128e1944003cf5726cff1" [[package]] name = "ppv-lite86" @@ -6067,9 +6070,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.45" +version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ "aws-lc-rs", "log", @@ -6410,9 +6413,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.151" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" dependencies = [ "itoa", "memchr", @@ -6597,9 +6600,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19" dependencies = [ "cfg-if", "cpufeatures 0.3.0", @@ -8073,9 +8076,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.53.2" +version = "1.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044" +checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e" dependencies = [ "bytes", "libc", @@ -8135,9 +8138,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b" dependencies = [ "bytes", "futures-core", @@ -10150,9 +10153,9 @@ dependencies = [ [[package]] name = "zip" -version = "9.0.1" +version = "9.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e49ade69c4434c55dd651d36fe05f38e0578db948b773cbc01c48c4b5e560692" +checksum = "a954114b47a54df49f83d2722814e86b23d4bb1b54a1b90fb7d92b41619ddc22" dependencies = [ "aes", "bzip2", @@ -10202,27 +10205,27 @@ dependencies = [ [[package]] name = "zstd" -version = "0.13.3" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +checksum = "db3ae9bf90af6e40197bef767eeefc46ad6397420fe873830bd85e5fbbfb3c70" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.2.4" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +checksum = "ded520f16b29e1a9b771c722221b2b0a0398c2316d9bb3c42b458a5414d7434b" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" +version = "2.1.2+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +checksum = "481ada9c543b2323cbb7bbdbb5249177fbf0188ed959ed2c15e4b22421c84ed3" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index 3dffbca78..a91a42b2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,7 +67,7 @@ parking_lot = { version = "0.12.5", features = ["hardware-lock-elision"] } anyhow = "1.0.104" chrono = "0.4.45" criterion = { version = "0.8.2", features = ["async_tokio"] } -tokio = { version = "1.53.2", features = [ +tokio = { version = "1.53.3", features = [ "rt-multi-thread", "macros", "time", @@ -88,7 +88,7 @@ rust_iso3166 = "0.2.0" smartstring = { version = "1.0.1" } serde = { version = "1.0.229" } -serde_json = { version = "1.0.151" } +serde_json = { version = "1.0.154" } serde_yaml_ng = { version = "0.10.0" } bitflags = { version = "2.13.2" } socket2 = "0.6.5" diff --git a/crates/tauri-plugin-clash-verge-sysinfo/Cargo.toml b/crates/tauri-plugin-clash-verge-sysinfo/Cargo.toml index aa5f1ba02..839fcbd04 100644 --- a/crates/tauri-plugin-clash-verge-sysinfo/Cargo.toml +++ b/crates/tauri-plugin-clash-verge-sysinfo/Cargo.toml @@ -15,7 +15,7 @@ serde = { workspace = true, features = ["derive"] } sysinfo = { version = "0.39.6", features = ["network", "system"] } [target.'cfg(not(windows))'.dependencies] -libc = "0.2.190" +libc = "0.2.191" [target.'cfg(windows)'.dependencies] deelevate = { workspace = true } diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f8b2fe11b..6b2f670bf 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -79,13 +79,13 @@ tauri-plugin-fs = "2.6.0" tauri-plugin-process = "2.4.0" tauri-plugin-deep-link = "2.6.1" tauri-plugin-window-state = "2.5.0" -zip = "9.0.1" +zip = "9.0.4" flate2 = "1.1.10" reqwest_dav = "0.3.3" aes-gcm = { version = "0.11.1" } base64 = "0.23.1" minisign-verify = "0.3.0" -sha2 = "0.11" +sha2 = "0.11.1" getrandom = "0.4.3" futures = "0.3.34" gethostname = "1.1.0" @@ -103,17 +103,17 @@ clash_verge_service_ipc = { git = "https://github.com/clash-verge-rev/clash-verg ] } arc-swap = "1.9.2" tokio-rustls = "0.26.6" -rustls = { version = "0.23.45", features = ["ring"] } +rustls = { version = "0.23.46", features = ["ring"] } webpki-roots = "1.0.9" dark-light = "3.0.0" bytes = "1.12.1" -tokio-util = { version = "0.7.19", features = ["time"] } +tokio-util = { version = "0.7.20", features = ["time"] } specta = { version = "=2.0.0-rc.25", features = ["derive", "function", "serde_json"] } tauri-specta = { version = "=2.0.0-rc.25", features = ["derive", "typescript"] } specta-typescript = "=0.0.12" [target.'cfg(unix)'.dependencies] -libc = "0.2.190" +libc = "0.2.191" [target.'cfg(target_os = "linux")'.dependencies] # Upstream has no session-end signal support on Linux; see crates/clash-verge-signal. From 4e5ac8683b6de668e4ca59878303b428b7cbfa2f Mon Sep 17 00:00:00 2001 From: wonfen Date: Mon, 19 Oct 2026 20:01:43 +0800 Subject: [PATCH 18/25] feat(proxy): confirm before enabling chain proxy Show the speed warning with explicit enable/keep-disabled actions, and add a close button to the empty chain panel. --- Changelog.md | 1 + src/components/proxy/proxy-chain.tsx | 7 +++ src/components/proxy/proxy-groups-chain.tsx | 3 + src/components/proxy/proxy-groups.tsx | 13 +++- src/locales/ar/proxies.json | 2 + src/locales/de/proxies.json | 2 + src/locales/en/proxies.json | 2 + src/locales/es/proxies.json | 2 + src/locales/fa/proxies.json | 2 + src/locales/id/proxies.json | 2 + src/locales/jp/proxies.json | 2 + src/locales/ko/proxies.json | 2 + src/locales/pt/proxies.json | 2 + src/locales/ru/proxies.json | 2 + src/locales/tr/proxies.json | 2 + src/locales/tt/proxies.json | 2 + src/locales/zh/proxies.json | 2 + src/locales/zhtw/proxies.json | 2 + src/pages/proxies.tsx | 67 +++++++++++++-------- src/types/generated/i18n-keys.ts | 2 + src/types/generated/i18n-resources.ts | 2 + 21 files changed, 96 insertions(+), 27 deletions(-) diff --git a/Changelog.md b/Changelog.md index 310e376f8..d738083fc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@
🚀 优化改进 +- 优化「链式代理」:开启前需确认网速影响提示,空面板新增「关闭」按钮 **🖥️ Windows** diff --git a/src/components/proxy/proxy-chain.tsx b/src/components/proxy/proxy-chain.tsx index 439b23e2e..1eb188165 100644 --- a/src/components/proxy/proxy-chain.tsx +++ b/src/components/proxy/proxy-chain.tsx @@ -75,6 +75,7 @@ interface ProxyChainProps { onMarkUnsavedChanges?: () => void mode?: string selectedGroup?: string | null + onExitChainMode: () => void } interface ProxyChainItemProps { @@ -331,6 +332,7 @@ export const ProxyChain = ({ onMarkUnsavedChanges, mode, selectedGroup, + onExitChainMode, }: ProxyChainProps) => { const theme = useTheme() const { t } = useTranslation() @@ -696,13 +698,18 @@ export const ProxyChain = ({ {t('proxies.page.chain.empty')} + ) : ( void availableGroups: any[] activeSelectedGroup: string | null showScrollTop: boolean @@ -305,6 +306,7 @@ export function ProxyGroupsChain(props: ProxyGroupsChainProps) { const { mode, chainConfigData, + onExitChainMode, availableGroups, activeSelectedGroup, showScrollTop, @@ -521,6 +523,7 @@ export function ProxyGroupsChain(props: ProxyGroupsChainProps) { chainConfigData={chainConfigData} mode={mode} selectedGroup={activeSelectedGroup} + onExitChainMode={onExitChainMode} /> diff --git a/src/components/proxy/proxy-groups.tsx b/src/components/proxy/proxy-groups.tsx index ac86975c5..28e3b3e06 100644 --- a/src/components/proxy/proxy-groups.tsx +++ b/src/components/proxy/proxy-groups.tsx @@ -71,6 +71,7 @@ interface Props { mode: string isChainMode?: boolean chainConfigData?: string | null + onExitChainMode: () => void } function useEmptyRenderList() { @@ -199,8 +200,9 @@ function useProxyRenderState( function ChainProxyGroups(props: { mode: string chainConfigData?: string | null + onExitChainMode: () => void }) { - const { mode, chainConfigData } = props + const { mode, chainConfigData, onExitChainMode } = props const { proxyView } = useProxiesData() const [selectedGroup, setSelectedGroup] = useState(null) @@ -355,6 +357,7 @@ function ChainProxyGroups(props: { { - const { mode, isChainMode = false, chainConfigData } = props + const { mode, isChainMode = false, chainConfigData, onExitChainMode } = props const { profiles, isLoading: isProfilesLoading } = useProfiles() const { isProxyViewPending } = useProxiesData() const { isRunningModePending } = useSystemData() @@ -648,7 +651,11 @@ export const ProxyGroups = (props: Props) => { return case 'render': return isChainMode ? ( - + ) : ( ) diff --git a/src/locales/ar/proxies.json b/src/locales/ar/proxies.json index 55f99cec8..c884d9a0e 100644 --- a/src/locales/ar/proxies.json +++ b/src/locales/ar/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Chain Proxy Config", "warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", + "confirmEnable": "I understand, enable", + "keepDisabled": "Keep disabled", "empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", "instruction": "Click nodes in order to add to proxy chain", "minimumNodes": "Chain proxy requires at least 2 nodes", diff --git a/src/locales/de/proxies.json b/src/locales/de/proxies.json index 3e19338ea..0ae1d2af3 100644 --- a/src/locales/de/proxies.json +++ b/src/locales/de/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Proxy-Kette konfigurieren", "warning": "Eine Proxy-Kette verringert die Netzwerkgeschwindigkeit deutlich. Wenn Sie keinen klaren Bedarf haben oder diese Konfiguration nicht verstehen, lassen Sie sie deaktiviert.", + "confirmEnable": "Verstanden, aktivieren", + "keepDisabled": "Deaktiviert lassen", "empty": "Eine Proxy-Kette verringert die Netzwerkgeschwindigkeit deutlich. Wenn Sie keinen klaren Bedarf haben oder diese Konfiguration nicht verstehen, lassen Sie sie deaktiviert.", "instruction": "Klicken Sie die Knoten nacheinander an, um sie zur Proxy-Kette hinzuzufügen", "minimumNodes": "Eine Proxy-Kette braucht mindestens 2 Knoten", diff --git a/src/locales/en/proxies.json b/src/locales/en/proxies.json index ead3f0cbf..83c2a56bc 100644 --- a/src/locales/en/proxies.json +++ b/src/locales/en/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Chain Proxy Config", "warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", + "confirmEnable": "I understand, enable", + "keepDisabled": "Keep disabled", "empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", "instruction": "Click nodes in order to add to proxy chain", "minimumNodes": "Chain proxy requires at least 2 nodes", diff --git a/src/locales/es/proxies.json b/src/locales/es/proxies.json index 537790ba3..46d0b4f5a 100644 --- a/src/locales/es/proxies.json +++ b/src/locales/es/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Chain Proxy Config", "warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", + "confirmEnable": "I understand, enable", + "keepDisabled": "Keep disabled", "empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", "instruction": "Click nodes in order to add to proxy chain", "minimumNodes": "Chain proxy requires at least 2 nodes", diff --git a/src/locales/fa/proxies.json b/src/locales/fa/proxies.json index b430a2475..d055557d7 100644 --- a/src/locales/fa/proxies.json +++ b/src/locales/fa/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Chain Proxy Config", "warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", + "confirmEnable": "I understand, enable", + "keepDisabled": "Keep disabled", "empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", "instruction": "Click nodes in order to add to proxy chain", "minimumNodes": "Chain proxy requires at least 2 nodes", diff --git a/src/locales/id/proxies.json b/src/locales/id/proxies.json index 7bb44c604..83f3c6c23 100644 --- a/src/locales/id/proxies.json +++ b/src/locales/id/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Chain Proxy Config", "warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", + "confirmEnable": "I understand, enable", + "keepDisabled": "Keep disabled", "empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", "instruction": "Click nodes in order to add to proxy chain", "minimumNodes": "Chain proxy requires at least 2 nodes", diff --git a/src/locales/jp/proxies.json b/src/locales/jp/proxies.json index 950e65646..3dcb125dd 100644 --- a/src/locales/jp/proxies.json +++ b/src/locales/jp/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Chain Proxy Config", "warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", + "confirmEnable": "I understand, enable", + "keepDisabled": "Keep disabled", "empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", "instruction": "Click nodes in order to add to proxy chain", "minimumNodes": "Chain proxy requires at least 2 nodes", diff --git a/src/locales/ko/proxies.json b/src/locales/ko/proxies.json index 64e7b6a9c..1ec805f00 100644 --- a/src/locales/ko/proxies.json +++ b/src/locales/ko/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "체인 프록시 구성", "warning": "체인 프록시는 네트워크 속도를 크게 저하시킬 수 있습니다. 명확한 업무상 필요가 없거나 이 구성을 이해하지 못한다면 비활성화 상태로 두세요.", + "confirmEnable": "이해했습니다, 활성화", + "keepDisabled": "비활성화 유지", "empty": "체인 프록시는 네트워크 속도를 크게 저하시킬 수 있습니다. 명확한 업무상 필요가 없거나 이 구성을 이해하지 못한다면 비활성화 상태로 두세요.", "instruction": "프록시 체인에 추가하려면 순서대로 노드를 클릭하세요", "minimumNodes": "체인 프록시는 최소 2개의 노드가 필요합니다", diff --git a/src/locales/pt/proxies.json b/src/locales/pt/proxies.json index 1740f6043..2f32fcdc9 100644 --- a/src/locales/pt/proxies.json +++ b/src/locales/pt/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Configuração do proxy em cadeia", "warning": "O proxy em cadeia reduz significativamente a velocidade da rede. Se você não tem uma necessidade clara ou não entende esta configuração, mantenha-o desativado.", + "confirmEnable": "Entendi, ativar", + "keepDisabled": "Manter desativado", "empty": "O proxy em cadeia reduz significativamente a velocidade da rede. Se você não tem uma necessidade clara ou não entende esta configuração, mantenha-o desativado.", "instruction": "Clique nos nós em ordem para adicioná-los à cadeia de proxy", "minimumNodes": "O proxy em cadeia requer pelo menos 2 nós", diff --git a/src/locales/ru/proxies.json b/src/locales/ru/proxies.json index 603abacc1..9ac3af1df 100644 --- a/src/locales/ru/proxies.json +++ b/src/locales/ru/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Цепочка прокси", "warning": "Цепочка прокси может значительно снизить скорость сети. Если у вас нет явной рабочей необходимости или вы не понимаете эту настройку, оставьте ее отключенной.", + "confirmEnable": "Понятно, включить", + "keepDisabled": "Оставить выключенным", "empty": "Цепочка прокси может значительно снизить скорость сети. Если у вас нет явной рабочей необходимости или вы не понимаете эту настройку, оставьте ее отключенной.", "instruction": "Нажимайте на узлы по порядку, чтобы добавить их в цепочку", "minimumNodes": "Для цепочки требуется минимум 2 узла", diff --git a/src/locales/tr/proxies.json b/src/locales/tr/proxies.json index 6c4a84122..5fa5f8a4b 100644 --- a/src/locales/tr/proxies.json +++ b/src/locales/tr/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Zincir Vekil Yapılandırması", "warning": "Zincir vekil ağ hızını belirgin biçimde düşürür. Açık bir ihtiyacınız yoksa ya da bu yapılandırmayı bilmiyorsanız devre dışı bırakın.", + "confirmEnable": "Anladım, etkinleştir", + "keepDisabled": "Devre dışı kalsın", "empty": "Zincir vekil ağ hızını belirgin biçimde düşürür. Açık bir ihtiyacınız yoksa ya da bu yapılandırmayı bilmiyorsanız devre dışı bırakın.", "instruction": "Vekil zincirine eklemek için düğümlere sırayla tıklayın", "minimumNodes": "Zincir vekil en az 2 düğüm gerektirir", diff --git a/src/locales/tt/proxies.json b/src/locales/tt/proxies.json index 59fcd096b..6222875fe 100644 --- a/src/locales/tt/proxies.json +++ b/src/locales/tt/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "Chain Proxy Config", "warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", + "confirmEnable": "I understand, enable", + "keepDisabled": "Keep disabled", "empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.", "instruction": "Click nodes in order to add to proxy chain", "minimumNodes": "Chain proxy requires at least 2 nodes", diff --git a/src/locales/zh/proxies.json b/src/locales/zh/proxies.json index cc792f5e7..3cecd8eb7 100644 --- a/src/locales/zh/proxies.json +++ b/src/locales/zh/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "代理链配置", "warning": "链式代理会显著降低网速。如果您没有明确的业务需求,或不了解此项配置,请保持关闭", + "confirmEnable": "我明白,开启", + "keepDisabled": "保持关闭", "empty": "链式代理会显著降低网速。如果您没有明确的业务需求,或不了解此项配置,请保持关闭", "instruction": "顺序点击节点添加到代理链中", "minimumNodes": "链式代理至少需要 2 个节点", diff --git a/src/locales/zhtw/proxies.json b/src/locales/zhtw/proxies.json index 48150df00..890a8ac4b 100644 --- a/src/locales/zhtw/proxies.json +++ b/src/locales/zhtw/proxies.json @@ -70,6 +70,8 @@ "chain": { "header": "鏈式代理設定", "warning": "鏈式代理會顯著降低網速。如果您沒有明確的業務需求,或不了解此項設定,請保持關閉", + "confirmEnable": "我明白,開啟", + "keepDisabled": "保持關閉", "empty": "鏈式代理會顯著降低網速。如果您沒有明確的業務需求,或不了解此項設定,請保持關閉", "instruction": "依序點擊節點新增到鏈式代理中", "minimumNodes": "鏈式代理至少需要 2 個節點", diff --git a/src/pages/proxies.tsx b/src/pages/proxies.tsx index cbf1d9ce3..14b56f25f 100644 --- a/src/pages/proxies.tsx +++ b/src/pages/proxies.tsx @@ -1,10 +1,10 @@ import { LanOutlined, LanRounded, WarningRounded } from '@mui/icons-material' -import { Box, Button, ButtonGroup } from '@mui/material' +import { Box, Button, ButtonGroup, Typography } from '@mui/material' import { useLockFn } from 'ahooks' import { useCallback, useEffect, useReducer, useState } from 'react' import { useTranslation } from 'react-i18next' -import { BasePage, TooltipIcon } from '@/components/base' +import { BaseDialog, BasePage, TooltipIcon } from '@/components/base' import { ProviderButton } from '@/components/proxy/provider-button' import { ProxyGroups } from '@/components/proxy/proxy-groups' import { @@ -38,6 +38,7 @@ const ProxyPage = () => { return false } }) + const [chainConfirmOpen, setChainConfirmOpen] = useState(false) const [chainConfigData, dispatchChainConfigData] = useReducer( (_: string | null, action: string | null) => action, @@ -68,32 +69,34 @@ const ProxyPage = () => { } }) - const onToggleChainMode = useLockFn(async () => { - const newChainMode = !isChainMode + const applyChainMode = (enabled: boolean) => { + setIsChainMode(enabled) + localStorage.setItem('proxy-chain-mode-enabled', enabled.toString()) + } - if (!newChainMode) { - // 退出链式代理模式时,清除链式代理配置 - try { - debugLog('Exiting chain mode, clearing chain configuration') - const result = await mutate( - () => updateProxyChainConfigInRuntime(null), - { - id: 'update-proxy-chain-runtime', - errorNotice: false, - }, - ) - if (!result.ok) return - debugLog('Chain configuration cleared successfully') - } catch (error) { - console.error('Failed to clear chain configuration:', error) - showNotice.error(error) - return - } + const onExitChainMode = useLockFn(async () => { + // 退出链式代理模式时,清除链式代理配置 + try { + debugLog('Exiting chain mode, clearing chain configuration') + const result = await mutate(() => updateProxyChainConfigInRuntime(null), { + id: 'update-proxy-chain-runtime', + errorNotice: false, + }) + if (!result.ok) return + debugLog('Chain configuration cleared successfully') + } catch (error) { + console.error('Failed to clear chain configuration:', error) + showNotice.error(error) + return } - setIsChainMode(newChainMode) - localStorage.setItem('proxy-chain-mode-enabled', newChainMode.toString()) + applyChainMode(false) }) + const onToggleChainMode = () => { + if (isChainMode) onExitChainMode().catch(() => {}) + else setChainConfirmOpen(true) + } + // 当开启链式代理模式时,获取配置数据 useEffect(() => { if (!isChainMode) { @@ -202,7 +205,23 @@ const ProxyPage = () => { mode={curMode ?? 'rule'} isChainMode={isChainMode} chainConfigData={chainConfigData} + onExitChainMode={onExitChainMode} /> + setChainConfirmOpen(false)} + onClose={() => setChainConfirmOpen(false)} + onOk={() => { + setChainConfirmOpen(false) + applyChainMode(true) + }} + > + {chainWarning} + ) } diff --git a/src/types/generated/i18n-keys.ts b/src/types/generated/i18n-keys.ts index 4e566dce4..07be729be 100644 --- a/src/types/generated/i18n-keys.ts +++ b/src/types/generated/i18n-keys.ts @@ -322,6 +322,8 @@ export const translationKeys = [ 'proxies.page.empty.actions.openLogs', 'proxies.page.chain.header', 'proxies.page.chain.warning', + 'proxies.page.chain.confirmEnable', + 'proxies.page.chain.keepDisabled', 'proxies.page.chain.empty', 'proxies.page.chain.instruction', 'proxies.page.chain.minimumNodes', diff --git a/src/types/generated/i18n-resources.ts b/src/types/generated/i18n-resources.ts index 87aba3645..b2f2a64bf 100644 --- a/src/types/generated/i18n-resources.ts +++ b/src/types/generated/i18n-resources.ts @@ -525,6 +525,7 @@ export interface TranslationResources { toggleChain: string } chain: { + confirmEnable: string connectFailed: string disconnectFailed: string duplicateNode: string @@ -533,6 +534,7 @@ export interface TranslationResources { exitNode: string header: string instruction: string + keepDisabled: string minimumNodes: string minimumNodesHint: string warning: string From 9dd5aa676b7fc8c3a82c968103de89b07bf0a9be Mon Sep 17 00:00:00 2001 From: susu-Sugar Date: Mon, 19 Oct 2026 17:41:33 +0000 Subject: [PATCH 19/25] fix(profiles): refresh remote profile name from server on update (#8360) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(profiles): refresh remote profile name from server on update Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> * chore(changelog): Update changelog for the PR Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> --------- Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> Co-authored-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> --- Changelog.md | 1 + src-tauri/src/config/profiles.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index d738083fc..ffb34844c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -23,6 +23,7 @@ 🚀 优化改进 - 优化「链式代理」:开启前需确认网速影响提示,空面板新增「关闭」按钮 +- 优化「订阅更新」:在刷新订阅自身内容的同时,一并刷新订阅配置文件名称 **🖥️ Windows** diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index 7680fff58..fc31618c0 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -294,6 +294,7 @@ impl IProfiles { each.extra = item.extra; each.updated = item.updated; each.home = item.home.to_owned(); + each.name = item.name.clone(); each.option = PrfOption::merge(each.option.as_ref(), item.option.as_ref()); if let Some(file_data) = item.file_data.take() { let file = each.file.take(); From 27d8a71d4141c0be677fbca41d1caee53fc27cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9D=A4=E6=98=AF=E7=BA=B1=E9=9B=BE=E9=85=B1=E5=93=9F?= =?UTF-8?q?=EF=BD=9E?= <49941141+Dragon1573@users.noreply.github.com> Date: Tue, 20 Oct 2026 15:52:35 +0000 Subject: [PATCH 20/25] Revert "fix(profiles): refresh remote profile name from server on update (#8360)" (#8366) This reverts commit 9dd5aa676b7fc8c3a82c968103de89b07bf0a9be. --- Changelog.md | 1 - src-tauri/src/config/profiles.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index ffb34844c..d738083fc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -23,7 +23,6 @@ 🚀 优化改进 - 优化「链式代理」:开启前需确认网速影响提示,空面板新增「关闭」按钮 -- 优化「订阅更新」:在刷新订阅自身内容的同时,一并刷新订阅配置文件名称 **🖥️ Windows** diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index fc31618c0..7680fff58 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -294,7 +294,6 @@ impl IProfiles { each.extra = item.extra; each.updated = item.updated; each.home = item.home.to_owned(); - each.name = item.name.clone(); each.option = PrfOption::merge(each.option.as_ref(), item.option.as_ref()); if let Some(file_data) = item.file_data.take() { let file = each.file.take(); From 5e6a696087a5c855f5fd1ab51f4a3f4c6451afc3 Mon Sep 17 00:00:00 2001 From: wonfen Date: Wed, 21 Oct 2026 05:34:49 +0800 Subject: [PATCH 21/25] revert(tray): revert per-group latency testing (#8173) This reverts commit cb751052a423c017e75cf0379adb12848e3f0fae. Remove the tray latency test and its dashboard URL persistence and cache changes because the two entry points have diverging behavior. Preserve the subsequent IPC binding migration and remove generated fields, input projections, and locale entries that depended on the reverted feature. --- Changelog.md | 1 + crates/clash-verge-i18n/locales/ar.yml | 2 - crates/clash-verge-i18n/locales/de.yml | 2 - crates/clash-verge-i18n/locales/en.yml | 2 - crates/clash-verge-i18n/locales/es.yml | 2 - crates/clash-verge-i18n/locales/fa.yml | 2 - crates/clash-verge-i18n/locales/id.yml | 2 - crates/clash-verge-i18n/locales/jp.yml | 2 - crates/clash-verge-i18n/locales/ko.yml | 2 - crates/clash-verge-i18n/locales/pt.yml | 2 - crates/clash-verge-i18n/locales/ru.yml | 2 - crates/clash-verge-i18n/locales/tr.yml | 2 - crates/clash-verge-i18n/locales/tt.yml | 2 - crates/clash-verge-i18n/locales/zh.yml | 2 - crates/clash-verge-i18n/locales/zhtw.yml | 2 - src-tauri/src/cmd/profile.rs | 3 - src-tauri/src/cmd/proxy.rs | 16 +- src-tauri/src/config/prfitem.rs | 6 - src-tauri/src/config/profiles.rs | 1 - src-tauri/src/core/proxy_view.rs | 103 +--- src-tauri/src/core/tray/latency.rs | 156 ------ src-tauri/src/core/tray/menu_def.rs | 1 - src-tauri/src/core/tray/mod.rs | 491 +++++------------- src/components/home/current-proxy-card.tsx | 23 - src/components/proxy/proxy-group-tools.tsx | 17 +- src/components/proxy/proxy-groups.tsx | 8 - src/components/proxy/proxy-head.tsx | 17 +- src/components/proxy/proxy-test-url-input.tsx | 55 -- src/components/proxy/use-filter-sort.test.ts | 16 +- src/components/proxy/use-head-state.ts | 78 +-- src/components/proxy/use-render-list.ts | 1 - src/hooks/use-profiles.ts | 7 +- src/hooks/use-proxy-delay-state.ts | 21 +- src/services/bindings.ts | 12 - src/services/cmds.ts | 15 +- src/services/delay.test.ts | 133 ----- src/services/delay.ts | 96 ++-- src/services/proxy-test-url.test.ts | 124 ----- src/services/proxy-test-url.ts | 101 ---- src/utils/network.ts | 13 - 40 files changed, 228 insertions(+), 1315 deletions(-) delete mode 100644 src-tauri/src/core/tray/latency.rs delete mode 100644 src/components/proxy/proxy-test-url-input.tsx delete mode 100644 src/services/proxy-test-url.test.ts delete mode 100644 src/services/proxy-test-url.ts diff --git a/Changelog.md b/Changelog.md index d738083fc..0110ee42a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@
🐞 修复问题 +- 修复托盘测速与代理页行为不一致的问题,移除托盘「测试延迟」入口 - 修复通过 URL 导入订阅时,即使导入的订阅并非当前使用的订阅,也会重新加载当前配置 - 修复 首页 网站测速失败后卡片一直显示测试中 - 修复 代理 页展开分组后不显示最新测速结果,需切换节点才刷新 diff --git a/crates/clash-verge-i18n/locales/ar.yml b/crates/clash-verge-i18n/locales/ar.yml index 81dec23dc..523f49c55 100644 --- a/crates/clash-verge-i18n/locales/ar.yml +++ b/crates/clash-verge-i18n/locales/ar.yml @@ -70,8 +70,6 @@ tray: global: عام profiles: الملفات التعريفية proxies: وكلاء - testLatency: اختبار التأخير - testingLatency: جارٍ اختبار التأخير… systemProxy: وكيل النظام tunMode: وضع TUN closeAllConnections: إغلاق كل الاتصالات diff --git a/crates/clash-verge-i18n/locales/de.yml b/crates/clash-verge-i18n/locales/de.yml index 058f3b3d3..d8accd74b 100644 --- a/crates/clash-verge-i18n/locales/de.yml +++ b/crates/clash-verge-i18n/locales/de.yml @@ -70,8 +70,6 @@ tray: global: Global profiles: Profile proxies: Proxy - testLatency: Latenz testen - testingLatency: Latenz wird getestet… systemProxy: Systemproxy tunMode: TUN-Modus closeAllConnections: Alle Verbindungen schließen diff --git a/crates/clash-verge-i18n/locales/en.yml b/crates/clash-verge-i18n/locales/en.yml index 9db8ff3cd..d1b144b94 100644 --- a/crates/clash-verge-i18n/locales/en.yml +++ b/crates/clash-verge-i18n/locales/en.yml @@ -70,8 +70,6 @@ tray: global: Global profiles: Profiles proxies: Proxies - testLatency: Test Latency - testingLatency: Testing latency… systemProxy: System Proxy tunMode: TUN Mode closeAllConnections: Close All Connections diff --git a/crates/clash-verge-i18n/locales/es.yml b/crates/clash-verge-i18n/locales/es.yml index 85ad7d95d..119d630d7 100644 --- a/crates/clash-verge-i18n/locales/es.yml +++ b/crates/clash-verge-i18n/locales/es.yml @@ -70,8 +70,6 @@ tray: global: Global profiles: Perfiles proxies: Proxies - testLatency: Probar latencia - testingLatency: Probando latencia… systemProxy: Proxy del sistema tunMode: Modo TUN closeAllConnections: Cerrar todas las conexiones diff --git a/crates/clash-verge-i18n/locales/fa.yml b/crates/clash-verge-i18n/locales/fa.yml index 2a3453405..e5270cebd 100644 --- a/crates/clash-verge-i18n/locales/fa.yml +++ b/crates/clash-verge-i18n/locales/fa.yml @@ -70,8 +70,6 @@ tray: global: سراسری profiles: پروفایل‌ها proxies: پروکسی‌ها - testLatency: آزمایش تأخیر - testingLatency: در حال آزمایش تأخیر… systemProxy: پروکسی سیستم tunMode: حالت TUN closeAllConnections: بستن همه اتصال‌ها diff --git a/crates/clash-verge-i18n/locales/id.yml b/crates/clash-verge-i18n/locales/id.yml index 9c037b90d..316b3e523 100644 --- a/crates/clash-verge-i18n/locales/id.yml +++ b/crates/clash-verge-i18n/locales/id.yml @@ -70,8 +70,6 @@ tray: global: Global profiles: Profil proxies: Proksi - testLatency: Uji Latensi - testingLatency: Menguji latensi… systemProxy: Proksi Sistem tunMode: Mode TUN closeAllConnections: Tutup Semua Koneksi diff --git a/crates/clash-verge-i18n/locales/jp.yml b/crates/clash-verge-i18n/locales/jp.yml index 327383e8b..9817405e6 100644 --- a/crates/clash-verge-i18n/locales/jp.yml +++ b/crates/clash-verge-i18n/locales/jp.yml @@ -70,8 +70,6 @@ tray: global: グローバル profiles: プロファイル proxies: プロキシ - testLatency: 遅延テスト - testingLatency: 遅延をテスト中… systemProxy: システムプロキシ tunMode: TUN モード closeAllConnections: すべての接続を閉じる diff --git a/crates/clash-verge-i18n/locales/ko.yml b/crates/clash-verge-i18n/locales/ko.yml index 9fcaa6a79..241d0d327 100644 --- a/crates/clash-verge-i18n/locales/ko.yml +++ b/crates/clash-verge-i18n/locales/ko.yml @@ -70,8 +70,6 @@ tray: global: 글로벌 profiles: 프로필 proxies: 프록시 - testLatency: 지연 테스트 - testingLatency: 지연 테스트 중… systemProxy: 시스템 프록시 tunMode: TUN 모드 closeAllConnections: 모든 연결 닫기 diff --git a/crates/clash-verge-i18n/locales/pt.yml b/crates/clash-verge-i18n/locales/pt.yml index 5999d1b91..2373529ee 100644 --- a/crates/clash-verge-i18n/locales/pt.yml +++ b/crates/clash-verge-i18n/locales/pt.yml @@ -70,8 +70,6 @@ tray: global: Global profiles: Perfis proxies: Proxies - testLatency: Test Latency - testingLatency: Testing latency… systemProxy: Proxy do sistema tunMode: Modo TUN closeAllConnections: Fechar todas as conexões diff --git a/crates/clash-verge-i18n/locales/ru.yml b/crates/clash-verge-i18n/locales/ru.yml index 630366a8f..985b9d1e6 100644 --- a/crates/clash-verge-i18n/locales/ru.yml +++ b/crates/clash-verge-i18n/locales/ru.yml @@ -70,8 +70,6 @@ tray: global: Глобальный profiles: Профили proxies: Прокси - testLatency: Проверить задержку - testingLatency: Проверка задержки… systemProxy: Системный прокси tunMode: Режим TUN closeAllConnections: Закрыть все соединения diff --git a/crates/clash-verge-i18n/locales/tr.yml b/crates/clash-verge-i18n/locales/tr.yml index 3ced8c82d..0d0f0c945 100644 --- a/crates/clash-verge-i18n/locales/tr.yml +++ b/crates/clash-verge-i18n/locales/tr.yml @@ -70,8 +70,6 @@ tray: global: Küresel profiles: Profiller proxies: Vekil'ler - testLatency: Gecikmeyi Test Et - testingLatency: Gecikme test ediliyor… systemProxy: Sistem Vekil'i tunMode: TUN Modu closeAllConnections: Tüm Bağlantıları Kapat diff --git a/crates/clash-verge-i18n/locales/tt.yml b/crates/clash-verge-i18n/locales/tt.yml index 2f067cc07..c136061ae 100644 --- a/crates/clash-verge-i18n/locales/tt.yml +++ b/crates/clash-verge-i18n/locales/tt.yml @@ -70,8 +70,6 @@ tray: global: Глобаль profiles: Профильләр proxies: Проксилар - testLatency: Кичектерүне тикшерү - testingLatency: Кичектерү тикшерелә… systemProxy: Системалы прокси tunMode: TUN режимы closeAllConnections: Барлык тоташуларны ябу diff --git a/crates/clash-verge-i18n/locales/zh.yml b/crates/clash-verge-i18n/locales/zh.yml index dbb40569b..d87c1e2f0 100644 --- a/crates/clash-verge-i18n/locales/zh.yml +++ b/crates/clash-verge-i18n/locales/zh.yml @@ -70,8 +70,6 @@ tray: global: 全局 profiles: 订阅 proxies: 代理 - testLatency: 测试延迟 - testingLatency: 正在测试延迟… systemProxy: 系统代理 tunMode: TUN 模式 closeAllConnections: 关闭所有连接 diff --git a/crates/clash-verge-i18n/locales/zhtw.yml b/crates/clash-verge-i18n/locales/zhtw.yml index ccf2ab2ac..b6baa3adb 100644 --- a/crates/clash-verge-i18n/locales/zhtw.yml +++ b/crates/clash-verge-i18n/locales/zhtw.yml @@ -70,8 +70,6 @@ tray: global: 全域 profiles: 訂閱 proxies: 代理 - testLatency: 測試延遲 - testingLatency: 正在測試延遲… systemProxy: 系統代理 tunMode: 虛擬網路介面卡模式 closeAllConnections: 關閉所有連線 diff --git a/src-tauri/src/cmd/profile.rs b/src-tauri/src/cmd/profile.rs index 3448d1502..6b36e0fc9 100644 --- a/src-tauri/src/cmd/profile.rs +++ b/src-tauri/src/cmd/profile.rs @@ -372,8 +372,6 @@ pub struct ProfilePatch { #[specta(type = Option)] pub url: Option, pub selected: Option>, - #[specta(type = Option>)] - pub latency_test_urls: Option>, pub extra: Option, pub updated: Option, pub option: Option, @@ -388,7 +386,6 @@ impl From for PrfItem { file: patch.file, url: patch.url, selected: patch.selected, - latency_test_urls: patch.latency_test_urls, extra: patch.extra, updated: patch.updated, option: patch.option, diff --git a/src-tauri/src/cmd/proxy.rs b/src-tauri/src/cmd/proxy.rs index f20d0b6b6..aa5521833 100644 --- a/src-tauri/src/cmd/proxy.rs +++ b/src-tauri/src/cmd/proxy.rs @@ -108,32 +108,20 @@ fn runtime_group_scopes(config: Option<&Mapping>) -> BTreeMap CmdResult { - proxy_view(None).await -} - -pub(crate) async fn proxy_view(provider_timeout: Option) -> CmdResult { let runtime = Config::runtime().await; let latest_runtime = runtime.latest_arc(); let runtime_group_order = runtime_group_order(latest_runtime.config.as_ref()); let group_scopes = runtime_group_scopes(latest_runtime.config.as_ref()); let mihomo = Handle::mihomo(); - let (proxies, providers) = tokio::join!(mihomo.get_proxies(), async { - match provider_timeout { - Some(timeout) => tokio::time::timeout(timeout, mihomo.get_proxy_providers()) - .await - .ok() - .and_then(Result::ok), - None => mihomo.get_proxy_providers().await.ok(), - } - }); + let (proxies, providers) = tokio::join!(mihomo.get_proxies(), mihomo.get_proxy_providers(),); let proxies = proxies.stringify_err()?; Ok(ProxyViewBuilder::build(ProxyViewInput { runtime_group_order, group_scopes, proxies, - providers, + providers: providers.ok(), })) } diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs index 0c99355d5..da8728d21 100644 --- a/src-tauri/src/config/prfitem.rs +++ b/src-tauri/src/config/prfitem.rs @@ -53,10 +53,6 @@ pub struct PrfItem { #[serde(skip_serializing_if = "Option::is_none")] pub selected: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - #[specta(type = Option>)] - pub latency_test_urls: Option>, - #[serde(skip_serializing_if = "Option::is_none")] pub extra: Option, @@ -233,7 +229,6 @@ impl PrfItem { desc: Some(desc), file: Some(file), url: None, - latency_test_urls: None, selected: None, extra: None, option: Some(PrfOption { @@ -413,7 +408,6 @@ impl PrfItem { desc: desc.cloned(), file: Some(file), url: Some(url.as_str().into()), - latency_test_urls: None, selected: None, extra, option: Some(PrfOption { diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index 7680fff58..4b149b716 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -250,7 +250,6 @@ impl IProfiles { patch!(each, item, file); patch!(each, item, url); patch!(each, item, selected); - patch!(each, item, latency_test_urls); patch!(each, item, extra); patch!(each, item, updated); patch!(each, item, option); diff --git a/src-tauri/src/core/proxy_view.rs b/src-tauri/src/core/proxy_view.rs index 54d488fc0..0fe394280 100644 --- a/src-tauri/src/core/proxy_view.rs +++ b/src-tauri/src/core/proxy_view.rs @@ -1,8 +1,8 @@ -use std::collections::{BTreeMap, BTreeSet, HashMap}; +use std::collections::{BTreeMap, BTreeSet}; -use serde::{Serialize, Serializer, ser::SerializeMap as _}; +use serde::Serialize; use tauri_plugin_mihomo::models::{ - DelayHistory, Extra, Proxies, Proxy, ProxyProvider, ProxyProviders, ProxyType, VehicleType, + DelayHistory, Proxies, Proxy, ProxyProvider, ProxyProviders, ProxyType, VehicleType, }; pub struct ProxyViewInput { @@ -57,28 +57,6 @@ pub struct ProxyCapabilities { pub smux: bool, } -#[derive(Serialize, specta::Type)] -struct ProxyLatencyHistory<'a> { - #[specta(type = Vec)] - history: &'a [DelayHistory], -} - -fn serialize_proxy_latency_history( - extra: &HashMap, - serializer: S, -) -> Result { - let mut map = serializer.serialize_map(Some(extra.len()))?; - for (url, extra) in extra { - map.serialize_entry( - url, - &ProxyLatencyHistory { - history: &extra.history, - }, - )?; - } - map.end() -} - #[derive(Debug, PartialEq, Eq, Serialize, specta::Type)] #[serde(rename_all = "camelCase")] pub struct ProxyGroupView { @@ -98,9 +76,6 @@ pub struct ProxyGroupView { pub test_url: Option, #[specta(type = Vec)] pub history: Vec, - #[serde(serialize_with = "serialize_proxy_latency_history")] - #[specta(type = HashMap>)] - pub extra: HashMap, #[serde(flatten)] pub capabilities: ProxyCapabilities, pub members: Vec, @@ -116,9 +91,6 @@ pub struct ProxyNodeView { pub proxy_type: ProxyType, #[specta(type = Vec)] pub history: Vec, - #[serde(serialize_with = "serialize_proxy_latency_history")] - #[specta(type = HashMap>)] - pub extra: HashMap, #[serde(skip_serializing_if = "Option::is_none")] pub id: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -284,7 +256,7 @@ impl ProxyViewBuilder { } else { ProxyViewProviderState::Unavailable }; - let (mut core_groups, core_nodes) = partition_core(proxies, providers.is_some()); + let (mut core_groups, core_nodes) = partition_core(proxies); let (mut records, core_node_ids) = build_core_records(core_nodes); let (providers, provider_candidates) = build_provider_records(providers, &mut records); let resolver = MemberResolver { @@ -317,14 +289,14 @@ impl ProxyViewBuilder { } } -fn partition_core(proxies: Proxies, providers_available: bool) -> (BTreeMap, BTreeMap) { +fn partition_core(proxies: Proxies) -> (BTreeMap, BTreeMap) { let mut groups = BTreeMap::new(); let mut nodes = BTreeMap::new(); for (name, proxy) in proxies.proxies { if proxy.all.is_some() { groups.insert(name, proxy); - } else if !providers_available || proxy.provider_name.is_empty() { + } else { nodes.insert(name, proxy); } } @@ -431,7 +403,6 @@ fn build_group(name: String, proxy: Proxy, resolver: &MemberResolver<'_>) -> Pro now, test_url, history, - extra, udp, xudp, tfo, @@ -464,7 +435,6 @@ fn build_group(name: String, proxy: Proxy, resolver: &MemberResolver<'_>) -> Pro icon, test_url, history, - extra, capabilities: ProxyCapabilities { udp, xudp, @@ -483,7 +453,6 @@ fn build_node(record_id: String, name: String, proxy: Proxy, source: ProxyNodeSo icon, test_url, history, - extra, udp, xudp, tfo, @@ -498,7 +467,6 @@ fn build_node(record_id: String, name: String, proxy: Proxy, source: ProxyNodeSo name, proxy_type, history, - extra, id, hidden, icon, @@ -552,62 +520,3 @@ fn build_standalone(core_node_ids: &BTreeMap) -> Vec { ); standalone } - -#[cfg(test)] -mod tests { - use super::*; - use serde_json::json; - - #[test] - fn provider_echo_in_proxies_does_not_override_group_membership() -> anyhow::Result<()> { - let view = ProxyViewBuilder::build(ProxyViewInput { - runtime_group_order: vec!["A".into(), "B".into()], - group_scopes: ["A", "B"] - .into_iter() - .map(|name| { - ( - name.into(), - GroupScope { - providers: vec![name.into()], - exclude_types: vec![], - }, - ) - }) - .collect(), - proxies: serde_json::from_value(json!({"proxies": { - "A": {"all": ["node"], "type": "Selector"}, - "B": {"all": ["node"], "type": "Selector"}, - "node": {"name": "node", "provider-name": "A", "history": [{"time": "2026-10-08T00:00:00Z", "delay": 32}]} - }}))?, - providers: Some(serde_json::from_value(json!({"providers": { - "A": {"vehicleType": "Inline", "proxies": [{"name": "node", "history": [{"time": "2026-10-08T00:00:00Z", "delay": 32}]}]}, - "B": {"vehicleType": "Inline", "proxies": [{"name": "node", "history": [{"time": "2026-10-08T00:00:00Z", "delay": 123}]}]} - }}))?), - }); - for (group, expected) in view.groups.iter().zip([32, 123]) { - let ProxyMemberRef::Node { record_id, .. } = &group.members[0] else { - anyhow::bail!("Expected node") - }; - let record = &view.records[record_id]; - assert_eq!(record.history.last().map(|entry| entry.delay), Some(expected)); - assert!( - matches!(&record.source, ProxyNodeSource::Provider { provider_name, .. } if provider_name == &group.name) - ); - } - Ok(()) - } - #[test] - fn unavailable_provider_keeps_core_echo_interactable() -> anyhow::Result<()> { - let view = ProxyViewBuilder::build(ProxyViewInput { - runtime_group_order: vec!["A".into()], - group_scopes: BTreeMap::new(), - proxies: serde_json::from_value(json!({"proxies": { - "A": {"all": ["node"], "type": "Selector"}, - "node": {"name": "node", "provider-name": "provider"} - }}))?, - providers: None, - }); - assert!(matches!(&view.groups[0].members[0], ProxyMemberRef::Node { .. })); - Ok(()) - } -} diff --git a/src-tauri/src/core/tray/latency.rs b/src-tauri/src/core/tray/latency.rs deleted file mode 100644 index 5c1106ede..000000000 --- a/src-tauri/src/core/tray/latency.rs +++ /dev/null @@ -1,156 +0,0 @@ -use super::Tray; -use crate::{ - Type, cmd, - config::Config, - core::{ - handle, - notify::{Refresh, announce}, - proxy_view::{ProxyMemberRef, ProxyNodeSource}, - }, - logging, -}; - -const TRAY_DELAY_TEST_CONCURRENCY: usize = 10; -const TRAY_DEFAULT_LATENCY_URL: &str = "http://cp.cloudflare.com/generate_204"; - -fn is_latency_test_url(raw: &str) -> bool { - let raw = raw.trim(); - raw.split_once("://") - .is_some_and(|(scheme, _)| scheme.eq_ignore_ascii_case("http") || scheme.eq_ignore_ascii_case("https")) - && tauri::Url::parse(raw).is_ok_and(|url| url.has_host() && matches!(url.scheme(), "http" | "https")) -} - -pub(super) fn test_url( - group: &crate::core::proxy_view::ProxyGroupView, - verge: &crate::config::IVerge, - profiles: &crate::config::IProfiles, -) -> String { - let custom_url = profiles - .current - .as_ref() - .and_then(|uid| profiles.get_item(uid).ok()) - .and_then(|profile| profile.latency_test_urls.as_ref()) - .and_then(|urls| urls.get(group.name.as_str())) - .map(|url| url.as_str()) - .filter(|url| !url.trim().is_empty()); - let group_url = group.test_url.as_deref().filter(|url| !url.trim().is_empty()); - let default_url = verge - .default_latency_test - .as_deref() - .filter(|url| !url.trim().is_empty()); - custom_url - .or(group_url) - .or(default_url) - .filter(|&url| is_latency_test_url(url)) - .unwrap_or(TRAY_DEFAULT_LATENCY_URL) - .trim() - .to_owned() -} - -static RUNNING: parking_lot::Mutex> = - parking_lot::Mutex::new(std::collections::BTreeSet::new()); - -pub(super) fn is_running(group_name: &str) -> bool { - RUNNING.lock().contains(group_name) -} - -pub(super) async fn test_proxy_group_delay(group_name: &str) { - if !RUNNING.lock().insert(group_name.to_owned()) { - return; - } - Tray::global().refresh_latency_item(group_name); - let _running = scopeguard::guard(group_name, |name| { - RUNNING.lock().remove(name); - Tray::global().refresh_latency_item(name); - }); - use futures::{StreamExt as _, stream}; - - let view = match cmd::proxy::get_proxy_view().await { - Ok(view) => view, - Err(err) => { - logging!(warn, Type::Tray, "Failed to read proxies for tray latency test: {err}"); - return; - } - }; - let verge = Config::verge().await.latest_arc(); - - let group = view - .groups - .iter() - .chain(view.global.iter()) - .find(|group| group.name.as_str() == group_name); - let Some(group) = group else { - logging!(warn, Type::Tray, "Tray latency test group not found: {group_name}"); - return; - }; - - let profiles = Config::profiles().await.latest_arc(); - let url = test_url(group, &verge, &profiles); - let timeout = verge - .default_latency_timeout - .filter(|timeout| *timeout > 0) - .unwrap_or(10000) as u32; - - let mut targets: Vec<(std::string::String, Option)> = Vec::with_capacity(group.members.len()); - for member in &group.members { - match member { - ProxyMemberRef::Node { name, record_id } => match view.records.get(record_id).map(|node| &node.source) { - Some(ProxyNodeSource::Provider { - provider_name, - proxy_name, - }) => targets.push((proxy_name.clone(), Some(provider_name.clone()))), - _ => targets.push((name.clone(), None)), - }, - ProxyMemberRef::Group { name } => targets.push((name.clone(), None)), - ProxyMemberRef::Unresolved { .. } => {} - } - } - let mihomo = handle::Handle::mihomo(); - - stream::iter(targets.into_iter().map(move |(member, provider)| { - let url = url.clone(); - async move { - let result = match provider { - Some(provider_name) => { - mihomo - .healthcheck_node_in_provider(&provider_name, &member, &url, timeout) - .await - } - None => mihomo.delay_proxy_by_name(&member, &url, timeout).await, - }; - if let Err(err) = result { - logging!(debug, Type::Tray, "Tray latency test failed: {member} - {err}"); - } - } - })) - .buffer_unordered(TRAY_DELAY_TEST_CONCURRENCY) - .for_each(|()| std::future::ready(())) - .await; - - if let Err(err) = cmd::proxy::sync_tray_proxy_selection().await { - logging!(warn, Type::Tray, "Failed to refresh tray after latency test: {err}"); - } - - announce(Refresh::Proxies); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn latency_urls_require_a_valid_http_host_and_port() { - for invalid in [ - "http://?", - "http://host:invalid", - "http://bad host/", - "ftp://localhost", - "http:localhost", - ] { - assert!(!is_latency_test_url(invalid), "{invalid}"); - } - for valid in ["http://localhost/", " https://example.com/ ", "HTTP://localhost:8080/"] { - assert!(is_latency_test_url(valid), "{valid}"); - } - } -} diff --git a/src-tauri/src/core/tray/menu_def.rs b/src-tauri/src/core/tray/menu_def.rs index 6c9641773..7012ce219 100644 --- a/src-tauri/src/core/tray/menu_def.rs +++ b/src-tauri/src/core/tray/menu_def.rs @@ -32,7 +32,6 @@ define_menu! { outbound_modes => OUTBOUND_MODES, "tray_outbound_modes", "tray.outboundModes", profiles => PROFILES, "tray_profiles", "tray.profiles", proxies => PROXIES, "tray_proxies", "tray.proxies", - test_latency => TEST_LATENCY, "tray_test_latency", "tray.testLatency", system_proxy => SYSTEM_PROXY, "tray_system_proxy", "tray.systemProxy", tun_mode => TUN_MODE, "tray_tun_mode", "tray.tunMode", close_all_connections => CLOSE_ALL_CONNECTIONS, "tray_close_all_connections", "tray.closeAllConnections", diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index 221f23aa1..3d7f0aaf5 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -1,6 +1,5 @@ use crate::config::{IProfilePreview, IVerge}; use crate::core::lightweight; -use crate::core::proxy_view::{ProxyGroupView, ProxyMemberRef, ProxyNodeSource, ProxyViewProviderState, ProxyViewV1}; use crate::core::tray::menu_def::TrayAction; use crate::process::AsyncHandler; use crate::singleton; @@ -15,6 +14,7 @@ use crate::{ use clash_verge_limiter::{Limiter, SystemClock, SystemLimiter}; use clash_verge_logging::logging_error; use tauri::tray::{MouseButton, MouseButtonState, TrayIcon, TrayIconBuilder, TrayIconEvent}; +use tauri_plugin_mihomo::models::Proxies; use tokio::fs; use super::handle; @@ -28,7 +28,6 @@ use tauri::{ menu::{CheckMenuItem, IsMenuItem, MenuEvent, MenuItem, PredefinedMenuItem, Submenu}, }; -mod latency; mod menu_def; #[cfg(target_os = "macos")] mod speed_task; @@ -56,25 +55,8 @@ enum IconKind { Tun, } -struct LatencyMenuItem { - item: MenuItem, - running: bool, - proxies: Vec, - provider_state: ProxyViewProviderState, -} - -struct ProxyLatencyItem { - item: CheckMenuItem, - name: std::string::String, - provider_name: Option, - text: std::string::String, -} - pub struct Tray { limiter: SystemLimiter, - proxy_hover_limiter: SystemLimiter, - menu_update: tokio::sync::Mutex<()>, - latency_items: parking_lot::Mutex>, #[cfg(target_os = "macos")] speed_controller: speed_task::TraySpeedController, } @@ -148,9 +130,6 @@ impl Default for Tray { fn default() -> Self { Self { limiter: Limiter::new(Duration::from_millis(TRAY_CLICK_DEBOUNCE_MS), SystemClock), - proxy_hover_limiter: Limiter::new(Duration::from_secs(1), SystemClock), - menu_update: tokio::sync::Mutex::new(()), - latency_items: parking_lot::Mutex::new(HashMap::new()), #[cfg(target_os = "macos")] speed_controller: speed_task::TraySpeedController::new(), } @@ -216,7 +195,6 @@ impl Tray { } async fn update_menu_internal(&self, app_handle: &AppHandle, include_proxy_groups: bool) -> Result<()> { - let _update = self.menu_update.lock().await; let Some(tray) = app_handle.tray_by_id(TRAY_ID) else { logging!(warn, Type::Tray, "Failed to update tray menu: tray not found"); return Ok(()); @@ -241,133 +219,29 @@ impl Tray { let profiles_preview = profiles_arc.profiles_preview().unwrap_or_default(); let is_lightweight_mode = is_in_lightweight_mode(); - let (menu, latency_items) = create_tray_menu( - app_handle, - Some(mode.as_str()), - *system_proxy, - *tun_mode, - tun_mode_available, - profiles_preview, - TrayMenuOptions { - is_lightweight_mode, - include_proxy_groups, - }, - ) - .await?; - tray.set_menu(Some(menu))?; - let groups: Vec<_> = latency_items.keys().cloned().collect(); - *self.latency_items.lock() = latency_items; - for group in groups { - self.refresh_latency_item(&group); - } + logging_error!( + Type::Tray, + tray.set_menu(Some( + create_tray_menu( + app_handle, + Some(mode.as_str()), + *system_proxy, + *tun_mode, + tun_mode_available, + profiles_preview, + TrayMenuOptions { + is_lightweight_mode, + include_proxy_groups, + }, + ) + .await?, + )) + ); logging!(debug, Type::Tray, "托盘菜单更新成功"); Ok(()) } - async fn refresh_proxy_items(&'static self) { - let Ok(update) = self.menu_update.try_lock() else { - return; - }; - if self.latency_items.lock().is_empty() || handle::Handle::global().is_exiting() { - return; - } - let Ok(Ok(view)) = tokio::time::timeout( - Duration::from_secs(1), - cmd::proxy::proxy_view(Some(Duration::from_millis(750))), - ) - .await - else { - return; - }; - if self - .latency_items - .lock() - .values() - .any(|entry| entry.provider_state != view.provider_state) - { - // Provider fallback changes member identities; rebuild through the existing queue. - drop(update); - logging_error!(Type::Tray, cmd::proxy::sync_tray_proxy_selection().await); - return; - } - let verge = Config::verge().await.latest_arc(); - let profiles = Config::profiles().await.latest_arc(); - logging_error!( - Type::Tray, - handle::Handle::app_handle().run_on_main_thread(move || { - // Keep rebuilding serialized until these handles have received their snapshot. - let _update = update; - let mut items = self.latency_items.lock(); - for (group_name, entry) in items.iter_mut() { - let Some(group) = find_group(&view, group_name) else { - continue; - }; - let url = latency::test_url(group, &verge, &profiles); - let mut members = HashMap::with_capacity(group.members.len()); - for member in &group.members { - members - .entry((member_name(member), member_provider(&view, member))) - .or_insert(member); - } - for proxy in &mut entry.proxies { - let Some(member) = members.get(&(proxy.name.as_str(), proxy.provider_name.as_deref())) else { - continue; - }; - let text = proxy_item_text(&view, member, &url, &verge); - let checked = group.now.as_ref() == Some(&proxy.name); - if text != proxy.text { - match proxy.item.set_text(&text) { - Ok(()) => proxy.text = text, - Err(err) => logging!(warn, Type::Tray, "Failed to refresh proxy latency: {err}"), - } - } - match proxy.item.is_checked() { - Ok(current) if current != checked => { - logging_error!(Type::Tray, proxy.item.set_checked(checked)) - } - Err(err) => logging!(warn, Type::Tray, "Failed to read proxy selection: {err}"), - _ => {} - } - } - } - }) - ); - } - - fn refresh_latency_item(&self, group_name: &str) { - let group_name = group_name.to_owned(); - logging_error!( - Type::Tray, - handle::Handle::app_handle().run_on_main_thread(move || { - Self::global().refresh_latency_item_on_main_thread(&group_name); - }) - ); - } - - fn refresh_latency_item_on_main_thread(&self, group_name: &str) { - let running = latency::is_running(group_name); - let item = { - let mut items = self.latency_items.lock(); - items.get_mut(group_name).and_then(|entry| { - if entry.running == running { - return None; - } - entry.running = running; - Some(entry.item.clone()) - }) - }; - if let Some(item) = item { - let label = if running { - clash_verge_i18n::t!("tray.testingLatency") - } else { - clash_verge_i18n::t!("tray.testLatency") - }; - logging_error!(Type::Tray, item.set_text(label)); - logging_error!(Type::Tray, item.set_enabled(!running)); - } - } - pub async fn update_icon(&self, verge: &IVerge) -> Result<()> { if handle::Handle::global().is_exiting() { logging!(debug, Type::Tray, "应用正在退出,跳过托盘图标更新"); @@ -583,175 +457,96 @@ fn create_profile_menu_item( .collect() } -const UNTESTED_DELAY_TEXT: &str = "-ms"; -const TIMEOUT_DELAY_TEXT: &str = "T/O"; -const TRAY_GROUP_DEPTH_LIMIT: usize = 8; - -const fn member_name(member: &ProxyMemberRef) -> &str { - match member { - ProxyMemberRef::Node { name, .. } - | ProxyMemberRef::Group { name } - | ProxyMemberRef::Unresolved { name, .. } => name.as_str(), - } -} - -fn find_group<'a>(view: &'a ProxyViewV1, name: &str) -> Option<&'a ProxyGroupView> { - view.groups - .iter() - .chain(view.global.iter()) - .find(|group| group.name.as_str() == name) -} - -/// The delay recorded for `url`, falling back to the node's latest measurement under any URL, so a -/// node the core tested on its own still shows a value. -fn node_delay(view: &ProxyViewV1, record_id: &str, url: &str) -> Option { - view.records - .get(record_id) - .map(|node| node.extra.get(url).map_or(&node.history, |extra| &extra.history)) - .and_then(|history| history.last()) - .map(|history| history.delay) -} - -/// A group row shows the delay of the node the group currently selects. The core never writes a -/// history for the group itself, so `now` is followed until the chain reaches a node. -fn selected_member_delay(view: &ProxyViewV1, group_name: &str, url: &str) -> Option { - let mut current = group_name; - for _ in 0..TRAY_GROUP_DEPTH_LIMIT { - let Some(group) = find_group(view, current) else { break }; - let Some(now) = group.now.as_deref().filter(|now| !now.is_empty() && *now != current) else { - break; - }; - let Some(member) = group.members.iter().find(|member| member_name(member) == now) else { - break; - }; - match member { - ProxyMemberRef::Node { record_id, .. } => return node_delay(view, record_id, url), - ProxyMemberRef::Group { name } => current = name.as_str(), - ProxyMemberRef::Unresolved { .. } => break, - } - } - find_group(view, group_name) - .map(|group| group.extra.get(url).map_or(&group.history, |extra| &extra.history)) - .and_then(|history| history.last()) - .map(|history| history.delay) -} - -fn member_provider<'a>(view: &'a ProxyViewV1, member: &ProxyMemberRef) -> Option<&'a str> { - let ProxyMemberRef::Node { record_id, .. } = member else { - return None; - }; - match &view.records.get(record_id)?.source { - ProxyNodeSource::Provider { provider_name, .. } => Some(provider_name), - ProxyNodeSource::Core { .. } => None, - } -} - -fn proxy_item_text(view: &ProxyViewV1, member: &ProxyMemberRef, url: &str, verge: &IVerge) -> std::string::String { - let timeout = verge - .default_latency_timeout - .filter(|timeout| *timeout > 0) - .unwrap_or(10000); - let delay = match member { - ProxyMemberRef::Node { record_id, .. } => node_delay(view, record_id, url), - ProxyMemberRef::Group { name } => selected_member_delay(view, name, url), - ProxyMemberRef::Unresolved { .. } => None, - }; - let delay_text = delay.map_or_else( - || UNTESTED_DELAY_TEXT.to_owned(), - |delay| { - if delay == 0 || u32::from(delay) >= timeout as u32 { - TIMEOUT_DELAY_TEXT.to_owned() - } else { - format!("{delay}ms") - } - }, - ); - format!("{} | {delay_text}", member_name(member)) -} - fn create_subcreate_proxy_menu_item( app_handle: &AppHandle, proxy_mode: &str, - view: Option, - latency_items: &mut HashMap, - texts: &MenuTexts, - verge: &IVerge, - profiles: &crate::config::IProfiles, + proxy_group_order_map: Option>, + proxy_nodes_data: Option, ) -> Vec> { - let Some(view) = view else { return Vec::new() }; - view.groups - .iter() - .chain(view.global.iter()) - .filter_map(|group| { - if group.hidden.unwrap_or_default() || (proxy_mode == "global") != (group.name == "GLOBAL") { - return None; - } - let url = latency::test_url(group, verge, profiles); - let proxies: Vec = group - .members - .iter() - .filter_map(|member| { - let name = member_name(member); - let text = proxy_item_text(&view, member, &url, verge); - let checked = group.now.as_deref() == Some(name); - CheckMenuItem::with_id( - app_handle, - format!("proxy_{}_{}", group.name, name), - &text, - true, - checked, - None::<&str>, - ) - .map(|item| ProxyLatencyItem { - item, - name: name.to_owned(), - provider_name: member_provider(&view, member).map(str::to_owned), - text, + let proxy_submenus: Vec> = { + let mut submenus: Vec<(String, usize, Submenu)> = Vec::new(); + + // TODO: 应用启动时,内核还未启动完全,无法获取代理节点信息 + if let Some(proxy_nodes_data) = proxy_nodes_data { + for (group_name, group_data) in proxy_nodes_data.proxies.iter() { + let should_show = match proxy_mode { + "global" => group_name == "GLOBAL", + _ => group_name != "GLOBAL", + } && !group_data.hidden.unwrap_or_default(); + + if !should_show { + continue; + } + + let Some(all_proxies) = group_data.all.as_ref() else { + continue; + }; + + let now_proxy = group_data.now.as_deref().unwrap_or_default(); + + let group_items: Vec> = all_proxies + .iter() + .filter_map(|proxy_str| { + let is_selected = *proxy_str == now_proxy; + let item_id = format!("proxy_{}_{}", group_name, proxy_str); + + let delay_text = proxy_nodes_data + .proxies + .get(proxy_str) + .and_then(|h| h.history.last()) + .map(|h| match h.delay { + 0 => "-ms".into(), + delay if delay >= 10000 => "-ms".into(), + _ => format!("{}ms", h.delay), + }) + .unwrap_or_else(|| "-ms".into()); + + let display_text = format!("{} | {}", proxy_str, delay_text); + + CheckMenuItem::with_id(app_handle, item_id, display_text, true, is_selected, None::<&str>) + .map_err(|e| logging!(warn, Type::Tray, "Failed to create proxy menu item: {}", e)) + .ok() }) - .map_err(|e| logging!(warn, Type::Tray, "Failed to create proxy menu item: {e}")) - .ok() - }) - .collect(); - let group_items: Vec<_> = proxies.iter().map(|proxy| proxy.item.clone()).collect(); - if group_items.is_empty() { - return None; - } - let running = latency::is_running(&group.name); - let test_item = MenuItem::with_id( - app_handle, - format!("{}_{}", MenuIds::TEST_LATENCY, group.name), - if running { - clash_verge_i18n::t!("tray.testingLatency") + .collect(); + + if group_items.is_empty() { + continue; + } + + let group_display_name = group_name.to_string(); + + let group_items_refs: Vec<&dyn IsMenuItem> = + group_items.iter().map(|item| item as &dyn IsMenuItem).collect(); + + if let Ok(submenu) = Submenu::with_id_and_items( + app_handle, + format!("proxy_group_{}", group_name), + group_display_name, + true, + &group_items_refs, + ) { + let insertion_index = submenus.len(); + submenus.push((group_name.into(), insertion_index, submenu)); } else { - texts.test_latency.clone() - }, - !running, - None::<&str>, - ) - .ok()?; - latency_items.insert( - group.name.clone(), - LatencyMenuItem { - item: test_item.clone(), - running, - proxies, - provider_state: view.provider_state, - }, - ); - let separator = PredefinedMenuItem::separator(app_handle).ok()?; - let mut items: Vec<&dyn IsMenuItem> = vec![&test_item, &separator]; - items.extend(group_items.iter().map(|item| item as &dyn IsMenuItem)); - Submenu::with_id_and_items( - app_handle, - format!("proxy_group_{}", group.name), - &group.name, - true, - &items, - ) - .map_err(|e| logging!(warn, Type::Tray, "Failed to create proxy group submenu: {e}")) - .ok() - }) - .collect() + logging!(warn, Type::Tray, "Failed to create proxy group submenu: {}", group_name); + } + } + } + + if let Some(order_map) = proxy_group_order_map.as_ref() { + submenus.sort_by(|(name_a, original_index_a, _), (name_b, original_index_b, _)| { + match (order_map.get(name_a), order_map.get(name_b)) { + (Some(index_a), Some(index_b)) => index_a.cmp(index_b), + (Some(_), None) => std::cmp::Ordering::Less, + (None, Some(_)) => std::cmp::Ordering::Greater, + (None, None) => original_index_a.cmp(original_index_b), + } + }); + } + + submenus.into_iter().map(|(_, _, submenu)| submenu).collect() + }; + proxy_submenus } fn create_proxy_menu_item( @@ -798,38 +593,54 @@ async fn create_tray_menu( tun_mode_available: bool, profiles_preview: Vec>, options: TrayMenuOptions, -) -> Result<(tauri::menu::Menu, HashMap)> { +) -> Result> { let current_proxy_mode = mode.unwrap_or(""); let mut verge_settings = Config::verge().await.latest_arc(); let fetch_proxy_groups = options.include_proxy_groups && verge_settings.tray_proxy_groups_display_mode.as_deref() != Some("disable"); - // Proxy data must remain optional so a stopped Core cannot roll back unrelated settings. - let proxy_view = if fetch_proxy_groups { - tokio::time::timeout( - Duration::from_millis(1000), - cmd::proxy::proxy_view(Some(Duration::from_millis(750))), - ) - .await - .ok() - .and_then(Result::ok) + // TODO: should update tray menu again when it was timeout error + let (proxy_nodes_data, runtime_proxy_groups_order) = if fetch_proxy_groups { + let proxy_nodes_data = + tokio::time::timeout(Duration::from_millis(1000), handle::Handle::mihomo().get_proxies()) + .await + .map_or(None, |res| res.ok()); + + let runtime = Config::runtime().await.latest_arc(); + let runtime_proxy_groups_order = runtime.config.as_ref().map(|config| { + config + .get("proxy-groups") + .and_then(|groups| groups.as_sequence()) + .map(|groups| { + groups + .iter() + .filter_map(|group| group.get("name")) + .filter_map(|name| name.as_str()) + .enumerate() + .map(|(index, name)| (name.into(), index)) + .collect::>() + }) + .unwrap_or_default() + }); + + (proxy_nodes_data, runtime_proxy_groups_order) } else { - None + (None, None) }; if fetch_proxy_groups { verge_settings = Config::verge().await.latest_arc(); } - let profiles_config = Config::profiles().await.latest_arc(); - let tray_proxy_groups_display_mode = verge_settings .tray_proxy_groups_display_mode .as_deref() .unwrap_or("default"); let include_proxy_groups = options.include_proxy_groups && tray_proxy_groups_display_mode != "disable"; + let proxy_group_order_map = runtime_proxy_groups_order; + let show_outbound_modes_inline = verge_settings.tray_inline_outbound_modes.unwrap_or(false); let version = env!("CARGO_PKG_VERSION"); @@ -909,17 +720,9 @@ async fn create_tray_menu( &profile_menu_items_refs, )?; - let mut latency_items = HashMap::new(); let (proxies_menu, inline_proxy_items) = if include_proxy_groups { - let proxy_sub_menus = create_subcreate_proxy_menu_item( - app_handle, - current_proxy_mode, - proxy_view, - &mut latency_items, - &texts, - &verge_settings, - &profiles_config, - ); + let proxy_sub_menus = + create_subcreate_proxy_menu_item(app_handle, current_proxy_mode, proxy_group_order_map, proxy_nodes_data); match tray_proxy_groups_display_mode { "default" => create_proxy_menu_item(app_handle, false, proxy_sub_menus, &texts.proxies)?, @@ -1063,25 +866,10 @@ async fn create_tray_menu( ]); let menu = tauri::menu::MenuBuilder::new(app_handle).items(&menu_items).build()?; - Ok((menu, latency_items)) + Ok(menu) } fn on_tray_icon_event(_tray_icon: &TrayIcon, tray_event: TrayIconEvent) { - let refresh_proxies = match tray_event { - TrayIconEvent::Enter { .. } => Tray::global().proxy_hover_limiter.check(), - TrayIconEvent::Click { - button: MouseButton::Left | MouseButton::Right, - button_state: MouseButtonState::Down, - .. - } => true, - _ => false, - }; - if refresh_proxies { - AsyncHandler::spawn(|| async { - Tray::global().refresh_proxy_items().await; - }); - } - if matches!( tray_event, TrayIconEvent::Move { .. } | TrayIconEvent::Leave { .. } | TrayIconEvent::Enter { .. } @@ -1203,15 +991,6 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) { }; feat::toggle_proxy_profile(profile_index.into()).await; } - id if id.starts_with(MenuIds::TEST_LATENCY) => { - let group_name = id - .strip_prefix(MenuIds::TEST_LATENCY) - .and_then(|rest| rest.strip_prefix('_')); - if let Some(group_name) = group_name { - logging!(info, Type::Tray, "Tray menu: test group latency {}", group_name); - latency::test_proxy_group_delay(group_name).await; - } - } id if id.starts_with("proxy_") => { let rest = match id.strip_prefix("proxy_") { Some(r) => r, diff --git a/src/components/home/current-proxy-card.tsx b/src/components/home/current-proxy-card.tsx index c7145b05f..4b891a623 100644 --- a/src/components/home/current-proxy-card.tsx +++ b/src/components/home/current-proxy-card.tsx @@ -47,10 +47,7 @@ import { useCoreDataStatus, useProxiesData, } from '@/providers/app-data-context' -import { syncTrayProxySelection } from '@/services/cmds' import delayManager from '@/services/delay' -import { mutate } from '@/services/mutate' -import { profileTestUrls } from '@/services/proxy-test-url' import { findCurrentGroupMember, getRecord, @@ -678,20 +675,6 @@ export const CurrentProxyCard = () => { [proxyView], ) - useEffect(() => { - if (!selectedGroup) return - const customUrl = currentProfile - ? profileTestUrls(currentProfile)[selectedGroup.name] - : undefined - delayManager.setUrl( - selectedGroup.name, - customUrl?.trim() || - selectedGroup.testUrl?.trim() || - verge?.default_latency_test?.trim() || - 'http://cp.cloudflare.com/generate_204', - ) - }, [selectedGroup, currentProfile, verge?.default_latency_test]) - const unsortedProxyOptions = useMemo( () => optionsForGroup(selectedGroup), [optionsForGroup, selectedGroup], @@ -924,12 +907,6 @@ export const CurrentProxyCard = () => { } refreshProxy() - mutate(() => syncTrayProxySelection(), { - id: 'sync-tray-selection', - errorNotice: false, - }).catch((error) => { - console.error('[CurrentProxyCard] Failed to sync tray latency:', error) - }) }) const proxyOptions = useMemo( diff --git a/src/components/proxy/proxy-group-tools.tsx b/src/components/proxy/proxy-group-tools.tsx index 194b1cde4..44cc8a3da 100644 --- a/src/components/proxy/proxy-group-tools.tsx +++ b/src/components/proxy/proxy-group-tools.tsx @@ -9,7 +9,7 @@ import VisibilityOffRounded from '@mui/icons-material/VisibilityOffRounded' import VisibilityRounded from '@mui/icons-material/VisibilityRounded' import WifiTetheringOffRounded from '@mui/icons-material/WifiTetheringOffRounded' import WifiTetheringRounded from '@mui/icons-material/WifiTetheringRounded' -import { Box, IconButton, type SxProps } from '@mui/material' +import { Box, IconButton, type SxProps, TextField } from '@mui/material' import { useDebounceFn } from 'ahooks' import { memo, useEffect, useRef } from 'react' import { flushSync } from 'react-dom' @@ -18,11 +18,10 @@ import { useTranslation } from 'react-i18next' import { useVerge } from '@/hooks/use-verge' import delayManager from '@/services/delay' import { showNotice } from '@/services/notice-service' -import { isValidLatencyTestUrl } from '@/utils/network' +import { isValidUrl } from '@/utils/network' import { BaseSearchBox, type SearchState } from '../base' -import { ProxyTestUrlInput } from './proxy-test-url-input' import type { ProxySortType } from './use-filter-sort' import type { HeadState } from './use-head-state' @@ -70,10 +69,7 @@ export const ProxyGroupTools = memo(function ProxyGroupTools(props: Props) { const inputRef = useRef(null) useEffect(() => { - delayManager.setUrl( - groupName, - testUrl?.trim() || url?.trim() || defaultLatencyUrl, - ) + delayManager.setUrl(groupName, testUrl?.trim() || url || defaultLatencyUrl) }, [groupName, testUrl, defaultLatencyUrl, url]) // 过滤输入是高频操作,且每次都会触发整组代理的重新过滤/排序与虚拟列表重渲染, @@ -116,8 +112,7 @@ export const ProxyGroupTools = memo(function ProxyGroupTools(props: Props) { )} {textState === 'url' && ( - onHeadState({ testUrl })} + onChange={(e) => onHeadState({ testUrl: e.target.value })} sx={{ flex: '1 1 auto', input: { py: 0.65, px: 1 } }} /> )} @@ -181,7 +176,7 @@ export const ProxyGroupTools = memo(function ProxyGroupTools(props: Props) { if (testUrl?.trim() && textState !== 'filter') { onHeadState({ textState: 'url' }) } - if (testUrl?.trim() && !isValidLatencyTestUrl(testUrl)) { + if (testUrl?.trim() && !isValidUrl(testUrl)) { showNotice.warning('proxies.feedback.warnings.invalidTestUrl') return } diff --git a/src/components/proxy/proxy-groups.tsx b/src/components/proxy/proxy-groups.tsx index 28e3b3e06..7a852543b 100644 --- a/src/components/proxy/proxy-groups.tsx +++ b/src/components/proxy/proxy-groups.tsx @@ -23,9 +23,7 @@ import { useProfiles } from '@/hooks/use-profiles' import { useProxySelection } from '@/hooks/use-proxy-selection' import { useVerge } from '@/hooks/use-verge' import { useProxiesData, useSystemData } from '@/providers/app-data-context' -import { syncTrayProxySelection } from '@/services/cmds' import delayManager from '@/services/delay' -import { mutate } from '@/services/mutate' import { isInteractableMember, resolveMember, @@ -145,12 +143,6 @@ function useProxyRenderState( console.error(`[ProxyGroups] 延迟测试出错,组: ${groupName}`, error) } finally { onProxies() - mutate(() => syncTrayProxySelection(), { - id: 'sync-tray-selection', - errorNotice: false, - }).catch((error) => { - console.error('[ProxyGroups] Failed to sync tray latency:', error) - }) } }), ) diff --git a/src/components/proxy/proxy-head.tsx b/src/components/proxy/proxy-head.tsx index 4fa9aefc7..4db54f36f 100644 --- a/src/components/proxy/proxy-head.tsx +++ b/src/components/proxy/proxy-head.tsx @@ -11,7 +11,7 @@ import { SortByAlphaRounded, SortRounded, } from '@mui/icons-material' -import { Box, IconButton, type SxProps } from '@mui/material' +import { Box, IconButton, TextField, type SxProps } from '@mui/material' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -20,9 +20,8 @@ import { useVerge } from '@/hooks/use-verge' import delayManager from '@/services/delay' import { showNotice } from '@/services/notice-service' import { debugLog } from '@/utils/debug' -import { isValidLatencyTestUrl } from '@/utils/network' +import { isValidUrl } from '@/utils/network' -import { ProxyTestUrlInput } from './proxy-test-url-input' import type { ProxySortType } from './use-filter-sort' import type { HeadState } from './use-head-state' @@ -73,10 +72,7 @@ export const ProxyHead = ({ 'http://cp.cloudflare.com/generate_204' useEffect(() => { - delayManager.setUrl( - groupName, - testUrl?.trim() || url?.trim() || defaultLatencyUrl, - ) + delayManager.setUrl(groupName, testUrl?.trim() || url || defaultLatencyUrl) }, [groupName, testUrl, defaultLatencyUrl, url]) return ( @@ -101,7 +97,7 @@ export const ProxyHead = ({ debugLog(`[ProxyHead] 使用自定义测试URL: ${testUrl}`) onHeadState({ textState: 'url' }) } - if (testUrl?.trim() && !isValidLatencyTestUrl(testUrl)) { + if (testUrl?.trim() && !isValidUrl(testUrl)) { showNotice.warning('proxies.feedback.warnings.invalidTestUrl') return } @@ -192,8 +188,7 @@ export const ProxyHead = ({ )} {textState === 'url' && ( - onHeadState({ testUrl })} + onChange={(e) => onHeadState({ testUrl: e.target.value })} sx={{ ml: 0.5, flex: '1 1 auto', input: { py: 0.65, px: 1 } }} /> )} diff --git a/src/components/proxy/proxy-test-url-input.tsx b/src/components/proxy/proxy-test-url-input.tsx deleted file mode 100644 index 287e2f0f5..000000000 --- a/src/components/proxy/proxy-test-url-input.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { TextField, type TextFieldProps } from '@mui/material' -import { useEffect, useEffectEvent, useRef, useState } from 'react' - -import { useProfiles } from '@/hooks/use-profiles' - -type Props = Omit & { - value: string - onCommit: (url: string) => void -} - -export const ProxyTestUrlInput = ({ value, name, ...props }: Props) => { - const { profiles } = useProfiles() - return ( - - ) -} - -const DraftTestUrlInput = ({ value, onCommit, ...props }: Props) => { - const [draft, setDraft] = useState(null) - const pendingRef = useRef(null) - const commitOnUnmount = useEffectEvent(() => { - if (pendingRef.current !== null && pendingRef.current !== value) - onCommit(pendingRef.current) - }) - useEffect(() => () => commitOnUnmount(), []) - - return ( - { - pendingRef.current = event.target.value - setDraft(event.target.value) - }} - onBlur={() => { - const next = pendingRef.current - pendingRef.current = null - setDraft(null) - if (next !== null && next !== value) onCommit(next) - }} - onKeyDown={(event) => { - if (event.key === 'Enter') { - event.preventDefault() - const input = event.target as HTMLInputElement - input.blur() - } - }} - /> - ) -} diff --git a/src/components/proxy/use-filter-sort.test.ts b/src/components/proxy/use-filter-sort.test.ts index dd5effc33..2f8d0d46e 100644 --- a/src/components/proxy/use-filter-sort.test.ts +++ b/src/components/proxy/use-filter-sort.test.ts @@ -13,17 +13,11 @@ const node = (memberIndex: number, delay: number, name = `${memberIndex}`) => kind: 'node', ref: { kind: 'node', name, recordId: `${memberIndex}` }, node: { - recordId: `${memberIndex}`, history: [{ delay }], - extra: { - 'http://cp.cloudflare.com/generate_204': { - history: [{ time: new Date(0).toISOString(), delay }], - }, - }, source: { kind: 'provider', providerName: `${memberIndex}` }, }, }, - }) as unknown as ResolvedMemberOccurrence + }) as ResolvedMemberOccurrence afterEach(() => vi.restoreAllMocks()) @@ -42,9 +36,7 @@ test('matches the previous comparator for cached, fallback and sentinel delays', for (const cached of [false, true]) { const group = `sort-${cached}` if (cached) { - values.forEach((delay, i) => - delayManager.setDelay(list[i].member, group, delay), - ) + values.forEach((delay, i) => delayManager.setDelay(`${i}`, group, delay)) } for (const timeout of [10000, 20, 0, NaN]) { const expected = list @@ -74,7 +66,7 @@ test('reads each occurrence once and observes cache updates and expiry on the ne node(3, 25), ] const cachedOrder = [list[0], list[2], list[1], list[3]] - delayManager.setDelay(list[0].member, 'expiry', 1) + delayManager.setDelay('0', 'expiry', 1) const get = vi.spyOn(delayManager, 'getDelayFix') expect(filterSort(list, 'expiry', '', 1)).toEqual(cachedOrder) expect(get).toHaveBeenCalledTimes(list.length) @@ -88,7 +80,7 @@ test('reads each occurrence once and observes cache updates and expiry on the ne list[3], list[0], ]) - delayManager.setDelay(list[0].member, 'expiry', 2) + delayManager.setDelay('0', 'expiry', 2) expect(filterSort(list, 'expiry', '', 1)).toEqual(cachedOrder) get.mockClear() filterSort([], 'expiry', '', 1) diff --git a/src/components/proxy/use-head-state.ts b/src/components/proxy/use-head-state.ts index d536564cc..5d30c5e1c 100644 --- a/src/components/proxy/use-head-state.ts +++ b/src/components/proxy/use-head-state.ts @@ -1,10 +1,6 @@ import { useCallback, useEffect, useReducer } from 'react' import { useProfiles } from '@/hooks/use-profiles' -import { - profileTestUrls, - commitProfileTestUrl, -} from '@/services/proxy-test-url' import { ProxySortType } from './use-filter-sort' @@ -36,45 +32,22 @@ export const DEFAULT_STATE: HeadState = { } type HeadStateAction = - | { type: 'reset'; profile: string } - | { type: 'replace'; profile: string; payload: Record } + | { type: 'reset' } + | { type: 'replace'; payload: Record } | { type: 'update'; groupName: string; patch: Partial } - | { type: 'urls'; urls: Record } - -interface LoadedHeadState { - profile: string | null - heads: Record -} function headStateReducer( - state: LoadedHeadState, + state: Record, action: HeadStateAction, -): LoadedHeadState { +): Record { switch (action.type) { case 'reset': - return { profile: action.profile, heads: {} } + return {} case 'replace': - return { profile: action.profile, heads: action.payload } - case 'urls': { - let heads = state.heads - for (const [name, testUrl] of Object.entries(action.urls)) { - if (heads[name]?.testUrl === testUrl) continue - heads = { - ...heads, - [name]: { ...DEFAULT_STATE, ...heads[name], testUrl }, - } - } - return heads === state.heads ? state : { ...state, heads } - } + return action.payload case 'update': { - const prev = state.heads[action.groupName] || DEFAULT_STATE - return { - ...state, - heads: { - ...state.heads, - [action.groupName]: { ...prev, ...action.patch }, - }, - } + const prev = state[action.groupName] || DEFAULT_STATE + return { ...state, [action.groupName]: { ...prev, ...action.patch } } } default: return state @@ -82,42 +55,30 @@ function headStateReducer( } export function useHeadStateNew() { - const { profiles, current: profile } = useProfiles() + const { profiles } = useProfiles() const current = profiles?.current || '' - const [{ profile: loadedProfile, heads: state }, dispatch] = useReducer( - headStateReducer, - { profile: null, heads: {} }, - ) + const [state, dispatch] = useReducer(headStateReducer, {}) useEffect(() => { - const urls = profile ? profileTestUrls(profile) : {} - if (loadedProfile === current) { - dispatch({ type: 'urls', urls }) - return - } try { const data = JSON.parse( - localStorage.getItem(HEAD_STATE_KEY) || '{}', + localStorage.getItem(HEAD_STATE_KEY)!, ) as HeadStateStorage - const value = data?.[current] || {} - for (const [name, testUrl] of Object.entries(urls)) { - value[name] = { ...DEFAULT_STATE, ...value[name], testUrl } - } + const value = data[current] || {} if (value && typeof value === 'object') { - dispatch({ type: 'replace', profile: current, payload: value }) + dispatch({ type: 'replace', payload: value }) } else { - dispatch({ type: 'reset', profile: current }) + dispatch({ type: 'reset' }) } } catch { - dispatch({ type: 'reset', profile: current }) + dispatch({ type: 'reset' }) } - }, [current, loadedProfile, profile]) + }, [current]) useEffect(() => { - if (loadedProfile !== current) return const timer = setTimeout(() => { try { const item = localStorage.getItem(HEAD_STATE_KEY) @@ -133,16 +94,13 @@ export function useHeadStateNew() { }) return () => clearTimeout(timer) - }, [state, current, loadedProfile]) + }, [state, current]) const setHeadState = useCallback( (groupName: string, obj: Partial) => { dispatch({ type: 'update', groupName, patch: obj }) - if (current && obj.testUrl !== undefined) { - void commitProfileTestUrl(current, groupName, obj.testUrl) - } }, - [current], + [], ) return [state, setHeadState] as const diff --git a/src/components/proxy/use-render-list.ts b/src/components/proxy/use-render-list.ts index 826331bde..659e0af4a 100644 --- a/src/components/proxy/use-render-list.ts +++ b/src/components/proxy/use-render-list.ts @@ -116,7 +116,6 @@ const virtualGroup = (members: ProxyGroupView['members']): ProxyGroupView => ({ mptcp: false, smux: false, history: [], - extra: {}, members, }) diff --git a/src/hooks/use-profiles.ts b/src/hooks/use-profiles.ts index f07fd4ce0..71196bd36 100644 --- a/src/hooks/use-profiles.ts +++ b/src/hooks/use-profiles.ts @@ -1,9 +1,8 @@ -import { useCallback, useEffect, useRef } from 'react' +import { useCallback, useRef } from 'react' import type { ProfilePatch, ProfileSelection } from '@/services/bindings' import { getProfiles, patchProfile, patchProfilesConfig } from '@/services/cmds' import { mutate } from '@/services/mutate' -import { migrateProfileTestUrls } from '@/services/proxy-test-url' import { fetchCacheData, setCacheData, useQuery } from '@/services/query-client' import { debugLog } from '@/utils/debug' @@ -36,10 +35,6 @@ export const useProfiles = () => { refetchInterval: false, }) - useEffect(() => { - if (profiles) migrateProfileTestUrls(profiles) - }, [profiles]) - const refetchRef = useRef(refetch) refetchRef.current = refetch const mutateProfiles = useCallback(async () => { diff --git a/src/hooks/use-proxy-delay-state.ts b/src/hooks/use-proxy-delay-state.ts index 8b999edba..f8a07f299 100644 --- a/src/hooks/use-proxy-delay-state.ts +++ b/src/hooks/use-proxy-delay-state.ts @@ -34,6 +34,7 @@ export function useProxyDelayState( groupName: string, ): UseProxyDelayState { const name = member.ref.name + const details = memberDetails(member) const unresolved = member.kind === 'unresolved' const isPreset = unresolved || PRESET_PROXY_NAMES.includes(name) const [delayState, setDelayState] = useReducer(identity, INITIAL_DELAY) @@ -42,18 +43,18 @@ export function useProxyDelayState( useEffect(() => { if (isPreset) return - delayManager.setListener(member, groupName, setDelayState) + delayManager.setListener(name, groupName, setDelayState) return () => { - delayManager.removeListener(member, groupName) + delayManager.removeListener(name, groupName) } - }, [member, groupName, isPreset]) + }, [name, groupName, isPreset]) const updateDelay = useCallback(() => { if (unresolved) { setDelayState(INITIAL_DELAY) return } - const cachedUpdate = delayManager.getDelayUpdate(member, groupName) + const cachedUpdate = delayManager.getDelayUpdate(name, groupName) if (cachedUpdate) { setDelayState({ ...cachedUpdate }) return @@ -66,9 +67,7 @@ export function useProxyDelayState( } let updatedAt = 0 - const history = - delayManager.getHistory(member, groupName) ?? - memberDetails(member)?.history + const history = details?.history if (history && history.length > 0) { const lastRecord = history[history.length - 1] const parsed = Date.parse(lastRecord.time) @@ -78,18 +77,16 @@ export function useProxyDelayState( } setDelayState({ delay: fallbackDelay, updatedAt }) - }, [groupName, member, unresolved]) + }, [details?.history, groupName, member, name, unresolved]) useEffect(() => { updateDelay() - return delayManager.addGroupListener(groupName, updateDelay) - }, [groupName, updateDelay]) + }, [updateDelay]) const onDelay = useLockFn(async () => { if (!isInteractableMember(member)) return setDelayState({ delay: -2, updatedAt: Date.now() }) - await delayManager.checkDelay(member, groupName, timeout) - updateDelay() + setDelayState(await delayManager.checkDelay(member, groupName, timeout)) }) return { diff --git a/src/services/bindings.ts b/src/services/bindings.ts index 73e886a69..4a1623bdc 100644 --- a/src/services/bindings.ts +++ b/src/services/bindings.ts @@ -659,7 +659,6 @@ export type PrfItem_Deserialize = { desc?: string | null url?: string | null selected?: PrfSelected[] | null - latency_test_urls?: { [key in string]: string } | null extra?: PrfExtra | null updated?: number | null option?: PrfOption_Deserialize | null @@ -675,7 +674,6 @@ export type PrfItem_Serialize = { desc?: string | null url?: string | null selected?: PrfSelected[] | null - latency_test_urls?: { [key in string]: string } | null extra?: PrfExtra | null updated: number | null option?: PrfOption_Serialize | null @@ -770,7 +768,6 @@ export type ProfilePatch_Deserialize = { file?: string | null url?: string | null selected?: PrfSelected[] | null - latency_test_urls?: { [key in string]: string } | null extra?: PrfExtra | null updated?: number | null option?: PrfOption_Deserialize | null @@ -783,7 +780,6 @@ export type ProfilePatch_Serialize = { file: string | null url: string | null selected: PrfSelected[] | null - latency_test_urls: { [key in string]: string } | null extra: PrfExtra | null updated: number | null option: PrfOption_Serialize | null @@ -818,7 +814,6 @@ export type ProxyGroupView_Deserialize = { icon: string | null testUrl: string | null history: DelayHistory[] - extra: { [key in string]: ProxyLatencyHistory } members: ProxyMemberRef[] } & ProxyCapabilities @@ -831,14 +826,9 @@ export type ProxyGroupView_Serialize = { icon?: string | null testUrl?: string | null history: DelayHistory[] - extra: { [key in string]: ProxyLatencyHistory } members: ProxyMemberRef[] } & ProxyCapabilities -export type ProxyLatencyHistory = { - history: DelayHistory[] -} - export type ProxyMemberRef = | { kind: 'group'; name: string } | { kind: 'node'; name: string; recordId: string } @@ -860,7 +850,6 @@ export type ProxyNodeView_Deserialize = { name: string type: string history: DelayHistory[] - extra: { [key in string]: ProxyLatencyHistory } id: string | null hidden: boolean | null icon: string | null @@ -873,7 +862,6 @@ export type ProxyNodeView_Serialize = { name: string type: string history: DelayHistory[] - extra: { [key in string]: ProxyLatencyHistory } id?: string | null hidden?: boolean | null icon?: string | null diff --git a/src/services/cmds.ts b/src/services/cmds.ts index 001ee3c71..f46377335 100644 --- a/src/services/cmds.ts +++ b/src/services/cmds.ts @@ -91,18 +91,8 @@ export async function deleteProfile(index: string) { } export async function patchProfile(index: string, profile: ProfilePatch) { - const { - type, - name, - desc, - file, - url, - selected, - latency_test_urls, - extra, - updated, - option, - } = profile + const { type, name, desc, file, url, selected, extra, updated, option } = + profile return commands.patchProfile(index, { type, name, @@ -110,7 +100,6 @@ export async function patchProfile(index: string, profile: ProfilePatch) { file, url, selected, - latency_test_urls, extra, updated, option, diff --git a/src/services/delay.test.ts b/src/services/delay.test.ts index a26d25dde..a4d7c92fd 100644 --- a/src/services/delay.test.ts +++ b/src/services/delay.test.ts @@ -59,136 +59,3 @@ describe('group delay completion', () => { stop() }) }) - -test('uses newer core history after a tray test without hiding an active page test', () => { - const member = node('tray-refresh') - if (member.kind !== 'node') throw new Error('Expected node') - const cached = delayManager.setDelay(member, 'tray-group', 50) - member.node.extra = { - [delayManager.getUrl('tray-group')]: { - history: [ - { time: new Date(cached.updatedAt + 1000).toISOString(), delay: 300 }, - ], - }, - } - - expect(delayManager.getDelayFix(member, 'tray-group')).toBe(300) - expect(delayManager.getDelayUpdate(member, 'tray-group')?.delay).toBe(300) - - delayManager.setDelay(member, 'tray-group', -2) - expect(delayManager.getDelayFix(member, 'tray-group')).toBe(-2) -}) - -test('latency URL validation rejects malformed hosts and ports and trims valid URLs', () => { - for (const url of [ - 'http://?', - 'http://host:invalid', - 'http://bad host/', - 'ftp://localhost', - 'http:localhost', - ]) { - delayManager.setUrl('url-validation', url) - expect(delayManager.getUrl('url-validation')).toBe( - 'http://cp.cloudflare.com/generate_204', - ) - } - delayManager.setUrl('url-validation', ' HTTP://localhost:8080/ ') - expect(delayManager.getUrl('url-validation')).toBe('HTTP://localhost:8080/') -}) - -test('another URL cannot replace a group measurement, but a newer matching URL can', () => { - const member = node('url-isolation') - if (member.kind !== 'node') throw new Error('Expected node') - delayManager.setUrl('url-a', 'http://localhost/a') - const cached = delayManager.setDelay(member, 'url-a', 50) - const newer = new Date(cached.updatedAt + 1000).toISOString() - Object.assign(member.node, { - history: [{ time: newer, delay: 126 }], - extra: { - 'http://localhost/a': { - history: [ - { time: new Date(cached.updatedAt - 1000).toISOString(), delay: 49 }, - ], - }, - 'http://localhost/b': { - history: [{ time: newer, delay: 126 }], - }, - }, - }) - expect(delayManager.getDelayFix(member, 'url-a')).toBe(50) - Object.assign(member.node, { - extra: { - 'http://localhost/a': { - history: [{ time: newer, delay: 75 }], - }, - }, - }) - expect(delayManager.getDelayFix(member, 'url-a')).toBe(75) -}) - -test('same-named provider members keep separate measurements and listeners', async () => { - const first = node('same-provider-name') - const second = node('same-provider-name') - if (first.kind !== 'node' || second.kind !== 'node') - throw new Error('Expected nodes') - first.node.recordId = 'provider-a:N' - first.node.source = { kind: 'provider', providerName: 'a', proxyName: 'N' } - second.node.recordId = 'provider-b:N' - second.node.source = { kind: 'provider', providerName: 'b', proxyName: 'N' } - const { healthcheckNodeInProvider } = await import('tauri-plugin-mihomo-api') - vi.mocked(healthcheckNodeInProvider) - .mockResolvedValueOnce({ delay: 40 }) - .mockResolvedValueOnce({ delay: 125 }) - const firstListener = vi.fn() - const secondListener = vi.fn() - delayManager.setListener(first, 'provider-collision', firstListener) - delayManager.setListener(second, 'provider-collision', secondListener) - await delayManager.checkListDelay([first, second], 'provider-collision', 5000) - await flush() - expect(firstListener).toHaveBeenLastCalledWith( - expect.objectContaining({ delay: 40 }), - ) - expect(secondListener).toHaveBeenLastCalledWith( - expect.objectContaining({ delay: 125 }), - ) - delayManager.removeListener(first, 'provider-collision') - delayManager.removeListener(second, 'provider-collision') - expect(delayManager.getDelayFix(first, 'provider-collision')).toBe(40) - expect(delayManager.getDelayFix(second, 'provider-collision')).toBe(125) -}) - -test.each(['core', 'provider'] as const)( - 'cached %s delays follow source identity after record IDs move', - (kind) => { - const original = node(`stable-${kind}`) - const replacement = node(`replacement-${kind}`) - if (original.kind !== 'node' || replacement.kind !== 'node') - throw new Error('Expected nodes') - const source = (proxyName: string) => - kind === 'core' - ? { kind, proxyName } - : { kind, providerName: 'subscription', proxyName } - original.node.source = source(original.ref.name) - replacement.node.source = source(replacement.ref.name) - original.node.recordId = 'position:0' - replacement.node.recordId = 'position:0' - delayManager.setDelay(original, `reorder-${kind}`, 40) - expect(delayManager.getDelayFix(replacement, `reorder-${kind}`)).toBe(-1) - original.node.recordId = 'position:1' - expect(delayManager.getDelayFix(original, `reorder-${kind}`)).toBe(40) - }, -) - -test('unmeasured selectors show automatic history without replacing a manual URL result', () => { - const member = node('selector-member') - if (member.kind !== 'node') throw new Error('Expected node') - member.node.history = [ - { time: new Date(Date.now() + 1000).toISOString(), delay: 126 }, - ] - member.node.extra = { - 'http://localhost/automatic': { history: member.node.history }, - } - expect(delayManager.getDelayFix(member, 'selector')).toBe(126) - delayManager.setDelay(member, 'selector', 50) - expect(delayManager.getDelayFix(member, 'selector')).toBe(50) -}) diff --git a/src/services/delay.ts b/src/services/delay.ts index 323809b67..18602faaf 100644 --- a/src/services/delay.ts +++ b/src/services/delay.ts @@ -12,23 +12,13 @@ import { } from '@/types/proxy-view' import { debugLog } from '@/utils/debug' import { classifyDelay, DEFAULT_DELAY_TIMEOUT } from '@/utils/delay' -import { isValidLatencyTestUrl } from '@/utils/network' +import { isValidUrl } from '@/utils/network' export type DelaySnapshot = { of: (member: ResolvedProxyMember) => number } -const hashKey = (member: ResolvedProxyMember, group: string) => { - if (member.kind !== 'node') - return JSON.stringify([group, member.kind, member.ref.name]) - const source = member.node.source - return JSON.stringify([ - group, - source.kind, - source.kind === 'provider' ? source.providerName : null, - source.proxyName, - ]) -} +const hashKey = (name: string, group: string) => `${group ?? ''}::${name}` export interface DelayUpdate { delay: number @@ -39,7 +29,7 @@ export interface DelayUpdate { const CACHE_TTL = 30 * 60 * 1000 class DelayManager { - private cache = new Map() + private cache = new Map() private urlMap = new Map() private listenerMap = new Map void>() @@ -163,13 +153,13 @@ class DelayManager { } setUrl(group: string, url: string) { - const previous = this.getUrl(group) - if (isValidLatencyTestUrl(url)) { - this.urlMap.set(group, url.trim()) - } else { + if (!isValidUrl(url)) { + debugLog(`[DelayManager] 拒绝无效测试URL,组: ${group}, URL: ${url}`) this.urlMap.delete(group) + return } - if (previous !== this.getUrl(group)) this.queueGroupNotification(group) + debugLog(`[DelayManager] 设置测试URL,组: ${group}, URL: ${url}`) + this.urlMap.set(group, url) } getUrl(group: string) { @@ -181,16 +171,16 @@ class DelayManager { } setListener( - member: ResolvedProxyMember, + name: string, group: string, listener: (update: DelayUpdate) => void, ) { - const key = hashKey(member, group) + const key = hashKey(name, group) this.listenerMap.set(key, listener) } - removeListener(member: ResolvedProxyMember, group: string) { - const key = hashKey(member, group) + removeListener(name: string, group: string) { + const key = hashKey(name, group) this.listenerMap.delete(key) } @@ -209,14 +199,14 @@ class DelayManager { } setDelay( - member: ResolvedProxyMember, + name: string, group: string, delay: number, - meta?: { elapsed?: number; url?: string }, + meta?: { elapsed?: number }, ): DelayUpdate { - const key = hashKey(member, group) + const key = hashKey(name, group) debugLog( - `[DelayManager] 设置延迟,代理: ${member.ref.name}, 组: ${group}, 延迟: ${delay}`, + `[DelayManager] 设置延迟,代理: ${name}, 组: ${group}, 延迟: ${delay}`, ) const update: DelayUpdate = { delay, @@ -224,9 +214,7 @@ class DelayManager { updatedAt: Date.now(), } - const url = meta?.url ?? this.getUrl(group) - if (url !== this.getUrl(group)) return update - this.cache.set(key, { ...update, url }) + this.cache.set(key, update) const queue = this.pendingItemUpdates.get(key) if (queue) { @@ -239,16 +227,9 @@ class DelayManager { return update } - getDelayUpdate(member: ResolvedProxyMember, group: string) { - const history = this.getHistory(member, group) - const key = hashKey(member, group) - const cached = this.cache.get(key) - const entry = cached?.url === this.getUrl(group) ? cached : undefined - const latest = history?.at(-1) - const updatedAt = latest ? Date.parse(latest.time) : 0 - if (latest && entry?.delay !== -2 && updatedAt > (entry?.updatedAt ?? 0)) { - return { delay: latest.delay || 1e6, updatedAt } - } + getDelayUpdate(name: string, group: string) { + const key = hashKey(name, group) + const entry = this.cache.get(key) if (!entry) return undefined if (Date.now() - entry.updatedAt > CACHE_TTL) { @@ -259,25 +240,23 @@ class DelayManager { return { ...entry } } - getDelay(member: ResolvedProxyMember, group: string) { - const update = this.getDelayUpdate(member, group) + getDelay(name: string, group: string) { + const update = this.getDelayUpdate(name, group) return update ? update.delay : -1 } - getHistory(member: ResolvedProxyMember, group: string) { - return memberDetails(member)?.extra?.[this.getUrl(group)]?.history - } - getDelayFix(member: ResolvedProxyMember, group: string) { if (member.kind === 'unresolved') return -1 - const history = - this.getHistory(member, group) ?? memberDetails(member)?.history - const update = this.getDelayUpdate(member, group) + const details = memberDetails(member) + const name = member.ref.name + const update = this.getDelayUpdate(name, group) if (update && (update.delay >= 0 || update.delay === -2)) { return update.delay } - if (history?.length) return history[history.length - 1].delay || 1e6 + if (details?.history && details.history.length > 0) { + return details.history[details.history.length - 1].delay || 1e6 + } return -1 } @@ -319,12 +298,12 @@ class DelayManager { `[DelayManager] 开始测试延迟,代理: ${name}, 组: ${group}, 超时: ${timeout}ms`, ) - const url = this.getUrl(group) - this.setDelay(member, group, -2, { url }) + this.setDelay(name, group, -2) const startTime = Date.now() try { + const url = this.getUrl(group) debugLog(`[DelayManager] 调用API测试延迟,代理: ${name}, URL: ${url}`) const timeoutPromise = new Promise((resolve) => { @@ -345,14 +324,14 @@ class DelayManager { const elapsed = elapsedTime debugLog(`[DelayManager] 延迟测试完成,代理: ${name}, 结果: ${delay}ms`) - return this.setDelay(member, group, delay, { elapsed, url }) + return this.setDelay(name, group, delay, { elapsed }) } catch (error) { await new Promise((resolve) => setTimeout(resolve, 500)) console.error(`[DelayManager] 延迟测试出错,代理: ${name}`, error) const delay = 1e6 // error const elapsed = Date.now() - startTime - return this.setDelay(member, group, delay, { elapsed, url }) + return this.setDelay(name, group, delay, { elapsed }) } } @@ -365,9 +344,10 @@ class DelayManager { debugLog( `[DelayManager] 批量测试延迟开始,组: ${group}, 数量: ${proxies.length}, 并发数: ${concurrency}`, ) + const names = proxies.map((member) => member.ref.name) this.activeBatches.set(group, (this.activeBatches.get(group) ?? 0) + 1) - proxies.forEach((member) => { - this.setDelay(member, group, -2) + names.forEach((name) => { + this.setDelay(name, group, -2) }) let index = 0 @@ -379,7 +359,7 @@ class DelayManager { const currName = currMember.ref.name try { - this.setDelay(currMember, group, -2) + this.setDelay(currName, group, -2) // Stagger requests so a batch does not hit the core at once. if (index > 1) { @@ -395,13 +375,13 @@ class DelayManager { `[DelayManager] 批量测试单个代理出错,代理: ${currName}`, error, ) - this.setDelay(currMember, group, 1e6) + this.setDelay(currName, group, 1e6) } return help() } - const actualConcurrency = Math.min(concurrency, proxies.length, 10) + const actualConcurrency = Math.min(concurrency, names.length, 10) debugLog(`[DelayManager] 实际并发数: ${actualConcurrency}`) const promiseList: Promise[] = [] diff --git a/src/services/proxy-test-url.test.ts b/src/services/proxy-test-url.test.ts deleted file mode 100644 index 4f2969c88..000000000 --- a/src/services/proxy-test-url.test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { afterEach, expect, test, vi } from 'vitest' - -vi.mock('@/services/cmds', () => ({ - getProfiles: vi.fn(), - patchProfile: vi.fn().mockResolvedValue(undefined), - syncTrayProxySelection: vi.fn().mockResolvedValue(undefined), -})) -vi.mock('@/services/query-client', () => ({ revalidateQueries: vi.fn() })) -vi.mock('@/services/notice-service', () => ({ showNotice: { error: vi.fn() } })) - -import { - getProfiles, - patchProfile, - syncTrayProxySelection, -} from '@/services/cmds' -import { revalidateQueries } from '@/services/query-client' - -import { - profileTestUrls, - saveProfileTestUrls, - commitProfileTestUrl, -} from './proxy-test-url' - -afterEach(() => { - vi.useRealTimers() - vi.clearAllMocks() -}) - -test('committed edits retain their profile and merge with fresh saved URLs', async () => { - vi.mocked(getProfiles).mockResolvedValue({ - current: 'new-profile', - items: [ - { - uid: 'old-profile', - type: null, - name: null, - file: null, - updated: null, - latency_test_urls: { untouched: 'https://example.com/' }, - }, - ], - }) - await commitProfileTestUrl('old-profile', 'A', ' http://localhost/new ') - expect(patchProfile).toHaveBeenCalledExactlyOnceWith('old-profile', { - latency_test_urls: { - untouched: 'https://example.com/', - A: 'http://localhost/new', - }, - }) - expect(revalidateQueries).toHaveBeenCalledWith([['getProfiles']]) - expect(syncTrayProxySelection).toHaveBeenCalledOnce() -}) - -test('migration cannot overwrite a previously saved or cleared override', async () => { - vi.mocked(getProfiles).mockResolvedValue({ - items: [ - { - uid: 'p', - type: null, - name: null, - file: null, - updated: null, - latency_test_urls: { A: '' }, - }, - ], - }) - await saveProfileTestUrls('p', { A: 'http://localhost/stale' }, true) - expect(patchProfile).not.toHaveBeenCalled() -}) - -test('pending edits survive a reload and older save acknowledgements', async () => { - vi.useFakeTimers() - const profile = { - uid: 'pending-profile', - type: null, - name: null, - file: null, - updated: null, - latency_test_urls: { A: 'http://localhost/old' }, - } - vi.mocked(getProfiles).mockResolvedValue({ items: [profile] }) - let finish!: () => void - vi.mocked(patchProfile).mockImplementationOnce( - () => - new Promise((resolve) => { - finish = () => resolve(null) - }), - ) - const first = commitProfileTestUrl(profile.uid, 'A', 'http://localhost/new') - expect(profileTestUrls(profile).A).toBe('http://localhost/new') - await vi.advanceTimersByTimeAsync(300) - expect(profileTestUrls(profile).A).toBe('http://localhost/new') - const second = commitProfileTestUrl( - profile.uid, - 'A', - 'http://localhost/newest', - ) - finish() - await first - expect(profileTestUrls(profile).A).toBe('http://localhost/newest') - await second - expect(patchProfile).toHaveBeenLastCalledWith(profile.uid, { - latency_test_urls: { A: 'http://localhost/newest' }, - }) -}) - -test('a failed save preserves the committed input across profile refreshes', async () => { - const profile = { - uid: 'failed-profile', - type: null, - name: null, - file: null, - updated: null, - latency_test_urls: { A: 'http://localhost/old' }, - } - vi.mocked(getProfiles).mockResolvedValue({ items: [profile] }) - vi.mocked(patchProfile).mockRejectedValueOnce(new Error('save failed')) - const log = vi.spyOn(console, 'error').mockImplementation(() => {}) - await commitProfileTestUrl(profile.uid, 'A', 'http://localhost/new') - expect(profileTestUrls(profile).A).toBe('http://localhost/new') - await commitProfileTestUrl(profile.uid, 'A', 'http://localhost/new') - expect(profileTestUrls(profile).A).toBe('http://localhost/old') - log.mockRestore() -}) diff --git a/src/services/proxy-test-url.ts b/src/services/proxy-test-url.ts deleted file mode 100644 index 059b632fe..000000000 --- a/src/services/proxy-test-url.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { - getProfiles, - patchProfile, - syncTrayProxySelection, -} from '@/services/cmds' -import { mutate } from '@/services/mutate' - -function readLegacyTestUrls(uid: string): Record { - try { - const states = JSON.parse(localStorage.getItem('proxy-head-state') || '{}')[ - uid - ] - return Object.fromEntries( - Object.entries(states || {}).flatMap(([name, state]) => { - const url = (state as { testUrl?: string }).testUrl - return typeof url === 'string' && url.trim() ? [[name, url.trim()]] : [] - }), - ) - } catch { - return {} - } -} - -export async function saveProfileTestUrls( - uid: string, - urls: Record, - migrateOnly = false, -) { - return mutate( - async () => { - const profiles = await getProfiles() - const profile = profiles.items?.find((item) => item.uid === uid) - if (!profile || (migrateOnly && profile.latency_test_urls !== undefined)) - return - await patchProfile(uid, { - latency_test_urls: { - ...(profile.latency_test_urls ?? readLegacyTestUrls(uid)), - ...urls, - }, - }) - await syncTrayProxySelection().catch((error) => { - console.error( - 'Failed to refresh tray after saving latency test URL:', - error, - ) - }) - }, - { id: `patch-profile:${uid}`, revalidate: [['getProfiles']] }, - ) -} - -const migrating = new Set() - -export function migrateProfileTestUrls(profiles: IProfilesConfig) { - for (const profile of profiles.items || []) { - const uid = profile.uid - if (!uid) continue - if (profile.latency_test_urls !== undefined || migrating.has(uid)) continue - const urls = readLegacyTestUrls(uid) - if (!Object.keys(urls).length) continue - migrating.add(uid) - void saveProfileTestUrls(uid, urls, true) - .catch((error) => { - console.error('Failed to migrate latency test URLs:', error) - }) - .finally(() => migrating.delete(uid)) - } -} - -const pending = new Map>() - -export async function commitProfileTestUrl( - uid: string, - group: string, - url: string, -) { - const edit = { url: url.trim() } - const urls = { ...pending.get(uid), [group]: edit } - pending.set(uid, urls) - try { - await saveProfileTestUrls(uid, { [group]: edit.url }) - const current = pending.get(uid) - if (current?.[group] === edit) { - delete current[group] - if (!Object.keys(current).length) pending.delete(uid) - } - } catch (error) { - console.error('Failed to save latency test URL:', error) - } -} - -export function profileTestUrls(profile: IProfileItem): Record { - return { - ...profile.latency_test_urls, - ...Object.fromEntries( - Object.entries( - (profile.uid ? pending.get(profile.uid) : undefined) ?? {}, - ).map(([group, edit]) => [group, edit.url]), - ), - } -} diff --git a/src/utils/network.ts b/src/utils/network.ts index 99db4a6f9..647efafc1 100644 --- a/src/utils/network.ts +++ b/src/utils/network.ts @@ -20,19 +20,6 @@ export const isValidUrl = (value: string) => require_tld: false, }) -export const isValidLatencyTestUrl = (value: string) => { - const raw = value.trim() - if (!/^https?:\/\//i.test(raw)) return false - try { - const url = new URL(raw) - return ( - (url.protocol === 'http:' || url.protocol === 'https:') && !!url.hostname - ) - } catch { - return false - } -} - export const isValidPort = (value: string) => isPort(value.trim()) export const normalizeHost = (value: string): string | null => { From b6c7af82a7c48e4b8ada3f3d9efd89613861c02a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 08:25:55 +0000 Subject: [PATCH 22/25] chore(deps): update tauri (#8346) * chore(deps): update tauri * fix(deps): pin rust-ini to 0.21.1 for tauri-plugin-deep-link 2.6.2 tauri-plugin-deep-link 2.6.2 constructs ini::ParseOption with an exhaustive struct literal, which fails to compile against rust-ini 0.21.2+ (new required fields enabled_indented_mutiline_value and enabled_preserve_key_leading_whitespace, E0063 on linux). Upstream fixed it in tauri-apps/plugins-workspace#3711 with ..Default::default() but no release contains the fix yet, so downgrade rust-ini in Cargo.lock until deep-link 2.6.3 ships. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com> --- Cargo.lock | 233 +++++++++++----------------------- Cargo.toml | 4 +- package.json | 18 +-- pnpm-lock.yaml | 290 +++++++++++++++++++++---------------------- src-tauri/Cargo.toml | 22 ++-- 5 files changed, 240 insertions(+), 327 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c2f85631..384c6330f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1119,7 +1119,7 @@ dependencies = [ "getrandom 0.4.3", "libc", "log", - "minisign-verify 0.3.0", + "minisign-verify", "nanoid", "network-interface", "objc2", @@ -4170,12 +4170,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "minisign-verify" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f9645cb765ea72b8111f36c522475d2daa0d22c957a9826437e97534bc4e9e" - [[package]] name = "minisign-verify" version = "0.3.0" @@ -5999,12 +5993,13 @@ dependencies = [ [[package]] name = "rust-ini" -version = "0.21.3" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7" +checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f" dependencies = [ "cfg-if", "ordered-multimap", + "trim-in-place", ] [[package]] @@ -6625,7 +6620,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7" dependencies = [ "libc", - "sigchld", "windows-sys 0.60.2", ] @@ -6645,17 +6639,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" -[[package]] -name = "sigchld" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1" -dependencies = [ - "libc", - "os_pipe", - "signal-hook 0.3.18", -] - [[package]] name = "signal-hook" version = "0.1.17" @@ -6666,16 +6649,6 @@ dependencies = [ "signal-hook-registry", ] -[[package]] -name = "signal-hook" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" version = "1.4.8" @@ -6881,6 +6854,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "static_vcruntime" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff7589a1859b09232522bb9edf076ca7fcf14ded96685d3fa629db73023ffbb7" + [[package]] name = "string_cache" version = "0.9.0" @@ -6940,9 +6919,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "swift-rs" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45c444e496845d3f2a351146bff59aae4975b2280238df1dfaa0c7d1846f38e" +checksum = "cefd87076fd385308ee4aff597256c902f1fbb4d031de1558efc12f8ffefadd9" dependencies = [ "base64 0.21.7", "serde", @@ -7189,9 +7168,9 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tauri" -version = "2.12.1" +version = "2.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed99ee9694a2deb776d91cae48ac7411ddfc89ecae2f9b5041111d8c88f2ace9" +checksum = "f316751027fc2644221d1a448564d519efb07067fda584879d9cda966391d212" dependencies = [ "anyhow", "bytes", @@ -7237,16 +7216,16 @@ dependencies = [ "tray-icon", "url", "webkit2gtk", - "webview2-com 0.39.1", + "webview2-com", "window-vibrancy", "windows 0.62.2", ] [[package]] name = "tauri-build" -version = "2.7.1" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59563ca5b331fd97f27ee9672ec8d36d33bb3c9e2c9f6710a1a5687256052e45" +checksum = "641dd5fd297c99ab92717b0428cca5b9c6f960b2ac96ca131b3eebc9d70b8ddc" dependencies = [ "anyhow", "cargo_toml", @@ -7258,6 +7237,8 @@ dependencies = [ "semver 1.0.28", "serde", "serde_json", + "static_vcruntime", + "strsim", "tauri-utils", "tauri-winres", "walkdir", @@ -7265,11 +7246,11 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.7.1" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e50213e463086ecc283d7e9f51c30cc0fd304ad457425158018be26dbf0d0a80" +checksum = "a6585c5b536c00f039d12ce70a9755172d5423bbcfd3969863baa70314c3e02f" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "brotli", "ico", "json-patch", @@ -7292,9 +7273,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.7.1" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8129fb43bb6e0d6b73ad3315cd172beaab17cd28899c594b1b32c80edbbfd99c" +checksum = "e2e83a0cfa1bae376e8fbbdc0b1692707aed50cd6072ce85cae4789af5d6c19f" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -7350,9 +7331,9 @@ dependencies = [ [[package]] name = "tauri-plugin-clipboard-manager" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333d3b6beeb1c2c7fc040233d4ea7b6c03a9f8f039592b7400833c43fb5b568a" +checksum = "9be5ed8d94c33afe8377e885119069f6508780659271d0a25cfc54d441f2bc81" dependencies = [ "arboard", "log", @@ -7365,9 +7346,9 @@ dependencies = [ [[package]] name = "tauri-plugin-deep-link" -version = "2.6.1" +version = "2.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac7a92a46ab5c88f44532ca50906d6e448a948d4ddf8c5376ab125e3260f736" +checksum = "1b3c64e24ebcbc63aaa2d88a9c51e2507084b46620baf39ecb0baa0738a08bb4" dependencies = [ "dunce", "plist", @@ -7413,9 +7394,9 @@ dependencies = [ [[package]] name = "tauri-plugin-dialog" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf9a5c92e39bdd84f22f6be9230e39d0c4e140345f71ffe6058dca4f71127cf" +checksum = "b7461aaacf1901915ea7b9f5cd74f8224a351ed96af0a62c07fce934003cb34b" dependencies = [ "log", "raw-window-handle", @@ -7431,9 +7412,9 @@ dependencies = [ [[package]] name = "tauri-plugin-fs" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "466eb32466fe5021b6728b06862f9ff14a9f7e1af890047654e03a96d7c0e1bb" +checksum = "5d58eb1d4984e535f47a642ffec09a2da6f5c18a12b5902d12126cb7626d628b" dependencies = [ "anyhow", "dunce", @@ -7455,9 +7436,9 @@ dependencies = [ [[package]] name = "tauri-plugin-global-shortcut" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd2e1f725891a1613af8f25bf918ba3357654b0fd3f2d794c0ce76cbdd92ed2" +checksum = "93ff17919fe09852d269bd37b1d3d2e993b9dbb514afe7acbf3346c1d3627e2d" dependencies = [ "global-hotkey", "log", @@ -7470,9 +7451,9 @@ dependencies = [ [[package]] name = "tauri-plugin-http" -version = "2.8.0" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e9d6b3319e101bc1be27cfa0fb4054d7784a12509c67ead0033b82180e5ed1" +checksum = "2c57e3451553f95a1db3bfed6a358a77ce5080b6399a242c6eadac113f97abd2" dependencies = [ "bytes", "cookie_store", @@ -7489,7 +7470,7 @@ dependencies = [ "thiserror 2.0.20", "tokio", "url", - "urlpattern 0.3.0", + "urlpattern", ] [[package]] @@ -7519,9 +7500,9 @@ dependencies = [ [[package]] name = "tauri-plugin-notification" -version = "2.5.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533770889abb60a0407d5a32096182f0e6463f5a3dfaa675be94580aa14070e1" +checksum = "b939d7b19c8af1381a72ef8474b3aba2b56c1ddac2c23f0c8e96abbcf86b198b" dependencies = [ "log", "notify-rust", @@ -7534,13 +7515,14 @@ dependencies = [ "thiserror 2.0.20", "time", "url", + "zbus", ] [[package]] name = "tauri-plugin-opener" -version = "2.7.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39404b2572927e0d3ed30a7ca226037f7508d22e79c96ee6ef0d42b6a4b3345" +checksum = "53810be1b4fed22bb6ac3f4cab5a2b80d9391d1af436bda145607532bc0bb219" dependencies = [ "dunce", "glob", @@ -7570,11 +7552,12 @@ dependencies = [ [[package]] name = "tauri-plugin-shell" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "094bdbc47e5efe36544ba21b3a53ab5c724150236cf55e6c9be46191deb6eab6" +checksum = "8567d42b2c7264355daa1df415ec77f52aa42e885924c86a969be2e920e05521" dependencies = [ "encoding_rs", + "libc", "log", "open", "os_pipe", @@ -7587,13 +7570,14 @@ dependencies = [ "tauri-plugin", "thiserror 2.0.20", "tokio", + "windows-sys 0.60.2", ] [[package]] name = "tauri-plugin-updater" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb0b2ea3e85ca287990d3859a29cc5cb18024240fd78f62e027fb7963670f18" +checksum = "7259989d4fe11b2bf51f7d671642249b1837c4ae2da1430dc713ae38f98ceeec" dependencies = [ "base64 0.22.1", "dirs 7.0.0", @@ -7601,8 +7585,9 @@ dependencies = [ "futures-util", "http", "infer", + "libc", "log", - "minisign-verify 0.2.5", + "minisign-verify", "osakit", "percent-encoding", "reqwest 0.13.5", @@ -7624,9 +7609,9 @@ dependencies = [ [[package]] name = "tauri-plugin-wdio-webdriver" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c5e97428174a52b7f4357bbc4535fcce52c6a06c8ee7a379502f7cda1b6045" +checksum = "4f76676d510d271d80abcf8b0552987b5b4f0eae5e3f906e9b5660d43c97c62e" dependencies = [ "async-trait", "axum", @@ -7650,9 +7635,9 @@ dependencies = [ "tracing", "uuid", "webkit2gtk", - "webview2-com 0.38.2", - "windows 0.61.3", - "windows-core 0.61.2", + "webview2-com", + "windows 0.62.2", + "windows-core 0.62.2", ] [[package]] @@ -7672,9 +7657,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.12.1" +version = "2.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a57a2a9b8c8b7fc00d35b510fe808ded7f9f1b44fc1cdda6aee38632ea5413" +checksum = "7c55766d99cea69055904d1735b93c2049302b2e09effd462120deb5581d78e9" dependencies = [ "cookie", "dpi", @@ -7691,15 +7676,15 @@ dependencies = [ "thiserror 2.0.20", "url", "webkit2gtk", - "webview2-com 0.39.1", + "webview2-com", "windows 0.62.2", ] [[package]] name = "tauri-runtime-wry" -version = "2.12.1" +version = "2.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e7e0c9f80a5130773cfabb6df4dc924518fb1b2c923726966804634b57d22" +checksum = "8d61892587aea2a85245bcaec98c6fe46268874c0a0deae5535fb71ca7b93eae" dependencies = [ "gtk", "http", @@ -7717,7 +7702,7 @@ dependencies = [ "tracing", "url", "webkit2gtk", - "webview2-com 0.39.1", + "webview2-com", "windows 0.62.2", "wry", ] @@ -7755,9 +7740,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.10.1" +version = "2.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ff55a614843b9a3f010f211df637c94df2607175b8d0f6e0f4a7c19e18621ee" +checksum = "362ab21cd4cc713f2a02b1a9b5688198b1541cfb6907c4281e9190e0f0ef4aa3" dependencies = [ "anyhow", "brotli", @@ -7786,7 +7771,7 @@ dependencies = [ "thiserror 2.0.20", "toml 1.1.6+spec-1.1.0", "url", - "urlpattern 0.6.0", + "urlpattern", "uuid", "walkdir", ] @@ -7905,7 +7890,7 @@ dependencies = [ "regex", "semver 0.11.0", "sha2 0.9.9", - "signal-hook 0.1.17", + "signal-hook", "terminfo", "termios", "thiserror 1.0.69", @@ -8503,6 +8488,12 @@ dependencies = [ "petgraph", ] +[[package]] +name = "trim-in-place" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daa60874b45b168f67f3f9ba1ee821ad77144d6fa19cef1cd1874a7450a948da" + [[package]] name = "triomphe" version = "0.1.16" @@ -8595,47 +8586,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-ucd-ident" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - [[package]] name = "unicase" version = "2.9.0" @@ -8695,18 +8645,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "urlpattern" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" -dependencies = [ - "regex", - "serde", - "unic-ucd-ident", - "url", -] - [[package]] name = "urlpattern" version = "0.6.0" @@ -9098,20 +9036,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "webview2-com" -version = "0.38.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" -dependencies = [ - "webview2-com-macros", - "webview2-com-sys 0.38.2", - "windows 0.61.3", - "windows-core 0.61.2", - "windows-implement", - "windows-interface", -] - [[package]] name = "webview2-com" version = "0.39.1" @@ -9119,7 +9043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f89fca7a704cee10dcb3654c1dbb8941d1783132f1917358af75bec37a7d7e6" dependencies = [ "webview2-com-macros", - "webview2-com-sys 0.39.1", + "webview2-com-sys", "windows 0.62.2", "windows-core 0.62.2", ] @@ -9135,17 +9059,6 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "webview2-com-sys" -version = "0.38.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" -dependencies = [ - "thiserror 2.0.20", - "windows 0.61.3", - "windows-core 0.61.2", -] - [[package]] name = "webview2-com-sys" version = "0.39.1" @@ -9885,7 +9798,7 @@ dependencies = [ "url", "webkit2gtk", "webkit2gtk-sys", - "webview2-com 0.39.1", + "webview2-com", "windows 0.62.2", "windows-core 0.62.2", "windows-version", diff --git a/Cargo.toml b/Cargo.toml index a91a42b2b..8f52bdadb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,8 +61,8 @@ tracing-estuary = { git = "https://github.com/Tunglies/tracing-estuary.git", bra tauri-plugin-clash-verge-sysinfo = { path = "crates/tauri-plugin-clash-verge-sysinfo" } tracing = "0.1.44" -tauri = { version = "2.12.1" } -tauri-plugin-clipboard-manager = "2.4.1" +tauri = { version = "2.12.4" } +tauri-plugin-clipboard-manager = "2.5.0" parking_lot = { version = "0.12.5", features = ["hardware-lock-elision"] } anyhow = "1.0.104" chrono = "0.4.45" diff --git a/package.json b/package.json index 2146e126f..ce9ba44b9 100644 --- a/package.json +++ b/package.json @@ -54,13 +54,13 @@ "@mui/icons-material": "^9.4.0", "@mui/material": "^9.4.0", "@tanstack/react-virtual": "^3.14.13", - "@tauri-apps/api": "2.12.1", - "@tauri-apps/plugin-clipboard-manager": "2.4.0", - "@tauri-apps/plugin-dialog": "2.8.0", - "@tauri-apps/plugin-fs": "2.6.0", - "@tauri-apps/plugin-http": "2.8.0", - "@tauri-apps/plugin-opener": "2.7.0", - "@tauri-apps/plugin-updater": "2.13.1", + "@tauri-apps/api": "2.12.4", + "@tauri-apps/plugin-clipboard-manager": "2.5.0", + "@tauri-apps/plugin-dialog": "2.8.3", + "@tauri-apps/plugin-fs": "2.7.1", + "@tauri-apps/plugin-http": "2.8.3", + "@tauri-apps/plugin-opener": "2.7.2", + "@tauri-apps/plugin-updater": "2.14.0", "ahooks": "^3.10.0", "cidr-block": "^2.3.0", "compare-versions": "^6.1.1", @@ -95,7 +95,7 @@ "@biomejs/biome": "^2.5.14", "@eslint-react/eslint-plugin": "^5.20.5", "@eslint/js": "^10.0.1", - "@tauri-apps/cli": "2.12.1", + "@tauri-apps/cli": "2.12.3", "@types/lodash-es": "^4.17.12", "@types/node": "^24.13.6", "@types/react": "19.3.0", @@ -103,7 +103,7 @@ "@types/validator": "^13.15.10", "@vitejs/plugin-legacy": "^8.2.3", "@vitejs/plugin-react": "^6.1.1", - "@wdio/tauri-service": "1.4.0", + "@wdio/tauri-service": "1.5.0", "adm-zip": "^0.6.1", "axios": "^1.20.0", "cli-color": "^2.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0a6847b9d..187ebdd18 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -200,26 +200,26 @@ importers: specifier: ^3.14.13 version: 3.14.13(react-dom@19.3.1(react@19.3.1))(react@19.3.1) '@tauri-apps/api': - specifier: 2.12.1 - version: 2.12.1 + specifier: 2.12.4 + version: 2.12.4 '@tauri-apps/plugin-clipboard-manager': - specifier: 2.4.0 - version: 2.4.0 + specifier: 2.5.0 + version: 2.5.0 '@tauri-apps/plugin-dialog': - specifier: 2.8.0 - version: 2.8.0 + specifier: 2.8.3 + version: 2.8.3 '@tauri-apps/plugin-fs': - specifier: 2.6.0 - version: 2.6.0 + specifier: 2.7.1 + version: 2.7.1 '@tauri-apps/plugin-http': - specifier: 2.8.0 - version: 2.8.0 + specifier: 2.8.3 + version: 2.8.3 '@tauri-apps/plugin-opener': - specifier: 2.7.0 - version: 2.7.0 + specifier: 2.7.2 + version: 2.7.2 '@tauri-apps/plugin-updater': - specifier: 2.13.1 - version: 2.13.1 + specifier: 2.14.0 + version: 2.14.0 ahooks: specifier: ^3.10.0 version: 3.10.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1) @@ -318,8 +318,8 @@ importers: specifier: ^10.0.1 version: 10.0.1(eslint@10.11.0(jiti@2.7.0)(supports-color@7.2.0)) '@tauri-apps/cli': - specifier: 2.12.1 - version: 2.12.1 + specifier: 2.12.3 + version: 2.12.3 '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 @@ -342,8 +342,8 @@ importers: specifier: ^6.1.1 version: 6.1.1(vite@8.3.0(@types/node@24.13.6)(esbuild@0.28.2)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1)) '@wdio/tauri-service': - specifier: 1.4.0 - version: 1.4.0(expect-webdriverio@5.7.0)(supports-color@7.2.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) + specifier: 1.5.0 + version: 1.5.0(expect-webdriverio@6.1.0)(supports-color@7.2.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) adm-zip: specifier: ^0.6.1 version: 0.6.1 @@ -2129,102 +2129,102 @@ packages: '@tanstack/virtual-core@3.17.11': resolution: {integrity: sha512-+ILjvtHup6Y2hzQ6YzwMgX1Q+oQpxEGOXCEsCNaPoIP0VxMbizIBTmYTDtkerkIQS8/CbP1BRuyt8V/8BCsy1g==} - '@tauri-apps/api@2.12.1': - resolution: {integrity: sha512-DeyFHa3wynpyoqTDikDEDGTJIq4LQ5USfolQGRmGIWT6JMADyxZBTDa5cAdT3tDg73rUXufPaCwN7aXBos4OnQ==} + '@tauri-apps/api@2.12.4': + resolution: {integrity: sha512-pVmfis+4zT8H0Qhp3xPZx9Ju7kpzvA6rr/PSJPyuwfvucTQ8sVt61NYU9KMkK703UFlYadFmjKA4HhybOtN0gg==} - '@tauri-apps/cli-darwin-arm64@2.12.1': - resolution: {integrity: sha512-8bMnbpJ2jKO/ufrOPL65EMHC3ptw7fzeraoQkwibyfGLqIl+UCWsC0152kmNbW6r9NvVQduXqAZF5mH1QgTWhw==} + '@tauri-apps/cli-darwin-arm64@2.12.3': + resolution: {integrity: sha512-xmVNoJOOKzKLj7GLHXmXLimRby9M42aBIJa0sB80N7o24eKV5JiVmToKTRLVH9yhL05GZ/B6rSSOmbzNFJwBAA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tauri-apps/cli-darwin-x64@2.12.1': - resolution: {integrity: sha512-G+2qte8GNqNlEZ9ftd21rbu/APVkl3r/nzNDI7LVxEoqJWVNe9GbEgQUMH1r4PHT20Z2UxR3KjCkltIb0e/Wjg==} + '@tauri-apps/cli-darwin-x64@2.12.3': + resolution: {integrity: sha512-URd+0usfmUQQyb5kNPiKt2OT8gp7oGU7QR+qOppB6e35mpVBFFVNhWc9oWb3p0u71fDJ09DpF4T6m9xYxoIB8g==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tauri-apps/cli-linux-arm-gnueabihf@2.12.1': - resolution: {integrity: sha512-5b3n4DaTW+A1Zntnh4Yn44VyLrlPEpB8kMOBRfWkzNnzolBk+AYhKIfKjCLmoC8Mob3ETodxAEOMkE2YPKEWzQ==} + '@tauri-apps/cli-linux-arm-gnueabihf@2.12.3': + resolution: {integrity: sha512-0kwUVx2LbmOoTRlwF1oDww7th4/NSluv4ZBQ6KRZsFKg4g0TlTcIiJ0VehqkQYUeC9xIT1Mk6XtF52mI155VSQ==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tauri-apps/cli-linux-arm64-gnu@2.12.1': - resolution: {integrity: sha512-APArHhDu+8pXSCkCQmvaz1nD3d8WTmlCoSS/oG475TJ6AATBvyQOAmf5qELgsQ4s2+8MOsop0Zd699RKELF1Cw==} + '@tauri-apps/cli-linux-arm64-gnu@2.12.3': + resolution: {integrity: sha512-gKSGDx6fx+HBLQmG6guChFdisbrCSdx9Yli+j5teOa64gm1CeM+C6NLru5Pj3ZkkEep05BmCFjxvX+cjqAycZQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [glibc] - '@tauri-apps/cli-linux-arm64-musl@2.12.1': - resolution: {integrity: sha512-JaCxcLoV0oGtllVkLr4UAHWG/wTfkEunnUqnsEsGYOp0VRxnUwHg63wFBD0jU2ul5eFfSLIDS4RF2gfzsSo5Jg==} + '@tauri-apps/cli-linux-arm64-musl@2.12.3': + resolution: {integrity: sha512-Yr59qMy/gcvAfBuFdCGlAmGiLsYWMFDbsP4bAI6iNBzcJTGrYWZGeiQhGDo29MQwfF/NUBqyM2qljXu5tZ6wjQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] libc: [musl] - '@tauri-apps/cli-linux-riscv64-gnu@2.12.1': - resolution: {integrity: sha512-K5+VXM7+SGVDwZleA2+lMgvbTVuA5e1tkiVEawu1Yxj26ZyEfO8h8xTC1rBdRX2xgJDSwCk6vPUBCS6i+Z5slQ==} + '@tauri-apps/cli-linux-riscv64-gnu@2.12.3': + resolution: {integrity: sha512-jKr0/REBMnLKC0OwPQZkyge0mKDaNZ0b/AbfGwVyCgFfwS730EVLfVDo3nt7MUu6jJaytRq08+xSj5qfy+U1+Q==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] libc: [glibc] - '@tauri-apps/cli-linux-x64-gnu@2.12.1': - resolution: {integrity: sha512-Z1QGPr49HJZMktu+Spu6Q1b/f9ANadXvqZZZt2645ua1x1ev6prOgp85eiGv2jRzohFEMLo6aJyaLjLUX5KIvA==} + '@tauri-apps/cli-linux-x64-gnu@2.12.3': + resolution: {integrity: sha512-gTkEqJAGCMROGanxHnzaJzQ+/rXl39HWVg0/hDODS1wDWBGqoceqGC6Qm1+mQbyT11xnsB8mKu/gyVID/YpFIw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [glibc] - '@tauri-apps/cli-linux-x64-musl@2.12.1': - resolution: {integrity: sha512-nHuEhRPOMSJ/8RRhtMRxB9B9lVr7xxpe4DapBz8x1GIau3vdzjHHJ1hAfmw+PyayPLZ6XoaVIHPgI17rX6ii8w==} + '@tauri-apps/cli-linux-x64-musl@2.12.3': + resolution: {integrity: sha512-T2dTxL1svRym71fZtaW4pZYXbthbfFsEJr1NeOUg/p7laWXZbUt/8DMSZf8recu9f7+1F/Lv00HtzsEu6vDO9w==} engines: {node: '>= 10'} cpu: [x64] os: [linux] libc: [musl] - '@tauri-apps/cli-win32-arm64-msvc@2.12.1': - resolution: {integrity: sha512-I0oPk2uGh86R8dAs2X5OxSP+/GqSc8jh1Px3l8EqrocSNivsRHDTh2k3PVOqdv163dlV6PIVvmhZAbH/lPfZrA==} + '@tauri-apps/cli-win32-arm64-msvc@2.12.3': + resolution: {integrity: sha512-eoiQwpEZWbpsVHcM9BAzqqe4TCHszvr3rsM7pUQ4ofLK0lF1i1d/jX0Qo5DYMqcrUtwQuDdDuOCbcT0Izf1VwQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tauri-apps/cli-win32-ia32-msvc@2.12.1': - resolution: {integrity: sha512-baNZRBfepAJ5qNFRMwzgBk94xQmkcmTZrNDjZjnzrq2vAaTC3NAhallb/zo3hyoCGQlMS13sdovktrg46NZz6Q==} + '@tauri-apps/cli-win32-ia32-msvc@2.12.3': + resolution: {integrity: sha512-kE+KUg6Dbbkgvcw0m99wJVIToFQzJqpMBAXah74WqxaLzssNwSTUccrHp6+QVzMhjQP330tvekFmnQF+0NbE6Q==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@tauri-apps/cli-win32-x64-msvc@2.12.1': - resolution: {integrity: sha512-dIFaKslrzcbesb+bBh+E1R9km241pHyj32w6D9FPtvQeYpRUFbiCLEa/2S+S0UnIytfxepp4P+X8IerGqnXeYg==} + '@tauri-apps/cli-win32-x64-msvc@2.12.3': + resolution: {integrity: sha512-L7wndWAgX2mLW7alswpL3d1R0P9FN2WYBgHaQkAYEBxHHGkY4vFX9CjcRQ1LAxDAMIJxrY7/aDziFJeChS84NQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tauri-apps/cli@2.12.1': - resolution: {integrity: sha512-kEDEiGzG+yAc5FeLxtXpES/VN+F2C8H0r4gDVtfRLKxT9np9101d9REG/Kgo2lr0hKi0IpDsODiHnU3+naOmLg==} + '@tauri-apps/cli@2.12.3': + resolution: {integrity: sha512-f7/LsY74SVb1ChmOPw1ajOpxii0GSzDAgmWHRci8JUYuuai04rXsSbFobpmB0sP2DdlvMD/B5ZotEn8GOGMRUg==} engines: {node: '>= 10'} hasBin: true - '@tauri-apps/plugin-clipboard-manager@2.4.0': - resolution: {integrity: sha512-yAuTffXc/sm+4oYnrwxbUkaJXQMTesPJ9dim0ADcA31rpboyhAN2TGQqs9VCcPIpb60LFOeePkvhpP2I3xhejg==} + '@tauri-apps/plugin-clipboard-manager@2.5.0': + resolution: {integrity: sha512-dibUy1nKURYDXRMvjNk4deAbTZ5jPQ8wCE4nolt5xniryWgXQ4sK2GkFXoXlHbRdPzfZptZj95BRLfalA7m/2Q==} - '@tauri-apps/plugin-dialog@2.8.0': - resolution: {integrity: sha512-HSSD5C8UFE9ijD1wue84F7jjaIReFmj8AAPtS+xyjYRltJafIc4BiWHY7SJ6vbbew6u+YljEJHfyNfy5VwywXg==} + '@tauri-apps/plugin-dialog@2.8.3': + resolution: {integrity: sha512-Hd/yBfk2R5v2MFrz/0VArSXeh8xKLLXGunqSiTtcHKn1zNZwaKujuA0VSwUvNfwC4hDoF1PveS+gBDNe3nHspw==} - '@tauri-apps/plugin-fs@2.6.0': - resolution: {integrity: sha512-MhBAZ4rryd+h9fijd/GWDfArqiAeGI0ZNduV4wuRyUVI6wDZ+oDBY7atqtoXKDwlTUVSvpvmWJAY0ehQd/v6Uw==} + '@tauri-apps/plugin-fs@2.7.1': + resolution: {integrity: sha512-4TBVjpi/q8PuNzjpkAc2iBGXMTLjOrAyfTiiOL8ORaJCZJRG3tjzmQ4sqs2CMG75FvLyRkOkERfP7AyY4iBNwQ==} - '@tauri-apps/plugin-http@2.8.0': - resolution: {integrity: sha512-cPvZvfUSaBkqGxef/dgbh/iEl6T3jQfSJyypi9OdcWr1VcuTt4ZRlk9DLAHEHF2q2NML+0UOkjyXRPNo6Cky6g==} + '@tauri-apps/plugin-http@2.8.3': + resolution: {integrity: sha512-MrgCnnxSnzxkMX+Tk1XXB8rSI9hfhUHQmtbn0EpflEDcSx04K1BDfrv51tcK27SCuU/B1j8sNHL0UZur/1iqKA==} - '@tauri-apps/plugin-opener@2.7.0': - resolution: {integrity: sha512-mBorYfVKh9Lt7s4ZFtKbMUTxBw+Y/sVmSlKCtkkoBgMTC/DIbt/kaPm67L/2djAUqDI1wbixy5OHHVmipjuGMw==} + '@tauri-apps/plugin-opener@2.7.2': + resolution: {integrity: sha512-LyybP1VSzTMQiaFYcsbAse47KpivlyXdLZMQzGLEnkgQacGESnpjAfFoQ6h5sqWgAdZDH9szYjPzHMpv0Sz+TQ==} - '@tauri-apps/plugin-updater@2.13.1': - resolution: {integrity: sha512-+STDzJ0sdQLImjc63zkv6Nncimqeo6jyCWoTQtbSwgGLNj1qbP9I6LC4p5R5ocBk3gNKAZs6i/AJz0jxysytiw==} + '@tauri-apps/plugin-updater@2.14.0': + resolution: {integrity: sha512-gdylJ9tger4hkyOn24QZd6MNOKVo2Eh53iw5th2Qj1vKTR/+u4PIwJWuiis5hohYvobn6iOvlnALfrqIPSzh7Q==} '@tybys/wasm-util@0.10.4': resolution: {integrity: sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==} @@ -2570,12 +2570,12 @@ packages: resolution: {integrity: sha512-n6elHE4ItKAtr4lwAaWIh/sAFuEFhyesLM27i5l9IWBJEK6VECdt0Pigj/4vUD2tliOoBtsWxphSW4oiNFXotg==} engines: {node: '>=22.19.0'} - '@wdio/globals@9.29.1': - resolution: {integrity: sha512-F96BKppx4HGD64v+s57TM4K4zaxqUCg2RXHk6sjB2xrSa7P+d2VYV28ID2ddF7iSodVfPlpa1i2/jy8jMGrU8w==} + '@wdio/globals@9.31.3': + resolution: {integrity: sha512-ZzmRKUlwUBahNoNxHbAzst+9dNInEjLQc7Z3c86OhDRxAf3Ivw8k2rc56UCbyYiZnkd1dOpuA91zFiTrUNNORw==} engines: {node: '>=18.20.0'} peerDependencies: - expect-webdriverio: ^5.6.5 - webdriverio: ^9.0.0 + expect-webdriverio: ^6.0.9 + webdriverio: ^9.28.0 '@wdio/logger@10.0.0': resolution: {integrity: sha512-kUIw0ZzMs1mvXOaLEcjrM1nqNXY1reaJKReKNcjDSnfhnfUIb0Q5pAsxiMeil2uR0WsSUPzn0r3D9v//7vTOkA==} @@ -2585,21 +2585,21 @@ packages: resolution: {integrity: sha512-0ZAEIo6PNyMIJPlOGkIgyOJUjcd0pC8/QHlVAAe1c91/IcjZ1X+k0yidXHaboJdN7dq1XPUacmhRdtua0U5EZg==} engines: {node: '>=18.20.0'} - '@wdio/native-core@1.2.0': - resolution: {integrity: sha512-Z/Qa2xmV/2IMSCsCKyVk79tda8n47FOOOS9XEOWGpHUiFr1z4gGOFxt13Fd9RQu9Kk1IA9fJB1VmJZtrtkXvEw==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.11.0} + '@wdio/native-core@1.3.0': + resolution: {integrity: sha512-wUwc0QTdvhD0LwH4YcRaN9JWLX/yac8sovddUR5/4sqHMNJr3yaN11bpIfYoD/bEk+1nTLjWuDCFpe5l5wUgLQ==} + engines: {node: '>=18.20.0'} - '@wdio/native-spy@1.3.0': - resolution: {integrity: sha512-Kw1/HsOM8CNnlPHozlv0FP+nFnms5efICq5WqpaNdwa0urv/C9K/jhM69OqAbocBfRXkDVuWecNPmCV9S/cXGw==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.11.0} + '@wdio/native-spy@1.4.0': + resolution: {integrity: sha512-unsC2Vgu5T9atD478Zj/p2N+rVSK4i/NibIaaEw4rZF/T5u5bmAHChFntEiBEfyMzd62VwbhKhzwwOSKjzrfJA==} + engines: {node: '>=18.20.0'} - '@wdio/native-types@2.5.0': - resolution: {integrity: sha512-NjaIfcsEKpU9gm0goywEG0A7J4pyEsgORKNrQ1xboSy10BeTk5QpgHWP1bNvqUnZrKoKJRonpSn81ZyYKghO1g==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.11.0} + '@wdio/native-types@2.6.0': + resolution: {integrity: sha512-MVMVpZTH+UY6nUtLClCzY4BQSIs/nCCHo81i4ClLR+b2NehyBvwccttXDAGPgf0icyHUhd+PgIPXaLgRcm4M9A==} + engines: {node: '>=18.20.0'} - '@wdio/native-utils@2.7.0': - resolution: {integrity: sha512-qCzc+5o4YVESApQB5//NxomZ+F+M3Pc02hUNnJ1/w9naMb8mfgaHXBLWVwejEfO36z2MnwGatBNWZAm38G1frA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.11.0} + '@wdio/native-utils@2.8.0': + resolution: {integrity: sha512-TmIkPAd19FkJ747AdFVEtawbakVV3HHCh8zk3Kl/FLc6B2bbea7hn90jtLxqBZgCVqUuJIBcMNFg/nV/hgBFOw==} + engines: {node: '>=18.20.0'} peerDependencies: tsx: ^4.22.4 peerDependenciesMeta: @@ -2614,17 +2614,17 @@ packages: resolution: {integrity: sha512-wAC9ksdWWv2E3Sj86eNKxB3IUt0gEyw9rgDGAWjk/GWgi6K3e+/n3erGNweI9JMJyC/+RNe0qHgVPQpRJMRVpg==} engines: {node: '>=22.19.0'} - '@wdio/reporter@9.30.1': - resolution: {integrity: sha512-0whWaLfJtOAy3PzbGUxGrCAGitgaUCMe8qUgAuP2l7ess70AXqvp1wJibw74a/Z2giegJlJiAc4PxS0abs9/tw==} + '@wdio/reporter@9.31.2': + resolution: {integrity: sha512-3cKE6vCOsro/Ep9dGTIbo3FBn3WNvJ++BIn32lFd9m19pFdjuwlVgLtPXHb9jWNCJs740h5AIUcVkcscqUYhAA==} engines: {node: '>=18.20.0'} - '@wdio/spec-reporter@9.30.1': - resolution: {integrity: sha512-En74iLuj8xjNanSPA05rTCii0qHZQe6Zpwi74vTGO6LtfGxvcNr1Z1zUj8xWwnoclnAne3DtmCAyXTezLX1pEA==} + '@wdio/spec-reporter@9.31.2': + resolution: {integrity: sha512-lNLLPUk4y1Yp5pWwBFF+tjZIy7bOv0TPTk4HDWV4LnnHnkc24abI0nN+kb2y5/JV8ZgwLCCVKUFRdRUxfKsAaQ==} engines: {node: '>=18.20.0'} - '@wdio/tauri-service@1.4.0': - resolution: {integrity: sha512-EUTS8tfMOXK1yPNEaRd6yiSdPoX19zeV+gtp2m7UuPTWFZGayPuMUoFyttP6Lx3OFvJC3lnbxjr1vcCNAOA7tg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.11.0} + '@wdio/tauri-service@1.5.0': + resolution: {integrity: sha512-S3fs8T+jgNOFi4x/X2z69unS/1K3ZB28+owBouhHtVnrMKeBWAKP46IHnp8c8AZXppn6fiPNC4M1jfRZbLKeKw==} + engines: {node: '>=18.20.0'} peerDependencies: webdriverio: ^9.0.0 @@ -2632,8 +2632,8 @@ packages: resolution: {integrity: sha512-HGP9lAYXCsLAXzugfT4khCh7tYByWOMIxZHCG+tUvgmpwNzi6lfIsxyIlWownXK1wYJUpk6tkDBX/iXwN+q0lg==} engines: {node: '>=22.19.0'} - '@wdio/types@9.30.1': - resolution: {integrity: sha512-umKQDbSmu3/ucUsIA5UUTK5gCWnClyVpWz3fC39044rCXQ3zCd1a3GoJibbAITKiwnPFf2yU3LvTa+C78sh9Lg==} + '@wdio/types@9.31.2': + resolution: {integrity: sha512-lQKaiQDCJJ6VC1K/cKzaAxCpwB9pL1U0VbmX2uGksMxO4EDbNuLvIxWryuUDJ7OaSYTjxILTKYFErdbT/xEikg==} engines: {node: '>=18.20.0'} '@wdio/utils@10.0.1': @@ -3418,13 +3418,13 @@ packages: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} - expect-webdriverio@5.7.0: - resolution: {integrity: sha512-jLOTrJoPBC3Wtd83ryHMbRcEajMGtAnn6OWtSnoJoDLt16nHvxVdjcI4Bc0n+1KAOr8DvQtlJ55f0M48kJtEpw==} + expect-webdriverio@6.1.0: + resolution: {integrity: sha512-RXgaXoH1U8IiAHPelkMhZSnWUT0HfIhkjKK8nBkIpnXRO+zJ8dRafoyZhVy5mu/LtoyIr9juRWRwN284OSNM6Q==} engines: {node: '>=20'} peerDependencies: '@wdio/globals': ^9.0.0 '@wdio/logger': ^9.0.0 - webdriverio: ^9.0.0 + webdriverio: ^9.28.0 expect@30.5.2: resolution: {integrity: sha512-0LNuMvs8/5mRYhnCR4k+lGV7fqPMs6Bnksda4S3zsCUmdxBpAn4zU4NNzXdq1pMKe/H4W5t/zVIDSJ/H3e0vDA==} @@ -6910,78 +6910,78 @@ snapshots: '@tanstack/virtual-core@3.17.11': {} - '@tauri-apps/api@2.12.1': {} + '@tauri-apps/api@2.12.4': {} - '@tauri-apps/cli-darwin-arm64@2.12.1': + '@tauri-apps/cli-darwin-arm64@2.12.3': optional: true - '@tauri-apps/cli-darwin-x64@2.12.1': + '@tauri-apps/cli-darwin-x64@2.12.3': optional: true - '@tauri-apps/cli-linux-arm-gnueabihf@2.12.1': + '@tauri-apps/cli-linux-arm-gnueabihf@2.12.3': optional: true - '@tauri-apps/cli-linux-arm64-gnu@2.12.1': + '@tauri-apps/cli-linux-arm64-gnu@2.12.3': optional: true - '@tauri-apps/cli-linux-arm64-musl@2.12.1': + '@tauri-apps/cli-linux-arm64-musl@2.12.3': optional: true - '@tauri-apps/cli-linux-riscv64-gnu@2.12.1': + '@tauri-apps/cli-linux-riscv64-gnu@2.12.3': optional: true - '@tauri-apps/cli-linux-x64-gnu@2.12.1': + '@tauri-apps/cli-linux-x64-gnu@2.12.3': optional: true - '@tauri-apps/cli-linux-x64-musl@2.12.1': + '@tauri-apps/cli-linux-x64-musl@2.12.3': optional: true - '@tauri-apps/cli-win32-arm64-msvc@2.12.1': + '@tauri-apps/cli-win32-arm64-msvc@2.12.3': optional: true - '@tauri-apps/cli-win32-ia32-msvc@2.12.1': + '@tauri-apps/cli-win32-ia32-msvc@2.12.3': optional: true - '@tauri-apps/cli-win32-x64-msvc@2.12.1': + '@tauri-apps/cli-win32-x64-msvc@2.12.3': optional: true - '@tauri-apps/cli@2.12.1': + '@tauri-apps/cli@2.12.3': optionalDependencies: - '@tauri-apps/cli-darwin-arm64': 2.12.1 - '@tauri-apps/cli-darwin-x64': 2.12.1 - '@tauri-apps/cli-linux-arm-gnueabihf': 2.12.1 - '@tauri-apps/cli-linux-arm64-gnu': 2.12.1 - '@tauri-apps/cli-linux-arm64-musl': 2.12.1 - '@tauri-apps/cli-linux-riscv64-gnu': 2.12.1 - '@tauri-apps/cli-linux-x64-gnu': 2.12.1 - '@tauri-apps/cli-linux-x64-musl': 2.12.1 - '@tauri-apps/cli-win32-arm64-msvc': 2.12.1 - '@tauri-apps/cli-win32-ia32-msvc': 2.12.1 - '@tauri-apps/cli-win32-x64-msvc': 2.12.1 + '@tauri-apps/cli-darwin-arm64': 2.12.3 + '@tauri-apps/cli-darwin-x64': 2.12.3 + '@tauri-apps/cli-linux-arm-gnueabihf': 2.12.3 + '@tauri-apps/cli-linux-arm64-gnu': 2.12.3 + '@tauri-apps/cli-linux-arm64-musl': 2.12.3 + '@tauri-apps/cli-linux-riscv64-gnu': 2.12.3 + '@tauri-apps/cli-linux-x64-gnu': 2.12.3 + '@tauri-apps/cli-linux-x64-musl': 2.12.3 + '@tauri-apps/cli-win32-arm64-msvc': 2.12.3 + '@tauri-apps/cli-win32-ia32-msvc': 2.12.3 + '@tauri-apps/cli-win32-x64-msvc': 2.12.3 - '@tauri-apps/plugin-clipboard-manager@2.4.0': + '@tauri-apps/plugin-clipboard-manager@2.5.0': dependencies: - '@tauri-apps/api': 2.12.1 + '@tauri-apps/api': 2.12.4 - '@tauri-apps/plugin-dialog@2.8.0': + '@tauri-apps/plugin-dialog@2.8.3': dependencies: - '@tauri-apps/api': 2.12.1 + '@tauri-apps/api': 2.12.4 - '@tauri-apps/plugin-fs@2.6.0': + '@tauri-apps/plugin-fs@2.7.1': dependencies: - '@tauri-apps/api': 2.12.1 + '@tauri-apps/api': 2.12.4 - '@tauri-apps/plugin-http@2.8.0': + '@tauri-apps/plugin-http@2.8.3': dependencies: - '@tauri-apps/api': 2.12.1 + '@tauri-apps/api': 2.12.4 - '@tauri-apps/plugin-opener@2.7.0': + '@tauri-apps/plugin-opener@2.7.2': dependencies: - '@tauri-apps/api': 2.12.1 + '@tauri-apps/api': 2.12.4 - '@tauri-apps/plugin-updater@2.13.1': + '@tauri-apps/plugin-updater@2.14.0': dependencies: - '@tauri-apps/api': 2.12.1 + '@tauri-apps/api': 2.12.4 '@tybys/wasm-util@0.10.4': dependencies: @@ -7323,9 +7323,9 @@ snapshots: - supports-color - yauzl - '@wdio/globals@9.29.1(expect-webdriverio@5.7.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0))': + '@wdio/globals@9.31.3(expect-webdriverio@6.1.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0))': dependencies: - expect-webdriverio: 5.7.0(@wdio/globals@9.29.1)(@wdio/logger@9.29.1)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) + expect-webdriverio: 6.1.0(@wdio/globals@9.31.3)(@wdio/logger@9.29.1)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) webdriverio: 10.0.2(supports-color@7.2.0)(yauzl@2.10.0) '@wdio/logger@10.0.0': @@ -7344,11 +7344,11 @@ snapshots: safe-regex2: 5.1.1 strip-ansi: 7.2.0 - '@wdio/native-core@1.2.0(supports-color@7.2.0)': + '@wdio/native-core@1.3.0(supports-color@7.2.0)': dependencies: '@wdio/logger': 9.29.1 - '@wdio/native-types': 2.5.0 - '@wdio/native-utils': 2.7.0(supports-color@7.2.0) + '@wdio/native-types': 2.6.0 + '@wdio/native-utils': 2.8.0(supports-color@7.2.0) debug: 4.4.3(supports-color@7.2.0) get-port: 7.2.0 tslib: 2.8.1 @@ -7356,11 +7356,11 @@ snapshots: - supports-color - tsx - '@wdio/native-spy@1.3.0': {} + '@wdio/native-spy@1.4.0': {} - '@wdio/native-types@2.5.0': {} + '@wdio/native-types@2.6.0': {} - '@wdio/native-utils@2.7.0(supports-color@7.2.0)': + '@wdio/native-utils@2.8.0(supports-color@7.2.0)': dependencies: '@wdio/logger': 9.29.1 debug: 4.4.3(supports-color@7.2.0) @@ -7378,32 +7378,32 @@ snapshots: dependencies: '@types/node': 22.20.5 - '@wdio/reporter@9.30.1': + '@wdio/reporter@9.31.2': dependencies: '@types/node': 20.19.43 '@wdio/logger': 9.29.1 - '@wdio/types': 9.30.1 + '@wdio/types': 9.31.2 diff: 8.0.4 object-inspect: 1.13.4 - '@wdio/spec-reporter@9.30.1': + '@wdio/spec-reporter@9.31.2': dependencies: - '@wdio/reporter': 9.30.1 - '@wdio/types': 9.30.1 + '@wdio/reporter': 9.31.2 + '@wdio/types': 9.31.2 chalk: 5.6.2 easy-table: 1.2.0 pretty-ms: 9.3.1 - '@wdio/tauri-service@1.4.0(expect-webdriverio@5.7.0)(supports-color@7.2.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0))': + '@wdio/tauri-service@1.5.0(expect-webdriverio@6.1.0)(supports-color@7.2.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0))': dependencies: - '@wdio/globals': 9.29.1(expect-webdriverio@5.7.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) + '@wdio/globals': 9.31.3(expect-webdriverio@6.1.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) '@wdio/logger': 9.29.1 - '@wdio/native-core': 1.2.0(supports-color@7.2.0) - '@wdio/native-spy': 1.3.0 - '@wdio/native-types': 2.5.0 - '@wdio/native-utils': 2.7.0(supports-color@7.2.0) - '@wdio/spec-reporter': 9.30.1 - '@wdio/types': 9.30.1 + '@wdio/native-core': 1.3.0(supports-color@7.2.0) + '@wdio/native-spy': 1.4.0 + '@wdio/native-types': 2.6.0 + '@wdio/native-utils': 2.8.0(supports-color@7.2.0) + '@wdio/spec-reporter': 9.31.2 + '@wdio/types': 9.31.2 debug: 4.4.3(supports-color@7.2.0) get-port: 7.2.0 tslib: 2.8.1 @@ -7417,7 +7417,7 @@ snapshots: dependencies: '@types/node': 22.20.5 - '@wdio/types@9.30.1': + '@wdio/types@9.31.2': dependencies: '@types/node': 20.19.43 @@ -8331,10 +8331,10 @@ snapshots: expect-type@1.4.0: {} - expect-webdriverio@5.7.0(@wdio/globals@9.29.1)(@wdio/logger@9.29.1)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)): + expect-webdriverio@6.1.0(@wdio/globals@9.31.3)(@wdio/logger@9.29.1)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)): dependencies: '@vitest/snapshot': 4.1.11 - '@wdio/globals': 9.29.1(expect-webdriverio@5.7.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) + '@wdio/globals': 9.31.3(expect-webdriverio@6.1.0)(webdriverio@10.0.2(supports-color@7.2.0)(yauzl@2.10.0)) '@wdio/logger': 9.29.1 deep-eql: 5.0.2 expect: 30.5.2 @@ -10005,7 +10005,7 @@ snapshots: tauri-plugin-mihomo-api@https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/7a03d16f4d39b1bb885b7babe66b9e153e34b615: dependencies: - '@tauri-apps/api': 2.12.1 + '@tauri-apps/api': 2.12.4 teex@1.0.1: dependencies: diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6b2f670bf..824c83107 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -29,7 +29,7 @@ perf-harness = ["dep:tauri-plugin-wdio-webdriver"] identifier = "io.github.clash-verge-rev.clash-verge-rev" [build-dependencies] -tauri-build = { version = "2.7.1", features = [] } +tauri-build = { version = "2.7.3", features = [] } [dependencies] clash-verge-draft = { workspace = true } @@ -72,12 +72,12 @@ sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs.git", branch "guard", ] } network-interface = { version = "2.0.5", features = ["serde"] } -tauri-plugin-shell = "2.4.0" -tauri-plugin-opener = "2.7.0" -tauri-plugin-dialog = "2.8.1" -tauri-plugin-fs = "2.6.0" +tauri-plugin-shell = "2.5.0" +tauri-plugin-opener = "2.7.2" +tauri-plugin-dialog = "2.8.3" +tauri-plugin-fs = "2.7.1" tauri-plugin-process = "2.4.0" -tauri-plugin-deep-link = "2.6.1" +tauri-plugin-deep-link = "2.6.2" tauri-plugin-window-state = "2.5.0" zip = "9.0.4" flate2 = "1.1.10" @@ -90,10 +90,10 @@ getrandom = "0.4.3" futures = "0.3.34" gethostname = "1.1.0" scopeguard = "1.2.0" -tauri-plugin-notification = "2.5.1" +tauri-plugin-notification = "2.7.0" tokio-stream = "0.1.19" backon = { version = "1.6.0", features = ["tokio-sleep"] } -tauri-plugin-http = "2.8.0" +tauri-plugin-http = "2.8.3" tracing = { workspace = true } tauri-plugin-devtools = { version = "2.2.2", optional = true } tauri-plugin-mihomo = { git = "https://github.com/clash-verge-rev/tauri-plugin-mihomo", rev = "7a03d16f4d39b1bb885b7babe66b9e153e34b615" } @@ -120,7 +120,7 @@ libc = "0.2.191" clash-verge-signal = { workspace = true } [target.'cfg(target_os = "macos")'.dependencies] -tauri-plugin-wdio-webdriver = { version = "=1.4.0", optional = true } +tauri-plugin-wdio-webdriver = { version = "=1.5.0", optional = true } objc2 = "0.6.5" objc2-foundation = { version = "0.3.2", features = [ "NSString", @@ -153,8 +153,8 @@ windows-sys.workspace = true [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] tauri-plugin-autostart = "2.7.0" -tauri-plugin-global-shortcut = "2.4.0" -tauri-plugin-updater = "2.13.1" +tauri-plugin-global-shortcut = "2.4.1" +tauri-plugin-updater = "2.14.0" [dev-dependencies] criterion = { workspace = true } From 02bd739ab68ceecb9637ecce006dc10bc5704655 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Wed, 21 Oct 2026 19:21:08 +0800 Subject: [PATCH 23/25] docs: clarify issue and PR intake rules --- .github/ISSUE_GUIDELINES.md | 33 ++++++++++++++++ .github/ISSUE_TEMPLATE/bug_report.yml | 4 ++ .github/ISSUE_TEMPLATE/feature_request.yml | 4 ++ .github/PULL_REQUEST_TEMPLATE.md | 8 +++- AGENTS.md | 46 ++++++++++++---------- 5 files changed, 73 insertions(+), 22 deletions(-) create mode 100644 .github/ISSUE_GUIDELINES.md diff --git a/.github/ISSUE_GUIDELINES.md b/.github/ISSUE_GUIDELINES.md new file mode 100644 index 000000000..d1740006c --- /dev/null +++ b/.github/ISSUE_GUIDELINES.md @@ -0,0 +1,33 @@ +# Issue Guidelines / Issue 提交指引 + +Use these suggestions to make reports easier to assess. State what you observed +and what you could not verify; unknown details are fine. + +以下建议有助于维护者评估问题。请说明实际观察到的现象和无法确认的部分;未知信息可以留空。 + +- Search existing issues by symptom, conditions, and outcome. Add new evidence + to an existing report when it describes the same problem. + 按现象、条件和结果搜索已有 Issue。若描述的是同一问题,请在原 Issue 中补充新证据。 +- Keep each issue to one distinct user problem or requested outcome. Split + unrelated findings instead of bundling an audit or checklist. + 每个 Issue 聚焦一个独立的问题或需求结果;无关发现请拆开,不要把审计清单打包成一个 Issue。 +- For bugs, include the version, operating system, steps, and actual versus + expected behavior when known. A root-cause diagnosis is not required. Share + only relevant logs and redact tokens or personal information. + 反馈 Bug 时,尽可能提供版本、操作系统、复现步骤及实际与预期行为。无需先判断根因;只提供相关日志,并遮盖令牌和个人信息。 +- For feature requests, describe the user task, current limitation, desired + outcome, and affected platforms. An implementation proposal is optional. + 提交功能请求时,请描述用户要完成的任务、当前限制、期望结果和适用平台;实现方案不是必填项。 +- Separate observations from guesses. An AI or scanner finding is a hypothesis + until its affected configuration, concrete impact, and supporting evidence + are stated; do not present a list of theoretical risks as confirmed bugs. + 区分观察结果和推测。AI 或扫描器的发现应先视为假设;请说明受影响的配置、具体影响和支持证据,不要把理论风险清单写成已确认的 Bug。 +- Do not post secrets, personal data, or sensitive exploit details in a public + issue. Ask maintainers how to share sensitive security information safely. + 请勿在公开 Issue 中发布密钥、个人信息或敏感利用细节;如涉及安全敏感信息,请先询问维护者如何安全提供。 +- AI assistance is welcome; human contributors do not need to disclose it. If + an AI agent or automation creates or co-authors an issue, add a final body line + such as `Assisted by: GPT-5.6 High`. Omit effort when the runtime does not + report it. Disclosure is transparency only, not evidence for or against issue + quality. + 欢迎使用 AI 辅助,人工提交者无需披露。如果 Issue 由 AI Agent 或自动化创建或共同撰写,请在正文末尾添加披露行,例如 `Assisted by: GPT-5.6 High`。运行环境未提供 effort 时可省略。披露仅用于提高透明度,不作为 Issue 质量的正面或负面证据。 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index ebce301f4..876cdd09c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -10,6 +10,8 @@ body: value: | ## 在提交问题之前,请确认以下事项: + 提交前可参考 [Issue 提交指引](https://github.com/clash-verge-rev/clash-verge-rev/blob/dev/.github/ISSUE_GUIDELINES.md),说明可观察到的问题和证据;不确定的原因请标为猜测。 + 1. 请 **确保** 您已经查阅了 [Clash Verge Rev 官方文档](https://clash-verge-rev.github.io/guide/term.html) 以及 [常见问题](https://clash-verge-rev.github.io/faq/windows.html) 2. 请 **确保** [已有的问题](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue) 中没有人提交过相似 issue,否则请在已有的 issue 下进行讨论 3. 请 **务必** 给 issue 填写一个简洁明了的标题,以便他人快速检索 @@ -19,6 +21,8 @@ body: ## Before submitting the issue, please make sure of the following checklist: + See the [Issue guidelines](https://github.com/clash-verge-rev/clash-verge-rev/blob/dev/.github/ISSUE_GUIDELINES.md) for how to describe observed behavior and evidence; mark uncertain causes as hypotheses. + 1. Please make sure you have read the [Clash Verge Rev official documentation](https://clash-verge-rev.github.io/guide/term.html) and [FAQ](https://clash-verge-rev.github.io/faq/windows.html) 2. Please make sure there is no similar issue in the [existing issues](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue), otherwise please discuss under the existing issue 3. Please be sure to fill in a concise and clear title for the issue so that others can quickly search diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index d30728a51..1ef2780ca 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -9,12 +9,16 @@ body: attributes: value: | ## 在提交问题之前,请确认以下事项: + 可参考 [Issue 提交指引](https://github.com/clash-verge-rev/clash-verge-rev/blob/dev/.github/ISSUE_GUIDELINES.md),描述用户任务、当前限制和期望结果。 + 1. 请 **确保** 您已经查阅了 [Clash Verge Rev 官方文档](https://clash-verge-rev.github.io/guide/term.html) 确认软件不存在类似的功能 2. 请 **确保** [已有的问题](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue) 中没有人提交过相似 issue,否则请在已有的 issue 下进行讨论 3. 请 **务必** 给issue填写一个简洁明了的标题,以便他人快速检索 4. 请 **务必** 先下载 [AutoBuild](https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/autobuild) 版本测试,确保该功能还未实现 5. 请 **务必** 按照模板规范详细描述问题,否则 issue 将会被关闭 ## Before submitting the issue, please make sure of the following checklist: + See the [Issue guidelines](https://github.com/clash-verge-rev/clash-verge-rev/blob/dev/.github/ISSUE_GUIDELINES.md) for describing the user task, current limitation, and desired outcome. + 1. Please make sure you have read the [Clash Verge Rev official documentation](https://clash-verge-rev.github.io/guide/term.html) to confirm that the software does not have similar functions 2. Please make sure there is no similar issue in the [existing issues](https://github.com/clash-verge-rev/clash-verge-rev/issues?q=is%3Aissue), otherwise please discuss under the existing issue 3. Please be sure to fill in a concise and clear title for the issue so that others can quickly search diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9d3da294d..5137b940b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,12 @@ ## Problem -What breaks or what is missing. Link the issue if one exists (`Fixes #123`). +What breaks or what is missing. Product bug fixes and features require a +pre-existing issue; link it here (`Fixes #123` only when this PR fully resolves +it). Maintenance work (such as chore, perf, docs, refactor, test, CI/build, +dependency, style, routine localization, or release changes) does not require +an issue link; link one when it defines the scope. For reverts, link the PR or +commit being reverted. For security-sensitive fixes that cannot be tracked +publicly, follow maintainer-approved private tracking. ## Approach diff --git a/AGENTS.md b/AGENTS.md index ce9822479..d6ec809a9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,22 +18,25 @@ These rules apply to every change, whether human- or agent-authored. They match the ownership evidence the AI-slop review evaluates (see [`pr-ai-slop-review.md`](.github/workflows/pr-ai-slop-review.md)). -1. **Issue first.** Non-trivial changes require a pre-existing issue describing - the problem. If none exists, ask the maintainers to open or approve one - before implementing. +1. **Issue first.** Product bug fixes and features require a pre-existing issue; + self-scoped maintenance work does not. Follow the PR template for linkage and + revert references. If a required issue is missing, ask maintainers to open or + approve one before implementing. For security-sensitive fixes that cannot be + tracked publicly, follow maintainer-approved private tracking. 2. **Scope discipline.** Every changed file must be justifiable from the linked - issue. No drive-by refactors, renames, formatting churn, or dependency bumps - unrelated to the problem being fixed. + issue or the stated PR scope. No drive-by refactors, renames, formatting + churn, or dependency bumps unrelated to the work. 3. **Author accountability.** AI assistance is welcome, but the contributor owns the result: understand the change, describe the problem and approach in your own words, and verify the change against the reported behavior before submitting. 4. **Tests are justified, not default.** Do not add tests, test scaffolding, or - speculative defensive code unless the linked issue demands them. When a test - is genuinely necessary — it reproduces the reported regression or guards - behavior whose breakage would otherwise go unnoticed — keep it minimal and - state in the PR body why it is needed. Bulk test files and defensive - programming for hypothetical failure modes are PR bloat, not rigor. + speculative defensive code unless the linked issue or stated task demands + them. When a test is genuinely necessary — it reproduces the reported + regression or guards behavior whose breakage would otherwise go unnoticed — + keep it minimal and state in the PR body why it is needed. Bulk test files + and defensive programming for hypothetical failure modes are PR bloat, not + rigor. 5. **Comments state constraints, not narration.** Write a comment only for a non-obvious constraint the code cannot express; never restate what the code does. @@ -44,13 +47,12 @@ the ownership evidence the AI-slop review evaluates (see real evidence instead: reproduction steps, failure output, targeted tests. 8. **Minimal diffs.** Match the surrounding code's style, naming, and comment density. Do not introduce new dependencies or restructure working code unless - the issue demands it. -9. **Disclose AI automation.** When an agent produces or co-produces a change, - append a footer line to the PR body with the model and effort used (e.g. - `Assisted by: GPT-5.6 High`). The PR template intentionally omits this line — - the agent adds it itself, humans are not asked to declare anything. Effort may - be omitted when the runtime does not report it. Disclosure is transparency - only; it does not substitute for any rule above. + the linked issue or stated task demands it. +9. **Disclose AI automation.** When an agent creates or co-creates a PR or Issue, + append a final body line with the model and effort used (e.g. + `Assisted by: GPT-5.6 High`). Effort may be omitted when the runtime does not + report it. Human contributors are not asked to disclose AI assistance. + Disclosure is transparency only and carries no positive or negative weight. 10. **Compiled workflows.** The AI-slop review policy in [pr-ai-slop-review.md](.github/workflows/pr-ai-slop-review.md) is compiled: after editing it, run `gh aw compile` and commit the regenerated @@ -59,8 +61,10 @@ the ownership evidence the AI-slop review evaluates (see [`template/Changelog.md`](template/Changelog.md): one line per user-visible change, no internals. -## Pull Request Shape +## Issue and PR Workflows -Describe three things, briefly: the problem (with issue link), why this approach -solves it, and what changed. See -[`PULL_REQUEST_TEMPLATE.md`](.github/PULL_REQUEST_TEMPLATE.md). +When drafting, triaging, splitting, or implementing from a community issue, use +the conditional checklist in [`.github/ISSUE_GUIDELINES.md`](.github/ISSUE_GUIDELINES.md). +Do not make GitHub issue changes without explicit authorization. For PRs, follow +the directly loaded [PR template](.github/PULL_REQUEST_TEMPLATE.md); do not +duplicate its prompts here. From 8b88ddb7f24fbf9890a44f5a32bd13e6d2095069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9D=A4=E6=98=AF=E7=BA=B1=E9=9B=BE=E9=85=B1=E5=93=9F?= =?UTF-8?q?=EF=BD=9E?= <49941141+Dragon1573@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:25:15 +0000 Subject: [PATCH 24/25] chore(deps): update node.js to v24.22.1 (#8389) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .devcontainer/devcontainer.json | 2 +- .github/workflows/autobuild.yml | 10 +++++----- .github/workflows/cross_check.yaml | 2 +- .github/workflows/dev.yml | 2 +- .github/workflows/frontend-check.yml | 4 ++-- .github/workflows/release.yml | 12 ++++++------ .github/workflows/signpath-test.yml | 2 +- .github/workflows/telegram-notify.yml | 2 +- .github/workflows/updater.yml | 4 ++-- .tool-versions | 2 +- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index bdc7220f7..aa1703588 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ "features": { "ghcr.io/devcontainers/features/node:2": { - "version": "24.22.0", + "version": "24.22.1", "pnpmVersion": "12.14.0" }, "ghcr.io/devcontainers/features/rust:1": { diff --git a/.github/workflows/autobuild.yml b/.github/workflows/autobuild.yml index bd4454978..577d7d360 100644 --- a/.github/workflows/autobuild.yml +++ b/.github/workflows/autobuild.yml @@ -51,7 +51,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - name: Install dependencies run: pnpm install --frozen-lockfile @@ -185,7 +185,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' cache: 'pnpm' - name: Pnpm Cache @@ -282,7 +282,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' cache: 'pnpm' - name: Pnpm Cache @@ -426,7 +426,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' cache: 'pnpm' - name: Pnpm Cache @@ -524,7 +524,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6.1.0 name: Install pnpm diff --git a/.github/workflows/cross_check.yaml b/.github/workflows/cross_check.yaml index 3a57d9a77..1366e0c7a 100644 --- a/.github/workflows/cross_check.yaml +++ b/.github/workflows/cross_check.yaml @@ -43,7 +43,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6 name: Install pnpm diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index e7d0b0148..ec8a7d320 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -103,7 +103,7 @@ jobs: if: github.event.inputs[matrix.input] == 'true' uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' cache: 'pnpm' - name: Pnpm Cache diff --git a/.github/workflows/frontend-check.yml b/.github/workflows/frontend-check.yml index eb02eab42..2df2f0cdd 100644 --- a/.github/workflows/frontend-check.yml +++ b/.github/workflows/frontend-check.yml @@ -52,7 +52,7 @@ jobs: - uses: actions/setup-node@v7 if: steps.check_frontend.outputs.frontend == 'true' with: - node-version: '24.22.0' + node-version: '24.22.1' cache: 'pnpm' - name: Restore pnpm cache @@ -138,7 +138,7 @@ jobs: - uses: actions/setup-node@v7 if: steps.check_inputs.outputs.contract == 'true' with: - node-version: '24.22.0' + node-version: '24.22.1' cache: 'pnpm' - run: pnpm install --frozen-lockfile diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 97edf94bc..0e075ad35 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -230,7 +230,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -331,7 +331,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - name: Install pnpm uses: pnpm/action-setup@v6 @@ -466,7 +466,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -547,7 +547,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -573,7 +573,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -638,7 +638,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6 name: Install pnpm diff --git a/.github/workflows/signpath-test.yml b/.github/workflows/signpath-test.yml index 4f091646c..2d2055d24 100644 --- a/.github/workflows/signpath-test.yml +++ b/.github/workflows/signpath-test.yml @@ -28,7 +28,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - name: Install pnpm uses: pnpm/action-setup@v6 diff --git a/.github/workflows/telegram-notify.yml b/.github/workflows/telegram-notify.yml index 782466afa..ac3e7e82d 100644 --- a/.github/workflows/telegram-notify.yml +++ b/.github/workflows/telegram-notify.yml @@ -34,7 +34,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6 name: Install pnpm diff --git a/.github/workflows/updater.yml b/.github/workflows/updater.yml index f773f64b8..f55927bf6 100644 --- a/.github/workflows/updater.yml +++ b/.github/workflows/updater.yml @@ -15,7 +15,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6 name: Install pnpm @@ -39,7 +39,7 @@ jobs: - name: Install Node uses: actions/setup-node@v7 with: - node-version: '24.22.0' + node-version: '24.22.1' - uses: pnpm/action-setup@v6 name: Install pnpm diff --git a/.tool-versions b/.tool-versions index b422ea8d4..a9a8ee0a3 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -nodejs 24.22.0 +nodejs 24.22.1 pnpm 12.14.0 rust 1.99.1 From 3d9a79a3fb4d324ac66033cd3e27413eb6331e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9D=A4=E6=98=AF=E7=BA=B1=E9=9B=BE=E9=85=B1=E5=93=9F?= =?UTF-8?q?=EF=BD=9E?= <49941141+Dragon1573@users.noreply.github.com> Date: Thu, 22 Oct 2026 09:59:10 +0000 Subject: [PATCH 25/25] fix(windows): patch executable for common-controls-v6 (#8378) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Enhance patch logic, also patch for "example" executables Signed-off-by: ❤是纱雾酱哟~ <49941141+Dragon1573@users.noreply.github.com> --- src-tauri/build.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 8cdf2daf5..13df77750 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -1,10 +1,9 @@ fn main() -> Result<(), Box> { if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") && std::env::var("CARGO_CFG_TARGET_ENV").as_deref() == Ok("msvc") - && std::env::var_os("CARGO_FEATURE_CLIPPY").is_some() { - // Tauri's resource is linked to the app binary, but not to Rust unit-test harnesses. - // Give mock-context builds their own manifest so tests can resolve TaskDialogIndirect. + // Tauri's resource is linked to the app binary, but not to Rust unit-test harnesses or examples. + // Give non-app targets their own manifest so tests and examples can resolve TaskDialogIndirect. let out_dir = std::env::var_os("OUT_DIR").ok_or_else(|| std::io::Error::other("OUT_DIR is not set"))?; let manifest_path = std::path::PathBuf::from(out_dir).join("windows-test-manifest.xml"); std::fs::write( @@ -25,8 +24,14 @@ fn main() -> Result<(), Box> { "#, )?; - println!("cargo:rustc-link-arg=/MANIFEST:EMBED"); - println!("cargo:rustc-link-arg=/MANIFESTINPUT:{}", manifest_path.display()); + let manifest_display = manifest_path.display(); + if std::env::var_os("CARGO_FEATURE_CLIPPY").is_some() { + println!("cargo:rustc-link-arg=/MANIFEST:EMBED"); + println!("cargo:rustc-link-arg=/MANIFESTINPUT:{manifest_display}"); + } else { + println!("cargo:rustc-link-arg-examples=/MANIFEST:EMBED"); + println!("cargo:rustc-link-arg-examples=/MANIFESTINPUT:{manifest_display}"); + } } #[cfg(feature = "clippy")]