diff --git a/.dockerignore b/.dockerignore index c5530dc8..32c1c726 100644 --- a/.dockerignore +++ b/.dockerignore @@ -53,8 +53,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index fdda9f77..597b2d95 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -245,6 +245,15 @@ jobs: # https://github.com/edge-toolkit/core/commit/e2f650920e0179f4ff877fc2faf704e0b7a02684, upload log # `Found 10 coverage files to report` at # https://github.com/edge-toolkit/core/actions/runs/39376279480/job/118475035669. + # + # `plugins: noop` turns off the CLI's report generators (xcode, gcov, pycoverage), which run before an upload + # whatever it names. With each upload already naming its report they can only add a failure: pycoverage runs + # `coverage xml` on the root `.coverage` whenever `shutil.which("coverage")` finds one, and on Windows it found + # a `coverage` its subprocess call could not then start, failing the whole upload with + # FileNotFoundError: [WinError 2] The system cannot find the file specified + # ==> Failed to run upload-coverage + # on commit https://github.com/edge-toolkit/core/commit/bc3da2243096fcd6ee0805bf57a176a4785931a2 at + # https://github.com/edge-toolkit/core/actions/runs/42927591780/job/130218105614. - name: Upload Rust coverage to Codecov (OIDC) if: ${{ !cancelled() && hashFiles('lcov.info') != '' }} uses: codecov/codecov-action@v7 @@ -252,6 +261,7 @@ jobs: use_oidc: true files: lcov.info disable_search: true + plugins: noop flags: rust,${{ matrix.os_flag }} fail_ci_if_error: true @@ -262,6 +272,7 @@ jobs: use_oidc: true files: coverage-python.xml disable_search: true + plugins: noop flags: python,${{ matrix.os_flag }} fail_ci_if_error: true diff --git a/.gitignore b/.gitignore index 73f154f9..f56572f8 100644 --- a/.gitignore +++ b/.gitignore @@ -49,8 +49,10 @@ coverage-python.xml # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/.mise/config.coverage.toml b/.mise/config.coverage.toml index 82bc161e..4bb5f537 100644 --- a/.mise/config.coverage.toml +++ b/.mise/config.coverage.toml @@ -30,6 +30,9 @@ # platform would fall back to host perl. gocloc is the closest thing that installs as a prebuilt binary. "aqua:hhatto/gocloc" = "latest" "conda:clang" = { version = "latest", os = ["linux", "macos"] } +# coverage.py for et-ws-pyo3-runner's embedded interpreter, which imports it from mise's pipx site-packages. +# Pinned to the release uv.lock gives the pytest runs, because `coverage combine` merges the two sets of data. +"pipx:coverage" = "7.15.0" [tools."github:taiki-e/cargo-llvm-cov"] asset_pattern = "{{ vars.musl_pattern }}" @@ -121,10 +124,10 @@ eval "$(cargo llvm-cov show-env --sh)" # (RUSTUP_TOOLCHAIN above), so every cargo invocation below hits the same build-script layout. ort_build_dir="${CARGO_TARGET_DIR:-target}${CARGO_BUILD_TARGET:+/$CARGO_BUILD_TARGET}/debug/build" coreutils mkdir -p "$ort_build_dir/examples" "$ort_build_dir/deps" -# nextest SIGKILLs the spawned et-ws-pyo3-runner (services/ws-pyo3-runner/tests/modules.rs) after each exchange. -# LLVM flushes a process's counters only at exit, so a SIGKILLed process contributes nothing: the runner's async -# run/drive/worker paths reported 0% while its in-process initialize() was covered. Continuous mode (%c) memory-maps -# the counter file so increments persist live and survive the kill. %c is incompatible with the merge-pool (%Nm) +# A spawned workspace binary that a test kills, rather than lets exit, contributes no coverage. +# LLVM flushes a process's counters only at exit, and services/ws-server-firmware/tests/serves_modules.rs ends +# et-ws-server-firmware that way, on drop. Continuous mode (%c) memory-maps the counter file so increments persist +# live and survive the kill. %c is incompatible with the merge-pool (%Nm) # specifier show-env emits, so use a per-process (%p) continuous file in the same profile dir -- `cargo llvm-cov # report` globs every *.profraw there regardless of name. Branch coverage: `show-env` has no --branch flag (only # the top-level `cargo llvm-cov` does), so the nightly `-Zcoverage-options=branch` is appended to the wrapper @@ -143,9 +146,9 @@ coreutils mkdir -p "$ort_build_dir/examples" "$ort_build_dir/deps" # numbers under the merge-pool pattern and zeros under %c. The relocation flag above is what makes %c work # on Linux and has no Mach-O counterpart to reach for. Windows has never run %c here, and the way it fails on # macOS is silent -- a report of zeros, not an error -- so that lane takes the pattern known to work rather -# than finding out from its numbers. The carve-out costs exactly what %c was added for: the pyo3 runner that -# nextest SIGKILLs contributes nothing on macOS or Windows, so its async paths read 0% there and the Linux lane -# is the one that measures them. The wrapper flags env is CARGO_ENCODED_RUSTFLAGS format (ASCII +# than finding out from its numbers. The carve-out costs exactly what %c was added for: a killed binary +# contributes nothing on macOS or Windows, so the Linux lane is the one that measures it. The wrapper flags env is +# CARGO_ENCODED_RUSTFLAGS format (ASCII # unit separator 0x1f between flags), not space-separated -- a space append glues the llvm-arg onto the last # existing flag and rustc rejects `--cfg=coverage_nightly -Cllvm-args=...` as one invalid --cfg value. goawk # generates the separator byte at run time: bash dollar-quote hex is not a valid escape in this TOML basic @@ -165,14 +168,15 @@ fi export __CARGO_LLVM_COV_RUSTC_WRAPPER_RUSTFLAGS="$flags" # The --features flags compile each runner's coverage code, off by default so non-coverage builds omit it. # et-ws-web-runner/coverage adds the browser-module capture (shims + the __et_capture_coverage PUT); -# et-ws-wasi-runner/coverage adds the guest `/cov` preopen. ET_TEST_COVERAGE (set by the coverage job) still -# gates capture at runtime within each build. +# et-ws-wasi-runner/coverage adds the guest `/cov` preopen; et-ws-pyo3-runner/coverage adds coverage.py +# measurement of the module it loads. ET_TEST_COVERAGE (set by the coverage job) still gates capture at runtime +# within each build. # The run takes the same workspace exclusions as cargo-test, and the web runner's feature goes with its crate. # cargo_ws_excludes leaves et-ws-web-runner out on the gnullvm Windows target, and cargo refuses a feature of # an unselected package outright: # error: none of the selected packages contains this feature: et-ws-web-runner/coverage excludes="{{ vars.cargo_ws_excludes }}" -features=et-ws-wasi-runner/coverage +features=et-ws-pyo3-runner/coverage,et-ws-wasi-runner/coverage case " $excludes " in *" et-ws-web-runner "*) ;; *) features="$features,et-ws-web-runner/coverage" ;; @@ -418,11 +422,12 @@ cargo llvm-cov report -p et-test-recovery --summary-only --fail-under-lines 100 shell = "{{ vars.task_shell }}" [tasks.pytest-cov] -description = "Combined Python coverage (pytest + web-runner Pyodide runs) -> Cobertura, plus pytest JUnit results" -# One Python report is combined from several data sources: the pytest runs plus the web-runner Pyodide runs. -# The Python workflow pytest runs and the web-runner integration test (which drops the modules' .coverage files -# into target/pycov/ when ET_TEST_COVERAGE is set) all feed `coverage combine`. The paths in -# config/coverage.toml remap them into a single Cobertura report. +description = "Combined Python coverage (pytest + web and pyo3 runner runs) -> Cobertura, plus pytest JUnit results" +# One Python report is combined from several data sources: the pytest runs plus the runner integration tests. +# The Python workflow pytest runs, the web-runner integration test (which drops the Pyodide modules' .coverage +# files into target/pycov/ when ET_TEST_COVERAGE is set) and et-ws-pyo3-runner (which writes its module's data +# there itself) all feed `coverage combine`. The paths in config/coverage.toml remap them into a single Cobertura +# report. # Each pytest run also writes target/pycov/junit-.xml for the Codecov test-results upload. The path is # absolute because `uv run --directory` moves pytest into the module dir, and `junit_family=legacy` is the # schema that records each test's file, which Codecov's test analytics reads. @@ -442,7 +447,7 @@ cov_args="--cov=edge_toolkit --cov-report=term-missing --cov-fail-under=100" # shellcheck disable=SC2086 uv run --directory "$sdk" pytest $cov_args --junitxml="$junit" -o junit_family=legacy coreutils cp "$sdk/.coverage" "$pycov/.coverage.edge_toolkit_pytest" -bridge=modules/pyo3/pyo3-mlflow +bridge=modules/pyo3/mlflow junit="$PWD/$pycov/junit-pyo3-mlflow.xml" uv run --project "$pyface" pytest "$bridge" --cov="$bridge/pkg" --cov-report= --junitxml="$junit" -o junit_family=legacy coreutils cp .coverage "$pycov/.coverage.pyo3-mlflow_pytest" diff --git a/.mise/config.python.toml b/.mise/config.python.toml index 78e5c316..9babc7a8 100644 --- a/.mise/config.python.toml +++ b/.mise/config.python.toml @@ -115,7 +115,7 @@ depends = [ description = "Run Python tests" [tasks.test-pyo3-mlflow] -dir = "modules/pyo3/pyo3-mlflow" +dir = "modules/pyo3/mlflow" run = "python -m unittest discover -p 'test_*.py'" [tasks.test-edge-toolkit] diff --git a/.mise/locks/mise.coverage/pipx-coverage/7.15.0/pyproject.toml b/.mise/locks/mise.coverage/pipx-coverage/7.15.0/pyproject.toml new file mode 100644 index 00000000..37397f2e --- /dev/null +++ b/.mise/locks/mise.coverage/pipx-coverage/7.15.0/pyproject.toml @@ -0,0 +1,5 @@ +[project] +name = "mise-pypi-tool-environment" +version = "0.0.0" +requires-python = ">=3.10" +dependencies = ["coverage==7.15.0"] diff --git a/.mise/locks/mise.coverage/pipx-coverage/7.15.0/uv.lock b/.mise/locks/mise.coverage/pipx-coverage/7.15.0/uv.lock new file mode 100644 index 00000000..2184afb1 --- /dev/null +++ b/.mise/locks/mise.coverage/pipx-coverage/7.15.0/uv.lock @@ -0,0 +1,115 @@ +version = 1 +revision = 5 +requires-python = ">=3.10" + +[options] +exclude-newer = "2026-11-09T11:51:03.671727Z" + +[[package]] +name = "coverage" +version = "7.15.0" +source = { registry = "https://pypi.org/simple/" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/8b/adeb62ea8951f13c4c7fef2e7a85e1a06b499c8d8237ea589d496029e53f/coverage-7.15.0.tar.gz", hash = "sha256:9ac3fe7a1435986463eaa8ee253ae2f2a268709ba4ae5c7dd1f52a05391ad78f", size = 925362, upload-time = "2026-07-02T13:10:50.535Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/97/c52dc440c390b6cfa87be9432b141a956e2d56d9b9f5fc8bd71c5f471722/coverage-7.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50913d4bf5ddafa6ca3693da5e4dd833dd1b772e0283c99ca7f7d287db67331a", size = 220539, upload-time = "2026-07-02T13:08:19.252Z" }, + { url = "https://files.pythonhosted.org/packages/3f/26/602de8c2aec7e2e3e99ebfb8e04ba65598f746275396eea5f6794ff4673f/coverage-7.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:359e141ccd33893ce3f1ad5525f8b96083003677c82182e5907d62d4ea5799fc", size = 221058, upload-time = "2026-07-02T13:08:21.013Z" }, + { url = "https://files.pythonhosted.org/packages/fc/13/ebab0743138891c1d646d61e247ec29639afcbb6c4e1905e6a0f0c75291a/coverage-7.15.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3200b6204935f928c64b2ca1f923ab8c1acb7c9de45ec61569711b34d25cccaf", size = 247797, upload-time = "2026-07-02T13:08:22.474Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b7/b6ffb9e042aa48dc4144a8a65529affaec8dca0685309353614a2a7386ad/coverage-7.15.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:be616bf61346883b2cfdc5178669647e03531d81ab761a7e378558b7e8bcb628", size = 249626, upload-time = "2026-07-02T13:08:23.803Z" }, + { url = "https://files.pythonhosted.org/packages/9c/06/243ff05b652333d8e3d060c11223efc2723b19cacf6605e433fa686ab5d4/coverage-7.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc7bafc3fe1059463a8fdd97ca79972d6e2bf819d775c7d54991b5b1971201d6", size = 251493, upload-time = "2026-07-02T13:08:25.397Z" }, + { url = "https://files.pythonhosted.org/packages/d3/2b/867faa17030a806114dae388b32a3fa929d8cd4bf39226fbc11f6e6bb705/coverage-7.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b713aa7fcf325a01d4184d848acb46fd84f78fdb0978470c636b23a06a753d91", size = 253406, upload-time = "2026-07-02T13:08:26.842Z" }, + { url = "https://files.pythonhosted.org/packages/94/c0/d789ce18f6605afc4895db75723424be2ef494282f77f61d8e5832923183/coverage-7.15.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e38e6fba2d56652fdfaf0231f8f78aeb805234a912de25dc291ee5cce5b8faa4", size = 248512, upload-time = "2026-07-02T13:08:28.398Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b6/b2673c30739f4a2e06649a0a38ad8b093c4d865462dc7bab0e9524a2c3b1/coverage-7.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:884499f42e382675be80770391983b90e0c0c774d87dbeeebf5f991cf6612b20", size = 249532, upload-time = "2026-07-02T13:08:29.731Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/acd79e9a41beabee92b623afe4f30b549916f48566271475f2907e752828/coverage-7.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:840481b12e083dbcbafab14794a8781a958edf327c8d3d70b4eee42f9b8253aa", size = 247537, upload-time = "2026-07-02T13:08:31.173Z" }, + { url = "https://files.pythonhosted.org/packages/12/d4/2d301c4d1b3238d7c88b70ab9d13fd53ed9505662a7ff1b46ba1e2e4e3c3/coverage-7.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:276646e9481703d09f854f3b2f018f24e19fd7049ae670a92570043eb97203b1", size = 251348, upload-time = "2026-07-02T13:08:32.63Z" }, + { url = "https://files.pythonhosted.org/packages/35/bb/c67708b2bc00f32e12805ec23d5fa677a0a51652f449341a89f9d6b1b715/coverage-7.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4de4b4d3f5545aa6c60dc4efd9c63b5b5dcc3bf00fe83146b2bdfffb8f6613bd", size = 247806, upload-time = "2026-07-02T13:08:33.931Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6c/57c4f653c47a6e917748f8938e389e72fbcae44e3643cd906664f0477a13/coverage-7.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5c504097b2a89b1e85bc6070d920df77daec701337e3aeef2c17775a5dd0ca90", size = 248410, upload-time = "2026-07-02T13:08:35.189Z" }, + { url = "https://files.pythonhosted.org/packages/6c/94/bb083041aef828903668f134273f319f2bd49224962875359c52faa5497f/coverage-7.15.0-cp310-cp310-win32.whl", hash = "sha256:f6e80ed91f98316e86b9c137206b04b2bcfbffccbdff49bd2eb09dddb1cf14e0", size = 222588, upload-time = "2026-07-02T13:08:36.486Z" }, + { url = "https://files.pythonhosted.org/packages/ef/94/a09d8ee618956f626741b0734854bac4425a00e10c0565f5abca64e7e751/coverage-7.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:b3b3e22030f3f6f5e01a5ce69936552a5c0f6992b7698777377b99041961031f", size = 223214, upload-time = "2026-07-02T13:08:37.885Z" }, + { url = "https://files.pythonhosted.org/packages/ae/23/82e910835ef4b8391047025e1d53aa48d66029f444eb8b25373c849bf503/coverage-7.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:003fff99412ea848c0aaebcc78ed2b6ce7d8a1227ed17e68470672770b78a02a", size = 220662, upload-time = "2026-07-02T13:08:39.205Z" }, + { url = "https://files.pythonhosted.org/packages/6d/0d/c7b213dde2f1579de5231062b386d8413f79c11667eb58c39319b25991da/coverage-7.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5cbd804bf2784ce7b45114516050f346ecd50f960c4bb630a7ee9e1d78fa2118", size = 221168, upload-time = "2026-07-02T13:08:40.471Z" }, + { url = "https://files.pythonhosted.org/packages/33/77/d000aeedfac085088337b3c7becdad328474b1f8a9e4c9368a0c99605d68/coverage-7.15.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8773e15c23305b58882a4611fb9b2755977eae0dc2e515366a1b6c98866cc4c2", size = 251587, upload-time = "2026-07-02T13:08:42.033Z" }, + { url = "https://files.pythonhosted.org/packages/cc/e0/86787c56b9df17afd370d5e293515dd4d9a107a561d13054873eefad8ecc/coverage-7.15.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f50e40081494c1dc4239ebb202014cbcc3306ea96fb6302a34c8cc0967fc5ae8", size = 253497, upload-time = "2026-07-02T13:08:43.387Z" }, + { url = "https://files.pythonhosted.org/packages/3f/02/181bc917359299c07dead6270f94e411151c8b60cec905c33499da69afe6/coverage-7.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daf96f37f5fc3a7b6c6da862eb4aee61c426bd63da236ed4a73ef0e503b4bca5", size = 255607, upload-time = "2026-07-02T13:08:44.897Z" }, + { url = "https://files.pythonhosted.org/packages/b9/35/ca5e7427699913da6788c4f910e73ab16c5f4b59ec5d3a999dce2a45112f/coverage-7.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:51aa20f6ae2788fd197747766edf4cd8234fd9423309b934257fa6b21a592723", size = 257563, upload-time = "2026-07-02T13:08:46.334Z" }, + { url = "https://files.pythonhosted.org/packages/0b/4d/b8220bacc2fc3c4e9078e27c32e99fb411479a4718a72bdd00036a9891c8/coverage-7.15.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03d1f922757662eb7af586e77834792274cff776bc7b1d1a0b66a49ea9d84735", size = 251726, upload-time = "2026-07-02T13:08:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e4/2e145da1991d72189b9c3cf7eca05c716ee7080d099aaea6757cfc7df008/coverage-7.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a6d6acc9a7666245e6133dd15144ca038a85a9cd5026bb06d6bbae9e77440dc9", size = 253301, upload-time = "2026-07-02T13:08:49.5Z" }, + { url = "https://files.pythonhosted.org/packages/72/28/d2c841d698bf762e481f08bd4839d370246b6d9b61dab085a7b20b201a08/coverage-7.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1ac2c4c27c7df851dc9a017c2d7de00b69147e84ba3d96f37a530b0b6fb51035", size = 251361, upload-time = "2026-07-02T13:08:51.304Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ed/55d9ffde994fba3897c0c783f77a7d053b0c18787f6892ed5b0aed73f469/coverage-7.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b761a1d504fd4bd1f20f418753964dca9f5862a511fc854dac58296b3b223671", size = 255129, upload-time = "2026-07-02T13:08:52.661Z" }, + { url = "https://files.pythonhosted.org/packages/1d/c0/ecbf33b8c460ea2718aeb813e2df8140d0370e5f67261c31524ceb0a2a8d/coverage-7.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e43b045e11c16e897895758ae90e4a90cf99e93d58549e2f90c0e2272e155695", size = 251081, upload-time = "2026-07-02T13:08:54.188Z" }, + { url = "https://files.pythonhosted.org/packages/a9/de/fb87b4261f54448dd2b9504ef19a58be42cef0d9520595fbfe1219b15234/coverage-7.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:589b54513e901739f4b4582c705ce96b80c96f57641b1464607e2367a270e540", size = 251988, upload-time = "2026-07-02T13:08:55.726Z" }, + { url = "https://files.pythonhosted.org/packages/df/27/3494d5f291b9a4cb868f73c11221a8bd2d5bd761a8f9acea61ff57128dd1/coverage-7.15.0-cp311-cp311-win32.whl", hash = "sha256:106781b8482749162d0b47056937ba0933508e5d9447f65a5e7d5c422f0d6bb4", size = 222754, upload-time = "2026-07-02T13:08:57.091Z" }, + { url = "https://files.pythonhosted.org/packages/2a/ee/cd4847ebc9be6a9c0123d763645a6f1f3be6b8c58c962706368b79cbac07/coverage-7.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:821e92b3631d762a339695824cadbbc73020354eba2a23a551a99ad34938fbe6", size = 223225, upload-time = "2026-07-02T13:08:58.594Z" }, + { url = "https://files.pythonhosted.org/packages/57/37/5011581aa7f2be498b97dcc7c9902192442a42f4f9a748aeadb3d6506b42/coverage-7.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:309990eb5fb8014b9f67cb211f7fd41876ec8a88a88d3ae76de0ed1d611e3640", size = 222774, upload-time = "2026-07-02T13:09:00.074Z" }, + { url = "https://files.pythonhosted.org/packages/2a/74/fd4c0901137c4f8d81a76ada99e43c65163b4c94a02ece107a4ec0c6b615/coverage-7.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b75ee5e8cb7575636ac598719b4307ac529ec8fcd79608a35c3cd4d4dada812d", size = 220838, upload-time = "2026-07-02T13:09:02.084Z" }, + { url = "https://files.pythonhosted.org/packages/0f/2e/2347583467bd7f0402635101a916961915cc68fce652cd0db5f173ea04fc/coverage-7.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffb31267816b93b075302248cc1737506081b4f163df4401e9df1a6424aafabe", size = 221197, upload-time = "2026-07-02T13:09:03.617Z" }, + { url = "https://files.pythonhosted.org/packages/f0/17/99fa688541ae1d6e84543a0e544f83de0c944815b63e9e7b1ed411d15036/coverage-7.15.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e4d0bb73455bf97ab243a8f12c37c686ccf1c13bb614b7b85f1d062f06f42b2c", size = 252705, upload-time = "2026-07-02T13:09:05.059Z" }, + { url = "https://files.pythonhosted.org/packages/fb/02/6a95a5cd83b74839017ef9cf48d2d8c9ae60af919e17a3f336e6f9f1b7bd/coverage-7.15.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:20d9ccc4ebd0edc434d86dfd2a1dd2a8efa6b6b3073d0485a394fee86459ebb4", size = 255441, upload-time = "2026-07-02T13:09:06.559Z" }, + { url = "https://files.pythonhosted.org/packages/67/f2/406f6c57d600f68185942422c4c00f1a3255d60aee6e5fd961425cd9987e/coverage-7.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20c8a976c365c8cb12f0cbd099508772ea41fb5fa80657a8506df0e11bd278c5", size = 256556, upload-time = "2026-07-02T13:09:08.197Z" }, + { url = "https://files.pythonhosted.org/packages/74/8e/d3fa48489c15ecdec1ba48fd61f68798555dddd2f6716f9ad42adeb1a2a9/coverage-7.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f948fd5ba1b9cbca91f0ae08b4c1ce2b139509149a435e2585d056d57d70bf01", size = 258815, upload-time = "2026-07-02T13:09:09.691Z" }, + { url = "https://files.pythonhosted.org/packages/47/2e/2d40ddd110462c6a2769677cf7f1c119a52b45f568978fc6c98e4cc0dd0f/coverage-7.15.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f58185f06edf6ad68ec9fb155d63ef650c82f3fbd7e1770e2867751fb13158f4", size = 253117, upload-time = "2026-07-02T13:09:11.212Z" }, + { url = "https://files.pythonhosted.org/packages/51/c0/310782f0d7c3cb2b5ac05ba8d205fe91f24a36f6bf3256098f1782181c38/coverage-7.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02adc79a920c73c647c5d117f55747df7f2de94571884758ce8bc58e04f0a796", size = 254475, upload-time = "2026-07-02T13:09:13.029Z" }, + { url = "https://files.pythonhosted.org/packages/86/f7/702da6c275f8ae6ade423d2877243122932c9b27f5403003b9ef8c927d12/coverage-7.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6eb7c300fbed667fd6e3588eba71c1904cdb06110ca6fdf908c26bdd88b8e382", size = 252619, upload-time = "2026-07-02T13:09:14.699Z" }, + { url = "https://files.pythonhosted.org/packages/fb/84/c5b15a7e5ecba4e56218d772d99fe80a63e63f8d11f12783723a6005ab45/coverage-7.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b5fb23fa2de9dce1f5c36c09066d8fcda16cd96e8e26686caa2d7cb9b567d65c", size = 256689, upload-time = "2026-07-02T13:09:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/95/2f/c8b07559b57701230c61b23a953858c052890c12ef568d81780c6c46e92e/coverage-7.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cec79341dbe6281484024979976d0c7f22beae08b4a254655decd25d42cbe766", size = 252189, upload-time = "2026-07-02T13:09:17.828Z" }, + { url = "https://files.pythonhosted.org/packages/6b/80/6d2f049dd3fd3dbfd60b62ba6b2162a04009e2c002ce70b24cf3878dec7a/coverage-7.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c664c5444b1d970b1b2a450e21fb19ee5c9cfdf151ded2dda37260031cca0da", size = 254059, upload-time = "2026-07-02T13:09:19.304Z" }, + { url = "https://files.pythonhosted.org/packages/ce/92/b0287a2c42031d25c628f815f89a3cd9f8268ee78bb1252c9356cda1c689/coverage-7.15.0-cp312-cp312-win32.whl", hash = "sha256:5f764a3fa339bde6b3aa97657f5a6a3a9451e4a5b4ea98a2892c773a43525f77", size = 222893, upload-time = "2026-07-02T13:09:20.812Z" }, + { url = "https://files.pythonhosted.org/packages/a9/69/e34c481915fecb499b3146975061dac528752e37706edc1804f32c822469/coverage-7.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:52f9a4d2c4c56c8848bc2f524916698354b0211488b38c49ad9ae54f6cafbff6", size = 223429, upload-time = "2026-07-02T13:09:22.315Z" }, + { url = "https://files.pythonhosted.org/packages/fe/98/6e878f0b571d32684ef3f38d7c03db241ca5b82a5da8a5391596a8f209c4/coverage-7.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:31e5c3e70c85307ea35a12964e2e40f56ca2ee4b1c8c721ccf4609d17071080b", size = 222810, upload-time = "2026-07-02T13:09:23.812Z" }, + { url = "https://files.pythonhosted.org/packages/76/04/145a3748098bcc86b631a85408d2c3dc5c104e0bd86d605468239b25b6c4/coverage-7.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5be4caf3b28836f078abe700f8944dac4a65d78f16d6c600c89cb624e5535782", size = 220863, upload-time = "2026-07-02T13:09:25.371Z" }, + { url = "https://files.pythonhosted.org/packages/a4/5c/4ed55708fed2c64b63c9bc5715daef670872202101938869b7fe5d5fbb8f/coverage-7.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dd58ad1404704303ca8d4f4b8a1095e7cbc7040ef17a66df1e6619aa10176430", size = 221230, upload-time = "2026-07-02T13:09:26.897Z" }, + { url = "https://files.pythonhosted.org/packages/7b/19/3a80b97d3b2a5c77a01ae359c6bed20c13738fe3d9380f08616d4fec0281/coverage-7.15.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bbcbb317c2e5ded5b21104af81c29f391be2af98d065693ffbe8d23949b948e5", size = 252227, upload-time = "2026-07-02T13:09:28.543Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/b70062750686bd7da454da27927622f48bbac6990ac7a4c4a4653e7b0036/coverage-7.15.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:27f31ecb458da3f859aab3f15ada871eb7a7768807d88df4a9f186bb17737970", size = 254823, upload-time = "2026-07-02T13:09:30.177Z" }, + { url = "https://files.pythonhosted.org/packages/a9/09/dad6a75a2e561b9dc5086a8c5257a7591d584246f67e23e70d2995b89ab6/coverage-7.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fb759be317fdc62e0f56bffdf61cfcb45c7761ad6b71e3e583e71a67ae753c", size = 256059, upload-time = "2026-07-02T13:09:31.979Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e7/b5d2941fa9564573d44b693a871ff3156f0c42cbefe977a09fa7fdc59971/coverage-7.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5cf007add5ab4bb8fa9f4c77e3732127c9e6cad501d7db43355fbfafca0be84", size = 258190, upload-time = "2026-07-02T13:09:34.035Z" }, + { url = "https://files.pythonhosted.org/packages/7c/1d/8e895bcde3c57ccd46d896dda5f2b3d5df761a1b0c6c9d450d175dedc632/coverage-7.15.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc78d9843bd576fbe2118248258d485e968dc535f95ed504a7b0867ba9b51389", size = 252456, upload-time = "2026-07-02T13:09:35.765Z" }, + { url = "https://files.pythonhosted.org/packages/14/4c/f6997da343ddeb959be82c3b05322793f92c071ad45f7cb8a96336e2dd5f/coverage-7.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a263060f1de0b4b74b4e089c2a70b8003b3781c733329a9c8fd54995328f9950", size = 254192, upload-time = "2026-07-02T13:09:37.445Z" }, + { url = "https://files.pythonhosted.org/packages/17/27/a0bc09d032267b9da89d95a2d874cfbef2a5aebbf0e87cf7aba221d79a99/coverage-7.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c48decf16e0dfd5b049c7d5e82200c23c08126719142998d4f172444e3d0529e", size = 252153, upload-time = "2026-07-02T13:09:39.422Z" }, + { url = "https://files.pythonhosted.org/packages/54/c0/77fc233d9fba07b244c40948c53fe27308b8f21732fb3417f87fbd6fd992/coverage-7.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08fb028000ed0aaa0a4cbdfbb98be7cb42f370db973fbbb469733505ab20e13e", size = 256310, upload-time = "2026-07-02T13:09:41.006Z" }, + { url = "https://files.pythonhosted.org/packages/d5/24/601cecfb5825becacb8d45219a018a3b55b9dbaec624efdb0ea249d08be2/coverage-7.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb7dc0c3b7d8a1077abea0b8546ebc5e26d6ef6ecefc2f0f5ad2b8a53bdad837", size = 251974, upload-time = "2026-07-02T13:09:42.733Z" }, + { url = "https://files.pythonhosted.org/packages/47/1e/6f45e5a5b3d5484318d368702af6716b5ab8913b0428bec981a562fcf296/coverage-7.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cb3602054ccbe9f0d8c2dc04bbeba90d5719236e2cd06e042ddd6d3fc7b6e37", size = 253745, upload-time = "2026-07-02T13:09:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/8e/db/4df027a77bd11d0e527f44c53557c76e54ad027413d0304252ea3a78d67e/coverage-7.15.0-cp313-cp313-win32.whl", hash = "sha256:0bf781da64326b677be344df505171435b6f58716108606621d5d27d964fff8b", size = 222902, upload-time = "2026-07-02T13:09:46.122Z" }, + { url = "https://files.pythonhosted.org/packages/a0/10/0355894d34e231f2c5449e71287e81a50793a325df2e2b027b7bcd9dfd19/coverage-7.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:2c57a275078ee3fa185f83e400f765bc764a549de66d99b47881645cbd4ea629", size = 223444, upload-time = "2026-07-02T13:09:47.687Z" }, + { url = "https://files.pythonhosted.org/packages/06/ef/bb725f263befaaff851203ab338e68af15e195d7f7b5f323162532d9b6a8/coverage-7.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:3812c61afc6685c7999b39320779ab8f43b7a3081fdb0def39976e56fbdb9a21", size = 222839, upload-time = "2026-07-02T13:09:49.717Z" }, + { url = "https://files.pythonhosted.org/packages/4f/9c/1e3ca54f72a3185ece06c58d871099898c48f0ed6430d17b6ab75f0d180a/coverage-7.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:41cb79af843222e11da87127ad0ecbfa878abadd0f770a4a99391a27d3887324", size = 220906, upload-time = "2026-07-02T13:09:51.339Z" }, + { url = "https://files.pythonhosted.org/packages/09/37/f718613d83b274880382f6b67e78f3802549ae39b0b3e65ae5b5974df56e/coverage-7.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7d2008989ef8fe54188d3f3bfa2e3099b025af11e90a6a1b9e7dc433d04263d8", size = 221239, upload-time = "2026-07-02T13:09:53.138Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ce/22bae91e0b75445f68d365c7643ed0aa4880bbf77450ee74ca65bdae53a7/coverage-7.15.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:769e8ece11a596315ebf5aa7ec383aeeed016c091d2bf6363ffb996d41529092", size = 252286, upload-time = "2026-07-02T13:09:54.996Z" }, + { url = "https://files.pythonhosted.org/packages/dd/1e/bec5e32aa508615d9d7a2790effb25fb4dc28606e995816afe400b25ece3/coverage-7.15.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:65a6b6164ee5c39e2f3803f314292d6c61a607ba7fee253d1e03c42dc3903502", size = 254789, upload-time = "2026-07-02T13:09:56.678Z" }, + { url = "https://files.pythonhosted.org/packages/17/29/0e865435b4354e4a7c03b1b7920046d31d0a273d55decefea27e011cb9bf/coverage-7.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75128817f95a5c45bb01d65fd2d8b9cb54bbe03d81608fb70e3e14b437ad56c2", size = 256135, upload-time = "2026-07-02T13:09:58.343Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/33a870b58a13325d62fc0a6c8f01fa0ff667cef60c7498e2382a147dfa18/coverage-7.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9887bb428fe2d4cd4bee89bac1a6c9932f484afd5b36fbd4ff6ea5f825bb1f5e", size = 258449, upload-time = "2026-07-02T13:10:00.057Z" }, + { url = "https://files.pythonhosted.org/packages/18/7b/6fffe596bf3ddba8462758d02c5dad730fd91055a6634aa2e4226229181a/coverage-7.15.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0bfc0be1f702042207a93a00523b1065ee1fe951e96edf311581c0bbc2e34888", size = 252313, upload-time = "2026-07-02T13:10:01.946Z" }, + { url = "https://files.pythonhosted.org/packages/58/1b/11468dd6c1676ab831a70cb9a8d4e198e8607fa0b7220ab918b73fe9bfbd/coverage-7.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f64627d55def5a43282d70e08396672692f77e4da610a5bb8bb4060b432b6859", size = 254142, upload-time = "2026-07-02T13:10:04.065Z" }, + { url = "https://files.pythonhosted.org/packages/79/41/29328e21d16b1b95092c30dd700e08cf915bd3734f836df8f3bdb0e8fa9f/coverage-7.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2c6f0fa473003905c6d5bac328ee4eba9fbea654f15bc24b8a3274b23363fa99", size = 252108, upload-time = "2026-07-02T13:10:06.11Z" }, + { url = "https://files.pythonhosted.org/packages/9b/de/05ccfb990439655b35afbfd8e0d13fe66677565a7d4eb38c3f5ef2635e1c/coverage-7.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2bcf9afaf064172c6ec3c58a325a9957ad1178c05dd934e25f253321776e0676", size = 256385, upload-time = "2026-07-02T13:10:08.141Z" }, + { url = "https://files.pythonhosted.org/packages/51/0e/486828a3d2695ea7a2609f17ff572f6b01905e608379440a11da4b8dffbe/coverage-7.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:baf06bc987115d6fb938d403f7eab684a057766c490367999a2b71a6883110c6", size = 251923, upload-time = "2026-07-02T13:10:10.179Z" }, + { url = "https://files.pythonhosted.org/packages/18/c7/03582b6715f078e5e558354c87616d945b9894cda2dace8e4009b17035e4/coverage-7.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f0405f2ff97b1c4c0e782cb32e02f32369bcf2e6b618b591d67e1ea754575dfe", size = 253580, upload-time = "2026-07-02T13:10:12.052Z" }, + { url = "https://files.pythonhosted.org/packages/db/dc/9e578bbaf2ecb4959a81b7e7601ad8cca772cba2892e8d144cb749b4a71a/coverage-7.15.0-cp314-cp314-win32.whl", hash = "sha256:ab282853ed5fbd64bbb162f19cb8fcb7087187508a6374b4f9c34ec1577c4e8f", size = 223107, upload-time = "2026-07-02T13:10:13.994Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3e/c8c3b75d8dbe0e35f7b0cc3ff5e949fc59500f70b21d0398813f66740664/coverage-7.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bb3040e9f4bbe26fcb0cd7cc85ac63e630d3f3a9c74f027abf4caa27e706663", size = 223597, upload-time = "2026-07-02T13:10:15.906Z" }, + { url = "https://files.pythonhosted.org/packages/cd/bc/3cbc9fb036eb388519bccd521f783499c39b64256013fbc362782f196fe1/coverage-7.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:346771144d34f7fa84ec28386f78e0f31653f33cf35e19d253d5b35f9e8201da", size = 223020, upload-time = "2026-07-02T13:10:17.844Z" }, + { url = "https://files.pythonhosted.org/packages/28/00/199c4a8d656dff63102577a056c0fce2ff6a79e40adac092fc986c49cbf1/coverage-7.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d34a010905fb6401324ba016b5da03d574967f7b21ce48ea41e66f0f1f95f641", size = 221638, upload-time = "2026-07-02T13:10:19.703Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8e/9d0092c96a3d3a26951ecc7020826aa57bcb1b119ca81acbba996884ab13/coverage-7.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bb25d825d885ca8036795dacfc3924d33091fc76d71ebc99420c6b79e77d96fa", size = 221903, upload-time = "2026-07-02T13:10:21.514Z" }, + { url = "https://files.pythonhosted.org/packages/6d/b4/c0ca3028f42c9a08e51feb4561ef1192e5de99797cd1db5b04590c215bda/coverage-7.15.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:94c9686bfe8a9a6810297aecbd99beaa3445f9e8dc2f80b1382cca0d86b64461", size = 263267, upload-time = "2026-07-02T13:10:23.261Z" }, + { url = "https://files.pythonhosted.org/packages/5f/aa/a375e3846e5d3c013dc600b2a3231089055c73d77f5393dd2192a8d64da6/coverage-7.15.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9bd671c25f9d85f09d7ec481d0e43d5139f486c06a37139847a7ce569788af72", size = 265390, upload-time = "2026-07-02T13:10:25.152Z" }, + { url = "https://files.pythonhosted.org/packages/92/e1/5783cdabb797305e1c9e4809fea496d31834c51fa772514f73dc148bcfc9/coverage-7.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:110cbdf8d2e216577312cf06ccf85539c0e5a5420ef747e4a4719b5e483c88cd", size = 267811, upload-time = "2026-07-02T13:10:27.249Z" }, + { url = "https://files.pythonhosted.org/packages/85/31/96d8bbf58b8e9193bc8389574a91a0db48355ee98feb66aa6bf8d1b32eea/coverage-7.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2c5d4619214f1d9993e7b00a8600d14614b7e9d84e89507460b126aa5e6559e5", size = 268928, upload-time = "2026-07-02T13:10:29.242Z" }, + { url = "https://files.pythonhosted.org/packages/5e/7a/5294567e811a1cb7eda93140c628fa050d66189da28da320f93d1d815c73/coverage-7.15.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:781a704516e2d8346fbbd5be6c6f3412dd824785146528b3a01816f26c081007", size = 262378, upload-time = "2026-07-02T13:10:31.107Z" }, + { url = "https://files.pythonhosted.org/packages/69/3f/3f48538421f899f28946f90a3d272136a4686e1abf461cc9249a783ee0f3/coverage-7.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd4a1b44bcb65ee29e947ac92bbee04956df3a6bfc6143641bb6cae7ede00fc9", size = 265263, upload-time = "2026-07-02T13:10:32.942Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d3/092df15efcab8a9c1467ee960eb8019bbad3f9300d115d89ea6195f369ff/coverage-7.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0e4950c9d6d3e39c64c991814ff315e2d0b9cb8152363594212c9e55208c0a8f", size = 262866, upload-time = "2026-07-02T13:10:35.104Z" }, + { url = "https://files.pythonhosted.org/packages/e5/ab/0254d2b88665efb2c57ad368cc77ab5de3435bd8d5add4729c1b0e79431e/coverage-7.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:fe9c87ff42e5472d80d21704972e1f96e104a0a599d77c5e35db5a3c562e2571", size = 266599, upload-time = "2026-07-02T13:10:37.05Z" }, + { url = "https://files.pythonhosted.org/packages/a8/79/1cfa4023e489ce6fbc7be4a5d442dbc375edb4f4fda39a352cedb53263c2/coverage-7.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f00d5ae1dd2fe13fb8186e3e7d37bcbd8b25c0d764ff7d1b32cef9be058510a8", size = 261714, upload-time = "2026-07-02T13:10:38.966Z" }, + { url = "https://files.pythonhosted.org/packages/b7/eb/fee5c8665656be63f497418d410484637c438172568688e8ac92e06574e7/coverage-7.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:363ab38cc78b615f11c9cac3cf1d7eef950c18b9fdedfb9066f59461dcf84d68", size = 264025, upload-time = "2026-07-02T13:10:40.789Z" }, + { url = "https://files.pythonhosted.org/packages/ab/99/63005db722f91edc81abc16302f9cc2f6228c1679e46e15be9ae144b14d0/coverage-7.15.0-cp314-cp314t-win32.whl", hash = "sha256:54fd9c53a5fafff509195f1b6a3f9be615d8e8362a3629ff1de23d270c03c86b", size = 223413, upload-time = "2026-07-02T13:10:42.597Z" }, + { url = "https://files.pythonhosted.org/packages/c1/e8/2bc6181c4fb06f1a6b981eb85330cc57bfad7e3f710fc9c9d350013ba228/coverage-7.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:87b47553097ba185ed964866078e7e63adea9f5f51b5f39691c34f30afd21080", size = 224245, upload-time = "2026-07-02T13:10:44.47Z" }, + { url = "https://files.pythonhosted.org/packages/79/b8/4d959bf9cc45d0cfed2f4d35cafcab978cdb6ea02eb5100009cd740632a3/coverage-7.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aeefb2dd178fe7eee79f0ad25d75855cb35ee9ed472db2c5ea06f5b4fd00cec5", size = 223558, upload-time = "2026-07-02T13:10:46.368Z" }, + { url = "https://files.pythonhosted.org/packages/52/30/21b2ad45959cd50e909e02ebac1e30b4ceb7162e91c11d4c570223a458b7/coverage-7.15.0-py3-none-any.whl", hash = "sha256:56da6a4cbe8f7e9e80bd072ca9cefe67d7106a440a7ec06519ec6507ac94ad19", size = 212632, upload-time = "2026-07-02T13:10:48.641Z" }, +] + +[[package]] +name = "mise-pypi-tool-environment" +version = "0.0.0" +source = { virtual = "." } +dependencies = [ + { name = "coverage" }, +] + +[package.metadata] +requires-dist = [{ name = "coverage", specifier = "==7.15.0" }] diff --git a/.mise/locks/mise.js/npm-asyncapi-generator/3.5.0~39db1ca7/aube-lock.yaml b/.mise/locks/mise.js/npm-asyncapi-generator/3.5.0~39db1ca7/aube-lock.yaml index e32def16..1f78f93d 100644 --- a/.mise/locks/mise.js/npm-asyncapi-generator/3.5.0~39db1ca7/aube-lock.yaml +++ b/.mise/locks/mise.js/npm-asyncapi-generator/3.5.0~39db1ca7/aube-lock.yaml @@ -107,24 +107,24 @@ packages: resolution: {integrity: sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.29.7': - resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + '@babel/core@7.29.13': + resolution: {integrity: sha512-j1nvOQCZYSgp7HLmisnCXFTpVvFODiijQ9QHkORfGKWH6YDtskTEeCJS7eV545GZ9UBzrq0e2xsOd5QQ5PjIqw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.12': - resolution: {integrity: sha512-2W76mhjrpQFO1lK5e8IvGYB2D0YZ7S2R1Z2BjO2ZUYuW+amcpK/z60U6ZZmzskwoa7sJ6XohP/Wg8H5KxXI/IA==} + '@babel/generator@7.29.13': + resolution: {integrity: sha512-T5FRo+RzVHvGjWOuF1Ljc44b+NXAOazodHkGUHp4I3zCkQ4/sNVJm56h1S278LMR0bY5xBhztGziSbli8zObIw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.29.7': resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.29.7': - resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + '@babel/helper-compilation-targets@7.29.13': + resolution: {integrity: sha512-8WxJ4/Vmes3ghacj8VOJy3NW8eyHiFY/4thU/LSBuBE470+igjR/j1ZTNn8fV5VdNrLx6iXUwig526UdOvfP0w==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.29.12': - resolution: {integrity: sha512-ACxGoWMV866q/QlZHeCOaQZAR5QclKsIvkAmlDemqjm6+6Bynijs1mH068BzH2N2e+wSuDmBWY87fqKfvhi1Lw==} + '@babel/helper-create-class-features-plugin@7.29.13': + resolution: {integrity: sha512-fo8/Fr44/DMV71FQjk/HA0Npmu3bo5DFoWTCW1dhUR8Vx3NFfAVeEy0TbcBpt4e+hd2QhdmWgmspHo/9iWj8RA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -152,8 +152,8 @@ packages: resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.29.7': - resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + '@babel/helper-module-transforms@7.29.13': + resolution: {integrity: sha512-/U96wOz+SCoZ7Da/8kjDGltcNY280JPQcRNPK0Hk3PTbdpaiBDQImtC6JsbVwb1HGMr3usZQU2WsWVjhYNmRzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -178,12 +178,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-skip-transparent-expression-wrappers@7.29.7': - resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} + '@babel/helper-skip-transparent-expression-wrappers@7.29.13': + resolution: {integrity: sha512-Abm4rKIH0tmCayJLwcoeOkdzpYUphTbO52fHhyEBHn7S0R+ni4epNLI/8nq1L0DN2Bl0u5qmgWm2Og/z4fBb+Q==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.29.11': - resolution: {integrity: sha512-snZbO7MEDOof+hvNa97EjEY7qD7h2kwvQr5AJC3ZhQudKW5dnej6k3kP9NQV88hJwaS8vDqRLFo9rivLEhle2g==} + '@babel/helper-string-parser@7.29.13': + resolution: {integrity: sha512-fWegr+WsEsiMVW4KUNdIIzzMTZSzNiqhy0//6+2MRi2d5NFNsL/AYwBQW8eBnRbTBVRnDVzjaJEUqKaCWjMMdQ==} engines: {node: '>=6.9.0'} '@babel/helper-validator-identifier@7.29.7': @@ -198,12 +198,12 @@ packages: resolution: {integrity: sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.29.10': - resolution: {integrity: sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==} + '@babel/helpers@7.29.13': + resolution: {integrity: sha512-laoRpD/kO/iA4CDlgJbixHekg7oPvWALK0PQyK3Ob2I2njZRvVAD77RfWCIImtqWCq6KijoBoZK7bp/HlTWASQ==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.12': - resolution: {integrity: sha512-WJ7JBp/Q4+z/ImydtI7jS6NVco5++632ExBemSX+Ysb+G1lCwQ5BVo3SY+jGGOcZXI4ZccbZSUSJLNBW6eEpJg==} + '@babel/parser@7.29.13': + resolution: {integrity: sha512-fJM50YYjlTiBhgdkGmC1tBpv+FMAyo4annf2X6Aks+0yRlaiVkYW/3f07xAfVVkYIoZ9fFZp+mEThUFnuybhkQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -225,8 +225,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7': - resolution: {integrity: sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==} + '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.13': + resolution: {integrity: sha512-7RpEgFZq9xNRHsWwPLFQpjPOi0ZECE2QZWMBes+vgK7E02krjOfPiYtnHTIUF2nCDyeCJPvSAj0AP4NTVf4hsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -297,8 +297,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.29.12': - resolution: {integrity: sha512-nEreZBofjfd6FG621xe9Rk3+tMGBXf1nAuFrR6NUGF67fkQbSQf3NrbRuhgWRn+zb0qcy9XVok1GVFI/t9wWVQ==} + '@babel/plugin-transform-block-scoping@7.29.13': + resolution: {integrity: sha512-q7f5zYLtDLqO11ydQK1w2RqZ1m5kmcAlmgZlfXssKgqVyL8+HgDvWXMxvuEz8TuJfq1UNsY9sB6ABjjtQkN6wA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -327,8 +327,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.29.7': - resolution: {integrity: sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==} + '@babel/plugin-transform-destructuring@7.29.13': + resolution: {integrity: sha512-X2meXB39NOPPmmshSRJzyd50hX9uCzbscNQwVCjLCtq363PZIJFFxJIeZPpgAewC570vpdeGIHTcltwd0QUlJg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -375,8 +375,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-for-of@7.29.7': - resolution: {integrity: sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==} + '@babel/plugin-transform-for-of@7.29.13': + resolution: {integrity: sha512-dFjiIw+xBYpgLhYDc1QFQOZmMX44se0YCmXUjPsm9SQEj9HaCJAjvVnK6/yK9iE4E1LaKU5fIAKVJPZWCbKwXw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -624,8 +624,8 @@ packages: resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.12': - resolution: {integrity: sha512-MscXe/NAZcOkYEsRajHZFt3ynsb22PUi6CTrp5U7+RYycR9By84mn9mFN54YgfITiqK4hFx3Ju3tZSyzfpS5ew==} + '@babel/traverse@7.29.13': + resolution: {integrity: sha512-0ve0xMlFA73dgY1oyJRY6RoW+/bncdcOQqg6jjYcVfXBK90OdLXjm9R6lmRetdZVrPjXkKIoMVBqYFPjcAlZ4Q==} engines: {node: '>=6.9.0'} '@babel/types@7.29.11': @@ -881,16 +881,16 @@ packages: resolution: {integrity: sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==} engines: {node: '>=8'} - '@stoplight/spectral-core@1.24.0': - resolution: {integrity: sha512-abKt++GFFaqwKiGTfPZ5O3nIv8s+1V7J5awCjWPBtCXn7ZKTEPzEF8tBYsM3ne+RMrQ8ORkHzKFu9QZhenmkPw==} + '@stoplight/spectral-core@1.24.1': + resolution: {integrity: sha512-Q1i41CoYtzdRoxGkVH0arhv9jSNkByU/TbJ77CHMXvtgbLCTUMVCbB6W9IEIu+NndESki1tnJzt59SPifB9NWQ==} engines: {node: ^16.20 || ^18.18 || >= 20.17} '@stoplight/spectral-formats@1.9.0': resolution: {integrity: sha512-OmHZpeBdlWbDxAI43HR08vyVXY2D++YHBx9AWMQ6S2DH8aWWCvk64BJOJk161XsHJQuy/vnC8tRBIIKwSQPAsA==} engines: {node: ^16.20 || ^18.18 || >= 20.17} - '@stoplight/spectral-functions@1.11.0': - resolution: {integrity: sha512-HFlFhI+q13GqG8pphY4nNGYq9+5L14dhR9xLqx+/H2/FmAouHTfNaqE4SygIhSmtMxfNDJ8G4qnjxiQRv1kPWA==} + '@stoplight/spectral-functions@1.11.1': + resolution: {integrity: sha512-YfNXX+BKLUpMfx2tL876IJY7VHRfWfpiUmb0rseUTUzoh6ucLZLRiQIWLLkOueYz6uO1l0wE6JlVsn5VXftp9Q==} engines: {node: ^16.20 || ^18.18 || >= 20.17} '@stoplight/spectral-parsers@1.0.5': @@ -1027,8 +1027,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.5.0: - resolution: {integrity: sha512-zhvbbbdt1kbw7EJ9OQoxmQcuaNR9P5kTj7e/YdmOSU10aHWbycofJxA6jKfoEy3vlLdctOF9ZHaxLtmSm998wQ==} + ansi-regex@6.6.0: + resolution: {integrity: sha512-XZ5apbzreCbXSKwPjJstu8R0zOi247w3XYwWxtwBXgpZrCyc1Ka7p9/xY0A9/diMewmHbEKz+FIraWaEWjlN5g==} engines: {node: '>=12'} ansi-styles@4.3.0: @@ -1100,8 +1100,8 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - baseline-browser-mapping@2.11.34: - resolution: {integrity: sha512-Aqr8mA1kIvyJ3UY5YAY7ib8LSo1DmDMbMnVqGPtsKW1LxaFQFwn9Eb3yvq2fUKJsRvaXjnAV7R5osqETapzNiA==} + baseline-browser-mapping@2.11.35: + resolution: {integrity: sha512-GNk8KX52CHqeNKGk8+7tZnQab/2k1t/BgrUHPKNdijzpEhF1saPQZHVKb6m5loSAxB39gyrTYw34Qf9CQ3u1qQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -1149,8 +1149,8 @@ packages: camel-case@4.1.2: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - caniuse-lite@1.0.30001820: - resolution: {integrity: sha512-gfWD6MxqVCqAOwmODfZf7DchWvlrA+SRdNX7ceLfg3xRqe5ssjjpF7EgslC/0tiLiNTajdaNN/q8c/5u/7Gz8w==} + caniuse-lite@1.0.30001823: + resolution: {integrity: sha512-TQ5s/djDjNk1axreUW+4rULH+BmdCMLiJkhaXnO5wqivG7tITkSUj4ItIdzqdZHKaXcHAV8dhH3JxOM7/7bwqw==} capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} @@ -1162,8 +1162,8 @@ packages: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} - ci-info@4.4.0: - resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + ci-info@4.5.0: + resolution: {integrity: sha512-d1uM8k5UZEyPza1n/MG3ko8nKupKN0KJpFsipgPcgaCCvV+IqIfJ+NzTjetlLM+UcXZx3+cLrNr76+eAO7G1Mw==} engines: {node: '>=8'} cliui@8.0.1: @@ -1228,11 +1228,6 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -1284,8 +1279,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.472: - resolution: {integrity: sha512-s4+nfT29b0FKpVKoaIxl2pWsoNcn7A/nMPSrxayw4T3BsmPeV2lF9Y06BsAQeMGhCTQ4nYJ5XST7jkqe4ZEqFw==} + electron-to-chromium@1.5.478: + resolution: {integrity: sha512-pftG+ma5Lm8O6/p45bhYT6StBN5ziQymaRzmCZwFl8DwWHKPPD93FdOmP1aqftcepolQYvrcyTLa17kE8Yf+jg==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1380,8 +1375,8 @@ packages: fast-xml-builder@1.3.1: resolution: {integrity: sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==} - fast-xml-parser@5.11.2: - resolution: {integrity: sha512-R9iDuNrQYeQut46cn2r2wHKn4HYzVDvDm5J1wW+koZewykv0yuO2HChTYeZtrULyHIDM9cj9TUXloCsueCQUog==} + fast-xml-parser@5.12.0: + resolution: {integrity: sha512-/pXxRBtwxY9w8z7YbgsvIPPcPvFDsTbIkWwTQJhzNJPokj+TbN6ftmcv4j/pEQDvOCNnKGDzuk5Bo2oogIOiFg==} hasBin: true fastest-stable-stringify@2.0.2: @@ -1472,8 +1467,8 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true - glob@13.0.6: - resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + glob@13.0.7: + resolution: {integrity: sha512-wfsFgXQ8A3SEI9XGf7Nl3Y9l7ffSrGh7SUCT7vU/2CzYPep9kjxAn1S40F9OPKxAMGCVl7HtNlJhrCJUeUq83g==} engines: {node: 18 || 20 || >=22} glob@7.2.3: @@ -1577,8 +1572,8 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - ip-address@10.7.5: - resolution: {integrity: sha512-t2v0rkILYv9WXmSL7TpAaU3HXgaFYOPUcH3QHgwQ++gpJuH3bqyMy4Fvt/DJCTKwzH3Cf+bAp5W/mFL39KPLzA==} + ip-address@10.7.6: + resolution: {integrity: sha512-00LYkM6byILa9eQIx6qoaXCM40xTLd56AZ4vyaPW3YTyb49VZYPo5xsiAq4tuQ54GH4R7gVdYScJ1B7B77PuTg==} engines: {node: '>= 12'} is-array-buffer@3.0.5: @@ -1601,8 +1596,8 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.17.0: - resolution: {integrity: sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==} + is-core-module@2.18.0: + resolution: {integrity: sha512-qyax9fgaKOEC4qK8WZn7Q4IcoZC9RC1O1fFxRcRTq/oMMkWT/uXpqpXa12kzWR409zAt1drYN9N9BO26UmBCmw==} engines: {node: '>= 0.4'} is-data-view@1.0.2: @@ -1665,8 +1660,8 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} - is-unsafe@2.0.2: - resolution: {integrity: sha512-HgbIHPBH0KHHCcjLfGsCvhtPTVxjaAZlXjwdz7/GQC40SjSe4sfQsar8J5VFo8JOSbarkpV0OLG95bbaNd9aAQ==} + is-unsafe@2.0.3: + resolution: {integrity: sha512-ZBllczCCO267vgdFb6Tq3pv+LhHaCiGMdr+ZsuL+OopruAg7S+3ZDs1vD0RPC0uSrkjzbraxaGjtX1YBxjPeFQ==} is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} @@ -2038,8 +2033,8 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - pacote@21.5.2: - resolution: {integrity: sha512-rifBXawDMv3nLvABWr1kTpSk0UjeglTT4Vt9t8nU9xSnfdZcCTy+FOjO6TgXWAS77lIfbZlRkl2eKQcdY0++jA==} + pacote@21.5.3: + resolution: {integrity: sha512-XAHnxRzERPW/Y3sLaCgfUVdfP5Di1K0wiUWsDaK4reodu20Kl0pVZcw8Mdd2LaLsUpot6YLVOEgmIqMEL9Tjog==} engines: {node: ^20.17.0 || >=22.9.0} hasBin: true @@ -2109,8 +2104,8 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss-selector-parser@7.1.7: - resolution: {integrity: sha512-wWBro/7hJ40ye6TPiXkUQoXKCw23xSsjriUvqd7Uls9Sso3oLiON1flc18cCdnjgCRXw4fBVqUJJeOdDTh3P3g==} + postcss-selector-parser@7.2.0: + resolution: {integrity: sha512-Khh/tERVBn0I1499dvBSHY0pWJloMJWUxDsOBM0CCDPAcVZ10Jl2L1qy1f19uEX22spa8Mv7DCdEQJc0cGwBhQ==} engines: {node: '>=4'} proc-log@4.2.0: @@ -2190,15 +2185,15 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} - regexpu-core@6.5.3: - resolution: {integrity: sha512-E8VgUoSK+LMQrLboDxavm76MTBGrQhx9RiNuomRmYnZ10Uw12HrI8fkxOOncktb2hBpzIZ9SV/347euQHG5z+g==} + regexpu-core@6.5.4: + resolution: {integrity: sha512-VpdamrZ9bw4YmvMZfTA3Yg8IHU9Guvg21bonvgjC4l3KfBkOqCPJesHakz7cQeE4Vh4zz4r4Gy6igAcnJxZv9g==} engines: {node: '>=4'} regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - regjsparser@0.13.4: - resolution: {integrity: sha512-EWV80YgFaVgFrjGCAsV7oybp4GOxbls5RzBg8OB0nKEVXsBJR1JlV8Di1JhCROg3MzTfe1RI8yitIm1eOs68iA==} + regjsparser@0.14.1: + resolution: {integrity: sha512-IeYboCLG1KBNRksrZQIZ1SV5KVWZiR0ikFokOcA0n63vLvlaFvCsfxN+fd4aXwL0KW3YD+ByRzIgo9ZAHdbldw==} hasBin: true require-directory@2.1.1: @@ -2221,8 +2216,8 @@ packages: resolution: {integrity: sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ==} engines: {node: '>=8'} - resolve@1.22.13: - resolution: {integrity: sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==} + resolve@1.22.14: + resolution: {integrity: sha512-1ZjYvR9sbkiwC5+9QHetqW5HmA2pHRMaoupD01t2HlYnV/vydC2zPwLixhsMieSWVZt0JJRg5LVIk0Ow1D/TrA==} engines: {node: '>= 0.4'} hasBin: true @@ -2265,16 +2260,16 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + semver@5.7.3: + resolution: {integrity: sha512-kM18BPOqTi0+TB68703/GJRpAML5Me+IDQsR1J26YB3EFKKNEyHIVZuWDX7+WKQB3tHwDwgk24BfhdpWUbytvQ==} hasBin: true - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + semver@6.3.2: + resolution: {integrity: sha512-GYrCADwpu6yV5OAvchkQ27Z5wwMxWAEMg5NNWjyHh/5DboFFqbdbvYNIvZouQpxXyeMPoTOh0vdPYKlf0ZswdQ==} hasBin: true - semver@7.8.5: - resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + semver@7.8.6: + resolution: {integrity: sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==} engines: {node: '>=10'} hasBin: true @@ -2776,7 +2771,7 @@ snapshots: requireg: 0.2.2 resolve-from: 5.0.0 resolve-pkg: 2.0.0 - semver: 7.8.5 + semver: 7.8.6 simple-git: 3.36.0 ts-node: 10.9.2(@types/node@26.6.6)(typescript@4.9.5) typescript: 4.9.5 @@ -2796,7 +2791,7 @@ snapshots: '@asyncapi/parser': 3.6.6 alterschema: 1.1.3 change-case: 4.1.2 - fast-xml-parser: 5.11.2 + fast-xml-parser: 5.12.0 js-yaml: 4.3.2 openapi-types: 12.1.3 typescript-json-schema: 0.58.1 @@ -2832,8 +2827,8 @@ snapshots: '@stoplight/json': 3.21.0 '@stoplight/json-ref-readers': 1.2.2 '@stoplight/json-ref-resolver': 3.1.6 - '@stoplight/spectral-core': 1.24.0 - '@stoplight/spectral-functions': 1.11.0 + '@stoplight/spectral-core': 1.24.1 + '@stoplight/spectral-functions': 1.11.1 '@stoplight/spectral-parsers': 1.0.5 '@stoplight/spectral-ref-resolver': 1.0.5 '@stoplight/types': 13.20.0 @@ -2875,12 +2870,12 @@ snapshots: '@babel/core@7.12.9': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.12 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) - '@babel/helpers': 7.29.10 - '@babel/parser': 7.29.12 + '@babel/generator': 7.29.13 + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) + '@babel/helpers': 7.29.13 + '@babel/parser': 7.29.13 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 convert-source-map: 1.9.0 debug: 4.4.3 @@ -2888,34 +2883,34 @@ snapshots: json5: 2.2.3 lodash: 4.18.1 resolve: 1.7.1 - semver: 5.7.2 + semver: 5.7.3 source-map: 0.5.7 transitivePeerDependencies: - supports-color - '@babel/core@7.29.7': + '@babel/core@7.29.13': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.12 - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) - '@babel/helpers': 7.29.10 - '@babel/parser': 7.29.12 + '@babel/generator': 7.29.13 + '@babel/helper-compilation-targets': 7.29.13 + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.29.13) + '@babel/helpers': 7.29.13 + '@babel/parser': 7.29.13 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 - semver: 6.3.1 + semver: 6.3.2 transitivePeerDependencies: - supports-color - '@babel/generator@7.29.12': + '@babel/generator@7.29.13': dependencies: - '@babel/parser': 7.29.12 + '@babel/parser': 7.29.13 '@babel/types': 7.29.11 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 @@ -2925,24 +2920,24 @@ snapshots: dependencies: '@babel/types': 7.29.11 - '@babel/helper-compilation-targets@7.29.7': + '@babel/helper-compilation-targets@7.29.13': dependencies: '@babel/compat-data': 7.29.7 '@babel/helper-validator-option': 7.29.7 browserslist: 4.29.5 lru-cache: 5.1.1 - semver: 6.3.1 + semver: 6.3.2 - '@babel/helper-create-class-features-plugin@7.29.12(@babel/core@7.12.9)': + '@babel/helper-create-class-features-plugin@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-member-expression-to-functions': 7.29.7 '@babel/helper-optimise-call-expression': 7.29.7 '@babel/helper-replace-supers': 7.29.7(@babel/core@7.12.9) - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 - '@babel/traverse': 7.29.12 - semver: 6.3.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 + '@babel/traverse': 7.29.13 + semver: 6.3.2 transitivePeerDependencies: - supports-color @@ -2950,17 +2945,17 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 - regexpu-core: 6.5.3 - semver: 6.3.1 + regexpu-core: 6.5.4 + semver: 6.3.2 '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 debug: 4.4.3 lodash.debounce: 4.0.8 - resolve: 1.22.13 + resolve: 1.22.14 transitivePeerDependencies: - supports-color @@ -2968,33 +2963,33 @@ snapshots: '@babel/helper-member-expression-to-functions@7.29.7': dependencies: - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.29.7': dependencies: - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.12.9)': + '@babel/helper-module-transforms@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + '@babel/helper-module-transforms@7.29.13(@babel/core@7.29.13)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.13 '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -3009,7 +3004,7 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-wrap-function': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -3018,18 +3013,18 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-member-expression-to-functions': 7.29.7 '@babel/helper-optimise-call-expression': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color - '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + '@babel/helper-skip-transparent-expression-wrappers@7.29.13': dependencies: - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 transitivePeerDependencies: - supports-color - '@babel/helper-string-parser@7.29.11': {} + '@babel/helper-string-parser@7.29.13': {} '@babel/helper-validator-identifier@7.29.7': {} @@ -3038,17 +3033,17 @@ snapshots: '@babel/helper-wrap-function@7.29.7': dependencies: '@babel/template': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 transitivePeerDependencies: - supports-color - '@babel/helpers@7.29.10': + '@babel/helpers@7.29.13': dependencies: '@babel/template': 7.29.7 '@babel/types': 7.29.11 - '@babel/parser@7.29.12': + '@babel/parser@7.29.13': dependencies: '@babel/types': 7.29.11 @@ -3056,7 +3051,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -3070,20 +3065,20 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7(@babel/core@7.12.9)': + '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7(@babel/core@7.29.13)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 - '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7) + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.13) transitivePeerDependencies: - supports-color @@ -3091,7 +3086,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -3130,7 +3125,7 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.12.9) - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -3148,7 +3143,7 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-block-scoping@7.29.12(@babel/core@7.12.9)': + '@babel/plugin-transform-block-scoping@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 @@ -3156,7 +3151,7 @@ snapshots: '@babel/plugin-transform-class-properties@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-create-class-features-plugin': 7.29.12(@babel/core@7.12.9) + '@babel/helper-create-class-features-plugin': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -3164,7 +3159,7 @@ snapshots: '@babel/plugin-transform-class-static-block@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-create-class-features-plugin': 7.29.12(@babel/core@7.12.9) + '@babel/helper-create-class-features-plugin': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -3173,11 +3168,11 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-globals': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-replace-supers': 7.29.7(@babel/core@7.12.9) - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -3187,11 +3182,11 @@ snapshots: '@babel/helper-plugin-utils': 7.29.7 '@babel/template': 7.29.7 - '@babel/plugin-transform-destructuring@7.29.7(@babel/core@7.12.9)': + '@babel/plugin-transform-destructuring@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -3221,7 +3216,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.12.9) + '@babel/plugin-transform-destructuring': 7.29.13(@babel/core@7.12.9) transitivePeerDependencies: - supports-color @@ -3235,20 +3230,20 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-for-of@7.29.7(@babel/core@7.12.9)': + '@babel/plugin-transform-for-of@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color '@babel/plugin-transform-function-name@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -3275,7 +3270,7 @@ snapshots: '@babel/plugin-transform-modules-amd@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -3283,7 +3278,7 @@ snapshots: '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -3291,17 +3286,17 @@ snapshots: '@babel/plugin-transform-modules-systemjs@7.29.8(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color '@babel/plugin-transform-modules-umd@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -3330,11 +3325,11 @@ snapshots: '@babel/plugin-transform-object-rest-spread@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.12.9) + '@babel/plugin-transform-destructuring': 7.29.13(@babel/core@7.12.9) '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.12.9) - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -3355,15 +3350,15 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.13)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color @@ -3375,7 +3370,7 @@ snapshots: '@babel/plugin-transform-private-methods@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-create-class-features-plugin': 7.29.12(@babel/core@7.12.9) + '@babel/helper-create-class-features-plugin': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -3384,7 +3379,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.12(@babel/core@7.12.9) + '@babel/helper-create-class-features-plugin': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -3448,7 +3443,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color @@ -3494,14 +3489,14 @@ snapshots: dependencies: '@babel/compat-data': 7.29.7 '@babel/core': 7.12.9 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-option': 7.29.7 '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.29.7(@babel/core@7.12.9) '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.29.7(@babel/core@7.12.9) '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array': 7.29.13(@babel/core@7.12.9) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.29.7(@babel/core@7.29.13) '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.29.7(@babel/core@7.12.9) '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.12.9) '@babel/plugin-syntax-import-assertions': 7.29.7(@babel/core@7.12.9) @@ -3511,12 +3506,12 @@ snapshots: '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-block-scoped-functions': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-transform-block-scoping': 7.29.12(@babel/core@7.12.9) + '@babel/plugin-transform-block-scoping': 7.29.13(@babel/core@7.12.9) '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-class-static-block': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-classes': 7.29.11(@babel/core@7.12.9) '@babel/plugin-transform-computed-properties': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.12.9) + '@babel/plugin-transform-destructuring': 7.29.13(@babel/core@7.12.9) '@babel/plugin-transform-dotall-regex': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-duplicate-keys': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.7(@babel/core@7.12.9) @@ -3524,7 +3519,7 @@ snapshots: '@babel/plugin-transform-explicit-resource-management': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-exponentiation-operator': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-export-namespace-from': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.12.9) + '@babel/plugin-transform-for-of': 7.29.13(@babel/core@7.12.9) '@babel/plugin-transform-function-name': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-json-strings': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-literals': 7.29.7(@babel/core@7.12.9) @@ -3563,7 +3558,7 @@ snapshots: babel-plugin-polyfill-corejs3: 0.14.2(@babel/core@7.12.9) babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.12.9) core-js-compat: 3.51.0 - semver: 6.3.1 + semver: 6.3.2 transitivePeerDependencies: - supports-color @@ -3589,15 +3584,15 @@ snapshots: '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.12 + '@babel/parser': 7.29.13 '@babel/types': 7.29.11 - '@babel/traverse@7.29.12': + '@babel/traverse@7.29.13': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.12 + '@babel/generator': 7.29.13 '@babel/helper-globals': 7.29.7 - '@babel/parser': 7.29.12 + '@babel/parser': 7.29.13 '@babel/template': 7.29.7 '@babel/types': 7.29.11 debug: 4.4.3 @@ -3606,7 +3601,7 @@ snapshots: '@babel/types@7.29.11': dependencies: - '@babel/helper-string-parser': 7.29.11 + '@babel/helper-string-parser': 7.29.13 '@babel/helper-validator-identifier': 7.29.7 '@cspotcode/source-map-support@0.8.1': @@ -3747,13 +3742,13 @@ snapshots: npm-package-arg: 13.0.2 npm-pick-manifest: 11.0.3 npm-registry-fetch: 19.1.1 - pacote: 21.5.2 + pacote: 21.5.3 parse-conflict-json: 5.0.1 proc-log: 6.1.0 proggy: 4.0.0 promise-all-reject-late: 1.0.1 promise-call-limit: 3.0.2 - semver: 7.8.5 + semver: 7.8.6 ssri: 13.0.1 treeverse: 3.0.0 walk-up-path: 4.0.0 @@ -3764,16 +3759,16 @@ snapshots: dependencies: '@npmcli/map-workspaces': 3.0.6 '@npmcli/package-json': 5.2.1 - ci-info: 4.4.0 + ci-info: 4.5.0 ini: 4.1.3 nopt: 7.2.1 proc-log: 4.2.0 - semver: 7.8.5 + semver: 7.8.6 walk-up-path: 3.0.1 '@npmcli/fs@5.0.0': dependencies: - semver: 7.8.5 + semver: 7.8.6 '@npmcli/git@5.0.8': dependencies: @@ -3784,7 +3779,7 @@ snapshots: proc-log: 4.2.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.8.5 + semver: 7.8.6 which: 4.0.0 '@npmcli/git@7.0.2': @@ -3795,7 +3790,7 @@ snapshots: lru-cache: 11.5.3 npm-pick-manifest: 11.0.3 proc-log: 6.1.0 - semver: 7.8.5 + semver: 7.8.6 which: 6.0.1 '@npmcli/installed-package-contents@4.0.0': @@ -3814,16 +3809,16 @@ snapshots: dependencies: '@npmcli/name-from-folder': 4.0.0 '@npmcli/package-json': 7.0.5 - glob: 13.0.6 + glob: 13.0.7 minimatch: 10.2.6 '@npmcli/metavuln-calculator@9.0.3': dependencies: cacache: 20.0.4 json-parse-even-better-errors: 5.0.0 - pacote: 21.5.2 + pacote: 21.5.3 proc-log: 6.1.0 - semver: 7.8.5 + semver: 7.8.6 transitivePeerDependencies: - supports-color @@ -3841,16 +3836,16 @@ snapshots: json-parse-even-better-errors: 3.0.2 normalize-package-data: 6.0.2 proc-log: 4.2.0 - semver: 7.8.5 + semver: 7.8.6 '@npmcli/package-json@7.0.5': dependencies: '@npmcli/git': 7.0.2 - glob: 13.0.6 + glob: 13.0.7 hosted-git-info: 9.0.3 json-parse-even-better-errors: 5.0.0 proc-log: 6.1.0 - semver: 7.8.5 + semver: 7.8.6 spdx-expression-parse: 4.0.0 '@npmcli/promise-spawn@7.0.2': @@ -3863,7 +3858,7 @@ snapshots: '@npmcli/query@5.0.0': dependencies: - postcss-selector-parser: 7.1.7 + postcss-selector-parser: 7.2.0 '@npmcli/redact@4.0.0': {} @@ -3977,7 +3972,7 @@ snapshots: '@stoplight/path@1.3.2': {} - '@stoplight/spectral-core@1.24.0': + '@stoplight/spectral-core@1.24.1': dependencies: '@scarf/scarf': 1.4.0 '@stoplight/better-ajv-errors': 1.0.3(ajv@8.20.0) @@ -4008,18 +4003,18 @@ snapshots: dependencies: '@scarf/scarf': 1.4.0 '@stoplight/json': 3.21.0 - '@stoplight/spectral-core': 1.24.0 + '@stoplight/spectral-core': 1.24.1 '@types/json-schema': 7.0.15 tslib: 2.9.1 transitivePeerDependencies: - encoding - '@stoplight/spectral-functions@1.11.0': + '@stoplight/spectral-functions@1.11.1': dependencies: '@scarf/scarf': 1.4.0 '@stoplight/better-ajv-errors': 1.0.3(ajv@8.20.0) '@stoplight/json': 3.21.0 - '@stoplight/spectral-core': 1.24.0 + '@stoplight/spectral-core': 1.24.1 '@stoplight/spectral-formats': 1.9.0 '@stoplight/spectral-runtime': 1.1.6 ajv: 8.20.0 @@ -4176,7 +4171,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.5.0: {} + ansi-regex@6.6.0: {} ansi-styles@4.3.0: dependencies: @@ -4224,7 +4219,7 @@ snapshots: '@babel/compat-data': 7.29.7 '@babel/core': 7.12.9 '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.12.9) - semver: 6.3.1 + semver: 6.3.2 transitivePeerDependencies: - supports-color @@ -4253,7 +4248,7 @@ snapshots: balanced-match@4.0.4: {} - baseline-browser-mapping@2.11.34: {} + baseline-browser-mapping@2.11.35: {} bin-links@6.0.3: dependencies: @@ -4278,9 +4273,9 @@ snapshots: browserslist@4.29.5: dependencies: - baseline-browser-mapping: 2.11.34 - caniuse-lite: 1.0.30001820 - electron-to-chromium: 1.5.472 + baseline-browser-mapping: 2.11.35 + caniuse-lite: 1.0.30001823 + electron-to-chromium: 1.5.478 node-releases: 2.0.63 update-browserslist-db: 1.3.4(browserslist@4.29.5) @@ -4290,7 +4285,7 @@ snapshots: dependencies: '@npmcli/fs': 5.0.0 fs-minipass: 3.0.3 - glob: 13.0.6 + glob: 13.0.7 lru-cache: 11.5.3 minipass: 7.1.3 minipass-collect: 2.0.1 @@ -4323,7 +4318,7 @@ snapshots: pascal-case: 3.1.2 tslib: 2.9.1 - caniuse-lite@1.0.30001820: {} + caniuse-lite@1.0.30001823: {} capital-case@1.0.4: dependencies: @@ -4348,7 +4343,7 @@ snapshots: chownr@3.0.0: {} - ci-info@4.4.0: {} + ci-info@4.5.0: {} cliui@8.0.1: dependencies: @@ -4400,8 +4395,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - cssesc@3.0.0: {} - data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -4455,7 +4448,7 @@ snapshots: eastasianwidth@0.2.0: {} - electron-to-chromium@1.5.472: {} + electron-to-chromium@1.5.478: {} emoji-regex@8.0.0: {} @@ -4595,11 +4588,11 @@ snapshots: path-expression-matcher: 1.6.2 xml-naming: 0.3.0 - fast-xml-parser@5.11.2: + fast-xml-parser@5.12.0: dependencies: '@nodable/entities': 3.1.0 fast-xml-builder: 1.3.1 - is-unsafe: 2.0.2 + is-unsafe: 2.0.3 path-expression-matcher: 1.6.2 strnum: 2.5.1 xml-naming: 0.3.0 @@ -4706,7 +4699,7 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@13.0.6: + glob@13.0.7: dependencies: minimatch: 10.2.6 minipass: 7.1.3 @@ -4815,7 +4808,7 @@ snapshots: hasown: 2.0.4 side-channel: 1.1.1 - ip-address@10.7.5: {} + ip-address@10.7.6: {} is-array-buffer@3.0.5: dependencies: @@ -4842,7 +4835,7 @@ snapshots: is-callable@1.2.7: {} - is-core-module@2.17.0: + is-core-module@2.18.0: dependencies: hasown: 2.0.4 @@ -4912,7 +4905,7 @@ snapshots: dependencies: which-typed-array: 1.1.24 - is-unsafe@2.0.2: {} + is-unsafe@2.0.3: {} is-weakmap@2.0.2: {} @@ -5148,7 +5141,7 @@ snapshots: graceful-fs: 4.2.11 nopt: 9.0.0 proc-log: 6.1.0 - semver: 7.8.5 + semver: 7.8.6 tar: 7.5.22 tinyglobby: 0.2.17 undici: 6.29.1 @@ -5167,7 +5160,7 @@ snapshots: normalize-package-data@6.0.2: dependencies: hosted-git-info: 7.0.2 - semver: 7.8.5 + semver: 7.8.6 validate-npm-package-license: 3.0.4 npm-bundled@5.0.0: @@ -5176,11 +5169,11 @@ snapshots: npm-install-checks@6.3.0: dependencies: - semver: 7.8.5 + semver: 7.8.6 npm-install-checks@8.0.0: dependencies: - semver: 7.8.5 + semver: 7.8.6 npm-normalize-package-bin@3.0.1: {} @@ -5190,14 +5183,14 @@ snapshots: dependencies: hosted-git-info: 7.0.2 proc-log: 4.2.0 - semver: 7.8.5 + semver: 7.8.6 validate-npm-package-name: 5.0.1 npm-package-arg@13.0.2: dependencies: hosted-git-info: 9.0.3 proc-log: 6.1.0 - semver: 7.8.5 + semver: 7.8.6 validate-npm-package-name: 7.0.2 npm-packlist@10.0.4: @@ -5210,14 +5203,14 @@ snapshots: npm-install-checks: 8.0.0 npm-normalize-package-bin: 5.0.0 npm-package-arg: 13.0.2 - semver: 7.8.5 + semver: 7.8.6 npm-pick-manifest@9.1.0: dependencies: npm-install-checks: 6.3.0 npm-normalize-package-bin: 3.0.1 npm-package-arg: 11.0.3 - semver: 7.8.5 + semver: 7.8.6 npm-registry-fetch@19.1.1: dependencies: @@ -5266,7 +5259,7 @@ snapshots: package-json-from-dist@1.0.1: {} - pacote@21.5.2: + pacote@21.5.3: dependencies: '@gar/promise-retry': 1.0.3 '@npmcli/git': 7.0.2 @@ -5306,8 +5299,8 @@ snapshots: '@stoplight/json': 3.21.0 '@stoplight/json-ref-readers': 1.2.2 '@stoplight/json-ref-resolver': 3.1.6 - '@stoplight/spectral-core': 1.24.0 - '@stoplight/spectral-functions': 1.11.0 + '@stoplight/spectral-core': 1.24.1 + '@stoplight/spectral-functions': 1.11.1 '@stoplight/spectral-parsers': 1.0.5 '@stoplight/spectral-ref-resolver': 1.0.5 '@stoplight/types': 13.20.0 @@ -5328,8 +5321,8 @@ snapshots: '@asyncapi/specs': 6.11.1 '@openapi-contrib/openapi-schema-to-json-schema': 3.2.0 '@stoplight/json-ref-resolver': 3.1.6 - '@stoplight/spectral-core': 1.24.0 - '@stoplight/spectral-functions': 1.11.0 + '@stoplight/spectral-core': 1.24.1 + '@stoplight/spectral-functions': 1.11.1 '@stoplight/spectral-parsers': 1.0.5 '@types/json-schema': 7.0.15 '@types/urijs': 1.19.26 @@ -5385,9 +5378,8 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-selector-parser@7.1.7: + postcss-selector-parser@7.2.0: dependencies: - cssesc: 3.0.0 util-deprecate: 1.0.2 proc-log@4.2.0: {} @@ -5475,18 +5467,18 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 - regexpu-core@6.5.3: + regexpu-core@6.5.4: dependencies: regenerate: 1.5.0 regenerate-unicode-properties: 10.3.0 regjsgen: 0.8.0 - regjsparser: 0.13.4 + regjsparser: 0.14.1 unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.2.1 regjsgen@0.8.0: {} - regjsparser@0.13.4: + regjsparser@0.14.1: dependencies: jsesc: 3.1.0 @@ -5506,10 +5498,10 @@ snapshots: dependencies: resolve-from: 5.0.0 - resolve@1.22.13: + resolve@1.22.14: dependencies: es-errors: 1.3.0 - is-core-module: 2.17.0 + is-core-module: 2.18.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -5551,11 +5543,11 @@ snapshots: safer-buffer@2.1.2: optional: true - semver@5.7.2: {} + semver@5.7.3: {} - semver@6.3.1: {} + semver@6.3.2: {} - semver@7.8.5: {} + semver@7.8.6: {} sentence-case@3.0.4: dependencies: @@ -5659,7 +5651,7 @@ snapshots: socks@2.8.10: dependencies: - ip-address: 10.7.5 + ip-address: 10.7.6 smart-buffer: 4.2.0 source-map-support@0.5.21: @@ -5753,7 +5745,7 @@ snapshots: strip-ansi@7.2.0: dependencies: - ansi-regex: 6.5.0 + ansi-regex: 6.6.0 strip-json-comments@2.0.1: {} diff --git a/.mise/locks/mise.js/npm-asyncapi-markdown-template/2.0.0~34f72aac/aube-lock.yaml b/.mise/locks/mise.js/npm-asyncapi-markdown-template/2.0.0~34f72aac/aube-lock.yaml index 614a1b69..e173c02e 100644 --- a/.mise/locks/mise.js/npm-asyncapi-markdown-template/2.0.0~34f72aac/aube-lock.yaml +++ b/.mise/locks/mise.js/npm-asyncapi-markdown-template/2.0.0~34f72aac/aube-lock.yaml @@ -38,24 +38,24 @@ packages: resolution: {integrity: sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.29.7': - resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + '@babel/core@7.29.13': + resolution: {integrity: sha512-j1nvOQCZYSgp7HLmisnCXFTpVvFODiijQ9QHkORfGKWH6YDtskTEeCJS7eV545GZ9UBzrq0e2xsOd5QQ5PjIqw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.12': - resolution: {integrity: sha512-2W76mhjrpQFO1lK5e8IvGYB2D0YZ7S2R1Z2BjO2ZUYuW+amcpK/z60U6ZZmzskwoa7sJ6XohP/Wg8H5KxXI/IA==} + '@babel/generator@7.29.13': + resolution: {integrity: sha512-T5FRo+RzVHvGjWOuF1Ljc44b+NXAOazodHkGUHp4I3zCkQ4/sNVJm56h1S278LMR0bY5xBhztGziSbli8zObIw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.29.7': resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.29.7': - resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + '@babel/helper-compilation-targets@7.29.13': + resolution: {integrity: sha512-8WxJ4/Vmes3ghacj8VOJy3NW8eyHiFY/4thU/LSBuBE470+igjR/j1ZTNn8fV5VdNrLx6iXUwig526UdOvfP0w==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.29.12': - resolution: {integrity: sha512-ACxGoWMV866q/QlZHeCOaQZAR5QclKsIvkAmlDemqjm6+6Bynijs1mH068BzH2N2e+wSuDmBWY87fqKfvhi1Lw==} + '@babel/helper-create-class-features-plugin@7.29.13': + resolution: {integrity: sha512-fo8/Fr44/DMV71FQjk/HA0Npmu3bo5DFoWTCW1dhUR8Vx3NFfAVeEy0TbcBpt4e+hd2QhdmWgmspHo/9iWj8RA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -83,8 +83,8 @@ packages: resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.29.7': - resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + '@babel/helper-module-transforms@7.29.13': + resolution: {integrity: sha512-/U96wOz+SCoZ7Da/8kjDGltcNY280JPQcRNPK0Hk3PTbdpaiBDQImtC6JsbVwb1HGMr3usZQU2WsWVjhYNmRzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -109,12 +109,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-skip-transparent-expression-wrappers@7.29.7': - resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} + '@babel/helper-skip-transparent-expression-wrappers@7.29.13': + resolution: {integrity: sha512-Abm4rKIH0tmCayJLwcoeOkdzpYUphTbO52fHhyEBHn7S0R+ni4epNLI/8nq1L0DN2Bl0u5qmgWm2Og/z4fBb+Q==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.29.11': - resolution: {integrity: sha512-snZbO7MEDOof+hvNa97EjEY7qD7h2kwvQr5AJC3ZhQudKW5dnej6k3kP9NQV88hJwaS8vDqRLFo9rivLEhle2g==} + '@babel/helper-string-parser@7.29.13': + resolution: {integrity: sha512-fWegr+WsEsiMVW4KUNdIIzzMTZSzNiqhy0//6+2MRi2d5NFNsL/AYwBQW8eBnRbTBVRnDVzjaJEUqKaCWjMMdQ==} engines: {node: '>=6.9.0'} '@babel/helper-validator-identifier@7.29.7': @@ -129,12 +129,12 @@ packages: resolution: {integrity: sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.29.10': - resolution: {integrity: sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==} + '@babel/helpers@7.29.13': + resolution: {integrity: sha512-laoRpD/kO/iA4CDlgJbixHekg7oPvWALK0PQyK3Ob2I2njZRvVAD77RfWCIImtqWCq6KijoBoZK7bp/HlTWASQ==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.12': - resolution: {integrity: sha512-WJ7JBp/Q4+z/ImydtI7jS6NVco5++632ExBemSX+Ysb+G1lCwQ5BVo3SY+jGGOcZXI4ZccbZSUSJLNBW6eEpJg==} + '@babel/parser@7.29.13': + resolution: {integrity: sha512-fJM50YYjlTiBhgdkGmC1tBpv+FMAyo4annf2X6Aks+0yRlaiVkYW/3f07xAfVVkYIoZ9fFZp+mEThUFnuybhkQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -156,8 +156,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7': - resolution: {integrity: sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==} + '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.13': + resolution: {integrity: sha512-7RpEgFZq9xNRHsWwPLFQpjPOi0ZECE2QZWMBes+vgK7E02krjOfPiYtnHTIUF2nCDyeCJPvSAj0AP4NTVf4hsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -228,8 +228,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.29.12': - resolution: {integrity: sha512-nEreZBofjfd6FG621xe9Rk3+tMGBXf1nAuFrR6NUGF67fkQbSQf3NrbRuhgWRn+zb0qcy9XVok1GVFI/t9wWVQ==} + '@babel/plugin-transform-block-scoping@7.29.13': + resolution: {integrity: sha512-q7f5zYLtDLqO11ydQK1w2RqZ1m5kmcAlmgZlfXssKgqVyL8+HgDvWXMxvuEz8TuJfq1UNsY9sB6ABjjtQkN6wA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -258,8 +258,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.29.7': - resolution: {integrity: sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==} + '@babel/plugin-transform-destructuring@7.29.13': + resolution: {integrity: sha512-X2meXB39NOPPmmshSRJzyd50hX9uCzbscNQwVCjLCtq363PZIJFFxJIeZPpgAewC570vpdeGIHTcltwd0QUlJg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -306,8 +306,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-for-of@7.29.7': - resolution: {integrity: sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==} + '@babel/plugin-transform-for-of@7.29.13': + resolution: {integrity: sha512-dFjiIw+xBYpgLhYDc1QFQOZmMX44se0YCmXUjPsm9SQEj9HaCJAjvVnK6/yK9iE4E1LaKU5fIAKVJPZWCbKwXw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -555,8 +555,8 @@ packages: resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.12': - resolution: {integrity: sha512-MscXe/NAZcOkYEsRajHZFt3ynsb22PUi6CTrp5U7+RYycR9By84mn9mFN54YgfITiqK4hFx3Ju3tZSyzfpS5ew==} + '@babel/traverse@7.29.13': + resolution: {integrity: sha512-0ve0xMlFA73dgY1oyJRY6RoW+/bncdcOQqg6jjYcVfXBK90OdLXjm9R6lmRetdZVrPjXkKIoMVBqYFPjcAlZ4Q==} engines: {node: '>=6.9.0'} '@babel/types@7.29.11': @@ -649,16 +649,16 @@ packages: resolution: {integrity: sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==} engines: {node: '>=8'} - '@stoplight/spectral-core@1.24.0': - resolution: {integrity: sha512-abKt++GFFaqwKiGTfPZ5O3nIv8s+1V7J5awCjWPBtCXn7ZKTEPzEF8tBYsM3ne+RMrQ8ORkHzKFu9QZhenmkPw==} + '@stoplight/spectral-core@1.24.1': + resolution: {integrity: sha512-Q1i41CoYtzdRoxGkVH0arhv9jSNkByU/TbJ77CHMXvtgbLCTUMVCbB6W9IEIu+NndESki1tnJzt59SPifB9NWQ==} engines: {node: ^16.20 || ^18.18 || >= 20.17} '@stoplight/spectral-formats@1.9.0': resolution: {integrity: sha512-OmHZpeBdlWbDxAI43HR08vyVXY2D++YHBx9AWMQ6S2DH8aWWCvk64BJOJk161XsHJQuy/vnC8tRBIIKwSQPAsA==} engines: {node: ^16.20 || ^18.18 || >= 20.17} - '@stoplight/spectral-functions@1.11.0': - resolution: {integrity: sha512-HFlFhI+q13GqG8pphY4nNGYq9+5L14dhR9xLqx+/H2/FmAouHTfNaqE4SygIhSmtMxfNDJ8G4qnjxiQRv1kPWA==} + '@stoplight/spectral-functions@1.11.1': + resolution: {integrity: sha512-YfNXX+BKLUpMfx2tL876IJY7VHRfWfpiUmb0rseUTUzoh6ucLZLRiQIWLLkOueYz6uO1l0wE6JlVsn5VXftp9Q==} engines: {node: ^16.20 || ^18.18 || >= 20.17} '@stoplight/spectral-parsers@1.0.5': @@ -778,8 +778,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - baseline-browser-mapping@2.11.34: - resolution: {integrity: sha512-Aqr8mA1kIvyJ3UY5YAY7ib8LSo1DmDMbMnVqGPtsKW1LxaFQFwn9Eb3yvq2fUKJsRvaXjnAV7R5osqETapzNiA==} + baseline-browser-mapping@2.11.35: + resolution: {integrity: sha512-GNk8KX52CHqeNKGk8+7tZnQab/2k1t/BgrUHPKNdijzpEhF1saPQZHVKb6m5loSAxB39gyrTYw34Qf9CQ3u1qQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -806,8 +806,8 @@ packages: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} - caniuse-lite@1.0.30001820: - resolution: {integrity: sha512-gfWD6MxqVCqAOwmODfZf7DchWvlrA+SRdNX7ceLfg3xRqe5ssjjpF7EgslC/0tiLiNTajdaNN/q8c/5u/7Gz8w==} + caniuse-lite@1.0.30001823: + resolution: {integrity: sha512-TQ5s/djDjNk1axreUW+4rULH+BmdCMLiJkhaXnO5wqivG7tITkSUj4ItIdzqdZHKaXcHAV8dhH3JxOM7/7bwqw==} concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -859,8 +859,8 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.472: - resolution: {integrity: sha512-s4+nfT29b0FKpVKoaIxl2pWsoNcn7A/nMPSrxayw4T3BsmPeV2lF9Y06BsAQeMGhCTQ4nYJ5XST7jkqe4ZEqFw==} + electron-to-chromium@1.5.478: + resolution: {integrity: sha512-pftG+ma5Lm8O6/p45bhYT6StBN5ziQymaRzmCZwFl8DwWHKPPD93FdOmP1aqftcepolQYvrcyTLa17kE8Yf+jg==} es-abstract-get@1.0.0: resolution: {integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==} @@ -921,8 +921,8 @@ packages: fast-xml-builder@1.3.1: resolution: {integrity: sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==} - fast-xml-parser@5.11.2: - resolution: {integrity: sha512-R9iDuNrQYeQut46cn2r2wHKn4HYzVDvDm5J1wW+koZewykv0yuO2HChTYeZtrULyHIDM9cj9TUXloCsueCQUog==} + fast-xml-parser@5.12.0: + resolution: {integrity: sha512-/pXxRBtwxY9w8z7YbgsvIPPcPvFDsTbIkWwTQJhzNJPokj+TbN6ftmcv4j/pEQDvOCNnKGDzuk5Bo2oogIOiFg==} hasBin: true for-each@0.3.5: @@ -1025,8 +1025,8 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.17.0: - resolution: {integrity: sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==} + is-core-module@2.18.0: + resolution: {integrity: sha512-qyax9fgaKOEC4qK8WZn7Q4IcoZC9RC1O1fFxRcRTq/oMMkWT/uXpqpXa12kzWR409zAt1drYN9N9BO26UmBCmw==} engines: {node: '>= 0.4'} is-data-view@1.0.2: @@ -1085,8 +1085,8 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} - is-unsafe@2.0.2: - resolution: {integrity: sha512-HgbIHPBH0KHHCcjLfGsCvhtPTVxjaAZlXjwdz7/GQC40SjSe4sfQsar8J5VFo8JOSbarkpV0OLG95bbaNd9aAQ==} + is-unsafe@2.0.3: + resolution: {integrity: sha512-ZBllczCCO267vgdFb6Tq3pv+LhHaCiGMdr+ZsuL+OopruAg7S+3ZDs1vD0RPC0uSrkjzbraxaGjtX1YBxjPeFQ==} is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} @@ -1214,8 +1214,8 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - openapi-sampler@1.7.9: - resolution: {integrity: sha512-r3D6O5m3O6mhMpQkr+kddfVX6A5jos6/B9BRWiYk4dR0/jgoEbLtD853fDL3CDIyrlXRIL+sI7ap36VSeHSEPQ==} + openapi-sampler@1.7.10: + resolution: {integrity: sha512-WhPgO1qywzBbC0oLDSykd/V782yQFeTRFrCCJXgJGOCC8YG7DSrvOdJ++LqE61d1v4cqZ9aG0G80HNl1guU6zg==} own-keys@1.0.2: resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==} @@ -1268,23 +1268,23 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} - regexpu-core@6.5.3: - resolution: {integrity: sha512-E8VgUoSK+LMQrLboDxavm76MTBGrQhx9RiNuomRmYnZ10Uw12HrI8fkxOOncktb2hBpzIZ9SV/347euQHG5z+g==} + regexpu-core@6.5.4: + resolution: {integrity: sha512-VpdamrZ9bw4YmvMZfTA3Yg8IHU9Guvg21bonvgjC4l3KfBkOqCPJesHakz7cQeE4Vh4zz4r4Gy6igAcnJxZv9g==} engines: {node: '>=4'} regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - regjsparser@0.13.4: - resolution: {integrity: sha512-EWV80YgFaVgFrjGCAsV7oybp4GOxbls5RzBg8OB0nKEVXsBJR1JlV8Di1JhCROg3MzTfe1RI8yitIm1eOs68iA==} + regjsparser@0.14.1: + resolution: {integrity: sha512-IeYboCLG1KBNRksrZQIZ1SV5KVWZiR0ikFokOcA0n63vLvlaFvCsfxN+fd4aXwL0KW3YD+ByRzIgo9ZAHdbldw==} hasBin: true require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - resolve@1.22.13: - resolution: {integrity: sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==} + resolve@1.22.14: + resolution: {integrity: sha512-1ZjYvR9sbkiwC5+9QHetqW5HmA2pHRMaoupD01t2HlYnV/vydC2zPwLixhsMieSWVZt0JJRg5LVIk0Ow1D/TrA==} engines: {node: '>= 0.4'} hasBin: true @@ -1308,12 +1308,12 @@ packages: safe-stable-stringify@1.1.1: resolution: {integrity: sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==} - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + semver@5.7.3: + resolution: {integrity: sha512-kM18BPOqTi0+TB68703/GJRpAML5Me+IDQsR1J26YB3EFKKNEyHIVZuWDX7+WKQB3tHwDwgk24BfhdpWUbytvQ==} hasBin: true - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + semver@6.3.2: + resolution: {integrity: sha512-GYrCADwpu6yV5OAvchkQ27Z5wwMxWAEMg5NNWjyHh/5DboFFqbdbvYNIvZouQpxXyeMPoTOh0vdPYKlf0ZswdQ==} hasBin: true set-function-length@1.2.2: @@ -1494,7 +1494,7 @@ snapshots: '@asyncapi/markdown-template@2.0.0': dependencies: '@asyncapi/generator-react-sdk': 1.1.3 - openapi-sampler: 1.7.9 + openapi-sampler: 1.7.10 yaml: 1.10.3 transitivePeerDependencies: - '@types/babel__core' @@ -1508,8 +1508,8 @@ snapshots: '@stoplight/json': 3.21.0 '@stoplight/json-ref-readers': 1.2.2 '@stoplight/json-ref-resolver': 3.1.6 - '@stoplight/spectral-core': 1.24.0 - '@stoplight/spectral-functions': 1.11.0 + '@stoplight/spectral-core': 1.24.1 + '@stoplight/spectral-functions': 1.11.1 '@stoplight/spectral-parsers': 1.0.5 '@stoplight/spectral-ref-resolver': 1.0.5 '@stoplight/types': 13.20.0 @@ -1539,47 +1539,47 @@ snapshots: '@babel/core@7.12.9': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.12 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) - '@babel/helpers': 7.29.10 - '@babel/parser': 7.29.12 + '@babel/generator': 7.29.13 + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) + '@babel/helpers': 7.29.13 + '@babel/parser': 7.29.13 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 convert-source-map: 1.9.0 debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 lodash: 4.18.1 - resolve: 1.22.13 - semver: 5.7.2 + resolve: 1.22.14 + semver: 5.7.3 source-map: 0.5.7 transitivePeerDependencies: - supports-color - '@babel/core@7.29.7': + '@babel/core@7.29.13': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.12 - '@babel/helper-compilation-targets': 7.29.7 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) - '@babel/helpers': 7.29.10 - '@babel/parser': 7.29.12 + '@babel/generator': 7.29.13 + '@babel/helper-compilation-targets': 7.29.13 + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.29.13) + '@babel/helpers': 7.29.13 + '@babel/parser': 7.29.13 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 - semver: 6.3.1 + semver: 6.3.2 transitivePeerDependencies: - supports-color - '@babel/generator@7.29.12': + '@babel/generator@7.29.13': dependencies: - '@babel/parser': 7.29.12 + '@babel/parser': 7.29.13 '@babel/types': 7.29.11 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 @@ -1589,24 +1589,24 @@ snapshots: dependencies: '@babel/types': 7.29.11 - '@babel/helper-compilation-targets@7.29.7': + '@babel/helper-compilation-targets@7.29.13': dependencies: '@babel/compat-data': 7.29.7 '@babel/helper-validator-option': 7.29.7 browserslist: 4.29.5 lru-cache: 5.1.1 - semver: 6.3.1 + semver: 6.3.2 - '@babel/helper-create-class-features-plugin@7.29.12(@babel/core@7.12.9)': + '@babel/helper-create-class-features-plugin@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-member-expression-to-functions': 7.29.7 '@babel/helper-optimise-call-expression': 7.29.7 '@babel/helper-replace-supers': 7.29.7(@babel/core@7.12.9) - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 - '@babel/traverse': 7.29.12 - semver: 6.3.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 + '@babel/traverse': 7.29.13 + semver: 6.3.2 transitivePeerDependencies: - supports-color @@ -1614,17 +1614,17 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 - regexpu-core: 6.5.3 - semver: 6.3.1 + regexpu-core: 6.5.4 + semver: 6.3.2 '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 debug: 4.4.3 lodash.debounce: 4.0.8 - resolve: 1.22.13 + resolve: 1.22.14 transitivePeerDependencies: - supports-color @@ -1632,33 +1632,33 @@ snapshots: '@babel/helper-member-expression-to-functions@7.29.7': dependencies: - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.29.7': dependencies: - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.12.9)': + '@babel/helper-module-transforms@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + '@babel/helper-module-transforms@7.29.13(@babel/core@7.29.13)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.13 '@babel/helper-module-imports': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -1673,7 +1673,7 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-wrap-function': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -1682,18 +1682,18 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-member-expression-to-functions': 7.29.7 '@babel/helper-optimise-call-expression': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color - '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + '@babel/helper-skip-transparent-expression-wrappers@7.29.13': dependencies: - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 transitivePeerDependencies: - supports-color - '@babel/helper-string-parser@7.29.11': {} + '@babel/helper-string-parser@7.29.13': {} '@babel/helper-validator-identifier@7.29.7': {} @@ -1702,17 +1702,17 @@ snapshots: '@babel/helper-wrap-function@7.29.7': dependencies: '@babel/template': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 '@babel/types': 7.29.11 transitivePeerDependencies: - supports-color - '@babel/helpers@7.29.10': + '@babel/helpers@7.29.13': dependencies: '@babel/template': 7.29.7 '@babel/types': 7.29.11 - '@babel/parser@7.29.12': + '@babel/parser@7.29.13': dependencies: '@babel/types': 7.29.11 @@ -1720,7 +1720,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -1734,20 +1734,20 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7(@babel/core@7.12.9)': + '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7(@babel/core@7.29.13)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 - '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7) + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.13) transitivePeerDependencies: - supports-color @@ -1755,7 +1755,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -1794,7 +1794,7 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.12.9) - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -1812,7 +1812,7 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-block-scoping@7.29.12(@babel/core@7.12.9)': + '@babel/plugin-transform-block-scoping@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 @@ -1820,7 +1820,7 @@ snapshots: '@babel/plugin-transform-class-properties@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-create-class-features-plugin': 7.29.12(@babel/core@7.12.9) + '@babel/helper-create-class-features-plugin': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -1828,7 +1828,7 @@ snapshots: '@babel/plugin-transform-class-static-block@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-create-class-features-plugin': 7.29.12(@babel/core@7.12.9) + '@babel/helper-create-class-features-plugin': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -1837,11 +1837,11 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-globals': 7.29.7 '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-replace-supers': 7.29.7(@babel/core@7.12.9) - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -1851,11 +1851,11 @@ snapshots: '@babel/helper-plugin-utils': 7.29.7 '@babel/template': 7.29.7 - '@babel/plugin-transform-destructuring@7.29.7(@babel/core@7.12.9)': + '@babel/plugin-transform-destructuring@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -1885,7 +1885,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.12.9) + '@babel/plugin-transform-destructuring': 7.29.13(@babel/core@7.12.9) transitivePeerDependencies: - supports-color @@ -1899,20 +1899,20 @@ snapshots: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-for-of@7.29.7(@babel/core@7.12.9)': + '@babel/plugin-transform-for-of@7.29.13(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color '@babel/plugin-transform-function-name@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -1939,7 +1939,7 @@ snapshots: '@babel/plugin-transform-modules-amd@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -1947,7 +1947,7 @@ snapshots: '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -1955,17 +1955,17 @@ snapshots: '@babel/plugin-transform-modules-systemjs@7.29.8(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color '@babel/plugin-transform-modules-umd@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-module-transforms': 7.29.7(@babel/core@7.12.9) + '@babel/helper-module-transforms': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -1994,11 +1994,11 @@ snapshots: '@babel/plugin-transform-object-rest-spread@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.12.9) + '@babel/plugin-transform-destructuring': 7.29.13(@babel/core@7.12.9) '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.12.9) - '@babel/traverse': 7.29.12 + '@babel/traverse': 7.29.13 transitivePeerDependencies: - supports-color @@ -2019,15 +2019,15 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.7)': + '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.13)': dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color @@ -2039,7 +2039,7 @@ snapshots: '@babel/plugin-transform-private-methods@7.29.7(@babel/core@7.12.9)': dependencies: '@babel/core': 7.12.9 - '@babel/helper-create-class-features-plugin': 7.29.12(@babel/core@7.12.9) + '@babel/helper-create-class-features-plugin': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -2048,7 +2048,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-annotate-as-pure': 7.29.7 - '@babel/helper-create-class-features-plugin': 7.29.12(@babel/core@7.12.9) + '@babel/helper-create-class-features-plugin': 7.29.13(@babel/core@7.12.9) '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -2112,7 +2112,7 @@ snapshots: dependencies: '@babel/core': 7.12.9 '@babel/helper-plugin-utils': 7.29.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.13 transitivePeerDependencies: - supports-color @@ -2158,14 +2158,14 @@ snapshots: dependencies: '@babel/compat-data': 7.29.7 '@babel/core': 7.12.9 - '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-compilation-targets': 7.29.13 '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-option': 7.29.7 '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.29.7(@babel/core@7.12.9) '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.29.7(@babel/core@7.12.9) '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-bugfix-safari-rest-destructuring-rhs-array': 7.29.13(@babel/core@7.12.9) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.29.7(@babel/core@7.29.13) '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.29.7(@babel/core@7.12.9) '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.12.9) '@babel/plugin-syntax-import-assertions': 7.29.7(@babel/core@7.12.9) @@ -2175,12 +2175,12 @@ snapshots: '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-block-scoped-functions': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-transform-block-scoping': 7.29.12(@babel/core@7.12.9) + '@babel/plugin-transform-block-scoping': 7.29.13(@babel/core@7.12.9) '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-class-static-block': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-classes': 7.29.11(@babel/core@7.12.9) '@babel/plugin-transform-computed-properties': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.12.9) + '@babel/plugin-transform-destructuring': 7.29.13(@babel/core@7.12.9) '@babel/plugin-transform-dotall-regex': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-duplicate-keys': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.7(@babel/core@7.12.9) @@ -2188,7 +2188,7 @@ snapshots: '@babel/plugin-transform-explicit-resource-management': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-exponentiation-operator': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-export-namespace-from': 7.29.7(@babel/core@7.12.9) - '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.12.9) + '@babel/plugin-transform-for-of': 7.29.13(@babel/core@7.12.9) '@babel/plugin-transform-function-name': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-json-strings': 7.29.7(@babel/core@7.12.9) '@babel/plugin-transform-literals': 7.29.7(@babel/core@7.12.9) @@ -2227,7 +2227,7 @@ snapshots: babel-plugin-polyfill-corejs3: 0.14.2(@babel/core@7.12.9) babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.12.9) core-js-compat: 3.51.0 - semver: 6.3.1 + semver: 6.3.2 transitivePeerDependencies: - supports-color @@ -2253,15 +2253,15 @@ snapshots: '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/parser': 7.29.12 + '@babel/parser': 7.29.13 '@babel/types': 7.29.11 - '@babel/traverse@7.29.12': + '@babel/traverse@7.29.13': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.12 + '@babel/generator': 7.29.13 '@babel/helper-globals': 7.29.7 - '@babel/parser': 7.29.12 + '@babel/parser': 7.29.13 '@babel/template': 7.29.7 '@babel/types': 7.29.11 debug: 4.4.3 @@ -2270,7 +2270,7 @@ snapshots: '@babel/types@7.29.11': dependencies: - '@babel/helper-string-parser': 7.29.11 + '@babel/helper-string-parser': 7.29.13 '@babel/helper-validator-identifier': 7.29.7 '@jridgewell/gen-mapping@0.3.13': @@ -2367,7 +2367,7 @@ snapshots: '@stoplight/path@1.3.2': {} - '@stoplight/spectral-core@1.24.0': + '@stoplight/spectral-core@1.24.1': dependencies: '@scarf/scarf': 1.4.0 '@stoplight/better-ajv-errors': 1.0.3(ajv@8.20.0) @@ -2398,18 +2398,18 @@ snapshots: dependencies: '@scarf/scarf': 1.4.0 '@stoplight/json': 3.21.0 - '@stoplight/spectral-core': 1.24.0 + '@stoplight/spectral-core': 1.24.1 '@types/json-schema': 7.0.15 tslib: 2.9.1 transitivePeerDependencies: - encoding - '@stoplight/spectral-functions@1.11.0': + '@stoplight/spectral-functions@1.11.1': dependencies: '@scarf/scarf': 1.4.0 '@stoplight/better-ajv-errors': 1.0.3(ajv@8.20.0) '@stoplight/json': 3.21.0 - '@stoplight/spectral-core': 1.24.0 + '@stoplight/spectral-core': 1.24.1 '@stoplight/spectral-formats': 1.9.0 '@stoplight/spectral-runtime': 1.1.6 ajv: 8.20.0 @@ -2538,7 +2538,7 @@ snapshots: '@babel/compat-data': 7.29.7 '@babel/core': 7.12.9 '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.12.9) - semver: 6.3.1 + semver: 6.3.2 transitivePeerDependencies: - supports-color @@ -2565,7 +2565,7 @@ snapshots: balanced-match@1.0.2: {} - baseline-browser-mapping@2.11.34: {} + baseline-browser-mapping@2.11.35: {} brace-expansion@1.1.21: dependencies: @@ -2574,9 +2574,9 @@ snapshots: browserslist@4.29.5: dependencies: - baseline-browser-mapping: 2.11.34 - caniuse-lite: 1.0.30001820 - electron-to-chromium: 1.5.472 + baseline-browser-mapping: 2.11.35 + caniuse-lite: 1.0.30001823 + electron-to-chromium: 1.5.478 node-releases: 2.0.63 update-browserslist-db: 1.3.4(browserslist@4.29.5) @@ -2599,7 +2599,7 @@ snapshots: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 - caniuse-lite@1.0.30001820: {} + caniuse-lite@1.0.30001823: {} concat-map@0.0.1: {} @@ -2653,7 +2653,7 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.472: {} + electron-to-chromium@1.5.478: {} es-abstract-get@1.0.0: dependencies: @@ -2773,11 +2773,11 @@ snapshots: path-expression-matcher: 1.6.2 xml-naming: 0.3.0 - fast-xml-parser@5.11.2: + fast-xml-parser@5.12.0: dependencies: '@nodable/entities': 3.1.0 fast-xml-builder: 1.3.1 - is-unsafe: 2.0.2 + is-unsafe: 2.0.3 path-expression-matcher: 1.6.2 strnum: 2.5.1 xml-naming: 0.3.0 @@ -2895,7 +2895,7 @@ snapshots: is-callable@1.2.7: {} - is-core-module@2.17.0: + is-core-module@2.18.0: dependencies: hasown: 2.0.4 @@ -2963,7 +2963,7 @@ snapshots: dependencies: which-typed-array: 1.1.24 - is-unsafe@2.0.2: {} + is-unsafe@2.0.3: {} is-weakmap@2.0.2: {} @@ -3065,10 +3065,10 @@ snapshots: has-symbols: 1.1.0 object-keys: 1.1.1 - openapi-sampler@1.7.9: + openapi-sampler@1.7.10: dependencies: '@types/json-schema': 7.0.15 - fast-xml-parser: 5.11.2 + fast-xml-parser: 5.12.0 json-pointer: 0.6.2 own-keys@1.0.2: @@ -3129,27 +3129,27 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 - regexpu-core@6.5.3: + regexpu-core@6.5.4: dependencies: regenerate: 1.5.0 regenerate-unicode-properties: 10.3.0 regjsgen: 0.8.0 - regjsparser: 0.13.4 + regjsparser: 0.14.1 unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.2.1 regjsgen@0.8.0: {} - regjsparser@0.13.4: + regjsparser@0.14.1: dependencies: jsesc: 3.1.0 require-from-string@2.0.2: {} - resolve@1.22.13: + resolve@1.22.14: dependencies: es-errors: 1.3.0 - is-core-module: 2.17.0 + is-core-module: 2.18.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -3178,9 +3178,9 @@ snapshots: safe-stable-stringify@1.1.1: {} - semver@5.7.2: {} + semver@5.7.3: {} - semver@6.3.1: {} + semver@6.3.2: {} set-function-length@1.2.2: dependencies: diff --git a/.mise/mise.coverage.lock b/.mise/mise.coverage.lock index c7fe1fd4..78d4c043 100644 --- a/.mise/mise.coverage.lock +++ b/.mise/mise.coverage.lock @@ -1,5 +1,7 @@ # @generated - this file is auto-generated by `mise lock` https://mise.jdx.dev/dev-tools/mise-lock.html +lockfile_version = 3 + [conda-packages.linux-arm64."_openmp_mutex-4.5-20_gnu"] url = "https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-20_gnu.conda" checksum = "sha256:a2527b1d81792a0ccd2c05850960df119c2b6d8f5fdec97f2db7d25dc23b1068" @@ -781,3 +783,8 @@ checksum = "sha256:656590cfa13bb7478595bbfdd3bc6bc075a4f7f3f0df5a439c1856cb03c5a url = "https://github.com/taiki-e/cargo-llvm-cov/releases/download/v0.9.1/cargo-llvm-cov-x86_64-pc-windows-msvc.zip" url_api = "https://api.github.com/repos/taiki-e/cargo-llvm-cov/releases/assets/547404215" provenance = "github-attestations" + +[[tools."pipx:coverage"]] +version = "7.15.0" +backend = "pipx:coverage" +uv = { path = "locks/mise.coverage/pipx-coverage/7.15.0", digest = "sha256:1640adda2c6eb6e97cf2472282cdd39da66ae99c3c8802171ce4d6ef3b83422e" } diff --git a/.mise/mise.js.lock b/.mise/mise.js.lock index 3f95b63a..8b0bf487 100644 --- a/.mise/mise.js.lock +++ b/.mise/mise.js.lock @@ -55,7 +55,7 @@ url = "https://github.com/oxc-project/oxc/releases/download/apps_v1.73.0/oxlint- [[tools."npm:@asyncapi/generator"]] version = "3.5.0" -aube = { path = "locks/mise.js/npm-asyncapi-generator/3.5.0~39db1ca7", digest = "sha256:7f0f42969d2d0b14ab125d05f712d544d39c812de78a17e650576b2b7f5e2b7a" } +aube = { path = "locks/mise.js/npm-asyncapi-generator/3.5.0~39db1ca7", digest = "sha256:13d0958ec1b789f7b1e0ea4a3d50987edb908e7f67900f1b4fb8803dfa33f6bc" } backend = "npm:@asyncapi/generator" specifiers = ["latest"] @@ -64,7 +64,7 @@ trust_policy_excludes = '["rollup@2.80.0"]' [[tools."npm:@asyncapi/markdown-template"]] version = "2.0.0" -aube = { path = "locks/mise.js/npm-asyncapi-markdown-template/2.0.0~34f72aac", digest = "sha256:df38330379788243896e3f0a528e5eee13e225265f5a2b21b5676eb797523fd8" } +aube = { path = "locks/mise.js/npm-asyncapi-markdown-template/2.0.0~34f72aac", digest = "sha256:148c03d9c7af02b40a2a7e7aded301c727f9ad99673e5290bd785df9a3609aca" } backend = "npm:@asyncapi/markdown-template" specifiers = ["2.0.0"] diff --git a/CHANGELOG.md b/CHANGELOG.md index a9c3b483..58523c2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -185,6 +185,12 @@ Changelog 1.1.0. each module at `/app/modules//`. A hub configured with the old path, or a deployment generated before this change, must be pointed at the new one or regenerated. The Zig modules' shared build moved to `libs/zig-shared`. +- **Breaking:** The pyo3 modules' directories no longer repeat the `pyo3-` of their parent: `modules/pyo3/math1`, + `modules/pyo3/lidar1` and the rest, in place of `modules/pyo3/pyo3-math1`. A scenario names them as before, as + `type: "pyo3-math1"`, because `et-cli` now keys a module under `modules//` by its package name less + `@edge-toolkit/et-ws-` rather than by its directory, which for every other module is the same name. A deployment + generated before this change stages them at the old paths and must be regenerated, and a `PYO3_PYTHONPATH` naming an + old directory must name the new one. - **Breaking:** `et_ws_server::routes::HealthResponse`, the answer to `GET /health`, is now `et_ws_service::health::HealthResponse`, since a board's hub gives the same answer; import it from there. - **Breaking:** `et-ws-wasi-runner`'s host runner, its binary and `run_module` are behind the new default `std` diff --git a/Cargo.lock b/Cargo.lock index 2a0cbd06..65740eb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6415,12 +6415,15 @@ version = "0.3.0" dependencies = [ "backon", "command-error", + "document-features", "edge-toolkit", "et-org", "et-otlp", "et-rest-client", + "et-test-helpers", "et-ws-runner-common", "et-ws-test-server", + "fs-err", "futures-util", "pyo3", "pyo3-build-config", diff --git a/config/coverage.toml b/config/coverage.toml index 52d294ad..1fd7cf5a 100644 --- a/config/coverage.toml +++ b/config/coverage.toml @@ -1,13 +1,14 @@ # coverage.py config for the combined Python report (referenced via COVERAGE_RCFILE by the pytest-cov task). -# Data sources feed one report: pytest plus web-runner Pyodide runs. The web runner drops its .coverage files -# into target/pycov/. `[tool.coverage.paths]` remaps each source's recorded path to the repo-relative one so -# `coverage combine` merges them into a single file entry. The first entry is the canonical on-disk source. +# Data sources feed one report: pytest plus the web-runner Pyodide runs and the pyo3-runner runs, whose .coverage +# files land in target/pycov/. `[tool.coverage.paths]` remaps each source's recorded path to the repo-relative one +# so `coverage combine` merges them into a single file entry. The first entry is the canonical on-disk source. [tool.coverage.run] # Branch coverage must be enabled identically on every data source `coverage combine` merges. -# This rcfile covers the pytest runs (via COVERAGE_RCFILE); the Pyodide runs set branch=True on their Coverage() -# constructor directly because no COVERAGE_RCFILE env reaches the in-browser interpreter. A mismatch makes -# `coverage combine` refuse to merge arc data with line data for the same source files. +# This rcfile covers the pytest runs (via COVERAGE_RCFILE) and the pyo3 runner (via its Coverage() config_file); +# the Pyodide runs set branch=True on their Coverage() constructor directly because no COVERAGE_RCFILE env reaches +# the in-browser interpreter. A mismatch makes `coverage combine` refuse to merge arc data with line data for the +# same source files. branch = true relative_files = true @@ -18,4 +19,6 @@ pydemo1 = ["modules/web/pydemo1/pydemo1", "pydemo1", "**/pydemo1"] pyeye1 = ["modules/web/pyeye1/pyeye1", "pyeye1", "**/pyeye1"] pyface1 = ["modules/web/pyface1/pyface1", "pyface1", "**/pyface1"] pymath1 = ["modules/web/pymath1/pymath1", "pymath1", "**/pymath1"] +# Every pyo3 module at once: the runner records absolute paths, and each one's own directory survives the remap. +pyo3 = ["modules/pyo3", "**/modules/pyo3"] pyspeech1 = ["modules/web/pyspeech1/pyspeech1", "pyspeech1", "**/pyspeech1"] diff --git a/config/gitleaks.toml b/config/gitleaks.toml index 4a9011bc..86109dcc 100644 --- a/config/gitleaks.toml +++ b/config/gitleaks.toml @@ -58,8 +58,9 @@ paths = [ [[allowlists]] description = "Untracked artifacts matched by extension rather than location, per .gitignore's file patterns." paths = [ + '''(^|/)registry\.yaml$''', '''\.coverage$''', - '''\.local\.md$''', + '''\.local\.[^/]+$''', '''\.o$''', '''\.onnx$''', '''\.pem$''', diff --git a/config/jscpd-baseline.json b/config/jscpd-baseline.json index def86540..ad729bed 100644 --- a/config/jscpd-baseline.json +++ b/config/jscpd-baseline.json @@ -28,6 +28,7 @@ "161f873e1c1bf887": 1, "162b7eccbfa52a74": 1, "16acb47f836cc1f8": 1, + "183f5fff1e62dc4b": 1, "18f7ac455840240a": 1, "1a07ddf368451c0a": 1, "1a1867cca4e1d4e8": 1, @@ -300,6 +301,7 @@ "edfb18c73a139873": 1, "ef5b9c050e029806": 1, "ef69568ef92f1b79": 1, + "efae224386080be2": 1, "f1d71f58ab3823e9": 1, "f1f99624666ed51c": 1, "f20e3a3f28708194": 1, diff --git a/config/ls-lint.yaml b/config/ls-lint.yaml index 8e00f47c..486d2b0d 100644 --- a/config/ls-lint.yaml +++ b/config/ls-lint.yaml @@ -116,7 +116,12 @@ ignore: - modules/wasi/wasi-graphics-info/wit_world/__pycache__ - modules/wasi/wasi-graphics-info/wit_world/exports/__pycache__ - modules/wasi/wasi-graphics-info/wit_world/imports/__pycache__ - - services/ws-pyo3-runner/python/__pycache__ + - modules/pyo3/cowsay-probe/__pycache__ + - modules/pyo3/echo/__pycache__ + - modules/pyo3/fanout/__pycache__ + - modules/pyo3/no-hooks/__pycache__ + - modules/pyo3/storage-pingpong/__pycache__ + - modules/pyo3/torch-inference/__pycache__ - modules/web/pydata1/.venv - modules/web/pydata1/.pytest_cache - modules/web/pydemo1/.venv diff --git a/config/lychee.toml b/config/lychee.toml index 5b35b7b2..4af5c762 100644 --- a/config/lychee.toml +++ b/config/lychee.toml @@ -26,7 +26,7 @@ exclude_private = true # those paths). # Each entry is an unanchored regex over the path, so it is anchored to a whole directory name: a bare "data" also # dropped every file under the `*-data1` modules. -exclude_path = ['(^|/)node_modules/', '(^|/)target/', '\.local\.md$', '^(\./)?data/', '^(\./)?generated/'] +exclude_path = ['(^|/)node_modules/', '(^|/)target/', '\.local\.[^/]+$', '^(\./)?data/', '^(\./)?generated/'] # URL patterns (regex) to skip, none of which are real links. # doc/test placeholder hosts (e.g. http://host:8080/) and `{...}` format-string templates diff --git a/config/pyrefly.toml b/config/pyrefly.toml index 48ee0abd..f89b70bc 100644 --- a/config/pyrefly.toml +++ b/config/pyrefly.toml @@ -4,7 +4,7 @@ # parse legacy `# type:` comments -- a rule of our own bans those, so the annotation form Pyrefly does check is # the only one in the tree. -project-includes = ["../libs/python-*/**/*.py", "../modules/**/*.py", "../services/**/*.py"] +project-includes = ["../libs/python-*/**/*.py", "../modules/**/*.py"] # The Python the code is checked against, rather than whichever interpreter the host's PATH yields first. # Must equal the mise `python` pin. @@ -32,14 +32,13 @@ project-excludes = [ search-path = [ "../libs/python-edge-toolkit", "../libs/python-org", - "../modules/pyo3/pyo3-mlflow", + "../modules/pyo3/mlflow", "../modules/web/pydata1", "../modules/web/pydemo1", "../modules/web/pyeye1", "../modules/web/pyface1", "../modules/web/pymath1", "../modules/web/pyspeech1", - "../services/ws-pyo3-runner/python", ] # Third-party deps and generated packages that are absent from (or opaque to) the lint environment. diff --git a/config/semgrep/no-check-tool-mentions.yaml b/config/semgrep/no-check-tool-mentions.yaml index c50e3355..da796d51 100644 --- a/config/semgrep/no-check-tool-mentions.yaml +++ b/config/semgrep/no-check-tool-mentions.yaml @@ -590,8 +590,7 @@ rules: - "/CHECKS.md" # The generated catalogue of every check, which names each tool by design. - "/utilities/int-gen/src/checks.rs" # Names the root config the tool finds without being told to. - "/config/semgrep/no-*-mentions.yaml" # The mention bans, which cannot help but name what they ban. - - "/services/ws-pyo3-runner/python/*.py" # Single-file runner payloads, each exempt from the package rule. - - "/modules/pyo3/pyo3-math1/pkg/et_ws_pyo3_math1.py" # A single-file payload, the same exemption. + - "/modules/pyo3/math1/pkg/et_ws_pyo3_math1.py" # Single-file runner payload, exempt from the package rule. - "/modules/web/pywasm1/main.py" # A single file the browser runs verbatim, the same exemption. pattern-regex: '(?i)\bruff\b' message: >- diff --git a/config/semgrep/no-python-outside-modules.yaml b/config/semgrep/no-python-outside-modules.yaml index 7ee02114..3f8351a6 100644 --- a/config/semgrep/no-python-outside-modules.yaml +++ b/config/semgrep/no-python-outside-modules.yaml @@ -6,7 +6,6 @@ rules: - "/**/*.py" exclude: - "/modules/**" # The Python modules, whose source is why the language is here at all. - - "/services/ws-pyo3-runner/python/**" # Guest programs the runner loads, module payloads in all but name. - "/generated/**" # Generated clients, owned by the generator that emits them. - "/libs/python-*/**" # Libraries the Python modules import, each packaged as a module of its own. pattern-regex: \A diff --git a/libs/ws-runner-common/Cargo.toml b/libs/ws-runner-common/Cargo.toml index 075c5305..0bba869f 100644 --- a/libs/ws-runner-common/Cargo.toml +++ b/libs/ws-runner-common/Cargo.toml @@ -18,7 +18,7 @@ path = "src/lib.rs" ## Derives JSON Schema for every runner's environment configuration. ## et-int-gen renders each runner's environment variables into its HELP.md from that schema. env-schema = ["dep:schemars", "edge-toolkit/env-schema"] -## Internal: adds the `ET_TEST_COVERAGE` switch to the WASI and web runners' configs, for their coverage builds. +## Internal: adds the `ET_TEST_COVERAGE` switch to the WASI, web and pyo3 runners' configs, for their coverage builds. coverage = [] ## Adds the `SERIAL_PORTS_` ports to the WASI runner's config, for its own `lidar` feature to lend to guests. lidar = [] diff --git a/libs/ws-runner-common/src/pyo3_config.rs b/libs/ws-runner-common/src/pyo3_config.rs index 2d4554c9..4b48242c 100644 --- a/libs/ws-runner-common/src/pyo3_config.rs +++ b/libs/ws-runner-common/src/pyo3_config.rs @@ -14,6 +14,16 @@ runner_config! { /// `PYO3_*` settings unique to this runner. #[serde(default)] pub pyo3: Pyo3Config, + /// Runtime activation of the user module's coverage.py measurement, read from `ET_TEST_COVERAGE`. + /// + /// Only present under the `coverage` cargo feature -- the measurement code is compiled in only there. When + /// the feature is on, `ET_TEST_COVERAGE=true` measures the module the runner loads and writes the data under + /// `target/pycov/` for the combined Python coverage; `false` (the default) leaves the compiled-in measurement + /// inert. Left out of the env schema, so a runner's HELP.md documents only what every build reads. + #[cfg(feature = "coverage")] + #[cfg_attr(feature = "env-schema", schemars(skip))] + #[serde(default)] + pub et_test_coverage: bool, } } diff --git a/services/ws-pyo3-runner/python/cowsay_probe.py b/modules/pyo3/cowsay-probe/cowsay_probe.py similarity index 82% rename from services/ws-pyo3-runner/python/cowsay_probe.py rename to modules/pyo3/cowsay-probe/cowsay_probe.py index c55bb77a..8267a453 100644 --- a/services/ws-pyo3-runner/python/cowsay_probe.py +++ b/modules/pyo3/cowsay-probe/cowsay_probe.py @@ -1,4 +1,4 @@ -# ruff: noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package +# noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package """Prove a mise-preinstalled pipx package imports under the embedded interpreter. `cowsay` is declared as `pipx:cowsay` in the always-loaded mise config, and the @@ -6,7 +6,7 @@ `edge_toolkit::config::mise_python_site_packages`. So the top-level `import cowsay` below succeeds WITHOUT the operator adding it to PYO3_PYTHONPATH -- if the runner didn't wire that path in, this import would fail the whole module -load. Exercised by `tests/cowsay.rs`. +load. Exercised by `services/ws-pyo3-runner/tests/modules.rs`. """ from __future__ import annotations diff --git a/services/ws-pyo3-runner/python/echo.py b/modules/pyo3/echo/echo.py similarity index 75% rename from services/ws-pyo3-runner/python/echo.py rename to modules/pyo3/echo/echo.py index 0d47570e..f5c7233b 100644 --- a/services/ws-pyo3-runner/python/echo.py +++ b/modules/pyo3/echo/echo.py @@ -1,4 +1,4 @@ -# ruff: noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package +# noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package """Example Python module for `et-ws-pyo3-runner`. This file demonstrates the contract the runner expects. Every function is @@ -22,18 +22,18 @@ number of times during a handler -- or later from a background thread. Both styles compose: anything you `send.*()` during a handler goes out *before* the value you `return`, in submission order. See - `python/fanout.py` and `python/storage_pingpong.py` for modules that + `modules/pyo3/fanout/` and `modules/pyo3/storage-pingpong/` for modules that stash and use the host handles. -State lives in module-level globals. The runner instantiates one copy -per process, so this is the same as a singleton -- no classes, no state -threading across the FFI boundary. +State lives in a module-level dict the hooks mutate in place. The runner +instantiates one copy per process, so this is the same as a singleton -- +no classes, no state threading across the FFI boundary. To use this module, set these env vars and run the runner: WS_SERVER_URL=ws://127.0.0.1:8080/ws RUNNER_MODULE=echo - PYO3_PYTHONPATH=services/ws-pyo3-runner/python + PYO3_PYTHONPATH=modules/pyo3/echo cargo run -p et-ws-pyo3-runner """ @@ -45,7 +45,7 @@ # --- module state ---------------------------------------------------------- -_echoed: int = 0 +_state: dict[str, int] = {"echoed": 0} # --- runner hooks ---------------------------------------------------------- @@ -63,18 +63,16 @@ def on_connect(agent_id: str) -> None: def on_text_frame(text: str) -> str | None: """Echo the incoming text frame back verbatim (return-style).""" - global _echoed # noqa: PLW0603 -- runner contract: one module per process, state in module globals - _echoed += 1 + _state["echoed"] += 1 return text def on_binary_frame(frame: bytes) -> bytes | None: """Echo the incoming binary frame back verbatim (return-style).""" - global _echoed # noqa: PLW0603 -- runner contract: one module per process, state in module globals - _echoed += 1 + _state["echoed"] += 1 return frame def on_shutdown() -> None: """Log the running echo count as the connection closes.""" - _logger.info("echo agent shutting down after %d frames", _echoed) + _logger.info("echo agent shutting down after %d frames", _state["echoed"]) diff --git a/services/ws-pyo3-runner/python/fanout.py b/modules/pyo3/fanout/fanout.py similarity index 68% rename from services/ws-pyo3-runner/python/fanout.py rename to modules/pyo3/fanout/fanout.py index 441b4d50..a41abd8e 100644 --- a/services/ws-pyo3-runner/python/fanout.py +++ b/modules/pyo3/fanout/fanout.py @@ -1,7 +1,7 @@ -# ruff: noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package +# noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package """Emit multiple outbound frames per inbound frame via the `WsSender` push API. -Used by `tests/fanout.rs` to verify the multi-send path works end to end. +Used by `services/ws-pyo3-runner/tests/modules.rs` to verify the multi-send path works end to end. For each inbound binary frame containing `n` (a single byte 0-255), we push `n` distinct binary frames back through `send.binary(...)`. We @@ -15,13 +15,12 @@ _logger = logging.getLogger(__name__) -_send: Any = None # WsSender, set in init() +_state: dict[str, Any] = {} # "send": the WsSender, set in init() def init(send, _storage) -> None: """Stash the WsSender for the fan-out path.""" - global _send # noqa: PLW0603 -- runner contract: one module per process, state in module globals - _send = send + _state["send"] = send # `_storage` ignored -- fanout doesn't persist anything. _logger.info("fanout agent initialised") @@ -32,5 +31,5 @@ def on_binary_frame(frame: bytes) -> None: return count = frame[0] for i in range(count): - _send.binary(bytes([i])) + _state["send"].binary(bytes([i])) return diff --git a/modules/pyo3/pyo3-imu1/pkg/et_ws_pyo3_imu1.py b/modules/pyo3/imu1/pkg/et_ws_pyo3_imu1.py similarity index 100% rename from modules/pyo3/pyo3-imu1/pkg/et_ws_pyo3_imu1.py rename to modules/pyo3/imu1/pkg/et_ws_pyo3_imu1.py diff --git a/modules/pyo3/pyo3-imu1/pkg/package.json b/modules/pyo3/imu1/pkg/package.json similarity index 100% rename from modules/pyo3/pyo3-imu1/pkg/package.json rename to modules/pyo3/imu1/pkg/package.json diff --git a/modules/pyo3/pyo3-lidar1/pkg/et_ws_pyo3_lidar1.py b/modules/pyo3/lidar1/pkg/et_ws_pyo3_lidar1.py similarity index 100% rename from modules/pyo3/pyo3-lidar1/pkg/et_ws_pyo3_lidar1.py rename to modules/pyo3/lidar1/pkg/et_ws_pyo3_lidar1.py diff --git a/modules/pyo3/pyo3-lidar1/pkg/package.json b/modules/pyo3/lidar1/pkg/package.json similarity index 100% rename from modules/pyo3/pyo3-lidar1/pkg/package.json rename to modules/pyo3/lidar1/pkg/package.json diff --git a/modules/pyo3/pyo3-math1/pkg/et_ws_pyo3_math1.py b/modules/pyo3/math1/pkg/et_ws_pyo3_math1.py similarity index 100% rename from modules/pyo3/pyo3-math1/pkg/et_ws_pyo3_math1.py rename to modules/pyo3/math1/pkg/et_ws_pyo3_math1.py diff --git a/modules/pyo3/pyo3-math1/pkg/package.json b/modules/pyo3/math1/pkg/package.json similarity index 100% rename from modules/pyo3/pyo3-math1/pkg/package.json rename to modules/pyo3/math1/pkg/package.json diff --git a/modules/pyo3/pyo3-media1/pkg/et_ws_pyo3_media1.py b/modules/pyo3/media1/pkg/et_ws_pyo3_media1.py similarity index 100% rename from modules/pyo3/pyo3-media1/pkg/et_ws_pyo3_media1.py rename to modules/pyo3/media1/pkg/et_ws_pyo3_media1.py diff --git a/modules/pyo3/pyo3-media1/pkg/package.json b/modules/pyo3/media1/pkg/package.json similarity index 100% rename from modules/pyo3/pyo3-media1/pkg/package.json rename to modules/pyo3/media1/pkg/package.json diff --git a/modules/pyo3/pyo3-mlflow/README.md b/modules/pyo3/mlflow/README.md similarity index 100% rename from modules/pyo3/pyo3-mlflow/README.md rename to modules/pyo3/mlflow/README.md diff --git a/modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/__init__.py b/modules/pyo3/mlflow/mlflow_bridge_tests/__init__.py similarity index 100% rename from modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/__init__.py rename to modules/pyo3/mlflow/mlflow_bridge_tests/__init__.py diff --git a/modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/support.py b/modules/pyo3/mlflow/mlflow_bridge_tests/support.py similarity index 100% rename from modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/support.py rename to modules/pyo3/mlflow/mlflow_bridge_tests/support.py diff --git a/modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/test_artifacts.py b/modules/pyo3/mlflow/mlflow_bridge_tests/test_artifacts.py similarity index 100% rename from modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/test_artifacts.py rename to modules/pyo3/mlflow/mlflow_bridge_tests/test_artifacts.py diff --git a/modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/test_lifecycle.py b/modules/pyo3/mlflow/mlflow_bridge_tests/test_lifecycle.py similarity index 100% rename from modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/test_lifecycle.py rename to modules/pyo3/mlflow/mlflow_bridge_tests/test_lifecycle.py diff --git a/modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/test_persistence.py b/modules/pyo3/mlflow/mlflow_bridge_tests/test_persistence.py similarity index 100% rename from modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/test_persistence.py rename to modules/pyo3/mlflow/mlflow_bridge_tests/test_persistence.py diff --git a/modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/test_validation.py b/modules/pyo3/mlflow/mlflow_bridge_tests/test_validation.py similarity index 100% rename from modules/pyo3/pyo3-mlflow/mlflow_bridge_tests/test_validation.py rename to modules/pyo3/mlflow/mlflow_bridge_tests/test_validation.py diff --git a/modules/pyo3/pyo3-mlflow/pkg/et_ws_pyo3_mlflow.py b/modules/pyo3/mlflow/pkg/et_ws_pyo3_mlflow.py similarity index 100% rename from modules/pyo3/pyo3-mlflow/pkg/et_ws_pyo3_mlflow.py rename to modules/pyo3/mlflow/pkg/et_ws_pyo3_mlflow.py diff --git a/modules/pyo3/pyo3-mlflow/pkg/package.json b/modules/pyo3/mlflow/pkg/package.json similarity index 100% rename from modules/pyo3/pyo3-mlflow/pkg/package.json rename to modules/pyo3/mlflow/pkg/package.json diff --git a/services/ws-pyo3-runner/python/no_hooks.py b/modules/pyo3/no-hooks/no_hooks.py similarity index 68% rename from services/ws-pyo3-runner/python/no_hooks.py rename to modules/pyo3/no-hooks/no_hooks.py index 55d1b132..a880c178 100644 --- a/services/ws-pyo3-runner/python/no_hooks.py +++ b/modules/pyo3/no-hooks/no_hooks.py @@ -1,8 +1,8 @@ -# ruff: noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package +# noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package """Test fixture for et-ws-pyo3-runner's load-time hook sanity check. Intentionally defines none of the runner hooks (init / on_connect / on_text_frame / on_binary_frame / on_shutdown), so importing it must fail fast rather than register an agent that could never be driven. Used by -tests/no_hooks.rs. +`services/ws-pyo3-runner/tests/modules.rs`. """ diff --git a/services/ws-pyo3-runner/python/storage_pingpong.py b/modules/pyo3/storage-pingpong/storage_pingpong.py similarity index 63% rename from services/ws-pyo3-runner/python/storage_pingpong.py rename to modules/pyo3/storage-pingpong/storage_pingpong.py index 4987b150..a35a7fe1 100644 --- a/services/ws-pyo3-runner/python/storage_pingpong.py +++ b/modules/pyo3/storage-pingpong/storage_pingpong.py @@ -1,4 +1,4 @@ -# ruff: noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package +# noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package """Module that exercises `WsStorage.get` / `WsStorage.put`. On the first inbound binary frame, the module reads `key` (the first @@ -7,8 +7,8 @@ binary frame containing just `key`, it calls `storage.get(my_agent_id, key)` and pushes the resulting bytes back via `send.binary(...)`. -Used by `tests/storage.rs` to verify the storage path lands bytes on -the ws-server and reads them back. +Used by `services/ws-pyo3-runner/tests/modules.rs` to verify the storage +path lands bytes on the ws-server and reads them back. """ from __future__ import annotations @@ -18,22 +18,18 @@ _logger = logging.getLogger(__name__) -_send: Any = None -_storage: Any = None -_agent_id: str | None = None +_state: dict[str, Any] = {} # "send", "storage" and "agent_id", from init() and on_connect() def init(send, storage) -> None: """Stash the WsSender and WsStorage handles.""" - global _send, _storage # noqa: PLW0603 -- runner contract: one module per process, state in module globals - _send = send - _storage = storage + _state["send"] = send + _state["storage"] = storage def on_connect(agent_id: str) -> None: """Record the assigned agent id for later get/put calls.""" - global _agent_id # noqa: PLW0603 -- runner contract: one module per process, state in module globals - _agent_id = agent_id + _state["agent_id"] = agent_id def on_binary_frame(frame: bytes) -> None: @@ -41,15 +37,15 @@ def on_binary_frame(frame: bytes) -> None: if b"\x00" in frame: key_bytes, value = frame.split(b"\x00", 1) key = key_bytes.decode("utf-8") - _storage.put(key, value) + _state["storage"].put(key, value) _logger.info("stored %d bytes at key=%s", len(value), key) return key = frame.decode("utf-8") - value = _storage.get(_agent_id, key) + value = _state["storage"].get(_state["agent_id"], key) if value is None: - _send.binary(b"") + _state["send"].binary(b"") else: - _send.binary(value) + _state["send"].binary(value) _logger.info("fetched key=%s (%d bytes)", key, 0 if value is None else len(value)) return diff --git a/services/ws-pyo3-runner/python/torch_inference.py b/modules/pyo3/torch-inference/torch_inference.py similarity index 93% rename from services/ws-pyo3-runner/python/torch_inference.py rename to modules/pyo3/torch-inference/torch_inference.py index 2ab1f9b1..408c6a55 100644 --- a/services/ws-pyo3-runner/python/torch_inference.py +++ b/modules/pyo3/torch-inference/torch_inference.py @@ -1,4 +1,4 @@ -# ruff: noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package +# noqa: INP001 -- et-ws-pyo3-runner compiles this one file on its own; it is not a package """PyTorch analogue of the wasi-graphics-info module, for `et-ws-pyo3-runner`. Where wasi-graphics-info runs a deterministic 4x4 matmul (verifying C[0][0]) and @@ -13,7 +13,7 @@ `torch` is declared as `pipx:torch` in the python-only mise config and reaches `sys.path` via `edge_toolkit::config::mise_python_site_packages`, exactly like cowsay. The top-level `import torch` fails the whole module load if torch isn't -wired in -- so `tests/torch_inference.rs` checks for torch up front and SKIPS, +wired in -- so `services/ws-pyo3-runner/tests/modules.rs` checks for torch up front and SKIPS, rather than letting the runner fail, when torch isn't installed. On any inbound text frame the module runs the workflow and returns a JSON diff --git a/services/ws-pyo3-runner/Cargo.toml b/services/ws-pyo3-runner/Cargo.toml index 37945613..568236e2 100644 --- a/services/ws-pyo3-runner/Cargo.toml +++ b/services/ws-pyo3-runner/Cargo.toml @@ -7,6 +7,9 @@ edition.workspace = true license.workspace = true repository.workspace = true +[package.metadata.docs.rs] +features = ["docs"] + [lib] doctest = false path = "src/lib.rs" @@ -15,9 +18,18 @@ path = "src/lib.rs" name = "et-ws-pyo3-runner" path = "src/main.rs" +[features] +## Internal: compiles in coverage.py measurement of the user module for the repo's coverage workflow. +## `ET_TEST_COVERAGE` still gates the measurement at runtime. +coverage = ["dep:fs-err", "et-ws-runner-common/coverage"] +## Internal: renders this feature list into the crate documentation, as docs.rs builds it. +docs = ["dep:document-features"] + [dependencies] +document-features = { workspace = true, optional = true } edge-toolkit = { workspace = true, features = ["std"] } et-otlp.workspace = true +fs-err = { workspace = true, optional = true } # Typed ws-server REST client (storage GET/PUT). # `tracing` injects the W3C traceparent on each request, matching the other native runners. et-rest-client = { workspace = true, features = ["tracing"] } @@ -35,6 +47,7 @@ tracing = { workspace = true, features = ["std"] } backon = { workspace = true, features = ["tokio-sleep"] } command-error.workspace = true et-org.workspace = true +et-test-helpers.workspace = true et-ws-test-server.workspace = true rstest.workspace = true serde_json = { workspace = true, features = ["std"] } diff --git a/services/ws-pyo3-runner/README.md b/services/ws-pyo3-runner/README.md index 94110228..eb4170ec 100644 --- a/services/ws-pyo3-runner/README.md +++ b/services/ws-pyo3-runner/README.md @@ -16,7 +16,7 @@ You point it at a Python module by name, and tell it where to find that module o ```sh RUNNER_MODULE=echo # which Python module to load (required) -PYO3_PYTHONPATH=.../python # folders to import it (and its dependencies) from +PYO3_PYTHONPATH=modules/pyo3/echo # folders to import it (and its dependencies) from WS_SERVER_URL=ws://127.0.0.1:8080/ws # where the ws-server is (optional) cargo run -p et-ws-pyo3-runner ``` @@ -40,7 +40,7 @@ A name that resolves nowhere on `sys.path` is fetched from the ws-server, which way it serves every other module: the runner reads the module's `package.json`, downloads the single file its `main` field names, and compiles that source under the file's own stem. This is the shape the WASI and web runners already have, and it is what lets a generated deployment name a pyo3 module without also arranging for -that module to be on the runner's filesystem -- see `modules/pyo3/pyo3-math1/` for one. +that module to be on the runner's filesystem -- see `modules/pyo3/math1/` for one. The local path is tried first and is unchanged, so a module on `PYO3_PYTHONPATH` never causes a fetch. Only the module itself arrives over the wire: whatever it imports still resolves through `sys.path`, so its third-party @@ -66,7 +66,7 @@ Your module may define any of these top-level functions; the runner calls them a ws-server keeps for each agent. That is the whole interface: a module is "just a Python file with some of those functions." The smallest example -is [`python/echo.py`](https://github.com/edge-toolkit/core/blob/main/services/ws-pyo3-runner/python/echo.py). +is `modules/pyo3/echo/echo.py`. ## Persistent workers diff --git a/services/ws-pyo3-runner/src/agent.rs b/services/ws-pyo3-runner/src/agent.rs index e21f1dbe..5382704f 100644 --- a/services/ws-pyo3-runner/src/agent.rs +++ b/services/ws-pyo3-runner/src/agent.rs @@ -188,9 +188,15 @@ pub async fn run(agent: InitializedAgent, shutdown: &Notify) -> Result<(), Runne let _shutdown_sent = inbound_tx.send(InboundEvent::Shutdown); drop(inbound_tx); let _joined = worker.join(); + // The module has run its last hook, so this is the whole of what coverage can measure. + #[cfg(feature = "coverage")] + let finished = crate::coverage::finish(); let _close_sent = socket.send(tungstenite::Message::Close(None)).await; storage_task.abort(); - result + result?; + #[cfg(feature = "coverage")] + finished?; + Ok(()) } /// Run every Python hook on a dedicated OS thread, owning the `Dispatcher`. diff --git a/services/ws-pyo3-runner/src/coverage.rs b/services/ws-pyo3-runner/src/coverage.rs new file mode 100644 index 00000000..d1a1bf8a --- /dev/null +++ b/services/ws-pyo3-runner/src/coverage.rs @@ -0,0 +1,140 @@ +//! coverage.py measurement of the user module, for the repo's coverage workflow. +//! +//! Compiled in only under the `coverage` feature, and started only when `ET_TEST_COVERAGE` is `true`. The data lands +//! in `target/pycov/` as one `.coverage.` file per process, where the combined Python report's `coverage +//! combine` already gathers the pytest and Pyodide data, so every module under `modules/pyo3/` that a measured runner +//! loads joins that report without being named anywhere. +//! +//! Two things a plain `Coverage.start()` would miss are handled here. The hooks run on the runner's own dispatch +//! thread, which `threading` never started, so it never receives the tracer coverage.py gives every thread that +//! `threading` starts; [`measured`] installs it before each hook. And the embedded interpreter is never finalized, so +//! nothing saves the data for us: the runner calls [`finish`] once its teardown has run the module's last hook, and a +//! timer saves meanwhile for a runner that is killed before it gets there. Neither save sits between a hook and the +//! reply it returns, which a slow save would otherwise hold back. + +use std::path::PathBuf; +use std::sync::OnceLock; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use pyo3::prelude::*; +use pyo3::types::PyDict; +use tracing::error; + +use crate::python::{PythonError, prepend_sys_path}; + +/// How often the background save runs, which bounds what a runner killed before [`finish`] loses. +const SAVE_INTERVAL: Duration = Duration::from_secs(1); + +/// The `coverage.Coverage` measuring this process, once [`start`] has made it. +static COVERAGE: OnceLock> = OnceLock::new(); + +/// A failure to start measuring the user module. +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum CoverageError { + /// The data directory could not be created, or the thread that saves into it could not be spawned. + #[error("setting up coverage measurement: {0}")] + Io(#[from] std::io::Error), + /// coverage.py could not be imported, configured or started. + #[error(transparent)] + Python(#[from] PythonError), +} + +/// Start measuring every file under `modules/pyo3/`, before the user module is imported. +/// +/// `source` is what keeps the tracer off everything else a module imports -- torch's import alone runs far more +/// Python than every module here put together. `config/coverage.toml` supplies the branch setting, which has to +/// match the pytest data this is combined with. +/// +/// coverage.py itself is imported from `python_path`, the `sys.path` prefix the module resolves against, so it is +/// put in place first; mise's pipx site-packages are where the coverage env installs it. A module fetched from the +/// hub is compiled under its bare file name, which coverage.py resolves against `sys.path`; its directory has to be +/// on `PYO3_PYTHONPATH` for its lines to be attributed to it. +pub fn start(python_path: &[PathBuf]) -> Result<(), CoverageError> { + let root = edge_toolkit::config::get_project_root(); + let data_dir = root.join("target/pycov"); + fs_err::create_dir_all(&data_dir)?; + let config_file = root.join("config/coverage.toml").to_string_lossy().into_owned(); + let data_file = data_dir.join(".coverage").to_string_lossy().into_owned(); + let source = root.join("modules/pyo3").to_string_lossy().into_owned(); + // A suffix of our own rather than coverage.py's `True`. Given `True`, its first save renames the file after a hash + // of the data saved so far, which is still empty in every process at that point, and `coverage combine` then + // skips all but one of the files as duplicates. The time keeps a recycled pid from reusing a file. + let started = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_nanos(); + let suffix = format!("pyo3-runner.pid{}.{started}", std::process::id()); + Python::attach(|py| -> Result<(), PythonError> { + prepend_sys_path(py, python_path)?; + let options = PyDict::new(py); + options.set_item("config_file", config_file)?; + options.set_item("data_file", data_file)?; + options.set_item("data_suffix", suffix)?; + options.set_item("source", [source])?; + let coverage = py.import("coverage")?.getattr("Coverage")?.call((), Some(&options))?; + drop(coverage.call_method0("start")?); + if COVERAGE.set(coverage.unbind()).is_err() { + return Err(PythonError::Py("coverage measurement was already started".to_owned())); + } + Ok(()) + })?; + let _saver = std::thread::Builder::new() + .name("pycov-save".to_owned()) + .spawn(save_periodically)?; + Ok(()) +} + +/// Wrap `hook` to run under coverage.py's tracer on the calling thread. +/// +/// pyo3 creates a thread state for a thread Python did not start only for the length of one `Python::attach`, and +/// the tracer lives on that state, so it is installed for every hook rather than once for the thread. A no-op until +/// [`start`] has run. Failing to install it is an error rather than a log line: measurement that quietly stopped +/// reads as untested code in the report, not as a broken measurement. +pub fn measured(hook: F) -> impl FnOnce(Python<'_>) -> Result +where + F: FnOnce(Python<'_>) -> Result, +{ + move |py| { + trace_current_thread(py)?; + hook(py) + } +} + +/// Save the last of what was measured, once the module has run its last hook. +/// +/// A no-op until [`start`] has run. +pub fn finish() -> Result<(), PythonError> { + Python::attach(save) +} + +/// Give the calling thread the tracer coverage.py gives every thread that `threading` starts. +fn trace_current_thread(py: Python<'_>) -> Result<(), PythonError> { + if COVERAGE.get().is_none() { + return Ok(()); + } + let tracer = py.import("threading")?.call_method0("gettrace")?; + drop(py.import("sys")?.call_method1("settrace", (tracer,))?); + Ok(()) +} + +/// Write out what has been measured so far. +/// +/// A no-op until [`start`] has run, so a coverage build run without `ET_TEST_COVERAGE` writes nothing. +fn save(py: Python<'_>) -> Result<(), PythonError> { + if let Some(coverage) = COVERAGE.get() { + drop(coverage.bind(py).call_method0("save")?); + } + Ok(()) +} + +/// Save every [`SAVE_INTERVAL`] until a save fails, for a runner that is killed before [`finish`]. +fn save_periodically() { + loop { + std::thread::sleep(SAVE_INTERVAL); + if let Err(err) = Python::attach(save) { + error!("saving coverage failed, so nothing more is saved: {err}"); + return; + } + } +} diff --git a/services/ws-pyo3-runner/src/lib.rs b/services/ws-pyo3-runner/src/lib.rs index d7ec180e..c75a843a 100644 --- a/services/ws-pyo3-runner/src/lib.rs +++ b/services/ws-pyo3-runner/src/lib.rs @@ -1,4 +1,6 @@ #![cfg_attr(doc, doc = include_str!("../README.md"))] +#![cfg_attr(feature = "docs", doc = "## Feature flags")] +#![cfg_attr(feature = "docs", doc = document_features::document_features!())] #![expect( clippy::integer_division_remainder_used, clippy::single_call_fn, @@ -7,6 +9,8 @@ pub mod agent; pub mod config; +#[cfg(feature = "coverage")] +pub mod coverage; pub mod error; pub mod hub_module; pub mod python; diff --git a/services/ws-pyo3-runner/src/main.rs b/services/ws-pyo3-runner/src/main.rs index ff7ef3f5..ce306d07 100644 --- a/services/ws-pyo3-runner/src/main.rs +++ b/services/ws-pyo3-runner/src/main.rs @@ -31,6 +31,13 @@ async fn main() -> Result<(), Box> { info!("module={module} python_path={python_path:?} ws_url={ws_url}"); + // Measurement exists only under the `coverage` feature, and there `ET_TEST_COVERAGE` starts it, before the + // module's top level runs. + #[cfg(feature = "coverage")] + if config.et_test_coverage { + et_ws_pyo3_runner::coverage::start(&resolved_python_path(&python_path))?; + } + // Only a module that does not resolve locally is fetched, so a runner pointed at a module on // PYO3_PYTHONPATH never asks the hub for one. let fetched = fetch_if_absent(&module, &resolved_python_path(&python_path), &ws_url).await?; diff --git a/services/ws-pyo3-runner/src/python.rs b/services/ws-pyo3-runner/src/python.rs index 5c2c27f8..a9527393 100644 --- a/services/ws-pyo3-runner/src/python.rs +++ b/services/ws-pyo3-runner/src/python.rs @@ -355,7 +355,7 @@ fn nul_free(value: &str, what: &str) -> Result { /// Called once per load attempt, and a load can be attempted twice -- [`module_is_importable`] probes before /// [`Dispatcher::import`] runs -- so the same entries would otherwise pile up and `sys.path` would grow a /// duplicate for every extra. -fn prepend_sys_path(py: Python<'_>, extras: &[PathBuf]) -> Result<(), PythonError> { +pub(crate) fn prepend_sys_path(py: Python<'_>, extras: &[PathBuf]) -> Result<(), PythonError> { if extras.is_empty() { return Ok(()); } @@ -390,6 +390,16 @@ pub fn module_is_importable(module_name: &str, extras: &[PathBuf]) -> Result(hook: F) -> Result +where + F: FnOnce(Python<'_>) -> Result, +{ + #[cfg(feature = "coverage")] + let hook = crate::coverage::measured(hook); + Python::attach(hook) +} + /// Holds the imported user module across the lifetime of the agent loop. pub struct Dispatcher { module: Py, @@ -477,7 +487,7 @@ impl Dispatcher { /// Forward the assigned `agent_id` to the optional `on_connect` hook. pub fn on_connect(&self, agent_id: &str) -> Result<(), PythonError> { - Python::attach(|py| -> Result<(), PythonError> { + attach_hook(|py| { let module = self.module.bind(py); if !module.hasattr(HOOK_ON_CONNECT)? { return Ok(()); @@ -493,7 +503,7 @@ impl Dispatcher { /// utf-8). Outbound frames the handler queued via `WsSender` go out /// independently. pub fn on_text_frame(&self, text: &str) -> Result, PythonError> { - Python::attach(|py| -> Result, PythonError> { + attach_hook(|py| { let module = self.module.bind(py); if !module.hasattr(HOOK_ON_TEXT_FRAME)? { return Ok(None); @@ -518,7 +528,7 @@ impl Dispatcher { /// /// Returns the handler's optional reply (`bytes`, or `str` encoded as utf-8). pub fn on_binary_frame(&self, frame: &[u8]) -> Result>, PythonError> { - Python::attach(|py| -> Result>, PythonError> { + attach_hook(|py| { let module = self.module.bind(py); if !module.hasattr(HOOK_ON_BINARY_FRAME)? { return Ok(None); @@ -542,7 +552,7 @@ impl Dispatcher { /// Call the optional `on_shutdown` hook, best-effort. pub fn on_shutdown(&self) -> Result<(), PythonError> { - Python::attach(|py| -> Result<(), PythonError> { + attach_hook(|py| { let module = self.module.bind(py); if !module.hasattr(HOOK_ON_SHUTDOWN)? { return Ok(()); diff --git a/services/ws-pyo3-runner/tests/module_resolution.rs b/services/ws-pyo3-runner/tests/module_resolution.rs index 38bf1f86..043a5983 100644 --- a/services/ws-pyo3-runner/tests/module_resolution.rs +++ b/services/ws-pyo3-runner/tests/module_resolution.rs @@ -38,7 +38,7 @@ fn an_unknown_module_is_not_importable() { fn an_extra_path_makes_its_modules_importable() { // The non-empty branch: `echo` is only findable once PYO3_PYTHONPATH's directory is on sys.path, so this // also proves the probe searches the same paths the import will. - let python_dir = edge_toolkit::config::get_project_root().join("services/ws-pyo3-runner/python"); + let python_dir = edge_toolkit::config::get_project_root().join("modules/pyo3/echo"); assert!( !module_is_importable("echo", &[]).unwrap(), "echo must not be importable before its directory is added" diff --git a/services/ws-pyo3-runner/tests/modules.rs b/services/ws-pyo3-runner/tests/modules.rs index f9a18e6f..0cb07265 100644 --- a/services/ws-pyo3-runner/tests/modules.rs +++ b/services/ws-pyo3-runner/tests/modules.rs @@ -19,13 +19,14 @@ use std::error::Error; use std::path::{Component, Path, PathBuf, Prefix}; -use std::process::{Child, Command, Stdio}; +use std::process::{Command, Stdio}; use std::time::{Duration, Instant}; use backon::{ExponentialBuilder, RetryableWithContext as _}; use command_error::CommandExt as _; use edge_toolkit::config::{Language, mise_env_includes, mise_python_site_packages, mise_where}; use edge_toolkit::ws::{ClientMessage, ServerMessage}; +use et_test_helpers::ChildGuard; use futures_util::{SinkExt as _, StreamExt as _}; use rstest::rstest; use tokio_tungstenite::{connect_async, tungstenite}; @@ -50,6 +51,8 @@ const POLL_BACKOFF_MIN: Duration = Duration::from_millis(50); const POLL_BACKOFF_MAX: Duration = Duration::from_millis(500); /// How long each poll round drains inbound frames looking for the peer before backing off. const POLL_DRAIN_WINDOW: Duration = Duration::from_millis(250); +/// How long a runner gets to exit by itself once its hub has stopped, which takes it well under a second. +const RUNNER_EXIT_TIMEOUT: Duration = Duration::from_secs(30); const RUST_LOG: &str = "RUST_LOG"; type ControlSocket = tokio_tungstenite::WebSocketStream>; @@ -74,10 +77,12 @@ enum Exchange { }, /// Broadcast text; parse the reply as JSON and run the checker. TextJson(&'static str, fn(&serde_json::Value) -> Result<(), Box>), - /// Send `key\0value` then `key`; expect the binary reply to equal `value`. + /// Send `key` while nothing is stored, then `key\0value`, then `key`; expect an empty reply, then `value`. StoragePutGet { key: &'static str, value: &'static [u8] }, /// Send `[count]`; expect exactly `count` one-byte frames `0..count`. Fanout(u8), + /// Send the bytes as a binary frame; expect the same bytes back. + BinaryEcho(&'static [u8]), } #[rstest] @@ -96,6 +101,7 @@ enum Exchange { // proving the module imported the mise-provided cowsay and rendered our input. #[case::cowsay("cowsay_probe", Gate::Python, Exchange::TextContains { send: "cowsay-round-trip", extra: &["^__^"] })] #[case::torch("torch_inference", Gate::Torch, Exchange::TextJson("run-torch", check_torch))] +#[case::echo_binary("echo", Gate::Always, Exchange::BinaryEcho(b"\x00binary\xffframe"))] #[tokio::test(flavor = "current_thread")] async fn module_behaves( #[case] module: &str, @@ -113,7 +119,7 @@ async fn module_behaves( let server = et_ws_test_server::start(); // Control client registers first so the runner has a peer to broadcast to. let (mut control, control_id) = control_client(&server.ws_url).await?; - let mut runner = spawn_runner(module, &server.ws_url, &[]); + let mut runner = spawn_runner(module, &[module_dir(module)], &server.ws_url, &[]); // torch's cold import + first op is slow; the rest are quick. let budget = if matches!(gate, Gate::Torch) { @@ -127,15 +133,17 @@ async fn module_behaves( // the steps do, this call cuts them off at it. Deriving an inner deadline from the remaining time instead // would restore the nested-deadline shape that made the torch case fail at 122.2s with ~58s of its three // minutes unspent, the inner bound deciding an outcome the outer one still had room for. - let outcome = tokio::time::timeout(budget, run_exchange(&mut control, &control_id, &exchange, budget)).await; - - runner.kill().unwrap(); - let _status = runner.wait().unwrap(); + // Reduced to its message, in the one expression, before the hub is stopped: the boxed error is not `Send`, so a + // binding holding it across that await would make this test's future not `Send` either. + let verdict = match tokio::time::timeout(budget, run_exchange(&mut control, &control_id, &exchange, budget)).await { + Ok(Ok(())) => Ok(()), + Ok(Err(err)) => Err(err.to_string()), + Err(_elapsed) => Err(format!("`{module}` exchange timed out")), + }; - match outcome { - Ok(result) => result, - Err(_elapsed) => Err(format!("`{module}` exchange timed out").into()), - } + let stopped = stop_hub(&server, &mut runner).await; + verdict?; + stopped } /// Load-time sanity check: a module defining none of the runner hooks must fail to load. @@ -148,7 +156,7 @@ fn no_hooks_fails_to_load() -> Result<(), Box> { // we must inspect `output.status`/`output.stderr` rather than have a checked call turn it into an error. let output = Command::new(env!("CARGO_BIN_EXE_et-ws-pyo3-runner")) .env("RUNNER_MODULE", "no_hooks") - .env("PYO3_PYTHONPATH", python_dir()) + .env("PYO3_PYTHONPATH", module_dir("no_hooks")) // Safety net: if the check regressed and import succeeded, bound the // otherwise-forever connect retry so the assertion below fires instead. .env("RUNNER_TIMEOUT", "10s") @@ -171,15 +179,19 @@ fn no_hooks_fails_to_load() -> Result<(), Box> { /// worker, close the socket). `echo` loads without any gated toolchain, so the runner reaches its connected run /// loop before the short timeout trips; a clean (zero) exit code then confirms the teardown path ran to /// completion. +/// +/// It runs with `ET_TEST_COVERAGE=false`, the one case here that does, so that a coverage build also runs its +/// hooks with measurement compiled in but never started, as it is whenever that variable is not `true`. #[tokio::test(flavor = "current_thread")] async fn shuts_down_gracefully_on_timeout() -> Result<(), Box> { let server = et_ws_test_server::start(); let rust_log = std::env::var(RUST_LOG).unwrap_or_else(|_| "warn".to_string()); let mut runner = Command::new(env!("CARGO_BIN_EXE_et-ws-pyo3-runner")) .env("RUNNER_MODULE", "echo") - .env("PYO3_PYTHONPATH", python_dir()) + .env("PYO3_PYTHONPATH", module_dir("echo")) .env("WS_SERVER_URL", &server.ws_url) .env("RUNNER_TIMEOUT", "3s") + .env("ET_TEST_COVERAGE", "false") .env("RUST_LOG", rust_log) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) @@ -263,12 +275,21 @@ async fn exchange_text_json( check(&value) } -/// Send `key\0value`, then `key`, and require the binary reply to be `value` again. +/// Read `key` before it is stored, then send `key\0value` and `key`, and require the reply to be `value` again. +/// +/// The first read must come back empty: a key nothing has stored is an empty frame, not a missing reply. #[expect( clippy::single_call_fn, reason = "one Exchange variant's protocol; kept separate so run_exchange stays a dispatcher" )] async fn exchange_storage_put_get(control: &mut ControlSocket, key: &str, value: &[u8]) -> Result<(), Box> { + control + .send(tungstenite::Message::binary(key.as_bytes().to_vec())) + .await?; + let unstored = drain_binary(control).await?; + if !unstored.is_empty() { + return Err(format!("key {key:?} read back {unstored:?} before anything stored it").into()); + } let mut put_frame = Vec::with_capacity(key.len() + 1 + value.len()); put_frame.extend_from_slice(key.as_bytes()); put_frame.push(0); @@ -301,10 +322,24 @@ async fn exchange_fanout(control: &mut ControlSocket, count: u8) -> Result<(), B Ok(()) } +/// Send `frame` as a binary frame and require the same bytes back. +#[expect( + clippy::single_call_fn, + reason = "one Exchange variant's protocol; kept separate so run_exchange stays a dispatcher" +)] +async fn exchange_binary_echo(control: &mut ControlSocket, frame: &[u8]) -> Result<(), Box> { + control.send(tungstenite::Message::binary(frame.to_vec())).await?; + let reply = drain_binary(control).await?; + if reply.as_slice() != frame { + return Err(format!("binary reply {reply:?} did not echo {frame:?}").into()); + } + Ok(()) +} + /// Send the module's trigger and assert on its reply. /// /// Each variant's send-and-check sequence lives in its own function above rather than in an arm here. Inline, -/// the four of them made one 55-line body whose cyclomatic complexity was 19 against a ceiling of 10, and +/// the first four of them made one 55-line body whose cyclomatic complexity was 19 against a ceiling of 10, and /// they share nothing but the socket -- the reply is text, JSON, one binary frame or many, per variant. async fn run_exchange( control: &mut ControlSocket, @@ -318,6 +353,7 @@ async fn run_exchange( Exchange::TextJson(payload, check) => exchange_text_json(control, payload, *check).await, Exchange::StoragePutGet { key, value } => exchange_storage_put_get(control, key, value).await, Exchange::Fanout(count) => exchange_fanout(control, *count).await, + Exchange::BinaryEcho(frame) => exchange_binary_echo(control, frame).await, } } @@ -325,47 +361,49 @@ async fn run_exchange( /// /// The fake-agent side lives in `et_ws_test_server::math1`; the module reads the input through the /// runner's storage handle, computes, and stores its global model, which is verified against the -/// expected weights for the canonical input. The runner is long-lived, so it is killed once the +/// expected weights for the canonical input. The runner is long-lived, so its hub is stopped once the /// exchange resolves (mirroring `module_behaves`). /// -/// This is the hub-fetch case, and the only one: the module is a published ws-module rather than a file under -/// `python/`, so it is asked for by the scoped name its `package.json` declares -- which the hub serves it -/// under, and which is not a legal Python identifier, so it cannot resolve on `sys.path` at all. -/// `spawn_runner` still sets `PYO3_PYTHONPATH`, which is the point -- a configured python path that does not -/// happen to contain the module must fall through to the hub rather than fail. Every other case here names a -/// module under `python/` and so still takes the local import. +/// This case fetches its module from the hub: the module is a published ws-module rather than a test module in a +/// directory of its own, so it is asked for by the scoped name its `package.json` declares -- which the hub serves +/// it under, and which is not a legal Python identifier, so it cannot resolve on `sys.path` at all. +/// `PYO3_PYTHONPATH` still names the module's own directory, which is the point -- a configured python path that +/// does not resolve the requested name must fall through to the hub rather than fail. Each `module_behaves` case +/// names a test module by the name its file defines, and so takes the local import. #[tokio::test(flavor = "current_thread")] async fn math1_stores_verified_model() -> Result<(), Box> { let server = et_ws_test_server::start(); - let module = format!("{}et-ws-pyo3-math1", et_org::NPM_SCOPE); - let mut runner = spawn_runner(&module, &server.ws_url, &[]); + let name = "et-ws-pyo3-math1"; + let module = format!("{}{name}", et_org::NPM_SCOPE); + let mut runner = spawn_runner(&module, &[published_module_dir(name)], &server.ws_url, &[]); let outcome = et_ws_test_server::math1::drive_math1_exchange(&server.ws_url, server.storage_dir.path(), EXCHANGE_BUDGET) .await; - runner.kill().unwrap(); - let _status = runner.wait().unwrap(); + let stopped = stop_hub(&server, &mut runner).await; let (weight, bias) = outcome?; et_ws_test_server::math1::verify_math1_model(weight, bias)?; - Ok(()) + stopped } /// Run the published device module `module` with `envs` naming its devices, until `verify` judges what it stored. /// /// Like math1, each is fetched from the hub. Its persistent worker, which `init` starts, waits for `on_connect` to -/// give the agent a bucket and then stores what it reads; the runner is long-lived, so it is killed once `verify` -/// has decided, whichever way. +/// give the agent a bucket and then stores what it reads; the runner is long-lived, so its hub is stopped once +/// `verify` has decided, whichever way. fn stores_from_devices(module: &str, envs: &[(&str, &str)], verify: F) -> Result<(), Box> where F: FnOnce(&Path) -> Result<(), et_ws_test_server::device::DeviceError>, { let server = et_ws_test_server::start(); - let mut runner = spawn_runner(&format!("{}{module}", et_org::NPM_SCOPE), &server.ws_url, envs); + let scoped = format!("{}{module}", et_org::NPM_SCOPE); + let mut runner = spawn_runner(&scoped, &[published_module_dir(module)], &server.ws_url, envs); let outcome = verify(server.storage_dir.path()); - // A runner that has already exited cannot be killed, which is no failure here; it is reaped either way. - let _killed: std::io::Result<()> = runner.kill(); - let _status = runner.wait()?; + let stopped = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build()? + .block_on(stop_hub(&server, &mut runner)); outcome?; - Ok(()) + stopped } /// The pyo3 twin of wasi-lidar1 stores the last whole revolution a simulated COIN-D6 sends. @@ -430,9 +468,22 @@ fn check_torch(value: &serde_json::Value) -> Result<(), Box> { Ok(()) } -/// Directory of the bundled test Python modules -- the single source of truth for `PYO3_PYTHONPATH`. -fn python_dir() -> PathBuf { - edge_toolkit::config::get_project_root().join("services/ws-pyo3-runner/python") +/// Directory of the test module `module` under `modules/pyo3/` -- the single source of truth for its `PYO3_PYTHONPATH`. +fn module_dir(module: &str) -> PathBuf { + let dir = format!("modules/pyo3/{}", module.replace('_', "-")); + edge_toolkit::config::get_project_root().join(dir) +} + +/// Directory holding the file of the published module `module` (`et-ws-pyo3-math1`, say) under `modules/pyo3/`. +/// +/// On `PYO3_PYTHONPATH` it changes nothing about how the module loads, since the runner asks for the scoped package +/// name, which no file provides. It is where coverage.py finds the file the fetched source was compiled from. +fn published_module_dir(module: &str) -> PathBuf { + let dir = module.strip_prefix("et-ws-pyo3-").unwrap_or(module); + edge_toolkit::config::get_project_root() + .join("modules/pyo3") + .join(dir) + .join("pkg") } /// `path` in the form a colon-separated `PYO3_PYTHONPATH` holds whole. @@ -456,16 +507,19 @@ fn colon_free(path: &Path) -> PathBuf { } /// Spawn the runner subprocess for `module`, pointed at `ws_url`, with `envs` set beside what every case sets. -fn spawn_runner(module: &str, ws_url: &str, envs: &[(&str, &str)]) -> Child { +/// +/// `module_dirs` go on `PYO3_PYTHONPATH` ahead of edge-toolkit's source. +fn spawn_runner(module: &str, module_dirs: &[PathBuf], ws_url: &str, envs: &[(&str, &str)]) -> ChildGuard { // Silence the runner unless invoked with --nocapture and RUST_LOG opted in. let rust_log = std::env::var(RUST_LOG).unwrap_or_else(|_| "warn".to_string()); // edge-toolkit from this repository's source, which the lidar, IMU and media modules import. let edge_toolkit = edge_toolkit::config::get_project_root().join("libs/python-edge-toolkit"); - let python_path = format!( - "{}:{}", - colon_free(&python_dir()).display(), - colon_free(&edge_toolkit).display() - ); + let python_path = module_dirs + .iter() + .chain(std::iter::once(&edge_toolkit)) + .map(|dir| colon_free(dir).display().to_string()) + .collect::>() + .join(":"); Command::new(env!("CARGO_BIN_EXE_et-ws-pyo3-runner")) .env("RUNNER_MODULE", module) .env("PYO3_PYTHONPATH", python_path) @@ -475,8 +529,21 @@ fn spawn_runner(module: &str, ws_url: &str, envs: &[(&str, &str)]) -> Child { .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) .spawn_checked() + .map(|spawned| ChildGuard::new(spawned.into_child())) .unwrap() - .into_child() +} + +/// Stop `server` and give `runner` [`RUNNER_EXIT_TIMEOUT`] to exit by itself, failing if it has to be killed. +/// +/// Stopping the hub closes the runner's socket, so the runner leaves its run loop, runs `on_shutdown` and exits. +/// Killing it instead skips that teardown, and in a coverage build loses whatever it ran since its last save. +async fn stop_hub(server: &et_ws_test_server::TestServer, runner: &mut ChildGuard) -> Result<(), Box> { + server.stop().await; + if runner.wait_for_exit(RUNNER_EXIT_TIMEOUT) { + Ok(()) + } else { + Err("runner did not exit after its hub stopped".into()) + } } /// Open a control client and drive et-connect until we have an `agent_id`. diff --git a/services/ws-server/.gitignore b/services/ws-server/.gitignore deleted file mode 100644 index 3142720b..00000000 --- a/services/ws-server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -registry.yaml diff --git a/utilities/cli/src/lib.rs b/utilities/cli/src/lib.rs index bd03db26..4c66cccf 100644 --- a/utilities/cli/src/lib.rs +++ b/utilities/cli/src/lib.rs @@ -133,6 +133,9 @@ const REPO_MODULE_DIRS: [&str; 6] = [ /// Registry scope this project's own module packages carry, and which the hub drops when naming a module. pub(crate) const MODULE_SCOPE: &str = et_org::NPM_SCOPE; +/// The start of every module package's name after its scope, which the key a scenario names a module by leaves out. +const MODULE_NAME_PREFIX: &str = "et-ws-"; + /// Environment a runner gets from the deployment rather than from the scenario, and so cannot be overridden. pub(crate) const DERIVED_RUNNER_ENV: [&str; 2] = ["RUNNER_MODULE", "WS_SERVER_URL"]; @@ -307,7 +310,7 @@ pub(crate) struct ModuleRegistryEntry { /// The module's published package name, as `pkg/package.json` declares it. /// /// This is what a runner has to be told: `RUNNER_MODULE` is resolved against the names the hub serves modules - /// under, which is the package name (`et-ws-math1`) and not the directory a scenario names it by (`math1`). `None` + /// under, which is the package name (`et-ws-math1`) and not the name a scenario refers to it by (`math1`). `None` /// for a mise-staged package, which is already keyed by its published name. pub package_name: Option, } @@ -729,6 +732,7 @@ pub(crate) fn module_registry( &project_root.join(parent), ws_server_dir, &format!("/app/{parent}"), + MODULE_TYPE_DIRS.contains(&parent), ); } for module in REPO_MODULE_DIRS { @@ -847,11 +851,15 @@ fn register_scenario_paths( } } +/// Register every module directory under `root`. +/// +/// Each is keyed by [`runtime_module_key`] when `by_package`, and otherwise by its directory name. fn register_modules_under( registry: &mut BTreeMap, root: &Path, ws_server_dir: &Path, docker_root: &str, + by_package: bool, ) { let Ok(entries) = fs::read_dir(root) else { return; @@ -869,16 +877,31 @@ fn register_modules_under( let Some(directory_name) = module_path.file_name().and_then(|name| name.to_str()) else { continue; }; - register_module( - registry, - &module_path, - directory_name, - ws_server_dir, - &format!("{docker_root}/{directory_name}"), - ); + let module = module_entry(&module_path, ws_server_dir, &format!("{docker_root}/{directory_name}")); + let key = if by_package { + runtime_module_key(directory_name, &module) + } else { + directory_name.to_owned() + }; + insert_module(registry, &key, module); } } +/// The key a module of a module type directory is registered by. +/// +/// It is the module's package name, less the scope and the [`MODULE_NAME_PREFIX`] every module's name starts with. +/// That name carries the runtime as well as the module -- `et-ws-pyo3-math1`, `et-ws-wasi-math1`, `et-ws-math1` -- so +/// the key stays unique across the type directories even where two of them hold a directory of the same name, as +/// `modules/pyo3/math1` and `modules/web/math1` do. A module that declares no package, such as one the pyo3 runner +/// imports straight from disk, is registered by its directory name. +fn runtime_module_key(directory_name: &str, module: &ModuleRegistryEntry) -> String { + let Some(package) = module.package_name.as_deref() else { + return directory_name.to_owned(); + }; + let unscoped = package.strip_prefix(MODULE_SCOPE).unwrap_or(package); + unscoped.strip_prefix(MODULE_NAME_PREFIX).unwrap_or(unscoped).to_owned() +} + /// Register a single module by its filesystem path (not a parent dir). /// /// Used for modules that don't live under a module type directory -- currently the generated python clients under @@ -914,16 +937,12 @@ fn register_module( ); } -/// Add a module under its directory name and, when it declares one, the package name it is served as. -fn insert_module( - registry: &mut BTreeMap, - directory_name: &str, - entry: ModuleRegistryEntry, -) { +/// Add a module under `key` and, when it declares one, the package name it is served as. +fn insert_module(registry: &mut BTreeMap, key: &str, entry: ModuleRegistryEntry) { if let Some(served_name) = entry.package_name.clone() { let _previous: Option = registry.insert(served_name, entry.clone()); } - let _previous: Option = registry.insert(directory_name.to_string(), entry); + let _previous: Option = registry.insert(key.to_string(), entry); } /// The registry entry for a module directory of this repository. diff --git a/utilities/cli/tests/firmware.rs b/utilities/cli/tests/firmware.rs index a3c2d050..141f6b2e 100644 --- a/utilities/cli/tests/firmware.rs +++ b/utilities/cli/tests/firmware.rs @@ -315,7 +315,7 @@ fn a_board_as_the_server_runs_the_hub_and_its_guests_as_firmware() { let run = build["run"].as_str().unwrap(); assert!(run.contains("mise -E rust run build-firmware-pico-plus2w")); // The twin's module too, since it is fetched from the board's hub. - assert!(run.contains("$PWD/modules/pyo3/pyo3-math1")); + assert!(run.contains("$PWD/modules/pyo3/math1")); let flash = toml::Value::from("firmware-flash-hub-board"); assert_eq!( tasks["machine-hub-board"]["depends"].as_array().unwrap(), diff --git a/verification/local/output/core-math1/Dockerfile.dockerignore b/verification/local/output/core-math1/Dockerfile.dockerignore index 7474ecde..0be1785b 100644 --- a/verification/local/output/core-math1/Dockerfile.dockerignore +++ b/verification/local/output/core-math1/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/verification/local/output/default/Dockerfile.dockerignore b/verification/local/output/default/Dockerfile.dockerignore index 0be00b5a..62759fff 100644 --- a/verification/local/output/default/Dockerfile.dockerignore +++ b/verification/local/output/default/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/verification/local/output/expose/Dockerfile b/verification/local/output/expose/Dockerfile index 3b8a9896..691ddf08 100644 --- a/verification/local/output/expose/Dockerfile +++ b/verification/local/output/expose/Dockerfile @@ -113,7 +113,7 @@ FROM hub LABEL org.opencontainers.image.source="https://github.com/edge-toolkit/core" COPY --chown=10001:10001 data/model-modules/model-har-motion1/pkg /app/data/model-modules/model-har-motion1/pkg -COPY --chown=10001:10001 modules/pyo3/pyo3-math1/pkg /app/modules/pyo3/pyo3-math1/pkg +COPY --chown=10001:10001 modules/pyo3/math1/pkg /app/modules/pyo3/math1/pkg COPY --chown=10001:10001 modules/web/har1/pkg /app/modules/web/har1/pkg COPY --from=deps --chown=10001:10001 /staged/app/node_modules/onnxruntime-web /app/node_modules/onnxruntime-web diff --git a/verification/local/output/expose/Dockerfile.dockerignore b/verification/local/output/expose/Dockerfile.dockerignore index eb7fd151..dcfa2eb9 100644 --- a/verification/local/output/expose/Dockerfile.dockerignore +++ b/verification/local/output/expose/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather @@ -84,5 +86,5 @@ verification/**/.mise/locks/ # The rules above drop every `*.wasm` and `*.onnx`, which is what keeps the CI images small; these # negations put back the `pkg/` directories this image copies, and nothing else. !data/model-modules/model-har-motion1/pkg/** -!modules/pyo3/pyo3-math1/pkg/** +!modules/pyo3/math1/pkg/** !modules/web/har1/pkg/** diff --git a/verification/local/output/expose/compose.yaml b/verification/local/output/expose/compose.yaml index ddc25776..1883d447 100644 --- a/verification/local/output/expose/compose.yaml +++ b/verification/local/output/expose/compose.yaml @@ -59,7 +59,7 @@ services: network_mode: host environment: MODULES_PATHS: >- - /app/data/model-modules/model-har-motion1, /app/modules/pyo3/pyo3-math1, + /app/data/model-modules/model-har-motion1, /app/modules/pyo3/math1, /app/modules/web/har1, /app/node_modules/onnxruntime-web, /app/node_modules/stats-gl, /app/services/ws-server/static, /app/services/ws-wasm-agent MODULES_ROOT: "@edge-toolkit/et-ws-server-static" diff --git a/verification/local/output/expose/k3s.yaml b/verification/local/output/expose/k3s.yaml index 6a2ef3ff..a1f9d36c 100644 --- a/verification/local/output/expose/k3s.yaml +++ b/verification/local/output/expose/k3s.yaml @@ -141,7 +141,7 @@ spec: containers: - env: - name: MODULES_PATHS - value: /app/data/model-modules/model-har-motion1,/app/modules/pyo3/pyo3-math1,/app/modules/web/har1,/app/node_modules/onnxruntime-web,/app/node_modules/stats-gl,/app/services/ws-server/static,/app/services/ws-wasm-agent + value: /app/data/model-modules/model-har-motion1,/app/modules/pyo3/math1,/app/modules/web/har1,/app/node_modules/onnxruntime-web,/app/node_modules/stats-gl,/app/services/ws-server/static,/app/services/ws-wasm-agent - name: MODULES_ROOT value: "@edge-toolkit/et-ws-server-static" - name: OTLP_AUTH_USERNAME diff --git a/verification/local/output/expose/mise.toml b/verification/local/output/expose/mise.toml index 8b5e5fb6..8e47dcbf 100644 --- a/verification/local/output/expose/mise.toml +++ b/verification/local/output/expose/mise.toml @@ -40,7 +40,7 @@ dir = "../../../../services/ws-server" run = """ MODULES_PATHS="$(cargo run --quiet -p et-cli -- npm-module-path --package onnxruntime-web)" MODULES_PATHS="$MODULES_PATHS, $(cargo run --quiet -p et-cli -- npm-module-path --package stats-gl)" -MODULES_PATHS="$MODULES_PATHS, ../../data/model-modules/model-har-motion1, ../../modules/pyo3/pyo3-math1" +MODULES_PATHS="$MODULES_PATHS, ../../data/model-modules/model-har-motion1, ../../modules/pyo3/math1" MODULES_PATHS="$MODULES_PATHS, ../../modules/web/har1, ../ws-wasm-agent, static" export MODULES_PATHS cargo run diff --git a/verification/local/output/facility-security-scenario/Dockerfile.dockerignore b/verification/local/output/facility-security-scenario/Dockerfile.dockerignore index 7c943895..5b8c7369 100644 --- a/verification/local/output/facility-security-scenario/Dockerfile.dockerignore +++ b/verification/local/output/facility-security-scenario/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/verification/local/output/math1-cron/Dockerfile.dockerignore b/verification/local/output/math1-cron/Dockerfile.dockerignore index 7703cf3b..06afb38a 100644 --- a/verification/local/output/math1-cron/Dockerfile.dockerignore +++ b/verification/local/output/math1-cron/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/verification/local/output/math1-limits/Dockerfile.dockerignore b/verification/local/output/math1-limits/Dockerfile.dockerignore index b37f277f..87866ef1 100644 --- a/verification/local/output/math1-limits/Dockerfile.dockerignore +++ b/verification/local/output/math1-limits/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/verification/local/output/math1-multi-hub/Dockerfile.dockerignore b/verification/local/output/math1-multi-hub/Dockerfile.dockerignore index ebf811e4..341c1b1f 100644 --- a/verification/local/output/math1-multi-hub/Dockerfile.dockerignore +++ b/verification/local/output/math1-multi-hub/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/verification/local/output/math1-multi/Dockerfile.dockerignore b/verification/local/output/math1-multi/Dockerfile.dockerignore index 9d680c6d..58d95c53 100644 --- a/verification/local/output/math1-multi/Dockerfile.dockerignore +++ b/verification/local/output/math1-multi/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/verification/local/output/math1/Dockerfile.dockerignore b/verification/local/output/math1/Dockerfile.dockerignore index 94b4c3ab..7f65fbea 100644 --- a/verification/local/output/math1/Dockerfile.dockerignore +++ b/verification/local/output/math1/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/verification/local/output/mixed-hardware/mise.toml b/verification/local/output/mixed-hardware/mise.toml index 828084a7..5d3f153a 100644 --- a/verification/local/output/mixed-hardware/mise.toml +++ b/verification/local/output/mixed-hardware/mise.toml @@ -8,7 +8,7 @@ file = "secrets.env" description = "Build the Raspberry Pi Pico 2 W firmware serving mixed-hardware" dir = "../../../.." run = """ -MODULES_PATHS="$PWD/modules/pyo3/pyo3-math1, $PWD/modules/wasi/wasi-math1-sender, $PWD/services/ws-server/static" +MODULES_PATHS="$PWD/modules/pyo3/math1, $PWD/modules/wasi/wasi-math1-sender, $PWD/services/ws-server/static" MODULES_PATHS="$MODULES_PATHS, $PWD/services/ws-wasm-agent" export MODULES_PATHS mise -E rust run build-firmware-pico2w @@ -54,7 +54,7 @@ run = "picotool load -x -t elf target/firmware/runner-board/thumbv8m.main-none-e description = "Serve mixed-hardware's modules from this host as the board would, and fetch each" dir = "../../../.." run = """ -MODULES_PATHS="$PWD/modules/pyo3/pyo3-math1, $PWD/modules/wasi/wasi-math1-sender, $PWD/services/ws-server/static" +MODULES_PATHS="$PWD/modules/pyo3/math1, $PWD/modules/wasi/wasi-math1-sender, $PWD/services/ws-server/static" MODULES_PATHS="$MODULES_PATHS, $PWD/services/ws-wasm-agent" export MODULES_PATHS mise run cargo-test-pkg et-int-ws-server-firmware diff --git a/verification/local/output/pyo3-math1-recovery/Dockerfile b/verification/local/output/pyo3-math1-recovery/Dockerfile index 391b0584..ba6459b1 100644 --- a/verification/local/output/pyo3-math1-recovery/Dockerfile +++ b/verification/local/output/pyo3-math1-recovery/Dockerfile @@ -23,6 +23,6 @@ FROM hub LABEL org.opencontainers.image.source="https://github.com/edge-toolkit/core" -COPY --chown=10001:10001 modules/pyo3/pyo3-math1/pkg /app/modules/pyo3/pyo3-math1/pkg +COPY --chown=10001:10001 modules/pyo3/math1/pkg /app/modules/pyo3/math1/pkg USER 10001 diff --git a/verification/local/output/pyo3-math1-recovery/Dockerfile.dockerignore b/verification/local/output/pyo3-math1-recovery/Dockerfile.dockerignore index ad2ea6bf..b6463fc8 100644 --- a/verification/local/output/pyo3-math1-recovery/Dockerfile.dockerignore +++ b/verification/local/output/pyo3-math1-recovery/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather @@ -83,4 +85,4 @@ verification/**/.mise/locks/ # Re-admit the built module artifacts this scenario serves. # The rules above drop every `*.wasm` and `*.onnx`, which is what keeps the CI images small; these # negations put back the `pkg/` directories this image copies, and nothing else. -!modules/pyo3/pyo3-math1/pkg/** +!modules/pyo3/math1/pkg/** diff --git a/verification/local/output/pyo3-math1-recovery/k3s.yaml b/verification/local/output/pyo3-math1-recovery/k3s.yaml index b08e6dea..22ecf5ee 100644 --- a/verification/local/output/pyo3-math1-recovery/k3s.yaml +++ b/verification/local/output/pyo3-math1-recovery/k3s.yaml @@ -141,7 +141,7 @@ spec: containers: - env: - name: MODULES_PATHS - value: /app/modules/pyo3/pyo3-math1 + value: /app/modules/pyo3/math1 - name: MODULES_ROOT value: "" - name: OTLP_AUTH_USERNAME diff --git a/verification/local/output/pyo3-math1/Dockerfile b/verification/local/output/pyo3-math1/Dockerfile index b8bb6b0f..b8521519 100644 --- a/verification/local/output/pyo3-math1/Dockerfile +++ b/verification/local/output/pyo3-math1/Dockerfile @@ -23,7 +23,7 @@ FROM hub LABEL org.opencontainers.image.source="https://github.com/edge-toolkit/core" -COPY --chown=10001:10001 modules/pyo3/pyo3-math1/pkg /app/modules/pyo3/pyo3-math1/pkg +COPY --chown=10001:10001 modules/pyo3/math1/pkg /app/modules/pyo3/math1/pkg COPY --chown=10001:10001 modules/wasi/wasi-math1-sender/pkg /app/modules/wasi/wasi-math1-sender/pkg USER 10001 diff --git a/verification/local/output/pyo3-math1/Dockerfile.dockerignore b/verification/local/output/pyo3-math1/Dockerfile.dockerignore index b0ed77d1..5f89d0c0 100644 --- a/verification/local/output/pyo3-math1/Dockerfile.dockerignore +++ b/verification/local/output/pyo3-math1/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather @@ -83,5 +85,5 @@ verification/**/.mise/locks/ # Re-admit the built module artifacts this scenario serves. # The rules above drop every `*.wasm` and `*.onnx`, which is what keeps the CI images small; these # negations put back the `pkg/` directories this image copies, and nothing else. -!modules/pyo3/pyo3-math1/pkg/** +!modules/pyo3/math1/pkg/** !modules/wasi/wasi-math1-sender/pkg/** diff --git a/verification/local/output/pyo3-math1/compose.yaml b/verification/local/output/pyo3-math1/compose.yaml index fd617eca..2fe1a6e0 100644 --- a/verification/local/output/pyo3-math1/compose.yaml +++ b/verification/local/output/pyo3-math1/compose.yaml @@ -58,7 +58,7 @@ services: hub: service:hub-image-build network_mode: host environment: - MODULES_PATHS: /app/modules/pyo3/pyo3-math1, /app/modules/wasi/wasi-math1-sender + MODULES_PATHS: /app/modules/pyo3/math1, /app/modules/wasi/wasi-math1-sender MODULES_ROOT: "" OTLP_AUTH_USERNAME: root@example.com OTLP_COLLECTOR_URL: http://127.0.0.1:5080/api/default/v1 diff --git a/verification/local/output/pyo3-math1/k3s.yaml b/verification/local/output/pyo3-math1/k3s.yaml index 7918a5a4..ec2cc3e3 100644 --- a/verification/local/output/pyo3-math1/k3s.yaml +++ b/verification/local/output/pyo3-math1/k3s.yaml @@ -141,7 +141,7 @@ spec: containers: - env: - name: MODULES_PATHS - value: /app/modules/pyo3/pyo3-math1,/app/modules/wasi/wasi-math1-sender + value: /app/modules/pyo3/math1,/app/modules/wasi/wasi-math1-sender - name: MODULES_ROOT value: "" - name: OTLP_AUTH_USERNAME diff --git a/verification/local/output/pyo3-math1/mise.toml b/verification/local/output/pyo3-math1/mise.toml index 1a819019..dd00e25d 100644 --- a/verification/local/output/pyo3-math1/mise.toml +++ b/verification/local/output/pyo3-math1/mise.toml @@ -48,7 +48,7 @@ WS_SERVER_URL = "ws://localhost:8080/ws" description = "Run the WebSocket server" dir = "../../../../services/ws-server" run = """ -MODULES_PATHS="../../modules/pyo3/pyo3-math1, ../../modules/wasi/wasi-math1-sender" +MODULES_PATHS="../../modules/pyo3/math1, ../../modules/wasi/wasi-math1-sender" export MODULES_PATHS cargo run """ diff --git a/verification/local/output/wasi-math1/Dockerfile.dockerignore b/verification/local/output/wasi-math1/Dockerfile.dockerignore index 9be8033b..c17c9247 100644 --- a/verification/local/output/wasi-math1/Dockerfile.dockerignore +++ b/verification/local/output/wasi-math1/Dockerfile.dockerignore @@ -60,8 +60,10 @@ lcov.info # Dart pub tool dir, regenerated by `dart pub get`; one global rule for the whole workspace (root + members). **/.dart_tool/ services/ws-server/storage/ -# One-off Markdown an agent writes on request, such as an email draft or notes, which is never committed. -**/*.local.md +# The agent registry a lone ws-server saves on shutdown, written to whichever directory it was started from. +**/registry.yaml +# One-off files kept beside the repo but never committed, such as an agent's email draft or notes, or a paper. +**/*.local.* # Lock files a generated scenario leaves behind when it is run. # `lockfile = true` makes mise write one beside whichever config it resolved tools for, so running a scenario # drops `mise.lock` into that scenario's output directory. It is a by-product of running the deployment rather diff --git a/verification/published/output/pyo3-math1/Dockerfile b/verification/published/output/pyo3-math1/Dockerfile index ecc300c6..cf506724 100644 --- a/verification/published/output/pyo3-math1/Dockerfile +++ b/verification/published/output/pyo3-math1/Dockerfile @@ -25,7 +25,7 @@ printf '%s\n' '//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}' >> /released.np EOF ENV STAGE_PACKAGE="@edge-toolkit/et-ws-pyo3-math1" -ENV STAGE_DEST="/staged/app/modules/pyo3/pyo3-math1/pkg" +ENV STAGE_DEST="/staged/app/modules/pyo3/math1/pkg" RUN --mount=type=secret,id=gh_token,env=GITHUB_TOKEN bash <<'EOF' set -euo pipefail cd /tmp diff --git a/verification/published/output/pyo3-math1/compose.yaml b/verification/published/output/pyo3-math1/compose.yaml index ad97358c..b8ba5507 100644 --- a/verification/published/output/pyo3-math1/compose.yaml +++ b/verification/published/output/pyo3-math1/compose.yaml @@ -45,7 +45,7 @@ services: - gh_token network_mode: host environment: - MODULES_PATHS: /app/modules/pyo3/pyo3-math1, /app/modules/wasi/wasi-math1-sender + MODULES_PATHS: /app/modules/pyo3/math1, /app/modules/wasi/wasi-math1-sender MODULES_ROOT: "" OTLP_AUTH_USERNAME: root@example.com OTLP_COLLECTOR_URL: http://127.0.0.1:5080/api/default/v1 diff --git a/verification/published/output/pyo3-math1/k3s.yaml b/verification/published/output/pyo3-math1/k3s.yaml index 9d954246..8c30e303 100644 --- a/verification/published/output/pyo3-math1/k3s.yaml +++ b/verification/published/output/pyo3-math1/k3s.yaml @@ -141,7 +141,7 @@ spec: containers: - env: - name: MODULES_PATHS - value: /app/modules/pyo3/pyo3-math1,/app/modules/wasi/wasi-math1-sender + value: /app/modules/pyo3/math1,/app/modules/wasi/wasi-math1-sender - name: MODULES_ROOT value: "" - name: OTLP_AUTH_USERNAME