From fce0f76d577b5070f1e2b4a2abaa8350acfc38ff Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 12:41:56 -0700 Subject: [PATCH 01/17] build: migrate argument-comment-lint to a native Bazel aspect (#16106) ## Why `argument-comment-lint` had become a PR bottleneck because the repo-wide lane was still effectively running a `cargo dylint`-style flow across the workspace instead of reusing Bazel's Rust dependency graph. That kept the lint enforced, but it threw away the main benefit of moving this job under Bazel in the first place: metadata reuse and cacheable per-target analysis in the same shape as Clippy. This change moves the repo-wide lint onto a native Bazel Rust aspect so Linux and macOS can lint `codex-rs` without rebuilding the world crate-by-crate through the wrapper path. ## What Changed - add a nightly Rust toolchain with `rustc-dev` for Bazel and a dedicated crate-universe repo for `tools/argument-comment-lint` - add `tools/argument-comment-lint/driver.rs` and `tools/argument-comment-lint/lint_aspect.bzl` so Bazel can run the lint as a custom `rustc_driver` - switch repo-wide `just argument-comment-lint` and the Linux/macOS `rust-ci` lanes to `bazel build --config=argument-comment-lint //codex-rs/...` - keep the Python/DotSlash wrappers as the package-scoped fallback path and as the current Windows CI path - gate the Dylint entrypoint behind a `bazel_native` feature so the Bazel-native library avoids the `dylint_*` packaging stack - update the aspect runtime environment so the driver can locate `rustc_driver` correctly under remote execution - keep the dedicated `tools/argument-comment-lint` package tests and wrapper unit tests in CI so the source and packaged entrypoints remain covered ## Verification - `python3 -m unittest discover -s tools/argument-comment-lint -p 'test_*.py'` - `cargo test` in `tools/argument-comment-lint` - `bazel build //tools/argument-comment-lint:argument-comment-lint-driver --@rules_rust//rust/toolchain/channel=nightly` - `bazel build --config=argument-comment-lint //codex-rs/utils/path-utils:all` - `bazel build --config=argument-comment-lint //codex-rs/rollout:rollout` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/16106). * #16120 * __->__ #16106 --- .bazelrc | 5 + .github/actions/setup-bazel-ci/action.yml | 8 +- .github/workflows/bazel.yml | 2 + .github/workflows/rust-ci-full.yml | 31 ++- .github/workflows/rust-ci.yml | 65 ++++-- MODULE.bazel | 37 ++++ MODULE.bazel.lock | 64 ++++++ codex-rs/BUILD.bazel | 14 ++ defs.bzl | 25 +++ justfile | 14 +- tools/argument-comment-lint/BUILD.bazel | 32 +++ tools/argument-comment-lint/Cargo.toml | 3 + tools/argument-comment-lint/README.md | 20 +- tools/argument-comment-lint/driver.rs | 43 ++++ tools/argument-comment-lint/lint_aspect.bzl | 187 ++++++++++++++++++ tools/argument-comment-lint/src/lib.rs | 1 + .../test_wrapper_common.py | 20 ++ tools/argument-comment-lint/wrapper_common.py | 5 +- 18 files changed, 525 insertions(+), 51 deletions(-) create mode 100644 tools/argument-comment-lint/BUILD.bazel create mode 100644 tools/argument-comment-lint/driver.rs create mode 100644 tools/argument-comment-lint/lint_aspect.bzl diff --git a/.bazelrc b/.bazelrc index 340871831a..b9275426fa 100644 --- a/.bazelrc +++ b/.bazelrc @@ -77,6 +77,11 @@ build:clippy --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect build:clippy --output_groups=+clippy_checks build:clippy --@rules_rust//rust/settings:clippy.toml=//codex-rs:clippy.toml +# Shared config for Bazel-backed argument-comment-lint. +build:argument-comment-lint --aspects=//tools/argument-comment-lint:lint_aspect.bzl%rust_argument_comment_lint_aspect +build:argument-comment-lint --output_groups=argument_comment_lint_checks +build:argument-comment-lint --@rules_rust//rust/toolchain/channel=nightly + # Rearrange caches on Windows so they're on the same volume as the checkout. common:ci-windows --config=ci-bazel common:ci-windows --build_metadata=TAG_os=windows diff --git a/.github/actions/setup-bazel-ci/action.yml b/.github/actions/setup-bazel-ci/action.yml index 0775f928a5..34bbd40b19 100644 --- a/.github/actions/setup-bazel-ci/action.yml +++ b/.github/actions/setup-bazel-ci/action.yml @@ -57,9 +57,11 @@ runs: if: runner.os == 'Windows' shell: pwsh run: | - # Use a very short path to reduce argv/path length issues, but avoid the - # drive root because some Windows test launchers mis-handle MANIFEST paths there. - "BAZEL_OUTPUT_USER_ROOT=D:\b" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + # Use the shortest available drive to reduce argv/path length issues, + # but avoid the drive root because some Windows test launchers mis-handle + # MANIFEST paths there. + $bazelOutputUserRoot = if (Test-Path 'D:\') { 'D:\b' } else { 'C:\b' } + "BAZEL_OUTPUT_USER_ROOT=$bazelOutputUserRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Enable Git long paths (Windows) if: runner.os == 'Windows' diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index 2636213af9..a6c9277b61 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -81,6 +81,7 @@ jobs: --use-node-test-env \ -- \ test \ + --test_tag_filters=-argument-comment-lint \ --test_verbose_timeout_warnings \ --build_metadata=COMMIT_SHA=${GITHUB_SHA} \ -- \ @@ -98,6 +99,7 @@ jobs: key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }} clippy: + timeout-minutes: 30 strategy: fail-fast: false matrix: diff --git a/.github/workflows/rust-ci-full.yml b/.github/workflows/rust-ci-full.yml index 43ce57cd47..9480c05379 100644 --- a/.github/workflows/rust-ci-full.yml +++ b/.github/workflows/rust-ci-full.yml @@ -73,6 +73,7 @@ jobs: argument_comment_lint_prebuilt: name: Argument comment lint - ${{ matrix.name }} runs-on: ${{ matrix.runs_on || matrix.runner }} + timeout-minutes: 30 strategy: fail-fast: false matrix: @@ -88,29 +89,27 @@ jobs: labels: codex-windows-x64 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: ./.github/actions/setup-bazel-ci + with: + target: ${{ runner.os }} + install-test-prereqs: true - name: Install Linux sandbox build dependencies if: ${{ runner.os == 'Linux' }} shell: bash run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev - - uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0 - with: - toolchain: nightly-2025-09-18 - components: llvm-tools-preview, rustc-dev, rust-src - - uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2 - - name: Run argument comment lint on codex-rs - if: ${{ runner.os == 'macOS' }} + - name: Run argument comment lint on codex-rs via Bazel shell: bash - run: python3 ./tools/argument-comment-lint/run-prebuilt-linter.py - - name: Run argument comment lint on codex-rs (default targets only) - if: ${{ runner.os == 'Linux' }} - shell: bash - run: python3 ./tools/argument-comment-lint/run-prebuilt-linter.py -- --lib --bins - - name: Run argument comment lint on codex-rs - if: ${{ runner.os == 'Windows' }} - shell: bash - run: python ./tools/argument-comment-lint/run-prebuilt-linter.py + run: | + ./.github/scripts/run-bazel-ci.sh \ + -- \ + build \ + --config=argument-comment-lint \ + --keep_going \ + --build_metadata=COMMIT_SHA=${GITHUB_SHA} \ + -- \ + //codex-rs/... # --- CI to validate on different os/targets -------------------------------- lint_build: diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index f993bccbe7..a655b3071e 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -93,9 +93,16 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0 - with: - toolchain: nightly-2025-09-18 - components: llvm-tools-preview, rustc-dev, rust-src + - name: Install nightly argument-comment-lint toolchain + shell: bash + run: | + rustup toolchain install nightly-2025-09-18 \ + --profile minimal \ + --component llvm-tools-preview \ + --component rustc-dev \ + --component rust-src \ + --no-self-update + rustup default nightly-2025-09-18 - name: Cache cargo-dylint tooling id: cargo_dylint_cache uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5 @@ -121,6 +128,7 @@ jobs: argument_comment_lint_prebuilt: name: Argument comment lint - ${{ matrix.name }} runs-on: ${{ matrix.runs_on || matrix.runner }} + timeout-minutes: ${{ matrix.timeout_minutes }} needs: changed if: ${{ needs.changed.outputs.argument_comment_lint == 'true' || needs.changed.outputs.workflows == 'true' }} strategy: @@ -129,40 +137,57 @@ jobs: include: - name: Linux runner: ubuntu-24.04 + timeout_minutes: 30 - name: macOS runner: macos-15-xlarge + timeout_minutes: 30 - name: Windows runner: windows-x64 + timeout_minutes: 30 runs_on: group: codex-runners labels: codex-windows-x64 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: ./.github/actions/setup-bazel-ci + with: + target: ${{ runner.os }} + install-test-prereqs: true - name: Install Linux sandbox build dependencies if: ${{ runner.os == 'Linux' }} shell: bash run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev - - uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0 - with: - toolchain: nightly-2025-09-18 - components: llvm-tools-preview, rustc-dev, rust-src - - uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2 - - name: Run argument comment lint on codex-rs - if: ${{ runner.os == 'macOS' }} - shell: bash - run: python3 ./tools/argument-comment-lint/run-prebuilt-linter.py - # Linux still uses the default-targets-only form for now, but PRs run the - # released linter on all three platforms so wrapper regressions surface pre-merge. - - name: Run argument comment lint on codex-rs (default targets only) - if: ${{ runner.os == 'Linux' }} - shell: bash - run: python3 ./tools/argument-comment-lint/run-prebuilt-linter.py -- --lib --bins - - name: Run argument comment lint on codex-rs + - name: Install nightly argument-comment-lint toolchain if: ${{ runner.os == 'Windows' }} shell: bash - run: python ./tools/argument-comment-lint/run-prebuilt-linter.py + run: | + rustup toolchain install nightly-2025-09-18 \ + --profile minimal \ + --component llvm-tools-preview \ + --component rustc-dev \ + --component rust-src \ + --no-self-update + rustup default nightly-2025-09-18 + - name: Run argument comment lint on codex-rs via Bazel + if: ${{ runner.os != 'Windows' }} + env: + BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} + shell: bash + run: | + ./.github/scripts/run-bazel-ci.sh \ + -- \ + build \ + --config=argument-comment-lint \ + --keep_going \ + --build_metadata=COMMIT_SHA=${GITHUB_SHA} \ + -- \ + //codex-rs/... + - name: Run argument comment lint on codex-rs via packaged wrapper + if: ${{ runner.os == 'Windows' }} + shell: bash + run: python3 ./tools/argument-comment-lint/run-prebuilt-linter.py # --- Gatherer job that you mark as the ONLY required status ----------------- results: diff --git a/MODULE.bazel b/MODULE.bazel index 63a86bf830..8163c0b018 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -87,6 +87,17 @@ rules_rust.patch( ) use_repo(rules_rust, "rules_rust") +nightly_rust = use_extension( + "@rules_rs//rs/experimental:rules_rust_reexported_extensions.bzl", + "rust", +) +nightly_rust.toolchain( + versions = ["nightly/2025-09-18"], + dev_components = True, + edition = "2024", +) +use_repo(nightly_rust, "rust_toolchains") + toolchains = use_extension("@rules_rs//rs/experimental/toolchains:module_extension.bzl", "toolchains") toolchains.toolchain( edition = "2024", @@ -95,6 +106,7 @@ toolchains.toolchain( use_repo(toolchains, "default_rust_toolchains") register_toolchains("@default_rust_toolchains//:all") +register_toolchains("@rust_toolchains//:all") crate = use_extension("@rules_rs//rs:extensions.bzl", "crate") crate.from_cargo( @@ -117,6 +129,24 @@ crate.from_cargo( ], use_experimental_platforms = True, ) +crate.from_cargo( + name = "argument_comment_lint_crates", + cargo_lock = "//tools/argument-comment-lint:Cargo.lock", + cargo_toml = "//tools/argument-comment-lint:Cargo.toml", + platform_triples = [ + "aarch64-unknown-linux-gnu", + "aarch64-unknown-linux-musl", + "aarch64-apple-darwin", + "aarch64-pc-windows-msvc", + "aarch64-pc-windows-gnullvm", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-musl", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-pc-windows-gnullvm", + ], + use_experimental_platforms = True, +) bazel_dep(name = "zstd", version = "1.5.7") @@ -136,7 +166,14 @@ crate.annotation( ], ) +crate.annotation( + # The build script only validates embedded source/version metadata. + crate = "rustc_apfloat", + gen_build_script = "off", +) + inject_repo(crate, "zstd") +use_repo(crate, "argument_comment_lint_crates") bazel_dep(name = "bzip2", version = "1.0.8.bcr.3") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 9e7ff69455..53c145b6d0 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -611,7 +611,9 @@ "anstyle-query_1.1.5": "{\"dependencies\":[{\"features\":[\"Win32_System_Console\",\"Win32_Foundation\"],\"name\":\"windows-sys\",\"req\":\">=0.60.2, <0.62\",\"target\":\"cfg(windows)\"}],\"features\":{}}", "anstyle-wincon_3.0.11": "{\"dependencies\":[{\"name\":\"anstyle\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"lexopt\",\"req\":\"^0.3.1\"},{\"name\":\"once_cell_polyfill\",\"req\":\"^1.56.1\",\"target\":\"cfg(windows)\"},{\"features\":[\"Win32_System_Console\",\"Win32_Foundation\"],\"name\":\"windows-sys\",\"req\":\">=0.60.2, <0.62\",\"target\":\"cfg(windows)\"}],\"features\":{}}", "anstyle_1.0.13": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"lexopt\",\"req\":\"^0.3.0\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.5\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", + "anstyle_1.0.14": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"lexopt\",\"req\":\"^0.3.1\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.23\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "anyhow_1.0.101": "{\"dependencies\":[{\"name\":\"backtrace\",\"optional\":true,\"req\":\"^0.3.51\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"futures\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0.6\"},{\"features\":[\"full\"],\"kind\":\"dev\",\"name\":\"syn\",\"req\":\"^2.0\"},{\"kind\":\"dev\",\"name\":\"thiserror\",\"req\":\"^2\"},{\"features\":[\"diff\"],\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.108\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", + "anyhow_1.0.102": "{\"dependencies\":[{\"default_features\":false,\"kind\":\"dev\",\"name\":\"futures\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0.6\"},{\"features\":[\"full\"],\"kind\":\"dev\",\"name\":\"syn\",\"req\":\"^2.0\"},{\"kind\":\"dev\",\"name\":\"thiserror\",\"req\":\"^2\"},{\"features\":[\"diff\"],\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.108\"}],\"features\":{\"backtrace\":[],\"default\":[\"std\"],\"std\":[]}}", "arbitrary_1.4.2": "{\"dependencies\":[{\"name\":\"derive_arbitrary\",\"optional\":true,\"req\":\"~1.4.0\"},{\"kind\":\"dev\",\"name\":\"exhaustigen\",\"req\":\"^0.1.0\"}],\"features\":{\"derive\":[\"derive_arbitrary\"]}}", "arboard_3.6.1": "{\"dependencies\":[{\"features\":[\"std\"],\"name\":\"clipboard-win\",\"req\":\"^5.3.1\",\"target\":\"cfg(windows)\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.10.2\"},{\"default_features\":false,\"features\":[\"png\"],\"name\":\"image\",\"optional\":true,\"req\":\"^0.25\",\"target\":\"cfg(all(unix, not(any(target_os=\\\"macos\\\", target_os=\\\"android\\\", target_os=\\\"emscripten\\\"))))\"},{\"default_features\":false,\"features\":[\"tiff\"],\"name\":\"image\",\"optional\":true,\"req\":\"^0.25\",\"target\":\"cfg(target_os = \\\"macos\\\")\"},{\"default_features\":false,\"features\":[\"png\",\"bmp\"],\"name\":\"image\",\"optional\":true,\"req\":\"^0.25\",\"target\":\"cfg(windows)\"},{\"name\":\"log\",\"req\":\"^0.4\",\"target\":\"cfg(all(unix, not(any(target_os=\\\"macos\\\", target_os=\\\"android\\\", target_os=\\\"emscripten\\\"))))\"},{\"name\":\"log\",\"req\":\"^0.4\",\"target\":\"cfg(windows)\"},{\"name\":\"objc2\",\"req\":\"^0.6.0\",\"target\":\"cfg(target_os = \\\"macos\\\")\"},{\"default_features\":false,\"features\":[\"std\",\"objc2-core-graphics\",\"NSPasteboard\",\"NSPasteboardItem\",\"NSImage\"],\"name\":\"objc2-app-kit\",\"req\":\"^0.3.0\",\"target\":\"cfg(target_os = \\\"macos\\\")\"},{\"default_features\":false,\"features\":[\"std\",\"CFCGTypes\"],\"name\":\"objc2-core-foundation\",\"optional\":true,\"req\":\"^0.3.0\",\"target\":\"cfg(target_os = \\\"macos\\\")\"},{\"default_features\":false,\"features\":[\"std\",\"CGImage\",\"CGColorSpace\",\"CGDataProvider\"],\"name\":\"objc2-core-graphics\",\"optional\":true,\"req\":\"^0.3.0\",\"target\":\"cfg(target_os = \\\"macos\\\")\"},{\"default_features\":false,\"features\":[\"std\",\"NSArray\",\"NSString\",\"NSEnumerator\",\"NSGeometry\",\"NSValue\"],\"name\":\"objc2-foundation\",\"req\":\"^0.3.0\",\"target\":\"cfg(target_os = \\\"macos\\\")\"},{\"name\":\"parking_lot\",\"req\":\"^0.12\",\"target\":\"cfg(all(unix, not(any(target_os=\\\"macos\\\", target_os=\\\"android\\\", target_os=\\\"emscripten\\\"))))\"},{\"name\":\"percent-encoding\",\"req\":\"^2.3.1\",\"target\":\"cfg(all(unix, not(any(target_os=\\\"macos\\\", target_os=\\\"android\\\", target_os=\\\"emscripten\\\"))))\"},{\"features\":[\"Win32_Foundation\",\"Win32_Storage_FileSystem\",\"Win32_System_DataExchange\",\"Win32_System_Memory\",\"Win32_System_Ole\",\"Win32_UI_Shell\"],\"name\":\"windows-sys\",\"req\":\">=0.52.0, <0.61.0\",\"target\":\"cfg(windows)\"},{\"name\":\"wl-clipboard-rs\",\"optional\":true,\"req\":\"^0.9.0\",\"target\":\"cfg(all(unix, not(any(target_os=\\\"macos\\\", target_os=\\\"android\\\", target_os=\\\"emscripten\\\"))))\"},{\"name\":\"x11rb\",\"req\":\"^0.13\",\"target\":\"cfg(all(unix, not(any(target_os=\\\"macos\\\", target_os=\\\"android\\\", target_os=\\\"emscripten\\\"))))\"}],\"features\":{\"core-graphics\":[\"dep:objc2-core-graphics\"],\"default\":[\"image-data\"],\"image\":[\"dep:image\"],\"image-data\":[\"dep:objc2-core-graphics\",\"dep:objc2-core-foundation\",\"image\",\"windows-sys\",\"core-graphics\"],\"wayland-data-control\":[\"wl-clipboard-rs\"],\"windows-sys\":[\"windows-sys/Win32_Graphics_Gdi\"],\"wl-clipboard-rs\":[\"dep:wl-clipboard-rs\"]}}", "arc-swap_1.9.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"adaptive-barrier\",\"req\":\"~1\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"~0.7\"},{\"kind\":\"dev\",\"name\":\"crossbeam-utils\",\"req\":\"~0.8\"},{\"kind\":\"dev\",\"name\":\"itertools\",\"req\":\"^0.14\"},{\"kind\":\"dev\",\"name\":\"num_cpus\",\"req\":\"~1\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"~1\"},{\"kind\":\"dev\",\"name\":\"parking_lot\",\"req\":\"~0.12\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"name\":\"rustversion\",\"req\":\"^1\"},{\"features\":[\"rc\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0.130\"},{\"kind\":\"dev\",\"name\":\"serde_test\",\"req\":\"^1.0.177\"}],\"features\":{\"experimental-strategies\":[],\"experimental-thread-local\":[],\"internal-test-strategies\":[],\"weak\":[]}}", @@ -658,6 +660,7 @@ "bit-vec_0.6.3": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"rand_xorshift\",\"req\":\"^0.2\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"}],\"features\":{\"default\":[\"std\"],\"serde_no_std\":[\"serde/alloc\"],\"serde_std\":[\"std\",\"serde/std\"],\"std\":[]}}", "bitflags_1.3.2": "{\"dependencies\":[{\"name\":\"compiler_builtins\",\"optional\":true,\"req\":\"^0.1.2\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.3\"}],\"features\":{\"default\":[],\"example_generated\":[],\"rustc-dep-of-std\":[\"core\",\"compiler_builtins\"]}}", "bitflags_2.10.0": "{\"dependencies\":[{\"name\":\"arbitrary\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"arbitrary\",\"req\":\"^1.0\"},{\"name\":\"bytemuck\",\"optional\":true,\"req\":\"^1.12\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"bytemuck\",\"req\":\"^1.12.2\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.228\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde_lib\",\"package\":\"serde\",\"req\":\"^1.0.103\"},{\"kind\":\"dev\",\"name\":\"serde_test\",\"req\":\"^1.0.19\"},{\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.18\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"zerocopy\",\"req\":\"^0.8\"}],\"features\":{\"example_generated\":[],\"serde\":[\"serde_core\"],\"std\":[]}}", + "bitflags_2.11.0": "{\"dependencies\":[{\"name\":\"arbitrary\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"arbitrary\",\"req\":\"^1.0\"},{\"name\":\"bytemuck\",\"optional\":true,\"req\":\"^1.12\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"bytemuck\",\"req\":\"^1.12.2\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.228\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde_lib\",\"package\":\"serde\",\"req\":\"^1.0.103\"},{\"kind\":\"dev\",\"name\":\"serde_test\",\"req\":\"^1.0.19\"},{\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.18\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"zerocopy\",\"req\":\"^0.8\"}],\"features\":{\"example_generated\":[],\"serde\":[\"serde_core\"],\"std\":[]}}", "block-buffer_0.10.4": "{\"dependencies\":[{\"name\":\"generic-array\",\"req\":\"^0.14\"}],\"features\":{}}", "block-padding_0.3.3": "{\"dependencies\":[{\"name\":\"generic-array\",\"req\":\"^0.14\"}],\"features\":{\"std\":[]}}", "block2_0.6.2": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"std\"],\"name\":\"objc2\",\"req\":\">=0.6.2, <0.8.0\"}],\"features\":{\"alloc\":[],\"compiler-rt\":[\"objc2/unstable-compiler-rt\"],\"default\":[\"std\"],\"gnustep-1-7\":[\"objc2/gnustep-1-7\"],\"gnustep-1-8\":[\"gnustep-1-7\",\"objc2/gnustep-1-8\"],\"gnustep-1-9\":[\"gnustep-1-8\",\"objc2/gnustep-1-9\"],\"gnustep-2-0\":[\"gnustep-1-9\",\"objc2/gnustep-2-0\"],\"gnustep-2-1\":[\"gnustep-2-0\",\"objc2/gnustep-2-1\"],\"std\":[\"alloc\"],\"unstable-coerce-pointee\":[],\"unstable-objfw\":[],\"unstable-private\":[],\"unstable-winobjc\":[\"gnustep-1-8\"]}}", @@ -677,10 +680,14 @@ "cached_proc_macro_0.25.0": "{\"dependencies\":[{\"name\":\"darling\",\"req\":\"^0.20.8\"},{\"name\":\"proc-macro2\",\"req\":\"^1.0.49\"},{\"name\":\"quote\",\"req\":\"^1.0.6\"},{\"name\":\"syn\",\"req\":\"^2.0.52\"}],\"features\":{}}", "cached_proc_macro_types_0.1.1": "{\"dependencies\":[],\"features\":{}}", "calendrical_calculations_0.2.3": "{\"dependencies\":[{\"default_features\":false,\"name\":\"core_maths\",\"req\":\"^0.1.0\"},{\"default_features\":false,\"name\":\"displaydoc\",\"req\":\"^0.2.3\"},{\"default_features\":false,\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.17\"}],\"features\":{\"logging\":[\"dep:log\"]}}", + "camino_1.2.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1\"},{\"name\":\"proptest\",\"optional\":true,\"req\":\"^1.0.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.223\"},{\"kind\":\"dev\",\"name\":\"serde_bytes\",\"req\":\"^0.11.8\"},{\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"proptest1\":[\"dep:proptest\"],\"serde1\":[\"dep:serde_core\"]}}", + "cargo-platform_0.3.2": "{\"dependencies\":[{\"name\":\"serde\",\"req\":\"^1.0.228\",\"target\":\"cfg(any())\"},{\"name\":\"serde_core\",\"req\":\"^1.0.228\"}],\"features\":{}}", + "cargo_metadata_0.23.1": "{\"dependencies\":[{\"features\":[\"serde1\"],\"name\":\"camino\",\"req\":\"^1.1.10\"},{\"name\":\"cargo-platform\",\"req\":\"^0.3.0\"},{\"name\":\"derive_builder\",\"optional\":true,\"req\":\"^0.20\"},{\"features\":[\"serde\"],\"name\":\"semver\",\"req\":\"^1.0.26\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"req\":\"^1.0.219\"},{\"features\":[\"unbounded_depth\"],\"name\":\"serde_json\",\"req\":\"^1.0.142\"},{\"name\":\"thiserror\",\"req\":\"^2.0.12\"}],\"features\":{\"builder\":[\"derive_builder\"],\"default\":[],\"unstable\":[]}}", "cassowary_0.3.0": "{\"dependencies\":[],\"features\":{}}", "castaway_0.2.4": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"paste\",\"req\":\"^1\"},{\"name\":\"rustversion\",\"req\":\"^1\"}],\"features\":{\"alloc\":[],\"default\":[\"std\"],\"std\":[\"alloc\"]}}", "cbc_0.1.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"aes\",\"req\":\"^0.8\"},{\"name\":\"cipher\",\"req\":\"^0.4.2\"},{\"features\":[\"dev\"],\"kind\":\"dev\",\"name\":\"cipher\",\"req\":\"^0.4.2\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.3.3\"}],\"features\":{\"alloc\":[\"cipher/alloc\"],\"block-padding\":[\"cipher/block-padding\"],\"default\":[\"block-padding\"],\"std\":[\"cipher/std\",\"alloc\"],\"zeroize\":[\"cipher/zeroize\"]}}", "cc_1.2.55": "{\"dependencies\":[{\"name\":\"find-msvc-tools\",\"req\":\"^0.1.9\"},{\"default_features\":false,\"name\":\"jobserver\",\"optional\":true,\"req\":\"^0.1.30\"},{\"default_features\":false,\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.62\",\"target\":\"cfg(unix)\"},{\"name\":\"shlex\",\"req\":\"^1.3.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{\"jobserver\":[],\"parallel\":[\"dep:libc\",\"dep:jobserver\"]}}", + "cc_1.2.56": "{\"dependencies\":[{\"name\":\"find-msvc-tools\",\"req\":\"^0.1.9\"},{\"default_features\":false,\"name\":\"jobserver\",\"optional\":true,\"req\":\"^0.1.30\"},{\"default_features\":false,\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.62\",\"target\":\"cfg(unix)\"},{\"name\":\"shlex\",\"req\":\"^1.3.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{\"jobserver\":[],\"parallel\":[\"dep:libc\",\"dep:jobserver\"]}}", "cesu8_1.1.0": "{\"dependencies\":[],\"features\":{\"unstable\":[]}}", "cexpr_0.6.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"clang-sys\",\"req\":\">=0.13.0, <0.29.0\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"nom\",\"req\":\"^7\"}],\"features\":{}}", "cfg-if_1.0.4": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"}],\"features\":{\"rustc-dep-of-std\":[\"core\"]}}", @@ -705,8 +712,10 @@ "color-spantrace_0.3.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"ansi-parser\",\"req\":\"^0.8\"},{\"name\":\"once_cell\",\"req\":\"^1.18.0\"},{\"name\":\"owo-colors\",\"req\":\"^4.0\"},{\"kind\":\"dev\",\"name\":\"tracing\",\"req\":\"^0.1.29\"},{\"name\":\"tracing-core\",\"req\":\"^0.1.21\"},{\"name\":\"tracing-error\",\"req\":\"^0.2.0\"},{\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3.4\"}],\"features\":{}}", "color_quant_1.1.0": "{\"dependencies\":[],\"features\":{}}", "colorchoice_1.0.4": "{\"dependencies\":[],\"features\":{}}", + "colorchoice_1.0.5": "{\"dependencies\":[],\"features\":{}}", "combine_4.6.7": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"async-std\",\"req\":\"^1\"},{\"name\":\"bytes\",\"optional\":true,\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"bytes\",\"req\":\"^1\"},{\"name\":\"bytes_05\",\"optional\":true,\"package\":\"bytes\",\"req\":\"^0.5\"},{\"kind\":\"dev\",\"name\":\"bytes_05\",\"package\":\"bytes\",\"req\":\"^0.5\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"futures-03-dep\",\"package\":\"futures\",\"req\":\"^0.3.1\"},{\"default_features\":false,\"name\":\"futures-core-03\",\"optional\":true,\"package\":\"futures-core\",\"req\":\"^0.3.1\"},{\"default_features\":false,\"name\":\"futures-io-03\",\"optional\":true,\"package\":\"futures-io\",\"req\":\"^0.3.1\"},{\"default_features\":false,\"name\":\"memchr\",\"req\":\"^2.3\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"^1.0\"},{\"features\":[\"tokio\",\"quickcheck\"],\"kind\":\"dev\",\"name\":\"partial-io\",\"req\":\"^0.3\"},{\"name\":\"pin-project-lite\",\"optional\":true,\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"quick-error\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^0.6\"},{\"name\":\"regex\",\"optional\":true,\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"io-util\"],\"name\":\"tokio-02-dep\",\"optional\":true,\"package\":\"tokio\",\"req\":\"^0.2.3\"},{\"features\":[\"fs\",\"io-driver\",\"io-util\",\"macros\"],\"kind\":\"dev\",\"name\":\"tokio-02-dep\",\"package\":\"tokio\",\"req\":\"^0.2\"},{\"default_features\":false,\"name\":\"tokio-03-dep\",\"optional\":true,\"package\":\"tokio\",\"req\":\"^0.3\"},{\"features\":[\"fs\",\"macros\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio-03-dep\",\"package\":\"tokio\",\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"tokio-dep\",\"optional\":true,\"package\":\"tokio\",\"req\":\"^1\"},{\"features\":[\"fs\",\"macros\",\"rt\",\"rt-multi-thread\",\"io-util\"],\"kind\":\"dev\",\"name\":\"tokio-dep\",\"package\":\"tokio\",\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"codec\"],\"name\":\"tokio-util\",\"optional\":true,\"req\":\"^0.7\"}],\"features\":{\"alloc\":[],\"default\":[\"std\"],\"futures-03\":[\"pin-project\",\"std\",\"futures-core-03\",\"futures-io-03\",\"pin-project-lite\"],\"mp4\":[],\"pin-project\":[\"pin-project-lite\"],\"std\":[\"memchr/std\",\"bytes\",\"alloc\"],\"tokio\":[\"tokio-dep\",\"tokio-util/io\",\"futures-core-03\",\"pin-project-lite\"],\"tokio-02\":[\"pin-project\",\"std\",\"tokio-02-dep\",\"futures-core-03\",\"pin-project-lite\",\"bytes_05\"],\"tokio-03\":[\"pin-project\",\"std\",\"tokio-03-dep\",\"futures-core-03\",\"pin-project-lite\"]}}", "compact_str_0.8.1": "{\"dependencies\":[{\"default_features\":false,\"name\":\"arbitrary\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"borsh\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"bytes\",\"optional\":true,\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"castaway\",\"req\":\"^0.2.3\"},{\"name\":\"cfg-if\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"cfg-if\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"diesel\",\"optional\":true,\"req\":\"^2\"},{\"name\":\"itoa\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"markup\",\"optional\":true,\"req\":\"^0.13\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"proptest\",\"optional\":true,\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"quickcheck\",\"optional\":true,\"req\":\"^1\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"quickcheck_macros\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"size_32\"],\"name\":\"rkyv\",\"optional\":true,\"req\":\"^0.7\"},{\"default_features\":false,\"features\":[\"alloc\",\"size_32\"],\"kind\":\"dev\",\"name\":\"rkyv\",\"req\":\"^0.7\"},{\"name\":\"rustversion\",\"req\":\"^1\"},{\"name\":\"ryu\",\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"derive\",\"alloc\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1\"},{\"features\":[\"union\"],\"name\":\"smallvec\",\"optional\":true,\"req\":\"^1\"},{\"default_features\":false,\"name\":\"sqlx\",\"optional\":true,\"req\":\"^0.7\"},{\"name\":\"static_assertions\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"test-case\",\"req\":\"^3\"},{\"kind\":\"dev\",\"name\":\"test-strategy\",\"req\":\"^0.3\"}],\"features\":{\"arbitrary\":[\"dep:arbitrary\"],\"borsh\":[\"dep:borsh\"],\"bytes\":[\"dep:bytes\"],\"default\":[\"std\"],\"diesel\":[\"dep:diesel\"],\"markup\":[\"dep:markup\"],\"proptest\":[\"dep:proptest\"],\"quickcheck\":[\"dep:quickcheck\"],\"rkyv\":[\"dep:rkyv\"],\"serde\":[\"dep:serde\"],\"smallvec\":[\"dep:smallvec\"],\"sqlx\":[\"dep:sqlx\",\"std\"],\"sqlx-mysql\":[\"sqlx\",\"sqlx/mysql\"],\"sqlx-postgres\":[\"sqlx\",\"sqlx/postgres\"],\"sqlx-sqlite\":[\"sqlx\",\"sqlx/sqlite\"],\"std\":[]}}", + "compiletest_rs_0.11.2": "{\"dependencies\":[{\"name\":\"diff\",\"req\":\"^0.1.10\"},{\"name\":\"filetime\",\"req\":\"^0.2\"},{\"name\":\"getopts\",\"req\":\"^0.2\"},{\"name\":\"lazy_static\",\"req\":\"^1.4\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"name\":\"log\",\"req\":\"^0.4\"},{\"name\":\"miow\",\"req\":\"^0.6\",\"target\":\"cfg(windows)\"},{\"name\":\"regex\",\"req\":\"^1.0\"},{\"name\":\"rustfix\",\"req\":\"^0.8\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde_derive\",\"req\":\"^1.0\"},{\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"tempfile\",\"optional\":true,\"req\":\"^3.0\"},{\"name\":\"tester\",\"req\":\"^0.9\"},{\"features\":[\"Win32\"],\"name\":\"windows-sys\",\"req\":\"^0.59\",\"target\":\"cfg(windows)\"}],\"features\":{\"rustc\":[],\"stable\":[],\"tmp\":[\"tempfile\"]}}", "concurrent-queue_2.5.0": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"cargo_bench_support\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5\"},{\"default_features\":false,\"name\":\"crossbeam-utils\",\"req\":\"^0.8.11\"},{\"kind\":\"dev\",\"name\":\"easy-parallel\",\"req\":\"^3.1.0\"},{\"kind\":\"dev\",\"name\":\"fastrand\",\"req\":\"^2.0.0\"},{\"name\":\"loom\",\"optional\":true,\"req\":\"^0.7\",\"target\":\"cfg(loom)\"},{\"default_features\":false,\"name\":\"portable-atomic\",\"optional\":true,\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3\",\"target\":\"cfg(target_family = \\\"wasm\\\")\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "console_0.15.11": "{\"dependencies\":[{\"name\":\"encode_unicode\",\"req\":\"^1\",\"target\":\"cfg(windows)\"},{\"name\":\"libc\",\"req\":\"^0.2.99\"},{\"name\":\"once_cell\",\"req\":\"^1.8\"},{\"default_features\":false,\"features\":[\"std\",\"bit-set\",\"break-dead-code\"],\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.4.2\"},{\"name\":\"unicode-width\",\"optional\":true,\"req\":\"^0.2\"},{\"features\":[\"Win32_Foundation\",\"Win32_System_Console\",\"Win32_Storage_FileSystem\",\"Win32_UI_Input_KeyboardAndMouse\"],\"name\":\"windows-sys\",\"req\":\"^0.59\",\"target\":\"cfg(windows)\"}],\"features\":{\"ansi-parsing\":[],\"default\":[\"unicode-width\",\"ansi-parsing\"],\"windows-console-colors\":[\"ansi-parsing\"]}}", "const-hex_1.17.0": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1\"},{\"name\":\"cpufeatures\",\"req\":\"^0.2\",\"target\":\"cfg(any(target_arch = \\\"x86\\\", target_arch = \\\"x86_64\\\"))\"},{\"kind\":\"dev\",\"name\":\"divan\",\"package\":\"codspeed-divan-compat\",\"req\":\"^3\"},{\"default_features\":false,\"features\":[\"alloc\"],\"kind\":\"dev\",\"name\":\"faster-hex\",\"req\":\"^0.10.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"kind\":\"dev\",\"name\":\"hex\",\"req\":\"~0.4.2\"},{\"default_features\":false,\"name\":\"proptest\",\"optional\":true,\"req\":\"^1.4\"},{\"kind\":\"dev\",\"name\":\"rustc-hex\",\"req\":\"^2.1\"},{\"default_features\":false,\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"}],\"features\":{\"__fuzzing\":[\"dep:proptest\",\"std\"],\"alloc\":[\"serde_core?/alloc\",\"proptest?/alloc\"],\"core-error\":[],\"default\":[\"std\"],\"force-generic\":[],\"hex\":[],\"nightly\":[],\"portable-simd\":[],\"serde\":[\"dep:serde_core\"],\"std\":[\"serde_core?/std\",\"proptest?/std\",\"alloc\"]}}", @@ -793,6 +802,10 @@ "dunce_1.0.5": "{\"dependencies\":[],\"features\":{}}", "dupe_0.9.1": "{\"dependencies\":[{\"name\":\"dupe_derive\",\"req\":\"=0.9.1\"}],\"features\":{}}", "dupe_derive_0.9.1": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1.0\"},{\"name\":\"quote\",\"req\":\"^1.0.3\"},{\"features\":[\"extra-traits\"],\"name\":\"syn\",\"req\":\"^2\"}],\"features\":{}}", + "dylint_5.0.0": "{\"dependencies\":[{\"name\":\"anstyle\",\"req\":\"^1.0\"},{\"name\":\"anyhow\",\"req\":\"^1.0\"},{\"name\":\"cargo-util\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"cargo-util-schemas\",\"optional\":true,\"req\":\"^0.10\"},{\"name\":\"cargo_metadata\",\"req\":\"^0.23\"},{\"default_features\":false,\"name\":\"chrono\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"dunce\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"config\",\"git\",\"packaging\",\"rustup\"],\"name\":\"dylint_internal\",\"req\":\"=5.0.0\"},{\"features\":[\"cargo\"],\"kind\":\"build\",\"name\":\"dylint_internal\",\"req\":\"=5.0.0\"},{\"features\":[\"examples\"],\"kind\":\"dev\",\"name\":\"dylint_internal\",\"req\":\"=5.0.0\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.11\"},{\"name\":\"fs_extra\",\"optional\":true,\"req\":\"^1.3\"},{\"name\":\"glob\",\"optional\":true,\"req\":\"^0.3\"},{\"name\":\"heck\",\"optional\":true,\"req\":\"^0.5\"},{\"name\":\"hex\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"if_chain\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"log\",\"req\":\"^0.4\"},{\"name\":\"once_cell\",\"req\":\"^1.21\"},{\"name\":\"rewriter\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"rustc-stable-hash\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"semver\",\"req\":\"^1.0\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde-untagged\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"default-syntaxes\",\"regex-fancy\",\"parsing\"],\"name\":\"syntect\",\"optional\":true,\"req\":\"^5.3\"},{\"name\":\"tempfile\",\"req\":\"^3.23\"},{\"name\":\"toml\",\"optional\":true,\"req\":\"^0.9\"},{\"name\":\"url\",\"optional\":true,\"req\":\"^2.5\"},{\"name\":\"walkdir\",\"optional\":true,\"req\":\"^2.5\"}],\"features\":{\"__cargo_cli\":[\"cargo-util\",\"cargo-util-schemas\",\"dunce\",\"dylint_internal/home\",\"fs_extra\",\"glob\",\"hex\",\"if_chain\",\"rustc-stable-hash\",\"serde-untagged\",\"toml\",\"url\"],\"default\":[],\"library_packages\":[\"__cargo_cli\"],\"package_options\":[\"chrono\",\"dylint_internal/clippy_utils\",\"dylint_internal/git\",\"heck\",\"if_chain\",\"rewriter\",\"syntect\",\"walkdir\"]}}", + "dylint_internal_5.0.0": "{\"dependencies\":[{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"anyhow\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"assert_cmd\",\"req\":\"^2.0\"},{\"name\":\"bitflags\",\"optional\":true,\"req\":\"^2.9\"},{\"name\":\"cargo-util\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"cargo_metadata\",\"optional\":true,\"req\":\"^0.23\"},{\"name\":\"ctor\",\"optional\":true,\"req\":\"^0.6\"},{\"name\":\"env_logger\",\"optional\":true,\"req\":\"^0.11\"},{\"name\":\"git2\",\"optional\":true,\"req\":\"^0.20\"},{\"name\":\"home\",\"optional\":true,\"req\":\"=0.5.9\"},{\"name\":\"if_chain\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"log\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"predicates\",\"req\":\"^3.1\"},{\"name\":\"regex\",\"req\":\"^1.11\"},{\"name\":\"rustversion\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"semver\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"tar\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"tempfile\",\"optional\":true,\"req\":\"^3.23\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.23\"},{\"name\":\"thiserror\",\"optional\":true,\"req\":\"^2.0\"},{\"name\":\"toml\",\"optional\":true,\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"toml\",\"req\":\"^0.9\"},{\"name\":\"toml_edit\",\"optional\":true,\"req\":\"^0.23\"},{\"kind\":\"dev\",\"name\":\"toml_edit\",\"req\":\"^0.23\"},{\"name\":\"walkdir\",\"optional\":true,\"req\":\"^2.5\"}],\"features\":{\"cargo\":[\"anstyle\",\"bitflags\",\"cargo_metadata\",\"home\"],\"clippy_utils\":[\"git\",\"semver\",\"tempfile\",\"toml\",\"toml_edit\"],\"config\":[\"cargo_metadata\",\"serde\",\"thiserror\",\"toml\"],\"examples\":[\"cargo\",\"cargo-util\",\"rustup\",\"walkdir\"],\"git\":[\"git2\",\"if_chain\"],\"home\":[\"dep:home\",\"rustversion\"],\"match_def_path\":[],\"packaging\":[\"cargo\",\"tar\"],\"rustup\":[\"cargo_metadata\"],\"testing\":[\"ctor\",\"env_logger\",\"packaging\"]}}", + "dylint_linting_5.0.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"assert_cmd\",\"req\":\"^2.0\"},{\"name\":\"cargo_metadata\",\"req\":\"^0.23\"},{\"features\":[\"config\"],\"name\":\"dylint_internal\",\"req\":\"=5.0.0\"},{\"name\":\"paste\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"rustc_version\",\"req\":\"^0.4\"},{\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.23\"},{\"name\":\"thiserror\",\"req\":\"^2.0\"},{\"name\":\"toml\",\"req\":\"^0.9\"},{\"kind\":\"build\",\"name\":\"toml\",\"req\":\"^0.9\"}],\"features\":{\"constituent\":[]}}", + "dylint_testing_5.0.0": "{\"dependencies\":[{\"name\":\"anyhow\",\"req\":\"^1.0\"},{\"name\":\"cargo_metadata\",\"req\":\"^0.23\"},{\"name\":\"compiletest_rs\",\"req\":\"^0.11\"},{\"name\":\"dylint\",\"req\":\"=5.0.0\"},{\"name\":\"dylint_internal\",\"req\":\"=5.0.0\"},{\"name\":\"env_logger\",\"req\":\"^0.11\"},{\"name\":\"once_cell\",\"req\":\"^1.21\"},{\"name\":\"regex\",\"req\":\"^1.11\"},{\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"tempfile\",\"req\":\"^3.23\"}],\"features\":{\"default\":[],\"deny_warnings\":[]}}", "dyn-clone_1.0.20": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"features\":[\"diff\"],\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.66\"}],\"features\":{}}", "either_1.15.0": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"alloc\",\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.95\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.0\"}],\"features\":{\"default\":[\"std\"],\"std\":[],\"use_std\":[\"std\"]}}", "ena_0.14.3": "{\"dependencies\":[{\"name\":\"dogged\",\"optional\":true,\"req\":\"^0.2.0\"},{\"name\":\"log\",\"req\":\"^0.4\"}],\"features\":{\"bench\":[],\"persistent\":[\"dogged\"]}}", @@ -824,6 +837,7 @@ "fdeflate_0.3.7": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"miniz_oxide\",\"req\":\"^0.7.1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.5\"},{\"name\":\"simd-adler32\",\"req\":\"^0.3.4\"}],\"features\":{}}", "fiat-crypto_0.2.9": "{\"dependencies\":[],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "filedescriptor_0.8.3": "{\"dependencies\":[{\"name\":\"libc\",\"req\":\"^0.2\"},{\"name\":\"thiserror\",\"req\":\"^1.0\"},{\"features\":[\"winuser\",\"handleapi\",\"fileapi\",\"namedpipeapi\",\"processthreadsapi\",\"winsock2\",\"processenv\"],\"name\":\"winapi\",\"req\":\"^0.3\",\"target\":\"cfg(windows)\"}],\"features\":{}}", + "filetime_0.2.27": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1.0.0\"},{\"name\":\"libc\",\"req\":\"^0.2.27\",\"target\":\"cfg(unix)\"},{\"name\":\"libredox\",\"req\":\"^0.1.0\",\"target\":\"cfg(target_os = \\\"redox\\\")\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{}}", "find-crate_0.6.3": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"proc-macro2\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"quote\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"semver\",\"req\":\"^0.11\"},{\"name\":\"toml\",\"req\":\"^0.5.2\"}],\"features\":{}}", "find-msvc-tools_0.1.9": "{\"dependencies\":[],\"features\":{}}", "findshlibs_0.10.2": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0.67\"},{\"name\":\"lazy_static\",\"req\":\"^1.4\",\"target\":\"cfg(any(target_os = \\\"macos\\\", target_os = \\\"ios\\\"))\"},{\"name\":\"libc\",\"req\":\"^0.2.104\"},{\"features\":[\"psapi\",\"memoryapi\",\"libloaderapi\",\"processthreadsapi\"],\"name\":\"winapi\",\"req\":\"^0.3.9\",\"target\":\"cfg(target_os = \\\"windows\\\")\"}],\"features\":{}}", @@ -865,6 +879,7 @@ "getopts_0.2.24": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"log\",\"req\":\"^0.4\"},{\"name\":\"std\",\"optional\":true,\"package\":\"rustc-std-workspace-std\",\"req\":\"^1.0\"},{\"name\":\"unicode-width\",\"optional\":true,\"req\":\"^0.2.0\"}],\"features\":{\"default\":[\"unicode\"],\"rustc-dep-of-std\":[\"std\",\"core\"],\"unicode\":[\"dep:unicode-width\"]}}", "getrandom_0.2.17": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1\"},{\"name\":\"compiler_builtins\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0\"},{\"name\":\"js-sys\",\"optional\":true,\"req\":\"^0.3\",\"target\":\"cfg(all(any(target_arch = \\\"wasm32\\\", target_arch = \\\"wasm64\\\"), target_os = \\\"unknown\\\"))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(unix)\"},{\"default_features\":false,\"name\":\"wasi\",\"req\":\"^0.11\",\"target\":\"cfg(target_os = \\\"wasi\\\")\"},{\"default_features\":false,\"name\":\"wasm-bindgen\",\"optional\":true,\"req\":\"^0.2.62\",\"target\":\"cfg(all(any(target_arch = \\\"wasm32\\\", target_arch = \\\"wasm64\\\"), target_os = \\\"unknown\\\"))\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3.18\",\"target\":\"cfg(all(any(target_arch = \\\"wasm32\\\", target_arch = \\\"wasm64\\\"), target_os = \\\"unknown\\\"))\"}],\"features\":{\"custom\":[],\"js\":[\"wasm-bindgen\",\"js-sys\"],\"linux_disable_fallback\":[],\"rdrand\":[],\"rustc-dep-of-std\":[\"compiler_builtins\",\"core\",\"libc/rustc-dep-of-std\",\"wasi/rustc-dep-of-std\"],\"std\":[],\"test-in-browser\":[]}}", "getrandom_0.3.4": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"js-sys\",\"optional\":true,\"req\":\"^0.3.77\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", any(target_os = \\\"unknown\\\", target_os = \\\"none\\\"), target_feature = \\\"atomics\\\"))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(all(any(target_os = \\\"linux\\\", target_os = \\\"android\\\"), not(any(all(target_os = \\\"linux\\\", target_env = \\\"\\\"), getrandom_backend = \\\"custom\\\", getrandom_backend = \\\"linux_raw\\\", getrandom_backend = \\\"rdrand\\\", getrandom_backend = \\\"rndr\\\"))))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(any(target_os = \\\"dragonfly\\\", target_os = \\\"freebsd\\\", target_os = \\\"hurd\\\", target_os = \\\"illumos\\\", target_os = \\\"cygwin\\\", all(target_os = \\\"horizon\\\", target_arch = \\\"arm\\\")))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(any(target_os = \\\"haiku\\\", target_os = \\\"redox\\\", target_os = \\\"nto\\\", target_os = \\\"aix\\\"))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(any(target_os = \\\"ios\\\", target_os = \\\"visionos\\\", target_os = \\\"watchos\\\", target_os = \\\"tvos\\\"))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(any(target_os = \\\"macos\\\", target_os = \\\"openbsd\\\", target_os = \\\"vita\\\", target_os = \\\"emscripten\\\"))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(target_os = \\\"netbsd\\\")\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(target_os = \\\"solaris\\\")\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(target_os = \\\"vxworks\\\")\"},{\"default_features\":false,\"name\":\"r-efi\",\"req\":\"^5.1\",\"target\":\"cfg(all(target_os = \\\"uefi\\\", getrandom_backend = \\\"efi_rng\\\"))\"},{\"default_features\":false,\"name\":\"wasip2\",\"req\":\"^1\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", target_os = \\\"wasi\\\", target_env = \\\"p2\\\"))\"},{\"default_features\":false,\"name\":\"wasm-bindgen\",\"optional\":true,\"req\":\"^0.2.98\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", any(target_os = \\\"unknown\\\", target_os = \\\"none\\\")))\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", any(target_os = \\\"unknown\\\", target_os = \\\"none\\\")))\"}],\"features\":{\"std\":[],\"wasm_js\":[\"dep:wasm-bindgen\",\"dep:js-sys\"]}}", + "getrandom_0.4.2": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"js-sys\",\"optional\":true,\"req\":\"^0.3.77\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", any(target_os = \\\"unknown\\\", target_os = \\\"none\\\"), target_feature = \\\"atomics\\\"))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(all(any(target_os = \\\"linux\\\", target_os = \\\"android\\\"), not(any(all(target_os = \\\"linux\\\", target_env = \\\"\\\"), getrandom_backend = \\\"custom\\\", getrandom_backend = \\\"linux_raw\\\", getrandom_backend = \\\"rdrand\\\", getrandom_backend = \\\"rndr\\\"))))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(any(target_os = \\\"dragonfly\\\", target_os = \\\"freebsd\\\", target_os = \\\"hurd\\\", target_os = \\\"illumos\\\", target_os = \\\"cygwin\\\", all(target_os = \\\"horizon\\\", target_arch = \\\"arm\\\")))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(any(target_os = \\\"haiku\\\", target_os = \\\"redox\\\", target_os = \\\"nto\\\", target_os = \\\"aix\\\"))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(any(target_os = \\\"ios\\\", target_os = \\\"visionos\\\", target_os = \\\"watchos\\\", target_os = \\\"tvos\\\"))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(any(target_os = \\\"macos\\\", target_os = \\\"openbsd\\\", target_os = \\\"vita\\\", target_os = \\\"emscripten\\\"))\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(target_os = \\\"netbsd\\\")\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(target_os = \\\"solaris\\\")\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.154\",\"target\":\"cfg(target_os = \\\"vxworks\\\")\"},{\"default_features\":false,\"name\":\"r-efi\",\"req\":\"^6\",\"target\":\"cfg(all(target_os = \\\"uefi\\\", getrandom_backend = \\\"efi_rng\\\"))\"},{\"name\":\"rand_core\",\"optional\":true,\"req\":\"^0.10.0\"},{\"default_features\":false,\"name\":\"wasip2\",\"req\":\"^1\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", target_os = \\\"wasi\\\", target_env = \\\"p2\\\"))\"},{\"name\":\"wasip3\",\"req\":\"^0.4\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", target_os = \\\"wasi\\\", target_env = \\\"p3\\\"))\"},{\"default_features\":false,\"name\":\"wasm-bindgen\",\"optional\":true,\"req\":\"^0.2.98\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", any(target_os = \\\"unknown\\\", target_os = \\\"none\\\")))\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3\",\"target\":\"cfg(all(target_arch = \\\"wasm32\\\", any(target_os = \\\"unknown\\\", target_os = \\\"none\\\")))\"}],\"features\":{\"std\":[],\"sys_rng\":[\"dep:rand_core\"],\"wasm_js\":[\"dep:wasm-bindgen\",\"dep:js-sys\"]}}", "gif_0.14.1": "{\"dependencies\":[{\"name\":\"color_quant\",\"optional\":true,\"req\":\"^1.1\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.7.0\"},{\"kind\":\"dev\",\"name\":\"glob\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"png\",\"req\":\"^0.18.0\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1.10.0\"},{\"name\":\"weezl\",\"req\":\"^0.1.10\"}],\"features\":{\"color_quant\":[\"dep:color_quant\"],\"default\":[\"raii_no_panic\",\"std\",\"color_quant\"],\"raii_no_panic\":[],\"std\":[]}}", "gimli_0.32.3": "{\"dependencies\":[{\"name\":\"alloc\",\"optional\":true,\"package\":\"rustc-std-workspace-alloc\",\"req\":\"^1.0.0\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"default_features\":false,\"name\":\"fallible-iterator\",\"optional\":true,\"req\":\"^0.3.0\"},{\"name\":\"indexmap\",\"optional\":true,\"req\":\"^2.0.0\"},{\"default_features\":false,\"name\":\"stable_deref_trait\",\"optional\":true,\"req\":\"^1.1.0\"},{\"kind\":\"dev\",\"name\":\"test-assembler\",\"req\":\"^0.1.3\"}],\"features\":{\"default\":[\"read-all\",\"write\"],\"endian-reader\":[\"read\",\"dep:stable_deref_trait\"],\"fallible-iterator\":[\"dep:fallible-iterator\"],\"read\":[\"read-core\"],\"read-all\":[\"read\",\"std\",\"fallible-iterator\",\"endian-reader\"],\"read-core\":[],\"rustc-dep-of-std\":[\"dep:core\",\"dep:alloc\"],\"std\":[\"fallible-iterator?/std\",\"stable_deref_trait?/std\"],\"write\":[\"dep:indexmap\"]}}", "git+https://github.com/dzbarsky/rules_rust?rev=b56cbaa8465e74127f1ea216f813cd377295ad81#b56cbaa8465e74127f1ea216f813cd377295ad81_runfiles": "{\"dependencies\":[],\"features\":{},\"strip_prefix\":\"\"}", @@ -874,6 +889,8 @@ "git+https://github.com/nornagon/ratatui?branch=nornagon-v0.29.0-patch#9b2ad1298408c45918ee9f8241a6f95498cdbed2_ratatui": "{\"dependencies\":[{\"name\":\"bitflags\"},{\"name\":\"cassowary\"},{\"name\":\"compact_str\"},{\"default_features\":true,\"features\":[],\"name\":\"crossterm\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"document-features\",\"optional\":true},{\"name\":\"indoc\"},{\"name\":\"instability\"},{\"name\":\"itertools\"},{\"name\":\"lru\"},{\"default_features\":true,\"features\":[],\"name\":\"palette\",\"optional\":true},{\"name\":\"paste\"},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"strum\",\"optional\":false},{\"default_features\":true,\"features\":[],\"name\":\"termwiz\",\"optional\":true},{\"default_features\":true,\"features\":[\"local-offset\"],\"name\":\"time\",\"optional\":true},{\"name\":\"unicode-segmentation\"},{\"name\":\"unicode-truncate\"},{\"name\":\"unicode-width\"},{\"default_features\":true,\"features\":[],\"name\":\"termion\",\"optional\":true,\"target\":\"cfg(not(windows))\"}],\"features\":{\"all-widgets\":[\"widget-calendar\"],\"crossterm\":[\"dep:crossterm\"],\"default\":[\"crossterm\",\"underline-color\"],\"macros\":[],\"palette\":[\"dep:palette\"],\"scrolling-regions\":[],\"serde\":[\"dep:serde\",\"bitflags/serde\",\"compact_str/serde\"],\"termion\":[\"dep:termion\"],\"termwiz\":[\"dep:termwiz\"],\"underline-color\":[\"dep:crossterm\"],\"unstable\":[\"unstable-rendered-line-info\",\"unstable-widget-ref\",\"unstable-backend-writer\"],\"unstable-backend-writer\":[],\"unstable-rendered-line-info\":[],\"unstable-widget-ref\":[],\"widget-calendar\":[\"dep:time\"]},\"strip_prefix\":\"\"}", "git+https://github.com/openai-oss-forks/tokio-tungstenite?rev=132f5b39c862e3a970f731d709608b3e6276d5f6#132f5b39c862e3a970f731d709608b3e6276d5f6_tokio-tungstenite": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"sink\",\"std\"],\"name\":\"futures-util\",\"optional\":false},{\"name\":\"log\"},{\"default_features\":true,\"features\":[],\"name\":\"native-tls-crate\",\"optional\":true,\"package\":\"native-tls\"},{\"default_features\":false,\"features\":[],\"name\":\"rustls\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-native-certs\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-pki-types\",\"optional\":true},{\"default_features\":false,\"features\":[\"io-util\"],\"name\":\"tokio\",\"optional\":false},{\"default_features\":true,\"features\":[],\"name\":\"tokio-native-tls\",\"optional\":true},{\"default_features\":false,\"features\":[],\"name\":\"tokio-rustls\",\"optional\":true},{\"default_features\":false,\"features\":[],\"name\":\"tungstenite\",\"optional\":false},{\"default_features\":true,\"features\":[],\"name\":\"webpki-roots\",\"optional\":true}],\"features\":{\"__rustls-tls\":[\"rustls\",\"rustls-pki-types\",\"tokio-rustls\",\"stream\",\"tungstenite/__rustls-tls\",\"handshake\"],\"connect\":[\"stream\",\"tokio/net\",\"handshake\"],\"default\":[\"connect\",\"handshake\"],\"handshake\":[\"tungstenite/handshake\"],\"native-tls\":[\"native-tls-crate\",\"tokio-native-tls\",\"stream\",\"tungstenite/native-tls\",\"handshake\"],\"native-tls-vendored\":[\"native-tls\",\"native-tls-crate/vendored\",\"tungstenite/native-tls-vendored\"],\"proxy\":[\"tungstenite/proxy\",\"tokio/net\",\"handshake\"],\"rustls-tls-native-roots\":[\"__rustls-tls\",\"rustls-native-certs\"],\"rustls-tls-webpki-roots\":[\"__rustls-tls\",\"webpki-roots\"],\"stream\":[],\"url\":[\"tungstenite/url\"]},\"strip_prefix\":\"\"}", "git+https://github.com/openai-oss-forks/tungstenite-rs?rev=9200079d3b54a1ff51072e24d81fd354f085156f#9200079d3b54a1ff51072e24d81fd354f085156f_tungstenite": "{\"dependencies\":[{\"name\":\"bytes\"},{\"default_features\":true,\"features\":[],\"name\":\"data-encoding\",\"optional\":true},{\"default_features\":false,\"features\":[\"zlib\"],\"name\":\"flate2\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"headers\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"http\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"httparse\",\"optional\":true},{\"name\":\"log\"},{\"default_features\":true,\"features\":[],\"name\":\"native-tls-crate\",\"optional\":true,\"package\":\"native-tls\"},{\"name\":\"rand\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"rustls\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-native-certs\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"rustls-pki-types\",\"optional\":true},{\"default_features\":true,\"features\":[],\"name\":\"sha1\",\"optional\":true},{\"name\":\"thiserror\"},{\"default_features\":true,\"features\":[],\"name\":\"url\",\"optional\":true},{\"name\":\"utf-8\"},{\"default_features\":true,\"features\":[],\"name\":\"webpki-roots\",\"optional\":true}],\"features\":{\"__rustls-tls\":[\"rustls\",\"rustls-pki-types\"],\"default\":[\"handshake\"],\"deflate\":[\"headers\",\"flate2\"],\"handshake\":[\"data-encoding\",\"headers\",\"httparse\",\"sha1\"],\"headers\":[\"http\",\"dep:headers\"],\"native-tls\":[\"native-tls-crate\"],\"native-tls-vendored\":[\"native-tls\",\"native-tls-crate/vendored\"],\"proxy\":[\"handshake\"],\"rustls-tls-native-roots\":[\"__rustls-tls\",\"rustls-native-certs\"],\"rustls-tls-webpki-roots\":[\"__rustls-tls\",\"webpki-roots\"],\"url\":[\"dep:url\"]},\"strip_prefix\":\"\"}", + "git+https://github.com/rust-lang/rust-clippy?rev=20ce69b9a63bcd2756cd906fe0964d1e901e042a#20ce69b9a63bcd2756cd906fe0964d1e901e042a_clippy_utils": "{\"dependencies\":[{\"default_features\":false,\"features\":[],\"name\":\"arrayvec\",\"optional\":false},{\"name\":\"itertools\"},{\"name\":\"rustc_apfloat\"},{\"default_features\":true,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":false}],\"features\":{},\"strip_prefix\":\"clippy_utils\"}", + "git2_0.20.4": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2.1.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^4.4.13\"},{\"name\":\"libc\",\"req\":\"^0.2\"},{\"name\":\"libgit2-sys\",\"req\":\"^0.18.3\"},{\"name\":\"log\",\"req\":\"^0.4.8\"},{\"name\":\"openssl-probe\",\"optional\":true,\"req\":\"^0.1\",\"target\":\"cfg(all(unix, not(target_os = \\\"macos\\\")))\"},{\"name\":\"openssl-sys\",\"optional\":true,\"req\":\"^0.9.45\",\"target\":\"cfg(all(unix, not(target_os = \\\"macos\\\")))\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.1.0\"},{\"features\":[\"formatting\"],\"kind\":\"dev\",\"name\":\"time\",\"req\":\"^0.3.37\"},{\"name\":\"url\",\"req\":\"^2.5.4\"}],\"features\":{\"default\":[\"ssh\",\"https\"],\"https\":[\"libgit2-sys/https\",\"openssl-sys\",\"openssl-probe\"],\"ssh\":[\"libgit2-sys/ssh\"],\"unstable\":[],\"vendored-libgit2\":[\"libgit2-sys/vendored\"],\"vendored-openssl\":[\"openssl-sys/vendored\",\"libgit2-sys/vendored-openssl\"],\"zlib-ng-compat\":[\"libgit2-sys/zlib-ng-compat\"]}}", "glob_0.3.3": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"tempdir\",\"req\":\"^0.3\"}],\"features\":{}}", "globset_0.4.18": "{\"dependencies\":[{\"name\":\"aho-corasick\",\"req\":\"^1.1.1\"},{\"features\":[\"derive\"],\"name\":\"arbitrary\",\"optional\":true,\"req\":\"^1.3.2\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"bstr\",\"req\":\"^1.6.2\"},{\"kind\":\"dev\",\"name\":\"glob\",\"req\":\"^0.3.1\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.20\"},{\"default_features\":false,\"features\":[\"std\",\"perf\",\"syntax\",\"meta\",\"nfa\",\"hybrid\"],\"name\":\"regex-automata\",\"req\":\"^0.4.0\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"regex-syntax\",\"req\":\"^0.8.0\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.188\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.107\"}],\"features\":{\"arbitrary\":[\"dep:arbitrary\"],\"default\":[\"log\"],\"serde1\":[\"serde\"],\"simd-accel\":[]}}", "gzip-header_1.0.0": "{\"dependencies\":[{\"name\":\"crc32fast\",\"req\":\"^1.2.1\"}],\"features\":{}}", @@ -894,6 +911,7 @@ "hkdf_0.12.4": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"blobby\",\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.2.2\"},{\"name\":\"hmac\",\"req\":\"^0.12.1\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"sha1\",\"req\":\"^0.10\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"sha2\",\"req\":\"^0.10\"}],\"features\":{\"std\":[\"hmac/std\"]}}", "hmac_0.12.1": "{\"dependencies\":[{\"features\":[\"mac\"],\"name\":\"digest\",\"req\":\"^0.10.3\"},{\"features\":[\"dev\"],\"kind\":\"dev\",\"name\":\"digest\",\"req\":\"^0.10\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.2.2\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"md-5\",\"req\":\"^0.10\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"sha-1\",\"req\":\"^0.10\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"sha2\",\"req\":\"^0.10\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"streebog\",\"req\":\"^0.10\"}],\"features\":{\"reset\":[],\"std\":[\"digest/std\"]}}", "home_0.5.12": "{\"dependencies\":[{\"features\":[\"Win32_Foundation\",\"Win32_UI_Shell\",\"Win32_System_Com\"],\"name\":\"windows-sys\",\"req\":\"^0.61\",\"target\":\"cfg(windows)\"}],\"features\":{}}", + "home_0.5.9": "{\"dependencies\":[{\"features\":[\"Win32_Foundation\",\"Win32_UI_Shell\",\"Win32_System_Com\"],\"name\":\"windows-sys\",\"req\":\"^0.52\",\"target\":\"cfg(windows)\"}],\"features\":{}}", "hostname_0.4.2": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(any(unix, target_os = \\\"redox\\\"))\"},{\"kind\":\"dev\",\"name\":\"similar-asserts\",\"req\":\"^1.6.1\"},{\"kind\":\"dev\",\"name\":\"version-sync\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"windows-bindgen\",\"req\":\"^0.65\"},{\"name\":\"windows-link\",\"req\":\"^0.2\",\"target\":\"cfg(target_os = \\\"windows\\\")\"}],\"features\":{\"default\":[],\"set\":[]}}", "hound_3.5.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"cpal\",\"req\":\"^0.2.12\"}],\"features\":{}}", "http-body-util_0.1.3": "{\"dependencies\":[{\"name\":\"bytes\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"futures-core\",\"req\":\"^0.3\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"futures-util\",\"req\":\"^0.3\"},{\"name\":\"http\",\"req\":\"^1\"},{\"name\":\"http-body\",\"req\":\"^1\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2\"},{\"features\":[\"sync\"],\"name\":\"tokio\",\"optional\":true,\"req\":\"^1\"},{\"features\":[\"macros\",\"rt\",\"sync\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"}],\"features\":{\"channel\":[\"dep:tokio\"],\"default\":[],\"full\":[\"channel\"]}}", @@ -927,9 +945,11 @@ "icu_properties_2.1.2": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"databake\",\"optional\":true,\"req\":\"^0.2.0\"},{\"default_features\":false,\"name\":\"icu_collections\",\"req\":\"~2.1.1\"},{\"default_features\":false,\"features\":[\"zerovec\"],\"name\":\"icu_locale_core\",\"req\":\"^2.1.1\"},{\"default_features\":false,\"name\":\"icu_properties_data\",\"optional\":true,\"req\":\"~2.1.2\"},{\"default_features\":false,\"name\":\"icu_provider\",\"req\":\"^2.1.1\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.220\"},{\"default_features\":false,\"name\":\"unicode-bidi\",\"optional\":true,\"req\":\"^0.3.11\"},{\"default_features\":false,\"features\":[\"yoke\",\"zerofrom\"],\"name\":\"zerotrie\",\"req\":\"^0.2.0\"},{\"default_features\":false,\"features\":[\"derive\",\"yoke\"],\"name\":\"zerovec\",\"req\":\"^0.11.3\"}],\"features\":{\"alloc\":[\"zerovec/alloc\",\"icu_collections/alloc\",\"serde?/alloc\"],\"compiled_data\":[\"dep:icu_properties_data\",\"icu_provider/baked\"],\"datagen\":[\"serde\",\"dep:databake\",\"zerovec/databake\",\"icu_collections/databake\",\"icu_locale_core/databake\",\"zerotrie/databake\",\"icu_provider/export\"],\"default\":[\"compiled_data\"],\"serde\":[\"dep:serde\",\"icu_locale_core/serde\",\"zerovec/serde\",\"icu_collections/serde\",\"icu_provider/serde\",\"zerotrie/serde\"],\"unicode_bidi\":[\"dep:unicode-bidi\"]}}", "icu_properties_data_2.1.2": "{\"dependencies\":[],\"features\":{}}", "icu_provider_2.1.1": "{\"dependencies\":[{\"name\":\"bincode\",\"optional\":true,\"req\":\"^1.3.1\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"databake\",\"optional\":true,\"req\":\"^0.2.0\"},{\"default_features\":false,\"name\":\"displaydoc\",\"req\":\"^0.2.3\"},{\"name\":\"erased-serde\",\"optional\":true,\"req\":\"^0.4.0\"},{\"default_features\":false,\"name\":\"icu_locale_core\",\"req\":\"^2.1.1\"},{\"default_features\":false,\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.17\"},{\"default_features\":false,\"name\":\"postcard\",\"optional\":true,\"req\":\"^1.0.3\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.220\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0.45\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.45\"},{\"default_features\":false,\"name\":\"stable_deref_trait\",\"optional\":true,\"req\":\"^1.2.0\"},{\"default_features\":false,\"name\":\"writeable\",\"optional\":true,\"req\":\"^0.6.0\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"yoke\",\"req\":\"^0.8.0\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"zerofrom\",\"req\":\"^0.1.3\"},{\"default_features\":false,\"name\":\"zerotrie\",\"optional\":true,\"req\":\"^0.2.0\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"zerovec\",\"req\":\"^0.11.3\"}],\"features\":{\"alloc\":[\"icu_locale_core/alloc\",\"serde?/alloc\",\"yoke/alloc\",\"zerofrom/alloc\",\"zerovec/alloc\",\"zerotrie?/alloc\",\"dep:stable_deref_trait\",\"dep:writeable\"],\"baked\":[\"dep:zerotrie\",\"dep:writeable\"],\"deserialize_bincode_1\":[\"serde\",\"dep:bincode\",\"std\"],\"deserialize_json\":[\"serde\",\"dep:serde_json\"],\"deserialize_postcard_1\":[\"serde\",\"dep:postcard\"],\"export\":[\"serde\",\"dep:erased-serde\",\"dep:databake\",\"std\",\"sync\",\"dep:postcard\",\"zerovec/databake\"],\"logging\":[\"dep:log\"],\"serde\":[\"dep:serde\",\"yoke/serde\"],\"std\":[\"alloc\"],\"sync\":[],\"zerotrie\":[]}}", + "id-arena_2.3.0": "{\"dependencies\":[{\"name\":\"rayon\",\"optional\":true,\"req\":\"^1.0.3\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "ident_case_1.0.1": "{\"dependencies\":[],\"features\":{}}", "idna_1.1.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"assert_matches\",\"req\":\"^1.3\"},{\"kind\":\"dev\",\"name\":\"bencher\",\"req\":\"^0.1\"},{\"name\":\"idna_adapter\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"features\":[\"const_generics\"],\"name\":\"smallvec\",\"req\":\"^1.13.1\"},{\"kind\":\"dev\",\"name\":\"tester\",\"req\":\"^0.9\"},{\"name\":\"utf8_iter\",\"req\":\"^1.0.4\"}],\"features\":{\"alloc\":[],\"compiled_data\":[\"idna_adapter/compiled_data\"],\"default\":[\"std\",\"compiled_data\"],\"std\":[\"alloc\"]}}", "idna_adapter_1.2.1": "{\"dependencies\":[{\"default_features\":false,\"name\":\"icu_normalizer\",\"req\":\"^2\"},{\"default_features\":false,\"name\":\"icu_properties\",\"req\":\"^2\"}],\"features\":{\"compiled_data\":[\"icu_normalizer/compiled_data\",\"icu_properties/compiled_data\"]}}", + "if_chain_1.0.3": "{\"dependencies\":[],\"features\":{}}", "ignore_0.4.25": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"bstr\",\"req\":\"^1.6.2\"},{\"kind\":\"dev\",\"name\":\"crossbeam-channel\",\"req\":\"^0.5.15\"},{\"name\":\"crossbeam-deque\",\"req\":\"^0.8.3\"},{\"name\":\"globset\",\"req\":\"^0.4.18\"},{\"name\":\"log\",\"req\":\"^0.4.20\"},{\"name\":\"memchr\",\"req\":\"^2.6.3\"},{\"default_features\":false,\"features\":[\"std\",\"perf\",\"syntax\",\"meta\",\"nfa\",\"hybrid\",\"dfa-onepass\"],\"name\":\"regex-automata\",\"req\":\"^0.4.0\"},{\"name\":\"same-file\",\"req\":\"^1.0.6\"},{\"name\":\"walkdir\",\"req\":\"^2.4.0\"},{\"name\":\"winapi-util\",\"req\":\"^0.1.2\",\"target\":\"cfg(windows)\"}],\"features\":{\"simd-accel\":[]}}", "image-webp_0.2.4": "{\"dependencies\":[{\"name\":\"byteorder-lite\",\"req\":\"^0.1.0\"},{\"kind\":\"dev\",\"name\":\"paste\",\"req\":\"^1.0.14\"},{\"kind\":\"dev\",\"name\":\"png\",\"req\":\"^0.17.12\"},{\"name\":\"quick-error\",\"req\":\"^2.0.1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.5\"},{\"kind\":\"dev\",\"name\":\"webp\",\"req\":\"^0.3.0\"}],\"features\":{\"_benchmarks\":[]}}", "image_0.25.9": "{\"dependencies\":[{\"features\":[\"extern_crate_alloc\"],\"name\":\"bytemuck\",\"req\":\"^1.8.0\"},{\"name\":\"byteorder-lite\",\"req\":\"^0.1.0\"},{\"name\":\"color_quant\",\"optional\":true,\"req\":\"^1.1\"},{\"kind\":\"dev\",\"name\":\"crc32fast\",\"req\":\"^1.2.0\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5.0\"},{\"name\":\"dav1d\",\"optional\":true,\"req\":\"^0.10.3\"},{\"default_features\":false,\"name\":\"exr\",\"optional\":true,\"req\":\"^1.74.0\"},{\"name\":\"gif\",\"optional\":true,\"req\":\"^0.14.0\"},{\"kind\":\"dev\",\"name\":\"glob\",\"req\":\"^0.3\"},{\"name\":\"image-webp\",\"optional\":true,\"req\":\"^0.2.0\"},{\"name\":\"moxcms\",\"req\":\"^0.7.4\"},{\"name\":\"mp4parse\",\"optional\":true,\"req\":\"^0.17.0\"},{\"kind\":\"dev\",\"name\":\"num-complex\",\"req\":\"^0.4\"},{\"name\":\"num-traits\",\"req\":\"^0.2.0\"},{\"name\":\"png\",\"optional\":true,\"req\":\"^0.18.0\"},{\"name\":\"qoi\",\"optional\":true,\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"ravif\",\"optional\":true,\"req\":\"^0.12\"},{\"name\":\"rayon\",\"optional\":true,\"req\":\"^1.7.0\"},{\"default_features\":false,\"name\":\"rgb\",\"optional\":true,\"req\":\"^0.8.48\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.214\"},{\"name\":\"tiff\",\"optional\":true,\"req\":\"^0.10.3\"},{\"default_features\":false,\"name\":\"zune-core\",\"optional\":true,\"req\":\"^0.5.0\"},{\"name\":\"zune-jpeg\",\"optional\":true,\"req\":\"^0.5.5\"}],\"features\":{\"avif\":[\"dep:ravif\",\"dep:rgb\"],\"avif-native\":[\"dep:mp4parse\",\"dep:dav1d\"],\"benchmarks\":[],\"bmp\":[],\"color_quant\":[\"dep:color_quant\"],\"dds\":[],\"default\":[\"rayon\",\"default-formats\"],\"default-formats\":[\"avif\",\"bmp\",\"dds\",\"exr\",\"ff\",\"gif\",\"hdr\",\"ico\",\"jpeg\",\"png\",\"pnm\",\"qoi\",\"tga\",\"tiff\",\"webp\"],\"exr\":[\"dep:exr\"],\"ff\":[],\"gif\":[\"dep:gif\",\"dep:color_quant\"],\"hdr\":[],\"ico\":[\"bmp\",\"png\"],\"jpeg\":[\"dep:zune-core\",\"dep:zune-jpeg\"],\"nasm\":[\"ravif?/asm\"],\"png\":[\"dep:png\"],\"pnm\":[],\"qoi\":[\"dep:qoi\"],\"rayon\":[\"dep:rayon\",\"ravif?/threading\",\"exr?/rayon\"],\"serde\":[\"dep:serde\"],\"tga\":[],\"tiff\":[\"dep:tiff\"],\"webp\":[\"dep:image-webp\"]}}", @@ -956,12 +976,15 @@ "is_ci_1.2.0": "{\"dependencies\":[],\"features\":{}}", "is_terminal_polyfill_1.70.2": "{\"dependencies\":[],\"features\":{\"default\":[]}}", "itertools_0.10.5": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"= 0\"},{\"default_features\":false,\"name\":\"either\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"paste\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"permutohedron\",\"req\":\"^0.2\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.7\"}],\"features\":{\"default\":[\"use_std\"],\"use_alloc\":[],\"use_std\":[\"use_alloc\",\"either/use_std\"]}}", + "itertools_0.12.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4.0\"},{\"default_features\":false,\"name\":\"either\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"paste\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"permutohedron\",\"req\":\"^0.2\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.7\"}],\"features\":{\"default\":[\"use_std\"],\"use_alloc\":[],\"use_std\":[\"use_alloc\",\"either/use_std\"]}}", "itertools_0.13.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4.0\"},{\"default_features\":false,\"name\":\"either\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"paste\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"permutohedron\",\"req\":\"^0.2\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.7\"}],\"features\":{\"default\":[\"use_std\"],\"use_alloc\":[],\"use_std\":[\"use_alloc\",\"either/use_std\"]}}", "itertools_0.14.0": "{\"dependencies\":[{\"features\":[\"html_reports\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4.0\"},{\"default_features\":false,\"name\":\"either\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"paste\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"permutohedron\",\"req\":\"^0.2\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.7\"}],\"features\":{\"default\":[\"use_std\"],\"use_alloc\":[],\"use_std\":[\"use_alloc\",\"either/use_std\"]}}", "itoa_1.0.17": "{\"dependencies\":[{\"default_features\":false,\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.8\",\"target\":\"cfg(not(miri))\"},{\"name\":\"no-panic\",\"optional\":true,\"req\":\"^0.1\"}],\"features\":{}}", "ixdtf_0.6.4": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"serde-json-core\",\"req\":\"^0.6.0\"}],\"features\":{\"default\":[\"duration\"],\"duration\":[]}}", "jiff-static_0.2.18": "{\"dependencies\":[{\"name\":\"jiff-tzdb\",\"optional\":true,\"req\":\"^0.1.4\"},{\"name\":\"proc-macro2\",\"req\":\"^1.0.93\"},{\"name\":\"quote\",\"req\":\"^1.0.38\"},{\"name\":\"syn\",\"req\":\"^2.0.98\"}],\"features\":{\"default\":[],\"perf-inline\":[],\"tz-fat\":[],\"tzdb\":[\"dep:jiff-tzdb\"]}}", + "jiff-static_0.2.23": "{\"dependencies\":[{\"name\":\"jiff-tzdb\",\"optional\":true,\"req\":\"^0.1.6\"},{\"name\":\"proc-macro2\",\"req\":\"^1.0.93\"},{\"name\":\"quote\",\"req\":\"^1.0.38\"},{\"name\":\"syn\",\"req\":\"^2.0.98\"}],\"features\":{\"default\":[],\"perf-inline\":[],\"tz-fat\":[],\"tzdb\":[\"dep:jiff-tzdb\"]}}", "jiff_0.2.18": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.81\"},{\"features\":[\"serde\"],\"kind\":\"dev\",\"name\":\"chrono\",\"req\":\"^0.4.38\"},{\"kind\":\"dev\",\"name\":\"chrono-tz\",\"req\":\"^0.10.0\"},{\"kind\":\"dev\",\"name\":\"hifitime\",\"req\":\"^3.9.0\",\"target\":\"cfg(not(target_family = \\\"wasm\\\"))\"},{\"kind\":\"dev\",\"name\":\"humantime\",\"req\":\"^2.1.0\"},{\"kind\":\"dev\",\"name\":\"insta\",\"req\":\"^1.39.0\"},{\"name\":\"jiff-static\",\"req\":\"=0.2.18\",\"target\":\"cfg(any())\"},{\"name\":\"jiff-static\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"jiff-tzdb\",\"optional\":true,\"req\":\"^0.1.5\"},{\"name\":\"jiff-tzdb-platform\",\"optional\":true,\"req\":\"^0.1.3\",\"target\":\"cfg(any(windows, target_family = \\\"wasm\\\"))\"},{\"name\":\"js-sys\",\"optional\":true,\"req\":\"^0.3.50\",\"target\":\"cfg(all(any(target_arch = \\\"wasm32\\\", target_arch = \\\"wasm64\\\"), target_os = \\\"unknown\\\"))\"},{\"default_features\":false,\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.21\"},{\"kind\":\"dev\",\"name\":\"log\",\"req\":\"^0.4.21\"},{\"default_features\":false,\"name\":\"portable-atomic\",\"req\":\"^1.10.0\",\"target\":\"cfg(not(target_has_atomic = \\\"ptr\\\"))\"},{\"default_features\":false,\"name\":\"portable-atomic-util\",\"req\":\"^0.2.4\",\"target\":\"cfg(not(target_has_atomic = \\\"ptr\\\"))\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.3\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.203\"},{\"default_features\":false,\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.221\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.117\"},{\"kind\":\"dev\",\"name\":\"serde_yaml\",\"req\":\"^0.9.34\"},{\"kind\":\"dev\",\"name\":\"tabwriter\",\"req\":\"^1.4.0\"},{\"features\":[\"local-offset\",\"macros\",\"parsing\"],\"kind\":\"dev\",\"name\":\"time\",\"req\":\"^0.3.36\"},{\"kind\":\"dev\",\"name\":\"tzfile\",\"req\":\"^0.1.3\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.5.0\"},{\"name\":\"wasm-bindgen\",\"optional\":true,\"req\":\"^0.2.70\",\"target\":\"cfg(all(any(target_arch = \\\"wasm32\\\", target_arch = \\\"wasm64\\\"), target_os = \\\"unknown\\\"))\"},{\"default_features\":false,\"features\":[\"Win32_Foundation\",\"Win32_System_Time\"],\"name\":\"windows-sys\",\"optional\":true,\"req\":\">=0.52.0, <=0.61\",\"target\":\"cfg(windows)\"}],\"features\":{\"alloc\":[\"serde_core?/alloc\",\"portable-atomic-util/alloc\"],\"default\":[\"std\",\"tz-system\",\"tz-fat\",\"tzdb-bundle-platform\",\"tzdb-zoneinfo\",\"tzdb-concatenated\",\"perf-inline\"],\"js\":[\"dep:wasm-bindgen\",\"dep:js-sys\"],\"logging\":[\"dep:log\"],\"perf-inline\":[],\"serde\":[\"dep:serde_core\"],\"static\":[\"static-tz\",\"jiff-static?/tzdb\"],\"static-tz\":[\"dep:jiff-static\"],\"std\":[\"alloc\",\"log?/std\",\"serde_core?/std\"],\"tz-fat\":[\"jiff-static?/tz-fat\"],\"tz-system\":[\"std\",\"dep:windows-sys\"],\"tzdb-bundle-always\":[\"dep:jiff-tzdb\",\"alloc\"],\"tzdb-bundle-platform\":[\"dep:jiff-tzdb-platform\",\"alloc\"],\"tzdb-concatenated\":[\"std\"],\"tzdb-zoneinfo\":[\"std\"]}}", + "jiff_0.2.23": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.81\"},{\"features\":[\"serde\"],\"kind\":\"dev\",\"name\":\"chrono\",\"req\":\"^0.4.38\"},{\"kind\":\"dev\",\"name\":\"chrono-tz\",\"req\":\"^0.10.0\"},{\"kind\":\"dev\",\"name\":\"hifitime\",\"req\":\"^3.9.0\",\"target\":\"cfg(not(target_family = \\\"wasm\\\"))\"},{\"kind\":\"dev\",\"name\":\"humantime\",\"req\":\"^2.1.0\"},{\"kind\":\"dev\",\"name\":\"insta\",\"req\":\"^1.39.0\"},{\"name\":\"jiff-static\",\"req\":\"=0.2.23\",\"target\":\"cfg(any())\"},{\"name\":\"jiff-static\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"jiff-tzdb\",\"optional\":true,\"req\":\"^0.1.6\"},{\"name\":\"jiff-tzdb-platform\",\"optional\":true,\"req\":\"^0.1.3\",\"target\":\"cfg(any(windows, target_family = \\\"wasm\\\"))\"},{\"name\":\"js-sys\",\"optional\":true,\"req\":\"^0.3.50\",\"target\":\"cfg(all(any(target_arch = \\\"wasm32\\\", target_arch = \\\"wasm64\\\"), target_os = \\\"unknown\\\"))\"},{\"default_features\":false,\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.21\"},{\"kind\":\"dev\",\"name\":\"log\",\"req\":\"^0.4.21\"},{\"default_features\":false,\"name\":\"portable-atomic\",\"req\":\"^1.10.0\",\"target\":\"cfg(not(target_has_atomic = \\\"ptr\\\"))\"},{\"default_features\":false,\"name\":\"portable-atomic-util\",\"req\":\"^0.2.4\",\"target\":\"cfg(not(target_has_atomic = \\\"ptr\\\"))\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.3\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.203\"},{\"default_features\":false,\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.221\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.117\"},{\"kind\":\"dev\",\"name\":\"serde_yaml\",\"req\":\"^0.9.34\"},{\"kind\":\"dev\",\"name\":\"tabwriter\",\"req\":\"^1.4.0\"},{\"features\":[\"local-offset\",\"macros\",\"parsing\"],\"kind\":\"dev\",\"name\":\"time\",\"req\":\"^0.3.36\"},{\"kind\":\"dev\",\"name\":\"time-tz\",\"req\":\"^2.0.0\"},{\"kind\":\"dev\",\"name\":\"tzfile\",\"req\":\"^0.1.3\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.5.0\"},{\"name\":\"wasm-bindgen\",\"optional\":true,\"req\":\"^0.2.70\",\"target\":\"cfg(all(any(target_arch = \\\"wasm32\\\", target_arch = \\\"wasm64\\\"), target_os = \\\"unknown\\\"))\"},{\"default_features\":false,\"features\":[\"Win32_Foundation\",\"Win32_System_Time\"],\"name\":\"windows-sys\",\"optional\":true,\"req\":\">=0.52.0, <=0.61\",\"target\":\"cfg(windows)\"}],\"features\":{\"alloc\":[\"serde_core?/alloc\",\"portable-atomic-util/alloc\"],\"default\":[\"std\",\"tz-system\",\"tz-fat\",\"tzdb-bundle-platform\",\"tzdb-zoneinfo\",\"tzdb-concatenated\",\"perf-inline\"],\"js\":[\"dep:wasm-bindgen\",\"dep:js-sys\"],\"logging\":[\"dep:log\"],\"perf-inline\":[],\"serde\":[\"dep:serde_core\"],\"static\":[\"static-tz\",\"jiff-static?/tzdb\"],\"static-tz\":[\"dep:jiff-static\"],\"std\":[\"alloc\",\"log?/std\",\"serde_core?/std\"],\"tz-fat\":[\"jiff-static?/tz-fat\"],\"tz-system\":[\"std\",\"dep:windows-sys\"],\"tzdb-bundle-always\":[\"dep:jiff-tzdb\",\"alloc\"],\"tzdb-bundle-platform\":[\"dep:jiff-tzdb-platform\",\"alloc\"],\"tzdb-concatenated\":[\"std\"],\"tzdb-zoneinfo\":[\"std\"]}}", "jni-sys_0.3.0": "{\"dependencies\":[],\"features\":{}}", "jni_0.21.1": "{\"dependencies\":[{\"name\":\"cesu8\",\"req\":\"^1.1.0\"},{\"name\":\"cfg-if\",\"req\":\"^1.0.0\"},{\"name\":\"combine\",\"req\":\"^4.1.0\"},{\"name\":\"java-locator\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"jni-sys\",\"req\":\"^0.3.0\"},{\"name\":\"libloading\",\"optional\":true,\"req\":\"^0.7\"},{\"name\":\"log\",\"req\":\"^0.4.4\"},{\"name\":\"thiserror\",\"req\":\"^1.0.20\"},{\"kind\":\"dev\",\"name\":\"assert_matches\",\"req\":\"^1.5.0\"},{\"kind\":\"dev\",\"name\":\"lazy_static\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"rusty-fork\",\"req\":\"^0.3.0\"},{\"kind\":\"build\",\"name\":\"walkdir\",\"req\":\"^2\"},{\"features\":[\"Win32_Globalization\"],\"name\":\"windows-sys\",\"req\":\"^0.45.0\",\"target\":\"cfg(windows)\"},{\"kind\":\"dev\",\"name\":\"bytemuck\",\"req\":\"^1.13.0\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[],\"invocation\":[\"java-locator\",\"libloading\"]}}", "jobserver_0.1.34": "{\"dependencies\":[{\"features\":[\"std\"],\"name\":\"getrandom\",\"req\":\"^0.3.2\",\"target\":\"cfg(windows)\"},{\"name\":\"libc\",\"req\":\"^0.2.171\",\"target\":\"cfg(unix)\"},{\"features\":[\"fs\"],\"kind\":\"dev\",\"name\":\"nix\",\"req\":\"^0.28.0\",\"target\":\"cfg(unix)\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.10.1\"}],\"features\":{}}", @@ -975,16 +998,23 @@ "landlock_0.4.4": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0\"},{\"name\":\"enumflags2\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"lazy_static\",\"req\":\"^1\"},{\"name\":\"libc\",\"req\":\"^0.2.175\"},{\"kind\":\"dev\",\"name\":\"strum\",\"req\":\"^0.26\"},{\"kind\":\"dev\",\"name\":\"strum_macros\",\"req\":\"^0.26\"},{\"name\":\"thiserror\",\"req\":\"^2.0\"}],\"features\":{}}", "language-tags_0.3.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"bencher\",\"req\":\"^0.1\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"}],\"features\":{}}", "lazy_static_1.5.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3.1\"},{\"default_features\":false,\"features\":[\"once\"],\"name\":\"spin\",\"optional\":true,\"req\":\"^0.9.8\"},{\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1\"}],\"features\":{\"spin_no_std\":[\"spin\"]}}", + "leb128fmt_0.1.0": "{\"dependencies\":[],\"features\":{\"alloc\":[],\"default\":[\"std\"],\"std\":[]}}", "libc_0.2.182": "{\"dependencies\":[{\"name\":\"rustc-std-workspace-core\",\"optional\":true,\"req\":\"^1.0.1\"}],\"features\":{\"align\":[],\"const-extern-fn\":[],\"default\":[\"std\"],\"extra_traits\":[],\"rustc-dep-of-std\":[\"align\",\"rustc-std-workspace-core\"],\"std\":[],\"use_std\":[\"std\"]}}", + "libc_0.2.183": "{\"dependencies\":[{\"name\":\"rustc-std-workspace-core\",\"optional\":true,\"req\":\"^1.0.1\"}],\"features\":{\"align\":[],\"const-extern-fn\":[],\"default\":[\"std\"],\"extra_traits\":[],\"rustc-dep-of-std\":[\"align\",\"rustc-std-workspace-core\"],\"std\":[],\"use_std\":[\"std\"]}}", "libdbus-sys_0.2.7": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"cc\",\"optional\":true,\"req\":\"^1.0.78\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"optional\":true,\"req\":\"^0.3\"}],\"features\":{\"default\":[\"pkg-config\"],\"vendored\":[\"cc\"]}}", + "libgit2-sys_0.18.3+1.9.2": "{\"dependencies\":[{\"features\":[\"parallel\"],\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0.43\"},{\"name\":\"libc\",\"req\":\"^0.2\"},{\"name\":\"libssh2-sys\",\"optional\":true,\"req\":\"^0.3.0\"},{\"default_features\":false,\"features\":[\"libc\"],\"name\":\"libz-sys\",\"req\":\"^1.1.0\"},{\"name\":\"openssl-sys\",\"optional\":true,\"req\":\"^0.9.45\",\"target\":\"cfg(unix)\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"req\":\"^0.3.15\"}],\"features\":{\"https\":[\"openssl-sys\"],\"ssh\":[\"libssh2-sys\"],\"vendored\":[],\"vendored-openssl\":[\"openssl-sys/vendored\"],\"zlib-ng-compat\":[\"libz-sys/zlib-ng\",\"libssh2-sys?/zlib-ng-compat\"]}}", "libloading_0.8.9": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1\",\"target\":\"cfg(unix)\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1\"},{\"name\":\"windows-link\",\"req\":\"^0.2\",\"target\":\"cfg(windows)\"},{\"features\":[\"Win32_Foundation\"],\"kind\":\"dev\",\"name\":\"windows-sys\",\"req\":\"^0.61\",\"target\":\"cfg(windows)\"}],\"features\":{}}", "libm_0.2.16": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"no-panic\",\"req\":\"^0.1.35\"}],\"features\":{\"arch\":[],\"default\":[\"arch\"],\"force-soft-floats\":[],\"unstable\":[\"unstable-intrinsics\",\"unstable-float\"],\"unstable-float\":[],\"unstable-intrinsics\":[],\"unstable-public-internals\":[]}}", "libredox_0.1.12": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2\"},{\"name\":\"ioslice\",\"optional\":true,\"req\":\"^0.6\"},{\"name\":\"libc\",\"req\":\"^0.2\"},{\"name\":\"redox_syscall\",\"optional\":true,\"req\":\"^0.7\"}],\"features\":{\"call\":[],\"default\":[\"call\",\"std\",\"redox_syscall\"],\"mkns\":[\"ioslice\"],\"std\":[]}}", + "libredox_0.1.14": "{\"dependencies\":[{\"name\":\"bitflags\",\"optional\":true,\"req\":\"^2\"},{\"name\":\"ioslice\",\"optional\":true,\"req\":\"^0.6\"},{\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"plain\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"redox_syscall\",\"optional\":true,\"req\":\"^0.7\"}],\"features\":{\"base\":[\"libc\"],\"call\":[\"base\"],\"default\":[\"base\",\"call\",\"std\",\"redox_syscall\",\"protocol\"],\"mkns\":[\"ioslice\"],\"protocol\":[\"plain\",\"bitflags\",\"redox_syscall\"],\"std\":[\"base\"]}}", "libsqlite3-sys_0.30.1": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"runtime\"],\"kind\":\"build\",\"name\":\"bindgen\",\"optional\":true,\"req\":\"^0.69\"},{\"kind\":\"build\",\"name\":\"cc\",\"optional\":true,\"req\":\"^1.1.6\"},{\"name\":\"openssl-sys\",\"optional\":true,\"req\":\"^0.9.103\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"optional\":true,\"req\":\"^0.3.19\"},{\"kind\":\"build\",\"name\":\"prettyplease\",\"optional\":true,\"req\":\"^0.2.20\"},{\"default_features\":false,\"kind\":\"build\",\"name\":\"quote\",\"optional\":true,\"req\":\"^1.0.36\"},{\"features\":[\"full\",\"extra-traits\",\"visit-mut\"],\"kind\":\"build\",\"name\":\"syn\",\"optional\":true,\"req\":\"^2.0.72\"},{\"kind\":\"build\",\"name\":\"vcpkg\",\"optional\":true,\"req\":\"^0.2.15\"}],\"features\":{\"buildtime_bindgen\":[\"bindgen\",\"pkg-config\",\"vcpkg\"],\"bundled\":[\"cc\",\"bundled_bindings\"],\"bundled-sqlcipher\":[\"bundled\"],\"bundled-sqlcipher-vendored-openssl\":[\"bundled-sqlcipher\",\"openssl-sys/vendored\"],\"bundled-windows\":[\"cc\",\"bundled_bindings\"],\"bundled_bindings\":[],\"default\":[\"min_sqlite_version_3_14_0\"],\"in_gecko\":[],\"loadable_extension\":[\"prettyplease\",\"quote\",\"syn\"],\"min_sqlite_version_3_14_0\":[\"pkg-config\",\"vcpkg\"],\"preupdate_hook\":[\"buildtime_bindgen\"],\"session\":[\"preupdate_hook\",\"buildtime_bindgen\"],\"sqlcipher\":[],\"unlock_notify\":[],\"wasm32-wasi-vfs\":[],\"with-asan\":[]}}", + "libssh2-sys_0.3.1": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0.25\"},{\"name\":\"libc\",\"req\":\"^0.2\"},{\"default_features\":false,\"features\":[\"libc\"],\"name\":\"libz-sys\",\"req\":\"^1.1.0\"},{\"name\":\"openssl-sys\",\"req\":\"^0.9.35\",\"target\":\"cfg(unix)\"},{\"name\":\"openssl-sys\",\"optional\":true,\"req\":\"^0.9.35\",\"target\":\"cfg(windows)\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"req\":\"^0.3.11\"},{\"kind\":\"build\",\"name\":\"vcpkg\",\"req\":\"^0.2\",\"target\":\"cfg(target_env = \\\"msvc\\\")\"}],\"features\":{\"openssl-on-win32\":[\"openssl-sys\"],\"vendored-openssl\":[\"openssl-sys/vendored\"],\"zlib-ng-compat\":[\"libz-sys/zlib-ng\"]}}", "libz-sys_1.1.23": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0.98\"},{\"kind\":\"build\",\"name\":\"cmake\",\"optional\":true,\"req\":\"^0.1.50\"},{\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.43\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"req\":\"^0.3.9\"},{\"kind\":\"build\",\"name\":\"vcpkg\",\"req\":\"^0.2.11\"}],\"features\":{\"asm\":[],\"default\":[\"libc\",\"stock-zlib\"],\"static\":[],\"stock-zlib\":[],\"zlib-ng\":[\"libc\",\"cmake\"],\"zlib-ng-no-cmake-experimental-community-maintained\":[\"libc\"]}}", + "libz-sys_1.1.25": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0.98\"},{\"kind\":\"build\",\"name\":\"cmake\",\"optional\":true,\"req\":\"^0.1.50\"},{\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.43\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"req\":\"^0.3.9\"},{\"kind\":\"build\",\"name\":\"vcpkg\",\"req\":\"^0.2.11\"}],\"features\":{\"asm\":[],\"default\":[\"libc\",\"stock-zlib\"],\"static\":[],\"stock-zlib\":[],\"zlib-ng\":[\"libc\",\"cmake\"],\"zlib-ng-no-cmake-experimental-community-maintained\":[\"libc\"]}}", "linked-hash-map_0.5.6": "{\"dependencies\":[{\"name\":\"heapsize\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_test\",\"req\":\"^1.0\"}],\"features\":{\"heapsize_impl\":[\"heapsize\"],\"nightly\":[],\"serde_impl\":[\"serde\"]}}", "linux-keyutils_0.2.4": "{\"dependencies\":[{\"default_features\":false,\"name\":\"bitflags\",\"req\":\"^2.4\"},{\"default_features\":false,\"features\":[\"std\",\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^4.4.11\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.132\"},{\"kind\":\"dev\",\"name\":\"zeroize\",\"req\":\"^1.5.7\"}],\"features\":{\"default\":[],\"std\":[\"bitflags/std\"]}}", "linux-raw-sys_0.11.0": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.100\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"}],\"features\":{\"auxvec\":[],\"bootparam\":[],\"btrfs\":[],\"default\":[\"std\",\"general\",\"errno\"],\"elf\":[],\"elf_uapi\":[],\"errno\":[],\"general\":[],\"if_arp\":[],\"if_ether\":[],\"if_packet\":[],\"image\":[],\"io_uring\":[],\"ioctl\":[],\"landlock\":[],\"loop_device\":[],\"mempolicy\":[],\"net\":[],\"netlink\":[],\"no_std\":[],\"prctl\":[],\"ptrace\":[],\"rustc-dep-of-std\":[\"core\",\"no_std\"],\"std\":[],\"system\":[],\"xdp\":[]}}", + "linux-raw-sys_0.12.1": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.100\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"}],\"features\":{\"auxvec\":[],\"bootparam\":[],\"btrfs\":[],\"default\":[\"std\",\"general\",\"errno\"],\"elf\":[],\"elf_uapi\":[],\"errno\":[],\"general\":[],\"if_arp\":[],\"if_ether\":[],\"if_packet\":[],\"if_tun\":[],\"image\":[],\"io_uring\":[],\"ioctl\":[],\"landlock\":[],\"loop_device\":[],\"mempolicy\":[],\"net\":[],\"netlink\":[],\"no_std\":[],\"prctl\":[],\"ptrace\":[],\"rustc-dep-of-std\":[\"core\",\"no_std\"],\"std\":[],\"system\":[],\"vm_sockets\":[],\"xdp\":[]}}", "linux-raw-sys_0.4.15": "{\"dependencies\":[{\"name\":\"compiler_builtins\",\"optional\":true,\"req\":\"^0.1.49\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.100\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"}],\"features\":{\"bootparam\":[],\"btrfs\":[],\"default\":[\"std\",\"general\",\"errno\"],\"elf\":[],\"elf_uapi\":[],\"errno\":[],\"general\":[],\"if_arp\":[],\"if_ether\":[],\"if_packet\":[],\"io_uring\":[],\"ioctl\":[],\"landlock\":[],\"loop_device\":[],\"mempolicy\":[],\"net\":[],\"netlink\":[],\"no_std\":[],\"prctl\":[],\"ptrace\":[],\"rustc-dep-of-std\":[\"core\",\"compiler_builtins\",\"no_std\"],\"std\":[],\"system\":[],\"xdp\":[]}}", "litemap_0.8.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1.3.1\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"name\":\"databake\",\"optional\":true,\"req\":\"^0.2.0\"},{\"default_features\":false,\"features\":[\"use-std\"],\"kind\":\"dev\",\"name\":\"postcard\",\"req\":\"^1.0.3\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9\"},{\"features\":[\"validation\"],\"kind\":\"dev\",\"name\":\"rkyv\",\"req\":\"^0.7\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.220\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"serde_core\",\"req\":\"^1.0.220\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.45\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"yoke\",\"optional\":true,\"req\":\"^0.8.0\"}],\"features\":{\"alloc\":[],\"databake\":[\"dep:databake\"],\"default\":[\"alloc\"],\"serde\":[\"dep:serde_core\",\"alloc\"],\"testing\":[\"alloc\"],\"yoke\":[\"dep:yoke\"]}}", "local-waker_0.1.4": "{\"dependencies\":[],\"features\":{}}", @@ -1007,6 +1037,7 @@ "md-5_0.10.6": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1.0\"},{\"name\":\"digest\",\"req\":\"^0.10.7\"},{\"features\":[\"dev\"],\"kind\":\"dev\",\"name\":\"digest\",\"req\":\"^0.10.7\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.2.2\"},{\"name\":\"md5-asm\",\"optional\":true,\"req\":\"^0.5\",\"target\":\"cfg(any(target_arch = \\\"x86\\\", target_arch = \\\"x86_64\\\"))\"}],\"features\":{\"asm\":[\"md5-asm\"],\"default\":[\"std\"],\"force-soft\":[],\"loongarch64_asm\":[],\"oid\":[\"digest/oid\"],\"std\":[\"digest/std\"]}}", "md5_0.8.0": "{\"dependencies\":[],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "memchr_2.7.6": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.20\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.3\"}],\"features\":{\"alloc\":[],\"default\":[\"std\"],\"libc\":[],\"logging\":[\"dep:log\"],\"rustc-dep-of-std\":[\"core\"],\"std\":[\"alloc\"],\"use_std\":[\"std\"]}}", + "memchr_2.8.0": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.20\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.3\"}],\"features\":{\"alloc\":[],\"default\":[\"std\"],\"libc\":[],\"logging\":[\"dep:log\"],\"rustc-dep-of-std\":[\"core\"],\"std\":[\"alloc\"],\"use_std\":[\"std\"]}}", "memoffset_0.6.5": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"autocfg\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"}],\"features\":{\"default\":[],\"unstable_const\":[]}}", "memoffset_0.9.1": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"autocfg\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"}],\"features\":{\"default\":[],\"unstable_const\":[],\"unstable_offset_of\":[]}}", "mime_0.3.17": "{\"dependencies\":[],\"features\":{}}", @@ -1014,6 +1045,7 @@ "minimal-lexical_0.2.1": "{\"dependencies\":[],\"features\":{\"alloc\":[],\"compact\":[],\"default\":[\"std\"],\"lint\":[],\"nightly\":[],\"std\":[]}}", "miniz_oxide_0.8.9": "{\"dependencies\":[{\"default_features\":false,\"name\":\"adler2\",\"req\":\"^2.0\"},{\"name\":\"alloc\",\"optional\":true,\"package\":\"rustc-std-workspace-alloc\",\"req\":\"^1.0.0\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"simd-adler32\",\"optional\":true,\"req\":\"^0.3.3\"}],\"features\":{\"block-boundary\":[],\"default\":[\"with-alloc\"],\"rustc-dep-of-std\":[\"core\",\"alloc\",\"adler2/rustc-dep-of-std\"],\"simd\":[\"simd-adler32\"],\"std\":[],\"with-alloc\":[]}}", "mio_1.1.1": "{\"dependencies\":[{\"default_features\":false,\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.11\"},{\"name\":\"libc\",\"req\":\"^0.2.178\",\"target\":\"cfg(target_os = \\\"hermit\\\")\"},{\"name\":\"libc\",\"req\":\"^0.2.178\",\"target\":\"cfg(target_os = \\\"wasi\\\")\"},{\"name\":\"libc\",\"req\":\"^0.2.178\",\"target\":\"cfg(unix)\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.8\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9\"},{\"name\":\"wasi\",\"req\":\"^0.11.0\",\"target\":\"cfg(target_os = \\\"wasi\\\")\"},{\"features\":[\"Wdk_Foundation\",\"Wdk_Storage_FileSystem\",\"Wdk_System_IO\",\"Win32_Foundation\",\"Win32_Networking_WinSock\",\"Win32_Storage_FileSystem\",\"Win32_Security\",\"Win32_System_IO\",\"Win32_System_WindowsProgramming\"],\"name\":\"windows-sys\",\"req\":\"^0.61\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[\"log\"],\"net\":[],\"os-ext\":[\"os-poll\",\"windows-sys/Win32_System_Pipes\",\"windows-sys/Win32_Security\"],\"os-poll\":[]}}", + "miow_0.6.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.0\"},{\"kind\":\"dev\",\"name\":\"socket2\",\"req\":\"^0.6.0\"},{\"features\":[\"Win32_Foundation\",\"Win32_Networking_WinSock\",\"Win32_Security\",\"Win32_Storage_FileSystem\",\"Win32_System_IO\",\"Win32_System_Pipes\",\"Win32_System_Threading\"],\"name\":\"windows-sys\",\"req\":\">=0.60, <=0.61\"}],\"features\":{}}", "moka_0.12.13": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"actix-rt\",\"req\":\"^2.8\"},{\"kind\":\"dev\",\"name\":\"ahash\",\"req\":\"^0.8.3\"},{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.19\"},{\"name\":\"async-lock\",\"optional\":true,\"req\":\"^3.3\"},{\"name\":\"crossbeam-channel\",\"req\":\"^0.5.15\"},{\"name\":\"crossbeam-epoch\",\"req\":\"^0.9.18\"},{\"name\":\"crossbeam-utils\",\"req\":\"^0.8.21\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.10.0\"},{\"name\":\"equivalent\",\"req\":\"^1.0\"},{\"name\":\"event-listener\",\"optional\":true,\"req\":\"^5.3\"},{\"name\":\"futures-util\",\"optional\":true,\"req\":\"^0.3.17\"},{\"kind\":\"dev\",\"name\":\"getrandom\",\"req\":\"^0.2\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"loom\",\"req\":\"^0.7\",\"target\":\"cfg(moka_loom)\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"^1.7\"},{\"name\":\"parking_lot\",\"req\":\"^0.12\"},{\"name\":\"portable-atomic\",\"req\":\"^1.6\"},{\"name\":\"quanta\",\"optional\":true,\"req\":\"^0.12.2\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.5\"},{\"default_features\":false,\"features\":[\"rustls-tls\"],\"kind\":\"dev\",\"name\":\"reqwest\",\"req\":\"^0.12\"},{\"name\":\"smallvec\",\"req\":\"^1.8\"},{\"name\":\"tagptr\",\"req\":\"^0.2\"},{\"features\":[\"fs\",\"io-util\",\"macros\",\"rt-multi-thread\",\"sync\",\"time\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.19\"},{\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0\",\"target\":\"cfg(trybuild)\"},{\"features\":[\"v4\"],\"name\":\"uuid\",\"req\":\"^1.1\"}],\"features\":{\"atomic64\":[],\"default\":[],\"future\":[\"async-lock\",\"event-listener\",\"futures-util\"],\"logging\":[\"log\"],\"quanta\":[\"dep:quanta\"],\"sync\":[],\"unstable-debug-counters\":[\"future\"]}}", "moxcms_0.7.11": "{\"dependencies\":[{\"name\":\"num-traits\",\"req\":\"^0.2\"},{\"name\":\"pxfm\",\"req\":\"^0.1.1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9\"}],\"features\":{\"avx\":[],\"avx512\":[],\"default\":[\"avx\",\"sse\",\"neon\"],\"neon\":[],\"options\":[],\"sse\":[]}}", "multimap_0.10.1": "{\"dependencies\":[{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_test\",\"req\":\"^1.0\"}],\"features\":{\"default\":[\"serde_impl\"],\"serde_impl\":[\"serde\"]}}", @@ -1067,6 +1099,7 @@ "oboe_0.6.1": "{\"dependencies\":[{\"name\":\"jni\",\"optional\":true,\"req\":\"^0.21\"},{\"default_features\":false,\"name\":\"ndk\",\"optional\":true,\"req\":\"^0.8\"},{\"name\":\"ndk-context\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"num-derive\",\"req\":\"^0.4\"},{\"name\":\"num-traits\",\"req\":\"^0.2\"},{\"name\":\"oboe-sys\",\"req\":\"^0.6\"}],\"features\":{\"doc-cfg\":[],\"fetch-prebuilt\":[\"oboe-sys/fetch-prebuilt\"],\"generate-bindings\":[\"oboe-sys/generate-bindings\"],\"java-interface\":[\"ndk\",\"ndk-context\",\"jni\"],\"shared-link\":[\"oboe-sys/shared-link\"],\"shared-stdcxx\":[\"oboe-sys/shared-stdcxx\"]}}", "oid-registry_0.8.1": "{\"dependencies\":[{\"name\":\"asn1-rs\",\"req\":\"^0.7\"}],\"features\":{\"crypto\":[\"kdf\",\"pkcs1\",\"pkcs7\",\"pkcs9\",\"pkcs12\",\"nist_algs\",\"x962\"],\"default\":[\"registry\"],\"kdf\":[],\"ms_spc\":[],\"nist_algs\":[],\"pkcs1\":[],\"pkcs12\":[],\"pkcs7\":[],\"pkcs9\":[],\"registry\":[],\"x500\":[],\"x509\":[],\"x962\":[]}}", "once_cell_1.21.3": "{\"dependencies\":[{\"name\":\"critical-section\",\"optional\":true,\"req\":\"^1.1.3\"},{\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"critical-section\",\"req\":\"^1.1.3\"},{\"default_features\":false,\"name\":\"parking_lot_core\",\"optional\":true,\"req\":\"^0.9.10\"},{\"default_features\":false,\"name\":\"portable-atomic\",\"optional\":true,\"req\":\"^1.8\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.10.6\"}],\"features\":{\"alloc\":[\"race\"],\"atomic-polyfill\":[\"critical-section\"],\"critical-section\":[\"dep:critical-section\",\"portable-atomic\"],\"default\":[\"std\"],\"parking_lot\":[\"dep:parking_lot_core\"],\"portable-atomic\":[\"dep:portable-atomic\"],\"race\":[],\"std\":[\"alloc\"],\"unstable\":[]}}", + "once_cell_1.21.4": "{\"dependencies\":[{\"name\":\"critical-section\",\"optional\":true,\"req\":\"^1.1.3\"},{\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"critical-section\",\"req\":\"^1.1.3\"},{\"default_features\":false,\"name\":\"parking_lot_core\",\"optional\":true,\"req\":\"^0.9.10\"},{\"default_features\":false,\"name\":\"portable-atomic\",\"optional\":true,\"req\":\"^1.8\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.10.6\"}],\"features\":{\"alloc\":[\"race\"],\"atomic-polyfill\":[\"critical-section\"],\"critical-section\":[\"dep:critical-section\",\"portable-atomic\"],\"default\":[\"std\"],\"parking_lot\":[\"dep:parking_lot_core\"],\"portable-atomic\":[\"dep:portable-atomic\"],\"race\":[],\"std\":[\"alloc\"],\"unstable\":[]}}", "once_cell_polyfill_1.70.2": "{\"dependencies\":[],\"features\":{\"default\":[]}}", "onig_6.5.1": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2.4.0\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(windows)\"},{\"name\":\"once_cell\",\"req\":\"^1.12\"},{\"default_features\":false,\"name\":\"onig_sys\",\"req\":\"^69.9.1\"}],\"features\":{\"default\":[\"generate\"],\"generate\":[\"onig_sys/generate\"],\"posix-api\":[\"onig_sys/posix-api\"],\"print-debug\":[\"onig_sys/print-debug\"],\"std-pattern\":[]}}", "onig_sys_69.9.1": "{\"dependencies\":[{\"features\":[\"runtime\"],\"kind\":\"build\",\"name\":\"bindgen\",\"optional\":true,\"req\":\"^0.71\"},{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"req\":\"^0.3.16\"}],\"features\":{\"default\":[\"generate\"],\"generate\":[\"bindgen\"],\"posix-api\":[],\"print-debug\":[]}}", @@ -1076,6 +1109,7 @@ "openssl-probe_0.2.1": "{\"dependencies\":[],\"features\":{}}", "openssl-src_300.5.5+3.5.5": "{\"dependencies\":[{\"name\":\"cc\",\"req\":\"^1.0.79\"}],\"features\":{\"camellia\":[],\"default\":[],\"force-engine\":[],\"idea\":[],\"ktls\":[],\"legacy\":[],\"no-dso\":[],\"seed\":[],\"ssl3\":[],\"weak-crypto\":[]}}", "openssl-sys_0.9.111": "{\"dependencies\":[{\"features\":[\"ssl\",\"bindgen\"],\"name\":\"aws-lc-fips-sys\",\"optional\":true,\"req\":\"^0.13\"},{\"features\":[\"ssl\"],\"name\":\"aws-lc-sys\",\"optional\":true,\"req\":\"^0.27\"},{\"features\":[\"experimental\"],\"kind\":\"build\",\"name\":\"bindgen\",\"optional\":true,\"req\":\"^0.72.0\"},{\"name\":\"bssl-sys\",\"optional\":true,\"req\":\"^0.1.0\"},{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0.61\"},{\"name\":\"libc\",\"req\":\"^0.2\"},{\"features\":[\"legacy\"],\"kind\":\"build\",\"name\":\"openssl-src\",\"optional\":true,\"req\":\"^300.2.0\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"req\":\"^0.3.9\"},{\"kind\":\"build\",\"name\":\"vcpkg\",\"req\":\"^0.2.8\"}],\"features\":{\"aws-lc\":[\"dep:aws-lc-sys\"],\"aws-lc-fips\":[\"dep:aws-lc-fips-sys\"],\"unstable_boringssl\":[\"bssl-sys\"],\"vendored\":[\"openssl-src\"]}}", + "openssl-sys_0.9.112": "{\"dependencies\":[{\"features\":[\"ssl\",\"bindgen\"],\"name\":\"aws-lc-fips-sys\",\"optional\":true,\"req\":\"^0.13\"},{\"features\":[\"ssl\"],\"name\":\"aws-lc-sys\",\"optional\":true,\"req\":\"^0.38\"},{\"features\":[\"experimental\"],\"kind\":\"build\",\"name\":\"bindgen\",\"optional\":true,\"req\":\"^0.72.0\"},{\"name\":\"bssl-sys\",\"optional\":true,\"req\":\"^0.1.0\"},{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0.61\"},{\"name\":\"libc\",\"req\":\"^0.2\"},{\"features\":[\"legacy\"],\"kind\":\"build\",\"name\":\"openssl-src\",\"optional\":true,\"req\":\"^300.2.0\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"req\":\"^0.3.9\"},{\"kind\":\"build\",\"name\":\"vcpkg\",\"req\":\"^0.2.8\"}],\"features\":{\"aws-lc\":[\"dep:aws-lc-sys\"],\"aws-lc-fips\":[\"dep:aws-lc-fips-sys\"],\"unstable_boringssl\":[\"bssl-sys\"],\"vendored\":[\"openssl-src\"]}}", "openssl_0.10.75": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2.2.1\"},{\"name\":\"cfg-if\",\"req\":\"^1.0\"},{\"name\":\"ffi\",\"package\":\"openssl-sys\",\"req\":\"^0.9.111\"},{\"name\":\"foreign-types\",\"req\":\"^0.3.1\"},{\"kind\":\"dev\",\"name\":\"hex\",\"req\":\"^0.4\"},{\"name\":\"libc\",\"req\":\"^0.2\"},{\"name\":\"once_cell\",\"req\":\"^1.5.2\"},{\"name\":\"openssl-macros\",\"req\":\"^0.1.1\"}],\"features\":{\"aws-lc\":[\"ffi/aws-lc\"],\"aws-lc-fips\":[\"ffi/aws-lc-fips\"],\"bindgen\":[\"ffi/bindgen\"],\"default\":[],\"unstable_boringssl\":[\"ffi/unstable_boringssl\"],\"v101\":[],\"v102\":[],\"v110\":[],\"v111\":[],\"vendored\":[\"ffi/vendored\"]}}", "opentelemetry-appender-tracing_0.31.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.21\"},{\"kind\":\"dev\",\"name\":\"log\",\"req\":\"^0.4.21\"},{\"default_features\":false,\"features\":[\"logs\"],\"name\":\"opentelemetry\",\"req\":\"^0.31\"},{\"default_features\":false,\"features\":[\"logs\"],\"kind\":\"dev\",\"name\":\"opentelemetry-stdout\",\"req\":\"^0.31\"},{\"default_features\":false,\"features\":[\"logs\",\"testing\",\"internal-logs\"],\"kind\":\"dev\",\"name\":\"opentelemetry_sdk\",\"req\":\"^0.31\"},{\"features\":[\"flamegraph\",\"criterion\"],\"kind\":\"dev\",\"name\":\"pprof\",\"req\":\"^0.14\",\"target\":\"cfg(not(target_os = \\\"windows\\\"))\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"req\":\">=0.1.40\"},{\"default_features\":false,\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"tracing\",\"req\":\">=0.1.40\"},{\"default_features\":false,\"name\":\"tracing-core\",\"req\":\">=0.1.33\"},{\"name\":\"tracing-log\",\"optional\":true,\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"tracing-log\",\"req\":\"^0.2\"},{\"name\":\"tracing-opentelemetry\",\"optional\":true,\"req\":\"^0.32\"},{\"default_features\":false,\"features\":[\"registry\",\"std\"],\"name\":\"tracing-subscriber\",\"req\":\"^0.3\"},{\"default_features\":false,\"features\":[\"env-filter\",\"registry\",\"std\",\"fmt\"],\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3\"}],\"features\":{\"default\":[],\"experimental_metadata_attributes\":[\"dep:tracing-log\"],\"experimental_use_tracing_span_context\":[\"tracing-opentelemetry\"],\"spec_unstable_logs_enabled\":[\"opentelemetry/spec_unstable_logs_enabled\"]}}", "opentelemetry-http_0.31.0": "{\"dependencies\":[{\"name\":\"async-trait\",\"req\":\"^0.1\"},{\"name\":\"bytes\",\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"http\",\"req\":\"^1.1\"},{\"name\":\"http-body-util\",\"optional\":true,\"req\":\"^0.1\"},{\"default_features\":false,\"name\":\"hyper\",\"optional\":true,\"req\":\"^1.3\"},{\"features\":[\"client-legacy\",\"http1\",\"http2\"],\"name\":\"hyper-util\",\"optional\":true,\"req\":\"^0.1\"},{\"default_features\":false,\"features\":[\"trace\"],\"name\":\"opentelemetry\",\"req\":\"^0.31\"},{\"default_features\":false,\"name\":\"reqwest\",\"optional\":true,\"req\":\"^0.12\"},{\"default_features\":false,\"features\":[\"time\"],\"name\":\"tokio\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"default\":[\"internal-logs\"],\"hyper\":[\"dep:http-body-util\",\"dep:hyper\",\"dep:hyper-util\",\"dep:tokio\"],\"internal-logs\":[\"opentelemetry/internal-logs\"],\"reqwest\":[\"dep:reqwest\"],\"reqwest-blocking\":[\"dep:reqwest\",\"reqwest/blocking\"],\"reqwest-rustls\":[\"dep:reqwest\",\"reqwest/rustls-tls-native-roots\"],\"reqwest-rustls-webpki-roots\":[\"dep:reqwest\",\"reqwest/rustls-tls-webpki-roots\"]}}", @@ -1106,12 +1140,14 @@ "phf_shared_0.11.3": "{\"dependencies\":[{\"name\":\"siphasher\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"uncased\",\"optional\":true,\"req\":\"^0.9.9\"},{\"name\":\"unicase\",\"optional\":true,\"req\":\"^2.4.0\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "pin-project-internal_1.1.10": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1.0.60\"},{\"name\":\"quote\",\"req\":\"^1.0.25\"},{\"default_features\":false,\"features\":[\"parsing\",\"printing\",\"clone-impls\",\"proc-macro\",\"full\",\"visit-mut\"],\"name\":\"syn\",\"req\":\"^2.0.1\"}],\"features\":{}}", "pin-project-lite_0.2.16": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1\"}],\"features\":{}}", + "pin-project-lite_0.2.17": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1\"}],\"features\":{}}", "pin-project_1.1.10": "{\"dependencies\":[{\"name\":\"pin-project-internal\",\"req\":\"=1.1.10\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1\"}],\"features\":{}}", "pin-utils_0.1.0": "{\"dependencies\":[],\"features\":{}}", "piper_0.2.4": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"async-channel\",\"req\":\"^2.0.0\"},{\"kind\":\"dev\",\"name\":\"async-executor\",\"req\":\"^1.5.1\"},{\"kind\":\"dev\",\"name\":\"async-io\",\"req\":\"^2.0.0\"},{\"name\":\"atomic-waker\",\"req\":\"^1.1.0\"},{\"default_features\":false,\"features\":[\"cargo_bench_support\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4.0\"},{\"kind\":\"dev\",\"name\":\"easy-parallel\",\"req\":\"^3.2.0\"},{\"default_features\":false,\"name\":\"fastrand\",\"req\":\"^2.0.0\"},{\"name\":\"futures-io\",\"optional\":true,\"req\":\"^0.3.28\"},{\"kind\":\"dev\",\"name\":\"futures-lite\",\"req\":\"^2.0.0\"},{\"features\":[\"alloc\"],\"name\":\"portable-atomic-util\",\"optional\":true,\"req\":\"^0.2.0\"},{\"default_features\":false,\"name\":\"portable_atomic_crate\",\"optional\":true,\"package\":\"portable-atomic\",\"req\":\"^1.2.0\"}],\"features\":{\"default\":[\"std\"],\"portable-atomic\":[\"atomic-waker/portable-atomic\",\"portable_atomic_crate\",\"portable-atomic-util\"],\"std\":[\"fastrand/std\",\"futures-io\"]}}", "pkcs1_0.7.5": "{\"dependencies\":[{\"features\":[\"db\"],\"kind\":\"dev\",\"name\":\"const-oid\",\"req\":\"^0.9\"},{\"features\":[\"oid\"],\"name\":\"der\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"default_features\":false,\"name\":\"pkcs8\",\"optional\":true,\"req\":\"^0.10\"},{\"name\":\"spki\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{\"alloc\":[\"der/alloc\",\"zeroize\",\"pkcs8?/alloc\"],\"pem\":[\"alloc\",\"der/pem\",\"pkcs8?/pem\"],\"std\":[\"der/std\",\"alloc\"],\"zeroize\":[\"der/zeroize\"]}}", "pkcs8_0.10.2": "{\"dependencies\":[{\"features\":[\"oid\"],\"name\":\"der\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.3\"},{\"name\":\"pkcs5\",\"optional\":true,\"req\":\"^0.7\"},{\"default_features\":false,\"name\":\"rand_core\",\"optional\":true,\"req\":\"^0.6\"},{\"name\":\"spki\",\"req\":\"^0.7.1\"},{\"default_features\":false,\"name\":\"subtle\",\"optional\":true,\"req\":\"^2\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{\"3des\":[\"encryption\",\"pkcs5/3des\"],\"alloc\":[\"der/alloc\",\"der/zeroize\",\"spki/alloc\"],\"des-insecure\":[\"encryption\",\"pkcs5/des-insecure\"],\"encryption\":[\"alloc\",\"pkcs5/alloc\",\"pkcs5/pbes2\",\"rand_core\"],\"getrandom\":[\"rand_core/getrandom\"],\"pem\":[\"alloc\",\"der/pem\",\"spki/pem\"],\"sha1-insecure\":[\"encryption\",\"pkcs5/sha1-insecure\"],\"std\":[\"alloc\",\"der/std\",\"spki/std\"]}}", "pkg-config_0.3.32": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"lazy_static\",\"req\":\"^1\"}],\"features\":{}}", + "plain_0.2.3": "{\"dependencies\":[],\"features\":{}}", "plist_1.8.0": "{\"dependencies\":[{\"name\":\"base64\",\"req\":\"^0.22.0\"},{\"name\":\"indexmap\",\"req\":\"^2.1.0\"},{\"name\":\"quick_xml\",\"package\":\"quick-xml\",\"req\":\"^0.38.0\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.2\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0.2\"},{\"kind\":\"dev\",\"name\":\"serde_yaml\",\"req\":\"^0.8.21\"},{\"features\":[\"parsing\",\"formatting\"],\"name\":\"time\",\"req\":\"^0.3.30\"}],\"features\":{\"default\":[\"serde\"],\"enable_unstable_features_that_may_break_with_minor_version_bumps\":[]}}", "png_0.18.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"approx\",\"req\":\"^0.5.1\"},{\"name\":\"bitflags\",\"req\":\"^2.0\"},{\"kind\":\"dev\",\"name\":\"byteorder\",\"req\":\"^1.5.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^4.0\"},{\"name\":\"crc32fast\",\"req\":\"^1.2.0\"},{\"default_features\":false,\"features\":[\"cargo_bench_support\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.7.0\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.7.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"fdeflate\",\"req\":\"^0.3.3\"},{\"name\":\"flate2\",\"req\":\"^1.0.35\"},{\"kind\":\"dev\",\"name\":\"glob\",\"req\":\"^0.3\"},{\"features\":[\"simd\"],\"name\":\"miniz_oxide\",\"req\":\"^0.8\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9.2\"}],\"features\":{\"benchmarks\":[],\"unstable\":[\"crc32fast/nightly\"],\"zlib-rs\":[\"flate2/zlib-rs\"]}}", "polling_3.11.0": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1\"},{\"name\":\"concurrent-queue\",\"req\":\"^2.2.0\",\"target\":\"cfg(windows)\"},{\"kind\":\"dev\",\"name\":\"easy-parallel\",\"req\":\"^3.1.0\"},{\"kind\":\"dev\",\"name\":\"fastrand\",\"req\":\"^2.0.0\"},{\"name\":\"hermit-abi\",\"req\":\"^0.5.0\",\"target\":\"cfg(target_os = \\\"hermit\\\")\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.9\",\"target\":\"cfg(windows)\"},{\"default_features\":false,\"features\":[\"event\",\"fs\",\"pipe\",\"process\",\"std\",\"time\"],\"name\":\"rustix\",\"req\":\"^1.0.5\",\"target\":\"cfg(any(unix, target_os = \\\"fuchsia\\\", target_os = \\\"vxworks\\\"))\"},{\"kind\":\"dev\",\"name\":\"signal-hook\",\"req\":\"^0.3.17\",\"target\":\"cfg(all(unix, not(target_os=\\\"vita\\\")))\"},{\"kind\":\"dev\",\"name\":\"socket2\",\"req\":\"^0.6.0\"},{\"default_features\":false,\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1.37\"},{\"features\":[\"Wdk_Foundation\",\"Wdk_Storage_FileSystem\",\"Win32_Foundation\",\"Win32_Networking_WinSock\",\"Win32_Security\",\"Win32_Storage_FileSystem\",\"Win32_System_IO\",\"Win32_System_LibraryLoader\",\"Win32_System_Threading\",\"Win32_System_WindowsProgramming\"],\"name\":\"windows-sys\",\"req\":\"^0.61\",\"target\":\"cfg(windows)\"}],\"features\":{}}", @@ -1147,7 +1183,9 @@ "quinn-udp_0.5.14": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"cfg_aliases\",\"req\":\"^0.2\"},{\"default_features\":false,\"features\":[\"async_tokio\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.7\"},{\"name\":\"libc\",\"req\":\"^0.2.158\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"once_cell\",\"req\":\"^1.19\",\"target\":\"cfg(windows)\"},{\"name\":\"socket2\",\"req\":\">=0.5, <0.7\",\"target\":\"cfg(not(all(target_family = \\\"wasm\\\", target_os = \\\"unknown\\\")))\"},{\"features\":[\"sync\",\"rt\",\"rt-multi-thread\",\"net\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.28.1\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1.10\"},{\"features\":[\"Win32_Foundation\",\"Win32_System_IO\",\"Win32_Networking_WinSock\"],\"name\":\"windows-sys\",\"req\":\">=0.52, <=0.60\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[\"tracing\",\"log\"],\"direct-log\":[\"dep:log\"],\"fast-apple-datapath\":[],\"log\":[\"tracing/log\"]}}", "quinn_0.11.9": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.22\"},{\"name\":\"async-io\",\"optional\":true,\"req\":\"^2\"},{\"name\":\"async-std\",\"optional\":true,\"req\":\"^1.11\"},{\"kind\":\"dev\",\"name\":\"bencher\",\"req\":\"^0.1.5\"},{\"name\":\"bytes\",\"req\":\"^1\"},{\"kind\":\"build\",\"name\":\"cfg_aliases\",\"req\":\"^0.2\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^4\"},{\"kind\":\"dev\",\"name\":\"crc\",\"req\":\"^3\"},{\"kind\":\"dev\",\"name\":\"directories-next\",\"req\":\"^2\"},{\"name\":\"futures-io\",\"optional\":true,\"req\":\"^0.3.19\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2\"},{\"default_features\":false,\"name\":\"proto\",\"package\":\"quinn-proto\",\"req\":\"^0.11.12\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"rcgen\",\"req\":\"^0.14\"},{\"name\":\"rustc-hash\",\"req\":\"^2\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"rustls\",\"optional\":true,\"req\":\"^0.23.5\"},{\"kind\":\"dev\",\"name\":\"rustls-pemfile\",\"req\":\"^2\"},{\"name\":\"smol\",\"optional\":true,\"req\":\"^2\"},{\"name\":\"socket2\",\"req\":\">=0.5, <0.7\",\"target\":\"cfg(not(all(target_family = \\\"wasm\\\", target_os = \\\"unknown\\\")))\"},{\"name\":\"thiserror\",\"req\":\"^2.0.3\"},{\"features\":[\"sync\"],\"name\":\"tokio\",\"req\":\"^1.28.1\"},{\"features\":[\"sync\",\"rt\",\"rt-multi-thread\",\"time\",\"macros\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.28.1\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"req\":\"^0.1.10\"},{\"default_features\":false,\"features\":[\"std-future\"],\"kind\":\"dev\",\"name\":\"tracing-futures\",\"req\":\"^0.2.0\"},{\"default_features\":false,\"features\":[\"env-filter\",\"fmt\",\"ansi\",\"time\",\"local-time\"],\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3.0\"},{\"default_features\":false,\"features\":[\"tracing\"],\"name\":\"udp\",\"package\":\"quinn-udp\",\"req\":\"^0.5\"},{\"kind\":\"dev\",\"name\":\"url\",\"req\":\"^2\"},{\"name\":\"web-time\",\"req\":\"^1\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", target_os = \\\"unknown\\\"))\"}],\"features\":{\"aws-lc-rs\":[\"proto/aws-lc-rs\"],\"aws-lc-rs-fips\":[\"proto/aws-lc-rs-fips\"],\"bloom\":[\"proto/bloom\"],\"default\":[\"log\",\"platform-verifier\",\"runtime-tokio\",\"rustls-ring\",\"bloom\"],\"lock_tracking\":[],\"log\":[\"tracing/log\",\"proto/log\",\"udp/log\"],\"platform-verifier\":[\"proto/platform-verifier\"],\"qlog\":[\"proto/qlog\"],\"ring\":[\"proto/ring\"],\"runtime-async-std\":[\"async-io\",\"async-std\"],\"runtime-smol\":[\"async-io\",\"smol\"],\"runtime-tokio\":[\"tokio/time\",\"tokio/rt\",\"tokio/net\"],\"rustls\":[\"rustls-ring\"],\"rustls-aws-lc-rs\":[\"dep:rustls\",\"aws-lc-rs\",\"proto/rustls-aws-lc-rs\",\"proto/aws-lc-rs\"],\"rustls-aws-lc-rs-fips\":[\"dep:rustls\",\"aws-lc-rs-fips\",\"proto/rustls-aws-lc-rs-fips\",\"proto/aws-lc-rs-fips\"],\"rustls-log\":[\"rustls?/logging\"],\"rustls-ring\":[\"dep:rustls\",\"ring\",\"proto/rustls-ring\",\"proto/ring\"]}}", "quote_1.0.44": "{\"dependencies\":[{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.80\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"features\":[\"diff\"],\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.108\"}],\"features\":{\"default\":[\"proc-macro\"],\"proc-macro\":[\"proc-macro2/proc-macro\"]}}", + "quote_1.0.45": "{\"dependencies\":[{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.80\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"features\":[\"diff\"],\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.108\"}],\"features\":{\"default\":[\"proc-macro\"],\"proc-macro\":[\"proc-macro2/proc-macro\"]}}", "r-efi_5.3.0": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"}],\"features\":{\"efiapi\":[],\"examples\":[\"native\"],\"native\":[],\"rustc-dep-of-std\":[\"core\"]}}", + "r-efi_6.0.0": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"}],\"features\":{\"native\":[],\"rustc-dep-of-std\":[\"core\"]}}", "radix_trie_0.2.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.3\"},{\"name\":\"endian-type\",\"req\":\"^0.1.2\"},{\"name\":\"nibble_vec\",\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.3\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_test\",\"req\":\"^1.0\"}],\"features\":{}}", "radix_trie_0.3.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.3\"},{\"name\":\"endian-type\",\"req\":\"^0.2.0\"},{\"name\":\"nibble_vec\",\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_test\",\"req\":\"^1.0\"}],\"features\":{}}", "rama-core_0.3.0-alpha.4": "{\"dependencies\":[{\"name\":\"ahash\",\"req\":\"^0.8\"},{\"name\":\"asynk-strim\",\"req\":\"^0.1\"},{\"name\":\"bytes\",\"req\":\"^1\"},{\"name\":\"futures\",\"req\":\"^0.3\"},{\"default_features\":false,\"features\":[\"trace\"],\"name\":\"opentelemetry\",\"optional\":true,\"req\":\"^0.31\"},{\"features\":[\"semconv_experimental\"],\"name\":\"opentelemetry-semantic-conventions\",\"optional\":true,\"req\":\"^0.31\"},{\"default_features\":false,\"features\":[\"trace\",\"rt-tokio\"],\"name\":\"opentelemetry_sdk\",\"optional\":true,\"req\":\"^0.31\"},{\"name\":\"parking_lot\",\"req\":\"^0.12\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0\"},{\"name\":\"rama-error\",\"req\":\"^0.3.0-alpha.4\"},{\"name\":\"rama-macros\",\"req\":\"^0.3.0-alpha.4\"},{\"name\":\"rama-utils\",\"req\":\"^0.3.0-alpha.4\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"features\":[\"macros\",\"fs\",\"io-std\"],\"name\":\"tokio\",\"req\":\"^1.48\"},{\"features\":[\"full\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.48\"},{\"name\":\"tokio-graceful\",\"req\":\"^0.2\"},{\"kind\":\"dev\",\"name\":\"tokio-test\",\"req\":\"^0.4\"},{\"features\":[\"codec\",\"io\",\"io-util\"],\"name\":\"tokio-util\",\"req\":\"^0.7\"},{\"name\":\"tracing\",\"req\":\"^0.1\"},{\"name\":\"tracing-opentelemetry\",\"optional\":true,\"req\":\"^0.32\"}],\"features\":{\"default\":[],\"opentelemetry\":[\"dep:opentelemetry\",\"dep:opentelemetry-semantic-conventions\",\"dep:opentelemetry_sdk\",\"dep:tracing-opentelemetry\"]}}", @@ -1179,13 +1217,16 @@ "rcgen_0.14.7": "{\"dependencies\":[{\"default_features\":false,\"name\":\"aws-lc-rs\",\"optional\":true,\"req\":\"^1.13.3\"},{\"kind\":\"dev\",\"name\":\"openssl\",\"req\":\"^0.10\",\"target\":\"cfg(unix)\"},{\"name\":\"pem\",\"optional\":true,\"req\":\"^3.0.2\"},{\"name\":\"pki-types\",\"package\":\"rustls-pki-types\",\"req\":\"^1.4.1\"},{\"name\":\"ring\",\"optional\":true,\"req\":\"^0.17\"},{\"default_features\":false,\"name\":\"time\",\"req\":\"^0.3.6\"},{\"name\":\"x509-parser\",\"optional\":true,\"req\":\"^0.18\"},{\"features\":[\"time\",\"std\"],\"name\":\"yasna\",\"req\":\"^0.5.2\"},{\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1.2\"}],\"features\":{\"aws_lc_rs\":[\"crypto\",\"dep:aws-lc-rs\",\"aws-lc-rs/aws-lc-sys\",\"x509-parser?/verify-aws\"],\"aws_lc_rs_unstable\":[\"aws_lc_rs\",\"aws-lc-rs/unstable\",\"x509-parser?/verify-aws\"],\"crypto\":[],\"default\":[\"crypto\",\"pem\",\"ring\"],\"fips\":[\"crypto\",\"dep:aws-lc-rs\",\"aws-lc-rs/fips\"],\"ring\":[\"crypto\",\"dep:ring\",\"x509-parser?/verify\"]}}", "redox_syscall_0.5.18": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2.4\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"loom\",\"req\":\"^0.7\",\"target\":\"cfg(loom)\"}],\"features\":{\"default\":[\"userspace\"],\"rustc-dep-of-std\":[\"core\",\"bitflags/rustc-dep-of-std\"],\"std\":[],\"userspace\":[]}}", "redox_syscall_0.7.0": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2.4\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"loom\",\"req\":\"^0.7\",\"target\":\"cfg(loom)\"}],\"features\":{\"default\":[\"userspace\"],\"rustc-dep-of-std\":[\"core\",\"bitflags/rustc-dep-of-std\"],\"std\":[],\"userspace\":[]}}", + "redox_syscall_0.7.3": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2.4\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"loom\",\"req\":\"^0.7\",\"target\":\"cfg(loom)\"}],\"features\":{\"default\":[\"userspace\"],\"rustc-dep-of-std\":[\"core\",\"bitflags/rustc-dep-of-std\"],\"std\":[],\"userspace\":[]}}", "redox_users_0.4.6": "{\"dependencies\":[{\"features\":[\"std\"],\"name\":\"getrandom\",\"req\":\"^0.2\"},{\"default_features\":false,\"features\":[\"std\",\"call\"],\"name\":\"libredox\",\"req\":\"^0.1.3\"},{\"name\":\"rust-argon2\",\"optional\":true,\"req\":\"^0.8\"},{\"name\":\"thiserror\",\"req\":\"^1.0\"},{\"features\":[\"zeroize_derive\"],\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1.4\"}],\"features\":{\"auth\":[\"rust-argon2\",\"zeroize\"],\"default\":[\"auth\"]}}", "redox_users_0.5.2": "{\"dependencies\":[{\"features\":[\"std\"],\"name\":\"getrandom\",\"req\":\"^0.2\"},{\"default_features\":false,\"features\":[\"std\",\"call\"],\"name\":\"libredox\",\"req\":\"^0.1.3\"},{\"name\":\"rust-argon2\",\"optional\":true,\"req\":\"^0.8\"},{\"name\":\"thiserror\",\"req\":\"^2.0\"},{\"features\":[\"zeroize_derive\"],\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1.4\"}],\"features\":{\"auth\":[\"rust-argon2\",\"zeroize\"],\"default\":[\"auth\"]}}", "ref-cast-impl_1.0.25": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1.0.74\"},{\"name\":\"quote\",\"req\":\"^1.0.35\"},{\"kind\":\"dev\",\"name\":\"ref-cast\",\"req\":\"^1\"},{\"name\":\"syn\",\"req\":\"^2.0.46\"}],\"features\":{}}", "ref-cast_1.0.25": "{\"dependencies\":[{\"name\":\"ref-cast-impl\",\"req\":\"=1.0.25\"},{\"kind\":\"dev\",\"name\":\"ref-cast-test-suite\",\"req\":\"^0\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0.13\"},{\"features\":[\"diff\"],\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0.108\"}],\"features\":{}}", "regex-automata_0.4.13": "{\"dependencies\":[{\"default_features\":false,\"name\":\"aho-corasick\",\"optional\":true,\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.69\"},{\"default_features\":false,\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"bstr\",\"req\":\"^1.3.0\"},{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3.3\"},{\"default_features\":false,\"features\":[\"atty\",\"humantime\",\"termcolor\"],\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.9.3\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.14\"},{\"default_features\":false,\"name\":\"memchr\",\"optional\":true,\"req\":\"^2.6.0\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.3\"},{\"default_features\":false,\"name\":\"regex-syntax\",\"optional\":true,\"req\":\"^0.8.5\"},{\"kind\":\"dev\",\"name\":\"regex-test\",\"req\":\"^0.1.0\"}],\"features\":{\"alloc\":[],\"default\":[\"std\",\"syntax\",\"perf\",\"unicode\",\"meta\",\"nfa\",\"dfa\",\"hybrid\"],\"dfa\":[\"dfa-build\",\"dfa-search\",\"dfa-onepass\"],\"dfa-build\":[\"nfa-thompson\",\"dfa-search\"],\"dfa-onepass\":[\"nfa-thompson\"],\"dfa-search\":[],\"hybrid\":[\"alloc\",\"nfa-thompson\"],\"internal-instrument\":[\"internal-instrument-pikevm\"],\"internal-instrument-pikevm\":[\"logging\",\"std\"],\"logging\":[\"dep:log\",\"aho-corasick?/logging\",\"memchr?/logging\"],\"meta\":[\"syntax\",\"nfa-pikevm\"],\"nfa\":[\"nfa-thompson\",\"nfa-pikevm\",\"nfa-backtrack\"],\"nfa-backtrack\":[\"nfa-thompson\"],\"nfa-pikevm\":[\"nfa-thompson\"],\"nfa-thompson\":[\"alloc\"],\"perf\":[\"perf-inline\",\"perf-literal\"],\"perf-inline\":[],\"perf-literal\":[\"perf-literal-substring\",\"perf-literal-multisubstring\"],\"perf-literal-multisubstring\":[\"dep:aho-corasick\"],\"perf-literal-substring\":[\"aho-corasick?/perf-literal\",\"dep:memchr\"],\"std\":[\"regex-syntax?/std\",\"memchr?/std\",\"aho-corasick?/std\",\"alloc\"],\"syntax\":[\"dep:regex-syntax\",\"alloc\"],\"unicode\":[\"unicode-age\",\"unicode-bool\",\"unicode-case\",\"unicode-gencat\",\"unicode-perl\",\"unicode-script\",\"unicode-segment\",\"unicode-word-boundary\",\"regex-syntax?/unicode\"],\"unicode-age\":[\"regex-syntax?/unicode-age\"],\"unicode-bool\":[\"regex-syntax?/unicode-bool\"],\"unicode-case\":[\"regex-syntax?/unicode-case\"],\"unicode-gencat\":[\"regex-syntax?/unicode-gencat\"],\"unicode-perl\":[\"regex-syntax?/unicode-perl\"],\"unicode-script\":[\"regex-syntax?/unicode-script\"],\"unicode-segment\":[\"regex-syntax?/unicode-segment\"],\"unicode-word-boundary\":[]}}", + "regex-automata_0.4.14": "{\"dependencies\":[{\"default_features\":false,\"name\":\"aho-corasick\",\"optional\":true,\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.69\"},{\"default_features\":false,\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"bstr\",\"req\":\"^1.3.0\"},{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3.3\"},{\"default_features\":false,\"features\":[\"atty\",\"humantime\",\"termcolor\"],\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.9.3\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.14\"},{\"default_features\":false,\"name\":\"memchr\",\"optional\":true,\"req\":\"^2.6.0\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.3\"},{\"default_features\":false,\"name\":\"regex-syntax\",\"optional\":true,\"req\":\"^0.8.5\"},{\"kind\":\"dev\",\"name\":\"regex-test\",\"req\":\"^0.1.0\"}],\"features\":{\"alloc\":[],\"default\":[\"std\",\"syntax\",\"perf\",\"unicode\",\"meta\",\"nfa\",\"dfa\",\"hybrid\"],\"dfa\":[\"dfa-build\",\"dfa-search\",\"dfa-onepass\"],\"dfa-build\":[\"nfa-thompson\",\"dfa-search\"],\"dfa-onepass\":[\"nfa-thompson\"],\"dfa-search\":[],\"hybrid\":[\"alloc\",\"nfa-thompson\"],\"internal-instrument\":[\"internal-instrument-pikevm\"],\"internal-instrument-pikevm\":[\"logging\",\"std\"],\"logging\":[\"dep:log\",\"aho-corasick?/logging\",\"memchr?/logging\"],\"meta\":[\"syntax\",\"nfa-pikevm\"],\"nfa\":[\"nfa-thompson\",\"nfa-pikevm\",\"nfa-backtrack\"],\"nfa-backtrack\":[\"nfa-thompson\"],\"nfa-pikevm\":[\"nfa-thompson\"],\"nfa-thompson\":[\"alloc\"],\"perf\":[\"perf-inline\",\"perf-literal\"],\"perf-inline\":[],\"perf-literal\":[\"perf-literal-substring\",\"perf-literal-multisubstring\"],\"perf-literal-multisubstring\":[\"dep:aho-corasick\"],\"perf-literal-substring\":[\"aho-corasick?/perf-literal\",\"dep:memchr\"],\"std\":[\"regex-syntax?/std\",\"memchr?/std\",\"aho-corasick?/std\",\"alloc\"],\"syntax\":[\"dep:regex-syntax\",\"alloc\"],\"unicode\":[\"unicode-age\",\"unicode-bool\",\"unicode-case\",\"unicode-gencat\",\"unicode-perl\",\"unicode-script\",\"unicode-segment\",\"unicode-word-boundary\",\"regex-syntax?/unicode\"],\"unicode-age\":[\"regex-syntax?/unicode-age\"],\"unicode-bool\":[\"regex-syntax?/unicode-bool\"],\"unicode-case\":[\"regex-syntax?/unicode-case\"],\"unicode-gencat\":[\"regex-syntax?/unicode-gencat\"],\"unicode-perl\":[\"regex-syntax?/unicode-perl\"],\"unicode-script\":[\"regex-syntax?/unicode-script\"],\"unicode-segment\":[\"regex-syntax?/unicode-segment\"],\"unicode-word-boundary\":[]}}", "regex-lite_0.1.8": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.69\"},{\"kind\":\"dev\",\"name\":\"regex-test\",\"req\":\"^0.1.0\"}],\"features\":{\"default\":[\"std\",\"string\"],\"std\":[],\"string\":[]}}", "regex-syntax_0.6.29": "{\"dependencies\":[],\"features\":{\"default\":[\"unicode\"],\"unicode\":[\"unicode-age\",\"unicode-bool\",\"unicode-case\",\"unicode-gencat\",\"unicode-perl\",\"unicode-script\",\"unicode-segment\"],\"unicode-age\":[],\"unicode-bool\":[],\"unicode-case\":[],\"unicode-gencat\":[],\"unicode-perl\":[],\"unicode-script\":[],\"unicode-segment\":[]}}", + "regex-syntax_0.8.10": "{\"dependencies\":[{\"features\":[\"derive\"],\"name\":\"arbitrary\",\"optional\":true,\"req\":\"^1.3.0\"}],\"features\":{\"arbitrary\":[\"dep:arbitrary\"],\"default\":[\"std\",\"unicode\"],\"std\":[],\"unicode\":[\"unicode-age\",\"unicode-bool\",\"unicode-case\",\"unicode-gencat\",\"unicode-perl\",\"unicode-script\",\"unicode-segment\"],\"unicode-age\":[],\"unicode-bool\":[],\"unicode-case\":[],\"unicode-gencat\":[],\"unicode-perl\":[],\"unicode-script\":[],\"unicode-segment\":[]}}", "regex-syntax_0.8.8": "{\"dependencies\":[{\"features\":[\"derive\"],\"name\":\"arbitrary\",\"optional\":true,\"req\":\"^1.3.0\"}],\"features\":{\"arbitrary\":[\"dep:arbitrary\"],\"default\":[\"std\",\"unicode\"],\"std\":[],\"unicode\":[\"unicode-age\",\"unicode-bool\",\"unicode-case\",\"unicode-gencat\",\"unicode-perl\",\"unicode-script\",\"unicode-segment\"],\"unicode-age\":[],\"unicode-bool\":[],\"unicode-case\":[],\"unicode-gencat\":[],\"unicode-perl\":[],\"unicode-script\":[],\"unicode-segment\":[]}}", "regex_1.12.3": "{\"dependencies\":[{\"default_features\":false,\"name\":\"aho-corasick\",\"optional\":true,\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.69\"},{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"},{\"default_features\":false,\"features\":[\"atty\",\"humantime\",\"termcolor\"],\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.9.3\"},{\"default_features\":false,\"name\":\"memchr\",\"optional\":true,\"req\":\"^2.6.0\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.3\"},{\"default_features\":false,\"features\":[\"alloc\",\"syntax\",\"meta\",\"nfa-pikevm\"],\"name\":\"regex-automata\",\"req\":\"^0.4.12\"},{\"default_features\":false,\"name\":\"regex-syntax\",\"req\":\"^0.8.5\"},{\"kind\":\"dev\",\"name\":\"regex-test\",\"req\":\"^0.1.0\"}],\"features\":{\"default\":[\"std\",\"perf\",\"unicode\",\"regex-syntax/default\"],\"logging\":[\"aho-corasick?/logging\",\"memchr?/logging\",\"regex-automata/logging\"],\"pattern\":[],\"perf\":[\"perf-cache\",\"perf-dfa\",\"perf-onepass\",\"perf-backtrack\",\"perf-inline\",\"perf-literal\"],\"perf-backtrack\":[\"regex-automata/nfa-backtrack\"],\"perf-cache\":[],\"perf-dfa\":[\"regex-automata/hybrid\"],\"perf-dfa-full\":[\"regex-automata/dfa-build\",\"regex-automata/dfa-search\"],\"perf-inline\":[\"regex-automata/perf-inline\"],\"perf-literal\":[\"dep:aho-corasick\",\"dep:memchr\",\"regex-automata/perf-literal\"],\"perf-onepass\":[\"regex-automata/dfa-onepass\"],\"std\":[\"aho-corasick?/std\",\"memchr?/std\",\"regex-automata/std\",\"regex-syntax/std\"],\"unicode\":[\"unicode-age\",\"unicode-bool\",\"unicode-case\",\"unicode-gencat\",\"unicode-perl\",\"unicode-script\",\"unicode-segment\",\"regex-automata/unicode\",\"regex-syntax/unicode\"],\"unicode-age\":[\"regex-automata/unicode-age\",\"regex-syntax/unicode-age\"],\"unicode-bool\":[\"regex-automata/unicode-bool\",\"regex-syntax/unicode-bool\"],\"unicode-case\":[\"regex-automata/unicode-case\",\"regex-syntax/unicode-case\"],\"unicode-gencat\":[\"regex-automata/unicode-gencat\",\"regex-syntax/unicode-gencat\"],\"unicode-perl\":[\"regex-automata/unicode-perl\",\"regex-automata/unicode-word-boundary\",\"regex-syntax/unicode-perl\"],\"unicode-script\":[\"regex-automata/unicode-script\",\"regex-syntax/unicode-script\"],\"unicode-segment\":[\"regex-automata/unicode-segment\",\"regex-syntax/unicode-segment\"],\"unstable\":[\"pattern\"],\"use_std\":[\"std\"]}}", "reqwest_0.12.28": "{\"dependencies\":[{\"name\":\"base64\",\"req\":\"^0.22\"},{\"kind\":\"dev\",\"name\":\"brotli_crate\",\"package\":\"brotli\",\"req\":\"^8\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"bytes\",\"req\":\"^1.2\"},{\"name\":\"cookie_crate\",\"optional\":true,\"package\":\"cookie\",\"req\":\"^0.18.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"cookie_store\",\"optional\":true,\"req\":\"^0.22.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"encoding_rs\",\"optional\":true,\"req\":\"^0.8\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.10\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"flate2\",\"req\":\"^1.0.13\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"futures-channel\",\"optional\":true,\"req\":\"^0.3\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"name\":\"futures-core\",\"req\":\"^0.3.28\"},{\"default_features\":false,\"name\":\"futures-util\",\"optional\":true,\"req\":\"^0.3.28\"},{\"default_features\":false,\"features\":[\"std\",\"alloc\"],\"kind\":\"dev\",\"name\":\"futures-util\",\"req\":\"^0.3.28\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"h2\",\"optional\":true,\"req\":\"^0.4\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"h3\",\"optional\":true,\"req\":\"^0.0.8\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"h3-quinn\",\"optional\":true,\"req\":\"^0.0.10\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"tokio\"],\"name\":\"hickory-resolver\",\"optional\":true,\"req\":\"^0.25\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"http\",\"req\":\"^1.1\"},{\"name\":\"http-body\",\"req\":\"^1\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"http-body-util\",\"req\":\"^0.1.2\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"http1\",\"client\"],\"name\":\"hyper\",\"req\":\"^1.1\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"http1\",\"http2\",\"client\",\"server\"],\"kind\":\"dev\",\"name\":\"hyper\",\"req\":\"^1.1.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"http1\",\"tls12\"],\"name\":\"hyper-rustls\",\"optional\":true,\"req\":\"^0.27.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"hyper-tls\",\"optional\":true,\"req\":\"^0.6\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"http1\",\"client\",\"client-legacy\",\"client-proxy\",\"tokio\"],\"name\":\"hyper-util\",\"req\":\"^0.1.12\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"http1\",\"http2\",\"client\",\"client-legacy\",\"server-auto\",\"server-graceful\",\"tokio\"],\"kind\":\"dev\",\"name\":\"hyper-util\",\"req\":\"^0.1.12\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"js-sys\",\"req\":\"^0.3.77\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0\"},{\"name\":\"log\",\"req\":\"^0.4.17\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"mime\",\"optional\":true,\"req\":\"^0.3.16\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"name\":\"mime_guess\",\"optional\":true,\"req\":\"^2.0\"},{\"name\":\"native-tls-crate\",\"optional\":true,\"package\":\"native-tls\",\"req\":\"^0.2.10\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"num_cpus\",\"req\":\"^1.0\"},{\"name\":\"once_cell\",\"optional\":true,\"req\":\"^1.18\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"percent-encoding\",\"req\":\"^2.3\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.11\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"rustls\",\"runtime-tokio\"],\"name\":\"quinn\",\"optional\":true,\"req\":\"^0.11.1\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"std\",\"tls12\"],\"name\":\"rustls\",\"optional\":true,\"req\":\"^0.23.4\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"rustls-native-certs\",\"optional\":true,\"req\":\"^0.8.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"features\":[\"std\"],\"name\":\"rustls-pki-types\",\"optional\":true,\"req\":\"^1.9.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"serde_json\",\"req\":\"^1.0\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"serde_urlencoded\",\"req\":\"^0.7.1\"},{\"features\":[\"futures\"],\"name\":\"sync_wrapper\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"net\",\"time\"],\"name\":\"tokio\",\"req\":\"^1.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"macros\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"tokio-native-tls\",\"optional\":true,\"req\":\"^0.3.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"tls12\"],\"name\":\"tokio-rustls\",\"optional\":true,\"req\":\"^0.26\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"io\"],\"name\":\"tokio-util\",\"optional\":true,\"req\":\"^0.7.9\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"retry\",\"timeout\",\"util\"],\"name\":\"tower\",\"req\":\"^0.5.2\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"features\":[\"limit\"],\"kind\":\"dev\",\"name\":\"tower\",\"req\":\"^0.5.2\"},{\"default_features\":false,\"features\":[\"follow-redirect\"],\"name\":\"tower-http\",\"req\":\"^0.6.8\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"tower-service\",\"req\":\"^0.3\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"url\",\"req\":\"^2.4\"},{\"name\":\"wasm-bindgen\",\"req\":\"^0.2.89\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"features\":[\"serde-serialize\"],\"kind\":\"dev\",\"name\":\"wasm-bindgen\",\"req\":\"^0.2.89\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"wasm-bindgen-futures\",\"req\":\"^0.4.18\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"wasm-streams\",\"optional\":true,\"req\":\"^0.4\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"features\":[\"AbortController\",\"AbortSignal\",\"Headers\",\"Request\",\"RequestInit\",\"RequestMode\",\"Response\",\"Window\",\"FormData\",\"Blob\",\"BlobPropertyBag\",\"ServiceWorkerGlobalScope\",\"RequestCredentials\",\"File\",\"ReadableStream\",\"RequestCache\"],\"name\":\"web-sys\",\"req\":\"^0.3.28\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"webpki-roots\",\"optional\":true,\"req\":\"^1\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"kind\":\"dev\",\"name\":\"zstd_crate\",\"package\":\"zstd\",\"req\":\"^0.13\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"}],\"features\":{\"__rustls\":[\"dep:hyper-rustls\",\"dep:tokio-rustls\",\"dep:rustls\",\"__tls\"],\"__rustls-ring\":[\"hyper-rustls?/ring\",\"tokio-rustls?/ring\",\"rustls?/ring\",\"quinn?/ring\"],\"__tls\":[\"dep:rustls-pki-types\",\"tokio/io-util\"],\"blocking\":[\"dep:futures-channel\",\"futures-channel?/sink\",\"dep:futures-util\",\"futures-util?/io\",\"futures-util?/sink\",\"tokio/sync\"],\"brotli\":[\"tower-http/decompression-br\"],\"charset\":[\"dep:encoding_rs\",\"dep:mime\"],\"cookies\":[\"dep:cookie_crate\",\"dep:cookie_store\"],\"default\":[\"default-tls\",\"charset\",\"http2\",\"system-proxy\"],\"default-tls\":[\"dep:hyper-tls\",\"dep:native-tls-crate\",\"__tls\",\"dep:tokio-native-tls\"],\"deflate\":[\"tower-http/decompression-deflate\"],\"gzip\":[\"tower-http/decompression-gzip\"],\"hickory-dns\":[\"dep:hickory-resolver\",\"dep:once_cell\"],\"http2\":[\"h2\",\"hyper/http2\",\"hyper-util/http2\",\"hyper-rustls?/http2\"],\"http3\":[\"rustls-tls-manual-roots\",\"dep:h3\",\"dep:h3-quinn\",\"dep:quinn\",\"tokio/macros\"],\"json\":[\"dep:serde_json\"],\"macos-system-configuration\":[\"system-proxy\"],\"multipart\":[\"dep:mime_guess\",\"dep:futures-util\"],\"native-tls\":[\"default-tls\"],\"native-tls-alpn\":[\"native-tls\",\"native-tls-crate?/alpn\",\"hyper-tls?/alpn\"],\"native-tls-vendored\":[\"native-tls\",\"native-tls-crate?/vendored\"],\"rustls-tls\":[\"rustls-tls-webpki-roots\"],\"rustls-tls-manual-roots\":[\"rustls-tls-manual-roots-no-provider\",\"__rustls-ring\"],\"rustls-tls-manual-roots-no-provider\":[\"__rustls\"],\"rustls-tls-native-roots\":[\"rustls-tls-native-roots-no-provider\",\"__rustls-ring\"],\"rustls-tls-native-roots-no-provider\":[\"dep:rustls-native-certs\",\"hyper-rustls?/native-tokio\",\"__rustls\"],\"rustls-tls-no-provider\":[\"rustls-tls-manual-roots-no-provider\"],\"rustls-tls-webpki-roots\":[\"rustls-tls-webpki-roots-no-provider\",\"__rustls-ring\"],\"rustls-tls-webpki-roots-no-provider\":[\"dep:webpki-roots\",\"hyper-rustls?/webpki-tokio\",\"__rustls\"],\"socks\":[],\"stream\":[\"tokio/fs\",\"dep:futures-util\",\"dep:tokio-util\",\"dep:wasm-streams\"],\"system-proxy\":[\"hyper-util/client-proxy-system\"],\"trust-dns\":[],\"zstd\":[\"tower-http/decompression-zstd\"]}}", @@ -1202,10 +1243,13 @@ "rustc-demangle_0.1.27": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"}],\"features\":{\"compiler_builtins\":[],\"rustc-dep-of-std\":[\"core\"],\"std\":[]}}", "rustc-hash_1.1.0": "{\"dependencies\":[],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "rustc-hash_2.1.1": "{\"dependencies\":[{\"name\":\"rand\",\"optional\":true,\"req\":\"^0.8\"}],\"features\":{\"default\":[\"std\"],\"nightly\":[],\"rand\":[\"dep:rand\",\"std\"],\"std\":[]}}", + "rustc_apfloat_0.2.3+llvm-462a31f5a5ab": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2.6.0\"},{\"features\":[\"html_reports\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5.1\"},{\"features\":[\"const_generics\",\"union\"],\"name\":\"smallvec\",\"req\":\"^1.11.0\"}],\"features\":{}}", "rustc_version_0.4.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"},{\"name\":\"semver\",\"req\":\"^1.0\"}],\"features\":{}}", + "rustfix_0.8.7": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.86\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.5.0\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"req\":\"^1.0.204\"},{\"name\":\"serde_json\",\"req\":\"^1.0.120\"},{\"kind\":\"dev\",\"name\":\"similar\",\"req\":\"^2.6.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.10.1\"},{\"name\":\"thiserror\",\"req\":\"^1.0.63\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"req\":\"^0.1.40\"},{\"features\":[\"env-filter\"],\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3.18\"}],\"features\":{}}", "rusticata-macros_4.1.0": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"std\"],\"name\":\"nom\",\"req\":\"^7.0\"}],\"features\":{}}", "rustix_0.38.44": "{\"dependencies\":[{\"default_features\":false,\"name\":\"bitflags\",\"req\":\"^2.4.0\"},{\"name\":\"compiler_builtins\",\"optional\":true,\"req\":\"^0.1.49\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4\",\"target\":\"cfg(all(criterion, not(any(target_os = \\\"emscripten\\\", target_os = \\\"wasi\\\"))))\"},{\"kind\":\"dev\",\"name\":\"flate2\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"itoa\",\"optional\":true,\"req\":\"^1.0.13\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.161\",\"target\":\"cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", target_arch = \\\"s390x\\\"), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\"},{\"default_features\":false,\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.161\",\"target\":\"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", target_arch = \\\"s390x\\\"), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.161\"},{\"default_features\":false,\"name\":\"libc_errno\",\"package\":\"errno\",\"req\":\"^0.3.10\",\"target\":\"cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", target_arch = \\\"s390x\\\"), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\"},{\"default_features\":false,\"name\":\"libc_errno\",\"package\":\"errno\",\"req\":\"^0.3.10\",\"target\":\"cfg(windows)\"},{\"default_features\":false,\"name\":\"libc_errno\",\"optional\":true,\"package\":\"errno\",\"req\":\"^0.3.10\",\"target\":\"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", target_arch = \\\"s390x\\\"), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"libc_errno\",\"package\":\"errno\",\"req\":\"^0.3.10\"},{\"default_features\":false,\"features\":[\"general\",\"ioctl\",\"no_std\"],\"name\":\"linux-raw-sys\",\"req\":\"^0.4.14\",\"target\":\"cfg(all(any(target_os = \\\"android\\\", target_os = \\\"linux\\\"), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", target_arch = \\\"s390x\\\"), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\"},{\"default_features\":false,\"features\":[\"general\",\"errno\",\"ioctl\",\"no_std\",\"elf\"],\"name\":\"linux-raw-sys\",\"req\":\"^0.4.14\",\"target\":\"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", target_arch = \\\"s390x\\\"), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\"},{\"kind\":\"dev\",\"name\":\"memoffset\",\"req\":\"^0.9.0\"},{\"name\":\"once_cell\",\"optional\":true,\"req\":\"^1.5.2\",\"target\":\"cfg(any(target_os = \\\"android\\\", target_os = \\\"linux\\\"))\"},{\"name\":\"rustc-std-workspace-alloc\",\"optional\":true,\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"serial_test\",\"req\":\"^2.0.0\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.5.0\"},{\"features\":[\"Win32_Foundation\",\"Win32_Networking_WinSock\",\"Win32_NetworkManagement_IpHelper\",\"Win32_System_Threading\"],\"name\":\"windows-sys\",\"req\":\">=0.52, <=0.59\",\"target\":\"cfg(windows)\"}],\"features\":{\"all-apis\":[\"event\",\"fs\",\"io_uring\",\"mm\",\"mount\",\"net\",\"param\",\"pipe\",\"process\",\"procfs\",\"pty\",\"rand\",\"runtime\",\"shm\",\"stdio\",\"system\",\"termios\",\"thread\",\"time\"],\"alloc\":[],\"cc\":[],\"default\":[\"std\",\"use-libc-auxv\"],\"event\":[],\"fs\":[],\"io_uring\":[\"event\",\"fs\",\"net\",\"linux-raw-sys/io_uring\"],\"libc-extra-traits\":[\"libc?/extra_traits\"],\"linux_4_11\":[],\"linux_latest\":[\"linux_4_11\"],\"mm\":[],\"mount\":[],\"net\":[\"linux-raw-sys/net\",\"linux-raw-sys/netlink\",\"linux-raw-sys/if_ether\",\"linux-raw-sys/xdp\"],\"param\":[\"fs\"],\"pipe\":[],\"process\":[\"linux-raw-sys/prctl\"],\"procfs\":[\"once_cell\",\"itoa\",\"fs\"],\"pty\":[\"itoa\",\"fs\"],\"rand\":[],\"runtime\":[\"linux-raw-sys/prctl\"],\"rustc-dep-of-std\":[\"core\",\"rustc-std-workspace-alloc\",\"compiler_builtins\",\"linux-raw-sys/rustc-dep-of-std\",\"bitflags/rustc-dep-of-std\",\"compiler_builtins?/rustc-dep-of-std\"],\"shm\":[\"fs\"],\"std\":[\"bitflags/std\",\"alloc\",\"libc?/std\",\"libc_errno?/std\",\"libc-extra-traits\"],\"stdio\":[],\"system\":[\"linux-raw-sys/system\"],\"termios\":[],\"thread\":[\"linux-raw-sys/prctl\"],\"time\":[],\"try_close\":[],\"use-explicitly-provided-auxv\":[],\"use-libc\":[\"libc_errno\",\"libc\",\"libc-extra-traits\"],\"use-libc-auxv\":[]}}", "rustix_1.1.3": "{\"dependencies\":[{\"default_features\":false,\"name\":\"bitflags\",\"req\":\"^2.4.0\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4\",\"target\":\"cfg(all(criterion, not(any(target_os = \\\"emscripten\\\", target_os = \\\"wasi\\\"))))\"},{\"kind\":\"dev\",\"name\":\"flate2\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.177\",\"target\":\"cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\"},{\"default_features\":false,\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.177\",\"target\":\"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.171\"},{\"default_features\":false,\"name\":\"libc_errno\",\"package\":\"errno\",\"req\":\"^0.3.10\",\"target\":\"cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\"},{\"default_features\":false,\"name\":\"libc_errno\",\"package\":\"errno\",\"req\":\"^0.3.10\",\"target\":\"cfg(windows)\"},{\"default_features\":false,\"name\":\"libc_errno\",\"optional\":true,\"package\":\"errno\",\"req\":\"^0.3.10\",\"target\":\"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"libc_errno\",\"package\":\"errno\",\"req\":\"^0.3.10\"},{\"default_features\":false,\"features\":[\"general\",\"ioctl\",\"no_std\"],\"name\":\"linux-raw-sys\",\"req\":\"^0.11.0\",\"target\":\"cfg(all(any(target_os = \\\"linux\\\", target_os = \\\"android\\\"), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\"},{\"default_features\":false,\"features\":[\"auxvec\",\"general\",\"errno\",\"ioctl\",\"no_std\",\"elf\"],\"name\":\"linux-raw-sys\",\"req\":\"^0.11.0\",\"target\":\"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\"},{\"kind\":\"dev\",\"name\":\"memoffset\",\"req\":\"^0.9.0\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"^1.20.3\",\"target\":\"cfg(windows)\"},{\"name\":\"rustc-std-workspace-alloc\",\"optional\":true,\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"serial_test\",\"req\":\"^2.0.0\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.5.0\"},{\"features\":[\"Win32_Foundation\",\"Win32_Networking_WinSock\"],\"name\":\"windows-sys\",\"req\":\">=0.52, <0.62\",\"target\":\"cfg(windows)\"}],\"features\":{\"all-apis\":[\"event\",\"fs\",\"io_uring\",\"mm\",\"mount\",\"net\",\"param\",\"pipe\",\"process\",\"pty\",\"rand\",\"runtime\",\"shm\",\"stdio\",\"system\",\"termios\",\"thread\",\"time\"],\"alloc\":[],\"default\":[\"std\"],\"event\":[],\"fs\":[],\"io_uring\":[\"event\",\"fs\",\"net\",\"thread\",\"linux-raw-sys/io_uring\"],\"linux_4_11\":[],\"linux_5_1\":[\"linux_4_11\"],\"linux_5_11\":[\"linux_5_1\"],\"linux_latest\":[\"linux_5_11\"],\"mm\":[],\"mount\":[],\"net\":[\"linux-raw-sys/net\",\"linux-raw-sys/netlink\",\"linux-raw-sys/if_ether\",\"linux-raw-sys/xdp\"],\"param\":[],\"pipe\":[],\"process\":[\"linux-raw-sys/prctl\"],\"pty\":[\"fs\"],\"rand\":[],\"runtime\":[\"linux-raw-sys/prctl\"],\"rustc-dep-of-std\":[\"core\",\"rustc-std-workspace-alloc\",\"linux-raw-sys/rustc-dep-of-std\",\"bitflags/rustc-dep-of-std\"],\"shm\":[\"fs\"],\"std\":[\"bitflags/std\",\"alloc\",\"libc?/std\",\"libc_errno?/std\"],\"stdio\":[],\"system\":[\"linux-raw-sys/system\"],\"termios\":[],\"thread\":[\"linux-raw-sys/prctl\"],\"time\":[],\"try_close\":[],\"use-explicitly-provided-auxv\":[],\"use-libc\":[\"libc_errno\",\"libc\"],\"use-libc-auxv\":[]}}", + "rustix_1.1.4": "{\"dependencies\":[{\"default_features\":false,\"name\":\"bitflags\",\"req\":\"^2.4.0\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.4\",\"target\":\"cfg(all(criterion, not(any(target_os = \\\"emscripten\\\", target_os = \\\"wasi\\\"))))\"},{\"kind\":\"dev\",\"name\":\"flate2\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.182\",\"target\":\"cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\"},{\"default_features\":false,\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.182\",\"target\":\"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.171\"},{\"default_features\":false,\"name\":\"libc_errno\",\"package\":\"errno\",\"req\":\"^0.3.10\",\"target\":\"cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\"},{\"default_features\":false,\"name\":\"libc_errno\",\"package\":\"errno\",\"req\":\"^0.3.10\",\"target\":\"cfg(windows)\"},{\"default_features\":false,\"name\":\"libc_errno\",\"optional\":true,\"package\":\"errno\",\"req\":\"^0.3.10\",\"target\":\"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"libc_errno\",\"package\":\"errno\",\"req\":\"^0.3.10\"},{\"default_features\":false,\"features\":[\"general\",\"ioctl\",\"no_std\"],\"name\":\"linux-raw-sys\",\"req\":\"^0.12\",\"target\":\"cfg(all(any(target_os = \\\"linux\\\", target_os = \\\"android\\\"), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\"},{\"default_features\":false,\"features\":[\"auxvec\",\"general\",\"errno\",\"ioctl\",\"no_std\",\"elf\"],\"name\":\"linux-raw-sys\",\"req\":\"^0.12\",\"target\":\"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\"},{\"kind\":\"dev\",\"name\":\"memoffset\",\"req\":\"^0.9.0\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"^1.20.3\",\"target\":\"cfg(windows)\"},{\"name\":\"rustc-std-workspace-alloc\",\"optional\":true,\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"serial_test\",\"req\":\"^2.0.0\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.5.0\"},{\"features\":[\"Win32_Foundation\",\"Win32_Networking_WinSock\"],\"name\":\"windows-sys\",\"req\":\">=0.52, <0.62\",\"target\":\"cfg(windows)\"}],\"features\":{\"all-apis\":[\"event\",\"fs\",\"io_uring\",\"mm\",\"mount\",\"net\",\"param\",\"pipe\",\"process\",\"pty\",\"rand\",\"runtime\",\"shm\",\"stdio\",\"system\",\"termios\",\"thread\",\"time\"],\"alloc\":[],\"default\":[\"std\"],\"event\":[],\"fs\":[],\"io_uring\":[\"event\",\"fs\",\"net\",\"thread\",\"linux-raw-sys/io_uring\"],\"linux_4_11\":[],\"linux_5_1\":[\"linux_4_11\"],\"linux_5_11\":[\"linux_5_1\"],\"linux_latest\":[\"linux_5_11\"],\"mm\":[],\"mount\":[],\"net\":[\"linux-raw-sys/net\",\"linux-raw-sys/netlink\",\"linux-raw-sys/if_ether\",\"linux-raw-sys/xdp\"],\"param\":[],\"pipe\":[],\"process\":[\"linux-raw-sys/prctl\"],\"pty\":[\"fs\"],\"rand\":[],\"runtime\":[\"linux-raw-sys/prctl\"],\"rustc-dep-of-std\":[\"core\",\"rustc-std-workspace-alloc\",\"linux-raw-sys/rustc-dep-of-std\",\"bitflags/rustc-dep-of-std\"],\"shm\":[\"fs\"],\"std\":[\"bitflags/std\",\"alloc\",\"libc?/std\",\"libc_errno?/std\"],\"stdio\":[],\"system\":[\"linux-raw-sys/system\"],\"termios\":[],\"thread\":[\"linux-raw-sys/prctl\"],\"time\":[],\"try_close\":[],\"use-explicitly-provided-auxv\":[],\"use-libc\":[\"libc_errno\",\"libc\"],\"use-libc-auxv\":[]}}", "rustls-native-certs_0.8.3": "{\"dependencies\":[{\"name\":\"openssl-probe\",\"req\":\"^0.2\",\"target\":\"cfg(all(unix, not(target_os = \\\"macos\\\")))\"},{\"features\":[\"std\"],\"name\":\"pki-types\",\"package\":\"rustls-pki-types\",\"req\":\"^1.10\"},{\"kind\":\"dev\",\"name\":\"ring\",\"req\":\"^0.17\"},{\"kind\":\"dev\",\"name\":\"rustls\",\"req\":\"^0.23\"},{\"kind\":\"dev\",\"name\":\"rustls-webpki\",\"req\":\"^0.103\"},{\"name\":\"schannel\",\"req\":\"^0.1\",\"target\":\"cfg(windows)\"},{\"name\":\"security-framework\",\"req\":\"^3\",\"target\":\"cfg(target_os = \\\"macos\\\")\"},{\"kind\":\"dev\",\"name\":\"serial_test\",\"req\":\"^3\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.5\"},{\"kind\":\"dev\",\"name\":\"untrusted\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"webpki-roots\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"x509-parser\",\"req\":\"^0.18\"}],\"features\":{}}", "rustls-pki-types_1.14.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"crabgrind\",\"req\":\"=0.1.9\",\"target\":\"cfg(all(target_os = \\\"linux\\\", target_arch = \\\"x86_64\\\"))\"},{\"name\":\"web-time\",\"optional\":true,\"req\":\"^1\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", target_os = \\\"unknown\\\"))\"},{\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"alloc\":[\"dep:zeroize\"],\"default\":[\"alloc\"],\"std\":[\"alloc\"],\"web\":[\"web-time\"]}}", "rustls-webpki_0.103.10": "{\"dependencies\":[{\"default_features\":false,\"name\":\"aws-lc-rs\",\"optional\":true,\"req\":\"^1.14\"},{\"kind\":\"dev\",\"name\":\"base64\",\"req\":\"^0.22\"},{\"kind\":\"dev\",\"name\":\"bencher\",\"req\":\"^0.1.5\"},{\"kind\":\"dev\",\"name\":\"bzip2\",\"req\":\"^0.6\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"^1.17.2\"},{\"default_features\":false,\"name\":\"pki-types\",\"package\":\"rustls-pki-types\",\"req\":\"^1.12\"},{\"default_features\":false,\"features\":[\"aws_lc_rs\"],\"kind\":\"dev\",\"name\":\"rcgen\",\"req\":\"^0.14.2\"},{\"default_features\":false,\"name\":\"ring\",\"optional\":true,\"req\":\"^0.17\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"untrusted\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"x509-parser\",\"req\":\"^0.18.1\"}],\"features\":{\"alloc\":[\"ring?/alloc\",\"pki-types/alloc\"],\"aws-lc-rs\":[\"dep:aws-lc-rs\",\"aws-lc-rs/aws-lc-sys\",\"aws-lc-rs/prebuilt-nasm\"],\"aws-lc-rs-fips\":[\"dep:aws-lc-rs\",\"aws-lc-rs/fips\"],\"aws-lc-rs-unstable\":[\"aws-lc-rs\",\"aws-lc-rs/unstable\"],\"default\":[\"std\"],\"ring\":[\"dep:ring\"],\"std\":[\"alloc\",\"pki-types/std\"]}}", @@ -1318,6 +1362,7 @@ "supports-color_3.0.2": "{\"dependencies\":[{\"name\":\"is_ci\",\"req\":\"^1.2.0\"}],\"features\":{}}", "syn_1.0.109": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"flate2\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"insta\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.46\"},{\"default_features\":false,\"name\":\"quote\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"ref-cast\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.0\"},{\"features\":[\"blocking\"],\"kind\":\"dev\",\"name\":\"reqwest\",\"req\":\"^0.11\"},{\"kind\":\"dev\",\"name\":\"syn-test-suite\",\"req\":\"^0\"},{\"kind\":\"dev\",\"name\":\"tar\",\"req\":\"^0.4.16\"},{\"kind\":\"dev\",\"name\":\"termcolor\",\"req\":\"^1.0\"},{\"name\":\"unicode-ident\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.1\"}],\"features\":{\"clone-impls\":[],\"default\":[\"derive\",\"parsing\",\"printing\",\"clone-impls\",\"proc-macro\"],\"derive\":[],\"extra-traits\":[],\"fold\":[],\"full\":[],\"parsing\":[],\"printing\":[\"quote\"],\"proc-macro\":[\"proc-macro2/proc-macro\",\"quote/proc-macro\"],\"test\":[\"syn-test-suite/all-features\"],\"visit\":[],\"visit-mut\":[]}}", "syn_2.0.114": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"flate2\",\"req\":\"^1\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"insta\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.91\"},{\"default_features\":false,\"name\":\"quote\",\"optional\":true,\"req\":\"^1.0.35\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"ref-cast\",\"req\":\"^1\"},{\"features\":[\"blocking\"],\"kind\":\"dev\",\"name\":\"reqwest\",\"req\":\"^0.13\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"syn-test-suite\",\"req\":\"^0\"},{\"kind\":\"dev\",\"name\":\"tar\",\"req\":\"^0.4.16\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"termcolor\",\"req\":\"^1\"},{\"name\":\"unicode-ident\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.3.2\",\"target\":\"cfg(not(miri))\"}],\"features\":{\"clone-impls\":[],\"default\":[\"derive\",\"parsing\",\"printing\",\"clone-impls\",\"proc-macro\"],\"derive\":[],\"extra-traits\":[],\"fold\":[],\"full\":[],\"parsing\":[],\"printing\":[\"dep:quote\"],\"proc-macro\":[\"proc-macro2/proc-macro\",\"quote?/proc-macro\"],\"test\":[\"syn-test-suite/all-features\"],\"visit\":[],\"visit-mut\":[]}}", + "syn_2.0.117": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"flate2\",\"req\":\"^1\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"insta\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.91\"},{\"default_features\":false,\"name\":\"quote\",\"optional\":true,\"req\":\"^1.0.35\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"ref-cast\",\"req\":\"^1\"},{\"features\":[\"blocking\"],\"kind\":\"dev\",\"name\":\"reqwest\",\"req\":\"^0.13\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"syn-test-suite\",\"req\":\"^0\"},{\"kind\":\"dev\",\"name\":\"tar\",\"req\":\"^0.4.16\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"termcolor\",\"req\":\"^1\"},{\"name\":\"unicode-ident\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.3.2\",\"target\":\"cfg(not(miri))\"}],\"features\":{\"clone-impls\":[],\"default\":[\"derive\",\"parsing\",\"printing\",\"clone-impls\",\"proc-macro\"],\"derive\":[],\"extra-traits\":[],\"fold\":[],\"full\":[],\"parsing\":[],\"printing\":[\"dep:quote\"],\"proc-macro\":[\"proc-macro2/proc-macro\",\"quote?/proc-macro\"],\"test\":[\"syn-test-suite/all-features\"],\"visit\":[],\"visit-mut\":[]}}", "sync_wrapper_1.0.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"futures\",\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"futures-core\",\"optional\":true,\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"pin-project-lite\",\"req\":\"^0.2.7\"}],\"features\":{\"futures\":[\"futures-core\"]}}", "synstructure_0.13.2": "{\"dependencies\":[{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.60\"},{\"default_features\":false,\"name\":\"quote\",\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"derive\",\"parsing\",\"printing\",\"clone-impls\",\"visit\",\"extra-traits\"],\"name\":\"syn\",\"req\":\"^2\"},{\"kind\":\"dev\",\"name\":\"synstructure_test_traits\",\"req\":\"^0.1\"}],\"features\":{\"default\":[\"proc-macro\"],\"proc-macro\":[\"proc-macro2/proc-macro\",\"syn/proc-macro\",\"quote/proc-macro\"]}}", "syntect_5.3.0": "{\"dependencies\":[{\"name\":\"bincode\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"html_reports\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.3\"},{\"name\":\"fancy-regex\",\"optional\":true,\"req\":\"^0.16.2\"},{\"name\":\"flate2\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"fnv\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"getopts\",\"req\":\"^0.2\"},{\"name\":\"once_cell\",\"req\":\"^1.8\"},{\"default_features\":false,\"name\":\"onig\",\"optional\":true,\"req\":\"^6.5.1\"},{\"name\":\"plist\",\"optional\":true,\"req\":\"^1.3\"},{\"kind\":\"dev\",\"name\":\"pretty_assertions\",\"req\":\"^0.6\"},{\"kind\":\"dev\",\"name\":\"public-api\",\"req\":\"^0.50.1\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.0\"},{\"name\":\"regex-syntax\",\"optional\":true,\"req\":\"^0.8\"},{\"kind\":\"dev\",\"name\":\"rustdoc-json\",\"req\":\"^0.9.7\"},{\"kind\":\"dev\",\"name\":\"rustup-toolchain\",\"req\":\"^0.1.5\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde_derive\",\"req\":\"^1.0\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"thiserror\",\"req\":\"^2.0.12\"},{\"name\":\"walkdir\",\"req\":\"^2.0\"},{\"name\":\"yaml-rust\",\"optional\":true,\"req\":\"^0.4.5\"}],\"features\":{\"default\":[\"default-onig\"],\"default-fancy\":[\"parsing\",\"default-syntaxes\",\"default-themes\",\"html\",\"plist-load\",\"yaml-load\",\"dump-load\",\"dump-create\",\"regex-fancy\"],\"default-onig\":[\"parsing\",\"default-syntaxes\",\"default-themes\",\"html\",\"plist-load\",\"yaml-load\",\"dump-load\",\"dump-create\",\"regex-onig\"],\"default-syntaxes\":[\"parsing\",\"dump-load\"],\"default-themes\":[\"dump-load\"],\"dump-create\":[\"flate2\",\"bincode\"],\"dump-load\":[\"flate2\",\"bincode\"],\"html\":[\"parsing\"],\"metadata\":[\"parsing\",\"plist-load\",\"dep:serde_json\"],\"parsing\":[\"regex-syntax\",\"fnv\",\"dump-create\",\"dump-load\"],\"plist-load\":[\"plist\",\"dep:serde_json\"],\"regex-fancy\":[\"fancy-regex\"],\"regex-onig\":[\"onig\"],\"yaml-load\":[\"yaml-rust\",\"parsing\"]}}", @@ -1325,7 +1370,9 @@ "system-configuration-sys_0.6.0": "{\"dependencies\":[{\"name\":\"core-foundation-sys\",\"req\":\"^0.8\"},{\"name\":\"libc\",\"req\":\"^0.2.149\"}],\"features\":{}}", "system-configuration_0.6.1": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2\"},{\"name\":\"core-foundation\",\"req\":\"^0.9\"},{\"name\":\"system-configuration-sys\",\"req\":\"^0.6\"}],\"features\":{}}", "tagptr_0.2.0": "{\"dependencies\":[],\"features\":{}}", + "tar_0.4.44": "{\"dependencies\":[{\"name\":\"filetime\",\"req\":\"^0.2.8\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"},{\"name\":\"xattr\",\"optional\":true,\"req\":\"^1.1.3\",\"target\":\"cfg(unix)\"}],\"features\":{\"default\":[\"xattr\"]}}", "tempfile_3.24.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"},{\"name\":\"fastrand\",\"req\":\"^2.1.1\"},{\"default_features\":false,\"name\":\"getrandom\",\"optional\":true,\"req\":\"^0.3.0\",\"target\":\"cfg(any(unix, windows, target_os = \\\"wasi\\\"))\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"once_cell\",\"req\":\"^1.19.0\"},{\"features\":[\"fs\"],\"name\":\"rustix\",\"req\":\"^1.1.3\",\"target\":\"cfg(any(unix, target_os = \\\"wasi\\\"))\"},{\"features\":[\"Win32_Storage_FileSystem\",\"Win32_Foundation\"],\"name\":\"windows-sys\",\"req\":\">=0.52, <0.62\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[\"getrandom\"],\"nightly\":[]}}", + "tempfile_3.27.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3\"},{\"name\":\"fastrand\",\"req\":\"^2.1.1\"},{\"default_features\":false,\"name\":\"getrandom\",\"optional\":true,\"req\":\">=0.3.0, <0.5\",\"target\":\"cfg(any(unix, windows, target_os = \\\"wasi\\\"))\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"once_cell\",\"req\":\"^1.19.0\"},{\"features\":[\"fs\"],\"name\":\"rustix\",\"req\":\"^1.1.4\",\"target\":\"cfg(any(unix, target_os = \\\"wasi\\\"))\"},{\"features\":[\"Win32_Storage_FileSystem\",\"Win32_Foundation\"],\"name\":\"windows-sys\",\"req\":\">=0.52, <0.62\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[\"getrandom\"],\"nightly\":[]}}", "temporal_capi_0.1.2": "{\"dependencies\":[{\"default_features\":false,\"name\":\"diplomat\",\"req\":\"^0.14.0\"},{\"default_features\":false,\"name\":\"diplomat-runtime\",\"req\":\"^0.14.0\"},{\"default_features\":false,\"features\":[\"unstable\"],\"name\":\"icu_calendar\",\"req\":\"^2.1.0\"},{\"name\":\"icu_locale\",\"req\":\"^2.1.0\"},{\"default_features\":false,\"name\":\"num-traits\",\"req\":\"^0.2.19\"},{\"default_features\":false,\"name\":\"temporal_rs\",\"req\":\"^0.1.2\"},{\"name\":\"timezone_provider\",\"req\":\"^0.1.2\"},{\"name\":\"writeable\",\"req\":\"^0.6.0\"},{\"name\":\"zoneinfo64\",\"optional\":true,\"req\":\"^0.2.0\"}],\"features\":{\"compiled_data\":[\"temporal_rs/compiled_data\"],\"zoneinfo64\":[\"dep:zoneinfo64\",\"timezone_provider/zoneinfo64\"]}}", "temporal_rs_0.1.2": "{\"dependencies\":[{\"name\":\"core_maths\",\"req\":\"^0.1.1\"},{\"name\":\"iana-time-zone\",\"optional\":true,\"req\":\"^0.1.64\"},{\"default_features\":false,\"features\":[\"unstable\",\"compiled_data\"],\"name\":\"icu_calendar\",\"req\":\"^2.1.0\"},{\"name\":\"icu_locale\",\"req\":\"^2.1.0\"},{\"features\":[\"duration\"],\"name\":\"ixdtf\",\"req\":\"^0.6.4\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.28\"},{\"default_features\":false,\"name\":\"num-traits\",\"req\":\"^0.2.19\"},{\"name\":\"timezone_provider\",\"req\":\"^0.1.2\"},{\"name\":\"tinystr\",\"req\":\"^0.8.0\"},{\"name\":\"web-time\",\"optional\":true,\"req\":\"^1.1.0\"},{\"name\":\"writeable\",\"req\":\"^0.6.0\"}],\"features\":{\"compiled_data\":[\"tzdb\"],\"default\":[\"sys\"],\"float64_representable_durations\":[],\"log\":[\"dep:log\"],\"std\":[],\"sys\":[\"std\",\"compiled_data\",\"dep:web-time\",\"dep:iana-time-zone\"],\"tzdb\":[\"std\",\"timezone_provider/tzif\"]}}", "term_0.7.0": "{\"dependencies\":[{\"name\":\"dirs-next\",\"req\":\"^2\"},{\"name\":\"rustversion\",\"req\":\"^1\",\"target\":\"cfg(windows)\"},{\"features\":[\"consoleapi\",\"wincon\",\"handleapi\",\"fileapi\"],\"name\":\"winapi\",\"req\":\"^0.3\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[]}}", @@ -1337,6 +1384,7 @@ "test-case_3.3.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"insta\",\"req\":\"^1.12\"},{\"kind\":\"dev\",\"name\":\"itertools\",\"req\":\"^0.11\"},{\"name\":\"regex\",\"optional\":true,\"req\":\"^1.5\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.5\"},{\"default_features\":false,\"name\":\"test-case-macros\",\"req\":\"^3.2.1\"}],\"features\":{\"with-regex\":[\"regex\",\"test-case-macros/with-regex\"]}}", "test-log-macros_0.2.19": "{\"dependencies\":[{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.32\"},{\"default_features\":false,\"name\":\"quote\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"full\",\"parsing\",\"printing\",\"proc-macro\"],\"name\":\"syn\",\"req\":\"^2.0\"}],\"features\":{\"log\":[],\"trace\":[],\"unstable\":[]}}", "test-log_0.2.19": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"_lazy_static_unused\",\"package\":\"lazy_static\",\"req\":\"^1.0.2\"},{\"default_features\":false,\"name\":\"env_logger\",\"optional\":true,\"req\":\"^0.11\"},{\"kind\":\"dev\",\"name\":\"logging\",\"package\":\"log\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"rstest\",\"req\":\"^0.26\"},{\"kind\":\"dev\",\"name\":\"test-case\",\"req\":\"^3.1\"},{\"name\":\"test-log-macros\",\"req\":\"=0.2.19\"},{\"default_features\":false,\"features\":[\"rt-multi-thread\",\"macros\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.38\"},{\"kind\":\"dev\",\"name\":\"tracing\",\"req\":\"^0.1\"},{\"default_features\":false,\"features\":[\"env-filter\",\"fmt\"],\"name\":\"tracing-subscriber\",\"optional\":true,\"req\":\"^0.3.20\"}],\"features\":{\"color\":[\"env_logger?/auto-color\",\"tracing-subscriber?/ansi\"],\"default\":[\"log\",\"color\"],\"log\":[\"dep:env_logger\",\"test-log-macros/log\",\"tracing-subscriber?/tracing-log\"],\"trace\":[\"dep:tracing-subscriber\",\"test-log-macros/trace\"],\"unstable\":[\"test-log-macros/unstable\"]}}", + "tester_0.9.1": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1.0.0\"},{\"name\":\"getopts\",\"req\":\"^0.2\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"name\":\"num_cpus\",\"req\":\"^1.13.0\"},{\"name\":\"term\",\"req\":\"^0.7\"}],\"features\":{\"asm_black_box\":[],\"capture\":[]}}", "textwrap_0.11.0": "{\"dependencies\":[{\"features\":[\"embed_all\"],\"name\":\"hyphenation\",\"optional\":true,\"req\":\"^0.7.1\"},{\"kind\":\"dev\",\"name\":\"lipsum\",\"req\":\"^0.6\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.6\"},{\"kind\":\"dev\",\"name\":\"rand_xorshift\",\"req\":\"^0.1\"},{\"name\":\"term_size\",\"optional\":true,\"req\":\"^0.3.0\"},{\"name\":\"unicode-width\",\"req\":\"^0.1.3\"},{\"kind\":\"dev\",\"name\":\"version-sync\",\"req\":\"^0.6\"}],\"features\":{}}", "textwrap_0.16.2": "{\"dependencies\":[{\"features\":[\"embed_en-us\"],\"name\":\"hyphenation\",\"optional\":true,\"req\":\"^0.8.4\"},{\"name\":\"smawk\",\"optional\":true,\"req\":\"^0.3.2\"},{\"name\":\"terminal_size\",\"optional\":true,\"req\":\"^0.4.0\"},{\"kind\":\"dev\",\"name\":\"termion\",\"req\":\"^4.0.2\",\"target\":\"cfg(unix)\"},{\"kind\":\"dev\",\"name\":\"unic-emoji-char\",\"req\":\"^0.9.0\"},{\"name\":\"unicode-linebreak\",\"optional\":true,\"req\":\"^0.1.5\"},{\"name\":\"unicode-width\",\"optional\":true,\"req\":\"^0.2.0\"},{\"kind\":\"dev\",\"name\":\"version-sync\",\"req\":\"^0.9.5\"}],\"features\":{\"default\":[\"unicode-linebreak\",\"unicode-width\",\"smawk\"]}}", "thiserror-impl_1.0.69": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1.0.74\"},{\"name\":\"quote\",\"req\":\"^1.0.35\"},{\"name\":\"syn\",\"req\":\"^2.0.87\"}],\"features\":{}}", @@ -1364,10 +1412,12 @@ "tokio_1.49.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"async-stream\",\"req\":\"^0.3\"},{\"name\":\"backtrace\",\"optional\":true,\"req\":\"^0.3.58\",\"target\":\"cfg(all(tokio_unstable, target_os = \\\"linux\\\"))\"},{\"name\":\"bytes\",\"optional\":true,\"req\":\"^1.2.1\"},{\"features\":[\"async-await\"],\"kind\":\"dev\",\"name\":\"futures\",\"req\":\"^0.3.0\"},{\"kind\":\"dev\",\"name\":\"futures-concurrency\",\"req\":\"^7.6.3\"},{\"kind\":\"dev\",\"name\":\"futures-test\",\"req\":\"^0.3.31\"},{\"default_features\":false,\"name\":\"io-uring\",\"optional\":true,\"req\":\"^0.7.6\",\"target\":\"cfg(all(tokio_unstable, target_os = \\\"linux\\\"))\"},{\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.168\",\"target\":\"cfg(all(tokio_unstable, target_os = \\\"linux\\\"))\"},{\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.168\",\"target\":\"cfg(unix)\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.168\",\"target\":\"cfg(unix)\"},{\"features\":[\"futures\",\"checkpoint\"],\"kind\":\"dev\",\"name\":\"loom\",\"req\":\"^0.7\",\"target\":\"cfg(loom)\"},{\"default_features\":false,\"name\":\"mio\",\"optional\":true,\"req\":\"^1.0.1\"},{\"default_features\":false,\"features\":[\"os-poll\",\"os-ext\"],\"name\":\"mio\",\"optional\":true,\"req\":\"^1.0.1\",\"target\":\"cfg(all(tokio_unstable, target_os = \\\"linux\\\"))\"},{\"features\":[\"tokio\"],\"kind\":\"dev\",\"name\":\"mio-aio\",\"req\":\"^1\",\"target\":\"cfg(target_os = \\\"freebsd\\\")\"},{\"kind\":\"dev\",\"name\":\"mockall\",\"req\":\"^0.13.0\"},{\"default_features\":false,\"features\":[\"aio\",\"fs\",\"socket\"],\"kind\":\"dev\",\"name\":\"nix\",\"req\":\"^0.29.0\",\"target\":\"cfg(unix)\"},{\"name\":\"parking_lot\",\"optional\":true,\"req\":\"^0.12.0\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.11\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\",\"target\":\"cfg(not(target_family = \\\"wasm\\\"))\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9\",\"target\":\"cfg(not(all(target_family = \\\"wasm\\\", target_os = \\\"unknown\\\")))\"},{\"name\":\"signal-hook-registry\",\"optional\":true,\"req\":\"^1.1.1\",\"target\":\"cfg(unix)\"},{\"name\":\"slab\",\"optional\":true,\"req\":\"^0.4.9\",\"target\":\"cfg(all(tokio_unstable, target_os = \\\"linux\\\"))\"},{\"features\":[\"all\"],\"name\":\"socket2\",\"optional\":true,\"req\":\"^0.6.0\",\"target\":\"cfg(not(target_family = \\\"wasm\\\"))\"},{\"kind\":\"dev\",\"name\":\"socket2\",\"req\":\"^0.6.0\",\"target\":\"cfg(not(target_family = \\\"wasm\\\"))\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.1.0\",\"target\":\"cfg(not(target_family = \\\"wasm\\\"))\"},{\"name\":\"tokio-macros\",\"optional\":true,\"req\":\"~2.6.0\"},{\"kind\":\"dev\",\"name\":\"tokio-stream\",\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"tokio-test\",\"req\":\"^0.4.0\"},{\"features\":[\"rt\"],\"kind\":\"dev\",\"name\":\"tokio-util\",\"req\":\"^0.7\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1.29\",\"target\":\"cfg(tokio_unstable)\"},{\"kind\":\"dev\",\"name\":\"tracing-mock\",\"req\":\"=0.1.0-beta.1\",\"target\":\"cfg(all(tokio_unstable, target_has_atomic = \\\"64\\\"))\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3.0\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", not(target_os = \\\"wasi\\\")))\"},{\"name\":\"windows-sys\",\"optional\":true,\"req\":\"^0.61\",\"target\":\"cfg(windows)\"},{\"features\":[\"Win32_Foundation\",\"Win32_Security_Authorization\"],\"kind\":\"dev\",\"name\":\"windows-sys\",\"req\":\"^0.61\",\"target\":\"cfg(windows)\"}],\"features\":{\"default\":[],\"fs\":[],\"full\":[\"fs\",\"io-util\",\"io-std\",\"macros\",\"net\",\"parking_lot\",\"process\",\"rt\",\"rt-multi-thread\",\"signal\",\"sync\",\"time\"],\"io-std\":[],\"io-uring\":[\"dep:io-uring\",\"libc\",\"mio/os-poll\",\"mio/os-ext\",\"dep:slab\"],\"io-util\":[\"bytes\"],\"macros\":[\"tokio-macros\"],\"net\":[\"libc\",\"mio/os-poll\",\"mio/os-ext\",\"mio/net\",\"socket2\",\"windows-sys/Win32_Foundation\",\"windows-sys/Win32_Security\",\"windows-sys/Win32_Storage_FileSystem\",\"windows-sys/Win32_System_Pipes\",\"windows-sys/Win32_System_SystemServices\"],\"process\":[\"bytes\",\"libc\",\"mio/os-poll\",\"mio/os-ext\",\"mio/net\",\"signal-hook-registry\",\"windows-sys/Win32_Foundation\",\"windows-sys/Win32_System_Threading\",\"windows-sys/Win32_System_WindowsProgramming\"],\"rt\":[],\"rt-multi-thread\":[\"rt\"],\"signal\":[\"libc\",\"mio/os-poll\",\"mio/net\",\"mio/os-ext\",\"signal-hook-registry\",\"windows-sys/Win32_Foundation\",\"windows-sys/Win32_System_Console\"],\"sync\":[],\"taskdump\":[\"dep:backtrace\"],\"test-util\":[\"rt\",\"sync\",\"time\"],\"time\":[]}}", "toml_0.5.11": "{\"dependencies\":[{\"name\":\"indexmap\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"serde\",\"req\":\"^1.0.97\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"}],\"features\":{\"default\":[],\"preserve_order\":[\"indexmap\"]}}", "toml_0.9.11+spec-1.1.0": "{\"dependencies\":[{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.20\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.11\"},{\"default_features\":false,\"name\":\"foldhash\",\"optional\":true,\"req\":\"^0.2.0\"},{\"default_features\":false,\"name\":\"indexmap\",\"optional\":true,\"req\":\"^2.11.4\"},{\"kind\":\"dev\",\"name\":\"itertools\",\"req\":\"^0.14.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.225\"},{\"kind\":\"dev\",\"name\":\"serde-untagged\",\"req\":\"^0.1.9\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.225\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.145\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde_spanned\",\"req\":\"^1.0.4\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"},{\"kind\":\"dev\",\"name\":\"toml-test-data\",\"req\":\"^2.3.3\"},{\"features\":[\"snapshot\"],\"kind\":\"dev\",\"name\":\"toml-test-harness\",\"req\":\"^1.3.3\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"toml_datetime\",\"req\":\"^0.7.5\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"toml_parser\",\"optional\":true,\"req\":\"^1.0.6\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"toml_writer\",\"optional\":true,\"req\":\"^1.0.6\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.5.0\"},{\"default_features\":false,\"name\":\"winnow\",\"optional\":true,\"req\":\"^0.7.13\"}],\"features\":{\"debug\":[\"std\",\"toml_parser?/debug\",\"dep:anstream\",\"dep:anstyle\"],\"default\":[\"std\",\"serde\",\"parse\",\"display\"],\"display\":[\"dep:toml_writer\"],\"fast_hash\":[\"preserve_order\",\"dep:foldhash\"],\"parse\":[\"dep:toml_parser\",\"dep:winnow\"],\"preserve_order\":[\"dep:indexmap\",\"std\"],\"serde\":[\"dep:serde_core\",\"toml_datetime/serde\",\"serde_spanned/serde\"],\"std\":[\"indexmap?/std\",\"serde_core?/std\",\"toml_parser?/std\",\"toml_writer?/std\",\"toml_datetime/std\",\"serde_spanned/std\"],\"unbounded\":[]}}", + "toml_0.9.12+spec-1.1.0": "{\"dependencies\":[{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.20\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.11\"},{\"default_features\":false,\"name\":\"foldhash\",\"optional\":true,\"req\":\"^0.2.0\"},{\"default_features\":false,\"name\":\"indexmap\",\"optional\":true,\"req\":\"^2.11.4\"},{\"kind\":\"dev\",\"name\":\"itertools\",\"req\":\"^0.14.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.225\"},{\"kind\":\"dev\",\"name\":\"serde-untagged\",\"req\":\"^0.1.9\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.225\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.145\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde_spanned\",\"req\":\"^1.0.4\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"},{\"kind\":\"dev\",\"name\":\"toml-test-data\",\"req\":\"^2.3.3\"},{\"features\":[\"snapshot\"],\"kind\":\"dev\",\"name\":\"toml-test-harness\",\"req\":\"^1.3.3\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"toml_datetime\",\"req\":\"^0.7.5\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"toml_parser\",\"optional\":true,\"req\":\"^1.0.7\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"toml_writer\",\"optional\":true,\"req\":\"^1.0.6\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.5.0\"},{\"default_features\":false,\"name\":\"winnow\",\"optional\":true,\"req\":\"^0.7.13\"}],\"features\":{\"debug\":[\"std\",\"toml_parser?/debug\",\"dep:anstream\",\"dep:anstyle\"],\"default\":[\"std\",\"serde\",\"parse\",\"display\"],\"display\":[\"dep:toml_writer\"],\"fast_hash\":[\"preserve_order\",\"dep:foldhash\"],\"parse\":[\"dep:toml_parser\",\"dep:winnow\"],\"preserve_order\":[\"dep:indexmap\",\"std\"],\"serde\":[\"dep:serde_core\",\"toml_datetime/serde\",\"serde_spanned/serde\"],\"std\":[\"indexmap?/std\",\"serde_core?/std\",\"toml_parser?/std\",\"toml_writer?/std\",\"toml_datetime/std\",\"serde_spanned/std\"],\"unbounded\":[]}}", "toml_datetime_0.7.5+spec-1.1.0": "{\"dependencies\":[{\"default_features\":false,\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.225\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"}],\"features\":{\"alloc\":[\"serde_core?/alloc\"],\"default\":[\"std\"],\"serde\":[\"dep:serde_core\"],\"std\":[\"alloc\",\"serde_core?/std\"]}}", "toml_edit_0.23.10+spec-1.0.0": "{\"dependencies\":[{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.20\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.11\"},{\"features\":[\"std\"],\"name\":\"indexmap\",\"req\":\"^2.11.4\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.7.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.225\"},{\"kind\":\"dev\",\"name\":\"serde-untagged\",\"req\":\"^0.1.9\"},{\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.225\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.145\"},{\"features\":[\"serde\"],\"name\":\"serde_spanned\",\"optional\":true,\"req\":\"^1.0.4\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"},{\"kind\":\"dev\",\"name\":\"toml-test-data\",\"req\":\"^2.3.3\"},{\"features\":[\"snapshot\"],\"kind\":\"dev\",\"name\":\"toml-test-harness\",\"req\":\"^1.3.3\"},{\"name\":\"toml_datetime\",\"req\":\"^0.7.4\"},{\"name\":\"toml_parser\",\"optional\":true,\"req\":\"^1.0.5\"},{\"name\":\"toml_writer\",\"optional\":true,\"req\":\"^1.0.5\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.5.0\"},{\"name\":\"winnow\",\"optional\":true,\"req\":\"^0.7.13\"}],\"features\":{\"debug\":[\"toml_parser?/debug\",\"dep:anstream\",\"dep:anstyle\",\"display\"],\"default\":[\"parse\",\"display\"],\"display\":[\"dep:toml_writer\"],\"parse\":[\"dep:toml_parser\",\"dep:winnow\"],\"serde\":[\"dep:serde_core\",\"toml_datetime/serde\",\"dep:serde_spanned\"],\"unbounded\":[]}}", "toml_edit_0.24.0+spec-1.1.0": "{\"dependencies\":[{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.20\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.11\"},{\"features\":[\"std\"],\"name\":\"indexmap\",\"req\":\"^2.11.4\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.7.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.225\"},{\"kind\":\"dev\",\"name\":\"serde-untagged\",\"req\":\"^0.1.9\"},{\"name\":\"serde_core\",\"optional\":true,\"req\":\"^1.0.225\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.145\"},{\"features\":[\"serde\"],\"name\":\"serde_spanned\",\"optional\":true,\"req\":\"^1.0.4\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"},{\"kind\":\"dev\",\"name\":\"toml-test-data\",\"req\":\"^2.3.3\"},{\"features\":[\"snapshot\"],\"kind\":\"dev\",\"name\":\"toml-test-harness\",\"req\":\"^1.3.3\"},{\"name\":\"toml_datetime\",\"req\":\"^0.7.5\"},{\"name\":\"toml_parser\",\"optional\":true,\"req\":\"^1.0.6\"},{\"name\":\"toml_writer\",\"optional\":true,\"req\":\"^1.0.6\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.5.0\"},{\"name\":\"winnow\",\"optional\":true,\"req\":\"^0.7.13\"}],\"features\":{\"debug\":[\"toml_parser?/debug\",\"dep:anstream\",\"dep:anstyle\",\"display\"],\"default\":[\"parse\",\"display\"],\"display\":[\"dep:toml_writer\"],\"parse\":[\"dep:toml_parser\",\"dep:winnow\"],\"serde\":[\"dep:serde_core\",\"toml_datetime/serde\",\"dep:serde_spanned\"],\"unbounded\":[]}}", "toml_parser_1.0.6+spec-1.1.0": "{\"dependencies\":[{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.20\"},{\"features\":[\"test\"],\"kind\":\"dev\",\"name\":\"anstream\",\"req\":\"^0.6.20\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.11\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"},{\"default_features\":false,\"name\":\"winnow\",\"req\":\"^0.7.13\"}],\"features\":{\"alloc\":[],\"debug\":[\"std\",\"dep:anstream\",\"dep:anstyle\"],\"default\":[\"std\"],\"simd\":[\"winnow/simd\"],\"std\":[\"alloc\"],\"unsafe\":[]}}", + "toml_parser_1.0.9+spec-1.1.0": "{\"dependencies\":[{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.20\"},{\"features\":[\"test\"],\"kind\":\"dev\",\"name\":\"anstream\",\"req\":\"^0.6.20\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.11\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"},{\"default_features\":false,\"name\":\"winnow\",\"req\":\"^0.7.13\"}],\"features\":{\"alloc\":[],\"debug\":[\"std\",\"dep:anstream\",\"dep:anstyle\"],\"default\":[\"std\"],\"simd\":[\"winnow/simd\"],\"std\":[\"alloc\"],\"unsafe\":[]}}", "toml_writer_1.0.6+spec-1.1.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.7.0\"},{\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"},{\"kind\":\"dev\",\"name\":\"toml_old\",\"package\":\"toml\",\"req\":\"^0.5.11\"}],\"features\":{\"alloc\":[],\"default\":[\"std\"],\"std\":[\"alloc\"]}}", "tonic-prost_0.14.3": "{\"dependencies\":[{\"name\":\"bytes\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"http-body\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"http-body-util\",\"req\":\"^0.1\"},{\"name\":\"prost\",\"req\":\"^0.14\"},{\"features\":[\"macros\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"tokio-stream\",\"req\":\"^0.1\"},{\"default_features\":false,\"name\":\"tonic\",\"req\":\"^0.14.0\"}],\"features\":{}}", "tonic_0.14.3": "{\"dependencies\":[{\"name\":\"async-trait\",\"optional\":true,\"req\":\"^0.1.13\"},{\"default_features\":false,\"name\":\"axum\",\"optional\":true,\"req\":\"^0.8\"},{\"name\":\"base64\",\"req\":\"^0.22\"},{\"kind\":\"dev\",\"name\":\"bencher\",\"req\":\"^0.1.5\"},{\"name\":\"bytes\",\"req\":\"^1.0\"},{\"name\":\"flate2\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"h2\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"http\",\"req\":\"^1.1.0\"},{\"name\":\"http-body\",\"req\":\"^1\"},{\"name\":\"http-body-util\",\"req\":\"^0.1\"},{\"features\":[\"http1\",\"http2\"],\"name\":\"hyper\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"hyper-timeout\",\"optional\":true,\"req\":\"^0.5\"},{\"features\":[\"tokio\"],\"name\":\"hyper-util\",\"optional\":true,\"req\":\"^0.1.11\"},{\"name\":\"percent-encoding\",\"req\":\"^2.1\"},{\"name\":\"pin-project\",\"req\":\"^1.0.11\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"quickcheck_macros\",\"req\":\"^1.0\"},{\"name\":\"rustls-native-certs\",\"optional\":true,\"req\":\"^0.8\"},{\"features\":[\"all\"],\"name\":\"socket2\",\"optional\":true,\"req\":\"^0.6\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.0\"},{\"name\":\"sync_wrapper\",\"req\":\"^1.0.2\"},{\"default_features\":false,\"name\":\"tokio\",\"optional\":true,\"req\":\"^1\"},{\"features\":[\"rt-multi-thread\",\"macros\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.0\"},{\"default_features\":false,\"features\":[\"logging\",\"tls12\"],\"name\":\"tokio-rustls\",\"optional\":true,\"req\":\"^0.26.1\"},{\"default_features\":false,\"name\":\"tokio-stream\",\"req\":\"^0.1.16\"},{\"default_features\":false,\"name\":\"tower\",\"optional\":true,\"req\":\"^0.5\"},{\"features\":[\"load-shed\",\"timeout\"],\"kind\":\"dev\",\"name\":\"tower\",\"req\":\"^0.5\"},{\"name\":\"tower-layer\",\"req\":\"^0.3\"},{\"name\":\"tower-service\",\"req\":\"^0.3\"},{\"name\":\"tracing\",\"req\":\"^0.1\"},{\"name\":\"webpki-roots\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"zstd\",\"optional\":true,\"req\":\"^0.13.0\"}],\"features\":{\"_tls-any\":[\"dep:tokio\",\"tokio?/rt\",\"tokio?/macros\",\"tls-connect-info\"],\"channel\":[\"dep:hyper\",\"hyper?/client\",\"dep:hyper-util\",\"hyper-util?/client-legacy\",\"dep:tower\",\"tower?/balance\",\"tower?/buffer\",\"tower?/discover\",\"tower?/limit\",\"tower?/load-shed\",\"tower?/util\",\"dep:tokio\",\"tokio?/time\",\"dep:hyper-timeout\"],\"codegen\":[\"dep:async-trait\"],\"default\":[\"router\",\"transport\",\"codegen\"],\"deflate\":[\"dep:flate2\"],\"gzip\":[\"dep:flate2\"],\"router\":[\"dep:axum\",\"dep:tower\",\"tower?/util\"],\"server\":[\"dep:h2\",\"dep:hyper\",\"hyper?/server\",\"dep:hyper-util\",\"hyper-util?/service\",\"hyper-util?/server-auto\",\"dep:socket2\",\"dep:tokio\",\"tokio?/macros\",\"tokio?/net\",\"tokio?/time\",\"tokio-stream/net\",\"dep:tower\",\"tower?/util\",\"tower?/limit\",\"tower?/load-shed\"],\"tls-aws-lc\":[\"_tls-any\",\"tokio-rustls/aws-lc-rs\"],\"tls-connect-info\":[\"dep:tokio-rustls\"],\"tls-native-roots\":[\"_tls-any\",\"channel\",\"dep:rustls-native-certs\"],\"tls-ring\":[\"_tls-any\",\"tokio-rustls/ring\"],\"tls-webpki-roots\":[\"_tls-any\",\"channel\",\"dep:webpki-roots\"],\"transport\":[\"server\",\"channel\"],\"zstd\":[\"dep:zstd\"]}}", @@ -1404,6 +1454,7 @@ "unicase_2.9.0": "{\"dependencies\":[],\"features\":{\"nightly\":[]}}", "unicode-bidi_0.3.18": "{\"dependencies\":[{\"name\":\"flame\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"flamer\",\"optional\":true,\"req\":\"^0.4\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\">=0.8, <2.0\"},{\"kind\":\"dev\",\"name\":\"serde_test\",\"req\":\">=0.8, <2.0\"},{\"features\":[\"union\"],\"name\":\"smallvec\",\"optional\":true,\"req\":\">=1.13\"}],\"features\":{\"bench_it\":[],\"default\":[\"std\",\"hardcoded-data\"],\"flame_it\":[\"flame\",\"flamer\"],\"hardcoded-data\":[],\"std\":[],\"unstable\":[],\"with_serde\":[\"serde\"]}}", "unicode-ident_1.0.22": "{\"dependencies\":[{\"default_features\":false,\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"fst\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"roaring\",\"req\":\"^0.11\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"ucd-trie\",\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"unicode-xid\",\"req\":\"^0.2.6\"}],\"features\":{}}", + "unicode-ident_1.0.24": "{\"dependencies\":[{\"default_features\":false,\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.8\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"fst\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.10\"},{\"kind\":\"dev\",\"name\":\"roaring\",\"req\":\"^0.11\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"ucd-trie\",\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"unicode-xid\",\"req\":\"^0.2.6\"}],\"features\":{}}", "unicode-linebreak_0.1.5": "{\"dependencies\":[],\"features\":{}}", "unicode-normalization_0.1.25": "{\"dependencies\":[{\"features\":[\"alloc\"],\"name\":\"tinyvec\",\"req\":\"^1\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "unicode-properties_0.1.4": "{\"dependencies\":[],\"features\":{\"default\":[\"general-category\",\"emoji\"],\"emoji\":[],\"general-category\":[]}}", @@ -1411,6 +1462,7 @@ "unicode-truncate_1.1.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5\"},{\"default_features\":false,\"name\":\"itertools\",\"req\":\"^0.13\"},{\"default_features\":false,\"name\":\"unicode-segmentation\",\"req\":\"^1\"},{\"name\":\"unicode-width\",\"req\":\"^0.1\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "unicode-width_0.1.14": "{\"dependencies\":[{\"name\":\"compiler_builtins\",\"optional\":true,\"req\":\"^0.1\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0\"},{\"name\":\"std\",\"optional\":true,\"package\":\"rustc-std-workspace-std\",\"req\":\"^1.0\"}],\"features\":{\"cjk\":[],\"default\":[\"cjk\"],\"no_std\":[],\"rustc-dep-of-std\":[\"std\",\"core\",\"compiler_builtins\"]}}", "unicode-width_0.2.1": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0\"},{\"name\":\"std\",\"optional\":true,\"package\":\"rustc-std-workspace-std\",\"req\":\"^1.0\"}],\"features\":{\"cjk\":[],\"default\":[\"cjk\"],\"no_std\":[],\"rustc-dep-of-std\":[\"std\",\"core\"]}}", + "unicode-width_0.2.2": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0\"},{\"name\":\"std\",\"optional\":true,\"package\":\"rustc-std-workspace-std\",\"req\":\"^1.0\"}],\"features\":{\"cjk\":[],\"default\":[\"cjk\"],\"no_std\":[],\"rustc-dep-of-std\":[\"std\",\"core\"]}}", "unicode-xid_0.2.6": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.3\"}],\"features\":{\"bench\":[],\"default\":[],\"no_std\":[]}}", "universal-hash_0.5.1": "{\"dependencies\":[{\"name\":\"crypto-common\",\"req\":\"^0.1.6\"},{\"default_features\":false,\"name\":\"subtle\",\"req\":\"^2.4\"}],\"features\":{\"std\":[\"crypto-common/std\"]}}", "unsafe-libyaml_0.2.11": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"pretty_assertions\",\"req\":\"^1.0\"}],\"features\":{}}", @@ -1435,13 +1487,17 @@ "want_0.3.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"tokio-executor\",\"req\":\"^0.2.0-alpha.2\"},{\"kind\":\"dev\",\"name\":\"tokio-sync\",\"req\":\"^0.2.0-alpha.2\"},{\"name\":\"try-lock\",\"req\":\"^0.2.4\"}],\"features\":{}}", "wasi_0.11.1+wasi-snapshot-preview1": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0\"},{\"name\":\"rustc-std-workspace-alloc\",\"optional\":true,\"req\":\"^1.0\"}],\"features\":{\"default\":[\"std\"],\"rustc-dep-of-std\":[\"core\",\"rustc-std-workspace-alloc\"],\"std\":[]}}", "wasip2_1.0.2+wasi-0.2.9": "{\"dependencies\":[{\"name\":\"alloc\",\"optional\":true,\"package\":\"rustc-std-workspace-alloc\",\"req\":\"^1.0\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"wit-bindgen\",\"req\":\"^0.51.0\"}],\"features\":{\"bitflags\":[\"wit-bindgen/bitflags\"],\"default\":[\"std\",\"bitflags\"],\"rustc-dep-of-std\":[\"core\",\"alloc\",\"wit-bindgen/rustc-dep-of-std\"],\"std\":[]}}", + "wasip3_0.4.0+wasi-0.3.0-rc-2026-01-06": "{\"dependencies\":[{\"name\":\"bytes\",\"optional\":true,\"req\":\"^1.10.1\"},{\"kind\":\"dev\",\"name\":\"futures\",\"req\":\"^0.3.31\"},{\"name\":\"http\",\"optional\":true,\"req\":\"^1.3.1\"},{\"kind\":\"dev\",\"name\":\"http\",\"req\":\"^1.3.1\"},{\"name\":\"http-body\",\"optional\":true,\"req\":\"^1.0.1\"},{\"name\":\"thiserror\",\"optional\":true,\"req\":\"^2.0.17\"},{\"default_features\":false,\"features\":[\"async\"],\"name\":\"wit-bindgen\",\"req\":\"^0.51.0\"},{\"default_features\":false,\"features\":[\"async-spawn\"],\"kind\":\"dev\",\"name\":\"wit-bindgen\",\"req\":\"^0.51.0\"}],\"features\":{\"http-compat\":[\"dep:bytes\",\"dep:http-body\",\"dep:http\",\"dep:thiserror\",\"wit-bindgen/async-spawn\"]}}", "wasite_0.1.0": "{\"dependencies\":[],\"features\":{}}", "wasm-bindgen-futures_0.4.58": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"futures-channel\",\"req\":\"^0.3\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"default_features\":false,\"name\":\"futures-core\",\"optional\":true,\"req\":\"^0.3.8\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"futures-lite\",\"req\":\"^2\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"futures-util\",\"optional\":true,\"req\":\"^0.3.31\"},{\"default_features\":false,\"name\":\"js-sys\",\"req\":\"=0.3.85\"},{\"default_features\":false,\"name\":\"once_cell\",\"req\":\"^1.12\"},{\"default_features\":false,\"name\":\"wasm-bindgen\",\"req\":\"=0.2.108\"},{\"default_features\":false,\"features\":[\"MessageEvent\",\"Worker\"],\"name\":\"web-sys\",\"req\":\"=0.3.85\",\"target\":\"cfg(target_feature = \\\"atomics\\\")\"}],\"features\":{\"default\":[\"std\"],\"futures-core-03-stream\":[\"futures-core\"],\"std\":[\"wasm-bindgen/std\",\"js-sys/std\",\"web-sys/std\",\"futures-util\"]}}", "wasm-bindgen-macro-support_0.2.108": "{\"dependencies\":[{\"name\":\"bumpalo\",\"req\":\"^3.0.0\"},{\"name\":\"proc-macro2\",\"req\":\"^1.0\"},{\"name\":\"quote\",\"req\":\"^1.0\"},{\"features\":[\"visit\",\"visit-mut\",\"full\"],\"name\":\"syn\",\"req\":\"^2.0\"},{\"name\":\"wasm-bindgen-shared\",\"req\":\"=0.2.108\"}],\"features\":{\"extra-traits\":[\"syn/extra-traits\"],\"strict-macro\":[]}}", "wasm-bindgen-macro_0.2.108": "{\"dependencies\":[{\"name\":\"quote\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0\"},{\"name\":\"wasm-bindgen-macro-support\",\"req\":\"=0.2.108\"}],\"features\":{\"strict-macro\":[\"wasm-bindgen-macro-support/strict-macro\"]}}", "wasm-bindgen-shared_0.2.108": "{\"dependencies\":[{\"name\":\"unicode-ident\",\"req\":\"^1.0.5\"}],\"features\":{}}", "wasm-bindgen_0.2.108": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1.0.0\"},{\"default_features\":false,\"name\":\"once_cell\",\"req\":\"^1.12\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"paste\",\"req\":\"^1\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"kind\":\"build\",\"name\":\"rustversion-compat\",\"package\":\"rustversion\",\"req\":\"^1.0.6\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"wasm-bindgen-macro\",\"req\":\"=0.2.108\"},{\"name\":\"wasm-bindgen-shared\",\"req\":\"=0.2.108\"}],\"features\":{\"default\":[\"std\"],\"enable-interning\":[\"std\"],\"gg-alloc\":[],\"msrv\":[],\"rustversion\":[],\"serde-serialize\":[\"serde\",\"serde_json\",\"std\"],\"spans\":[],\"std\":[],\"strict-macro\":[\"wasm-bindgen-macro/strict-macro\"],\"xxx_debug_only_print_generated_code\":[]}}", + "wasm-encoder_0.244.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.58\"},{\"default_features\":false,\"name\":\"leb128fmt\",\"req\":\"^0.1.0\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.2.0\"},{\"default_features\":false,\"features\":[\"simd\",\"simd\"],\"name\":\"wasmparser\",\"optional\":true,\"req\":\"^0.244.0\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"wasmprinter\",\"req\":\"^0.244.0\"}],\"features\":{\"component-model\":[\"wasmparser?/component-model\"],\"default\":[\"std\",\"component-model\"],\"std\":[\"wasmparser?/std\"]}}", + "wasm-metadata_0.244.0": "{\"dependencies\":[{\"name\":\"anyhow\",\"req\":\"^1.0.58\"},{\"name\":\"auditable-serde\",\"optional\":true,\"req\":\"^0.8.0\"},{\"features\":[\"derive\"],\"name\":\"clap\",\"optional\":true,\"req\":\"^4.0.0\"},{\"name\":\"flate2\",\"optional\":true,\"req\":\"^1.1.0\"},{\"default_features\":false,\"features\":[\"serde\"],\"name\":\"indexmap\",\"req\":\"^2.7.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.166\"},{\"name\":\"serde_derive\",\"optional\":true,\"req\":\"^1.0.166\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"spdx\",\"optional\":true,\"req\":\"^0.10.1\"},{\"name\":\"url\",\"optional\":true,\"req\":\"^2.0.0\"},{\"default_features\":false,\"features\":[\"std\",\"component-model\"],\"name\":\"wasm-encoder\",\"req\":\"^0.244.0\"},{\"default_features\":false,\"features\":[\"simd\",\"std\",\"component-model\",\"hash-collections\"],\"name\":\"wasmparser\",\"req\":\"^0.244.0\"}],\"features\":{\"default\":[\"oci\",\"serde\"],\"oci\":[\"dep:auditable-serde\",\"dep:flate2\",\"dep:url\",\"dep:spdx\",\"dep:serde_json\",\"serde\"],\"serde\":[\"dep:serde_derive\",\"dep:serde\"]}}", "wasm-streams_0.4.2": "{\"dependencies\":[{\"features\":[\"io\",\"sink\"],\"name\":\"futures-util\",\"req\":\"^0.3.31\"},{\"features\":[\"futures\"],\"kind\":\"dev\",\"name\":\"gloo-timers\",\"req\":\"^0.3.0\"},{\"name\":\"js-sys\",\"req\":\"^0.3.72\"},{\"kind\":\"dev\",\"name\":\"pin-project\",\"req\":\"^1\"},{\"features\":[\"macros\",\"rt\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"name\":\"wasm-bindgen\",\"req\":\"^0.2.95\"},{\"name\":\"wasm-bindgen-futures\",\"req\":\"^0.4.45\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3.45\"},{\"features\":[\"AbortSignal\",\"QueuingStrategy\",\"ReadableStream\",\"ReadableStreamType\",\"ReadableWritablePair\",\"ReadableStreamByobReader\",\"ReadableStreamReaderMode\",\"ReadableStreamReadResult\",\"ReadableStreamByobRequest\",\"ReadableStreamDefaultReader\",\"ReadableByteStreamController\",\"ReadableStreamGetReaderOptions\",\"ReadableStreamDefaultController\",\"StreamPipeOptions\",\"TransformStream\",\"TransformStreamDefaultController\",\"Transformer\",\"UnderlyingSink\",\"UnderlyingSource\",\"WritableStream\",\"WritableStreamDefaultController\",\"WritableStreamDefaultWriter\"],\"name\":\"web-sys\",\"req\":\"^0.3.72\"},{\"features\":[\"console\",\"AbortSignal\",\"ErrorEvent\",\"PromiseRejectionEvent\",\"Response\",\"ReadableStream\",\"Window\"],\"kind\":\"dev\",\"name\":\"web-sys\",\"req\":\"^0.3.72\"}],\"features\":{}}", + "wasmparser_0.244.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.58\"},{\"name\":\"bitflags\",\"req\":\"^2.4.1\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5.1\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.11\"},{\"default_features\":false,\"features\":[\"default-hasher\"],\"name\":\"hashbrown\",\"optional\":true,\"req\":\"^0.15.2\"},{\"default_features\":false,\"name\":\"indexmap\",\"optional\":true,\"req\":\"^2.7.0\"},{\"kind\":\"dev\",\"name\":\"log\",\"req\":\"^0.4.17\"},{\"kind\":\"dev\",\"name\":\"once_cell\",\"req\":\"^1.13.0\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1.3\"},{\"default_features\":false,\"name\":\"semver\",\"optional\":true,\"req\":\"^1.0.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.166\"}],\"features\":{\"component-model\":[\"dep:semver\"],\"default\":[\"std\",\"validate\",\"serde\",\"features\",\"component-model\",\"hash-collections\",\"simd\"],\"features\":[],\"hash-collections\":[\"dep:hashbrown\",\"dep:indexmap\"],\"prefer-btree-collections\":[],\"serde\":[\"dep:serde\",\"indexmap?/serde\",\"hashbrown?/serde\"],\"simd\":[],\"std\":[\"indexmap?/std\"],\"validate\":[]}}", "wayland-backend_0.3.12": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"concat-idents\",\"req\":\"^1.1\"},{\"name\":\"downcast-rs\",\"req\":\"^1.2\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.10\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"raw-window-handle\",\"optional\":true,\"req\":\"^0.5.0\"},{\"features\":[\"event\",\"fs\",\"net\",\"process\"],\"name\":\"rustix\",\"req\":\"^1.0.2\"},{\"name\":\"rwh_06\",\"optional\":true,\"package\":\"raw-window-handle\",\"req\":\"^0.6.0\"},{\"name\":\"scoped-tls\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"scoped-tls\",\"req\":\"^1.0\"},{\"features\":[\"union\",\"const_generics\",\"const_new\"],\"name\":\"smallvec\",\"req\":\"^1.9\"},{\"name\":\"wayland-sys\",\"req\":\"^0.31.8\"}],\"features\":{\"client_system\":[\"wayland-sys/client\",\"dep:scoped-tls\"],\"dlopen\":[\"wayland-sys/dlopen\"],\"server_system\":[\"wayland-sys/server\",\"dep:scoped-tls\"]}}", "wayland-client_0.31.12": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2\"},{\"kind\":\"dev\",\"name\":\"futures-channel\",\"req\":\"^0.3.16\"},{\"kind\":\"dev\",\"name\":\"futures-util\",\"req\":\"^0.3\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4\"},{\"features\":[\"event\"],\"name\":\"rustix\",\"req\":\"^1.0.2\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.2\"},{\"name\":\"wayland-backend\",\"req\":\"^0.3.12\"},{\"name\":\"wayland-scanner\",\"req\":\"^0.31.8\"}],\"features\":{}}", "wayland-protocols-wlr_0.3.10": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2\"},{\"name\":\"wayland-backend\",\"req\":\"^0.3.12\"},{\"name\":\"wayland-client\",\"optional\":true,\"req\":\"^0.31.12\"},{\"name\":\"wayland-protocols\",\"req\":\"^0.32.10\"},{\"name\":\"wayland-scanner\",\"req\":\"^0.31.8\"},{\"name\":\"wayland-server\",\"optional\":true,\"req\":\"^0.31.11\"}],\"features\":{\"client\":[\"wayland-client\",\"wayland-protocols/client\"],\"server\":[\"wayland-server\",\"wayland-protocols/server\"]}}", @@ -1527,19 +1583,26 @@ "windows_x86_64_msvc_0.52.6": "{\"dependencies\":[],\"features\":{}}", "windows_x86_64_msvc_0.53.1": "{\"dependencies\":[],\"features\":{}}", "winnow_0.7.14": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"annotate-snippets\",\"req\":\"^0.11.4\"},{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.15\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.8\"},{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.100\"},{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1.0.15\"},{\"kind\":\"dev\",\"name\":\"circular\",\"req\":\"^0.3.0\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5.1\"},{\"name\":\"is_terminal_polyfill\",\"optional\":true,\"req\":\"^1.48.1\"},{\"kind\":\"dev\",\"name\":\"lexopt\",\"req\":\"^0.3.1\"},{\"default_features\":false,\"name\":\"memchr\",\"optional\":true,\"req\":\"^2.7\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.6.0\"},{\"kind\":\"dev\",\"name\":\"rustc-hash\",\"req\":\"^2.1.1\"},{\"features\":[\"examples\"],\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"},{\"kind\":\"dev\",\"name\":\"term-transcript\",\"req\":\"^0.2.0\"},{\"name\":\"terminal_size\",\"optional\":true,\"req\":\"^0.4.3\"}],\"features\":{\"alloc\":[],\"debug\":[\"std\",\"dep:anstream\",\"dep:anstyle\",\"dep:is_terminal_polyfill\",\"dep:terminal_size\"],\"default\":[\"std\"],\"simd\":[\"dep:memchr\"],\"std\":[\"alloc\",\"memchr?/std\"],\"unstable-doc\":[\"alloc\",\"std\",\"simd\",\"unstable-recover\"],\"unstable-recover\":[]}}", + "winnow_0.7.15": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"annotate-snippets\",\"req\":\"^0.11.4\"},{\"name\":\"anstream\",\"optional\":true,\"req\":\"^0.6.15\"},{\"name\":\"anstyle\",\"optional\":true,\"req\":\"^1.0.8\"},{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.100\"},{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1.0.15\"},{\"kind\":\"dev\",\"name\":\"circular\",\"req\":\"^0.3.0\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5.1\"},{\"name\":\"is_terminal_polyfill\",\"optional\":true,\"req\":\"^1.48.1\"},{\"kind\":\"dev\",\"name\":\"lexopt\",\"req\":\"^0.3.1\"},{\"default_features\":false,\"name\":\"memchr\",\"optional\":true,\"req\":\"^2.7\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.6.0\"},{\"kind\":\"dev\",\"name\":\"rustc-hash\",\"req\":\"^2.1.1\"},{\"features\":[\"examples\"],\"kind\":\"dev\",\"name\":\"snapbox\",\"req\":\"^0.6.21\"},{\"kind\":\"dev\",\"name\":\"term-transcript\",\"req\":\"^0.2.0\"},{\"name\":\"terminal_size\",\"optional\":true,\"req\":\"^0.4.3\"}],\"features\":{\"alloc\":[],\"debug\":[\"std\",\"dep:anstream\",\"dep:anstyle\",\"dep:is_terminal_polyfill\",\"dep:terminal_size\"],\"default\":[\"std\"],\"simd\":[\"dep:memchr\"],\"std\":[\"alloc\",\"memchr?/std\"],\"unstable-doc\":[\"alloc\",\"std\",\"simd\",\"unstable-recover\"],\"unstable-recover\":[]}}", "winreg_0.10.1": "{\"dependencies\":[{\"name\":\"chrono\",\"optional\":true,\"req\":\"^0.4.6\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.3\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"~3.0\"},{\"features\":[\"impl-default\",\"impl-debug\",\"minwindef\",\"minwinbase\",\"timezoneapi\",\"winerror\",\"winnt\",\"winreg\",\"handleapi\"],\"name\":\"winapi\",\"req\":\"^0.3.9\"}],\"features\":{\"serialization-serde\":[\"transactions\",\"serde\"],\"transactions\":[\"winapi/ktmw32\"]}}", "winreg_0.50.0": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1.0\"},{\"name\":\"chrono\",\"optional\":true,\"req\":\"^0.4.6\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.3\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"serde_bytes\",\"req\":\"^0.11\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"~3.0\"},{\"features\":[\"Win32_Foundation\",\"Win32_System_Time\",\"Win32_System_Registry\",\"Win32_Security\",\"Win32_Storage_FileSystem\",\"Win32_System_Diagnostics_Debug\"],\"name\":\"windows-sys\",\"req\":\"^0.48.0\"}],\"features\":{\"serialization-serde\":[\"transactions\",\"serde\"],\"transactions\":[]}}", "winres_0.1.12": "{\"dependencies\":[{\"name\":\"toml\",\"req\":\"^0.5\"},{\"features\":[\"winnt\"],\"kind\":\"dev\",\"name\":\"winapi\",\"req\":\"^0.3\"}],\"features\":{}}", "winsafe_0.0.19": "{\"dependencies\":[],\"features\":{\"comctl\":[\"ole\"],\"dshow\":[\"oleaut\"],\"dwm\":[\"uxtheme\"],\"dxgi\":[\"ole\"],\"gdi\":[\"user\"],\"gui\":[\"comctl\",\"shell\",\"uxtheme\"],\"kernel\":[],\"mf\":[\"oleaut\"],\"ole\":[\"user\"],\"oleaut\":[\"ole\"],\"shell\":[\"oleaut\"],\"taskschd\":[\"oleaut\"],\"user\":[\"kernel\"],\"uxtheme\":[\"gdi\",\"ole\"],\"version\":[\"kernel\"]}}", "winsplit_0.1.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"doc-comment\",\"req\":\"^0.3.3\"}],\"features\":{\"default\":[\"std\"],\"std\":[]}}", "wiremock_0.6.5": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"actix-rt\",\"req\":\"^2.10.0\"},{\"name\":\"assert-json-diff\",\"req\":\"^2.0.2\"},{\"features\":[\"attributes\",\"tokio1\"],\"kind\":\"dev\",\"name\":\"async-std\",\"req\":\"^1.13.2\"},{\"name\":\"base64\",\"req\":\"^0.22\"},{\"name\":\"deadpool\",\"req\":\"^0.12.2\"},{\"name\":\"futures\",\"req\":\"^0.3.31\"},{\"name\":\"http\",\"req\":\"^1.3\"},{\"name\":\"http-body-util\",\"req\":\"^0.1\"},{\"features\":[\"full\"],\"name\":\"hyper\",\"req\":\"^1.7\"},{\"features\":[\"tokio\",\"server\",\"http1\",\"http2\"],\"name\":\"hyper-util\",\"req\":\"^0.1\"},{\"name\":\"log\",\"req\":\"^0.4\"},{\"name\":\"once_cell\",\"req\":\"^1\"},{\"name\":\"regex\",\"req\":\"^1\"},{\"features\":[\"json\"],\"kind\":\"dev\",\"name\":\"reqwest\",\"req\":\"^0.12.23\"},{\"name\":\"serde\",\"req\":\"^1\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1\"},{\"name\":\"serde_json\",\"req\":\"^1\"},{\"features\":[\"rt\",\"macros\",\"net\"],\"name\":\"tokio\",\"req\":\"^1.47.1\"},{\"features\":[\"macros\",\"rt-multi-thread\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.47.1\"},{\"name\":\"url\",\"req\":\"^2.5\"}],\"features\":{}}", + "wit-bindgen-core_0.51.0": "{\"dependencies\":[{\"name\":\"anyhow\",\"req\":\"^1.0.72\"},{\"features\":[\"derive\"],\"name\":\"clap\",\"optional\":true,\"req\":\"^4.3.19\"},{\"name\":\"heck\",\"req\":\"^0.5\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.218\"},{\"name\":\"wit-parser\",\"req\":\"^0.244.0\"}],\"features\":{\"clap\":[\"dep:clap\"],\"serde\":[\"dep:serde\"]}}", + "wit-bindgen-rust-macro_0.51.0": "{\"dependencies\":[{\"name\":\"anyhow\",\"req\":\"^1.0.72\"},{\"name\":\"prettyplease\",\"req\":\"^0.2.20\"},{\"name\":\"proc-macro2\",\"req\":\"^1.0\"},{\"name\":\"quote\",\"req\":\"^1\"},{\"features\":[\"printing\"],\"name\":\"syn\",\"req\":\"^2.0.89\"},{\"name\":\"wit-bindgen-core\",\"req\":\"^0.51.0\"},{\"name\":\"wit-bindgen-rust\",\"req\":\"^0.51.0\"}],\"features\":{\"async\":[]}}", + "wit-bindgen-rust_0.51.0": "{\"dependencies\":[{\"name\":\"anyhow\",\"req\":\"^1.0.72\"},{\"kind\":\"dev\",\"name\":\"bytes\",\"req\":\"^1\"},{\"features\":[\"derive\"],\"name\":\"clap\",\"optional\":true,\"req\":\"^4.3.19\"},{\"kind\":\"dev\",\"name\":\"futures\",\"req\":\"^0.3.31\"},{\"name\":\"heck\",\"req\":\"^0.5\"},{\"name\":\"indexmap\",\"req\":\"^2.0.0\"},{\"name\":\"prettyplease\",\"req\":\"^0.2.20\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.218\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1\"},{\"features\":[\"printing\"],\"name\":\"syn\",\"req\":\"^2.0.89\"},{\"default_features\":false,\"name\":\"wasm-metadata\",\"req\":\"^0.244.0\"},{\"name\":\"wit-bindgen-core\",\"req\":\"^0.51.0\"},{\"name\":\"wit-component\",\"req\":\"^0.244.0\"}],\"features\":{\"clap\":[\"dep:clap\",\"wit-bindgen-core/clap\"],\"serde\":[\"dep:serde\",\"wit-bindgen-core/serde\"]}}", "wit-bindgen_0.51.0": "{\"dependencies\":[{\"name\":\"alloc\",\"optional\":true,\"package\":\"rustc-std-workspace-alloc\",\"req\":\"^1.0\"},{\"name\":\"bitflags\",\"optional\":true,\"req\":\"^2.3.3\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0\"},{\"name\":\"futures\",\"optional\":true,\"req\":\"^0.3.30\"},{\"name\":\"wit-bindgen-rust-macro\",\"optional\":true,\"req\":\"^0.51.0\"}],\"features\":{\"async\":[\"std\",\"wit-bindgen-rust-macro?/async\"],\"async-spawn\":[\"async\",\"dep:futures\"],\"bitflags\":[\"dep:bitflags\"],\"default\":[\"macros\",\"realloc\",\"async\",\"std\",\"bitflags\"],\"inter-task-wakeup\":[\"async\"],\"macros\":[\"dep:wit-bindgen-rust-macro\"],\"realloc\":[],\"rustc-dep-of-std\":[\"dep:core\",\"dep:alloc\"],\"std\":[]}}", + "wit-component_0.244.0": "{\"dependencies\":[{\"name\":\"anyhow\",\"req\":\"^1.0.58\"},{\"name\":\"bitflags\",\"req\":\"^2.3.3\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.11\"},{\"kind\":\"dev\",\"name\":\"glob\",\"req\":\"^0.3.0\"},{\"default_features\":false,\"name\":\"indexmap\",\"req\":\"^2.7.0\"},{\"kind\":\"dev\",\"name\":\"libtest-mimic\",\"req\":\"^0.8.1\"},{\"name\":\"log\",\"req\":\"^0.4.17\"},{\"kind\":\"dev\",\"name\":\"pretty_assertions\",\"req\":\"^1.3.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde\",\"req\":\"^1.0.166\"},{\"name\":\"serde_derive\",\"req\":\"^1.0.166\"},{\"name\":\"serde_json\",\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"std\",\"wasmparser\"],\"name\":\"wasm-encoder\",\"req\":\"^0.244.0\"},{\"default_features\":false,\"name\":\"wasm-metadata\",\"req\":\"^0.244.0\"},{\"default_features\":false,\"features\":[\"oci\"],\"kind\":\"dev\",\"name\":\"wasm-metadata\",\"req\":\"^0.244.0\"},{\"default_features\":false,\"features\":[\"simd\",\"std\",\"component-model\",\"simd\"],\"name\":\"wasmparser\",\"req\":\"^0.244.0\"},{\"default_features\":false,\"features\":[\"simd\",\"std\",\"component-model\",\"features\"],\"kind\":\"dev\",\"name\":\"wasmparser\",\"req\":\"^0.244.0\"},{\"default_features\":false,\"features\":[\"component-model\"],\"kind\":\"dev\",\"name\":\"wasmprinter\",\"req\":\"^0.244.0\"},{\"default_features\":false,\"features\":[\"cranelift\",\"component-model\",\"runtime\",\"gc-drc\"],\"kind\":\"dev\",\"name\":\"wasmtime\",\"req\":\"^34.0.1\",\"target\":\"cfg(not(target_family = \\\"wasm\\\"))\"},{\"default_features\":false,\"name\":\"wast\",\"optional\":true,\"req\":\"^244.0.0\"},{\"default_features\":false,\"name\":\"wat\",\"optional\":true,\"req\":\"^1.244.0\"},{\"default_features\":false,\"features\":[\"component-model\"],\"kind\":\"dev\",\"name\":\"wat\",\"req\":\"^1.244.0\"},{\"features\":[\"decoding\",\"serde\"],\"name\":\"wit-parser\",\"req\":\"^0.244.0\"}],\"features\":{\"dummy-module\":[\"dep:wat\"],\"semver-check\":[\"dummy-module\"],\"wat\":[\"dep:wast\",\"dep:wat\"]}}", + "wit-parser_0.244.0": "{\"dependencies\":[{\"name\":\"anyhow\",\"req\":\"^1.0.58\"},{\"kind\":\"dev\",\"name\":\"env_logger\",\"req\":\"^0.11\"},{\"name\":\"id-arena\",\"req\":\"^2\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"indexmap\",\"req\":\"^2.7.0\"},{\"kind\":\"dev\",\"name\":\"libtest-mimic\",\"req\":\"^0.8.1\"},{\"name\":\"log\",\"req\":\"^0.4.17\"},{\"kind\":\"dev\",\"name\":\"pretty_assertions\",\"req\":\"^1.3.0\"},{\"default_features\":false,\"name\":\"semver\",\"req\":\"^1.0.0\"},{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.166\"},{\"name\":\"serde_derive\",\"optional\":true,\"req\":\"^1.0.166\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1\"},{\"name\":\"unicode-xid\",\"req\":\"^0.2.2\"},{\"default_features\":false,\"features\":[\"simd\",\"std\",\"validate\",\"component-model\",\"features\"],\"name\":\"wasmparser\",\"optional\":true,\"req\":\"^0.244.0\"},{\"default_features\":false,\"features\":[\"component-model\"],\"name\":\"wat\",\"optional\":true,\"req\":\"^1.244.0\"}],\"features\":{\"decoding\":[\"dep:wasmparser\"],\"default\":[\"serde\",\"decoding\"],\"serde\":[\"dep:serde\",\"dep:serde_derive\",\"indexmap/serde\",\"serde_json\"],\"wat\":[\"decoding\",\"dep:wat\"]}}", "wl-clipboard-rs_0.9.3": "{\"dependencies\":[{\"name\":\"libc\",\"req\":\"^0.2.168\"},{\"name\":\"log\",\"req\":\"^0.4.11\"},{\"features\":[\"io_safety\"],\"name\":\"os_pipe\",\"req\":\"^1.1\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"proptest-derive\",\"req\":\"^0.7\"},{\"features\":[\"fs\",\"event\"],\"name\":\"rustix\",\"req\":\"^1.0.2\"},{\"name\":\"thiserror\",\"req\":\"^2\"},{\"name\":\"tree_magic_mini\",\"req\":\"^3\"},{\"name\":\"wayland-backend\",\"req\":\"^0.3.11\"},{\"name\":\"wayland-client\",\"req\":\"^0.31.11\"},{\"features\":[\"client\",\"staging\"],\"name\":\"wayland-protocols\",\"req\":\"^0.32.9\"},{\"features\":[\"server\",\"staging\"],\"kind\":\"dev\",\"name\":\"wayland-protocols\",\"req\":\"^0.32.9\"},{\"features\":[\"client\"],\"name\":\"wayland-protocols-wlr\",\"req\":\"^0.3.9\"},{\"features\":[\"server\"],\"kind\":\"dev\",\"name\":\"wayland-protocols-wlr\",\"req\":\"^0.3.9\"},{\"kind\":\"dev\",\"name\":\"wayland-server\",\"req\":\"^0.31.10\"}],\"features\":{\"dlopen\":[\"native_lib\",\"wayland-backend/dlopen\",\"wayland-backend/dlopen\"],\"native_lib\":[\"wayland-backend/client_system\",\"wayland-backend/server_system\"]}}", "writeable_0.6.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"default_features\":false,\"name\":\"either\",\"optional\":true,\"req\":\"^1.9.0\"},{\"features\":[\"small_rng\"],\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9\"}],\"features\":{\"alloc\":[],\"default\":[\"alloc\"],\"either\":[\"dep:either\"]}}", "x11rb-protocol_0.13.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5\"},{\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"all-extensions\":[\"composite\",\"damage\",\"dbe\",\"dpms\",\"dri2\",\"dri3\",\"glx\",\"present\",\"randr\",\"record\",\"render\",\"res\",\"screensaver\",\"shape\",\"shm\",\"sync\",\"xevie\",\"xf86dri\",\"xf86vidmode\",\"xfixes\",\"xinerama\",\"xinput\",\"xkb\",\"xprint\",\"xselinux\",\"xtest\",\"xv\",\"xvmc\"],\"composite\":[\"xfixes\"],\"damage\":[\"xfixes\"],\"dbe\":[],\"default\":[\"std\"],\"dpms\":[],\"dri2\":[],\"dri3\":[],\"extra-traits\":[],\"glx\":[],\"present\":[\"randr\",\"xfixes\",\"sync\",\"dri3\"],\"randr\":[\"render\"],\"record\":[],\"render\":[],\"request-parsing\":[],\"res\":[],\"resource_manager\":[\"std\"],\"screensaver\":[],\"shape\":[],\"shm\":[],\"std\":[],\"sync\":[],\"xevie\":[],\"xf86dri\":[],\"xf86vidmode\":[],\"xfixes\":[\"render\",\"shape\"],\"xinerama\":[],\"xinput\":[\"xfixes\"],\"xkb\":[],\"xprint\":[],\"xselinux\":[],\"xtest\":[],\"xv\":[\"shm\"],\"xvmc\":[\"xv\"]}}", "x11rb_0.13.2": "{\"dependencies\":[{\"name\":\"as-raw-xcb-connection\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"gethostname\",\"req\":\"^1.0\"},{\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2\"},{\"name\":\"libloading\",\"optional\":true,\"req\":\"^0.8.0\"},{\"name\":\"once_cell\",\"optional\":true,\"req\":\"^1.19\"},{\"kind\":\"dev\",\"name\":\"polling\",\"req\":\"^3.4\"},{\"name\":\"raw-window-handle\",\"optional\":true,\"req\":\"^0.5.0\"},{\"default_features\":false,\"features\":[\"std\",\"event\",\"fs\",\"net\",\"system\"],\"name\":\"rustix\",\"req\":\"^1.0\"},{\"default_features\":false,\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"tracing-subscriber\",\"req\":\"^0.3\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"x11rb-protocol\",\"req\":\"^0.13.2\"},{\"name\":\"xcursor\",\"optional\":true,\"req\":\"^0.3.7\"}],\"features\":{\"all-extensions\":[\"x11rb-protocol/all-extensions\",\"composite\",\"damage\",\"dbe\",\"dpms\",\"dri2\",\"dri3\",\"glx\",\"present\",\"randr\",\"record\",\"render\",\"res\",\"screensaver\",\"shape\",\"shm\",\"sync\",\"xevie\",\"xf86dri\",\"xf86vidmode\",\"xfixes\",\"xinerama\",\"xinput\",\"xkb\",\"xprint\",\"xselinux\",\"xtest\",\"xv\",\"xvmc\"],\"allow-unsafe-code\":[\"libc\",\"as-raw-xcb-connection\"],\"composite\":[\"x11rb-protocol/composite\",\"xfixes\"],\"cursor\":[\"render\",\"resource_manager\",\"xcursor\"],\"damage\":[\"x11rb-protocol/damage\",\"xfixes\"],\"dbe\":[\"x11rb-protocol/dbe\"],\"dl-libxcb\":[\"allow-unsafe-code\",\"libloading\",\"once_cell\"],\"dpms\":[\"x11rb-protocol/dpms\"],\"dri2\":[\"x11rb-protocol/dri2\"],\"dri3\":[\"x11rb-protocol/dri3\"],\"extra-traits\":[\"x11rb-protocol/extra-traits\"],\"glx\":[\"x11rb-protocol/glx\"],\"image\":[],\"present\":[\"x11rb-protocol/present\",\"randr\",\"xfixes\",\"sync\"],\"randr\":[\"x11rb-protocol/randr\",\"render\"],\"record\":[\"x11rb-protocol/record\"],\"render\":[\"x11rb-protocol/render\"],\"request-parsing\":[\"x11rb-protocol/request-parsing\"],\"res\":[\"x11rb-protocol/res\"],\"resource_manager\":[\"x11rb-protocol/resource_manager\"],\"screensaver\":[\"x11rb-protocol/screensaver\"],\"shape\":[\"x11rb-protocol/shape\"],\"shm\":[\"x11rb-protocol/shm\"],\"sync\":[\"x11rb-protocol/sync\"],\"xevie\":[\"x11rb-protocol/xevie\"],\"xf86dri\":[\"x11rb-protocol/xf86dri\"],\"xf86vidmode\":[\"x11rb-protocol/xf86vidmode\"],\"xfixes\":[\"x11rb-protocol/xfixes\",\"render\",\"shape\"],\"xinerama\":[\"x11rb-protocol/xinerama\"],\"xinput\":[\"x11rb-protocol/xinput\",\"xfixes\"],\"xkb\":[\"x11rb-protocol/xkb\"],\"xprint\":[\"x11rb-protocol/xprint\"],\"xselinux\":[\"x11rb-protocol/xselinux\"],\"xtest\":[\"x11rb-protocol/xtest\"],\"xv\":[\"x11rb-protocol/xv\",\"shm\"],\"xvmc\":[\"x11rb-protocol/xvmc\",\"xv\"]}}", "x25519-dalek_2.0.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"bincode\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.5\"},{\"default_features\":false,\"name\":\"curve25519-dalek\",\"req\":\"^4\"},{\"default_features\":false,\"name\":\"rand_core\",\"req\":\"^0.6\"},{\"default_features\":false,\"features\":[\"getrandom\"],\"kind\":\"dev\",\"name\":\"rand_core\",\"req\":\"^0.6\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"zeroize_derive\"],\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"alloc\":[\"curve25519-dalek/alloc\",\"serde?/alloc\",\"zeroize?/alloc\"],\"default\":[\"alloc\",\"precomputed-tables\",\"zeroize\"],\"getrandom\":[\"rand_core/getrandom\"],\"precomputed-tables\":[\"curve25519-dalek/precomputed-tables\"],\"reusable_secrets\":[],\"serde\":[\"dep:serde\",\"curve25519-dalek/serde\"],\"static_secrets\":[],\"zeroize\":[\"dep:zeroize\",\"curve25519-dalek/zeroize\"]}}", "x509-parser_0.18.1": "{\"dependencies\":[{\"features\":[\"datetime\"],\"name\":\"asn1-rs\",\"req\":\"^0.7.0\"},{\"name\":\"aws-lc-rs\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"data-encoding\",\"req\":\"^2.2.1\"},{\"features\":[\"bigint\"],\"name\":\"der-parser\",\"req\":\"^10.0\"},{\"name\":\"lazy_static\",\"req\":\"^1.4\"},{\"name\":\"nom\",\"req\":\"^7.0\"},{\"features\":[\"crypto\",\"x509\",\"x962\"],\"name\":\"oid-registry\",\"req\":\"^0.8.1\"},{\"name\":\"ring\",\"optional\":true,\"req\":\"^0.17.12\"},{\"name\":\"rusticata-macros\",\"req\":\"^4.0\"},{\"name\":\"thiserror\",\"req\":\"^2.0\"},{\"features\":[\"formatting\"],\"name\":\"time\",\"req\":\"^0.3.35\"}],\"features\":{\"default\":[],\"validate\":[],\"verify\":[\"ring\"],\"verify-aws\":[\"aws-lc-rs\"]}}", + "xattr_1.6.1": "{\"dependencies\":[{\"name\":\"libc\",\"req\":\"^0.2.150\",\"target\":\"cfg(any(target_os = \\\"freebsd\\\", target_os = \\\"netbsd\\\"))\"},{\"default_features\":false,\"features\":[\"fs\",\"std\"],\"name\":\"rustix\",\"req\":\"^1.0.0\",\"target\":\"cfg(any(target_os = \\\"android\\\", target_os = \\\"linux\\\", target_os = \\\"macos\\\", target_os = \\\"hurd\\\"))\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{\"default\":[\"unsupported\"],\"unsupported\":[]}}", "xdg-home_1.3.0": "{\"dependencies\":[{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"features\":[\"Win32_Foundation\",\"Win32_UI_Shell\",\"Win32_System_Com\"],\"name\":\"windows-sys\",\"req\":\"^0.59\",\"target\":\"cfg(windows)\"}],\"features\":{}}", "xz2_0.1.7": "{\"dependencies\":[{\"name\":\"futures\",\"optional\":true,\"req\":\"^0.1.26\"},{\"name\":\"lzma-sys\",\"req\":\"^0.1.18\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.0\"},{\"kind\":\"dev\",\"name\":\"tokio-core\",\"req\":\"^0.1.17\"},{\"name\":\"tokio-io\",\"optional\":true,\"req\":\"^0.1.12\"}],\"features\":{\"static\":[\"lzma-sys/static\"],\"tokio\":[\"tokio-io\",\"futures\"]}}", "yaml-rust_0.4.5": "{\"dependencies\":[{\"name\":\"linked-hash-map\",\"req\":\"^0.5.3\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^0.9\"}],\"features\":{}}", @@ -1561,6 +1624,7 @@ "zerovec_0.11.5": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"databake\",\"optional\":true,\"req\":\"^0.2.0\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.220\"},{\"default_features\":false,\"features\":[\"xxhash64\"],\"name\":\"twox-hash\",\"optional\":true,\"req\":\"^2.0.0\"},{\"default_features\":false,\"name\":\"yoke\",\"optional\":true,\"req\":\"^0.8.0\"},{\"default_features\":false,\"name\":\"zerofrom\",\"req\":\"^0.1.3\"},{\"default_features\":false,\"name\":\"zerovec-derive\",\"optional\":true,\"req\":\"^0.11.1\"}],\"features\":{\"alloc\":[\"serde?/alloc\"],\"databake\":[\"dep:databake\"],\"derive\":[\"dep:zerovec-derive\"],\"hashmap\":[\"dep:twox-hash\",\"alloc\"],\"serde\":[\"dep:serde\"],\"std\":[],\"yoke\":[\"dep:yoke\"]}}", "zip_2.4.2": "{\"dependencies\":[{\"name\":\"aes\",\"optional\":true,\"req\":\"^0.8\"},{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1.0.95\"},{\"features\":[\"derive\"],\"name\":\"arbitrary\",\"req\":\"^1.4.1\",\"target\":\"cfg(fuzzing)\"},{\"kind\":\"dev\",\"name\":\"bencher\",\"req\":\"^0.1.5\"},{\"name\":\"bzip2\",\"optional\":true,\"req\":\"^0.5.0\"},{\"name\":\"chrono\",\"optional\":true,\"req\":\"^0.4\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"=4.4.18\"},{\"name\":\"constant_time_eq\",\"optional\":true,\"req\":\"^0.3\"},{\"name\":\"crc32fast\",\"req\":\"^1.4\"},{\"name\":\"crossbeam-utils\",\"req\":\"^0.8.21\",\"target\":\"cfg(any(all(target_arch = \\\"arm\\\", target_pointer_width = \\\"32\\\"), target_arch = \\\"mips\\\", target_arch = \\\"powerpc\\\"))\"},{\"name\":\"deflate64\",\"optional\":true,\"req\":\"^0.1.9\"},{\"default_features\":false,\"name\":\"displaydoc\",\"req\":\"^0.2\"},{\"default_features\":false,\"name\":\"flate2\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"wasm_js\",\"std\"],\"name\":\"getrandom\",\"optional\":true,\"req\":\"^0.3.1\"},{\"features\":[\"wasm_js\",\"std\"],\"kind\":\"dev\",\"name\":\"getrandom\",\"req\":\"^0.3.1\"},{\"features\":[\"reset\"],\"name\":\"hmac\",\"optional\":true,\"req\":\"^0.12\"},{\"name\":\"indexmap\",\"req\":\"^2\"},{\"default_features\":false,\"name\":\"lzma-rs\",\"optional\":true,\"req\":\"^0.3\"},{\"name\":\"memchr\",\"req\":\"^2.7\"},{\"default_features\":false,\"name\":\"nt-time\",\"optional\":true,\"req\":\"^0.10.6\"},{\"name\":\"pbkdf2\",\"optional\":true,\"req\":\"^0.12\"},{\"name\":\"sha1\",\"optional\":true,\"req\":\"^0.10\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3.15\"},{\"name\":\"thiserror\",\"req\":\"^2\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"time\",\"optional\":true,\"req\":\"^0.3.37\"},{\"default_features\":false,\"features\":[\"formatting\",\"macros\"],\"kind\":\"dev\",\"name\":\"time\",\"req\":\"^0.3.37\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.5\"},{\"name\":\"xz2\",\"optional\":true,\"req\":\"^0.1.7\"},{\"features\":[\"zeroize_derive\"],\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1.8\"},{\"name\":\"zopfli\",\"optional\":true,\"req\":\"^0.8\"},{\"default_features\":false,\"name\":\"zstd\",\"optional\":true,\"req\":\"^0.13\"}],\"features\":{\"_all-features\":[],\"_deflate-any\":[],\"aes-crypto\":[\"aes\",\"constant_time_eq\",\"hmac\",\"pbkdf2\",\"sha1\",\"getrandom\",\"zeroize\"],\"chrono\":[\"chrono/default\"],\"default\":[\"aes-crypto\",\"bzip2\",\"deflate64\",\"deflate\",\"lzma\",\"time\",\"zstd\",\"xz\"],\"deflate\":[\"flate2/rust_backend\",\"deflate-zopfli\",\"deflate-flate2\"],\"deflate-flate2\":[\"_deflate-any\"],\"deflate-miniz\":[\"deflate\",\"deflate-flate2\"],\"deflate-zlib\":[\"flate2/zlib\",\"deflate-flate2\"],\"deflate-zlib-ng\":[\"flate2/zlib-ng\",\"deflate-flate2\"],\"deflate-zopfli\":[\"zopfli\",\"_deflate-any\"],\"lzma\":[\"lzma-rs/stream\"],\"nt-time\":[\"dep:nt-time\"],\"unreserved\":[],\"xz\":[\"dep:xz2\"]}}", "zmij_1.0.19": "{\"dependencies\":[{\"default_features\":false,\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.8\",\"target\":\"cfg(not(miri))\"},{\"name\":\"no-panic\",\"optional\":true,\"req\":\"^0.1.36\"},{\"kind\":\"dev\",\"name\":\"num-bigint\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"num-integer\",\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"num_cpus\",\"req\":\"^1.8\"},{\"kind\":\"dev\",\"name\":\"opt-level\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9\"},{\"kind\":\"dev\",\"name\":\"ryu\",\"req\":\"^1\"}],\"features\":{}}", + "zmij_1.0.21": "{\"dependencies\":[{\"default_features\":false,\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.8\",\"target\":\"cfg(not(miri))\"},{\"name\":\"no-panic\",\"optional\":true,\"req\":\"^0.1.36\"},{\"kind\":\"dev\",\"name\":\"num-bigint\",\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"num-integer\",\"req\":\"^0.1\"},{\"kind\":\"dev\",\"name\":\"num_cpus\",\"req\":\"^1.8\"},{\"kind\":\"dev\",\"name\":\"opt-level\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.10\"},{\"kind\":\"dev\",\"name\":\"ryu\",\"req\":\"^1\"}],\"features\":{}}", "zoneinfo64_0.2.1": "{\"dependencies\":[{\"default_features\":false,\"name\":\"calendrical_calculations\",\"req\":\"^0.2.3\"},{\"name\":\"chrono\",\"optional\":true,\"req\":\"^0.4\"},{\"kind\":\"dev\",\"name\":\"chrono-tz\",\"req\":\"^0.10.4\"},{\"default_features\":false,\"name\":\"icu_locale_core\",\"req\":\"^2.1.0\"},{\"kind\":\"dev\",\"name\":\"itertools\",\"req\":\"^0.14.0\"},{\"default_features\":false,\"features\":[\"tzdb-bundle-always\",\"std\"],\"kind\":\"dev\",\"name\":\"jiff\",\"req\":\"^0.2.15\"},{\"default_features\":false,\"name\":\"potential_utf\",\"req\":\"^0.1.3\"},{\"default_features\":false,\"name\":\"resb\",\"req\":\"^0.1.0\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"serde\",\"req\":\"^1.0.220\"}],\"features\":{\"chrono\":[\"dep:chrono\"]}}", "zopfli_0.8.3": "{\"dependencies\":[{\"name\":\"bumpalo\",\"req\":\"^3.19.0\"},{\"default_features\":false,\"name\":\"crc32fast\",\"optional\":true,\"req\":\"^1.5.0\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.28\"},{\"kind\":\"dev\",\"name\":\"miniz_oxide\",\"req\":\"^0.8.9\"},{\"kind\":\"dev\",\"name\":\"proptest\",\"req\":\"^1.7.0\"},{\"kind\":\"dev\",\"name\":\"proptest-derive\",\"req\":\"^0.6.0\"},{\"default_features\":false,\"name\":\"simd-adler32\",\"optional\":true,\"req\":\"^0.3.7\"}],\"features\":{\"default\":[\"gzip\",\"std\",\"zlib\"],\"gzip\":[\"dep:crc32fast\"],\"nightly\":[\"crc32fast?/nightly\"],\"std\":[\"crc32fast?/std\",\"dep:log\",\"simd-adler32?/std\"],\"zlib\":[\"dep:simd-adler32\"]}}", "zstd-safe_7.2.4": "{\"dependencies\":[{\"default_features\":false,\"name\":\"zstd-sys\",\"req\":\"^2.0.15\"}],\"features\":{\"arrays\":[],\"bindgen\":[\"zstd-sys/bindgen\"],\"debug\":[\"zstd-sys/debug\"],\"default\":[\"legacy\",\"arrays\",\"zdict_builder\"],\"doc-cfg\":[],\"experimental\":[\"zstd-sys/experimental\"],\"fat-lto\":[\"zstd-sys/fat-lto\"],\"legacy\":[\"zstd-sys/legacy\"],\"no_asm\":[\"zstd-sys/no_asm\"],\"pkg-config\":[\"zstd-sys/pkg-config\"],\"seekable\":[\"zstd-sys/seekable\"],\"std\":[\"zstd-sys/std\"],\"thin\":[\"zstd-sys/thin\"],\"thin-lto\":[\"zstd-sys/thin-lto\"],\"zdict_builder\":[\"zstd-sys/zdict_builder\"],\"zstdmt\":[\"zstd-sys/zstdmt\"]}}", diff --git a/codex-rs/BUILD.bazel b/codex-rs/BUILD.bazel index b6711d9b81..66c7ebcb61 100644 --- a/codex-rs/BUILD.bazel +++ b/codex-rs/BUILD.bazel @@ -2,3 +2,17 @@ exports_files([ "clippy.toml", "node-version.txt", ]) + +filegroup( + name = "workspace-files", + srcs = glob( + [ + "*", + ".cargo/**", + ], + exclude = [ + "BUILD.bazel", + ], + ), + visibility = ["//visibility:public"], +) diff --git a/defs.bzl b/defs.bzl index 02cbbc6295..d23398c8fd 100644 --- a/defs.bzl +++ b/defs.bzl @@ -57,6 +57,9 @@ def _workspace_root_test_impl(ctx): ) runfiles = ctx.runfiles(files = [test_bin, workspace_root_marker]).merge(ctx.attr.test_bin[DefaultInfo].default_runfiles) + for data_dep in ctx.attr.data: + runfiles = runfiles.merge(ctx.runfiles(files = data_dep[DefaultInfo].files.to_list())) + runfiles = runfiles.merge(data_dep[DefaultInfo].default_runfiles) return [ DefaultInfo( @@ -73,6 +76,9 @@ workspace_root_test = rule( implementation = _workspace_root_test_impl, test = True, attrs = { + "data": attr.label_list( + allow_files = True, + ), "env": attr.string_dict(), "test_bin": attr.label( cfg = "target", @@ -157,10 +163,29 @@ def codex_rust_crate( "INSTA_SNAPSHOT_PATH": "src", } + native.filegroup( + name = "package-files", + srcs = native.glob( + ["**"], + exclude = [ + "**/BUILD.bazel", + "BUILD.bazel", + "target/**", + ], + allow_empty = True, + ), + visibility = ["//visibility:public"], + ) + rustc_env = { "BAZEL_PACKAGE": native.package_name(), } | rustc_env + manifest_relpath = native.package_name() + if manifest_relpath.startswith("codex-rs/"): + manifest_relpath = manifest_relpath[len("codex-rs/"):] + manifest_path = manifest_relpath + "/Cargo.toml" + binaries = DEP_DATA.get(native.package_name())["binaries"] lib_srcs = crate_srcs or native.glob(["src/**/*.rs"], exclude = binaries.values(), allow_empty = True) diff --git a/justfile b/justfile index 39a65df46d..a39d2dd6ba 100644 --- a/justfile +++ b/justfile @@ -67,13 +67,17 @@ bazel-lock-check: ./scripts/check-module-bazel-lock.sh bazel-test: - bazel test //... --keep_going + bazel test --test_tag_filters=-argument-comment-lint //... --keep_going bazel-clippy: bazel build --config=clippy -- //codex-rs/... -//codex-rs/v8-poc:all +[no-cd] +bazel-argument-comment-lint: + bazel build --config=argument-comment-lint -- //codex-rs/... + bazel-remote-test: - bazel test //... --config=remote --platforms=//:rbe --keep_going + bazel test --test_tag_filters=-argument-comment-lint //... --config=remote --platforms=//:rbe --keep_going build-for-release: bazel build //codex-rs/cli:release_binaries --config=remote @@ -97,7 +101,11 @@ write-hooks-schema: # Run the argument-comment Dylint checks across codex-rs. [no-cd] argument-comment-lint *args: - ./tools/argument-comment-lint/run-prebuilt-linter.py "$@" + if [ "$#" -eq 0 ]; then \ + bazel build --config=argument-comment-lint -- //codex-rs/...; \ + else \ + ./tools/argument-comment-lint/run-prebuilt-linter.py "$@"; \ + fi [no-cd] argument-comment-lint-from-source *args: diff --git a/tools/argument-comment-lint/BUILD.bazel b/tools/argument-comment-lint/BUILD.bazel new file mode 100644 index 0000000000..82d280e30e --- /dev/null +++ b/tools/argument-comment-lint/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library") + +exports_files(["lint_aspect.bzl"]) + +rust_library( + name = "argument-comment-lint-lib", + crate_name = "argument_comment_lint", + crate_features = ["bazel_native"], + crate_root = "src/lib.rs", + srcs = [ + "src/comment_parser.rs", + "src/lib.rs", + ], + edition = "2024", + deps = ["@argument_comment_lint_crates//:clippy_utils"], + tags = ["manual"], + visibility = ["//visibility:public"], +) + +rust_binary( + name = "argument-comment-lint-driver", + crate_name = "argument_comment_lint_driver", + crate_root = "driver.rs", + srcs = ["driver.rs"], + edition = "2024", + deps = [ + ":argument-comment-lint-lib", + "@zlib//:z", + ], + tags = ["manual"], + visibility = ["//visibility:public"], +) diff --git a/tools/argument-comment-lint/Cargo.toml b/tools/argument-comment-lint/Cargo.toml index e4b24694dd..db02b392f3 100644 --- a/tools/argument-comment-lint/Cargo.toml +++ b/tools/argument-comment-lint/Cargo.toml @@ -8,6 +8,9 @@ publish = false [lib] crate-type = ["cdylib"] +[features] +bazel_native = [] + [dependencies] clippy_utils = { git = "https://github.com/rust-lang/rust-clippy", rev = "20ce69b9a63bcd2756cd906fe0964d1e901e042a" } dylint_linting = "5.0.0" diff --git a/tools/argument-comment-lint/README.md b/tools/argument-comment-lint/README.md index 92b0739601..78e28f308f 100644 --- a/tools/argument-comment-lint/README.md +++ b/tools/argument-comment-lint/README.md @@ -85,9 +85,11 @@ rustup toolchain install nightly-2025-09-18 \ The checked-in DotSlash file lives at `tools/argument-comment-lint/argument-comment-lint`. `run-prebuilt-linter.py` resolves that file via `dotslash` and is the path used by -`just clippy`, `just argument-comment-lint`, and the Rust CI job. The -source-build path remains available in `run.py` for people -iterating on the lint crate itself. +targeted package runs such as `just argument-comment-lint -p codex-core`. +Repo-wide runs now go through a native Bazel aspect that invokes a custom +`rustc_driver` and reuses Bazel-managed Rust dependency metadata instead of +spawning `cargo dylint` once per crate. The source-build path remains available +in `run.py` for people iterating on the lint crate itself. The Unix archive layout is: @@ -126,15 +128,17 @@ If you are changing the lint crate itself, use the source-build wrapper: Run the lint against `codex-rs` from the repo root: ```bash +just argument-comment-lint +bazel build --config=argument-comment-lint -- //codex-rs/... ./tools/argument-comment-lint/run-prebuilt-linter.py -p codex-core just argument-comment-lint -p codex-core ``` -If no package selection is provided, `run-prebuilt-linter.py` defaults to checking the -`codex-rs` workspace with `--workspace --no-deps`. -For non-`--fix` runs, both wrappers also default the underlying Cargo -invocation to `--all-targets` unless you explicitly narrow the target set, so -workspace and package lint runs both cover test-only call sites by default. +If no package selection is provided, `just argument-comment-lint` now defaults +to the Bazel aspect path over `//codex-rs/...`. The Python wrappers remain the +package-scoped escape hatch and still default the underlying Cargo invocation +to `--all-targets` unless you explicitly narrow the target set, so targeted +wrapper runs cover test-only call sites by default. Repo runs also promote `uncommented_anonymous_literal_argument` to an error by default: diff --git a/tools/argument-comment-lint/driver.rs b/tools/argument-comment-lint/driver.rs new file mode 100644 index 0000000000..b6417d45fd --- /dev/null +++ b/tools/argument-comment-lint/driver.rs @@ -0,0 +1,43 @@ +#![feature(rustc_private)] + +extern crate rustc_driver; +extern crate rustc_interface; + +use std::env; +use std::ffi::OsString; +use std::path::Path; + +fn main() { + let mut callbacks = Callbacks; + let args = rustc_args(env::args_os().skip(1).collect()); + rustc_driver::run_compiler(&args, &mut callbacks); +} + +struct Callbacks; + +impl rustc_driver::Callbacks for Callbacks { + fn config(&mut self, config: &mut rustc_interface::Config) { + let previous = config.register_lints.take(); + config.register_lints = Some(Box::new(move |sess, lint_store| { + if let Some(previous) = &previous { + previous(sess, lint_store); + } + argument_comment_lint::register_lints(sess, lint_store); + })); + } +} + +fn rustc_args(args: Vec) -> Vec { + let mut rustc_args: Vec = args + .into_iter() + .map(|arg| arg.to_string_lossy().into_owned()) + .collect(); + if rustc_args.first().is_none_or(|arg| !is_rustc(arg)) { + rustc_args.insert(0, "rustc".to_string()); + } + rustc_args +} + +fn is_rustc(arg: &str) -> bool { + Path::new(arg).file_stem().and_then(|stem| stem.to_str()) == Some("rustc") +} diff --git a/tools/argument-comment-lint/lint_aspect.bzl b/tools/argument-comment-lint/lint_aspect.bzl new file mode 100644 index 0000000000..2f0878d9f8 --- /dev/null +++ b/tools/argument-comment-lint/lint_aspect.bzl @@ -0,0 +1,187 @@ +"""Bazel aspect for running argument-comment-lint on Rust targets.""" + +load("@rules_rust//rust:defs.bzl", "rust_common") +load("@rules_rust//rust/private:rust.bzl", "RUSTC_ATTRS") +load( + "@rules_rust//rust/private:rustc.bzl", + "collect_deps", + "collect_inputs", + "construct_arguments", +) +load( + "@rules_rust//rust/private:utils.bzl", + "determine_output_hash", + "find_cc_toolchain", + "find_toolchain", +) + +_STRICT_LINT_FLAGS = [ + "-Duncommented-anonymous-literal-argument", + "-Aunknown-lints", +] + +def _find_rustc_driver_library(toolchain): + for file in toolchain.rustc_lib.to_list(): + if file.basename.startswith("librustc_driver-") or file.basename.startswith("rustc_driver-"): + return file + return None + +def _prepend_runtime_path(env, key, path, separator): + previous = env.get(key) + env[key] = "{}{}{}".format(path, separator, previous) if previous else path + +def _set_driver_runtime_env(env, toolchain): + driver_library = _find_rustc_driver_library(toolchain) + if not driver_library: + return + + library_dir = driver_library.dirname + if driver_library.basename.endswith(".dll"): + _prepend_runtime_path(env, "PATH", library_dir, ";") + return + + # The lint driver runs in exec configuration. Under remote execution the + # exec OS can differ from the Rust target OS, so populate both Unix loader + # variables from the located driver library instead of keying off target_os. + _prepend_runtime_path(env, "LD_LIBRARY_PATH", library_dir, ":") + _prepend_runtime_path(env, "DYLD_LIBRARY_PATH", library_dir, ":") + +def _get_argument_comment_lint_ready_crate_info(target, aspect_ctx): + if target.label.workspace_root.startswith("external"): + return None + + if aspect_ctx: + ignore_tags = [ + "no_argument_comment_lint", + "no-lint", + "no_lint", + "nolint", + ] + for tag in aspect_ctx.rule.attr.tags: + if tag.replace("-", "_").lower() in ignore_tags: + return None + + if rust_common.crate_info in target: + return target[rust_common.crate_info] + if rust_common.test_crate_info in target: + return target[rust_common.test_crate_info].crate + return None + +def _rust_argument_comment_lint_aspect_impl(target, ctx): + if OutputGroupInfo in target and hasattr(target[OutputGroupInfo], "argument_comment_lint_checks"): + return [] + + crate_info = _get_argument_comment_lint_ready_crate_info(target, ctx) + if not crate_info: + return [] + + toolchain = find_toolchain(ctx) + cc_toolchain, feature_configuration = find_cc_toolchain(ctx) + + dep_info, build_info, _ = collect_deps( + deps = crate_info.deps.to_list(), + proc_macro_deps = crate_info.proc_macro_deps.to_list(), + aliases = crate_info.aliases, + ) + + compile_inputs, out_dir, build_env_files, build_flags_files, linkstamp_outs, ambiguous_libs = collect_inputs( + ctx, + ctx.rule.file, + ctx.rule.files, + depset([]), + toolchain, + cc_toolchain, + feature_configuration, + crate_info, + dep_info, + build_info, + [], + ) + + success_marker = ctx.actions.declare_file( + ctx.label.name + ".argument_comment_lint.ok", + sibling = crate_info.output, + ) + + args, env = construct_arguments( + ctx = ctx, + attr = ctx.rule.attr, + file = ctx.file, + toolchain = toolchain, + tool_path = ctx.executable._driver.path, + cc_toolchain = cc_toolchain, + feature_configuration = feature_configuration, + crate_info = crate_info, + dep_info = dep_info, + linkstamp_outs = linkstamp_outs, + ambiguous_libs = ambiguous_libs, + output_hash = determine_output_hash(crate_info.root, ctx.label), + rust_flags = [], + out_dir = out_dir, + build_env_files = build_env_files, + build_flags_files = build_flags_files, + emit = ["dep-info", "metadata"], + skip_expanding_rustc_env = True, + ) + + if crate_info.is_test: + args.rustc_flags.add("--test") + + args.process_wrapper_flags.add("--touch-file", success_marker) + args.rustc_flags.add_all(_STRICT_LINT_FLAGS) + _set_driver_runtime_env(env, toolchain) + + driver_runfiles = ctx.attr._driver[DefaultInfo].default_runfiles.files + action_inputs = depset( + transitive = [ + compile_inputs, + driver_runfiles, + toolchain.rustc_lib, + ], + ) + + ctx.actions.run( + executable = ctx.executable._process_wrapper, + inputs = action_inputs, + outputs = [success_marker], + env = env, + tools = [ctx.executable._driver], + execution_requirements = { + "no-sandbox": "1", + }, + arguments = args.all, + mnemonic = "ArgumentCommentLint", + progress_message = "ArgumentCommentLint %{label}", + toolchain = "@rules_rust//rust:toolchain_type", + ) + + return [OutputGroupInfo(argument_comment_lint_checks = depset([success_marker]))] + +rust_argument_comment_lint_aspect = aspect( + implementation = _rust_argument_comment_lint_aspect_impl, + fragments = ["cpp"], + attrs = { + "_driver": attr.label( + default = Label("//tools/argument-comment-lint:argument-comment-lint-driver"), + executable = True, + cfg = "exec", + ), + } | RUSTC_ATTRS, + toolchains = [ + str(Label("@rules_rust//rust:toolchain_type")), + config_common.toolchain_type("@bazel_tools//tools/cpp:toolchain_type", mandatory = False), + ], + required_providers = [ + [rust_common.crate_info], + [rust_common.test_crate_info], + ], + doc = """\ +Runs argument-comment-lint on Rust targets using Bazel's Rust dependency graph. + +Example: + +```output +$ bazel build --config=argument-comment-lint //codex-rs/... +``` +""", +) diff --git a/tools/argument-comment-lint/src/lib.rs b/tools/argument-comment-lint/src/lib.rs index fcd3f1bcd0..5586509f24 100644 --- a/tools/argument-comment-lint/src/lib.rs +++ b/tools/argument-comment-lint/src/lib.rs @@ -31,6 +31,7 @@ use rustc_span::Span; use crate::comment_parser::parse_argument_comment; use crate::comment_parser::parse_argument_comment_prefix; +#[cfg(not(feature = "bazel_native"))] dylint_linting::dylint_library!(); #[unsafe(no_mangle)] diff --git a/tools/argument-comment-lint/test_wrapper_common.py b/tools/argument-comment-lint/test_wrapper_common.py index a3a57dfe34..3da6da604b 100644 --- a/tools/argument-comment-lint/test_wrapper_common.py +++ b/tools/argument-comment-lint/test_wrapper_common.py @@ -83,6 +83,26 @@ class WrapperCommonTest(unittest.TestCase): ], ) + def test_explicit_package_manifest_does_not_force_workspace(self) -> None: + parsed = wrapper_common.parse_wrapper_args( + [ + "--manifest-path", + "/tmp/custom/Cargo.toml", + ] + ) + final_args = wrapper_common.build_final_args(parsed, Path("/repo/codex-rs/Cargo.toml")) + + self.assertEqual( + final_args, + [ + "--no-deps", + "--manifest-path", + "/tmp/custom/Cargo.toml", + "--", + "--all-targets", + ], + ) + if __name__ == "__main__": unittest.main() diff --git a/tools/argument-comment-lint/wrapper_common.py b/tools/argument-comment-lint/wrapper_common.py index 3202c22381..75e03ecfbe 100644 --- a/tools/argument-comment-lint/wrapper_common.py +++ b/tools/argument-comment-lint/wrapper_common.py @@ -107,7 +107,7 @@ def build_final_args(parsed: ParsedWrapperArgs, manifest_path: Path) -> list[str if not parsed.has_manifest_path: final_args.extend(["--manifest-path", str(manifest_path)]) - if not parsed.has_package_selection: + if not parsed.has_package_selection and not parsed.has_manifest_path: final_args.append("--workspace") if not parsed.has_no_deps: final_args.append("--no-deps") @@ -205,6 +205,9 @@ def ensure_source_prerequisites(env: MutableMapping[str, str]) -> None: def prefer_rustup_shims(env: MutableMapping[str, str]) -> None: + if env.get("CODEX_ARGUMENT_COMMENT_LINT_SKIP_RUSTUP_SHIMS") == "1": + return + rustup = shutil.which("rustup", path=env.get("PATH")) if rustup is None: return From 48144a7fa41e2343c7622f01e82eb6065e29b7b7 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sat, 28 Mar 2026 13:49:37 -0600 Subject: [PATCH 02/17] Remove remaining custom prompt support (#16115) ## Summary - remove protocol and core support for discovering and listing custom prompts - simplify the TUI slash-command flow and command popup to built-in commands only - delete obsolete custom prompt tests, helpers, and docs references - clean up downstream event handling for the removed protocol events --- codex-rs/core/src/codex.rs | 24 - codex-rs/core/src/custom_prompts.rs | 149 -- codex-rs/core/src/custom_prompts_tests.rs | 95 -- codex-rs/core/src/lib.rs | 1 - codex-rs/mcp-server/src/codex_tool_runner.rs | 1 - codex-rs/protocol/src/custom_prompts.rs | 20 - codex-rs/protocol/src/lib.rs | 1 - codex-rs/protocol/src/protocol.rs | 14 - codex-rs/rollout/src/policy.rs | 1 - codex-rs/tui/src/bottom_pane/chat_composer.rs | 1338 +---------------- codex-rs/tui/src/bottom_pane/command_popup.rs | 326 +--- codex-rs/tui/src/bottom_pane/prompt_args.rs | 829 ---------- codex-rs/tui/src/chatwidget.rs | 3 - docs/prompts.md | 3 - docs/tui-chat-composer.md | 20 +- 15 files changed, 114 insertions(+), 2711 deletions(-) delete mode 100644 codex-rs/core/src/custom_prompts.rs delete mode 100644 codex-rs/core/src/custom_prompts_tests.rs delete mode 100644 codex-rs/protocol/src/custom_prompts.rs delete mode 100644 docs/prompts.md diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 9400af7219..4dca8dc685 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -4385,10 +4385,6 @@ async fn submission_loop(sess: Arc, config: Arc, rx_sub: Receiv handlers::reload_user_config(&sess).await; false } - Op::ListCustomPrompts => { - handlers::list_custom_prompts(&sess, sub.id.clone()).await; - false - } Op::ListSkills { cwds, force_reload } => { handlers::list_skills(&sess, sub.id.clone(), cwds, force_reload).await; false @@ -4514,13 +4510,11 @@ mod handlers { use crate::tasks::UserShellCommandMode; use crate::tasks::UserShellCommandTask; use crate::tasks::execute_user_shell_command; - use codex_protocol::custom_prompts::CustomPrompt; use codex_protocol::protocol::CodexErrorInfo; use codex_protocol::protocol::ErrorEvent; use codex_protocol::protocol::Event; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::InterAgentCommunication; - use codex_protocol::protocol::ListCustomPromptsResponseEvent; use codex_protocol::protocol::ListSkillsResponseEvent; use codex_protocol::protocol::McpServerRefreshConfig; use codex_protocol::protocol::Op; @@ -4907,23 +4901,6 @@ mod handlers { sess.send_event_raw(event).await; } - pub async fn list_custom_prompts(sess: &Session, sub_id: String) { - let custom_prompts: Vec = - if let Some(dir) = crate::custom_prompts::default_prompts_dir() { - crate::custom_prompts::discover_prompts_in(&dir).await - } else { - Vec::new() - }; - - let event = Event { - id: sub_id, - msg: EventMsg::ListCustomPromptsResponse(ListCustomPromptsResponseEvent { - custom_prompts, - }), - }; - sess.send_event_raw(event).await; - } - pub async fn list_skills( sess: &Session, sub_id: String, @@ -6845,7 +6822,6 @@ fn realtime_text_for_event(msg: &EventMsg) -> Option { | EventMsg::TurnDiff(_) | EventMsg::GetHistoryEntryResponse(_) | EventMsg::McpListToolsResponse(_) - | EventMsg::ListCustomPromptsResponse(_) | EventMsg::ListSkillsResponse(_) | EventMsg::SkillsUpdateAvailable | EventMsg::PlanUpdate(_) diff --git a/codex-rs/core/src/custom_prompts.rs b/codex-rs/core/src/custom_prompts.rs deleted file mode 100644 index 54ccaa62fe..0000000000 --- a/codex-rs/core/src/custom_prompts.rs +++ /dev/null @@ -1,149 +0,0 @@ -use codex_protocol::custom_prompts::CustomPrompt; -use std::collections::HashSet; -use std::path::Path; -use std::path::PathBuf; -use tokio::fs; - -/// Return the default prompts directory: `$CODEX_HOME/prompts`. -/// If `CODEX_HOME` cannot be resolved, returns `None`. -pub fn default_prompts_dir() -> Option { - crate::config::find_codex_home() - .ok() - .map(|home| home.join("prompts")) -} - -/// Discover prompt files in the given directory, returning entries sorted by name. -/// Non-files are ignored. If the directory does not exist or cannot be read, returns empty. -pub async fn discover_prompts_in(dir: &Path) -> Vec { - discover_prompts_in_excluding(dir, &HashSet::new()).await -} - -/// Discover prompt files in the given directory, excluding any with names in `exclude`. -/// Returns entries sorted by name. Non-files are ignored. Missing/unreadable dir yields empty. -pub async fn discover_prompts_in_excluding( - dir: &Path, - exclude: &HashSet, -) -> Vec { - let mut out: Vec = Vec::new(); - let mut entries = match fs::read_dir(dir).await { - Ok(entries) => entries, - Err(_) => return out, - }; - - while let Ok(Some(entry)) = entries.next_entry().await { - let path = entry.path(); - let is_file_like = fs::metadata(&path) - .await - .map(|m| m.is_file()) - .unwrap_or(false); - if !is_file_like { - continue; - } - // Only include Markdown files with a .md extension. - let is_md = path - .extension() - .and_then(|s| s.to_str()) - .map(|ext| ext.eq_ignore_ascii_case("md")) - .unwrap_or(false); - if !is_md { - continue; - } - let Some(name) = path - .file_stem() - .and_then(|s| s.to_str()) - .map(str::to_string) - else { - continue; - }; - if exclude.contains(&name) { - continue; - } - let content = match fs::read_to_string(&path).await { - Ok(s) => s, - Err(_) => continue, - }; - let (description, argument_hint, body) = parse_frontmatter(&content); - out.push(CustomPrompt { - name, - path, - content: body, - description, - argument_hint, - }); - } - out.sort_by(|a, b| a.name.cmp(&b.name)); - out -} - -/// Parse optional YAML-like frontmatter at the beginning of `content`. -/// Supported keys: -/// - `description`: short description shown in the slash popup -/// - `argument-hint` or `argument_hint`: brief hint string shown after the description -/// Returns (description, argument_hint, body_without_frontmatter). -fn parse_frontmatter(content: &str) -> (Option, Option, String) { - let mut segments = content.split_inclusive('\n'); - let Some(first_segment) = segments.next() else { - return (None, None, String::new()); - }; - let first_line = first_segment.trim_end_matches(['\r', '\n']); - if first_line.trim() != "---" { - return (None, None, content.to_string()); - } - - let mut desc: Option = None; - let mut hint: Option = None; - let mut frontmatter_closed = false; - let mut consumed = first_segment.len(); - - for segment in segments { - let line = segment.trim_end_matches(['\r', '\n']); - let trimmed = line.trim(); - - if trimmed == "---" { - frontmatter_closed = true; - consumed += segment.len(); - break; - } - - if trimmed.is_empty() || trimmed.starts_with('#') { - consumed += segment.len(); - continue; - } - - if let Some((k, v)) = trimmed.split_once(':') { - let key = k.trim().to_ascii_lowercase(); - let mut val = v.trim().to_string(); - if val.len() >= 2 { - let bytes = val.as_bytes(); - let first = bytes[0]; - let last = bytes[bytes.len() - 1]; - if (first == b'\"' && last == b'\"') || (first == b'\'' && last == b'\'') { - val = val[1..val.len().saturating_sub(1)].to_string(); - } - } - match key.as_str() { - "description" => desc = Some(val), - "argument-hint" | "argument_hint" => hint = Some(val), - _ => {} - } - } - - consumed += segment.len(); - } - - if !frontmatter_closed { - // Unterminated frontmatter: treat input as-is. - return (None, None, content.to_string()); - } - - let body = if consumed >= content.len() { - String::new() - } else { - content[consumed..].to_string() - }; - (desc, hint, body) -} - -#[cfg(test)] -#[path = "custom_prompts_tests.rs"] -mod tests; diff --git a/codex-rs/core/src/custom_prompts_tests.rs b/codex-rs/core/src/custom_prompts_tests.rs deleted file mode 100644 index b1208a04e0..0000000000 --- a/codex-rs/core/src/custom_prompts_tests.rs +++ /dev/null @@ -1,95 +0,0 @@ -use super::*; -use std::fs; -use tempfile::tempdir; - -#[tokio::test] -async fn empty_when_dir_missing() { - let tmp = tempdir().expect("create TempDir"); - let missing = tmp.path().join("nope"); - let found = discover_prompts_in(&missing).await; - assert!(found.is_empty()); -} - -#[tokio::test] -async fn discovers_and_sorts_files() { - let tmp = tempdir().expect("create TempDir"); - let dir = tmp.path(); - fs::write(dir.join("b.md"), b"b").unwrap(); - fs::write(dir.join("a.md"), b"a").unwrap(); - fs::create_dir(dir.join("subdir")).unwrap(); - let found = discover_prompts_in(dir).await; - let names: Vec = found.into_iter().map(|e| e.name).collect(); - assert_eq!(names, vec!["a", "b"]); -} - -#[tokio::test] -async fn excludes_builtins() { - let tmp = tempdir().expect("create TempDir"); - let dir = tmp.path(); - fs::write(dir.join("init.md"), b"ignored").unwrap(); - fs::write(dir.join("foo.md"), b"ok").unwrap(); - let mut exclude = HashSet::new(); - exclude.insert("init".to_string()); - let found = discover_prompts_in_excluding(dir, &exclude).await; - let names: Vec = found.into_iter().map(|e| e.name).collect(); - assert_eq!(names, vec!["foo"]); -} - -#[tokio::test] -async fn skips_non_utf8_files() { - let tmp = tempdir().expect("create TempDir"); - let dir = tmp.path(); - // Valid UTF-8 file - fs::write(dir.join("good.md"), b"hello").unwrap(); - // Invalid UTF-8 content in .md file (e.g., lone 0xFF byte) - fs::write(dir.join("bad.md"), vec![0xFF, 0xFE, b'\n']).unwrap(); - let found = discover_prompts_in(dir).await; - let names: Vec = found.into_iter().map(|e| e.name).collect(); - assert_eq!(names, vec!["good"]); -} - -#[tokio::test] -#[cfg(unix)] -async fn discovers_symlinked_md_files() { - let tmp = tempdir().expect("create TempDir"); - let dir = tmp.path(); - - // Create a real file - fs::write(dir.join("real.md"), b"real content").unwrap(); - - // Create a symlink to the real file - std::os::unix::fs::symlink(dir.join("real.md"), dir.join("link.md")).unwrap(); - - let found = discover_prompts_in(dir).await; - let names: Vec = found.into_iter().map(|e| e.name).collect(); - - // Both real and link should be discovered, sorted alphabetically - assert_eq!(names, vec!["link", "real"]); -} - -#[tokio::test] -async fn parses_frontmatter_and_strips_from_body() { - let tmp = tempdir().expect("create TempDir"); - let dir = tmp.path(); - let file = dir.join("withmeta.md"); - let text = "---\nname: ignored\ndescription: \"Quick review command\"\nargument-hint: \"[file] [priority]\"\n---\nActual body with $1 and $ARGUMENTS"; - fs::write(&file, text).unwrap(); - - let found = discover_prompts_in(dir).await; - assert_eq!(found.len(), 1); - let p = &found[0]; - assert_eq!(p.name, "withmeta"); - assert_eq!(p.description.as_deref(), Some("Quick review command")); - assert_eq!(p.argument_hint.as_deref(), Some("[file] [priority]")); - // Body should not include the frontmatter delimiters. - assert_eq!(p.content, "Actual body with $1 and $ARGUMENTS"); -} - -#[test] -fn parse_frontmatter_preserves_body_newlines() { - let content = "---\r\ndescription: \"Line endings\"\r\nargument_hint: \"[arg]\"\r\n---\r\nFirst line\r\nSecond line\r\n"; - let (desc, hint, body) = parse_frontmatter(content); - assert_eq!(desc.as_deref(), Some("Line endings")); - assert_eq!(hint.as_deref(), Some("[arg]")); - assert_eq!(body, "First line\r\nSecond line\r\n"); -} diff --git a/codex-rs/core/src/lib.rs b/codex-rs/core/src/lib.rs index f0390c805a..5276b09de3 100644 --- a/codex-rs/core/src/lib.rs +++ b/codex-rs/core/src/lib.rs @@ -30,7 +30,6 @@ pub mod config_loader; pub mod connectors; mod context_manager; mod contextual_user_message; -pub mod custom_prompts; pub use codex_utils_path::env; mod environment_context; pub mod error; diff --git a/codex-rs/mcp-server/src/codex_tool_runner.rs b/codex-rs/mcp-server/src/codex_tool_runner.rs index a08f93007e..64d553bbff 100644 --- a/codex-rs/mcp-server/src/codex_tool_runner.rs +++ b/codex-rs/mcp-server/src/codex_tool_runner.rs @@ -336,7 +336,6 @@ async fn run_codex_tool_session_inner( | EventMsg::McpToolCallBegin(_) | EventMsg::McpToolCallEnd(_) | EventMsg::McpListToolsResponse(_) - | EventMsg::ListCustomPromptsResponse(_) | EventMsg::ListSkillsResponse(_) | EventMsg::ExecCommandBegin(_) | EventMsg::TerminalInteraction(_) diff --git a/codex-rs/protocol/src/custom_prompts.rs b/codex-rs/protocol/src/custom_prompts.rs deleted file mode 100644 index 7472d1b4c5..0000000000 --- a/codex-rs/protocol/src/custom_prompts.rs +++ /dev/null @@ -1,20 +0,0 @@ -use schemars::JsonSchema; -use serde::Deserialize; -use serde::Serialize; -use std::path::PathBuf; -use ts_rs::TS; - -/// Base namespace for custom prompt slash commands (without trailing colon). -/// Example usage forms constructed in code: -/// - Command token after '/': `"{PROMPTS_CMD_PREFIX}:name"` -/// - Full slash prefix: `"/{PROMPTS_CMD_PREFIX}:"` -pub const PROMPTS_CMD_PREFIX: &str = "prompts"; - -#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, TS)] -pub struct CustomPrompt { - pub name: String, - pub path: PathBuf, - pub content: String, - pub description: Option, - pub argument_hint: Option, -} diff --git a/codex-rs/protocol/src/lib.rs b/codex-rs/protocol/src/lib.rs index 56924cc50d..97e204d0a3 100644 --- a/codex-rs/protocol/src/lib.rs +++ b/codex-rs/protocol/src/lib.rs @@ -5,7 +5,6 @@ pub use agent_path::AgentPath; pub use thread_id::ThreadId; pub mod approvals; pub mod config_types; -pub mod custom_prompts; pub mod dynamic_tools; pub mod items; pub mod mcp; diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index 27e7b4e464..aa9f319ffd 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -23,7 +23,6 @@ use crate::config_types::Personality; use crate::config_types::ReasoningSummary as ReasoningSummaryConfig; use crate::config_types::ServiceTier; use crate::config_types::WindowsSandboxLevel; -use crate::custom_prompts::CustomPrompt; use crate::dynamic_tools::DynamicToolCallOutputContentItem; use crate::dynamic_tools::DynamicToolCallRequest; use crate::dynamic_tools::DynamicToolResponse; @@ -451,9 +450,6 @@ pub enum Op { /// enable/disable state) without restarting the thread. ReloadUserConfig, - /// Request the list of available custom prompts. - ListCustomPrompts, - /// Request the list of skills for the provided `cwd` values or the session default. ListSkills { /// Working directories to scope repo skills discovery. @@ -595,7 +591,6 @@ impl Op { Self::ListMcpTools => "list_mcp_tools", Self::RefreshMcpServers { .. } => "refresh_mcp_servers", Self::ReloadUserConfig => "reload_user_config", - Self::ListCustomPrompts => "list_custom_prompts", Self::ListSkills { .. } => "list_skills", Self::Compact => "compact", Self::DropMemories => "drop_memories", @@ -1370,9 +1365,6 @@ pub enum EventMsg { /// List of MCP tools available to the agent. McpListToolsResponse(McpListToolsResponseEvent), - /// List of custom prompts available to the agent. - ListCustomPromptsResponse(ListCustomPromptsResponseEvent), - /// List of skills available to the agent. ListSkillsResponse(ListSkillsResponseEvent), @@ -3102,12 +3094,6 @@ impl fmt::Display for McpAuthStatus { } } -/// Response payload for `Op::ListCustomPrompts`. -#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)] -pub struct ListCustomPromptsResponseEvent { - pub custom_prompts: Vec, -} - /// Response payload for `Op::ListSkills`. #[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)] pub struct ListSkillsResponseEvent { diff --git a/codex-rs/rollout/src/policy.rs b/codex-rs/rollout/src/policy.rs index c4b4b8c339..8e099c38dd 100644 --- a/codex-rs/rollout/src/policy.rs +++ b/codex-rs/rollout/src/policy.rs @@ -161,7 +161,6 @@ fn event_msg_persistence_mode(ev: &EventMsg) -> Option { | EventMsg::McpListToolsResponse(_) | EventMsg::McpStartupUpdate(_) | EventMsg::McpStartupComplete(_) - | EventMsg::ListCustomPromptsResponse(_) | EventMsg::ListSkillsResponse(_) | EventMsg::PlanUpdate(_) | EventMsg::ShutdownComplete diff --git a/codex-rs/tui/src/bottom_pane/chat_composer.rs b/codex-rs/tui/src/bottom_pane/chat_composer.rs index a85dd131ba..d8b862e635 100644 --- a/codex-rs/tui/src/bottom_pane/chat_composer.rs +++ b/codex-rs/tui/src/bottom_pane/chat_composer.rs @@ -39,7 +39,6 @@ //! //! - Expands pending paste placeholders so element ranges align with the final text. //! - Trims whitespace and rebases text elements accordingly. -//! - Expands `/prompts:` custom prompts (named or numeric args), preserving text elements. //! - Prunes local attached images so only placeholders that survive expansion are sent. //! - Preserves remote image URLs as separate attachments even when text is empty. //! @@ -182,24 +181,16 @@ use super::skill_popup::SkillPopup; use super::slash_commands; use super::slash_commands::BuiltinCommandFlags; use crate::bottom_pane::paste_burst::FlushResult; -use crate::bottom_pane::prompt_args::expand_custom_prompt; -use crate::bottom_pane::prompt_args::expand_if_numeric_with_positional_args; use crate::bottom_pane::prompt_args::parse_slash_name; -use crate::bottom_pane::prompt_args::prompt_argument_names; -use crate::bottom_pane::prompt_args::prompt_command_with_arg_placeholders; -use crate::bottom_pane::prompt_args::prompt_has_numeric_placeholders; use crate::render::Insets; use crate::render::RectExt; use crate::render::renderable::Renderable; use crate::slash_command::SlashCommand; use crate::style::user_message_style; -use codex_protocol::custom_prompts::CustomPrompt; -use codex_protocol::custom_prompts::PROMPTS_CMD_PREFIX; use codex_protocol::models::local_image_label_text; use codex_protocol::user_input::ByteRange; use codex_protocol::user_input::MAX_USER_INPUT_TEXT_CHARS; use codex_protocol::user_input::TextElement; -use codex_utils_fuzzy_match::fuzzy_match; use crate::app_event::AppEvent; use crate::app_event::ConnectorsSnapshot; @@ -267,22 +258,6 @@ struct AttachedImage { path: PathBuf, } -enum PromptSelectionMode { - Completion, - Submit, -} - -enum PromptSelectionAction { - Insert { - text: String, - cursor: Option, - }, - Submit { - text: String, - text_elements: Vec, - }, -} - /// Feature flags for reusing the chat composer in other bottom-pane surfaces. /// /// The default keeps today's behavior intact. Other call sites can opt out of @@ -380,7 +355,6 @@ pub(crate) struct ChatComposer { paste_burst: PasteBurst, // When true, disables paste-burst logic and inserts characters immediately. disable_paste_burst: bool, - custom_prompts: Vec, footer_mode: FooterMode, footer_hint_override: Option>, remote_image_urls: Vec, @@ -507,7 +481,6 @@ impl ChatComposer { input_disabled_placeholder: None, paste_burst: PasteBurst::default(), disable_paste_burst: false, - custom_prompts: Vec::new(), footer_mode: FooterMode::ComposerEmpty, footer_hint_override: None, remote_image_urls: Vec::new(), @@ -1415,46 +1388,21 @@ impl ChatComposer { let first_line = self.textarea.text().lines().next().unwrap_or(""); popup.on_composer_text_change(first_line.to_string()); if let Some(sel) = popup.selected_item() { - let mut cursor_target: Option = None; - match sel { - CommandItem::Builtin(cmd) => { - if cmd == SlashCommand::Skills { - self.textarea.set_text_clearing_elements(""); - return (InputResult::Command(cmd), true); - } - - let starts_with_cmd = first_line - .trim_start() - .starts_with(&format!("/{}", cmd.command())); - if !starts_with_cmd { - self.textarea - .set_text_clearing_elements(&format!("/{} ", cmd.command())); - } - if !self.textarea.text().is_empty() { - cursor_target = Some(self.textarea.text().len()); - } - } - CommandItem::UserPrompt(idx) => { - if let Some(prompt) = popup.prompt(idx) { - match prompt_selection_action( - prompt, - first_line, - PromptSelectionMode::Completion, - &self.textarea.text_elements(), - ) { - PromptSelectionAction::Insert { text, cursor } => { - let target = cursor.unwrap_or(text.len()); - // Inserted prompt text is plain input; discard any elements. - self.textarea.set_text_clearing_elements(&text); - cursor_target = Some(target); - } - PromptSelectionAction::Submit { .. } => {} - } - } - } + let CommandItem::Builtin(cmd) = sel; + if cmd == SlashCommand::Skills { + self.textarea.set_text_clearing_elements(""); + return (InputResult::Command(cmd), true); } - if let Some(pos) = cursor_target { - self.textarea.set_cursor(pos); + + let starts_with_cmd = first_line + .trim_start() + .starts_with(&format!("/{}", cmd.command())); + if !starts_with_cmd { + self.textarea + .set_text_clearing_elements(&format!("/{} ", cmd.command())); + } + if !self.textarea.text().is_empty() { + self.textarea.set_cursor(self.textarea.text().len()); } } (InputResult::None, true) @@ -1464,82 +1412,10 @@ impl ChatComposer { modifiers: KeyModifiers::NONE, .. } => { - // If the current line starts with a custom prompt name and includes - // positional args for a numeric-style template, expand and submit - // immediately regardless of the popup selection. - let mut text = self.textarea.text().to_string(); - let mut text_elements = self.textarea.text_elements(); - if !self.pending_pastes.is_empty() { - let (expanded, expanded_elements) = - Self::expand_pending_pastes(&text, text_elements, &self.pending_pastes); - text = expanded; - text_elements = expanded_elements; - } - let first_line = text.lines().next().unwrap_or(""); - if let Some((name, _rest, _rest_offset)) = parse_slash_name(first_line) - && let Some(prompt_name) = name.strip_prefix(&format!("{PROMPTS_CMD_PREFIX}:")) - && let Some(prompt) = self.custom_prompts.iter().find(|p| p.name == prompt_name) - && let Some(expanded) = - expand_if_numeric_with_positional_args(prompt, first_line, &text_elements) - { - self.prune_attached_images_for_submission( - &expanded.text, - &expanded.text_elements, - ); - self.pending_pastes.clear(); - self.textarea.set_text_clearing_elements(""); - return ( - InputResult::Submitted { - text: expanded.text, - text_elements: expanded.text_elements, - }, - true, - ); - } - if let Some(sel) = popup.selected_item() { - match sel { - CommandItem::Builtin(cmd) => { - self.textarea.set_text_clearing_elements(""); - return (InputResult::Command(cmd), true); - } - CommandItem::UserPrompt(idx) => { - if let Some(prompt) = popup.prompt(idx) { - match prompt_selection_action( - prompt, - first_line, - PromptSelectionMode::Submit, - &self.textarea.text_elements(), - ) { - PromptSelectionAction::Submit { - text, - text_elements, - } => { - self.prune_attached_images_for_submission( - &text, - &text_elements, - ); - self.textarea.set_text_clearing_elements(""); - return ( - InputResult::Submitted { - text, - text_elements, - }, - true, - ); - } - PromptSelectionAction::Insert { text, cursor } => { - let target = cursor.unwrap_or(text.len()); - // Inserted prompt text is plain input; discard any elements. - self.textarea.set_text_clearing_elements(&text); - self.textarea.set_cursor(target); - return (InputResult::None, true); - } - } - } - return (InputResult::None, true); - } - } + let CommandItem::Builtin(cmd) = sel; + self.textarea.set_text_clearing_elements(""); + return (InputResult::Command(cmd), true); } // Fallback to default newline handling if no command selected. self.handle_key_event_without_popup(key_event) @@ -2327,34 +2203,13 @@ impl ChatComposer { let is_builtin = slash_commands::find_builtin_command(name, self.builtin_command_flags()) .is_some(); - let prompt_prefix = format!("{PROMPTS_CMD_PREFIX}:"); - let is_custom_prompt_command = name.starts_with(&prompt_prefix); - let is_known_prompt = name - .strip_prefix(&prompt_prefix) - .map(|prompt_name| { - self.custom_prompts - .iter() - .any(|prompt| prompt.name == prompt_name) - }) - .unwrap_or(false); - if !is_builtin && !is_known_prompt { - let message = if is_custom_prompt_command && self.custom_prompts.is_empty() { - tracing::warn!("custom prompt listing/picker is not available in TUI yet"); - "Not available in TUI yet.".to_string() - } else { - format!( - r#"Unrecognized command '/{name}'. Type "/" for a list of supported commands."# - ) - }; - if is_custom_prompt_command && self.custom_prompts.is_empty() { - self.app_event_tx.send(AppEvent::InsertHistoryCell(Box::new( - history_cell::new_error_event(message), - ))); - } else { - self.app_event_tx.send(AppEvent::InsertHistoryCell(Box::new( - history_cell::new_info_event(message, /*hint*/ None), - ))); - } + if !is_builtin { + let message = format!( + r#"Unrecognized command '/{name}'. Type "/" for a list of supported commands."# + ); + self.app_event_tx.send(AppEvent::InsertHistoryCell(Box::new( + history_cell::new_info_event(message, /*hint*/ None), + ))); self.set_text_content_with_mention_bindings( original_input.clone(), original_text_elements, @@ -2368,30 +2223,6 @@ impl ChatComposer { } } - if self.slash_commands_enabled() { - let expanded_prompt = - match expand_custom_prompt(&text, &text_elements, &self.custom_prompts) { - Ok(expanded) => expanded, - Err(err) => { - self.app_event_tx.send(AppEvent::InsertHistoryCell(Box::new( - history_cell::new_error_event(err.user_message()), - ))); - self.set_text_content_with_mention_bindings( - original_input.clone(), - original_text_elements, - original_local_image_paths, - original_mention_bindings, - ); - self.pending_pastes.clone_from(&original_pending_pastes); - self.textarea.set_cursor(original_input.len()); - return None; - } - }; - if let Some(expanded) = expanded_prompt { - text = expanded.text; - text_elements = expanded.text_elements; - } - } let actual_chars = text.chars().count(); if actual_chars > MAX_USER_INPUT_TEXT_CHARS { let message = user_input_too_large_message(actual_chars); @@ -2408,8 +2239,6 @@ impl ChatComposer { self.textarea.set_cursor(original_input.len()); return None; } - // Custom prompt expansion can remove or rewrite image placeholders, so prune any - // attachments that no longer have a corresponding placeholder in the expanded text. self.prune_attached_images_for_submission(&text, &text_elements); if text.is_empty() && self.attached_images.is_empty() && self.remote_image_urls.is_empty() { return None; @@ -3390,20 +3219,7 @@ impl ChatComposer { } fn is_known_slash_name(&self, name: &str) -> bool { - let is_builtin = - slash_commands::find_builtin_command(name, self.builtin_command_flags()).is_some(); - if is_builtin { - return true; - } - if let Some(rest) = name.strip_prefix(PROMPTS_CMD_PREFIX) - && let Some(prompt_name) = rest.strip_prefix(':') - { - return self - .custom_prompts - .iter() - .any(|prompt| prompt.name == prompt_name); - } - false + slash_commands::find_builtin_command(name, self.builtin_command_flags()).is_some() } /// If the cursor is currently within a slash command on the first line, @@ -3435,7 +3251,7 @@ impl ChatComposer { } /// Heuristic for whether the typed slash command looks like a valid - /// prefix for any known command (built-in or custom prompt). + /// prefix for any known built-in command. /// Empty names only count when there is no extra content after the '/'. fn looks_like_slash_prefix(&self, name: &str, rest_after_name: &str) -> bool { if !self.slash_commands_enabled() { @@ -3445,13 +3261,7 @@ impl ChatComposer { return rest_after_name.is_empty(); } - if slash_commands::has_builtin_prefix(name, self.builtin_command_flags()) { - return true; - } - - self.custom_prompts.iter().any(|prompt| { - fuzzy_match(&format!("{PROMPTS_CMD_PREFIX}:{}", prompt.name), name).is_some() - }) + slash_commands::has_builtin_prefix(name, self.builtin_command_flags()) } /// Synchronize `self.command_popup` with the current text in the @@ -3501,32 +3311,22 @@ impl ChatComposer { let personality_command_enabled = self.personality_command_enabled; let realtime_conversation_enabled = self.realtime_conversation_enabled; let audio_device_selection_enabled = self.audio_device_selection_enabled; - let mut command_popup = CommandPopup::new( - self.custom_prompts.clone(), - CommandPopupFlags { - collaboration_modes_enabled, - connectors_enabled, - plugins_command_enabled, - fast_command_enabled, - personality_command_enabled, - realtime_conversation_enabled, - audio_device_selection_enabled, - windows_degraded_sandbox_active: self.windows_degraded_sandbox_active, - }, - ); + let mut command_popup = CommandPopup::new(CommandPopupFlags { + collaboration_modes_enabled, + connectors_enabled, + plugins_command_enabled, + fast_command_enabled, + personality_command_enabled, + realtime_conversation_enabled, + audio_device_selection_enabled, + windows_degraded_sandbox_active: self.windows_degraded_sandbox_active, + }); command_popup.on_composer_text_change(first_line.to_string()); self.active_popup = ActivePopup::Command(command_popup); } } } } - #[cfg(test)] - pub(crate) fn set_custom_prompts(&mut self, prompts: Vec) { - self.custom_prompts = prompts.clone(); - if let ActivePopup::Command(popup) = &mut self.active_popup { - popup.set_prompts(prompts); - } - } /// Synchronize `self.file_search_popup` with the current text in the textarea. /// Note this is only called when self.active_popup is NOT Command. @@ -4457,62 +4257,6 @@ impl ChatComposer { } } -fn prompt_selection_action( - prompt: &CustomPrompt, - first_line: &str, - mode: PromptSelectionMode, - text_elements: &[TextElement], -) -> PromptSelectionAction { - let named_args = prompt_argument_names(&prompt.content); - let has_numeric = prompt_has_numeric_placeholders(&prompt.content); - - match mode { - PromptSelectionMode::Completion => { - if !named_args.is_empty() { - let (text, cursor) = - prompt_command_with_arg_placeholders(&prompt.name, &named_args); - return PromptSelectionAction::Insert { - text, - cursor: Some(cursor), - }; - } - if has_numeric { - let text = format!("/{PROMPTS_CMD_PREFIX}:{} ", prompt.name); - return PromptSelectionAction::Insert { text, cursor: None }; - } - let text = format!("/{PROMPTS_CMD_PREFIX}:{}", prompt.name); - PromptSelectionAction::Insert { text, cursor: None } - } - PromptSelectionMode::Submit => { - if !named_args.is_empty() { - let (text, cursor) = - prompt_command_with_arg_placeholders(&prompt.name, &named_args); - return PromptSelectionAction::Insert { - text, - cursor: Some(cursor), - }; - } - if has_numeric { - if let Some(expanded) = - expand_if_numeric_with_positional_args(prompt, first_line, text_elements) - { - return PromptSelectionAction::Submit { - text: expanded.text, - text_elements: expanded.text_elements, - }; - } - let text = format!("/{PROMPTS_CMD_PREFIX}:{} ", prompt.name); - return PromptSelectionAction::Insert { text, cursor: None }; - } - PromptSelectionAction::Submit { - text: prompt.content.clone(), - // By now we know this custom prompt has no args, so no text elements to preserve. - text_elements: Vec::new(), - } - } - } -} - impl Drop for ChatComposer { fn drop(&mut self) { // Stop any running spinner tasks. @@ -4538,8 +4282,6 @@ mod tests { use crate::bottom_pane::InputResult; use crate::bottom_pane::chat_composer::AttachedImage; use crate::bottom_pane::chat_composer::LARGE_PASTE_CHAR_THRESHOLD; - use crate::bottom_pane::prompt_args::PromptArg; - use crate::bottom_pane::prompt_args::extract_positional_args_for_prompt_line; use crate::bottom_pane::textarea::TextArea; use tokio::sync::mpsc::unbounded_channel; @@ -6716,9 +6458,6 @@ mod tests { Some(CommandItem::Builtin(cmd)) => { assert_eq!(cmd.command(), "model") } - Some(CommandItem::UserPrompt(_)) => { - panic!("unexpected prompt selected for '/mo'") - } None => panic!("no selected command for '/mo'"), }, _ => panic!("slash popup not active after typing '/mo'"), @@ -6772,9 +6511,6 @@ mod tests { Some(CommandItem::Builtin(cmd)) => { assert_eq!(cmd.command(), "resume") } - Some(CommandItem::UserPrompt(_)) => { - panic!("unexpected prompt selected for '/res'") - } None => panic!("no selected command for '/res'"), }, _ => panic!("slash popup not active after typing '/res'"), @@ -7153,44 +6889,6 @@ mod tests { assert!(composer.spinner_stop_flags.is_empty()); } - #[test] - fn extract_args_supports_quoted_paths_single_arg() { - let args = extract_positional_args_for_prompt_line( - "/prompts:review \"docs/My File.md\"", - "review", - &[], - ); - assert_eq!( - args, - vec![PromptArg { - text: "docs/My File.md".to_string(), - text_elements: Vec::new(), - }] - ); - } - - #[test] - fn extract_args_supports_mixed_quoted_and_unquoted() { - let args = extract_positional_args_for_prompt_line( - "/prompts:cmd \"with spaces\" simple", - "cmd", - &[], - ); - assert_eq!( - args, - vec![ - PromptArg { - text: "with spaces".to_string(), - text_elements: Vec::new(), - }, - PromptArg { - text: "simple".to_string(), - text_elements: Vec::new(), - } - ] - ); - } - #[test] fn slash_tab_completion_moves_cursor_to_end() { use crossterm::event::KeyCode; @@ -8494,398 +8192,6 @@ mod tests { assert_eq!(imgs, vec![tmp_path]); } - #[test] - fn selecting_custom_prompt_without_args_submits_content() { - let prompt_text = "Hello from saved prompt"; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - // Inject prompts as if received via event. - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: prompt_text.to_string(), - description: None, - argument_hint: None, - }]); - - type_chars_humanlike( - &mut composer, - &[ - '/', 'p', 'r', 'o', 'm', 'p', 't', 's', ':', 'm', 'y', '-', 'p', 'r', 'o', 'm', - 'p', 't', - ], - ); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert!(matches!( - result, - InputResult::Submitted { text, .. } if text == prompt_text - )); - assert!(composer.textarea.is_empty()); - } - - #[test] - fn custom_prompt_submission_expands_arguments() { - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review $USER changes on $BRANCH".to_string(), - description: None, - argument_hint: None, - }]); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt USER=Alice BRANCH=main"); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert!(matches!( - result, - InputResult::Submitted { text, .. } - if text == "Review Alice changes on main" - )); - assert!(composer.textarea.is_empty()); - } - - #[test] - fn custom_prompt_submission_accepts_quoted_values() { - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Pair $USER with $BRANCH".to_string(), - description: None, - argument_hint: None, - }]); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt USER=\"Alice Smith\" BRANCH=dev-main"); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert!(matches!( - result, - InputResult::Submitted { text, .. } - if text == "Pair Alice Smith with dev-main" - )); - assert!(composer.textarea.is_empty()); - } - - #[test] - fn custom_prompt_submission_preserves_image_placeholder_unquoted() { - use crossterm::event::KeyCode; - use crossterm::event::KeyEvent; - use crossterm::event::KeyModifiers; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review $IMG".to_string(), - description: None, - argument_hint: None, - }]); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt IMG="); - composer.textarea.set_cursor(composer.textarea.text().len()); - let path = PathBuf::from("/tmp/image_prompt.png"); - composer.attach_image(path); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - match result { - InputResult::Submitted { - text, - text_elements, - } => { - let placeholder = local_image_label_text(/*label_number*/ 1); - assert_eq!(text, format!("Review {placeholder}")); - assert_eq!( - text_elements, - vec![TextElement::new( - ByteRange { - start: "Review ".len(), - end: "Review ".len() + placeholder.len(), - }, - Some(placeholder), - )] - ); - } - _ => panic!("expected Submitted"), - } - } - - #[test] - fn custom_prompt_submission_preserves_image_placeholder_quoted() { - use crossterm::event::KeyCode; - use crossterm::event::KeyEvent; - use crossterm::event::KeyModifiers; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review $IMG".to_string(), - description: None, - argument_hint: None, - }]); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt IMG=\""); - composer.textarea.set_cursor(composer.textarea.text().len()); - let path = PathBuf::from("/tmp/image_prompt_quoted.png"); - composer.attach_image(path); - composer.handle_paste("\"".to_string()); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - match result { - InputResult::Submitted { - text, - text_elements, - } => { - let placeholder = local_image_label_text(/*label_number*/ 1); - assert_eq!(text, format!("Review {placeholder}")); - assert_eq!( - text_elements, - vec![TextElement::new( - ByteRange { - start: "Review ".len(), - end: "Review ".len() + placeholder.len(), - }, - Some(placeholder), - )] - ); - } - _ => panic!("expected Submitted"), - } - } - - #[test] - fn custom_prompt_submission_drops_unused_image_arg() { - use crossterm::event::KeyCode; - use crossterm::event::KeyEvent; - use crossterm::event::KeyModifiers; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review changes".to_string(), - description: None, - argument_hint: None, - }]); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt IMG="); - composer.textarea.set_cursor(composer.textarea.text().len()); - let path = PathBuf::from("/tmp/unused_image.png"); - composer.attach_image(path); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - match result { - InputResult::Submitted { - text, - text_elements, - } => { - assert_eq!(text, "Review changes"); - assert!(text_elements.is_empty()); - } - _ => panic!("expected Submitted"), - } - assert!(composer.take_recent_submission_images().is_empty()); - } - - /// Behavior: selecting a custom prompt that includes a large paste placeholder should expand - /// to the full pasted content before submission. - #[test] - fn custom_prompt_with_large_paste_expands_correctly() { - use crossterm::event::KeyCode; - use crossterm::event::KeyEvent; - use crossterm::event::KeyModifiers; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - // Create a custom prompt with positional args (no named args like $USER) - composer.set_custom_prompts(vec![CustomPrompt { - name: "code-review".to_string(), - path: "/tmp/code-review.md".to_string().into(), - content: "Please review the following code:\n\n$1".to_string(), - description: None, - argument_hint: None, - }]); - - // Type the slash command - let command_text = "/prompts:code-review "; - composer.textarea.set_text_clearing_elements(command_text); - composer.textarea.set_cursor(command_text.len()); - - // Paste large content (>3000 chars) to trigger placeholder - let large_content = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 3000); - composer.handle_paste(large_content.clone()); - - // Verify placeholder was created - let placeholder = format!("[Pasted Content {} chars]", large_content.chars().count()); - assert_eq!( - composer.textarea.text(), - format!("/prompts:code-review {}", placeholder) - ); - assert_eq!(composer.pending_pastes.len(), 1); - assert_eq!(composer.pending_pastes[0].0, placeholder); - assert_eq!(composer.pending_pastes[0].1, large_content); - - // Submit by pressing Enter - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - // Verify the custom prompt was expanded with the large content as positional arg - match result { - InputResult::Submitted { text, .. } => { - // The prompt should be expanded, with the large content replacing $1 - assert_eq!( - text, - format!("Please review the following code:\n\n{}", large_content), - "Expected prompt expansion with large content as $1" - ); - } - _ => panic!("expected Submitted, got: {result:?}"), - } - assert!(composer.textarea.is_empty()); - assert!(composer.pending_pastes.is_empty()); - } - - #[test] - fn custom_prompt_with_large_paste_and_image_preserves_elements() { - use crossterm::event::KeyCode; - use crossterm::event::KeyEvent; - use crossterm::event::KeyModifiers; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review $IMG\n\n$CODE".to_string(), - description: None, - argument_hint: None, - }]); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt IMG="); - composer.textarea.set_cursor(composer.textarea.text().len()); - let path = PathBuf::from("/tmp/image_prompt_combo.png"); - composer.attach_image(path); - composer.handle_paste(" CODE=".to_string()); - let large_content = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 5); - composer.handle_paste(large_content.clone()); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - match result { - InputResult::Submitted { - text, - text_elements, - } => { - let placeholder = local_image_label_text(/*label_number*/ 1); - assert_eq!(text, format!("Review {placeholder}\n\n{large_content}")); - assert_eq!( - text_elements, - vec![TextElement::new( - ByteRange { - start: "Review ".len(), - end: "Review ".len() + placeholder.len(), - }, - Some(placeholder), - )] - ); - } - _ => panic!("expected Submitted"), - } - } - #[test] fn slash_path_input_submits_without_command_error() { use crossterm::event::KeyCode; @@ -8958,576 +8264,6 @@ mod tests { } } - #[test] - fn custom_prompt_invalid_args_reports_error() { - let (tx, mut rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review $USER changes".to_string(), - description: None, - argument_hint: None, - }]); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt USER=Alice stray"); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert_eq!(InputResult::None, result); - assert_eq!( - "/prompts:my-prompt USER=Alice stray", - composer.textarea.text() - ); - - let mut found_error = false; - while let Ok(event) = rx.try_recv() { - if let AppEvent::InsertHistoryCell(cell) = event { - let message = cell - .display_lines(/*width*/ 80) - .into_iter() - .map(|line| line.to_string()) - .collect::>() - .join("\n"); - assert!(message.contains("expected key=value")); - found_error = true; - break; - } - } - assert!(found_error, "expected error history cell to be sent"); - } - - #[test] - fn custom_prompt_command_is_stubbed_when_prompt_listing_is_unavailable() { - let (tx, mut rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt"); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert_eq!(InputResult::None, result); - assert_eq!("/prompts:my-prompt", composer.textarea.text()); - - let AppEvent::InsertHistoryCell(cell) = rx.try_recv().expect("expected stub history cell") - else { - panic!("expected stub history cell"); - }; - let message = cell - .display_lines(/*width*/ 80) - .into_iter() - .map(|line| line.to_string()) - .collect::>() - .join("\n"); - assert!(message.contains("Not available in TUI yet.")); - } - - #[test] - fn custom_prompt_missing_required_args_reports_error() { - let (tx, mut rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review $USER changes on $BRANCH".to_string(), - description: None, - argument_hint: None, - }]); - - // Provide only one of the required args - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt USER=Alice"); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert_eq!(InputResult::None, result); - assert_eq!("/prompts:my-prompt USER=Alice", composer.textarea.text()); - - let mut found_error = false; - while let Ok(event) = rx.try_recv() { - if let AppEvent::InsertHistoryCell(cell) = event { - let message = cell - .display_lines(/*width*/ 80) - .into_iter() - .map(|line| line.to_string()) - .collect::>() - .join("\n"); - assert!(message.to_lowercase().contains("missing required args")); - assert!(message.contains("BRANCH")); - found_error = true; - break; - } - } - assert!( - found_error, - "expected missing args error history cell to be sent" - ); - } - - #[test] - fn selecting_custom_prompt_with_args_expands_placeholders() { - // Support $1..$9 and $ARGUMENTS in prompt content. - let prompt_text = "Header: $1\nArgs: $ARGUMENTS\nNinth: $9\n"; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: prompt_text.to_string(), - description: None, - argument_hint: None, - }]); - - // Type the slash command with two args and hit Enter to submit. - type_chars_humanlike( - &mut composer, - &[ - '/', 'p', 'r', 'o', 'm', 'p', 't', 's', ':', 'm', 'y', '-', 'p', 'r', 'o', 'm', - 'p', 't', ' ', 'f', 'o', 'o', ' ', 'b', 'a', 'r', - ], - ); - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - let expected = "Header: foo\nArgs: foo bar\nNinth: \n".to_string(); - assert!(matches!( - result, - InputResult::Submitted { text, .. } if text == expected - )); - } - - #[test] - fn popup_prompt_submission_prunes_unused_image_attachments() { - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Hello".to_string(), - description: None, - argument_hint: None, - }]); - - composer.attach_image(PathBuf::from("/tmp/unused.png")); - composer.textarea.set_cursor(/*pos*/ 0); - composer.handle_paste(format!("/{PROMPTS_CMD_PREFIX}:my-prompt ")); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert!(matches!( - result, - InputResult::Submitted { text, .. } if text == "Hello" - )); - assert!( - composer - .take_recent_submission_images_with_placeholders() - .is_empty() - ); - } - - #[test] - fn numeric_prompt_auto_submit_prunes_unused_image_attachments() { - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Hello $1".to_string(), - description: None, - argument_hint: None, - }]); - - type_chars_humanlike( - &mut composer, - &[ - '/', 'p', 'r', 'o', 'm', 'p', 't', 's', ':', 'm', 'y', '-', 'p', 'r', 'o', 'm', - 'p', 't', ' ', 'f', 'o', 'o', ' ', - ], - ); - composer.attach_image(PathBuf::from("/tmp/unused.png")); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert!(matches!( - result, - InputResult::Submitted { text, .. } if text == "Hello foo" - )); - assert!( - composer - .take_recent_submission_images_with_placeholders() - .is_empty() - ); - } - - #[test] - fn numeric_prompt_auto_submit_expands_pending_pastes() { - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Echo: $1".to_string(), - description: None, - argument_hint: None, - }]); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt "); - composer.textarea.set_cursor(composer.textarea.text().len()); - let large_content = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 5); - composer.handle_paste(large_content.clone()); - - assert_eq!(composer.pending_pastes.len(), 1); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - let expected = format!("Echo: {large_content}"); - assert!(matches!( - result, - InputResult::Submitted { text, .. } if text == expected - )); - assert!(composer.pending_pastes.is_empty()); - } - - #[test] - fn queued_prompt_submission_prunes_unused_image_attachments() { - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Hello $1".to_string(), - description: None, - argument_hint: None, - }]); - - composer - .textarea - .set_text_clearing_elements("/prompts:my-prompt foo "); - composer.textarea.set_cursor(composer.textarea.text().len()); - composer.attach_image(PathBuf::from("/tmp/unused.png")); - composer.set_task_running(/*running*/ true); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Tab, KeyModifiers::NONE)); - - assert!(matches!( - result, - InputResult::Queued { text, .. } if text == "Hello foo" - )); - assert!( - composer - .take_recent_submission_images_with_placeholders() - .is_empty() - ); - } - - #[test] - fn prompt_expansion_over_character_limit_reports_error_and_restores_draft() { - let (tx, mut rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - composer.set_steer_enabled(true); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Echo: $1".to_string(), - description: None, - argument_hint: None, - }]); - - let oversized_arg = "x".repeat(MAX_USER_INPUT_TEXT_CHARS); - let original_input = format!("/prompts:my-prompt {oversized_arg}"); - composer - .textarea - .set_text_clearing_elements(&original_input); - - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert_eq!(InputResult::None, result); - assert_eq!(composer.textarea.text(), original_input); - - let actual_chars = format!("Echo: {oversized_arg}").chars().count(); - let mut found_error = false; - while let Ok(event) = rx.try_recv() { - if let AppEvent::InsertHistoryCell(cell) = event { - let message = cell - .display_lines(/*width*/ 80) - .into_iter() - .map(|line| line.to_string()) - .collect::>() - .join("\n"); - assert!(message.contains(&user_input_too_large_message(actual_chars))); - found_error = true; - break; - } - } - assert!(found_error, "expected oversized-input error history cell"); - } - - #[test] - fn selecting_custom_prompt_with_positional_args_submits_numeric_expansion() { - let prompt_text = "Header: $1\nArgs: $ARGUMENTS\n"; - - let prompt = CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: prompt_text.to_string(), - description: None, - argument_hint: None, - }; - - let action = prompt_selection_action( - &prompt, - "/prompts:my-prompt foo bar", - PromptSelectionMode::Submit, - &[], - ); - match action { - PromptSelectionAction::Submit { - text, - text_elements, - } => { - assert_eq!(text, "Header: foo\nArgs: foo bar\n"); - assert!(text_elements.is_empty()); - } - _ => panic!("expected Submit action"), - } - } - - #[test] - fn numeric_prompt_positional_args_does_not_error() { - // Ensure that a prompt with only numeric placeholders does not trigger - // key=value parsing errors when given positional arguments. - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "elegant".to_string(), - path: "/tmp/elegant.md".to_string().into(), - content: "Echo: $ARGUMENTS".to_string(), - description: None, - argument_hint: None, - }]); - - // Type positional args; should submit with numeric expansion, no errors. - composer - .textarea - .set_text_clearing_elements("/prompts:elegant hi"); - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert!(matches!( - result, - InputResult::Submitted { text, .. } if text == "Echo: hi" - )); - assert!(composer.textarea.is_empty()); - } - - #[test] - fn selecting_custom_prompt_with_no_args_inserts_template() { - let prompt_text = "X:$1 Y:$2 All:[$ARGUMENTS]"; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "p".to_string(), - path: "/tmp/p.md".to_string().into(), - content: prompt_text.to_string(), - description: None, - argument_hint: None, - }]); - - type_chars_humanlike( - &mut composer, - &['/', 'p', 'r', 'o', 'm', 'p', 't', 's', ':', 'p'], - ); - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - // With no args typed, selecting the prompt inserts the command template - // and does not submit immediately. - assert_eq!(InputResult::None, result); - assert_eq!("/prompts:p ", composer.textarea.text()); - } - - #[test] - fn selecting_custom_prompt_preserves_literal_dollar_dollar() { - // '$$' should remain untouched. - let prompt_text = "Cost: $$ and first: $1"; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "price".to_string(), - path: "/tmp/price.md".to_string().into(), - content: prompt_text.to_string(), - description: None, - argument_hint: None, - }]); - - type_chars_humanlike( - &mut composer, - &[ - '/', 'p', 'r', 'o', 'm', 'p', 't', 's', ':', 'p', 'r', 'i', 'c', 'e', ' ', 'x', - ], - ); - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - assert!(matches!( - result, - InputResult::Submitted { text, .. } - if text == "Cost: $$ and first: x" - )); - } - - #[test] - fn selecting_custom_prompt_reuses_cached_arguments_join() { - let prompt_text = "First: $ARGUMENTS\nSecond: $ARGUMENTS"; - - let (tx, _rx) = unbounded_channel::(); - let sender = AppEventSender::new(tx); - let mut composer = ChatComposer::new( - /*has_input_focus*/ true, - sender, - /*enhanced_keys_supported*/ false, - "Ask Codex to do anything".to_string(), - /*disable_paste_burst*/ false, - ); - - composer.set_custom_prompts(vec![CustomPrompt { - name: "repeat".to_string(), - path: "/tmp/repeat.md".to_string().into(), - content: prompt_text.to_string(), - description: None, - argument_hint: None, - }]); - - type_chars_humanlike( - &mut composer, - &[ - '/', 'p', 'r', 'o', 'm', 'p', 't', 's', ':', 'r', 'e', 'p', 'e', 'a', 't', ' ', - 'o', 'n', 'e', ' ', 't', 'w', 'o', - ], - ); - let (result, _needs_redraw) = - composer.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE)); - - let expected = "First: one two\nSecond: one two".to_string(); - assert!(matches!( - result, - InputResult::Submitted { text, .. } if text == expected - )); - } - /// Behavior: the first fast ASCII character is held briefly to avoid flicker; if no burst /// follows, it should eventually flush as normal typed input (not as a paste). #[test] diff --git a/codex-rs/tui/src/bottom_pane/command_popup.rs b/codex-rs/tui/src/bottom_pane/command_popup.rs index 5ad3df5c2e..8bef8ddbc8 100644 --- a/codex-rs/tui/src/bottom_pane/command_popup.rs +++ b/codex-rs/tui/src/bottom_pane/command_popup.rs @@ -10,27 +10,21 @@ use super::slash_commands; use crate::render::Insets; use crate::render::RectExt; use crate::slash_command::SlashCommand; -use codex_protocol::custom_prompts::CustomPrompt; -use codex_protocol::custom_prompts::PROMPTS_CMD_PREFIX; -use std::collections::HashSet; // Hide alias commands in the default popup list so each unique action appears once. // `quit` is an alias of `exit`, so we skip `quit` here. // `approvals` is an alias of `permissions`. const ALIAS_COMMANDS: &[SlashCommand] = &[SlashCommand::Quit, SlashCommand::Approvals]; -/// A selectable item in the popup: either a built-in command or a user prompt. +/// A selectable item in the popup. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(crate) enum CommandItem { Builtin(SlashCommand), - // Index into `prompts` - UserPrompt(usize), } pub(crate) struct CommandPopup { command_filter: String, builtins: Vec<(&'static str, SlashCommand)>, - prompts: Vec, state: ScrollState, } @@ -62,7 +56,7 @@ impl From for slash_commands::BuiltinCommandFlags { } impl CommandPopup { - pub(crate) fn new(mut prompts: Vec, flags: CommandPopupFlags) -> Self { + pub(crate) fn new(flags: CommandPopupFlags) -> Self { // Keep built-in availability in sync with the composer. let builtins: Vec<(&'static str, SlashCommand)> = slash_commands::builtins_for_input(flags.into()) @@ -70,34 +64,13 @@ impl CommandPopup { .filter(|(name, _)| !name.starts_with("debug")) .filter(|(_, cmd)| *cmd != SlashCommand::Apps) .collect(); - // Exclude prompts that collide with builtin command names and sort by name. - let exclude: HashSet = builtins.iter().map(|(n, _)| (*n).to_string()).collect(); - prompts.retain(|p| !exclude.contains(&p.name)); - prompts.sort_by(|a, b| a.name.cmp(&b.name)); Self { command_filter: String::new(), builtins, - prompts, state: ScrollState::new(), } } - #[cfg(test)] - pub(crate) fn set_prompts(&mut self, mut prompts: Vec) { - let exclude: HashSet = self - .builtins - .iter() - .map(|(n, _)| (*n).to_string()) - .collect(); - prompts.retain(|p| !exclude.contains(&p.name)); - prompts.sort_by(|a, b| a.name.cmp(&b.name)); - self.prompts = prompts; - } - - pub(crate) fn prompt(&self, idx: usize) -> Option<&CustomPrompt> { - self.prompts.get(idx) - } - /// Update the filter string based on the current composer text. The text /// passed in is expected to start with a leading '/'. Everything after the /// *first* '/' on the *first* line becomes the active filter that is used @@ -145,17 +118,12 @@ impl CommandPopup { let filter = self.command_filter.trim(); let mut out: Vec<(CommandItem, Option>)> = Vec::new(); if filter.is_empty() { - // Built-ins first, in presentation order. for (_, cmd) in self.builtins.iter() { if ALIAS_COMMANDS.contains(cmd) { continue; } out.push((CommandItem::Builtin(*cmd), None)); } - // Then prompts, already sorted by name. - for idx in 0..self.prompts.len() { - out.push((CommandItem::UserPrompt(idx), None)); - } return out; } @@ -163,7 +131,6 @@ impl CommandPopup { let filter_chars = filter.chars().count(); let mut exact: Vec<(CommandItem, Option>)> = Vec::new(); let mut prefix: Vec<(CommandItem, Option>)> = Vec::new(); - let prompt_prefix_len = PROMPTS_CMD_PREFIX.chars().count() + 1; let indices_for = |offset| Some((offset..offset + filter_chars).collect()); let mut push_match = @@ -190,18 +157,6 @@ impl CommandPopup { for (_, cmd) in self.builtins.iter() { push_match(CommandItem::Builtin(*cmd), cmd.command(), None, 0); } - // Support both search styles: - // - Typing "name" should surface "/prompts:name" results. - // - Typing "prompts:name" should also work. - for (idx, p) in self.prompts.iter().enumerate() { - let display = format!("{PROMPTS_CMD_PREFIX}:{}", p.name); - push_match( - CommandItem::UserPrompt(idx), - &display, - Some(&p.name), - prompt_prefix_len, - ); - } out.extend(exact); out.extend(prefix); @@ -219,22 +174,9 @@ impl CommandPopup { matches .into_iter() .map(|(item, indices)| { - let (name, description) = match item { - CommandItem::Builtin(cmd) => { - (format!("/{}", cmd.command()), cmd.description().to_string()) - } - CommandItem::UserPrompt(i) => { - let prompt = &self.prompts[i]; - let description = prompt - .description - .clone() - .unwrap_or_else(|| "send saved prompt".to_string()); - ( - format!("/{PROMPTS_CMD_PREFIX}:{}", prompt.name), - description, - ) - } - }; + let CommandItem::Builtin(cmd) = item; + let name = format!("/{}", cmd.command()); + let description = cmd.description().to_string(); GenericDisplayRow { name, name_prefix_spans: Vec::new(), @@ -297,7 +239,7 @@ mod tests { #[test] fn filter_includes_init_when_typing_prefix() { - let mut popup = CommandPopup::new(Vec::new(), CommandPopupFlags::default()); + let mut popup = CommandPopup::new(CommandPopupFlags::default()); // Simulate the composer line starting with '/in' so the popup filters // matching commands by prefix. popup.on_composer_text_change("/in".to_string()); @@ -307,7 +249,6 @@ mod tests { let matches = popup.filtered_items(); let has_init = matches.iter().any(|item| match item { CommandItem::Builtin(cmd) => cmd.command() == "init", - CommandItem::UserPrompt(_) => false, }); assert!( has_init, @@ -317,7 +258,7 @@ mod tests { #[test] fn selecting_init_by_exact_match() { - let mut popup = CommandPopup::new(Vec::new(), CommandPopupFlags::default()); + let mut popup = CommandPopup::new(CommandPopupFlags::default()); popup.on_composer_text_change("/init".to_string()); // When an exact match exists, the selected command should be that @@ -325,144 +266,46 @@ mod tests { let selected = popup.selected_item(); match selected { Some(CommandItem::Builtin(cmd)) => assert_eq!(cmd.command(), "init"), - Some(CommandItem::UserPrompt(_)) => panic!("unexpected prompt selected for '/init'"), None => panic!("expected a selected command for exact match"), } } #[test] fn model_is_first_suggestion_for_mo() { - let mut popup = CommandPopup::new(Vec::new(), CommandPopupFlags::default()); + let mut popup = CommandPopup::new(CommandPopupFlags::default()); popup.on_composer_text_change("/mo".to_string()); let matches = popup.filtered_items(); match matches.first() { Some(CommandItem::Builtin(cmd)) => assert_eq!(cmd.command(), "model"), - Some(CommandItem::UserPrompt(_)) => { - panic!("unexpected prompt ranked before '/model' for '/mo'") - } None => panic!("expected at least one match for '/mo'"), } } #[test] fn filtered_commands_keep_presentation_order_for_prefix() { - let mut popup = CommandPopup::new(Vec::new(), CommandPopupFlags::default()); + let mut popup = CommandPopup::new(CommandPopupFlags::default()); popup.on_composer_text_change("/m".to_string()); let cmds: Vec<&str> = popup .filtered_items() .into_iter() - .filter_map(|item| match item { - CommandItem::Builtin(cmd) => Some(cmd.command()), - CommandItem::UserPrompt(_) => None, + .map(|item| match item { + CommandItem::Builtin(cmd) => cmd.command(), }) .collect(); assert_eq!(cmds, vec!["model", "mention", "mcp"]); } - #[test] - fn prompt_discovery_lists_custom_prompts() { - let prompts = vec![ - CustomPrompt { - name: "foo".to_string(), - path: "/tmp/foo.md".to_string().into(), - content: "hello from foo".to_string(), - description: None, - argument_hint: None, - }, - CustomPrompt { - name: "bar".to_string(), - path: "/tmp/bar.md".to_string().into(), - content: "hello from bar".to_string(), - description: None, - argument_hint: None, - }, - ]; - let popup = CommandPopup::new(prompts, CommandPopupFlags::default()); - let items = popup.filtered_items(); - let mut prompt_names: Vec = items - .into_iter() - .filter_map(|it| match it { - CommandItem::UserPrompt(i) => popup.prompt(i).map(|p| p.name.clone()), - _ => None, - }) - .collect(); - prompt_names.sort(); - assert_eq!(prompt_names, vec!["bar".to_string(), "foo".to_string()]); - } - - #[test] - fn prompt_name_collision_with_builtin_is_ignored() { - // Create a prompt named like a builtin (e.g. "init"). - let popup = CommandPopup::new( - vec![CustomPrompt { - name: "init".to_string(), - path: "/tmp/init.md".to_string().into(), - content: "should be ignored".to_string(), - description: None, - argument_hint: None, - }], - CommandPopupFlags::default(), - ); - let items = popup.filtered_items(); - let has_collision_prompt = items.into_iter().any(|it| match it { - CommandItem::UserPrompt(i) => popup.prompt(i).is_some_and(|p| p.name == "init"), - _ => false, - }); - assert!( - !has_collision_prompt, - "prompt with builtin name should be ignored" - ); - } - - #[test] - fn prompt_description_uses_frontmatter_metadata() { - let popup = CommandPopup::new( - vec![CustomPrompt { - name: "draftpr".to_string(), - path: "/tmp/draftpr.md".to_string().into(), - content: "body".to_string(), - description: Some("Create feature branch, commit and open draft PR.".to_string()), - argument_hint: None, - }], - CommandPopupFlags::default(), - ); - let rows = popup.rows_from_matches(vec![(CommandItem::UserPrompt(0), None)]); - let description = rows.first().and_then(|row| row.description.as_deref()); - assert_eq!( - description, - Some("Create feature branch, commit and open draft PR.") - ); - } - - #[test] - fn prompt_description_falls_back_when_missing() { - let popup = CommandPopup::new( - vec![CustomPrompt { - name: "foo".to_string(), - path: "/tmp/foo.md".to_string().into(), - content: "body".to_string(), - description: None, - argument_hint: None, - }], - CommandPopupFlags::default(), - ); - let rows = popup.rows_from_matches(vec![(CommandItem::UserPrompt(0), None)]); - let description = rows.first().and_then(|row| row.description.as_deref()); - assert_eq!(description, Some("send saved prompt")); - } - #[test] fn prefix_filter_limits_matches_for_ac() { - let mut popup = CommandPopup::new(Vec::new(), CommandPopupFlags::default()); + let mut popup = CommandPopup::new(CommandPopupFlags::default()); popup.on_composer_text_change("/ac".to_string()); let cmds: Vec<&str> = popup .filtered_items() .into_iter() - .filter_map(|item| match item { - CommandItem::Builtin(cmd) => Some(cmd.command()), - CommandItem::UserPrompt(_) => None, + .map(|item| match item { + CommandItem::Builtin(cmd) => cmd.command(), }) .collect(); assert!( @@ -473,7 +316,7 @@ mod tests { #[test] fn quit_hidden_in_empty_filter_but_shown_for_prefix() { - let mut popup = CommandPopup::new(Vec::new(), CommandPopupFlags::default()); + let mut popup = CommandPopup::new(CommandPopupFlags::default()); popup.on_composer_text_change("/".to_string()); let items = popup.filtered_items(); assert!(!items.contains(&CommandItem::Builtin(SlashCommand::Quit))); @@ -485,15 +328,14 @@ mod tests { #[test] fn collab_command_hidden_when_collaboration_modes_disabled() { - let mut popup = CommandPopup::new(Vec::new(), CommandPopupFlags::default()); + let mut popup = CommandPopup::new(CommandPopupFlags::default()); popup.on_composer_text_change("/".to_string()); let cmds: Vec<&str> = popup .filtered_items() .into_iter() - .filter_map(|item| match item { - CommandItem::Builtin(cmd) => Some(cmd.command()), - CommandItem::UserPrompt(_) => None, + .map(|item| match item { + CommandItem::Builtin(cmd) => cmd.command(), }) .collect(); assert!( @@ -508,19 +350,16 @@ mod tests { #[test] fn collab_command_visible_when_collaboration_modes_enabled() { - let mut popup = CommandPopup::new( - Vec::new(), - CommandPopupFlags { - collaboration_modes_enabled: true, - connectors_enabled: false, - plugins_command_enabled: false, - fast_command_enabled: false, - personality_command_enabled: true, - realtime_conversation_enabled: false, - audio_device_selection_enabled: false, - windows_degraded_sandbox_active: false, - }, - ); + let mut popup = CommandPopup::new(CommandPopupFlags { + collaboration_modes_enabled: true, + connectors_enabled: false, + plugins_command_enabled: false, + fast_command_enabled: false, + personality_command_enabled: true, + realtime_conversation_enabled: false, + audio_device_selection_enabled: false, + windows_degraded_sandbox_active: false, + }); popup.on_composer_text_change("/collab".to_string()); match popup.selected_item() { @@ -531,19 +370,16 @@ mod tests { #[test] fn plan_command_visible_when_collaboration_modes_enabled() { - let mut popup = CommandPopup::new( - Vec::new(), - CommandPopupFlags { - collaboration_modes_enabled: true, - connectors_enabled: false, - plugins_command_enabled: false, - fast_command_enabled: false, - personality_command_enabled: true, - realtime_conversation_enabled: false, - audio_device_selection_enabled: false, - windows_degraded_sandbox_active: false, - }, - ); + let mut popup = CommandPopup::new(CommandPopupFlags { + collaboration_modes_enabled: true, + connectors_enabled: false, + plugins_command_enabled: false, + fast_command_enabled: false, + personality_command_enabled: true, + realtime_conversation_enabled: false, + audio_device_selection_enabled: false, + windows_degraded_sandbox_active: false, + }); popup.on_composer_text_change("/plan".to_string()); match popup.selected_item() { @@ -554,27 +390,23 @@ mod tests { #[test] fn personality_command_hidden_when_disabled() { - let mut popup = CommandPopup::new( - Vec::new(), - CommandPopupFlags { - collaboration_modes_enabled: true, - connectors_enabled: false, - plugins_command_enabled: false, - fast_command_enabled: false, - personality_command_enabled: false, - realtime_conversation_enabled: false, - audio_device_selection_enabled: false, - windows_degraded_sandbox_active: false, - }, - ); + let mut popup = CommandPopup::new(CommandPopupFlags { + collaboration_modes_enabled: true, + connectors_enabled: false, + plugins_command_enabled: false, + fast_command_enabled: false, + personality_command_enabled: false, + realtime_conversation_enabled: false, + audio_device_selection_enabled: false, + windows_degraded_sandbox_active: false, + }); popup.on_composer_text_change("/pers".to_string()); let cmds: Vec<&str> = popup .filtered_items() .into_iter() - .filter_map(|item| match item { - CommandItem::Builtin(cmd) => Some(cmd.command()), - CommandItem::UserPrompt(_) => None, + .map(|item| match item { + CommandItem::Builtin(cmd) => cmd.command(), }) .collect(); assert!( @@ -585,19 +417,16 @@ mod tests { #[test] fn personality_command_visible_when_enabled() { - let mut popup = CommandPopup::new( - Vec::new(), - CommandPopupFlags { - collaboration_modes_enabled: true, - connectors_enabled: false, - plugins_command_enabled: false, - fast_command_enabled: false, - personality_command_enabled: true, - realtime_conversation_enabled: false, - audio_device_selection_enabled: false, - windows_degraded_sandbox_active: false, - }, - ); + let mut popup = CommandPopup::new(CommandPopupFlags { + collaboration_modes_enabled: true, + connectors_enabled: false, + plugins_command_enabled: false, + fast_command_enabled: false, + personality_command_enabled: true, + realtime_conversation_enabled: false, + audio_device_selection_enabled: false, + windows_degraded_sandbox_active: false, + }); popup.on_composer_text_change("/personality".to_string()); match popup.selected_item() { @@ -608,27 +437,23 @@ mod tests { #[test] fn settings_command_hidden_when_audio_device_selection_is_disabled() { - let mut popup = CommandPopup::new( - Vec::new(), - CommandPopupFlags { - collaboration_modes_enabled: false, - connectors_enabled: false, - plugins_command_enabled: false, - fast_command_enabled: false, - personality_command_enabled: true, - realtime_conversation_enabled: true, - audio_device_selection_enabled: false, - windows_degraded_sandbox_active: false, - }, - ); + let mut popup = CommandPopup::new(CommandPopupFlags { + collaboration_modes_enabled: false, + connectors_enabled: false, + plugins_command_enabled: false, + fast_command_enabled: false, + personality_command_enabled: true, + realtime_conversation_enabled: true, + audio_device_selection_enabled: false, + windows_degraded_sandbox_active: false, + }); popup.on_composer_text_change("/aud".to_string()); let cmds: Vec<&str> = popup .filtered_items() .into_iter() - .filter_map(|item| match item { - CommandItem::Builtin(cmd) => Some(cmd.command()), - CommandItem::UserPrompt(_) => None, + .map(|item| match item { + CommandItem::Builtin(cmd) => cmd.command(), }) .collect(); @@ -640,13 +465,12 @@ mod tests { #[test] fn debug_commands_are_hidden_from_popup() { - let popup = CommandPopup::new(Vec::new(), CommandPopupFlags::default()); + let popup = CommandPopup::new(CommandPopupFlags::default()); let cmds: Vec<&str> = popup .filtered_items() .into_iter() - .filter_map(|item| match item { - CommandItem::Builtin(cmd) => Some(cmd.command()), - CommandItem::UserPrompt(_) => None, + .map(|item| match item { + CommandItem::Builtin(cmd) => cmd.command(), }) .collect(); diff --git a/codex-rs/tui/src/bottom_pane/prompt_args.rs b/codex-rs/tui/src/bottom_pane/prompt_args.rs index efe0a00713..7c816d5ee7 100644 --- a/codex-rs/tui/src/bottom_pane/prompt_args.rs +++ b/codex-rs/tui/src/bottom_pane/prompt_args.rs @@ -1,63 +1,3 @@ -use codex_protocol::custom_prompts::CustomPrompt; -use codex_protocol::custom_prompts::PROMPTS_CMD_PREFIX; -use codex_protocol::user_input::ByteRange; -use codex_protocol::user_input::TextElement; -use lazy_static::lazy_static; -use regex_lite::Regex; -use shlex::Shlex; -use std::collections::HashMap; -use std::collections::HashSet; - -lazy_static! { - static ref PROMPT_ARG_REGEX: Regex = - Regex::new(r"\$[A-Z][A-Z0-9_]*").unwrap_or_else(|_| std::process::abort()); -} - -#[derive(Debug)] -pub enum PromptArgsError { - MissingAssignment { token: String }, - MissingKey { token: String }, -} - -impl PromptArgsError { - fn describe(&self, command: &str) -> String { - match self { - PromptArgsError::MissingAssignment { token } => format!( - "Could not parse {command}: expected key=value but found '{token}'. Wrap values in double quotes if they contain spaces." - ), - PromptArgsError::MissingKey { token } => { - format!("Could not parse {command}: expected a name before '=' in '{token}'.") - } - } - } -} - -#[derive(Debug)] -pub enum PromptExpansionError { - Args { - command: String, - error: PromptArgsError, - }, - MissingArgs { - command: String, - missing: Vec, - }, -} - -impl PromptExpansionError { - pub fn user_message(&self) -> String { - match self { - PromptExpansionError::Args { command, error } => error.describe(command), - PromptExpansionError::MissingArgs { command, missing } => { - let list = missing.join(", "); - format!( - "Missing required args for {command}: {list}. Provide as key=value (quote values with spaces)." - ) - } - } - } -} - /// Parse a first-line slash command of the form `/name `. /// Returns `(name, rest_after_name, rest_offset)` if the line begins with `/` /// and contains a non-empty name; otherwise returns `None`. @@ -80,775 +20,6 @@ pub fn parse_slash_name(line: &str) -> Option<(&str, &str, usize)> { let rest_untrimmed = &stripped[name_end_in_stripped..]; let rest = rest_untrimmed.trim_start(); let rest_start_in_stripped = name_end_in_stripped + (rest_untrimmed.len() - rest.len()); - // `stripped` is `line` without the leading '/', so add 1 to get the original offset. let rest_offset = rest_start_in_stripped + 1; Some((name, rest, rest_offset)) } - -#[derive(Debug, Clone, PartialEq)] -pub struct PromptArg { - pub text: String, - pub text_elements: Vec, -} - -#[derive(Debug, Clone, PartialEq)] -pub struct PromptExpansion { - pub text: String, - pub text_elements: Vec, -} - -/// Parse positional arguments using shlex semantics (supports quoted tokens). -/// -/// `text_elements` must be relative to `rest`. -pub fn parse_positional_args(rest: &str, text_elements: &[TextElement]) -> Vec { - parse_tokens_with_elements(rest, text_elements) -} - -/// Extracts the unique placeholder variable names from a prompt template. -/// -/// A placeholder is any token that matches the pattern `$[A-Z][A-Z0-9_]*` -/// (for example `$USER`). The function returns the variable names without -/// the leading `$`, de-duplicated and in the order of first appearance. -pub fn prompt_argument_names(content: &str) -> Vec { - let mut seen = HashSet::new(); - let mut names = Vec::new(); - for m in PROMPT_ARG_REGEX.find_iter(content) { - if m.start() > 0 && content.as_bytes()[m.start() - 1] == b'$' { - continue; - } - let name = &content[m.start() + 1..m.end()]; - // Exclude special positional aggregate token from named args. - if name == "ARGUMENTS" { - continue; - } - let name = name.to_string(); - if seen.insert(name.clone()) { - names.push(name); - } - } - names -} - -/// Shift a text element's byte range left by `offset`, returning `None` if empty. -/// -/// `offset` is the byte length of the prefix removed from the original text. -fn shift_text_element_left(elem: &TextElement, offset: usize) -> Option { - if elem.byte_range.end <= offset { - return None; - } - let start = elem.byte_range.start.saturating_sub(offset); - let end = elem.byte_range.end.saturating_sub(offset); - (start < end).then_some(elem.map_range(|_| ByteRange { start, end })) -} - -/// Parses the `key=value` pairs that follow a custom prompt name. -/// -/// The input is split using shlex rules, so quoted values are supported -/// (for example `USER="Alice Smith"`). The function returns a map of parsed -/// arguments, or an error if a token is missing `=` or if the key is empty. -pub fn parse_prompt_inputs( - rest: &str, - text_elements: &[TextElement], -) -> Result, PromptArgsError> { - let mut map = HashMap::new(); - if rest.trim().is_empty() { - return Ok(map); - } - - // Tokenize the rest of the command using shlex rules, but keep text element - // ranges relative to each emitted token. - for token in parse_tokens_with_elements(rest, text_elements) { - let Some((key, value)) = token.text.split_once('=') else { - return Err(PromptArgsError::MissingAssignment { token: token.text }); - }; - if key.is_empty() { - return Err(PromptArgsError::MissingKey { token: token.text }); - } - // The token is `key=value`; translate element ranges into the value-only - // coordinate space by subtracting the `key=` prefix length. - let value_start = key.len() + 1; - let value_elements = token - .text_elements - .iter() - .filter_map(|elem| shift_text_element_left(elem, value_start)) - .collect(); - map.insert( - key.to_string(), - PromptArg { - text: value.to_string(), - text_elements: value_elements, - }, - ); - } - Ok(map) -} - -/// Expands a message of the form `/prompts:name [value] [value] …` using a matching saved prompt. -/// -/// If the text does not start with `/prompts:`, or if no prompt named `name` exists, -/// the function returns `Ok(None)`. On success it returns -/// `Ok(Some(expanded))`; otherwise it returns a descriptive error. -pub fn expand_custom_prompt( - text: &str, - text_elements: &[TextElement], - custom_prompts: &[CustomPrompt], -) -> Result, PromptExpansionError> { - let Some((name, rest, rest_offset)) = parse_slash_name(text) else { - return Ok(None); - }; - - // Only handle custom prompts when using the explicit prompts prefix with a colon. - let Some(prompt_name) = name.strip_prefix(&format!("{PROMPTS_CMD_PREFIX}:")) else { - return Ok(None); - }; - - let prompt = match custom_prompts.iter().find(|p| p.name == prompt_name) { - Some(prompt) => prompt, - None => return Ok(None), - }; - // If there are named placeholders, expect key=value inputs. - let required = prompt_argument_names(&prompt.content); - let local_elements: Vec = text_elements - .iter() - .filter_map(|elem| { - let mut shifted = shift_text_element_left(elem, rest_offset)?; - if shifted.byte_range.start >= rest.len() { - return None; - } - let end = shifted.byte_range.end.min(rest.len()); - shifted.byte_range.end = end; - (shifted.byte_range.start < shifted.byte_range.end).then_some(shifted) - }) - .collect(); - if !required.is_empty() { - let inputs = parse_prompt_inputs(rest, &local_elements).map_err(|error| { - PromptExpansionError::Args { - command: format!("/{name}"), - error, - } - })?; - let missing: Vec = required - .into_iter() - .filter(|k| !inputs.contains_key(k)) - .collect(); - if !missing.is_empty() { - return Err(PromptExpansionError::MissingArgs { - command: format!("/{name}"), - missing, - }); - } - let (text, elements) = expand_named_placeholders_with_elements(&prompt.content, &inputs); - return Ok(Some(PromptExpansion { - text, - text_elements: elements, - })); - } - - // Otherwise, treat it as numeric/positional placeholder prompt (or none). - let pos_args = parse_positional_args(rest, &local_elements); - Ok(Some(expand_numeric_placeholders( - &prompt.content, - &pos_args, - ))) -} - -/// Detect whether `content` contains numeric placeholders ($1..$9) or `$ARGUMENTS`. -pub fn prompt_has_numeric_placeholders(content: &str) -> bool { - if content.contains("$ARGUMENTS") { - return true; - } - let bytes = content.as_bytes(); - let mut i = 0; - while i + 1 < bytes.len() { - if bytes[i] == b'$' { - let b1 = bytes[i + 1]; - if (b'1'..=b'9').contains(&b1) { - return true; - } - } - i += 1; - } - false -} - -/// Extract positional arguments from a composer first line like "/name a b" for a given prompt name. -/// Returns empty when the command name does not match or when there are no args. -pub fn extract_positional_args_for_prompt_line( - line: &str, - prompt_name: &str, - text_elements: &[TextElement], -) -> Vec { - let trimmed = line.trim_start(); - let trim_offset = line.len() - trimmed.len(); - let Some((name, rest, rest_offset)) = parse_slash_name(trimmed) else { - return Vec::new(); - }; - // Require the explicit prompts prefix for custom prompt invocations. - let Some(after_prefix) = name.strip_prefix(&format!("{PROMPTS_CMD_PREFIX}:")) else { - return Vec::new(); - }; - if after_prefix != prompt_name { - return Vec::new(); - } - let rest_trimmed_start = rest.trim_start(); - let args_str = rest_trimmed_start.trim_end(); - if args_str.is_empty() { - return Vec::new(); - } - let args_offset = trim_offset + rest_offset + (rest.len() - rest_trimmed_start.len()); - let local_elements: Vec = text_elements - .iter() - .filter_map(|elem| { - let mut shifted = shift_text_element_left(elem, args_offset)?; - if shifted.byte_range.start >= args_str.len() { - return None; - } - let end = shifted.byte_range.end.min(args_str.len()); - shifted.byte_range.end = end; - (shifted.byte_range.start < shifted.byte_range.end).then_some(shifted) - }) - .collect(); - parse_positional_args(args_str, &local_elements) -} - -/// If the prompt only uses numeric placeholders and the first line contains -/// positional args for it, expand and return Some(expanded); otherwise None. -pub fn expand_if_numeric_with_positional_args( - prompt: &CustomPrompt, - first_line: &str, - text_elements: &[TextElement], -) -> Option { - if !prompt_argument_names(&prompt.content).is_empty() { - return None; - } - if !prompt_has_numeric_placeholders(&prompt.content) { - return None; - } - let args = extract_positional_args_for_prompt_line(first_line, &prompt.name, text_elements); - if args.is_empty() { - return None; - } - Some(expand_numeric_placeholders(&prompt.content, &args)) -} - -/// Expand `$1..$9` and `$ARGUMENTS` in `content` with values from `args`. -pub fn expand_numeric_placeholders(content: &str, args: &[PromptArg]) -> PromptExpansion { - let mut out = String::with_capacity(content.len()); - let mut out_elements = Vec::new(); - let mut i = 0; - while let Some(off) = content[i..].find('$') { - let j = i + off; - out.push_str(&content[i..j]); - let rest = &content[j..]; - let bytes = rest.as_bytes(); - if bytes.len() >= 2 { - match bytes[1] { - b'$' => { - out.push_str("$$"); - i = j + 2; - continue; - } - b'1'..=b'9' => { - let idx = (bytes[1] - b'1') as usize; - if let Some(arg) = args.get(idx) { - append_arg_with_elements(&mut out, &mut out_elements, arg); - } - i = j + 2; - continue; - } - _ => {} - } - } - if rest.len() > "ARGUMENTS".len() && rest[1..].starts_with("ARGUMENTS") { - if !args.is_empty() { - append_joined_args_with_elements(&mut out, &mut out_elements, args); - } - i = j + 1 + "ARGUMENTS".len(); - continue; - } - out.push('$'); - i = j + 1; - } - out.push_str(&content[i..]); - PromptExpansion { - text: out, - text_elements: out_elements, - } -} - -fn parse_tokens_with_elements(rest: &str, text_elements: &[TextElement]) -> Vec { - let mut elements = text_elements.to_vec(); - elements.sort_by_key(|elem| elem.byte_range.start); - // Keep element placeholders intact across shlex splitting by replacing - // each element range with a unique sentinel token first. - let (rest_for_shlex, replacements) = replace_text_elements_with_sentinels(rest, &elements); - Shlex::new(&rest_for_shlex) - .map(|token| apply_replacements_to_token(token, &replacements)) - .collect() -} - -#[derive(Debug, Clone)] -struct ElementReplacement { - sentinel: String, - text: String, - placeholder: Option, -} - -/// Replace each text element range with a unique sentinel token. -/// -/// The sentinel is chosen so it will survive shlex tokenization as a single word. -fn replace_text_elements_with_sentinels( - rest: &str, - elements: &[TextElement], -) -> (String, Vec) { - let mut out = String::with_capacity(rest.len()); - let mut replacements = Vec::new(); - let mut cursor = 0; - - for (idx, elem) in elements.iter().enumerate() { - let start = elem.byte_range.start; - let end = elem.byte_range.end; - out.push_str(&rest[cursor..start]); - let mut sentinel = format!("__CODEX_ELEM_{idx}__"); - // Ensure we never collide with user content so a sentinel can't be mistaken for text. - while rest.contains(&sentinel) { - sentinel.push('_'); - } - out.push_str(&sentinel); - replacements.push(ElementReplacement { - sentinel, - text: rest[start..end].to_string(), - placeholder: elem.placeholder(rest).map(str::to_string), - }); - cursor = end; - } - - out.push_str(&rest[cursor..]); - (out, replacements) -} - -/// Rehydrate a shlex token by swapping sentinels back to the original text -/// and rebuilding text element ranges relative to the resulting token. -fn apply_replacements_to_token(token: String, replacements: &[ElementReplacement]) -> PromptArg { - if replacements.is_empty() { - return PromptArg { - text: token, - text_elements: Vec::new(), - }; - } - - let mut out = String::with_capacity(token.len()); - let mut out_elements = Vec::new(); - let mut cursor = 0; - - while cursor < token.len() { - let Some((offset, replacement)) = next_replacement(&token, cursor, replacements) else { - out.push_str(&token[cursor..]); - break; - }; - let start_in_token = cursor + offset; - out.push_str(&token[cursor..start_in_token]); - let start = out.len(); - out.push_str(&replacement.text); - let end = out.len(); - if start < end { - out_elements.push(TextElement::new( - ByteRange { start, end }, - replacement.placeholder.clone(), - )); - } - cursor = start_in_token + replacement.sentinel.len(); - } - - PromptArg { - text: out, - text_elements: out_elements, - } -} - -/// Find the earliest sentinel occurrence at or after `cursor`. -fn next_replacement<'a>( - token: &str, - cursor: usize, - replacements: &'a [ElementReplacement], -) -> Option<(usize, &'a ElementReplacement)> { - let slice = &token[cursor..]; - let mut best: Option<(usize, &'a ElementReplacement)> = None; - for replacement in replacements { - if let Some(pos) = slice.find(&replacement.sentinel) { - match best { - Some((best_pos, _)) if best_pos <= pos => {} - _ => best = Some((pos, replacement)), - } - } - } - best -} - -fn expand_named_placeholders_with_elements( - content: &str, - args: &HashMap, -) -> (String, Vec) { - let mut out = String::with_capacity(content.len()); - let mut out_elements = Vec::new(); - let mut cursor = 0; - for m in PROMPT_ARG_REGEX.find_iter(content) { - let start = m.start(); - let end = m.end(); - if start > 0 && content.as_bytes()[start - 1] == b'$' { - out.push_str(&content[cursor..end]); - cursor = end; - continue; - } - out.push_str(&content[cursor..start]); - cursor = end; - let key = &content[start + 1..end]; - if let Some(arg) = args.get(key) { - append_arg_with_elements(&mut out, &mut out_elements, arg); - } else { - out.push_str(&content[start..end]); - } - } - out.push_str(&content[cursor..]); - (out, out_elements) -} - -fn append_arg_with_elements( - out: &mut String, - out_elements: &mut Vec, - arg: &PromptArg, -) { - let start = out.len(); - out.push_str(&arg.text); - if arg.text_elements.is_empty() { - return; - } - out_elements.extend(arg.text_elements.iter().map(|elem| { - elem.map_range(|range| ByteRange { - start: start + range.start, - end: start + range.end, - }) - })); -} - -fn append_joined_args_with_elements( - out: &mut String, - out_elements: &mut Vec, - args: &[PromptArg], -) { - // `$ARGUMENTS` joins args with single spaces while preserving element ranges. - for (idx, arg) in args.iter().enumerate() { - if idx > 0 { - out.push(' '); - } - append_arg_with_elements(out, out_elements, arg); - } -} - -/// Constructs a command text for a custom prompt with arguments. -/// Returns the text and the cursor position (inside the first double quote). -pub fn prompt_command_with_arg_placeholders(name: &str, args: &[String]) -> (String, usize) { - let mut text = format!("/{PROMPTS_CMD_PREFIX}:{name}"); - let mut cursor: usize = text.len(); - for (i, arg) in args.iter().enumerate() { - text.push_str(format!(" {arg}=\"\"").as_str()); - if i == 0 { - cursor = text.len() - 1; // inside first "" - } - } - (text, cursor) -} - -#[cfg(test)] -mod tests { - use super::*; - use pretty_assertions::assert_eq; - - #[test] - fn expand_arguments_basic() { - let prompts = vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review $USER changes on $BRANCH".to_string(), - description: None, - argument_hint: None, - }]; - - let out = expand_custom_prompt("/prompts:my-prompt USER=Alice BRANCH=main", &[], &prompts) - .unwrap(); - assert_eq!( - out, - Some(PromptExpansion { - text: "Review Alice changes on main".to_string(), - text_elements: Vec::new(), - }) - ); - } - - #[test] - fn quoted_values_ok() { - let prompts = vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Pair $USER with $BRANCH".to_string(), - description: None, - argument_hint: None, - }]; - - let out = expand_custom_prompt( - "/prompts:my-prompt USER=\"Alice Smith\" BRANCH=dev-main", - &[], - &prompts, - ) - .unwrap(); - assert_eq!( - out, - Some(PromptExpansion { - text: "Pair Alice Smith with dev-main".to_string(), - text_elements: Vec::new(), - }) - ); - } - - #[test] - fn invalid_arg_token_reports_error() { - let prompts = vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review $USER changes".to_string(), - description: None, - argument_hint: None, - }]; - let err = expand_custom_prompt("/prompts:my-prompt USER=Alice stray", &[], &prompts) - .unwrap_err() - .user_message(); - assert!(err.contains("expected key=value")); - } - - #[test] - fn missing_required_args_reports_error() { - let prompts = vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "Review $USER changes on $BRANCH".to_string(), - description: None, - argument_hint: None, - }]; - let err = expand_custom_prompt("/prompts:my-prompt USER=Alice", &[], &prompts) - .unwrap_err() - .user_message(); - assert!(err.to_lowercase().contains("missing required args")); - assert!(err.contains("BRANCH")); - } - - #[test] - fn escaped_placeholder_is_ignored() { - assert_eq!( - prompt_argument_names("literal $$USER"), - Vec::::new() - ); - assert_eq!( - prompt_argument_names("literal $$USER and $REAL"), - vec!["REAL".to_string()] - ); - } - - #[test] - fn escaped_placeholder_remains_literal() { - let prompts = vec![CustomPrompt { - name: "my-prompt".to_string(), - path: "/tmp/my-prompt.md".to_string().into(), - content: "literal $$USER".to_string(), - description: None, - argument_hint: None, - }]; - - let out = expand_custom_prompt("/prompts:my-prompt", &[], &prompts).unwrap(); - assert_eq!( - out, - Some(PromptExpansion { - text: "literal $$USER".to_string(), - text_elements: Vec::new(), - }) - ); - } - - #[test] - fn positional_args_treat_placeholder_with_spaces_as_single_token() { - let placeholder = "[Image #1]"; - let rest = format!("alpha {placeholder} beta"); - let start = rest.find(placeholder).expect("placeholder"); - let end = start + placeholder.len(); - let text_elements = vec![TextElement::new( - ByteRange { start, end }, - Some(placeholder.to_string()), - )]; - - let args = parse_positional_args(&rest, &text_elements); - assert_eq!( - args, - vec![ - PromptArg { - text: "alpha".to_string(), - text_elements: Vec::new(), - }, - PromptArg { - text: placeholder.to_string(), - text_elements: vec![TextElement::new( - ByteRange { - start: 0, - end: placeholder.len(), - }, - Some(placeholder.to_string()), - )], - }, - PromptArg { - text: "beta".to_string(), - text_elements: Vec::new(), - } - ] - ); - } - - #[test] - fn extract_positional_args_shifts_element_offsets_into_args_str() { - let placeholder = "[Image #1]"; - let line = format!(" /{PROMPTS_CMD_PREFIX}:my-prompt alpha {placeholder} beta "); - let start = line.find(placeholder).expect("placeholder"); - let end = start + placeholder.len(); - let text_elements = vec![TextElement::new( - ByteRange { start, end }, - Some(placeholder.to_string()), - )]; - - let args = extract_positional_args_for_prompt_line(&line, "my-prompt", &text_elements); - assert_eq!( - args, - vec![ - PromptArg { - text: "alpha".to_string(), - text_elements: Vec::new(), - }, - PromptArg { - text: placeholder.to_string(), - text_elements: vec![TextElement::new( - ByteRange { - start: 0, - end: placeholder.len(), - }, - Some(placeholder.to_string()), - )], - }, - PromptArg { - text: "beta".to_string(), - text_elements: Vec::new(), - } - ] - ); - } - - #[test] - fn key_value_args_treat_placeholder_with_spaces_as_single_token() { - let placeholder = "[Image #1]"; - let rest = format!("IMG={placeholder} NOTE=hello"); - let start = rest.find(placeholder).expect("placeholder"); - let end = start + placeholder.len(); - let text_elements = vec![TextElement::new( - ByteRange { start, end }, - Some(placeholder.to_string()), - )]; - - let args = parse_prompt_inputs(&rest, &text_elements).expect("inputs"); - assert_eq!( - args.get("IMG"), - Some(&PromptArg { - text: placeholder.to_string(), - text_elements: vec![TextElement::new( - ByteRange { - start: 0, - end: placeholder.len(), - }, - Some(placeholder.to_string()), - )], - }) - ); - assert_eq!( - args.get("NOTE"), - Some(&PromptArg { - text: "hello".to_string(), - text_elements: Vec::new(), - }) - ); - } - - #[test] - fn positional_args_allow_placeholder_inside_quotes() { - let placeholder = "[Image #1]"; - let rest = format!("alpha \"see {placeholder} here\" beta"); - let start = rest.find(placeholder).expect("placeholder"); - let end = start + placeholder.len(); - let text_elements = vec![TextElement::new( - ByteRange { start, end }, - Some(placeholder.to_string()), - )]; - - let args = parse_positional_args(&rest, &text_elements); - assert_eq!( - args, - vec![ - PromptArg { - text: "alpha".to_string(), - text_elements: Vec::new(), - }, - PromptArg { - text: format!("see {placeholder} here"), - text_elements: vec![TextElement::new( - ByteRange { - start: "see ".len(), - end: "see ".len() + placeholder.len(), - }, - Some(placeholder.to_string()), - )], - }, - PromptArg { - text: "beta".to_string(), - text_elements: Vec::new(), - } - ] - ); - } - - #[test] - fn key_value_args_allow_placeholder_inside_quotes() { - let placeholder = "[Image #1]"; - let rest = format!("IMG=\"see {placeholder} here\" NOTE=ok"); - let start = rest.find(placeholder).expect("placeholder"); - let end = start + placeholder.len(); - let text_elements = vec![TextElement::new( - ByteRange { start, end }, - Some(placeholder.to_string()), - )]; - - let args = parse_prompt_inputs(&rest, &text_elements).expect("inputs"); - assert_eq!( - args.get("IMG"), - Some(&PromptArg { - text: format!("see {placeholder} here"), - text_elements: vec![TextElement::new( - ByteRange { - start: "see ".len(), - end: "see ".len() + placeholder.len(), - }, - Some(placeholder.to_string()), - )], - }) - ); - assert_eq!( - args.get("NOTE"), - Some(&PromptArg { - text: "ok".to_string(), - text_elements: Vec::new(), - }) - ); - } -} diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index cb5c039ce1..dd04aec372 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -6821,9 +6821,6 @@ impl ChatWidget { EventMsg::WebSearchEnd(ev) => self.on_web_search_end(ev), EventMsg::GetHistoryEntryResponse(ev) => self.handle_history_entry_response(ev), EventMsg::McpListToolsResponse(ev) => self.on_list_mcp_tools(ev), - EventMsg::ListCustomPromptsResponse(_) => { - tracing::warn!("ignoring unsupported custom prompt list response in TUI"); - } EventMsg::ListSkillsResponse(ev) => self.on_list_skills(ev), EventMsg::SkillsUpdateAvailable => { self.submit_op(AppCommand::list_skills( diff --git a/docs/prompts.md b/docs/prompts.md deleted file mode 100644 index fa3da5b3bd..0000000000 --- a/docs/prompts.md +++ /dev/null @@ -1,3 +0,0 @@ -# Custom prompts - -For an overview of custom prompts, see [this documentation](https://developers.openai.com/codex/custom-prompts). diff --git a/docs/tui-chat-composer.md b/docs/tui-chat-composer.md index 5630b84eca..a61a0b5beb 100644 --- a/docs/tui-chat-composer.md +++ b/docs/tui-chat-composer.md @@ -81,8 +81,6 @@ Key effects when disabled: - When `popups_enabled` is `false`, `sync_popups()` forces `ActivePopup::None`. - When `slash_commands_enabled` is `false`, the composer does not treat `/...` input as commands. -- When `slash_commands_enabled` is `false`, the composer does not expand custom prompts in - `prepare_submission_text`. - When `slash_commands_enabled` is `false`, slash-context paste-burst exceptions are disabled. - When `image_paste_enabled` is `false`, file-path paste image attachment is skipped. - `ChatWidget` may toggle `image_paste_enabled` at runtime based on the selected model's @@ -107,12 +105,8 @@ the input starts with `!` (shell command). 1. Expands any pending paste placeholders so element ranges align with the final text. 2. Trims whitespace and rebases element ranges to the trimmed buffer. -3. Expands `/prompts:` custom prompts: - - Named args use key=value parsing. - - Numeric args use positional parsing for `$1..$9` and `$ARGUMENTS`. - The expansion preserves text elements and yields the final submission payload. -4. Prunes attachments so only placeholders that survive expansion are sent. -5. Clears pending pastes on success and suppresses submission if the final text is empty and there +3. Prunes attachments so only placeholders that survive trimming are sent. +4. Clears pending pastes on success and suppresses submission if the final text is empty and there are no attachments. The same preparation path is reused for slash commands with arguments (for example `/plan` and @@ -124,16 +118,6 @@ still available for `Ctrl+Y`. This supports flows where a user kills part of a d composer action such as changing reasoning level, and then yanks that text back into the cleared draft. -### Numeric auto-submit path - -When the slash popup is open and the first line matches a numeric-only custom prompt with -positional args, Enter auto-submits without calling `prepare_submission_text`. That path still: - -- Expands pending pastes before parsing positional args. -- Uses expanded text elements for prompt expansion. -- Prunes attachments based on expanded placeholders. -- Clears pending pastes after a successful auto-submit. - ## Remote image rows (selection/deletion flow) Remote image URLs are shown as `[Image #N]` rows above the textarea, inside the same composer box. From 178d2b00b1da55e24a16695337bb1b78d6f5883c Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sat, 28 Mar 2026 13:53:33 -0600 Subject: [PATCH 03/17] Remove the codex-tui app-server originator workaround (#16116) ## Summary - remove the temporary `codex-tui` special-case when setting the default originator during app-server initialization --- codex-rs/app-server/src/message_processor.rs | 10 +--------- codex-rs/login/src/auth/default_client.rs | 1 + codex-rs/login/src/auth/default_client_tests.rs | 1 + 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/codex-rs/app-server/src/message_processor.rs b/codex-rs/app-server/src/message_processor.rs index ff0402e903..7f0e1d18f8 100644 --- a/codex-rs/app-server/src/message_processor.rs +++ b/codex-rs/app-server/src/message_processor.rs @@ -61,7 +61,6 @@ use codex_core::ThreadManager; use codex_core::config::Config; use codex_core::config_loader::CloudRequirementsLoader; use codex_core::config_loader::LoaderOverrides; -use codex_core::default_client::DEFAULT_ORIGINATOR; use codex_core::default_client::SetOriginatorError; use codex_core::default_client::USER_AGENT_SUFFIX; use codex_core::default_client::get_codex_user_agent; @@ -88,7 +87,6 @@ use toml::Value as TomlValue; use tracing::Instrument; const EXTERNAL_AUTH_REFRESH_TIMEOUT: Duration = Duration::from_secs(10); -const TUI_CLIENT_NAME: &str = "codex-tui"; #[derive(Clone)] struct ExternalAuthRefreshBridge { @@ -569,13 +567,7 @@ impl MessageProcessor { } = params.client_info; session.app_server_client_name = Some(name.clone()); session.client_version = Some(version.clone()); - let originator = if name == TUI_CLIENT_NAME { - // TODO: Remove this temporary workaround once the TUI no longer - // needs to retain the `codex_cli_rs` originator behavior. - DEFAULT_ORIGINATOR.to_string() - } else { - name.clone() - }; + let originator = name.clone(); if let Err(error) = set_default_originator(originator) { match error { SetOriginatorError::InvalidHeaderValue => { diff --git a/codex-rs/login/src/auth/default_client.rs b/codex-rs/login/src/auth/default_client.rs index 87a7132d9c..7923c74782 100644 --- a/codex-rs/login/src/auth/default_client.rs +++ b/codex-rs/login/src/auth/default_client.rs @@ -119,6 +119,7 @@ pub fn originator() -> Originator { pub fn is_first_party_originator(originator_value: &str) -> bool { originator_value == DEFAULT_ORIGINATOR + || originator_value == "codex-tui" || originator_value == "codex_vscode" || originator_value.starts_with("Codex ") } diff --git a/codex-rs/login/src/auth/default_client_tests.rs b/codex-rs/login/src/auth/default_client_tests.rs index 6a0ce1432b..be8e6bc392 100644 --- a/codex-rs/login/src/auth/default_client_tests.rs +++ b/codex-rs/login/src/auth/default_client_tests.rs @@ -14,6 +14,7 @@ fn test_get_codex_user_agent() { #[test] fn is_first_party_originator_matches_known_values() { assert_eq!(is_first_party_originator(DEFAULT_ORIGINATOR), true); + assert_eq!(is_first_party_originator("codex-tui"), true); assert_eq!(is_first_party_originator("codex_vscode"), true); assert_eq!(is_first_party_originator("Codex Something Else"), true); assert_eq!(is_first_party_originator("codex_cli"), false); From bc53d42fd98c3e7bc74ece9ac31ddbe894b7a942 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 13:37:00 -0700 Subject: [PATCH 04/17] codex-tools: extract tool spec models (#16047) ## Why This continues the `codex-tools` migration by moving another passive tool-definition layer out of `codex-core`. After `ResponsesApiTool` and the lower-level schema adapters moved into `codex-tools`, `core/src/client_common.rs` was still owning `ToolSpec` and the web-search request wire types even though they are serialized data models rather than runtime orchestration. Keeping those types in `codex-core` makes the crate boundary look smaller than it really is and leaves non-runtime tool-shape code coupled to core. ## What changed - moved `ToolSpec`, `ResponsesApiWebSearchFilters`, and `ResponsesApiWebSearchUserLocation` into `codex-rs/tools/src/tool_spec.rs` - added focused unit tests in `codex-rs/tools/src/tool_spec_tests.rs` for: - `ToolSpec::name()` - web-search config conversions - `ToolSpec` serialization for `web_search` and `tool_search` - kept `codex-rs/tools/src/lib.rs` exports-only by re-exporting the new module from `lib.rs` - reduced `core/src/client_common.rs` to a compatibility shim that re-exports the extracted tool-spec types for current core call sites - updated `core/src/tools/spec_tests.rs` to consume the extracted web-search types directly from `codex-tools` - updated `codex-rs/tools/README.md` so the crate contract reflects that `codex-tools` now owns the passive tool-spec request models in addition to the lower-level Responses API structs ## Test plan - `cargo test -p codex-tools` - `cargo test -p codex-core --lib tools::spec::` - `cargo test -p codex-core --lib client_common::` - `just fix -p codex-tools -p codex-core` - `just argument-comment-lint` ## References - #15923 - #15928 - #15944 - #15953 - #16031 --- codex-rs/core/src/client_common.rs | 100 +------------- codex-rs/core/src/tools/spec_tests.rs | 17 +-- codex-rs/tools/README.md | 3 + codex-rs/tools/src/lib.rs | 4 + codex-rs/tools/src/tool_spec.rs | 105 +++++++++++++++ codex-rs/tools/src/tool_spec_tests.rs | 183 ++++++++++++++++++++++++++ 6 files changed, 303 insertions(+), 109 deletions(-) create mode 100644 codex-rs/tools/src/tool_spec.rs create mode 100644 codex-rs/tools/src/tool_spec_tests.rs diff --git a/codex-rs/core/src/client_common.rs b/codex-rs/core/src/client_common.rs index 50a523a26e..908dec56c6 100644 --- a/codex-rs/core/src/client_common.rs +++ b/codex-rs/core/src/client_common.rs @@ -1,10 +1,10 @@ -use crate::client_common::tools::ToolSpec; use crate::config::types::Personality; use crate::error::Result; pub use codex_api::common::ResponseEvent; use codex_protocol::models::BaseInstructions; use codex_protocol::models::FunctionCallOutputBody; use codex_protocol::models::ResponseItem; +use codex_tools::ToolSpec; use futures::Stream; use serde::Deserialize; use serde_json::Value; @@ -157,107 +157,11 @@ fn strip_total_output_header(output: &str) -> Option<(&str, u32)> { } pub(crate) mod tools { - use codex_protocol::config_types::WebSearchContextSize; - use codex_protocol::config_types::WebSearchFilters as ConfigWebSearchFilters; - use codex_protocol::config_types::WebSearchUserLocation as ConfigWebSearchUserLocation; - use codex_protocol::config_types::WebSearchUserLocationType; pub(crate) use codex_tools::FreeformTool; pub(crate) use codex_tools::FreeformToolFormat; - use codex_tools::JsonSchema; pub(crate) use codex_tools::ResponsesApiTool; pub(crate) use codex_tools::ToolSearchOutputTool; - use serde::Serialize; - - /// When serialized as JSON, this produces a valid "Tool" in the OpenAI - /// Responses API. - #[derive(Debug, Clone, Serialize, PartialEq)] - #[serde(tag = "type")] - pub(crate) enum ToolSpec { - #[serde(rename = "function")] - Function(ResponsesApiTool), - #[serde(rename = "tool_search")] - ToolSearch { - execution: String, - description: String, - parameters: JsonSchema, - }, - #[serde(rename = "local_shell")] - LocalShell {}, - #[serde(rename = "image_generation")] - ImageGeneration { output_format: String }, - // TODO: Understand why we get an error on web_search although the API docs say it's supported. - // https://platform.openai.com/docs/guides/tools-web-search?api-mode=responses#:~:text=%7B%20type%3A%20%22web_search%22%20%7D%2C - // The `external_web_access` field determines whether the web search is over cached or live content. - // https://platform.openai.com/docs/guides/tools-web-search#live-internet-access - #[serde(rename = "web_search")] - WebSearch { - #[serde(skip_serializing_if = "Option::is_none")] - external_web_access: Option, - #[serde(skip_serializing_if = "Option::is_none")] - filters: Option, - #[serde(skip_serializing_if = "Option::is_none")] - user_location: Option, - #[serde(skip_serializing_if = "Option::is_none")] - search_context_size: Option, - #[serde(skip_serializing_if = "Option::is_none")] - search_content_types: Option>, - }, - #[serde(rename = "custom")] - Freeform(FreeformTool), - } - - impl ToolSpec { - pub(crate) fn name(&self) -> &str { - match self { - ToolSpec::Function(tool) => tool.name.as_str(), - ToolSpec::ToolSearch { .. } => "tool_search", - ToolSpec::LocalShell {} => "local_shell", - ToolSpec::ImageGeneration { .. } => "image_generation", - ToolSpec::WebSearch { .. } => "web_search", - ToolSpec::Freeform(tool) => tool.name.as_str(), - } - } - } - - #[derive(Debug, Clone, Serialize, PartialEq)] - pub(crate) struct ResponsesApiWebSearchFilters { - #[serde(skip_serializing_if = "Option::is_none")] - pub(crate) allowed_domains: Option>, - } - - impl From for ResponsesApiWebSearchFilters { - fn from(filters: ConfigWebSearchFilters) -> Self { - Self { - allowed_domains: filters.allowed_domains, - } - } - } - - #[derive(Debug, Clone, Serialize, PartialEq)] - pub(crate) struct ResponsesApiWebSearchUserLocation { - #[serde(rename = "type")] - pub(crate) r#type: WebSearchUserLocationType, - #[serde(skip_serializing_if = "Option::is_none")] - pub(crate) country: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub(crate) region: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub(crate) city: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub(crate) timezone: Option, - } - - impl From for ResponsesApiWebSearchUserLocation { - fn from(user_location: ConfigWebSearchUserLocation) -> Self { - Self { - r#type: user_location.r#type, - country: user_location.country, - region: user_location.region, - city: user_location.city, - timezone: user_location.timezone, - } - } - } + pub(crate) use codex_tools::ToolSpec; } pub struct ResponseStream { diff --git a/codex-rs/core/src/tools/spec_tests.rs b/codex-rs/core/src/tools/spec_tests.rs index b62407778f..60339b7811 100644 --- a/codex-rs/core/src/tools/spec_tests.rs +++ b/codex-rs/core/src/tools/spec_tests.rs @@ -1,4 +1,3 @@ -use crate::client_common::tools::FreeformTool; use crate::config::test_config; use crate::models_manager::manager::ModelsManager; use crate::models_manager::model_info::with_config_overrides; @@ -12,6 +11,9 @@ use codex_protocol::openai_models::InputModality; use codex_protocol::openai_models::ModelInfo; use codex_protocol::openai_models::ModelsResponse; use codex_tools::AdditionalProperties; +use codex_tools::FreeformTool; +use codex_tools::ResponsesApiWebSearchFilters; +use codex_tools::ResponsesApiWebSearchUserLocation; use codex_tools::mcp_tool_to_deferred_responses_api_tool; use codex_utils_absolute_path::AbsolutePathBuf; use pretty_assertions::assert_eq; @@ -106,14 +108,7 @@ fn deferred_responses_api_tool_serializes_with_defer_loading() { } fn tool_name(tool: &ToolSpec) -> &str { - match tool { - ToolSpec::Function(ResponsesApiTool { name, .. }) => name, - ToolSpec::ToolSearch { .. } => "tool_search", - ToolSpec::LocalShell {} => "local_shell", - ToolSpec::ImageGeneration { .. } => "image_generation", - ToolSpec::WebSearch { .. } => "web_search", - ToolSpec::Freeform(FreeformTool { name, .. }) => name, - } + tool.name() } // Avoid order-based assertions; compare via set containment instead. @@ -1205,10 +1200,10 @@ fn web_search_config_is_forwarded_to_tool_spec() { external_web_access: Some(true), filters: web_search_config .filters - .map(crate::client_common::tools::ResponsesApiWebSearchFilters::from), + .map(ResponsesApiWebSearchFilters::from), user_location: web_search_config .user_location - .map(crate::client_common::tools::ResponsesApiWebSearchUserLocation::from), + .map(ResponsesApiWebSearchUserLocation::from), search_context_size: web_search_config.search_context_size, search_content_types: None, } diff --git a/codex-rs/tools/README.md b/codex-rs/tools/README.md index ca73e8cf63..d8dabdcd72 100644 --- a/codex-rs/tools/README.md +++ b/codex-rs/tools/README.md @@ -11,10 +11,13 @@ schema and Responses API tool primitives that no longer need to live in - `JsonSchema` - `AdditionalProperties` - `ToolDefinition` +- `ToolSpec` - `ResponsesApiTool` - `FreeformTool` - `FreeformToolFormat` - `ToolSearchOutputTool` +- `ResponsesApiWebSearchFilters` +- `ResponsesApiWebSearchUserLocation` - `ResponsesApiNamespace` - `ResponsesApiNamespaceTool` - `parse_tool_input_schema()` diff --git a/codex-rs/tools/src/lib.rs b/codex-rs/tools/src/lib.rs index 92dc860d6c..05b527ba94 100644 --- a/codex-rs/tools/src/lib.rs +++ b/codex-rs/tools/src/lib.rs @@ -6,6 +6,7 @@ mod json_schema; mod mcp_tool; mod responses_api; mod tool_definition; +mod tool_spec; pub use dynamic_tool::parse_dynamic_tool; pub use json_schema::AdditionalProperties; @@ -24,3 +25,6 @@ pub use responses_api::mcp_tool_to_deferred_responses_api_tool; pub use responses_api::mcp_tool_to_responses_api_tool; pub use responses_api::tool_definition_to_responses_api_tool; pub use tool_definition::ToolDefinition; +pub use tool_spec::ResponsesApiWebSearchFilters; +pub use tool_spec::ResponsesApiWebSearchUserLocation; +pub use tool_spec::ToolSpec; diff --git a/codex-rs/tools/src/tool_spec.rs b/codex-rs/tools/src/tool_spec.rs new file mode 100644 index 0000000000..fc63223e1b --- /dev/null +++ b/codex-rs/tools/src/tool_spec.rs @@ -0,0 +1,105 @@ +use crate::FreeformTool; +use crate::JsonSchema; +use crate::ResponsesApiTool; +use codex_protocol::config_types::WebSearchContextSize; +use codex_protocol::config_types::WebSearchFilters as ConfigWebSearchFilters; +use codex_protocol::config_types::WebSearchUserLocation as ConfigWebSearchUserLocation; +use codex_protocol::config_types::WebSearchUserLocationType; +use serde::Serialize; + +/// When serialized as JSON, this produces a valid "Tool" in the OpenAI +/// Responses API. +#[derive(Debug, Clone, Serialize, PartialEq)] +#[serde(tag = "type")] +pub enum ToolSpec { + #[serde(rename = "function")] + Function(ResponsesApiTool), + #[serde(rename = "tool_search")] + ToolSearch { + execution: String, + description: String, + parameters: JsonSchema, + }, + #[serde(rename = "local_shell")] + LocalShell {}, + #[serde(rename = "image_generation")] + ImageGeneration { output_format: String }, + // TODO: Understand why we get an error on web_search although the API docs + // say it's supported. + // https://platform.openai.com/docs/guides/tools-web-search?api-mode=responses#:~:text=%7B%20type%3A%20%22web_search%22%20%7D%2C + // The `external_web_access` field determines whether the web search is over + // cached or live content. + // https://platform.openai.com/docs/guides/tools-web-search#live-internet-access + #[serde(rename = "web_search")] + WebSearch { + #[serde(skip_serializing_if = "Option::is_none")] + external_web_access: Option, + #[serde(skip_serializing_if = "Option::is_none")] + filters: Option, + #[serde(skip_serializing_if = "Option::is_none")] + user_location: Option, + #[serde(skip_serializing_if = "Option::is_none")] + search_context_size: Option, + #[serde(skip_serializing_if = "Option::is_none")] + search_content_types: Option>, + }, + #[serde(rename = "custom")] + Freeform(FreeformTool), +} + +impl ToolSpec { + pub fn name(&self) -> &str { + match self { + ToolSpec::Function(tool) => tool.name.as_str(), + ToolSpec::ToolSearch { .. } => "tool_search", + ToolSpec::LocalShell {} => "local_shell", + ToolSpec::ImageGeneration { .. } => "image_generation", + ToolSpec::WebSearch { .. } => "web_search", + ToolSpec::Freeform(tool) => tool.name.as_str(), + } + } +} + +#[derive(Debug, Clone, Serialize, PartialEq)] +pub struct ResponsesApiWebSearchFilters { + #[serde(skip_serializing_if = "Option::is_none")] + pub allowed_domains: Option>, +} + +impl From for ResponsesApiWebSearchFilters { + fn from(filters: ConfigWebSearchFilters) -> Self { + Self { + allowed_domains: filters.allowed_domains, + } + } +} + +#[derive(Debug, Clone, Serialize, PartialEq)] +pub struct ResponsesApiWebSearchUserLocation { + #[serde(rename = "type")] + pub r#type: WebSearchUserLocationType, + #[serde(skip_serializing_if = "Option::is_none")] + pub country: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub region: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub city: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub timezone: Option, +} + +impl From for ResponsesApiWebSearchUserLocation { + fn from(user_location: ConfigWebSearchUserLocation) -> Self { + Self { + r#type: user_location.r#type, + country: user_location.country, + region: user_location.region, + city: user_location.city, + timezone: user_location.timezone, + } + } +} + +#[cfg(test)] +#[path = "tool_spec_tests.rs"] +mod tests; diff --git a/codex-rs/tools/src/tool_spec_tests.rs b/codex-rs/tools/src/tool_spec_tests.rs new file mode 100644 index 0000000000..33d31c1401 --- /dev/null +++ b/codex-rs/tools/src/tool_spec_tests.rs @@ -0,0 +1,183 @@ +use super::ResponsesApiWebSearchFilters; +use super::ResponsesApiWebSearchUserLocation; +use super::ToolSpec; +use crate::AdditionalProperties; +use crate::FreeformTool; +use crate::FreeformToolFormat; +use crate::JsonSchema; +use crate::ResponsesApiTool; +use codex_protocol::config_types::WebSearchContextSize; +use codex_protocol::config_types::WebSearchFilters as ConfigWebSearchFilters; +use codex_protocol::config_types::WebSearchUserLocation as ConfigWebSearchUserLocation; +use codex_protocol::config_types::WebSearchUserLocationType; +use pretty_assertions::assert_eq; +use serde_json::json; +use std::collections::BTreeMap; + +#[test] +fn tool_spec_name_covers_all_variants() { + assert_eq!( + ToolSpec::Function(ResponsesApiTool { + name: "lookup_order".to_string(), + description: "Look up an order".to_string(), + strict: false, + defer_loading: None, + parameters: JsonSchema::Object { + properties: BTreeMap::new(), + required: None, + additional_properties: None, + }, + output_schema: None, + }) + .name(), + "lookup_order" + ); + assert_eq!( + ToolSpec::ToolSearch { + execution: "sync".to_string(), + description: "Search for tools".to_string(), + parameters: JsonSchema::Object { + properties: BTreeMap::new(), + required: None, + additional_properties: None, + }, + } + .name(), + "tool_search" + ); + assert_eq!(ToolSpec::LocalShell {}.name(), "local_shell"); + assert_eq!( + ToolSpec::ImageGeneration { + output_format: "png".to_string(), + } + .name(), + "image_generation" + ); + assert_eq!( + ToolSpec::WebSearch { + external_web_access: Some(true), + filters: None, + user_location: None, + search_context_size: None, + search_content_types: None, + } + .name(), + "web_search" + ); + assert_eq!( + ToolSpec::Freeform(FreeformTool { + name: "exec".to_string(), + description: "Run a command".to_string(), + format: FreeformToolFormat { + r#type: "grammar".to_string(), + syntax: "lark".to_string(), + definition: "start: \"exec\"".to_string(), + }, + }) + .name(), + "exec" + ); +} + +#[test] +fn web_search_config_converts_to_responses_api_types() { + assert_eq!( + ResponsesApiWebSearchFilters::from(ConfigWebSearchFilters { + allowed_domains: Some(vec!["example.com".to_string()]), + }), + ResponsesApiWebSearchFilters { + allowed_domains: Some(vec!["example.com".to_string()]), + } + ); + assert_eq!( + ResponsesApiWebSearchUserLocation::from(ConfigWebSearchUserLocation { + r#type: WebSearchUserLocationType::Approximate, + country: Some("US".to_string()), + region: Some("California".to_string()), + city: Some("San Francisco".to_string()), + timezone: Some("America/Los_Angeles".to_string()), + }), + ResponsesApiWebSearchUserLocation { + r#type: WebSearchUserLocationType::Approximate, + country: Some("US".to_string()), + region: Some("California".to_string()), + city: Some("San Francisco".to_string()), + timezone: Some("America/Los_Angeles".to_string()), + } + ); +} + +#[test] +fn web_search_tool_spec_serializes_expected_wire_shape() { + assert_eq!( + serde_json::to_value(ToolSpec::WebSearch { + external_web_access: Some(true), + filters: Some(ResponsesApiWebSearchFilters { + allowed_domains: Some(vec!["example.com".to_string()]), + }), + user_location: Some(ResponsesApiWebSearchUserLocation { + r#type: WebSearchUserLocationType::Approximate, + country: Some("US".to_string()), + region: Some("California".to_string()), + city: Some("San Francisco".to_string()), + timezone: Some("America/Los_Angeles".to_string()), + }), + search_context_size: Some(WebSearchContextSize::High), + search_content_types: Some(vec!["text".to_string(), "image".to_string()]), + }) + .expect("serialize web_search"), + json!({ + "type": "web_search", + "external_web_access": true, + "filters": { + "allowed_domains": ["example.com"], + }, + "user_location": { + "type": "approximate", + "country": "US", + "region": "California", + "city": "San Francisco", + "timezone": "America/Los_Angeles", + }, + "search_context_size": "high", + "search_content_types": ["text", "image"], + }) + ); +} + +#[test] +fn tool_search_tool_spec_serializes_expected_wire_shape() { + assert_eq!( + serde_json::to_value(ToolSpec::ToolSearch { + execution: "sync".to_string(), + description: "Search app tools".to_string(), + parameters: JsonSchema::Object { + properties: BTreeMap::from([( + "query".to_string(), + JsonSchema::String { + description: Some("Tool search query".to_string()), + }, + )]), + required: Some(vec!["query".to_string()]), + additional_properties: Some(AdditionalProperties::Boolean(false)), + }, + }) + .expect("serialize tool_search"), + json!({ + "type": "tool_search", + "execution": "sync", + "description": "Search app tools", + "parameters": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "Tool search query", + } + }, + "required": ["query"], + "additionalProperties": false, + }, + }) + ); +} From ae8a3be9585d0918fe38fa199c963aeb80ee4f55 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 14:08:19 -0700 Subject: [PATCH 05/17] bazel: refresh the expired macOS SDK pin (#16128) ## Why macOS BuildBuddy started failing before target analysis because the Apple CDN object pinned in [`MODULE.bazel`](https://github.com/openai/codex/blob/fce0f76d577b5070f1e2b4a2abaa8350acfc38ff/MODULE.bazel#L28-L36) now returns `403 Forbidden`. The failure report that triggered this change was this [BuildBuddy invocation](https://app.buildbuddy.io/invocation/c57590e0-1bdb-4e19-a86f-74d4a7ded228). This repo uses `@llvm//extensions:osx.bzl` via `osx.from_archive(...)`, and that API does not discover a current SDK URL for us. It fetches exactly the `urls`, `sha256`, and `strip_prefix` we pin. Once Apple retires that `swcdn.apple.com` object, `@macos_sdk` stops resolving and every downstream macOS build fails during external repository fetch. This is the same basic failure mode we hit in [b9fa08ec619c96617a9ae2041c9ddb02d2c02434](https://github.com/openai/codex/commit/b9fa08ec619c96617a9ae2041c9ddb02d2c02434): the pin itself aged out. ## How I tracked it down 1. I started from the BuildBuddy error and copied the exact `swcdn.apple.com/.../CLTools_macOSNMOS_SDK.pkg` URL from the failure. 2. I reproduced the issue outside CI by opening that URL directly in a browser and by running `curl -I` against it locally. Both returned `403 Forbidden`, which ruled out BuildBuddy as the root cause. 3. I searched the repo for that URL and found it hardcoded in `MODULE.bazel`. 4. I inspected the `llvm` Bzlmod `osx` extension implementation to confirm that `osx.from_archive(...)` is just a literal fetch of the pinned archive metadata. There is no automatic fallback or catalog lookup behind it. 5. I queried Apple's software update catalogs to find the current Command Line Tools package for macOS 26.x. The useful catalog was: - `https://swscan.apple.com/content/catalogs/others/index-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz` This is scriptable; it does not require opening a website in a browser. The catalog is a gzip-compressed plist served over HTTP, so the workflow is just: 1. fetch the catalog, 2. decompress it, 3. search or parse the plist for `CLTools_macOSNMOS_SDK.pkg` entries, 4. inspect the matching product metadata. The quick shell version I used was: ```shell curl -L \ | gzip -dc \ | rg -n -C 6 'CLTools_macOSNMOS_SDK\.pkg|PostDate|English\.dist' ``` That is enough to surface the current product id, package URL, post date, and the matching `.dist` file. If we want something less grep-driven next time, the same catalog can be parsed structurally. For example: ```python import gzip import plistlib import urllib.request url = "https://swscan.apple.com/content/catalogs/others/index-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz" with urllib.request.urlopen(url) as resp: catalog = plistlib.loads(gzip.decompress(resp.read())) for product_id, product in catalog["Products"].items(): for package in product.get("Packages", []): package_url = package.get("URL", "") if package_url.endswith("CLTools_macOSNMOS_SDK.pkg"): print(product_id) print(product.get("PostDate")) print(package_url) print(product.get("Distributions", {}).get("English")) ``` In practice, `curl` was only the transport. The important part is that the catalog itself is a machine-readable plist, so this can be automated. 6. That catalog contains the newer `047-96692` Command Line Tools release, and its distribution file identifies it as [Command Line Tools for Xcode 26.4](https://swdist.apple.com/content/downloads/32/53/047-96692-A_OAHIHT53YB/ybtshxmrcju8m2qvw3w5elr4rajtg1x3y3/047-96692.English.dist). 7. I downloaded that package locally, computed its SHA-256, expanded it with `pkgutil --expand-full`, and verified that it contains `Payload/Library/Developer/CommandLineTools/SDKs/MacOSX26.4.sdk`, which is the correct new `strip_prefix` for this pin. The core debugging loop looked like this: ```shell curl -I rg 'swcdn\.apple\.com|osx\.from_archive' MODULE.bazel curl -L | gzip -dc | rg 'CLTools_macOSNMOS_SDK.pkg' pkgutil --expand-full CLTools_macOSNMOS_SDK.pkg expanded find expanded/Payload/Library/Developer/CommandLineTools/SDKs -maxdepth 1 -mindepth 1 ``` ## What changed - Updated `MODULE.bazel` to point `osx.from_archive(...)` at the currently live `047-96692` `CLTools_macOSNMOS_SDK.pkg` object. - Updated the pinned `sha256` to match that package. - Updated the `strip_prefix` from `MacOSX26.2.sdk` to `MacOSX26.4.sdk`. ## Verification - `bazel --output_user_root="$(mktemp -d /tmp/codex-bazel-sdk-fetch.XXXXXX)" build @macos_sdk//sysroot` ## Notes for next time As long as we pin raw `swcdn.apple.com` objects, this will likely happen again. When it does, the expected recovery path is: 1. Reproduce the `403` against the exact URL from CI. 2. Find the stale pin in `MODULE.bazel`. 3. Look up the current CLTools package in the relevant Apple software update catalog for that macOS major version. 4. Download the replacement package and refresh both `sha256` and `strip_prefix`. 5. Validate the new pin with a fresh `@macos_sdk` fetch, not just an incremental Bazel build. The important detail is that the non-`26` catalog did not surface the macOS 26.x SDK package here; the `index-26-15-14-...` catalog was the one that exposed the currently live replacement. --- MODULE.bazel | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 8163c0b018..e71f92ca77 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -27,11 +27,11 @@ register_toolchains("@llvm//toolchain:all") osx = use_extension("@llvm//extensions:osx.bzl", "osx") osx.from_archive( - sha256 = "6a4922f89487a96d7054ec6ca5065bfddd9f1d017c74d82f1d79cecf7feb8228", - strip_prefix = "Payload/Library/Developer/CommandLineTools/SDKs/MacOSX26.2.sdk", + sha256 = "1bde70c0b1c2ab89ff454acbebf6741390d7b7eb149ca2a3ca24cc9203a408b7", + strip_prefix = "Payload/Library/Developer/CommandLineTools/SDKs/MacOSX26.4.sdk", type = "pkg", urls = [ - "https://swcdn.apple.com/content/downloads/26/44/047-81934-A_28TPKM5SD1/ps6pk6dk4x02vgfa5qsctq6tgf23t5f0w2/CLTools_macOSNMOS_SDK.pkg", + "https://swcdn.apple.com/content/downloads/32/53/047-96692-A_OAHIHT53YB/ybtshxmrcju8m2qvw3w5elr4rajtg1x3y3/CLTools_macOSNMOS_SDK.pkg", ], ) osx.frameworks(names = [ From 4e27a87ec6e1ac95e5bc8a56e5687829e809270c Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 14:24:14 -0700 Subject: [PATCH 06/17] codex-tools: extract configured tool specs (#16129) ## Why This continues the `codex-tools` migration by moving another passive tool-spec layer out of `codex-core`. After `ToolSpec` moved into `codex-tools`, `codex-core` still owned `ConfiguredToolSpec` and `create_tools_json_for_responses_api()`. Both are data-model and serialization helpers rather than runtime orchestration, so keeping them in `core/src/tools/registry.rs` and `core/src/tools/spec.rs` left passive tool-definition code coupled to `codex-core` longer than necessary. ## What changed - moved `ConfiguredToolSpec` into `codex-rs/tools/src/tool_spec.rs` - moved `create_tools_json_for_responses_api()` into `codex-rs/tools/src/tool_spec.rs` - re-exported the new surface from `codex-rs/tools/src/lib.rs`, which remains exports-only - updated `core/src/client.rs`, `core/src/tools/registry.rs`, and `core/src/tools/router.rs` to consume the extracted types and serializer from `codex-tools` - moved the tool-list serialization test into `codex-rs/tools/src/tool_spec_tests.rs` - added focused unit coverage for `ConfiguredToolSpec::name()` - simplified `core/src/tools/spec_tests.rs` to use the extracted `ConfiguredToolSpec::name()` directly and removed the now-redundant local `tool_name()` helper - updated `codex-rs/tools/README.md` so the crate boundary reflects the newly extracted tool-spec wrapper and serialization helper ## Test plan - `cargo test -p codex-tools` - `CARGO_TARGET_DIR=/tmp/codex-core-configured-spec cargo test -p codex-core --lib tools::spec::` - `CARGO_TARGET_DIR=/tmp/codex-core-configured-spec cargo test -p codex-core --lib client::` - `just fix -p codex-tools -p codex-core` - `just argument-comment-lint` ## References - #15923 - #15928 - #15944 - #15953 - #16031 - #16047 --- codex-rs/core/src/client.rs | 2 +- codex-rs/core/src/tools/registry.rs | 16 +------ codex-rs/core/src/tools/router.rs | 8 ++-- codex-rs/core/src/tools/spec.rs | 16 ------- codex-rs/core/src/tools/spec_tests.rs | 69 +++++---------------------- codex-rs/tools/README.md | 2 + codex-rs/tools/src/lib.rs | 2 + codex-rs/tools/src/tool_spec.rs | 36 ++++++++++++++ codex-rs/tools/src/tool_spec_tests.rs | 59 +++++++++++++++++++++++ 9 files changed, 118 insertions(+), 92 deletions(-) diff --git a/codex-rs/core/src/client.rs b/codex-rs/core/src/client.rs index e38ff3a562..af5e3007b4 100644 --- a/codex-rs/core/src/client.rs +++ b/codex-rs/core/src/client.rs @@ -72,6 +72,7 @@ use codex_protocol::openai_models::ModelInfo; use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::W3cTraceContext; +use codex_tools::create_tools_json_for_responses_api; use eventsource_stream::Event; use eventsource_stream::EventStreamError; use futures::StreamExt; @@ -107,7 +108,6 @@ use crate::response_debug_context::extract_response_debug_context; use crate::response_debug_context::extract_response_debug_context_from_api_error; use crate::response_debug_context::telemetry_api_error_message; use crate::response_debug_context::telemetry_transport_error_message; -use crate::tools::spec::create_tools_json_for_responses_api; use crate::util::FeedbackRequestTags; use crate::util::emit_feedback_auth_recovery_tags; use crate::util::emit_feedback_request_tags_with_auth_env; diff --git a/codex-rs/core/src/tools/registry.rs b/codex-rs/core/src/tools/registry.rs index aa7f401099..0e77caac72 100644 --- a/codex-rs/core/src/tools/registry.rs +++ b/codex-rs/core/src/tools/registry.rs @@ -24,6 +24,7 @@ use codex_hooks::HookToolInput; use codex_hooks::HookToolInputLocalShell; use codex_hooks::HookToolKind; use codex_protocol::models::ResponseInputItem; +use codex_tools::ConfiguredToolSpec; use codex_utils_readiness::Readiness; use serde_json::Value; use tracing::warn; @@ -436,21 +437,6 @@ impl ToolRegistry { } } -#[derive(Debug, Clone)] -pub struct ConfiguredToolSpec { - pub spec: ToolSpec, - pub supports_parallel_tool_calls: bool, -} - -impl ConfiguredToolSpec { - pub fn new(spec: ToolSpec, supports_parallel_tool_calls: bool) -> Self { - Self { - spec, - supports_parallel_tool_calls, - } - } -} - pub struct ToolRegistryBuilder { handlers: HashMap>, specs: Vec, diff --git a/codex-rs/core/src/tools/router.rs b/codex-rs/core/src/tools/router.rs index 345f7ce06f..1145e3a8f2 100644 --- a/codex-rs/core/src/tools/router.rs +++ b/codex-rs/core/src/tools/router.rs @@ -9,7 +9,6 @@ use crate::tools::context::ToolInvocation; use crate::tools::context::ToolPayload; use crate::tools::discoverable::DiscoverableTool; use crate::tools::registry::AnyToolResult; -use crate::tools::registry::ConfiguredToolSpec; use crate::tools::registry::ToolRegistry; use crate::tools::spec::ToolsConfig; use crate::tools::spec::build_specs_with_discoverable_tools; @@ -18,6 +17,7 @@ use codex_protocol::models::LocalShellAction; use codex_protocol::models::ResponseItem; use codex_protocol::models::SearchToolCallParams; use codex_protocol::models::ShellToolCallParams; +use codex_tools::ConfiguredToolSpec; use rmcp::model::Tool; use std::collections::HashMap; use std::sync::Arc; @@ -66,7 +66,7 @@ impl ToolRouter { specs .iter() .filter_map(|configured_tool| { - if !codex_code_mode::is_code_mode_nested_tool(configured_tool.spec.name()) { + if !codex_code_mode::is_code_mode_nested_tool(configured_tool.name()) { Some(configured_tool.spec.clone()) } else { None @@ -101,7 +101,7 @@ impl ToolRouter { pub fn find_spec(&self, tool_name: &str) -> Option { self.specs .iter() - .find(|config| config.spec.name() == tool_name) + .find(|config| config.name() == tool_name) .map(|config| config.spec.clone()) } @@ -109,7 +109,7 @@ impl ToolRouter { self.specs .iter() .filter(|config| config.supports_parallel_tool_calls) - .any(|config| config.spec.name() == tool_name) + .any(|config| config.name() == tool_name) } #[instrument(level = "trace", skip_all, err)] diff --git a/codex-rs/core/src/tools/spec.rs b/codex-rs/core/src/tools/spec.rs index 2a0704262c..d5b4b29216 100644 --- a/codex-rs/core/src/tools/spec.rs +++ b/codex-rs/core/src/tools/spec.rs @@ -2351,22 +2351,6 @@ pub(crate) struct ApplyPatchToolArgs { pub(crate) input: String, } -/// Returns JSON values that are compatible with Function Calling in the -/// Responses API: -/// https://platform.openai.com/docs/guides/function-calling?api-mode=responses -pub fn create_tools_json_for_responses_api( - tools: &[ToolSpec], -) -> crate::error::Result> { - let mut tools_json = Vec::new(); - - for tool in tools { - let json = serde_json::to_value(tool)?; - tools_json.push(json); - } - - Ok(tools_json) -} - fn push_tool_spec( builder: &mut ToolRegistryBuilder, spec: ToolSpec, diff --git a/codex-rs/core/src/tools/spec_tests.rs b/codex-rs/core/src/tools/spec_tests.rs index 60339b7811..2a7644eec5 100644 --- a/codex-rs/core/src/tools/spec_tests.rs +++ b/codex-rs/core/src/tools/spec_tests.rs @@ -4,13 +4,13 @@ use crate::models_manager::model_info::with_config_overrides; use crate::shell::Shell; use crate::shell::ShellType; use crate::tools::ToolRouter; -use crate::tools::registry::ConfiguredToolSpec; use crate::tools::router::ToolRouterParams; use codex_app_server_protocol::AppInfo; use codex_protocol::openai_models::InputModality; use codex_protocol::openai_models::ModelInfo; use codex_protocol::openai_models::ModelsResponse; use codex_tools::AdditionalProperties; +use codex_tools::ConfiguredToolSpec; use codex_tools::FreeformTool; use codex_tools::ResponsesApiWebSearchFilters; use codex_tools::ResponsesApiWebSearchUserLocation; @@ -107,16 +107,12 @@ fn deferred_responses_api_tool_serializes_with_defer_loading() { ); } -fn tool_name(tool: &ToolSpec) -> &str { - tool.name() -} - // Avoid order-based assertions; compare via set containment instead. fn assert_contains_tool_names(tools: &[ConfiguredToolSpec], expected_subset: &[&str]) { use std::collections::HashSet; let mut names = HashSet::new(); let mut duplicates = Vec::new(); - for name in tools.iter().map(|t| tool_name(&t.spec)) { + for name in tools.iter().map(ConfiguredToolSpec::name) { if !names.insert(name) { duplicates.push(name); } @@ -136,7 +132,7 @@ fn assert_contains_tool_names(tools: &[ConfiguredToolSpec], expected_subset: &[& fn assert_lacks_tool_name(tools: &[ConfiguredToolSpec], expected_absent: &str) { let names = tools .iter() - .map(|tool| tool_name(&tool.spec)) + .map(ConfiguredToolSpec::name) .collect::>(); assert!( !names.contains(&expected_absent), @@ -157,7 +153,7 @@ fn shell_tool_name(config: &ToolsConfig) -> Option<&'static str> { fn find_tool<'a>(tools: &'a [ConfiguredToolSpec], expected_name: &str) -> &'a ConfiguredToolSpec { tools .iter() - .find(|tool| tool_name(&tool.spec) == expected_name) + .find(|tool| tool.name() == expected_name) .unwrap_or_else(|| panic!("expected tool {expected_name}")) } @@ -289,7 +285,7 @@ fn test_full_toolset_specs_for_gpt5_codex_unified_exec_web_search() { let mut actual: BTreeMap = BTreeMap::from([]); let mut duplicate_names = Vec::new(); for t in &tools { - let name = tool_name(&t.spec).to_string(); + let name = t.name().to_string(); if actual.insert(name.clone(), t.spec.clone()).is_some() { duplicate_names.push(name); } @@ -318,7 +314,7 @@ fn test_full_toolset_specs_for_gpt5_codex_unified_exec_web_search() { }, create_view_image_tool(config.can_request_original_image_detail), ] { - expected.insert(tool_name(&spec).to_string(), spec); + expected.insert(spec.name().to_string(), spec); } let collab_specs = if config.multi_agent_v2 { vec![ @@ -336,16 +332,16 @@ fn test_full_toolset_specs_for_gpt5_codex_unified_exec_web_search() { ] }; for spec in collab_specs { - expected.insert(tool_name(&spec).to_string(), spec); + expected.insert(spec.name().to_string(), spec); } if !config.multi_agent_v2 { let spec = create_resume_agent_tool(); - expected.insert(tool_name(&spec).to_string(), spec); + expected.insert(spec.name().to_string(), spec); } if config.exec_permission_approvals_enabled { let spec = create_request_permissions_tool(); - expected.insert(tool_name(&spec).to_string(), spec); + expected.insert(spec.name().to_string(), spec); } // Exact name set match — this is the only test allowed to fail when tools change. @@ -1679,11 +1675,7 @@ fn test_test_model_info_includes_sync_tool() { ) .build(); - assert!( - tools - .iter() - .any(|tool| tool_name(&tool.spec) == "test_sync_tool") - ); + assert!(tools.iter().any(|tool| tool.name() == "test_sync_tool")); } #[test] @@ -1817,7 +1809,7 @@ fn test_build_specs_mcp_tools_sorted_by_name() { // Only assert that the MCP tools themselves are sorted by fully-qualified name. let mcp_names: Vec<_> = tools .iter() - .map(|t| tool_name(&t.spec).to_string()) + .map(|t| t.name().to_string()) .filter(|n| n.starts_with("test_server/")) .collect(); let expected = vec![ @@ -2064,7 +2056,7 @@ fn tool_suggest_is_not_registered_without_feature_flag() { assert!( !tools .iter() - .any(|tool| tool_name(&tool.spec) == TOOL_SUGGEST_TOOL_NAME) + .any(|tool| tool.name() == TOOL_SUGGEST_TOOL_NAME) ); } @@ -2155,7 +2147,7 @@ fn tool_suggest_requires_apps_and_plugins_features() { assert!( !tools .iter() - .any(|tool| tool_name(&tool.spec) == TOOL_SUGGEST_TOOL_NAME), + .any(|tool| tool.name() == TOOL_SUGGEST_TOOL_NAME), "tool_suggest should be absent when {disabled_feature:?} is disabled" ); } @@ -3106,38 +3098,3 @@ fn code_mode_exec_description_omits_nested_tool_details_when_not_code_mode_only( assert!(!description.contains("### `update_plan` (`update_plan`)")); assert!(!description.contains("### `view_image` (`view_image`)")); } - -#[test] -fn chat_tools_include_top_level_name() { - let properties = - BTreeMap::from([("foo".to_string(), JsonSchema::String { description: None })]); - let tools = vec![ToolSpec::Function(ResponsesApiTool { - name: "demo".to_string(), - description: "A demo tool".to_string(), - strict: false, - defer_loading: None, - parameters: JsonSchema::Object { - properties, - required: None, - additional_properties: None, - }, - output_schema: None, - })]; - - let responses_json = create_tools_json_for_responses_api(&tools).unwrap(); - assert_eq!( - responses_json, - vec![json!({ - "type": "function", - "name": "demo", - "description": "A demo tool", - "strict": false, - "parameters": { - "type": "object", - "properties": { - "foo": { "type": "string" } - }, - }, - })] - ); -} diff --git a/codex-rs/tools/README.md b/codex-rs/tools/README.md index d8dabdcd72..66d342cdb4 100644 --- a/codex-rs/tools/README.md +++ b/codex-rs/tools/README.md @@ -12,6 +12,7 @@ schema and Responses API tool primitives that no longer need to live in - `AdditionalProperties` - `ToolDefinition` - `ToolSpec` +- `ConfiguredToolSpec` - `ResponsesApiTool` - `FreeformTool` - `FreeformToolFormat` @@ -23,6 +24,7 @@ schema and Responses API tool primitives that no longer need to live in - `parse_tool_input_schema()` - `parse_dynamic_tool()` - `parse_mcp_tool()` +- `create_tools_json_for_responses_api()` - `mcp_call_tool_result_output_schema()` - `tool_definition_to_responses_api_tool()` - `dynamic_tool_to_responses_api_tool()` diff --git a/codex-rs/tools/src/lib.rs b/codex-rs/tools/src/lib.rs index 05b527ba94..527424c276 100644 --- a/codex-rs/tools/src/lib.rs +++ b/codex-rs/tools/src/lib.rs @@ -25,6 +25,8 @@ pub use responses_api::mcp_tool_to_deferred_responses_api_tool; pub use responses_api::mcp_tool_to_responses_api_tool; pub use responses_api::tool_definition_to_responses_api_tool; pub use tool_definition::ToolDefinition; +pub use tool_spec::ConfiguredToolSpec; pub use tool_spec::ResponsesApiWebSearchFilters; pub use tool_spec::ResponsesApiWebSearchUserLocation; pub use tool_spec::ToolSpec; +pub use tool_spec::create_tools_json_for_responses_api; diff --git a/codex-rs/tools/src/tool_spec.rs b/codex-rs/tools/src/tool_spec.rs index fc63223e1b..f537388853 100644 --- a/codex-rs/tools/src/tool_spec.rs +++ b/codex-rs/tools/src/tool_spec.rs @@ -6,6 +6,7 @@ use codex_protocol::config_types::WebSearchFilters as ConfigWebSearchFilters; use codex_protocol::config_types::WebSearchUserLocation as ConfigWebSearchUserLocation; use codex_protocol::config_types::WebSearchUserLocationType; use serde::Serialize; +use serde_json::Value; /// When serialized as JSON, this produces a valid "Tool" in the OpenAI /// Responses API. @@ -60,6 +61,41 @@ impl ToolSpec { } } +#[derive(Debug, Clone, PartialEq)] +pub struct ConfiguredToolSpec { + pub spec: ToolSpec, + pub supports_parallel_tool_calls: bool, +} + +impl ConfiguredToolSpec { + pub fn new(spec: ToolSpec, supports_parallel_tool_calls: bool) -> Self { + Self { + spec, + supports_parallel_tool_calls, + } + } + + pub fn name(&self) -> &str { + self.spec.name() + } +} + +/// Returns JSON values that are compatible with Function Calling in the +/// Responses API: +/// https://platform.openai.com/docs/guides/function-calling?api-mode=responses +pub fn create_tools_json_for_responses_api( + tools: &[ToolSpec], +) -> Result, serde_json::Error> { + let mut tools_json = Vec::new(); + + for tool in tools { + let json = serde_json::to_value(tool)?; + tools_json.push(json); + } + + Ok(tools_json) +} + #[derive(Debug, Clone, Serialize, PartialEq)] pub struct ResponsesApiWebSearchFilters { #[serde(skip_serializing_if = "Option::is_none")] diff --git a/codex-rs/tools/src/tool_spec_tests.rs b/codex-rs/tools/src/tool_spec_tests.rs index 33d31c1401..c84ea94a36 100644 --- a/codex-rs/tools/src/tool_spec_tests.rs +++ b/codex-rs/tools/src/tool_spec_tests.rs @@ -1,3 +1,4 @@ +use super::ConfiguredToolSpec; use super::ResponsesApiWebSearchFilters; use super::ResponsesApiWebSearchUserLocation; use super::ToolSpec; @@ -6,6 +7,7 @@ use crate::FreeformTool; use crate::FreeformToolFormat; use crate::JsonSchema; use crate::ResponsesApiTool; +use crate::create_tools_json_for_responses_api; use codex_protocol::config_types::WebSearchContextSize; use codex_protocol::config_types::WebSearchFilters as ConfigWebSearchFilters; use codex_protocol::config_types::WebSearchUserLocation as ConfigWebSearchUserLocation; @@ -79,6 +81,29 @@ fn tool_spec_name_covers_all_variants() { ); } +#[test] +fn configured_tool_spec_name_delegates_to_tool_spec() { + assert_eq!( + ConfiguredToolSpec::new( + ToolSpec::Function(ResponsesApiTool { + name: "lookup_order".to_string(), + description: "Look up an order".to_string(), + strict: false, + defer_loading: None, + parameters: JsonSchema::Object { + properties: BTreeMap::new(), + required: None, + additional_properties: None, + }, + output_schema: None, + }), + /*supports_parallel_tool_calls*/ true, + ) + .name(), + "lookup_order" + ); +} + #[test] fn web_search_config_converts_to_responses_api_types() { assert_eq!( @@ -107,6 +132,40 @@ fn web_search_config_converts_to_responses_api_types() { ); } +#[test] +fn create_tools_json_for_responses_api_includes_top_level_name() { + assert_eq!( + create_tools_json_for_responses_api(&[ToolSpec::Function(ResponsesApiTool { + name: "demo".to_string(), + description: "A demo tool".to_string(), + strict: false, + defer_loading: None, + parameters: JsonSchema::Object { + properties: BTreeMap::from([( + "foo".to_string(), + JsonSchema::String { description: None }, + )]), + required: None, + additional_properties: None, + }, + output_schema: None, + })]) + .expect("serialize tools"), + vec![json!({ + "type": "function", + "name": "demo", + "description": "A demo tool", + "strict": false, + "parameters": { + "type": "object", + "properties": { + "foo": { "type": "string" } + }, + }, + })] + ); +} + #[test] fn web_search_tool_spec_serializes_expected_wire_shape() { assert_eq!( From 313fb959896b257ab1df2aa32adb8efc789806aa Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 14:50:19 -0700 Subject: [PATCH 07/17] ci: keep rust-ci-full Windows argument-comment-lint on packaged wrapper (#16130) ## Why PR #16106 switched `rust-ci-full` over to the native Bazel-backed `argument-comment-lint` path on all three platforms. That works on Linux and macOS, but the Windows leg in `rust-ci-full` now fails before linting starts: Bazel dies while building `rules_rust`'s `process_wrapper` tool, so `main` reports an `argument-comment-lint` failure even though no Rust lint finding was produced. Until native Windows Bazel linting is repaired, `rust-ci-full` should keep the same Windows split that `rust-ci.yml` already uses. ## What changed - restored the Windows-only nightly `argument-comment-lint` toolchain setup in `rust-ci-full` - limited the Bazel-backed lint step in `rust-ci-full` to non-Windows runners - routed the Windows runner back through `tools/argument-comment-lint/run-prebuilt-linter.py` - left the Linux and macOS `rust-ci-full` behavior unchanged ## Test plan - loaded `.github/workflows/rust-ci-full.yml` and `.github/workflows/rust-ci.yml` with `python3` + `yaml.safe_load(...)` - inspected failing Actions run `23692864849`, especially job `69023229311`, to confirm the Windows failure occurs in Bazel `process_wrapper` setup before lint output is emitted ## References - #16106 --- .github/workflows/rust-ci-full.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/rust-ci-full.yml b/.github/workflows/rust-ci-full.yml index 9480c05379..7bc4d9c040 100644 --- a/.github/workflows/rust-ci-full.yml +++ b/.github/workflows/rust-ci-full.yml @@ -99,7 +99,19 @@ jobs: run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev + - name: Install nightly argument-comment-lint toolchain + if: ${{ runner.os == 'Windows' }} + shell: bash + run: | + rustup toolchain install nightly-2025-09-18 \ + --profile minimal \ + --component llvm-tools-preview \ + --component rustc-dev \ + --component rust-src \ + --no-self-update + rustup default nightly-2025-09-18 - name: Run argument comment lint on codex-rs via Bazel + if: ${{ runner.os != 'Windows' }} shell: bash run: | ./.github/scripts/run-bazel-ci.sh \ @@ -110,6 +122,10 @@ jobs: --build_metadata=COMMIT_SHA=${GITHUB_SHA} \ -- \ //codex-rs/... + - name: Run argument comment lint on codex-rs via packaged wrapper + if: ${{ runner.os == 'Windows' }} + shell: bash + run: python3 ./tools/argument-comment-lint/run-prebuilt-linter.py # --- CI to validate on different os/targets -------------------------------- lint_build: From c25c0d6e9efb143df91fe91e56c1bb05f09359bd Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 15:00:39 -0700 Subject: [PATCH 08/17] core: fix stale curated plugin cache refresh races (#16126) ## Why The `plugin/list` force-sync path can race app-server startup's curated plugin cache refresh. Startup was capturing the configured curated plugin IDs from the initial config snapshot. If `plugin/list` with `forceRemoteSync` removed curated plugin entries from `config.toml` while that background refresh was still in flight, the startup task could recreate cache directories for plugins that had just been uninstalled. That leaves the `plugin/list` response logically correct but the on-disk cache stale, which matches the flaky Ubuntu arm failure seen in `codex-app-server::all suite::v2::plugin_list::plugin_list_force_remote_sync_reconciles_curated_plugin_state` while validating [#16047](https://github.com/openai/codex/pull/16047). ## What - change `codex-rs/core/src/plugins/manager.rs` so startup curated-repo refresh rereads the current user `config.toml` before deciding which curated plugin cache entries to refresh - factor the configured-plugin parsing so the same logic can be reused from either the config layer stack or the persisted user config value - add a regression test that verifies curated plugin IDs are read from the latest user config state before cache refresh runs ## Testing - `cargo test -p codex-core configured_curated_plugin_ids_from_codex_home_reads_latest_user_config -- --nocapture` - `cargo test -p codex-app-server suite::v2::plugin_list::plugin_list_force_remote_sync_reconciles_curated_plugin_state -- --nocapture` - `just argument-comment-lint` --- codex-rs/core/src/plugins/manager.rs | 90 ++++++++++++++++------ codex-rs/core/src/plugins/manager_tests.rs | 37 +++++++++ 2 files changed, 103 insertions(+), 24 deletions(-) diff --git a/codex-rs/core/src/plugins/manager.rs b/codex-rs/core/src/plugins/manager.rs index 140882a187..59bc99b238 100644 --- a/codex-rs/core/src/plugins/manager.rs +++ b/codex-rs/core/src/plugins/manager.rs @@ -29,6 +29,7 @@ use super::sync_openai_plugins_repo; use crate::AuthManager; use crate::SkillMetadata; use crate::auth::CodexAuth; +use crate::config::CONFIG_TOML_FILE; use crate::config::Config; use crate::config::ConfigService; use crate::config::ConfigServiceError; @@ -1008,28 +1009,7 @@ impl PluginsManager { auth_manager: Arc, ) { if config.features.enabled(Feature::Plugins) { - let mut configured_curated_plugin_ids = - configured_plugins_from_stack(&config.config_layer_stack) - .into_keys() - .filter_map(|plugin_key| match PluginId::parse(&plugin_key) { - Ok(plugin_id) - if plugin_id.marketplace_name == OPENAI_CURATED_MARKETPLACE_NAME => - { - Some(plugin_id) - } - Ok(_) => None, - Err(err) => { - warn!( - plugin_key, - error = %err, - "ignoring invalid configured plugin key during curated sync setup" - ); - None - } - }) - .collect::>(); - configured_curated_plugin_ids.sort_unstable_by_key(PluginId::as_key); - self.start_curated_repo_sync(configured_curated_plugin_ids); + self.start_curated_repo_sync(); start_startup_remote_plugin_sync_once( Arc::clone(self), self.codex_home.clone(), @@ -1054,7 +1034,7 @@ impl PluginsManager { } } - fn start_curated_repo_sync(self: &Arc, configured_curated_plugin_ids: Vec) { + fn start_curated_repo_sync(self: &Arc) { if CURATED_REPO_SYNC_STARTED.swap(true, Ordering::SeqCst) { return; } @@ -1065,6 +1045,8 @@ impl PluginsManager { .spawn( move || match sync_openai_plugins_repo(codex_home.as_path()) { Ok(curated_plugin_version) => { + let configured_curated_plugin_ids = + configured_curated_plugin_ids_from_codex_home(codex_home.as_path()); match refresh_curated_plugin_cache( codex_home.as_path(), &curated_plugin_version, @@ -1333,7 +1315,13 @@ fn configured_plugins_from_stack( let Some(user_layer) = config_layer_stack.get_user_layer() else { return HashMap::new(); }; - let Some(plugins_value) = user_layer.config.get("plugins") else { + configured_plugins_from_user_config_value(&user_layer.config) +} + +fn configured_plugins_from_user_config_value( + user_config: &toml::Value, +) -> HashMap { + let Some(plugins_value) = user_config.get("plugins") else { return HashMap::new(); }; match plugins_value.clone().try_into() { @@ -1345,6 +1333,60 @@ fn configured_plugins_from_stack( } } +fn configured_curated_plugin_ids( + configured_plugins: HashMap, +) -> Vec { + let mut configured_curated_plugin_ids = configured_plugins + .into_keys() + .filter_map(|plugin_key| match PluginId::parse(&plugin_key) { + Ok(plugin_id) if plugin_id.marketplace_name == OPENAI_CURATED_MARKETPLACE_NAME => { + Some(plugin_id) + } + Ok(_) => None, + Err(err) => { + warn!( + plugin_key, + error = %err, + "ignoring invalid configured plugin key during curated sync setup" + ); + None + } + }) + .collect::>(); + configured_curated_plugin_ids.sort_unstable_by_key(PluginId::as_key); + configured_curated_plugin_ids +} + +fn configured_curated_plugin_ids_from_codex_home(codex_home: &Path) -> Vec { + let config_path = codex_home.join(CONFIG_TOML_FILE); + let user_config = match fs::read_to_string(&config_path) { + Ok(user_config) => user_config, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Vec::new(), + Err(err) => { + warn!( + path = %config_path.display(), + error = %err, + "failed to read user config while refreshing curated plugin cache" + ); + return Vec::new(); + } + }; + + let user_config = match toml::from_str::(&user_config) { + Ok(user_config) => user_config, + Err(err) => { + warn!( + path = %config_path.display(), + error = %err, + "failed to parse user config while refreshing curated plugin cache" + ); + return Vec::new(); + } + }; + + configured_curated_plugin_ids(configured_plugins_from_user_config_value(&user_config)) +} + fn load_plugin( config_name: String, plugin: &PluginConfig, diff --git a/codex-rs/core/src/plugins/manager_tests.rs b/codex-rs/core/src/plugins/manager_tests.rs index ab0ad7084f..08d0e7cc77 100644 --- a/codex-rs/core/src/plugins/manager_tests.rs +++ b/codex-rs/core/src/plugins/manager_tests.rs @@ -2207,6 +2207,43 @@ fn refresh_curated_plugin_cache_reinstalls_missing_configured_plugin_with_curren ); } +#[test] +fn configured_curated_plugin_ids_from_codex_home_reads_latest_user_config() { + let tmp = tempfile::tempdir().unwrap(); + write_file( + &tmp.path().join(CONFIG_TOML_FILE), + r#"[features] +plugins = true + +[plugins."slack@openai-curated"] +enabled = true + +[plugins."sample@debug"] +enabled = true +"#, + ); + + assert_eq!( + configured_curated_plugin_ids_from_codex_home(tmp.path()) + .into_iter() + .map(|plugin_id| plugin_id.as_key()) + .collect::>(), + vec!["slack@openai-curated".to_string()] + ); + + write_file( + &tmp.path().join(CONFIG_TOML_FILE), + r#"[features] +plugins = true +"#, + ); + + assert_eq!( + configured_curated_plugin_ids_from_codex_home(tmp.path()), + Vec::::new() + ); +} + #[test] fn refresh_curated_plugin_cache_returns_false_when_configured_plugins_are_current() { let tmp = tempfile::tempdir().unwrap(); From 2238c16a914c9b7337b2bd87bc65972f8daf06d1 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 15:32:35 -0700 Subject: [PATCH 09/17] codex-tools: extract code mode tool spec adapters (#16132) ## Why The longer-term `codex-tools` migration is to move pure tool-definition and tool-spec plumbing out of `codex-core` while leaving session- and runtime-coupled orchestration behind. The remaining code-mode adapter layer in `core/src/tools/code_mode_description.rs` was a good next extraction seam because it only transformed `ToolSpec` values for code mode and already delegated the low-level description rendering to `codex-code-mode`. ## What Changed - added `codex-rs/tools/src/code_mode.rs` with `augment_tool_spec_for_code_mode()` and `tool_spec_to_code_mode_tool_definition()` - added focused unit coverage in `codex-rs/tools/src/code_mode_tests.rs` - rewired `core/src/tools/spec.rs` and `core/src/tools/code_mode/mod.rs` to use the extracted adapters from `codex-tools` - removed the old `core/src/tools/code_mode_description.rs` shim and its test file from `codex-core` - added the `codex-code-mode` dependency to `codex-tools`, updated `Cargo.lock`, and refreshed the `codex-tools` README to reflect the expanded boundary ## Test Plan - `cargo test -p codex-tools` - `CARGO_TARGET_DIR=/tmp/codex-core-code-mode-adapters cargo test -p codex-core --lib tools::spec::` - `CARGO_TARGET_DIR=/tmp/codex-core-code-mode-adapters cargo test -p codex-core --lib tools::code_mode::` - `just bazel-lock-update` - `just bazel-lock-check` - `just argument-comment-lint` ## References - #15923 - #15928 - #15944 - #15953 - #16031 - #16047 - #16129 --- codex-rs/Cargo.lock | 1 + codex-rs/core/src/tools/code_mode/mod.rs | 33 +---- .../core/src/tools/code_mode_description.rs | 49 ------- .../src/tools/code_mode_description_tests.rs | 104 --------------- codex-rs/core/src/tools/mod.rs | 1 - codex-rs/core/src/tools/spec.rs | 21 ++- codex-rs/tools/Cargo.toml | 1 + codex-rs/tools/README.md | 3 + codex-rs/tools/src/code_mode.rs | 60 +++++++++ codex-rs/tools/src/code_mode_tests.rs | 123 ++++++++++++++++++ codex-rs/tools/src/lib.rs | 3 + 11 files changed, 202 insertions(+), 197 deletions(-) delete mode 100644 codex-rs/core/src/tools/code_mode_description.rs delete mode 100644 codex-rs/core/src/tools/code_mode_description_tests.rs create mode 100644 codex-rs/tools/src/code_mode.rs create mode 100644 codex-rs/tools/src/code_mode_tests.rs diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 3327b8c874..92e0c25923 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -2613,6 +2613,7 @@ dependencies = [ name = "codex-tools" version = "0.0.0" dependencies = [ + "codex-code-mode", "codex-protocol", "pretty_assertions", "rmcp", diff --git a/codex-rs/core/src/tools/code_mode/mod.rs b/codex-rs/core/src/tools/code_mode/mod.rs index a1f21a6227..c8f16ca602 100644 --- a/codex-rs/core/src/tools/code_mode/mod.rs +++ b/codex-rs/core/src/tools/code_mode/mod.rs @@ -19,7 +19,6 @@ use crate::codex::Session; use crate::codex::TurnContext; use crate::function_tool::FunctionCallError; use crate::tools::ToolRouter; -use crate::tools::code_mode_description::augment_tool_spec_for_code_mode; use crate::tools::context::FunctionToolOutput; use crate::tools::context::SharedTurnDiffTracker; use crate::tools::context::ToolPayload; @@ -29,6 +28,7 @@ use crate::tools::router::ToolCallSource; use crate::tools::router::ToolRouterParams; use crate::unified_exec::resolve_max_tokens; use codex_features::Feature; +use codex_tools::tool_spec_to_code_mode_tool_definition; use codex_utils_output_truncation::TruncationPolicy; use codex_utils_output_truncation::formatted_truncate_text_content_items_with_policy; use codex_utils_output_truncation::truncate_function_output_items_with_policy; @@ -247,42 +247,13 @@ pub(super) async fn build_enabled_tools( let mut out = router .specs() .into_iter() - .map(|spec| augment_tool_spec_for_code_mode(spec, /*code_mode_enabled*/ true)) - .filter_map(enabled_tool_from_spec) + .filter_map(|spec| tool_spec_to_code_mode_tool_definition(&spec)) .collect::>(); out.sort_by(|left, right| left.name.cmp(&right.name)); out.dedup_by(|left, right| left.name == right.name); out } -fn enabled_tool_from_spec(spec: ToolSpec) -> Option { - let tool_name = spec.name().to_string(); - if !codex_code_mode::is_code_mode_nested_tool(&tool_name) { - return None; - } - - match spec { - ToolSpec::Function(tool) => Some(codex_code_mode::ToolDefinition { - name: tool_name, - description: tool.description, - kind: codex_code_mode::CodeModeToolKind::Function, - input_schema: serde_json::to_value(&tool.parameters).ok(), - output_schema: tool.output_schema, - }), - ToolSpec::Freeform(tool) => Some(codex_code_mode::ToolDefinition { - name: tool_name, - description: tool.description, - kind: codex_code_mode::CodeModeToolKind::Freeform, - input_schema: None, - output_schema: None, - }), - ToolSpec::LocalShell {} - | ToolSpec::ImageGeneration { .. } - | ToolSpec::ToolSearch { .. } - | ToolSpec::WebSearch { .. } => None, - } -} - async fn build_nested_router(exec: &ExecContext) -> ToolRouter { let nested_tools_config = exec.turn.tools_config.for_code_mode_nested_tools(); let mcp_tools = exec diff --git a/codex-rs/core/src/tools/code_mode_description.rs b/codex-rs/core/src/tools/code_mode_description.rs deleted file mode 100644 index fb4fc1f519..0000000000 --- a/codex-rs/core/src/tools/code_mode_description.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::client_common::tools::ToolSpec; - -#[allow(unused_imports)] -#[cfg(test)] -pub(crate) use codex_code_mode::append_code_mode_sample; -#[allow(unused_imports)] -#[cfg(test)] -pub(crate) use codex_code_mode::render_json_schema_to_typescript; - -pub(crate) fn augment_tool_spec_for_code_mode(spec: ToolSpec, code_mode_enabled: bool) -> ToolSpec { - if !code_mode_enabled { - return spec; - } - - match spec { - ToolSpec::Function(mut tool) => { - let input_type = serde_json::to_value(&tool.parameters) - .ok() - .map(|schema| codex_code_mode::render_json_schema_to_typescript(&schema)) - .unwrap_or_else(|| "unknown".to_string()); - let output_type = tool - .output_schema - .as_ref() - .map(codex_code_mode::render_json_schema_to_typescript) - .unwrap_or_else(|| "unknown".to_string()); - tool.description = codex_code_mode::append_code_mode_sample( - &tool.description, - &tool.name, - "args", - input_type, - output_type, - ); - ToolSpec::Function(tool) - } - ToolSpec::Freeform(mut tool) => { - if tool.name != codex_code_mode::PUBLIC_TOOL_NAME { - tool.description = codex_code_mode::append_code_mode_sample( - &tool.description, - &tool.name, - "input", - "string".to_string(), - "unknown".to_string(), - ); - } - ToolSpec::Freeform(tool) - } - other => other, - } -} diff --git a/codex-rs/core/src/tools/code_mode_description_tests.rs b/codex-rs/core/src/tools/code_mode_description_tests.rs deleted file mode 100644 index 034a1e3f32..0000000000 --- a/codex-rs/core/src/tools/code_mode_description_tests.rs +++ /dev/null @@ -1,104 +0,0 @@ -use super::append_code_mode_sample; -use super::render_json_schema_to_typescript; -use pretty_assertions::assert_eq; -use serde_json::json; - -#[test] -fn render_json_schema_to_typescript_renders_object_properties() { - let schema = json!({ - "type": "object", - "properties": { - "path": {"type": "string"}, - "recursive": {"type": "boolean"} - }, - "required": ["path"], - "additionalProperties": false - }); - - assert_eq!( - render_json_schema_to_typescript(&schema), - "{ path: string; recursive?: boolean; }" - ); -} - -#[test] -fn render_json_schema_to_typescript_renders_anyof_unions() { - let schema = json!({ - "anyOf": [ - {"const": "pending"}, - {"const": "done"}, - {"type": "number"} - ] - }); - - assert_eq!( - render_json_schema_to_typescript(&schema), - "\"pending\" | \"done\" | number" - ); -} - -#[test] -fn render_json_schema_to_typescript_renders_additional_properties() { - let schema = json!({ - "type": "object", - "properties": { - "tags": { - "type": "array", - "items": {"type": "string"} - } - }, - "additionalProperties": {"type": "integer"} - }); - - assert_eq!( - render_json_schema_to_typescript(&schema), - "{ tags?: Array; [key: string]: number; }" - ); -} - -#[test] -fn render_json_schema_to_typescript_sorts_object_properties() { - let schema = json!({ - "type": "object", - "properties": { - "structuredContent": {"type": "string"}, - "_meta": {"type": "string"}, - "isError": {"type": "boolean"}, - "content": {"type": "array", "items": {"type": "string"}} - }, - "required": ["content"] - }); - - assert_eq!( - render_json_schema_to_typescript(&schema), - "{ _meta?: string; content: Array; isError?: boolean; structuredContent?: string; }" - ); -} - -#[test] -fn append_code_mode_sample_uses_global_tools_for_valid_identifiers() { - assert_eq!( - append_code_mode_sample( - "desc", - "mcp__ologs__get_profile", - "args", - "{ foo: string }".to_string(), - "unknown".to_string(), - ), - "desc\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__ologs__get_profile(args: { foo: string }): Promise; };\n```" - ); -} - -#[test] -fn append_code_mode_sample_normalizes_invalid_identifiers() { - assert_eq!( - append_code_mode_sample( - "desc", - "mcp__rmcp__echo-tool", - "args", - "{ foo: string }".to_string(), - "unknown".to_string(), - ), - "desc\n\nexec tool declaration:\n```ts\ndeclare const tools: { mcp__rmcp__echo_tool(args: { foo: string }): Promise; };\n```" - ); -} diff --git a/codex-rs/core/src/tools/mod.rs b/codex-rs/core/src/tools/mod.rs index 87a01c8e3b..57859bba42 100644 --- a/codex-rs/core/src/tools/mod.rs +++ b/codex-rs/core/src/tools/mod.rs @@ -1,5 +1,4 @@ pub mod code_mode; -pub(crate) mod code_mode_description; pub mod context; pub(crate) mod discoverable; pub mod events; diff --git a/codex-rs/core/src/tools/spec.rs b/codex-rs/core/src/tools/spec.rs index d5b4b29216..e478c55e48 100644 --- a/codex-rs/core/src/tools/spec.rs +++ b/codex-rs/core/src/tools/spec.rs @@ -8,7 +8,6 @@ use crate::shell::Shell; use crate::shell::ShellType; use crate::tools::code_mode::PUBLIC_TOOL_NAME; use crate::tools::code_mode::WAIT_TOOL_NAME; -use crate::tools::code_mode_description::augment_tool_spec_for_code_mode; use crate::tools::discoverable::DiscoverablePluginInfo; use crate::tools::discoverable::DiscoverableTool; use crate::tools::discoverable::DiscoverableToolAction; @@ -46,8 +45,10 @@ use codex_protocol::protocol::SubAgentSource; use codex_tools::FreeformTool; use codex_tools::FreeformToolFormat; use codex_tools::ResponsesApiTool; +use codex_tools::augment_tool_spec_for_code_mode; use codex_tools::dynamic_tool_to_responses_api_tool; use codex_tools::mcp_tool_to_responses_api_tool; +use codex_tools::tool_spec_to_code_mode_tool_definition; use codex_utils_absolute_path::AbsolutePathBuf; use codex_utils_template::Template; use serde::Deserialize; @@ -2357,7 +2358,11 @@ fn push_tool_spec( supports_parallel_tool_calls: bool, code_mode_enabled: bool, ) { - let spec = augment_tool_spec_for_code_mode(spec, code_mode_enabled); + let spec = if code_mode_enabled { + augment_tool_spec_for_code_mode(spec) + } else { + spec + }; if supports_parallel_tool_calls { builder.push_spec_with_parallel_support(spec, /*supports_parallel_tool_calls*/ true); } else { @@ -2455,16 +2460,8 @@ pub(crate) fn build_specs_with_discoverable_tools( .build(); let mut enabled_tools = nested_specs .into_iter() - .filter_map(|spec| { - let (name, description) = match augment_tool_spec_for_code_mode( - spec.spec, /*code_mode_enabled*/ true, - ) { - ToolSpec::Function(tool) => (tool.name, tool.description), - ToolSpec::Freeform(tool) => (tool.name, tool.description), - _ => return None, - }; - codex_code_mode::is_code_mode_nested_tool(&name).then_some((name, description)) - }) + .filter_map(|spec| tool_spec_to_code_mode_tool_definition(&spec.spec)) + .map(|tool| (tool.name, tool.description)) .collect::>(); enabled_tools.sort_by(|left, right| left.0.cmp(&right.0)); enabled_tools.dedup_by(|left, right| left.0 == right.0); diff --git a/codex-rs/tools/Cargo.toml b/codex-rs/tools/Cargo.toml index 1dc9b1c2fa..9e2d23fb58 100644 --- a/codex-rs/tools/Cargo.toml +++ b/codex-rs/tools/Cargo.toml @@ -8,6 +8,7 @@ version.workspace = true workspace = true [dependencies] +codex-code-mode = { workspace = true } codex-protocol = { workspace = true } rmcp = { workspace = true, default-features = false, features = [ "base64", diff --git a/codex-rs/tools/README.md b/codex-rs/tools/README.md index 66d342cdb4..29eeea2660 100644 --- a/codex-rs/tools/README.md +++ b/codex-rs/tools/README.md @@ -21,6 +21,7 @@ schema and Responses API tool primitives that no longer need to live in - `ResponsesApiWebSearchUserLocation` - `ResponsesApiNamespace` - `ResponsesApiNamespaceTool` +- code-mode `ToolSpec` adapters - `parse_tool_input_schema()` - `parse_dynamic_tool()` - `parse_mcp_tool()` @@ -30,6 +31,8 @@ schema and Responses API tool primitives that no longer need to live in - `dynamic_tool_to_responses_api_tool()` - `mcp_tool_to_responses_api_tool()` - `mcp_tool_to_deferred_responses_api_tool()` +- `augment_tool_spec_for_code_mode()` +- `tool_spec_to_code_mode_tool_definition()` That extraction is the first step in a longer migration. The goal is not to move all of `core/src/tools` into this crate in one shot. Instead, the plan is diff --git a/codex-rs/tools/src/code_mode.rs b/codex-rs/tools/src/code_mode.rs new file mode 100644 index 0000000000..ba6f68ae2d --- /dev/null +++ b/codex-rs/tools/src/code_mode.rs @@ -0,0 +1,60 @@ +use crate::ToolSpec; +use codex_code_mode::CodeModeToolKind; +use codex_code_mode::ToolDefinition as CodeModeToolDefinition; + +/// Augment tool descriptions with code-mode-specific exec samples. +pub fn augment_tool_spec_for_code_mode(spec: ToolSpec) -> ToolSpec { + let Some(description) = code_mode_tool_definition_for_spec(&spec) + .map(codex_code_mode::augment_tool_definition) + .map(|definition| definition.description) + else { + return spec; + }; + + match spec { + ToolSpec::Function(mut tool) => { + tool.description = description; + ToolSpec::Function(tool) + } + ToolSpec::Freeform(mut tool) => { + tool.description = description; + ToolSpec::Freeform(tool) + } + other => other, + } +} + +/// Convert a supported nested tool spec into the code-mode runtime shape, +/// including the code-mode-specific description sample. +pub fn tool_spec_to_code_mode_tool_definition(spec: &ToolSpec) -> Option { + let definition = code_mode_tool_definition_for_spec(spec)?; + codex_code_mode::is_code_mode_nested_tool(&definition.name) + .then(|| codex_code_mode::augment_tool_definition(definition)) +} + +fn code_mode_tool_definition_for_spec(spec: &ToolSpec) -> Option { + match spec { + ToolSpec::Function(tool) => Some(CodeModeToolDefinition { + name: tool.name.clone(), + description: tool.description.clone(), + kind: CodeModeToolKind::Function, + input_schema: serde_json::to_value(&tool.parameters).ok(), + output_schema: tool.output_schema.clone(), + }), + ToolSpec::Freeform(tool) => Some(CodeModeToolDefinition { + name: tool.name.clone(), + description: tool.description.clone(), + kind: CodeModeToolKind::Freeform, + input_schema: None, + output_schema: None, + }), + ToolSpec::LocalShell {} + | ToolSpec::ImageGeneration { .. } + | ToolSpec::ToolSearch { .. } + | ToolSpec::WebSearch { .. } => None, + } +} + +#[cfg(test)] +#[path = "code_mode_tests.rs"] +mod tests; diff --git a/codex-rs/tools/src/code_mode_tests.rs b/codex-rs/tools/src/code_mode_tests.rs new file mode 100644 index 0000000000..07e0a33784 --- /dev/null +++ b/codex-rs/tools/src/code_mode_tests.rs @@ -0,0 +1,123 @@ +use super::augment_tool_spec_for_code_mode; +use super::tool_spec_to_code_mode_tool_definition; +use crate::AdditionalProperties; +use crate::FreeformTool; +use crate::FreeformToolFormat; +use crate::JsonSchema; +use crate::ResponsesApiTool; +use crate::ToolSpec; +use pretty_assertions::assert_eq; +use serde_json::json; +use std::collections::BTreeMap; + +#[test] +fn augment_tool_spec_for_code_mode_augments_function_tools() { + assert_eq!( + augment_tool_spec_for_code_mode(ToolSpec::Function(ResponsesApiTool { + name: "lookup_order".to_string(), + description: "Look up an order".to_string(), + strict: false, + defer_loading: Some(true), + parameters: JsonSchema::Object { + properties: BTreeMap::from([( + "order_id".to_string(), + JsonSchema::String { description: None }, + )]), + required: Some(vec!["order_id".to_string()]), + additional_properties: Some(AdditionalProperties::Boolean(false)), + }, + output_schema: Some(json!({ + "type": "object", + "properties": { + "ok": {"type": "boolean"} + }, + "required": ["ok"], + })), + })), + ToolSpec::Function(ResponsesApiTool { + name: "lookup_order".to_string(), + description: "Look up an order\n\nexec tool declaration:\n```ts\ndeclare const tools: { lookup_order(args: { order_id: string; }): Promise<{ ok: boolean; }>; };\n```".to_string(), + strict: false, + defer_loading: Some(true), + parameters: JsonSchema::Object { + properties: BTreeMap::from([( + "order_id".to_string(), + JsonSchema::String { description: None }, + )]), + required: Some(vec!["order_id".to_string()]), + additional_properties: Some(AdditionalProperties::Boolean(false)), + }, + output_schema: Some(json!({ + "type": "object", + "properties": { + "ok": {"type": "boolean"} + }, + "required": ["ok"], + })), + }) + ); +} + +#[test] +fn augment_tool_spec_for_code_mode_preserves_exec_tool_description() { + assert_eq!( + augment_tool_spec_for_code_mode(ToolSpec::Freeform(FreeformTool { + name: codex_code_mode::PUBLIC_TOOL_NAME.to_string(), + description: "Run code".to_string(), + format: FreeformToolFormat { + r#type: "grammar".to_string(), + syntax: "lark".to_string(), + definition: "start: \"exec\"".to_string(), + }, + })), + ToolSpec::Freeform(FreeformTool { + name: codex_code_mode::PUBLIC_TOOL_NAME.to_string(), + description: "Run code".to_string(), + format: FreeformToolFormat { + r#type: "grammar".to_string(), + syntax: "lark".to_string(), + definition: "start: \"exec\"".to_string(), + }, + }) + ); +} + +#[test] +fn tool_spec_to_code_mode_tool_definition_returns_augmented_nested_tools() { + let spec = ToolSpec::Freeform(FreeformTool { + name: "apply_patch".to_string(), + description: "Apply a patch".to_string(), + format: FreeformToolFormat { + r#type: "grammar".to_string(), + syntax: "lark".to_string(), + definition: "start: \"patch\"".to_string(), + }, + }); + + assert_eq!( + tool_spec_to_code_mode_tool_definition(&spec), + Some(codex_code_mode::ToolDefinition { + name: "apply_patch".to_string(), + description: "Apply a patch\n\nexec tool declaration:\n```ts\ndeclare const tools: { apply_patch(input: string): Promise; };\n```".to_string(), + kind: codex_code_mode::CodeModeToolKind::Freeform, + input_schema: None, + output_schema: None, + }) + ); +} + +#[test] +fn tool_spec_to_code_mode_tool_definition_skips_unsupported_variants() { + assert_eq!( + tool_spec_to_code_mode_tool_definition(&ToolSpec::ToolSearch { + execution: "sync".to_string(), + description: "Search".to_string(), + parameters: JsonSchema::Object { + properties: BTreeMap::new(), + required: None, + additional_properties: None, + }, + }), + None + ); +} diff --git a/codex-rs/tools/src/lib.rs b/codex-rs/tools/src/lib.rs index 527424c276..08352704c6 100644 --- a/codex-rs/tools/src/lib.rs +++ b/codex-rs/tools/src/lib.rs @@ -1,6 +1,7 @@ //! Shared tool definitions and Responses API tool primitives that can live //! outside `codex-core`. +mod code_mode; mod dynamic_tool; mod json_schema; mod mcp_tool; @@ -8,6 +9,8 @@ mod responses_api; mod tool_definition; mod tool_spec; +pub use code_mode::augment_tool_spec_for_code_mode; +pub use code_mode::tool_spec_to_code_mode_tool_definition; pub use dynamic_tool::parse_dynamic_tool; pub use json_schema::AdditionalProperties; pub use json_schema::JsonSchema; From a16a9109d7c464be03c463074fbe2daaa465b727 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 15:36:01 -0700 Subject: [PATCH 10/17] ci: use BuildBuddy for rust-ci-full non-Windows argument-comment-lint (#16136) ## Why PR #16130 fixed the Windows `argument-comment-lint` regression in `rust-ci-full`, but the next `main` runs still left the Linux and macOS lint legs timing out. In [run 23695263729](https://github.com/openai/codex/actions/runs/23695263729), both non-Windows `argument-comment-lint` jobs were cancelled almost exactly 30 minutes after they started. The remaining workflow difference versus `rust-ci.yml` was that `rust-ci-full` did not pass `BUILDBUDDY_API_KEY` into the non-Windows Bazel lint step, so `run-bazel-ci.sh` fell back to local Bazel configuration instead of using the faster remote-backed path available on `main`. ## What changed - passed `BUILDBUDDY_API_KEY` to the non-Windows `rust-ci-full` `argument-comment-lint` Bazel step - left the Windows packaged-wrapper path from #16130 unchanged - kept the change scoped to `rust-ci-full.yml` ## Test plan - loaded `.github/workflows/rust-ci-full.yml` and `.github/workflows/rust-ci.yml` with `python3` + `yaml.safe_load(...)` - inspected run `23695263729` and confirmed `Argument comment lint - Linux` and `Argument comment lint - macOS` were cancelled about 30 minutes after start - verified the updated `rust-ci-full` step now matches the non-Windows secret wiring already present in `rust-ci.yml` ## References - #16130 - #16106 --- .github/workflows/rust-ci-full.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/rust-ci-full.yml b/.github/workflows/rust-ci-full.yml index 7bc4d9c040..a09c7fd433 100644 --- a/.github/workflows/rust-ci-full.yml +++ b/.github/workflows/rust-ci-full.yml @@ -112,6 +112,8 @@ jobs: rustup default nightly-2025-09-18 - name: Run argument comment lint on codex-rs via Bazel if: ${{ runner.os != 'Windows' }} + env: + BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} shell: bash run: | ./.github/scripts/run-bazel-ci.sh \ From f7ef9599eddade2c4d1763fcc04581315994dbc6 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 16:01:04 -0700 Subject: [PATCH 11/17] exec: make review-policy tests hermetic (#16137) ## Why `thread_start_params_from_config()` is supposed to forward the effective `approvals_reviewer` into the app-server request, but these tests were constructing that config through `ConfigBuilder::build()`, which also loads ambient system and managed config layers. On machines with an admin or host-level reviewer override, the manual-only case could inherit `guardian_subagent` and fail even though the exec-side mapping was correct. ## What changed - Set `approvals_reviewer` explicitly via `harness_overrides` in the two `thread_start_params_*review_policy*` tests in `codex-rs/exec/src/lib.rs`. - Removed the dependence on default config resolution and temp `config.toml` writes so the tests exercise only the reviewer-to-request mapping in `codex-exec`. ## Testing - `cargo test -p codex-exec` --- codex-rs/exec/src/lib.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index 84f1685d9b..71a37cc6aa 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -1975,10 +1975,14 @@ mod tests { let cwd = tempdir().expect("create temp cwd"); let config = ConfigBuilder::default() .codex_home(codex_home.path().to_path_buf()) + .harness_overrides(ConfigOverrides { + approvals_reviewer: Some(ApprovalsReviewer::User), + ..Default::default() + }) .fallback_cwd(Some(cwd.path().to_path_buf())) .build() .await - .expect("build default config"); + .expect("build config with manual-only review policy"); let params = thread_start_params_from_config(&config); @@ -1992,17 +1996,16 @@ mod tests { async fn thread_start_params_include_review_policy_when_auto_review_is_enabled() { let codex_home = tempdir().expect("create temp codex home"); let cwd = tempdir().expect("create temp cwd"); - std::fs::write( - codex_home.path().join("config.toml"), - "approvals_reviewer = \"guardian_subagent\"\n", - ) - .expect("write auto-review config"); let config = ConfigBuilder::default() .codex_home(codex_home.path().to_path_buf()) + .harness_overrides(ConfigOverrides { + approvals_reviewer: Some(ApprovalsReviewer::GuardianSubagent), + ..Default::default() + }) .fallback_cwd(Some(cwd.path().to_path_buf())) .build() .await - .expect("build auto-review config"); + .expect("build config with guardian review policy"); let params = thread_start_params_from_config(&config); From 46b653e73c7900cc7fb2e06effc5cf305541aa76 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sat, 28 Mar 2026 17:22:25 -0600 Subject: [PATCH 12/17] Fix skills picker scrolling in tui app server (#16109) Fixes #16091. The app-server TUI was truncating the filtered mention candidate list to `MAX_POPUP_ROWS`, so the `$` skills picker only exposed the first 8 matches. That made it look like many skills were missing and prevented keyboard navigation beyond the first page, even though direct `$skill-name` insertion still worked. Testing: I manually verified the regression and confirmed the fix. --- codex-rs/tui/src/bottom_pane/skill_popup.rs | 25 +++++++++-- ...ll_popup__tests__skill_popup_scrolled.snap | 43 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 codex-rs/tui/src/bottom_pane/snapshots/codex_tui__bottom_pane__skill_popup__tests__skill_popup_scrolled.snap diff --git a/codex-rs/tui/src/bottom_pane/skill_popup.rs b/codex-rs/tui/src/bottom_pane/skill_popup.rs index 061d3f3b82..2e5c7c70f2 100644 --- a/codex-rs/tui/src/bottom_pane/skill_popup.rs +++ b/codex-rs/tui/src/bottom_pane/skill_popup.rs @@ -180,7 +180,6 @@ impl SkillPopup { }) }); - out.truncate(MAX_POPUP_ROWS); out } } @@ -235,6 +234,8 @@ fn skill_popup_hint_line() -> Line<'static> { mod tests { use super::*; use pretty_assertions::assert_eq; + use ratatui::buffer::Buffer; + use ratatui::layout::Rect; fn mention_item(index: usize) -> MentionItem { MentionItem { @@ -249,7 +250,7 @@ mod tests { } #[test] - fn filtered_mentions_are_capped_to_max_popup_rows() { + fn filtered_mentions_preserve_results_beyond_popup_height() { let popup = SkillPopup::new((0..(MAX_POPUP_ROWS + 2)).map(mention_item).collect()); let filtered_names: Vec = popup @@ -260,7 +261,7 @@ mod tests { assert_eq!( filtered_names, - (0..MAX_POPUP_ROWS) + (0..(MAX_POPUP_ROWS + 2)) .map(|idx| format!("Mention {idx:02}")) .collect::>() ); @@ -269,4 +270,22 @@ mod tests { (MAX_POPUP_ROWS as u16) + 2 ); } + + fn render_popup(popup: &SkillPopup, width: u16) -> String { + let area = Rect::new(0, 0, width, popup.calculate_required_height(width)); + let mut buf = Buffer::empty(area); + popup.render_ref(area, &mut buf); + format!("{buf:?}") + } + + #[test] + fn scrolling_mentions_shifts_rendered_window_snapshot() { + let mut popup = SkillPopup::new((0..(MAX_POPUP_ROWS + 2)).map(mention_item).collect()); + + for _ in 0..=MAX_POPUP_ROWS { + popup.move_down(); + } + + insta::assert_snapshot!("skill_popup_scrolled", render_popup(&popup, /*width*/ 72)); + } } diff --git a/codex-rs/tui/src/bottom_pane/snapshots/codex_tui__bottom_pane__skill_popup__tests__skill_popup_scrolled.snap b/codex-rs/tui/src/bottom_pane/snapshots/codex_tui__bottom_pane__skill_popup__tests__skill_popup_scrolled.snap new file mode 100644 index 0000000000..00789eadc1 --- /dev/null +++ b/codex-rs/tui/src/bottom_pane/snapshots/codex_tui__bottom_pane__skill_popup__tests__skill_popup_scrolled.snap @@ -0,0 +1,43 @@ +--- +source: tui/src/bottom_pane/skill_popup.rs +assertion_line: 289 +expression: "render_popup(&popup, /*width*/ 72)" +--- +Buffer { + area: Rect { x: 0, y: 0, width: 72, height: 10 }, + content: [ + " Mention 01 [Skill] Description 01 ", + " Mention 02 [Skill] Description 02 ", + " Mention 03 [Skill] Description 03 ", + " Mention 04 [Skill] Description 04 ", + " Mention 05 [Skill] Description 05 ", + " Mention 06 [Skill] Description 06 ", + " Mention 07 [Skill] Description 07 ", + " Mention 08 [Skill] Description 08 ", + " ", + " Press enter to insert or esc to close ", + ], + styles: [ + x: 0, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 14, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: DIM, + x: 36, y: 0, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 14, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: DIM, + x: 36, y: 1, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 14, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: DIM, + x: 36, y: 2, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 14, y: 3, fg: Reset, bg: Reset, underline: Reset, modifier: DIM, + x: 36, y: 3, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 14, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: DIM, + x: 36, y: 4, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 14, y: 5, fg: Reset, bg: Reset, underline: Reset, modifier: DIM, + x: 36, y: 5, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 14, y: 6, fg: Reset, bg: Reset, underline: Reset, modifier: DIM, + x: 36, y: 6, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 2, y: 7, fg: Cyan, bg: Reset, underline: Reset, modifier: BOLD, + x: 36, y: 7, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 8, y: 9, fg: Reset, bg: Reset, underline: Reset, modifier: DIM, + x: 13, y: 9, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + x: 27, y: 9, fg: Reset, bg: Reset, underline: Reset, modifier: DIM, + x: 30, y: 9, fg: Reset, bg: Reset, underline: Reset, modifier: NONE, + ] +} From 4e119a3b38e4a4decfccb003acecabc4614142b6 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 28 Mar 2026 16:33:58 -0700 Subject: [PATCH 13/17] codex-tools: extract local host tool specs (#16138) ## Why `core/src/tools/spec.rs` still bundled a set of pure local-host tool builders with the orchestration that actually decides when those tools are exposed and which handlers back them. That made `codex-core` responsible for JSON/tool-shape construction that does not depend on session state, and it kept the `codex-tools` migration from taking a meaningfully larger bite out of `spec.rs`. This PR moves that reusable spec-building layer into `codex-tools` while leaving feature gating, handler registration, and runtime-coupled descriptions in `codex-core`. ## What changed - added `codex-rs/tools/src/local_tool.rs` for the pure builders for `exec_command`, `write_stdin`, `shell`, `shell_command`, and `request_permissions` - added `codex-rs/tools/src/view_image.rs` for the `view_image` tool spec and output schema so the extracted modules stay right-sized - rewired `codex-rs/core/src/tools/spec.rs` to call those extracted builders instead of constructing these specs inline - kept the `request_permissions` description source in `codex-core`, with `codex-tools` taking the description as input so the crate boundary does not grow a dependency on handler/runtime code - moved the direct constructor coverage for this slice from `codex-rs/core/src/tools/spec_tests.rs` into `codex-rs/tools/src/local_tool_tests.rs` and `codex-rs/tools/src/view_image_tests.rs` - updated `codex-rs/tools/README.md` to reflect that `codex-tools` now owns this local-host spec layer ## Test plan - `CARGO_TARGET_DIR=/tmp/codex-tools-local-host cargo test -p codex-tools` - `CARGO_TARGET_DIR=/tmp/codex-core-local-tools cargo test -p codex-core --lib tools::spec::` - `just argument-comment-lint` ## References - #15923 - #15928 - #15944 - #15953 - #16031 - #16047 - #16129 - #16132 --- codex-rs/core/src/tools/spec.rs | 544 +------------------------ codex-rs/core/src/tools/spec_tests.rs | 197 +-------- codex-rs/tools/README.md | 1 + codex-rs/tools/src/lib.rs | 11 + codex-rs/tools/src/local_tool.rs | 463 +++++++++++++++++++++ codex-rs/tools/src/local_tool_tests.rs | 442 ++++++++++++++++++++ codex-rs/tools/src/view_image.rs | 67 +++ codex-rs/tools/src/view_image_tests.rs | 67 +++ 8 files changed, 1089 insertions(+), 703 deletions(-) create mode 100644 codex-rs/tools/src/local_tool.rs create mode 100644 codex-rs/tools/src/local_tool_tests.rs create mode 100644 codex-rs/tools/src/view_image.rs create mode 100644 codex-rs/tools/src/view_image_tests.rs diff --git a/codex-rs/core/src/tools/spec.rs b/codex-rs/core/src/tools/spec.rs index e478c55e48..2e0dcf0845 100644 --- a/codex-rs/core/src/tools/spec.rs +++ b/codex-rs/core/src/tools/spec.rs @@ -32,7 +32,6 @@ use codex_protocol::config_types::WebSearchConfig; use codex_protocol::config_types::WebSearchMode; use codex_protocol::config_types::WindowsSandboxLevel; use codex_protocol::dynamic_tools::DynamicToolSpec; -use codex_protocol::models::VIEW_IMAGE_TOOL_NAME; use codex_protocol::openai_models::ApplyPatchToolType; use codex_protocol::openai_models::ConfigShellToolType; use codex_protocol::openai_models::InputModality; @@ -42,10 +41,19 @@ use codex_protocol::openai_models::WebSearchToolType; use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::SubAgentSource; +use codex_tools::CommandToolOptions; use codex_tools::FreeformTool; use codex_tools::FreeformToolFormat; use codex_tools::ResponsesApiTool; +use codex_tools::ShellToolOptions; +use codex_tools::ViewImageToolOptions; use codex_tools::augment_tool_spec_for_code_mode; +use codex_tools::create_exec_command_tool; +use codex_tools::create_request_permissions_tool; +use codex_tools::create_shell_command_tool; +use codex_tools::create_shell_tool; +use codex_tools::create_view_image_tool; +use codex_tools::create_write_stdin_tool; use codex_tools::dynamic_tool_to_responses_api_tool; use codex_tools::mcp_tool_to_responses_api_tool; use codex_tools::tool_spec_to_code_mode_tool_definition; @@ -81,40 +89,6 @@ static TOOL_SUGGEST_DESCRIPTION_TEMPLATE: LazyLock