diff --git a/.github/release-notes/v0.2.0-beta.9.json b/.github/release-notes/v0.2.0-beta.9.json new file mode 100644 index 0000000..60e25e5 --- /dev/null +++ b/.github/release-notes/v0.2.0-beta.9.json @@ -0,0 +1,39 @@ +{ + "format": "codex-styler-release-notes-v1", + "version": "0.2.0-beta.9", + "defaultLocale": "en", + "locales": { + "en": { + "summary": "Managed launch now selects the stable Codex workspace from every trusted loopback CDP page and reports bounded, actionable failures.", + "highlights": [ + "All trusted loopback page targets are checked, so avatar overlays and other auxiliary Codex pages no longer hide the main workspace.", + "The same ready workspace WebSocket must pass three consecutive samples even when target ordering changes.", + "Per-candidate and overall time bounds prevent a temporary or unresponsive renderer from blocking launch indefinitely.", + "The affected multi-page macOS launch and theme-application path was verified with Codex 26.715.61943 on Apple Silicon." + ], + "fixes": [ + "Fixed Restart Codex & apply remaining disconnected when an avatar-overlay page appeared before the main workspace.", + "Fixed the first trusted CDP candidate preventing later ready candidates from being evaluated.", + "Fixed failed launch discovery remaining permanently in the launching state with no lifecycle event.", + "Added redacted launch-error diagnostics while preserving loopback-only validation and renderer-replacement recovery.", + "Cleared the frontend dependency audit by resolving astro, fast-uri, js-yaml, nanoid, and postcss to patched releases." + ] + }, + "zh-CN": { + "summary": "受控启动现在会从全部可信的本地 CDP 页面中选择稳定的 Codex 主工作区,并以有界、可诊断的方式处理失败。", + "highlights": [ + "检查全部可信的本地 page 目标,头像浮层及其他 Codex 辅助页面不再遮蔽主工作区。", + "即使目标顺序发生变化,同一工作区 WebSocket 仍须连续三次通过就绪检查。", + "单候选和整体等待均有明确上限,临时或无响应的渲染器不会再无限阻塞启动。", + "已在 Apple Silicon 上使用 Codex 26.715.61943 验证受影响的多页面 macOS 启动与主题应用链路。" + ], + "fixes": [ + "修复头像浮层页面排在主工作区之前时,“重启 Codex 并应用”始终保持未连接的问题。", + "修复第一个可信 CDP 候选阻止后续已就绪候选继续检查的问题。", + "修复启动发现失败后永久停留在 launching 且没有生命周期事件的问题。", + "新增脱敏的启动错误诊断,同时保留仅限本机回环的校验与渲染器替换恢复机制。", + "已将 astro、fast-uri、js-yaml、nanoid 与 postcss 升级到补丁版本,清零前端依赖审计告警。" + ] + } + } +} diff --git a/.github/release-notes/v0.2.0-beta.9.md b/.github/release-notes/v0.2.0-beta.9.md new file mode 100644 index 0000000..f1b5665 --- /dev/null +++ b/.github/release-notes/v0.2.0-beta.9.md @@ -0,0 +1,106 @@ +# Codex Styler 0.2.0-beta.9 — Reliable Multi-page Codex Launch + +Beta 9 fixes managed launch on Codex sessions that expose more than one trusted +CDP page. Styler now checks every loopback candidate, selects the stable main +workspace, and records an actionable failure instead of remaining indefinitely +in `launching` when no usable renderer appears. + +Release tag: `v0.2.0-beta.9` + +## Download and install + +### macOS 13+ on Apple Silicon + +1. Download `Codex-Styler_0.2.0-beta.9_aarch64-unsigned.dmg`. +2. Compare its SHA-256 digest with `SHA256SUMS.txt`. +3. Open the DMG and drag Codex Styler to Applications. +4. On first launch, Control-click Codex Styler and choose **Open**. + +The macOS app is ad-hoc signed, does not have an Apple Developer ID signature, +and is not notarized. Do not disable Gatekeeper globally. + +### Windows 11 x64 — community-validation Beta + +1. Download `Codex-Styler_0.2.0-beta.9_x64-unsigned-setup.exe`. +2. Compare its SHA-256 digest with `SHA256SUMS.txt`. +3. Review the GitHub build attestation, then run the per-user installer. + +The Windows installer is not Authenticode-signed, so SmartScreen may show an +unknown-publisher warning. It is built and structurally verified on a +GitHub-hosted Windows runner, but still requires independent real-device +evidence before RC. + +## Multi-page CDP compatibility + +- Styler evaluates all trusted `page` targets returned by the loopback-only CDP + endpoint instead of assuming the first target is the Codex workspace. +- Auxiliary pages such as avatar overlays, startup, login, upgrade, or settings + surfaces can appear before or after the main page without blocking it. +- Every candidate must retain the reserved `127.0.0.1` WebSocket port and pass + the live workspace readiness check. +- Candidate checks run independently with a bounded timeout, so an unresponsive + temporary renderer cannot prevent a later workspace from being selected. +- The same workspace WebSocket must be ready in three consecutive polls even if + the order of CDP targets changes between samples. + +## Failure recovery and diagnostics + +- The complete discovery operation has a hard time limit. +- A failed launch now transitions to an explicit error state, retains the + redacted error message, and records a `launch/error` lifecycle event. +- Diagnostics no longer report an indefinitely stale `launching` state with no + lifecycle history after target discovery fails. +- Existing renderer-replacement recovery during apply remains active. + +## Validation + +- The regression suite covers the overlay before the workspace, the workspace + before the overlay, multiple unready trusted pages, a timed-out first + candidate, candidate-order changes, stable sampling, and bounded failure. +- Rust formatting, Clippy with warnings denied, all Rust tests, all desktop + frontend tests, TypeScript checks, and production builds are release gates. +- The frontend dependency audit resolves `astro`, `fast-uri`, `js-yaml`, + `nanoid`, and `postcss` to patched releases with no remaining advisory. +- An affected Apple Silicon Mac running Codex `26.715.61943` exercised managed + restart and theme application with an avatar-overlay page preceding the main + workspace. The focused regression passed after this fix. + +The affected-device run confirms this launch/apply regression. It does not by +itself claim the full route, companion, pause, restore, update, uninstall, and +multi-device evidence required for RC or for adding that Codex build to the +complete public tested matrix. + +## Release evidence + +- `SHA256SUMS.txt` covers both installers and the macOS updater archive. +- `Codex-Styler_0.2.0-beta.9.spdx.json` exports the dependency graph as SPDX + 2.3. +- GitHub artifact attestations cover both installers; platform updater + artifacts carry Tauri signatures. +- `latest.json` contains macOS Apple Silicon and Windows x64 update entries. +- `release-notes.json` contains validated English and Simplified Chinese + summaries for the pre-download update panel. + +Verify installers with GitHub CLI: + +```bash +gh attestation verify Codex-Styler_0.2.0-beta.9_aarch64-unsigned.dmg \ + --repo xuhuanstudio/codex-styler + +gh attestation verify Codex-Styler_0.2.0-beta.9_x64-unsigned-setup.exe \ + --repo xuhuanstudio/codex-styler +``` + +## Beta limitations + +- Windows startup, managed restart, update, restore, and uninstall still need + independent community real-device reports before RC. +- Composer Interactions depend on Codex's native configuration semantics and + may require an adapter update after a substantial upstream control redesign. +- Complex-background automatic segmentation, video backgrounds, multi-entity + scenes, 3D/WebGL, macOS Intel, Windows ARM64, and Linux remain outside 0.2. +- macOS notarization and Windows Authenticode signing remain required before v1 + Stable. + +Codex Styler is unofficial and is not affiliated with, endorsed by, or +sponsored by OpenAI. diff --git a/CHANGELOG.md b/CHANGELOG.md index 441851e..4a1ddc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,31 @@ All notable changes will be documented here. The project follows Semantic Versio ## [Unreleased] +## [0.2.0-beta.9] - 2026-08-09 + +### Changed + +- Managed launch now evaluates every trusted loopback CDP page concurrently and + selects the workspace renderer that passes the live readiness check, instead + of assuming the first trusted page is the main Codex window. +- Ready-renderer tracking is keyed by WebSocket identity, so target ordering can + change while the same workspace still satisfies three consecutive stable + samples. + +### Fixed + +- Codex installations that expose an avatar overlay or another auxiliary app + page before the main workspace no longer remain disconnected after + **Restart Codex & apply**. +- A slow or unresponsive auxiliary renderer can no longer block discovery of a + later ready workspace; each candidate and the overall discovery operation + now have explicit time bounds. +- Failed managed launches now enter an actionable error state and record a + redacted `launch/error` lifecycle event instead of remaining indefinitely in + `launching` with an empty diagnostic history. +- Cleared the frontend dependency audit by resolving `astro`, `fast-uri`, + `js-yaml`, `nanoid`, and `postcss` to fixed releases. + ## [0.2.0-beta.8] - 2026-07-20 ### Added diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index 4e08888..cc5e35a 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -2,13 +2,13 @@ Compatibility is claimed only after real-device validation. -| Platform | Architecture | Beta 8 status | RC requirement | -| ---------- | ------------- | ----------------------------------------------------------------------- | ----------------------------------------- | -| macOS 13+ | Apple Silicon | Ad-hoc signed Beta; locally built, installed, and exercised | Two complete real-device runs | -| Windows 11 | x64 | CI-built unsigned Beta; lifecycle fixes await community device evidence | Two complete independent real-device runs | -| macOS | Intel | Not verified | Out of 0.2 scope | -| Windows | ARM64 | Not verified | Out of 0.2 scope | -| Linux | — | Unsupported | Out of 0.2 scope | +| Platform | Architecture | Beta 9 status | RC requirement | +| ---------- | ------------- | ------------------------------------------------------------------------------- | ----------------------------------------- | +| macOS 13+ | Apple Silicon | Ad-hoc signed Beta; multi-page CDP restart/apply verified on an affected device | Two complete real-device runs | +| Windows 11 | x64 | CI-built unsigned Beta; lifecycle fixes await community device evidence | Two complete independent real-device runs | +| macOS | Intel | Not verified | Out of 0.2 scope | +| Windows | ARM64 | Not verified | Out of 0.2 scope | +| Linux | — | Unsupported | Out of 0.2 scope | ## Codex versions and runtime strategy @@ -22,6 +22,13 @@ The health check runs after initial application and again after Codex route or D The semantic adapter currently has direct fixture evidence for Codex versions `26.707.72221` and `26.707.91948`. A version enters the public tested matrix only after detection, launch, application, route changes, companion update, pause, restore, normal restart, and the supported-platform lifecycle are verified on a real device. +Beta 9 also has focused Apple Silicon evidence for Codex `26.715.61943` in a +multi-page CDP session where an avatar-overlay page preceded the main +workspace. Managed restart and theme application succeeded after the target +selection fix. This focused regression run is recorded separately and does not +claim the complete lifecycle evidence required to add that Codex version to the +public tested matrix. + Codex Styler does not promise permanent compatibility with every Codex release. Run Settings → **Diagnostics & compatibility**, preview the redacted report, and attach the exported ZIP manually to a compatibility issue when reporting a regression. ## Installation discovery diff --git a/README.md b/README.md index 7a1ad7d..cfa1971 100644 --- a/README.md +++ b/README.md @@ -15,21 +15,21 @@

简体中文 · - Download Beta · + Download Beta · Website · Documentation

CI - Preview version + Preview version Apache-2.0 CC BY 4.0 assets macOS and Windows

> [!IMPORTANT] -> Codex Styler 0.2 is a Creator Beta. The macOS DMG is ad-hoc signed but not notarized, and the Windows EXE is not Authenticode-signed. Windows Beta 8 retains the rebuilt Store launch and bounded restart lifecycle and still awaits community real-device verification; v1 Stable remains gated on complete evidence and platform code signing. +> Codex Styler 0.2 is a Creator Beta. The macOS DMG is ad-hoc signed but not notarized, and the Windows EXE is not Authenticode-signed. Beta 9 adds bounded multi-page CDP target selection verified on an affected Apple Silicon Mac; Windows still awaits community real-device verification, and v1 Stable remains gated on complete evidence and platform code signing. ![Gilded Grandeur Codex theme with the Reset God companion](docs/media/codex-theme-gilded-grandeur.webp) @@ -115,14 +115,14 @@ Companions are selected independently from themes. Native Refined, Nocturne Stud Every shipped image and sprite is original project artwork. The reference repositories are studied for ideas only; their assets and source are not redistributed. -## Download Creator Beta 8 +## Download Creator Beta 9 -- **[macOS 13+ / Apple Silicon — DMG](https://github.com/xuhuanstudio/codex-styler/releases/download/v0.2.0-beta.8/Codex-Styler_0.2.0-beta.8_aarch64-unsigned.dmg)** -- **[Windows 11 / x64 — installer EXE](https://github.com/xuhuanstudio/codex-styler/releases/download/v0.2.0-beta.8/Codex-Styler_0.2.0-beta.8_x64-unsigned-setup.exe)** +- **[macOS 13+ / Apple Silicon — DMG](https://github.com/xuhuanstudio/codex-styler/releases/download/v0.2.0-beta.9/Codex-Styler_0.2.0-beta.9_aarch64-unsigned.dmg)** +- **[Windows 11 / x64 — installer EXE](https://github.com/xuhuanstudio/codex-styler/releases/download/v0.2.0-beta.9/Codex-Styler_0.2.0-beta.9_x64-unsigned-setup.exe)** On macOS, open the DMG, drag Codex Styler to Applications, then Control-click the app and choose **Open** on first launch. On Windows, SmartScreen may warn because this Beta does not yet have an Authenticode certificate; inspect the published checksum and provenance before continuing. Never disable Gatekeeper or SmartScreen globally. -The [pre-release page](https://github.com/xuhuanstudio/codex-styler/releases/tag/v0.2.0-beta.8) includes SHA-256 checksums, an SPDX SBOM, build attestations, updater artifacts, tested scope, and known limitations. Intel macOS is not included. Windows Beta 8 is CI-built and structurally verified but remains marked as awaiting community real-device validation. +The [pre-release page](https://github.com/xuhuanstudio/codex-styler/releases/tag/v0.2.0-beta.9) includes SHA-256 checksums, an SPDX SBOM, build attestations, updater artifacts, tested scope, and known limitations. Intel macOS is not included. Windows Beta 9 is CI-built and structurally verified but remains marked as awaiting community real-device validation. ## Run from source diff --git a/README.zh-CN.md b/README.zh-CN.md index 9f0a615..eb3d829 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -15,13 +15,13 @@

English · - 下载 Beta · + 下载 Beta · 项目网站 · 使用文档

> [!IMPORTANT] -> Codex Styler 0.2 当前处于创作器 Beta 阶段。macOS DMG 采用临时 ad-hoc 签名但尚未公证,Windows EXE 尚未进行 Authenticode 代码签名;Windows Beta 8 延续已重构的 Store 启动与有界重启链路,但仍等待社区实机验证,完成证据闭环和双平台签名前不会标记为稳定版。 +> Codex Styler 0.2 当前处于创作器 Beta 阶段。macOS DMG 采用临时 ad-hoc 签名但尚未公证,Windows EXE 尚未进行 Authenticode 代码签名;Beta 9 新增经过受影响 Apple Silicon Mac 验证的有界多页面 CDP 目标选择,Windows 仍等待社区实机验证,完成证据闭环和双平台签名前不会标记为稳定版。 ![金辉盛境 Codex 主题与 Reset God 互动伙伴](docs/media/codex-theme-gilded-grandeur.webp) @@ -107,14 +107,14 @@ Codex Styler 管理器可以跟随系统,也可以固定使用亮色或暗色 所有随项目分发的图片和序列帧都是原创资源。参考仓库只用于研究思路,不复制或重新分发其代码与素材。 -## 下载创作器 Beta 8 +## 下载创作器 Beta 9 -- **[macOS 13+ / Apple Silicon — DMG](https://github.com/xuhuanstudio/codex-styler/releases/download/v0.2.0-beta.8/Codex-Styler_0.2.0-beta.8_aarch64-unsigned.dmg)** -- **[Windows 11 / x64 — 安装 EXE](https://github.com/xuhuanstudio/codex-styler/releases/download/v0.2.0-beta.8/Codex-Styler_0.2.0-beta.8_x64-unsigned-setup.exe)** +- **[macOS 13+ / Apple Silicon — DMG](https://github.com/xuhuanstudio/codex-styler/releases/download/v0.2.0-beta.9/Codex-Styler_0.2.0-beta.9_aarch64-unsigned.dmg)** +- **[Windows 11 / x64 — 安装 EXE](https://github.com/xuhuanstudio/codex-styler/releases/download/v0.2.0-beta.9/Codex-Styler_0.2.0-beta.9_x64-unsigned-setup.exe)** 在 macOS 上打开 DMG,把 Codex Styler 拖入“应用程序”,首次启动时按住 Control 点击应用并选择“打开”。Windows 版因为当前 Beta 尚无 Authenticode 证书,SmartScreen 可能显示提醒;继续前请先核对 Release 中的校验和与构建证明。不要全局关闭 Gatekeeper 或 SmartScreen。 -[预发布页面](https://github.com/xuhuanstudio/codex-styler/releases/tag/v0.2.0-beta.8)同时提供 SHA-256 校验文件、SPDX SBOM、构建证明、更新包、已验证范围和已知限制。本次不提供 Intel Mac 安装包;Windows Beta 8 由 CI 构建并完成结构校验,但仍明确标记为等待社区实机验证。 +[预发布页面](https://github.com/xuhuanstudio/codex-styler/releases/tag/v0.2.0-beta.9)同时提供 SHA-256 校验文件、SPDX SBOM、构建证明、更新包、已验证范围和已知限制。本次不提供 Intel Mac 安装包;Windows Beta 9 由 CI 构建并完成结构校验,但仍明确标记为等待社区实机验证。 ## 从源码运行 diff --git a/ROADMAP.md b/ROADMAP.md index fd07c64..f97051d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -107,8 +107,9 @@ depends on an undocumented manual restart or hidden application state. 6. `v0.2.0-beta.6`: ordinary-user setup journey, one application model, compact resource details, and readability/accessibility convergence. 7. `v0.2.0-beta.7`: creator task completion, observable validation, and full error/recovery coverage without new formats. 8. `v0.2.0-beta.8`: verified composer interactions, current-Codex compatibility recovery, polished generated interaction assets, and documentation-complete release evidence. -9. `v0.2.0-rc.1`: at least two independent complete macOS and Windows device runs; no P0/P1; migration, upgrade, and recovery pass. -10. `v0.2.0`: only when RC evidence supports it. +9. `v0.2.0-beta.9`: bounded multi-page CDP workspace discovery, explicit launch-failure diagnostics, and affected-device macOS regression evidence. +10. `v0.2.0-rc.1`: at least two independent complete macOS and Windows device runs; no P0/P1; migration, upgrade, and recovery pass. +11. `v0.2.0`: only when RC evidence supports it. ## v1 Stable diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 1abbe1b..0cd577b 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@codex-styler/desktop", - "version": "0.2.0-beta.8", + "version": "0.2.0-beta.9", "private": true, "type": "module", "scripts": { diff --git a/apps/desktop/src-tauri/Cargo.lock b/apps/desktop/src-tauri/Cargo.lock index b944ae1..03ab98d 100644 --- a/apps/desktop/src-tauri/Cargo.lock +++ b/apps/desktop/src-tauri/Cargo.lock @@ -392,7 +392,7 @@ dependencies = [ [[package]] name = "codex-styler" -version = "0.2.0-beta.8" +version = "0.2.0-beta.9" dependencies = [ "base64 0.22.1", "futures-util", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index bc8f813..951cdf6 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "codex-styler" -version = "0.2.0-beta.8" +version = "0.2.0-beta.9" description = "Unofficial local-first theme and interactive scene editor for OpenAI Codex Desktop" authors = ["Codex Styler contributors"] license = "Apache-2.0" diff --git a/apps/desktop/src-tauri/src/cdp.rs b/apps/desktop/src-tauri/src/cdp.rs index 7a50981..185c3eb 100644 --- a/apps/desktop/src-tauri/src/cdp.rs +++ b/apps/desktop/src-tauri/src/cdp.rs @@ -1,11 +1,13 @@ use std::{ + collections::{HashMap, HashSet}, + future::Future, net::TcpListener, path::Path, process::{Command, Stdio}, time::Duration, }; -use futures_util::{SinkExt, StreamExt}; +use futures_util::{SinkExt, StreamExt, stream::FuturesUnordered}; use serde::Deserialize; use serde_json::{Value, json}; use tokio::time::sleep; @@ -13,6 +15,11 @@ use tokio_tungstenite::{connect_async, tungstenite::Message}; use crate::{codex::executable_from_install, error::StylerError}; +const TARGET_POLL_INTERVAL: Duration = Duration::from_millis(200); +const TARGET_HTTP_TIMEOUT: Duration = Duration::from_millis(900); +const RENDERER_READY_TIMEOUT: Duration = Duration::from_millis(750); +const READY_TARGET_STABLE_SAMPLES: usize = 3; + #[cfg(target_os = "windows")] use crate::codex::{is_windows_store_install, windows_store_app_user_model_ids}; @@ -112,6 +119,55 @@ struct CdpTarget { web_socket_debugger_url: Option, } +#[derive(Debug, Clone, Copy)] +struct TargetWaitPolicy { + attempts: usize, + poll_interval: Duration, + candidate_timeout: Duration, + overall_timeout: Duration, +} + +impl TargetWaitPolicy { + fn production(attempts: usize) -> Self { + Self { + attempts, + poll_interval: TARGET_POLL_INTERVAL, + candidate_timeout: RENDERER_READY_TIMEOUT, + // Preserve the existing polling budget while placing a hard bound + // around HTTP, websocket, and renderer work performed inside it. + overall_timeout: TARGET_POLL_INTERVAL + .saturating_mul(attempts as u32) + .saturating_add(Duration::from_secs(2)), + } + } +} + +#[derive(Debug, Default)] +struct ReadyTargetTracker { + streaks: HashMap, +} + +impl ReadyTargetTracker { + fn observe(&mut self, ready_websockets: Vec) -> Option { + let mut seen = HashSet::new(); + let ready_websockets = ready_websockets + .into_iter() + .filter(|websocket_url| seen.insert(websocket_url.clone())) + .collect::>(); + + self.streaks + .retain(|websocket_url, _| seen.contains(websocket_url)); + for websocket_url in ready_websockets { + let samples = self.streaks.entry(websocket_url.clone()).or_default(); + *samples += 1; + if *samples >= READY_TARGET_STABLE_SAMPLES { + return Some(websocket_url); + } + } + None + } +} + pub async fn launch_and_connect(install_path: &str) -> Result { let port = reserve_loopback_port()?; let executable = @@ -129,42 +185,101 @@ pub async fn launch_and_connect(install_path: &str) -> Result Result { let client = reqwest::Client::builder() - .timeout(Duration::from_millis(900)) + .timeout(TARGET_HTTP_TIMEOUT) .build()?; let endpoint = format!("http://127.0.0.1:{port}/json/list"); - let mut stable_websocket = None; - let mut stable_samples = 0; - for _ in 0..attempts { - if let Ok(response) = client.get(&endpoint).send().await - && let Ok(targets) = response.json::>().await - && let Some(target) = targets.into_iter().find(is_trusted_codex_target) - && let Some(websocket_url) = target.web_socket_debugger_url - && is_loopback_debugger_url(&websocket_url, port) - { - if renderer_is_ready(&websocket_url).await { - if stable_websocket.as_deref() == Some(websocket_url.as_str()) { - stable_samples += 1; - } else { - stable_websocket = Some(websocket_url.clone()); - stable_samples = 1; - } - // Electron can expose a trusted page before the React shell has - // finished replacing its bootstrap renderer. Requiring three - // consecutive ready samples prevents applying to that transient - // page and losing the runtime during the first launch. - if stable_samples >= 3 { - return Ok(websocket_url); - } + wait_for_ready_target_with( + port, + TargetWaitPolicy::production(attempts), + move || { + let client = client.clone(); + let endpoint = endpoint.clone(); + async move { + let response = client.get(endpoint).send().await.ok()?; + response.json::>().await.ok() + } + }, + |websocket_url| async move { renderer_is_ready(&websocket_url).await }, + ) + .await +} + +async fn wait_for_ready_target_with( + port: u16, + policy: TargetWaitPolicy, + mut fetch_targets: FetchTargets, + mut check_ready: CheckReady, +) -> Result +where + FetchTargets: FnMut() -> FetchFuture, + FetchFuture: Future>>, + CheckReady: FnMut(String) -> CheckFuture, + CheckFuture: Future, +{ + let wait = async { + let mut tracker = ReadyTargetTracker::default(); + for attempt in 0..policy.attempts { + let ready_websockets = if let Some(targets) = fetch_targets().await { + ready_websockets(targets, port, policy.candidate_timeout, &mut check_ready).await } else { - stable_websocket = None; - stable_samples = 0; + Vec::new() + }; + + // Electron can expose trusted auxiliary pages before the React + // workspace is ready. Requiring the same ready websocket in three + // consecutive polls prevents applying to a transient renderer. + if let Some(websocket_url) = tracker.observe(ready_websockets) { + return Ok(websocket_url); + } + + if attempt + 1 < policy.attempts { + sleep(policy.poll_interval).await; } } - sleep(Duration::from_millis(200)).await; + Err(StylerError::TargetTimeout) + }; + + tokio::time::timeout(policy.overall_timeout, wait) + .await + .unwrap_or(Err(StylerError::TargetTimeout)) +} + +async fn ready_websockets( + targets: Vec, + port: u16, + candidate_timeout: Duration, + check_ready: &mut CheckReady, +) -> Vec +where + CheckReady: FnMut(String) -> CheckFuture, + CheckFuture: Future, +{ + let mut checks = FuturesUnordered::new(); + for target in targets.into_iter().filter(is_trusted_codex_target) { + let Some(websocket_url) = target.web_socket_debugger_url else { + continue; + }; + if !is_loopback_debugger_url(&websocket_url, port) { + continue; + } + + let check = check_ready(websocket_url.clone()); + checks.push(async move { + let ready = tokio::time::timeout(candidate_timeout, check) + .await + .unwrap_or(false); + (websocket_url, ready) + }); } - Err(StylerError::TargetTimeout) + let mut ready = Vec::new(); + while let Some((websocket_url, is_ready)) = checks.next().await { + if is_ready { + ready.push(websocket_url); + } + } + ready } async fn renderer_is_ready(websocket_url: &str) -> bool { @@ -175,9 +290,10 @@ async fn renderer_is_ready(websocket_url: &str) -> bool { ); return document.readyState !== 'loading' && Boolean(root && surface); })()"#; - evaluate(websocket_url, expression) + tokio::time::timeout(RENDERER_READY_TIMEOUT, evaluate(websocket_url, expression)) .await .ok() + .and_then(Result::ok) .and_then(|response| { response .pointer("/result/result/value") @@ -257,10 +373,44 @@ fn is_loopback_debugger_url(url: &str, port: u16) -> bool { #[cfg(test)] mod tests { + use std::time::{Duration, Instant}; + use super::{ - CdpTarget, is_loopback_debugger_url, is_trusted_codex_target, reserve_loopback_port, + CdpTarget, TargetWaitPolicy, is_loopback_debugger_url, is_trusted_codex_target, + ready_websockets, reserve_loopback_port, wait_for_ready_target_with, }; + const TEST_PORT: u16 = 43123; + + fn target(name: &str, url: &str) -> CdpTarget { + CdpTarget { + target_type: "page".into(), + title: "Codex".into(), + url: url.into(), + web_socket_debugger_url: Some(format!( + "ws://127.0.0.1:{TEST_PORT}/devtools/page/{name}" + )), + } + } + + fn websocket(name: &str) -> String { + format!("ws://127.0.0.1:{TEST_PORT}/devtools/page/{name}") + } + + fn ready_names(targets: Vec) -> Vec { + tauri::async_runtime::block_on(async { + let mut check_ready = + |websocket_url: String| async move { websocket_url.ends_with("/workspace") }; + ready_websockets( + targets, + TEST_PORT, + Duration::from_millis(20), + &mut check_ready, + ) + .await + }) + } + #[test] fn reserves_only_a_loopback_port() { assert!(reserve_loopback_port().unwrap() > 0); @@ -292,4 +442,140 @@ mod tests { 43123 )); } + + #[test] + fn selects_ready_workspace_when_overlay_precedes_it() { + let ready = ready_names(vec![ + target( + "avatar-overlay", + "app://-/index.html?initialRoute=%2Favatar-overlay", + ), + target("workspace", "app://-/index.html"), + ]); + + assert_eq!(ready, vec![websocket("workspace")]); + } + + #[test] + fn selects_ready_workspace_when_it_precedes_overlay() { + let ready = ready_names(vec![ + target("workspace", "app://-/index.html"), + target( + "avatar-overlay", + "app://-/index.html?initialRoute=%2Favatar-overlay", + ), + ]); + + assert_eq!(ready, vec![websocket("workspace")]); + } + + #[test] + fn skips_multiple_unready_trusted_pages_before_workspace() { + let ready = ready_names(vec![ + target("login", "app://-/index.html?initialRoute=%2Flogin"), + target("upgrade", "app://-/index.html?initialRoute=%2Fupgrade"), + target("settings", "app://-/index.html?initialRoute=%2Fsettings"), + target("workspace", "app://-/index.html"), + ]); + + assert_eq!(ready, vec![websocket("workspace")]); + } + + #[test] + fn timed_out_candidate_does_not_block_ready_workspace() { + let ready = tauri::async_runtime::block_on(async { + let mut check_ready = |websocket_url: String| async move { + if websocket_url.ends_with("/avatar-overlay") { + tokio::time::sleep(Duration::from_millis(50)).await; + } + websocket_url.ends_with("/workspace") + }; + ready_websockets( + vec![ + target( + "avatar-overlay", + "app://-/index.html?initialRoute=%2Favatar-overlay", + ), + target("workspace", "app://-/index.html"), + ], + TEST_PORT, + Duration::from_millis(5), + &mut check_ready, + ) + .await + }); + + assert_eq!(ready, vec![websocket("workspace")]); + } + + #[test] + fn stable_workspace_survives_candidate_order_changes() { + let result = tauri::async_runtime::block_on(async { + let mut fetch_count = 0; + wait_for_ready_target_with( + TEST_PORT, + TargetWaitPolicy { + attempts: 3, + poll_interval: Duration::from_millis(1), + candidate_timeout: Duration::from_millis(20), + overall_timeout: Duration::from_millis(100), + }, + move || { + fetch_count += 1; + let targets = if fetch_count % 2 == 0 { + vec![ + target("workspace", "app://-/index.html"), + target( + "avatar-overlay", + "app://-/index.html?initialRoute=%2Favatar-overlay", + ), + ] + } else { + vec![ + target( + "avatar-overlay", + "app://-/index.html?initialRoute=%2Favatar-overlay", + ), + target("workspace", "app://-/index.html"), + ] + }; + async move { Some(targets) } + }, + |websocket_url| async move { websocket_url.ends_with("/workspace") }, + ) + .await + }); + + assert_eq!(result.unwrap(), websocket("workspace")); + } + + #[test] + fn unavailable_workspace_fails_within_overall_bound() { + let started_at = Instant::now(); + let result = tauri::async_runtime::block_on(wait_for_ready_target_with( + TEST_PORT, + TargetWaitPolicy { + attempts: 100, + poll_interval: Duration::from_millis(100), + candidate_timeout: Duration::from_secs(1), + overall_timeout: Duration::from_millis(30), + }, + || async { + Some(vec![target( + "avatar-overlay", + "app://-/index.html?initialRoute=%2Favatar-overlay", + )]) + }, + |_| async { + tokio::time::sleep(Duration::from_secs(1)).await; + false + }, + )); + + assert!(matches!( + result, + Err(crate::error::StylerError::TargetTimeout) + )); + assert!(started_at.elapsed() < Duration::from_millis(250)); + } } diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index 5a4cace..e6622eb 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -727,14 +727,27 @@ async fn launch_codex( runtime.message = None; } - let session = cdp::launch_and_connect( + let session = match cdp::launch_and_connect( detection .path .as_deref() .ok_or_else(|| "Codex executable path is unavailable".to_string())?, ) .await - .map_err(|error| error.to_string())?; + { + Ok(session) => session, + Err(error) => { + let detail = error.to_string(); + if let Ok(mut runtime) = state.lock() { + record_launch_failure( + &mut runtime, + detail.clone(), + started_at.elapsed().as_millis() as u64, + ); + } + return Err(detail); + } + }; let mut runtime = state .lock() @@ -756,6 +769,11 @@ async fn launch_codex( Ok(runtime.status()) } +fn record_launch_failure(runtime: &mut AppRuntime, detail: String, duration_ms: u64) { + runtime.invalidate_connection(model::RuntimeState::Error, detail); + runtime.record("launch", "error", duration_ms); +} + async fn injected_runtime_is_active(websocket_url: &str) -> bool { cdp::evaluate( websocket_url, @@ -1252,6 +1270,31 @@ mod tests { assert_eq!(compatibility_for_version(None), model::Compatibility::Safe); } + #[test] + fn failed_target_discovery_does_not_leave_runtime_launching() { + let mut runtime = AppRuntime { + state: model::RuntimeState::Launching, + ..Default::default() + }; + + record_launch_failure( + &mut runtime, + "Codex did not expose a ready workspace".into(), + 12_000, + ); + + assert_eq!(runtime.state, model::RuntimeState::Error); + assert!(!runtime.connected); + assert_eq!( + runtime.message.as_deref(), + Some("Codex did not expose a ready workspace") + ); + let event = runtime.lifecycle.back().unwrap(); + assert_eq!(event.action, "launch"); + assert_eq!(event.outcome, "error"); + assert_eq!(event.duration_ms, 12_000); + } + #[test] fn compatibility_mode_is_an_explicit_allowlist() { assert!(is_valid_compatibility_mode("auto")); diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index c5bd0f5..5be111c 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Codex Styler", - "version": "0.2.0-beta.8", + "version": "0.2.0-beta.9", "identifier": "studio.xuhuan.codexstyler", "build": { "beforeDevCommand": "pnpm dev", diff --git a/apps/desktop/src/App.test.tsx b/apps/desktop/src/App.test.tsx index c5e1a76..92afe41 100644 --- a/apps/desktop/src/App.test.tsx +++ b/apps/desktop/src/App.test.tsx @@ -721,7 +721,7 @@ describe("Codex Styler shell", () => { it("checks for updates from settings and reports the current version", async () => { render(); fireEvent.click(screen.getByRole("button", { name: "Settings" })); - expect(screen.getByText("Codex Styler 0.2.0-beta.8")).toBeInTheDocument(); + expect(screen.getByText("Codex Styler 0.2.0-beta.9")).toBeInTheDocument(); fireEvent.click(screen.getByRole("button", { name: "Check for updates" })); await waitFor(() => expect(checkForUpdates).toHaveBeenCalledWith("en")); expect(await screen.findByText("You’re up to date")).toBeInTheDocument(); diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index 3b5b3f8..c5039ba 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -297,7 +297,7 @@ export function App() { } | null>(null); const [installPathBusy, setInstallPathBusy] = useState(false); const [toast, setToast] = useState(null); - const [currentVersion, setCurrentVersion] = useState("0.2.0-beta.8"); + const [currentVersion, setCurrentVersion] = useState("0.2.0-beta.9"); const [updateStatus, setUpdateStatus] = useState("idle"); const [availableUpdate, setAvailableUpdate] = useState(null); diff --git a/apps/desktop/src/features/app-shell/AppDialogs.test.tsx b/apps/desktop/src/features/app-shell/AppDialogs.test.tsx index e7580c4..407e87e 100644 --- a/apps/desktop/src/features/app-shell/AppDialogs.test.tsx +++ b/apps/desktop/src/features/app-shell/AppDialogs.test.tsx @@ -33,7 +33,7 @@ describe("application dialogs", () => { render( { if (!isTauri()) { - return { currentVersion: "0.2.0-beta.8", update: null }; + return { currentVersion: "0.2.0-beta.9", update: null }; } return invoke("check_for_updates", { locale }); } diff --git a/apps/site/package.json b/apps/site/package.json index c7dd820..2db8fa3 100644 --- a/apps/site/package.json +++ b/apps/site/package.json @@ -1,6 +1,6 @@ { "name": "@codex-styler/site", - "version": "0.2.0-beta.8", + "version": "0.2.0-beta.9", "private": true, "type": "module", "scripts": { @@ -14,7 +14,7 @@ "dependencies": { "@codex-styler/theme-core": "workspace:*", "@astrojs/sitemap": "^3.7.3", - "astro": "^7.0.9" + "astro": "^7.2.0" }, "devDependencies": { "@astrojs/check": "^0.9.6", diff --git a/apps/site/src/components/LandingPage.astro b/apps/site/src/components/LandingPage.astro index 5287868..553e074 100644 --- a/apps/site/src/components/LandingPage.astro +++ b/apps/site/src/components/LandingPage.astro @@ -7,9 +7,9 @@ const zh = locale === "zh-CN"; const base = import.meta.env.BASE_URL.replace(/\/$/, ""); const docsBase = base + (zh ? "/zh-cn/docs/" : "/docs/"); const repo = "https://github.com/xuhuanstudio/codex-styler"; -const releaseTag = "v0.2.0-beta.8"; -const macAsset = "Codex-Styler_0.2.0-beta.8_aarch64-unsigned.dmg"; -const windowsAsset = "Codex-Styler_0.2.0-beta.8_x64-unsigned-setup.exe"; +const releaseTag = "v0.2.0-beta.9"; +const macAsset = "Codex-Styler_0.2.0-beta.9_aarch64-unsigned.dmg"; +const windowsAsset = "Codex-Styler_0.2.0-beta.9_x64-unsigned-setup.exe"; const macDownloadUrl = `${repo}/releases/download/${releaseTag}/${macAsset}`; const windowsDownloadUrl = `${repo}/releases/download/${releaseTag}/${windowsAsset}`; const copy = zh diff --git a/apps/site/src/data/docs.ts b/apps/site/src/data/docs.ts index e4508a9..da80809 100644 --- a/apps/site/src/data/docs.ts +++ b/apps/site/src/data/docs.ts @@ -391,7 +391,7 @@ export const docs: DocPage[] = [ { heading: "Current Beta targets", paragraphs: [ - "Unsigned Beta installers are available for macOS on Apple Silicon and Windows 11 x64. macOS has the current real-device evidence; Windows Beta 8 is produced and structurally checked in CI but explicitly awaits community validation. The RC gate requires at least two complete independent device reports per platform.", + "Unsigned Beta installers are available for macOS on Apple Silicon and Windows 11 x64. macOS Beta 9 includes affected-device evidence for multi-page CDP launch and apply; Windows is produced and structurally checked in CI but explicitly awaits community validation. The RC gate requires at least two complete independent device reports per platform.", ], }, { @@ -405,7 +405,7 @@ export const docs: DocPage[] = [ { heading: "当前 Beta 目标", paragraphs: [ - "当前提供未签名的 Apple Silicon macOS 与 Windows 11 x64 Beta 安装包。macOS 已有现阶段真实设备证据;Windows Beta 8 由 CI 构建并完成结构校验,但明确等待社区实机验证。进入 RC 前,两个平台都至少需要两份独立的完整实机报告。", + "当前提供未签名的 Apple Silicon macOS 与 Windows 11 x64 Beta 安装包。macOS Beta 9 已取得多页面 CDP 启动与应用的受影响设备证据;Windows 由 CI 构建并完成结构校验,但明确等待社区实机验证。进入 RC 前,两个平台都至少需要两份独立的完整实机报告。", ], }, { diff --git a/apps/site/src/layouts/BaseLayout.astro b/apps/site/src/layouts/BaseLayout.astro index 057b1f3..cfe4573 100644 --- a/apps/site/src/layouts/BaseLayout.astro +++ b/apps/site/src/layouts/BaseLayout.astro @@ -19,7 +19,7 @@ const english = new URL(base + path, Astro.site); const chinese = new URL(base + "/zh-cn" + path, Astro.site); const socialImage = new URL(base + image, Astro.site); const repo = "https://github.com/xuhuanstudio/codex-styler"; -const releaseTag = "v0.2.0-beta.8"; +const releaseTag = "v0.2.0-beta.9"; const downloadUrl = `${repo}/releases/tag/${releaseTag}`; const isChinese = locale === "zh-CN"; const structuredData = { @@ -28,7 +28,7 @@ const structuredData = { name: "Codex Styler", applicationCategory: "DeveloperApplication", operatingSystem: "macOS 13 or later; Windows 11", - softwareVersion: "0.2.0-beta.8", + softwareVersion: "0.2.0-beta.9", description, url: canonical.toString(), downloadUrl, diff --git a/package.json b/package.json index 7437b0c..9d1a3df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codex-styler", - "version": "0.2.0-beta.8", + "version": "0.2.0-beta.9", "private": true, "description": "Unofficial, open-source Codex theme editor and Codex skin creator for OpenAI Codex Desktop.", "license": "Apache-2.0", diff --git a/packages/theme-core/package.json b/packages/theme-core/package.json index 0c47f44..ea989f7 100644 --- a/packages/theme-core/package.json +++ b/packages/theme-core/package.json @@ -1,6 +1,6 @@ { "name": "@codex-styler/theme-core", - "version": "0.2.0-beta.8", + "version": "0.2.0-beta.9", "private": true, "type": "module", "exports": { @@ -23,7 +23,7 @@ "jszip": "^3.10.1" }, "devDependencies": { - "@types/node": "^24.1.0", + "@types/node": "^26.1.2", "tsx": "^4.20.5", "typescript": "^6.0.3", "vitest": "^4.1.10" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 149b97d..e43d26b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,12 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + fast-uri: 3.1.5 + js-yaml: 4.3.1 + nanoid: 3.3.17 + postcss: 8.5.23 + importers: .: @@ -47,19 +53,19 @@ importers: version: 2.11.4 '@testing-library/jest-dom': specifier: ^6.9.1 - version: 6.9.1 + version: 6.10.0(@testing-library/dom@10.4.1) '@testing-library/react': specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.4(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@types/react': specifier: ^19.2.17 version: 19.2.17 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.17) + version: 19.2.4(@types/react@19.2.17) '@vitejs/plugin-react': specifier: ^6.0.3 - version: 6.0.3(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) + version: 6.0.3(vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) jsdom: specifier: ^27.0.0 version: 27.4.0 @@ -68,10 +74,10 @@ importers: version: 6.0.3 vite: specifier: ^8.1.4 - version: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) + version: 8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) vitest: specifier: ^4.1.10 - version: 4.1.10(@types/node@24.13.3)(jsdom@27.4.0)(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.2)(jsdom@27.4.0)(vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) apps/site: dependencies: @@ -82,8 +88,8 @@ importers: specifier: workspace:* version: link:../../packages/theme-core astro: - specifier: ^7.0.9 - version: 7.0.9(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(tsx@4.23.1)(yaml@2.9.0) + specifier: ^7.2.0 + version: 7.2.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@26.1.2)(tsx@4.23.1)(yaml@2.9.0) devDependencies: '@astrojs/check': specifier: ^0.9.6 @@ -105,8 +111,8 @@ importers: version: 3.10.1 devDependencies: '@types/node': - specifier: ^24.1.0 - version: 24.13.3 + specifier: ^26.1.2 + version: 26.1.2 tsx: specifier: ^4.20.5 version: 4.23.1 @@ -115,7 +121,7 @@ importers: version: 6.0.3 vitest: specifier: ^4.1.10 - version: 4.1.10(@types/node@24.13.3)(jsdom@27.4.0)(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) + version: 4.1.10(@types/node@26.1.2)(jsdom@27.4.0)(vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) packages: @@ -140,76 +146,76 @@ packages: peerDependencies: typescript: ^5.0.0 || ^6.0.0 - '@astrojs/compiler-binding-darwin-arm64@0.3.1': - resolution: {integrity: sha512-IEmEF2fUIlTHtpeE/isyEGVOB14cEyh/LZOFYt6wn3jNyVpdC8aR5OZ+RzFUR/f+8ZDM1LaMwZKvoA7eMyJeFw==} + '@astrojs/compiler-binding-darwin-arm64@0.3.2': + resolution: {integrity: sha512-MM8tn8CSimcfytaOla4b6acN8mKWiL/rlAA1fpT3/Wl7dNGSE4y8FjTN/zJVNnb63CsLWG5zZwCt01TXtDKh9g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@astrojs/compiler-binding-darwin-x64@0.3.1': - resolution: {integrity: sha512-GF2kIxjpPDLsn94zbZNMsxEmkU828QqnmM7kiQJnaooS3jmI+I7kk6+oI6EpwOsK3femCMdcm+wmOsEqtGrmjQ==} + '@astrojs/compiler-binding-darwin-x64@0.3.2': + resolution: {integrity: sha512-2lXOlzf8xb7jLomRsf/aswh61/NnGusynB2OwFkK6k4pmOtpfXMYnG0PLfXrEvxXYj69NdCnmUYXtHDd+JOOag==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@astrojs/compiler-binding-linux-arm64-gnu@0.3.1': - resolution: {integrity: sha512-XJL3SDmOtVrqFhCirNcHwE91+IesJqlgNo23I4qW9QUYfwzm/TBZuH61fgqsb1ttgR1mMYz6ooPWs0JDhwMqpQ==} + '@astrojs/compiler-binding-linux-arm64-gnu@0.3.2': + resolution: {integrity: sha512-BmU3kWj7qnLrd4vzm49zFEPJ5oFnn1tCT4Vt9hZbqdU5Cmb8GZl7fn6VFsnNfe7B18a2gIFtVzbLINtYl5kBjQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@astrojs/compiler-binding-linux-arm64-musl@0.3.1': - resolution: {integrity: sha512-xqE8BVbDoBueK/B47w30PtkVofUWJKGkwoMVE+EOMLf11rnoANxIAdA9FPqY+rng4oNI5ndHGsri1yPj2k8vZQ==} + '@astrojs/compiler-binding-linux-arm64-musl@0.3.2': + resolution: {integrity: sha512-f0heT9ZZEseSu5bHCeb80eL2DH07ArE6U9xi1WT/PEusNjzPmEr3GJsjG1tRLo5VYUUYX7h3ScaqGmGrMOVGmw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@astrojs/compiler-binding-linux-x64-gnu@0.3.1': - resolution: {integrity: sha512-1y0StU1qiCuDFH3rmbRJXcxdfHxFPrES1Rd+RLffosvUR7I2cH5SF5SFnBN9vXpzpkmyElZm3Yr47iJBPN7vVA==} + '@astrojs/compiler-binding-linux-x64-gnu@0.3.2': + resolution: {integrity: sha512-M8fOUt0itRpqiGyoEA/ij184s8O+hqbCz3+YozRusOOM3osgGljpDThhbKAJjqh82wOo6FioQ4w8PBvU1XMD5Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@astrojs/compiler-binding-linux-x64-musl@0.3.1': - resolution: {integrity: sha512-16q0fYf7kpbmdObZEeZJEup8hQv/whgNwVjrSvT8umrKwLDSnNIWiQpm09lQQu6bweZB0XyIvHwlPitvJhC+hg==} + '@astrojs/compiler-binding-linux-x64-musl@0.3.2': + resolution: {integrity: sha512-/Kebk8sO6HnLeSd691JkaAPfN7CqR9/KEXmWvyNPkaKNGmj8rTZ/lf2uXtnPu92Lan84UrKdIKVPy1fSo2encQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@astrojs/compiler-binding-wasm32-wasi@0.3.1': - resolution: {integrity: sha512-cB456shIwDv/PrVT+2QG7LFndpHkVge5HjqADKZgGaAc9JHVktCtjSrcdkRQ+3tbkPazNKaTLRjXLIiz2NIx9g==} + '@astrojs/compiler-binding-wasm32-wasi@0.3.2': + resolution: {integrity: sha512-pUA6xbcOSB7DhfzIArB8BCAkFfAIqriiR7zl5zOStd6oU2G0kIKj+GUdGnyXyhfiv881Hffyk5tC0mR18sDjDw==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@astrojs/compiler-binding-win32-arm64-msvc@0.3.1': - resolution: {integrity: sha512-ur/9+If/yTE69mmeX5MqSZndL0HOyx67GeNZUy3N7wVdWpLz9UTJXwyWS4UR2PUQHitghjsM5xoX0Ge56WRVQQ==} + '@astrojs/compiler-binding-win32-arm64-msvc@0.3.2': + resolution: {integrity: sha512-ESruf+6Qkl1trHUFxI6GSf6t52j8yN2kCNSzMWdzt7V/T09tFHrYzrVaJQohb2C9bJUH76pNvX6Zb51+xCQc9Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@astrojs/compiler-binding-win32-x64-msvc@0.3.1': - resolution: {integrity: sha512-k0W+kDBzDkNZOqu4kElDvCOIbKw5Ut9S1WZ1Krj3KTgNuBERNKXsMMsRLLcbgfdMdbe7bTekQLshZrrvmYpmwA==} + '@astrojs/compiler-binding-win32-x64-msvc@0.3.2': + resolution: {integrity: sha512-wzzVrEbOwbsLWOdEbocskjMRx2aZPxJ7ZbmL+jnpBamFwmigm+2M/wzuM6JWncocgYwLic1csSpalBh96kQKXA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@astrojs/compiler-binding@0.3.1': - resolution: {integrity: sha512-DaAUj29AIBU2XdJ8uwcab8lW5O2pk9pY8AXkcMw0sw77nVa3oeTYRcO+Dvbbpoexf6ThMc0FMWYCQ/wN1/T7oQ==} + '@astrojs/compiler-binding@0.3.2': + resolution: {integrity: sha512-8w/9CWmYrAJJ8N0SY3O43ws2BgxoW6u3QsD8u2mE140lMYAlwh+tlNoUeSBq22wVheFuiBbR212l6ixZ2IIgCQ==} engines: {node: ^20.19.0 || >=22.12.0} - '@astrojs/compiler-rs@0.3.1': - resolution: {integrity: sha512-aT7xkgsbNoS6nriY5qKpbihK43slFHO41iqgHCTdOvn1ifaQxLCc5yXy+6GzAtiafoaC1zA7OwVXCXMsvUZOkg==} + '@astrojs/compiler-rs@0.3.2': + resolution: {integrity: sha512-xlx/T7JovIKduu4ucbTQUxQ5+Q8wxkHxhLjnZk3VlJbhbQ9RLvvuDk1p2YYFYFQ5y14dVm3FGGO4isQXa4F+Tg==} engines: {node: '>=22.12.0'} '@astrojs/compiler@2.13.1': resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==} - '@astrojs/internal-helpers@0.10.1': - resolution: {integrity: sha512-5phcroT/vmOOrYuuAxtkbPixy5hePtlz9i8K4OeDv3dNK6/UQRuXPOSRTxIOBbUY5Sonw2UaxjbuVc43Mcir6Q==} + '@astrojs/internal-helpers@0.10.2': + resolution: {integrity: sha512-yt7fMgPYqSM4Tmr+taTW6Per+hjJ8Pk6lA1PAcDyqzOt8HzJ6Kje5WzCxA2Sd+9wsUW7uhkLeoTMK0cXPwH9rQ==} '@astrojs/language-server@2.16.12': resolution: {integrity: sha512-3LpFphBCzveUgm5ZVDINB/v3YA4TgPa1EMOEFn3Zt/Ww6jojR25iN+kmzeUz7v/b9xkmq+hMACTX4hizN3VCEQ==} @@ -223,8 +229,8 @@ packages: prettier-plugin-astro: optional: true - '@astrojs/markdown-satteri@0.3.4': - resolution: {integrity: sha512-6Lvt/bQZEBW+zzdhPblvfZEy5PGEYJaUsUqaCgwHeRPxZJL1gc9I+DRLKWJjjYTWDzVUTzXlMq4WwSK+X34CVw==} + '@astrojs/markdown-satteri@0.3.5': + resolution: {integrity: sha512-CvWVEFAbay7YO+i9SaqDJubipA5ckiVB89QWoMJ5XC0m5CtFg8JwZ7Kau6X9sYY7FZURH0w2l03ISH2jOS/RDQ==} '@astrojs/prism@4.0.2': resolution: {integrity: sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==} @@ -722,10 +728,6 @@ packages: cpu: [x64] os: [win32] - '@jest/types@27.0.2': - resolution: {integrity: sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -735,6 +737,13 @@ packages: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 + '@napi-rs/wasm-runtime@1.2.2': + resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} + peerDependencies: + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.3 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3 + '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} @@ -844,15 +853,6 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@rollup/pluginutils@5.4.0': - resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@shikijs/core@4.3.1': resolution: {integrity: sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==} engines: {node: '>=20'} @@ -973,9 +973,12 @@ packages: resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} - '@testing-library/jest-dom@6.9.1': - resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} - engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + '@testing-library/jest-dom@6.10.0': + resolution: {integrity: sha512-HQwu0KaB2zyT0iLzBL+8CLyZDL3KlZlZJ+2iyc9uCUnlJVskJU/UlPuVCyIPhtukjPQdT2QNoR5nCP5FqTmmDQ==} + engines: {node: '>=22', npm: '>=6', yarn: '>=1'} + deprecated: Incorrect minor release with breaking changes (Node >=22 and required @testing-library/dom peer). Use 6.9.1 for the 6.x line, or upgrade to 7.0.0. + peerDependencies: + '@testing-library/dom': '>=10 <11' '@testing-library/react@16.3.2': resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} @@ -1013,15 +1016,6 @@ packages: '@types/hast@3.0.5': resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} - '@types/istanbul-lib-coverage@2.0.6': - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - - '@types/istanbul-lib-report@3.0.3': - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - - '@types/istanbul-reports@3.0.4': - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} @@ -1031,8 +1025,11 @@ packages: '@types/node@24.13.3': resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==} - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + '@types/node@26.1.2': + resolution: {integrity: sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg==} + + '@types/react-dom@19.2.4': + resolution: {integrity: sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==} peerDependencies: '@types/react': ^19.2.0 @@ -1045,12 +1042,6 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@types/yargs-parser@21.0.3': - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - - '@types/yargs@16.0.11': - resolution: {integrity: sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==} - '@ungap/structured-clone@1.3.3': resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} @@ -1191,12 +1182,12 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - astro@7.0.9: - resolution: {integrity: sha512-WB5pA4LLQnmqjBh6EIu0z8aUV4q2/AoThgSZq57Rsp+oqqvPu7OwZ5eF+W4ku20TUTxIhiJW8dccuGvJPiW2UA==} + astro@7.2.0: + resolution: {integrity: sha512-lLTYzx3fOvCmtwD3JVBLQcbORbIOW1/j0R+3IvJx/XKwMGrk7mFnF0BYSOeRiNw1qHUR5mdA6+hRnyvyDfqrWQ==} engines: {node: '>=22.12.0', npm: '>=9.6.5', pnpm: '>=7.1.0'} hasBin: true peerDependencies: - '@astrojs/markdown-remark': 7.2.1 + '@astrojs/markdown-remark': 7.2.2 peerDependenciesMeta: '@astrojs/markdown-remark': optional: true @@ -1221,10 +1212,6 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -1275,9 +1262,9 @@ packages: cookie-es@1.2.3: resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} - cookie@1.1.1: - resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} - engines: {node: '>=18'} + cookie@2.0.1: + resolution: {integrity: sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==} + engines: {node: '>=22'} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -1407,9 +1394,6 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -1432,8 +1416,8 @@ packages: fast-string-width@3.0.2: resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} - fast-uri@3.1.3: - resolution: {integrity: sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==} + fast-uri@3.1.5: + resolution: {integrity: sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==} fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} @@ -1482,10 +1466,6 @@ packages: h3@1.15.11: resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==} - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - hast-util-from-html@2.0.3: resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} @@ -1560,8 +1540,8 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.3.0: - resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + js-yaml@4.3.1: + resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==} hasBin: true jsdom@27.4.0: @@ -1685,6 +1665,9 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magic-string@1.1.0: + resolution: {integrity: sha512-kS3VHe0nEPST2saQV4Rbkchcd3UBRkVTQHo1D3h/ZTwFDhai/mfKkmtPAtD129EOI7K3HlHIsFOt0WrI2/oU9g==} + magicast@0.5.3: resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} @@ -1726,13 +1709,13 @@ packages: muggle-string@0.4.1: resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} - nanoid@3.3.16: - resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + nanoid@3.3.17: + resolution: {integrity: sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - neotraverse@0.6.18: - resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} + neotraverse@1.0.1: + resolution: {integrity: sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w==} engines: {node: '>= 10'} nlcst-to-string@4.0.0: @@ -1741,8 +1724,8 @@ packages: node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} - node-mock-http@1.0.4: - resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} + node-mock-http@1.0.5: + resolution: {integrity: sha512-KQyt/wLjG3TAc7DOUhpqWzgd4ERxR80JOlTK5VE5R1S12IaPVN5qkj4klBce9HPG1Njuup4Sb5bljaT34lIyjw==} normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} @@ -1821,8 +1804,8 @@ packages: engines: {node: '>=18'} hasBin: true - postcss@8.5.19: - resolution: {integrity: sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==} + postcss@8.5.23: + resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==} engines: {node: ^10 || ^12 || >=14} prettier@3.9.5: @@ -1830,8 +1813,8 @@ packages: engines: {node: '>=14'} hasBin: true - pretty-format@27.0.2: - resolution: {integrity: sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==} + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} prismjs@1.30.0: @@ -1860,8 +1843,8 @@ packages: peerDependencies: react: ^19.2.7 - react-is@17.0.1: - resolution: {integrity: sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} react@19.2.7: resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} @@ -1874,8 +1857,8 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} - readdirp@5.0.0: - resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + readdirp@5.1.1: + resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} engines: {node: '>= 20.19.0'} redent@3.0.0: @@ -2003,10 +1986,6 @@ packages: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - svgo@4.0.2: resolution: {integrity: sha512-ekx94z1rRc5LDi6oSUaeRnYhd0UOJxdtQCL2rF8xpWxD3TPAsISWOrxezqGovqS38GRZOdpDfvQe3ts6F7nsng==} engines: {node: '>=16'} @@ -2089,6 +2068,9 @@ packages: undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + undici-types@8.3.0: + resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + unified@11.0.5: resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} @@ -2517,67 +2499,67 @@ snapshots: - prettier - prettier-plugin-astro - '@astrojs/compiler-binding-darwin-arm64@0.3.1': + '@astrojs/compiler-binding-darwin-arm64@0.3.2': optional: true - '@astrojs/compiler-binding-darwin-x64@0.3.1': + '@astrojs/compiler-binding-darwin-x64@0.3.2': optional: true - '@astrojs/compiler-binding-linux-arm64-gnu@0.3.1': + '@astrojs/compiler-binding-linux-arm64-gnu@0.3.2': optional: true - '@astrojs/compiler-binding-linux-arm64-musl@0.3.1': + '@astrojs/compiler-binding-linux-arm64-musl@0.3.2': optional: true - '@astrojs/compiler-binding-linux-x64-gnu@0.3.1': + '@astrojs/compiler-binding-linux-x64-gnu@0.3.2': optional: true - '@astrojs/compiler-binding-linux-x64-musl@0.3.1': + '@astrojs/compiler-binding-linux-x64-musl@0.3.2': optional: true - '@astrojs/compiler-binding-wasm32-wasi@0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': + '@astrojs/compiler-binding-wasm32-wasi@0.3.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': dependencies: - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) + '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' optional: true - '@astrojs/compiler-binding-win32-arm64-msvc@0.3.1': + '@astrojs/compiler-binding-win32-arm64-msvc@0.3.2': optional: true - '@astrojs/compiler-binding-win32-x64-msvc@0.3.1': + '@astrojs/compiler-binding-win32-x64-msvc@0.3.2': optional: true - '@astrojs/compiler-binding@0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': + '@astrojs/compiler-binding@0.3.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': optionalDependencies: - '@astrojs/compiler-binding-darwin-arm64': 0.3.1 - '@astrojs/compiler-binding-darwin-x64': 0.3.1 - '@astrojs/compiler-binding-linux-arm64-gnu': 0.3.1 - '@astrojs/compiler-binding-linux-arm64-musl': 0.3.1 - '@astrojs/compiler-binding-linux-x64-gnu': 0.3.1 - '@astrojs/compiler-binding-linux-x64-musl': 0.3.1 - '@astrojs/compiler-binding-wasm32-wasi': 0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) - '@astrojs/compiler-binding-win32-arm64-msvc': 0.3.1 - '@astrojs/compiler-binding-win32-x64-msvc': 0.3.1 + '@astrojs/compiler-binding-darwin-arm64': 0.3.2 + '@astrojs/compiler-binding-darwin-x64': 0.3.2 + '@astrojs/compiler-binding-linux-arm64-gnu': 0.3.2 + '@astrojs/compiler-binding-linux-arm64-musl': 0.3.2 + '@astrojs/compiler-binding-linux-x64-gnu': 0.3.2 + '@astrojs/compiler-binding-linux-x64-musl': 0.3.2 + '@astrojs/compiler-binding-wasm32-wasi': 0.3.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) + '@astrojs/compiler-binding-win32-arm64-msvc': 0.3.2 + '@astrojs/compiler-binding-win32-x64-msvc': 0.3.2 transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' - '@astrojs/compiler-rs@0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': + '@astrojs/compiler-rs@0.3.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': dependencies: - '@astrojs/compiler-binding': 0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) + '@astrojs/compiler-binding': 0.3.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' '@astrojs/compiler@2.13.1': {} - '@astrojs/internal-helpers@0.10.1': + '@astrojs/internal-helpers@0.10.2': dependencies: '@types/hast': 3.0.5 '@types/mdast': 4.0.4 - js-yaml: 4.3.0 + js-yaml: 4.3.1 picomatch: 4.0.5 retext-smartypants: 6.2.0 shiki: 4.3.1 @@ -2609,9 +2591,9 @@ snapshots: transitivePeerDependencies: - typescript - '@astrojs/markdown-satteri@0.3.4': + '@astrojs/markdown-satteri@0.3.5': dependencies: - '@astrojs/internal-helpers': 0.10.1 + '@astrojs/internal-helpers': 0.10.2 '@astrojs/prism': 4.0.2 github-slugger: 2.0.0 hast-util-from-html: 2.0.3 @@ -2681,7 +2663,7 @@ snapshots: dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true '@bruits/satteri-win32-arm64-msvc@0.9.5': @@ -2961,14 +2943,6 @@ snapshots: '@img/sharp-win32-x64@0.35.3': optional: true - '@jest/types@27.0.2': - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 24.13.3 - '@types/yargs': 16.0.11 - chalk: 4.1.2 - '@jridgewell/sourcemap-codec@1.5.5': {} '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': @@ -2978,7 +2952,14 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': + '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.2 @@ -3044,12 +3025,6 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} - '@rollup/pluginutils@5.4.0': - dependencies: - '@types/estree': 1.0.9 - estree-walker: 2.0.2 - picomatch: 4.0.5 - '@shikijs/core@4.3.1': dependencies: '@shikijs/primitive': 4.3.1 @@ -3154,18 +3129,19 @@ snapshots: dom-accessibility-api: 0.5.16 lz-string: 1.5.0 picocolors: 1.1.1 - pretty-format: 27.0.2 + pretty-format: 27.5.1 - '@testing-library/jest-dom@6.9.1': + '@testing-library/jest-dom@6.10.0(@testing-library/dom@10.4.1)': dependencies: '@adobe/css-tools': 4.5.0 + '@testing-library/dom': 10.4.1 aria-query: 5.3.2 css.escape: 1.5.1 dom-accessibility-api: 0.6.3 picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.4(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@babel/runtime': 7.29.7 '@testing-library/dom': 10.4.1 @@ -3173,7 +3149,7 @@ snapshots: react-dom: 19.2.7(react@19.2.7) optionalDependencies: '@types/react': 19.2.17 - '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@types/react-dom': 19.2.4(@types/react@19.2.17) '@tybys/wasm-util@0.10.3': dependencies: @@ -3199,16 +3175,6 @@ snapshots: dependencies: '@types/unist': 3.0.3 - '@types/istanbul-lib-coverage@2.0.6': {} - - '@types/istanbul-lib-report@3.0.3': - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - - '@types/istanbul-reports@3.0.4': - dependencies: - '@types/istanbul-lib-report': 3.0.3 - '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 @@ -3221,7 +3187,11 @@ snapshots: dependencies: undici-types: 7.18.2 - '@types/react-dom@19.2.3(@types/react@19.2.17)': + '@types/node@26.1.2': + dependencies: + undici-types: 8.3.0 + + '@types/react-dom@19.2.4(@types/react@19.2.17)': dependencies: '@types/react': 19.2.17 @@ -3231,22 +3201,16 @@ snapshots: '@types/sax@1.2.7': dependencies: - '@types/node': 24.13.3 + '@types/node': 26.1.2 '@types/unist@3.0.3': {} - '@types/yargs-parser@21.0.3': {} - - '@types/yargs@16.0.11': - dependencies: - '@types/yargs-parser': 21.0.3 - '@ungap/structured-clone@1.3.3': {} - '@vitejs/plugin-react@6.0.3(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0))': + '@vitejs/plugin-react@6.0.3(vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) '@vitest/expect@4.1.10': dependencies: @@ -3257,13 +3221,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.10(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) '@vitest/pretty-format@4.1.10': dependencies: @@ -3366,7 +3330,7 @@ snapshots: ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.3 + fast-uri: 3.1.5 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -3399,23 +3363,22 @@ snapshots: assertion-error@2.0.1: {} - astro@7.0.9(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@24.13.3)(tsx@4.23.1)(yaml@2.9.0): + astro@7.2.0(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@26.1.2)(tsx@4.23.1)(yaml@2.9.0): dependencies: - '@astrojs/compiler-rs': 0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) - '@astrojs/internal-helpers': 0.10.1 - '@astrojs/markdown-satteri': 0.3.4 + '@astrojs/compiler-rs': 0.3.2(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) + '@astrojs/internal-helpers': 0.10.2 + '@astrojs/markdown-satteri': 0.3.5 '@astrojs/telemetry': 3.3.3 '@capsizecss/unpack': 4.0.1 '@clack/prompts': 1.7.0 '@oslojs/encoding': 1.1.0 - '@rollup/pluginutils': 5.4.0 am-i-vibing: 0.4.0 aria-query: 5.3.2 axobject-query: 4.1.0 ci-info: 4.4.0 clsx: 2.1.1 common-ancestor-path: 2.0.0 - cookie: 1.1.1 + cookie: 2.0.1 devalue: 5.8.1 diff: 8.0.4 dset: 3.1.4 @@ -3427,12 +3390,12 @@ snapshots: github-slugger: 2.0.0 html-escaper: 3.0.3 http-cache-semantics: 4.2.0 - js-yaml: 4.3.0 + js-yaml: 4.3.1 jsonc-parser: 3.3.1 - magic-string: 0.30.21 + magic-string: 1.1.0 magicast: 0.5.3 mrmime: 2.0.1 - neotraverse: 0.6.18 + neotraverse: 1.0.1 obug: 2.1.3 p-limit: 7.3.0 p-queue: 9.3.1 @@ -3449,13 +3412,13 @@ snapshots: ultrahtml: 1.7.0 unifont: 0.7.4 unstorage: 1.17.5 - vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) - vitefu: 1.1.3(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) + vite: 8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) + vitefu: 1.1.3(vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) xxhash-wasm: 1.1.0 yargs-parser: 22.0.0 zod: 4.4.3 optionalDependencies: - sharp: 0.35.3(@types/node@24.13.3) + sharp: 0.35.3(@types/node@26.1.2) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -3481,7 +3444,6 @@ snapshots: - ioredis - jiti - less - - rollup - sass - sass-embedded - stylus @@ -3505,11 +3467,6 @@ snapshots: chai@6.2.2: {} - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - character-entities-html4@2.1.0: {} character-entities-legacy@3.0.0: {} @@ -3520,7 +3477,7 @@ snapshots: chokidar@5.0.0: dependencies: - readdirp: 5.0.0 + readdirp: 5.1.1 ci-info@4.4.0: {} @@ -3548,7 +3505,7 @@ snapshots: cookie-es@1.2.3: {} - cookie@1.1.1: {} + cookie@2.0.1: {} core-util-is@1.0.3: {} @@ -3688,8 +3645,6 @@ snapshots: escalade@3.2.0: {} - estree-walker@2.0.2: {} - estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 @@ -3708,7 +3663,7 @@ snapshots: dependencies: fast-string-truncated-width: 3.0.3 - fast-uri@3.1.3: {} + fast-uri@3.1.5: {} fast-wrap-ansi@0.2.2: dependencies: @@ -3749,13 +3704,11 @@ snapshots: defu: 6.1.7 destr: 2.0.5 iron-webcrypto: 1.2.1 - node-mock-http: 1.0.4 + node-mock-http: 1.0.5 radix3: 1.1.2 ufo: 1.6.4 uncrypto: 0.1.3 - has-flag@4.0.0: {} - hast-util-from-html@2.0.3: dependencies: '@types/hast': 3.0.5 @@ -3852,7 +3805,7 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@4.3.0: + js-yaml@4.3.1: dependencies: argparse: 2.0.1 @@ -3966,6 +3919,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magic-string@1.1.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + magicast@0.5.3: dependencies: '@babel/parser': 7.29.7 @@ -4013,9 +3970,9 @@ snapshots: muggle-string@0.4.1: {} - nanoid@3.3.16: {} + nanoid@3.3.17: {} - neotraverse@0.6.18: {} + neotraverse@1.0.1: {} nlcst-to-string@4.0.0: dependencies: @@ -4023,7 +3980,7 @@ snapshots: node-fetch-native@1.6.7: {} - node-mock-http@1.0.4: {} + node-mock-http@1.0.5: {} normalize-path@3.0.0: {} @@ -4092,20 +4049,19 @@ snapshots: optionalDependencies: fsevents: 2.3.2 - postcss@8.5.19: + postcss@8.5.23: dependencies: - nanoid: 3.3.16 + nanoid: 3.3.17 picocolors: 1.1.1 source-map-js: 1.2.1 prettier@3.9.5: {} - pretty-format@27.0.2: + pretty-format@27.5.1: dependencies: - '@jest/types': 27.0.2 ansi-regex: 5.0.1 ansi-styles: 5.2.0 - react-is: 17.0.1 + react-is: 17.0.2 prismjs@1.30.0: {} @@ -4124,7 +4080,7 @@ snapshots: react: 19.2.7 scheduler: 0.27.0 - react-is@17.0.1: {} + react-is@17.0.2: {} react@19.2.7: {} @@ -4140,7 +4096,7 @@ snapshots: readdirp@4.1.2: {} - readdirp@5.0.0: {} + readdirp@5.1.1: {} redent@3.0.0: dependencies: @@ -4225,7 +4181,7 @@ snapshots: setimmediate@1.0.5: {} - sharp@0.35.3(@types/node@24.13.3): + sharp@0.35.3(@types/node@26.1.2): dependencies: '@img/colour': 1.1.0 detect-libc: 2.1.2 @@ -4256,7 +4212,7 @@ snapshots: '@img/sharp-win32-arm64': 0.35.3 '@img/sharp-win32-ia32': 0.35.3 '@img/sharp-win32-x64': 0.35.3 - '@types/node': 24.13.3 + '@types/node': 26.1.2 optional: true shiki@4.3.1: @@ -4316,10 +4272,6 @@ snapshots: dependencies: min-indent: 1.0.1 - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - svgo@4.0.2: dependencies: commander: 11.1.0 @@ -4390,6 +4342,8 @@ snapshots: undici-types@7.18.2: {} + undici-types@8.3.0: {} + unified@11.0.5: dependencies: '@types/unist': 3.0.3 @@ -4457,28 +4411,28 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0): + vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 picomatch: 4.0.5 - postcss: 8.5.19 + postcss: 8.5.23 rolldown: 1.1.5 tinyglobby: 0.2.17 optionalDependencies: - '@types/node': 24.13.3 + '@types/node': 26.1.2 esbuild: 0.28.1 fsevents: 2.3.3 tsx: 4.23.1 yaml: 2.9.0 - vitefu@1.1.3(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)): + vitefu@1.1.3(vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)): optionalDependencies: - vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) - vitest@4.1.10(@types/node@24.13.3)(jsdom@27.4.0)(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)): + vitest@4.1.10(@types/node@26.1.2)(jsdom@27.4.0)(vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(vite@8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -4495,10 +4449,10 @@ snapshots: tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.1.4(@types/node@24.13.3)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) + vite: 8.1.4(@types/node@26.1.2)(esbuild@0.28.1)(tsx@4.23.1)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 24.13.3 + '@types/node': 26.1.2 jsdom: 27.4.0 transitivePeerDependencies: - msw diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 65985fb..3db5a9b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -7,3 +7,9 @@ allowBuilds: sharedWorkspaceLockfile: true strictPeerDependencies: false + +overrides: + fast-uri: 3.1.5 + js-yaml: 4.3.1 + nanoid: 3.3.17 + postcss: 8.5.23