diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e22f89f..566eba4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -279,6 +279,14 @@ jobs: --target ${{ matrix.target }} --config src-tauri/tauri.adhoc.conf.json + # Reuse the installer build's compiled dependencies. These tests protect + # the native URL and deep-link dispatch boundaries before artifact upload. + - name: Test native command and deep-link contracts + run: >- + cargo test --locked --release + --manifest-path src-tauri/Cargo.toml + --target ${{ matrix.target }} + - name: Smoke-test macOS DMG install, launch, and uninstall if: runner.os == 'macOS' shell: bash diff --git a/docs/RELEASE_CANDIDATE_INSTALLERS.md b/docs/RELEASE_CANDIDATE_INSTALLERS.md index 1a8ab9b..449eefb 100644 --- a/docs/RELEASE_CANDIDATE_INSTALLERS.md +++ b/docs/RELEASE_CANDIDATE_INSTALLERS.md @@ -10,7 +10,7 @@ only the fixed `openadapt://connect` action and forwards it to the sidecar's strict, transactional pairing flow. The canonical compiler and governed runtime remain in `openadapt-flow`. Each -native installer freezes the exact `openadapt-flow[browser,console]==1.34.0` +native installer freezes the exact `openadapt-flow[browser,console]==1.35.1` runtime and its `playwright==1.61.0` browser automation dependency into the Desktop sidecar. The `console` extra is what lets an installed application serve the attended decision console the mobile decision portal relays; the diff --git a/package-lock.json b/package-lock.json index 78be0d6..fa602f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,10 +16,10 @@ }, "devDependencies": { "@tauri-apps/cli": "^2", - "@testing-library/react": "^16.3.2", + "@testing-library/react": "^16.3.3", "@types/react": "^18.3.31", "@types/react-dom": "^18.3.7", - "@vitejs/plugin-react": "^6.1.0", + "@vitejs/plugin-react": "^6.1.1", "jsdom": "^30.0.1", "typescript": "^5.5.4", "vite": "^8.2.2", @@ -782,21 +782,21 @@ } }, "node_modules/@tauri-apps/plugin-notification": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-notification/-/plugin-notification-2.3.3.tgz", - "integrity": "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-notification/-/plugin-notification-2.4.0.tgz", + "integrity": "sha512-xlJXMcUoKOjNupzDue5wrEsa1wytf+l/2gCAPhafHyP683Y3N7J/8clUWLZ3vpnwkpT2C1zcLMMQFjjecIG2xg==", "license": "MIT OR Apache-2.0", "dependencies": { - "@tauri-apps/api": "^2.8.0" + "@tauri-apps/api": "^2.11.0" } }, "node_modules/@tauri-apps/plugin-updater": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-updater/-/plugin-updater-2.10.1.tgz", - "integrity": "sha512-NFYMg+tWOZPJdzE/PpFj2qfqwAWwNS3kXrb1tm1gnBJ9mYzZ4WDRrwy8udzWoAnfGCHLuePNLY1WVCNHnh3eRA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-updater/-/plugin-updater-2.11.0.tgz", + "integrity": "sha512-AE36XkOoSna24G40jZMY15nzAnkXEPL/73tGoseGrtGOHuI/cZwWzHpZFLjKXDPgzYZ435z1gHu28LgrsBwIxQ==", "license": "MIT OR Apache-2.0", "dependencies": { - "@tauri-apps/api": "^2.10.1" + "@tauri-apps/api": "^2.11.0" } }, "node_modules/@testing-library/dom": { @@ -821,9 +821,9 @@ } }, "node_modules/@testing-library/react": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", - "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.3.tgz", + "integrity": "sha512-Uo193NgQbPMz6lrrhtRQQFcMC6Re/ELLFbbuVL30WDlZxlpZf9/lMHTAVxPRLw1q1iu9OJmR1c2BLiENRstdBg==", "dev": true, "license": "MIT", "dependencies": { @@ -910,9 +910,9 @@ } }, "node_modules/@vitejs/plugin-react": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.0.tgz", - "integrity": "sha512-qd2BzUBehkov86WFhg0JkEFEYyCLG9uPCe6qWTY/kRlss9OvJrOF2UbIWT7p+8IzZHkEu0DNGHc4HSv+JdDLsw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.1.tgz", + "integrity": "sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index e36bc96..65ac7d8 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,10 @@ }, "devDependencies": { "@tauri-apps/cli": "^2", - "@testing-library/react": "^16.3.2", + "@testing-library/react": "^16.3.3", "@types/react": "^18.3.31", "@types/react-dom": "^18.3.7", - "@vitejs/plugin-react": "^6.1.0", + "@vitejs/plugin-react": "^6.1.1", "jsdom": "^30.0.1", "typescript": "^5.5.4", "vite": "^8.2.2", diff --git a/pyproject.toml b/pyproject.toml index 4116c07..be6b343 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,9 +40,9 @@ dependencies = [ "openadapt-privacy>=1.0.0", # Exact cross-surface status/target contract used by the presentation # exporter and by the generated TypeScript projection checked into src/. - # 0.10.0 carries the portable business-decision V2 contract used by the + # 0.17.0 retains the portable business-decision V2 contract used by the # Desktop phone portal and Flow's governed runner. - "openadapt-types==0.10.0", + "openadapt-types==0.17.0", "pydantic>=2.0", "pydantic-settings>=2.0", "PyYAML>=6.0,<7", @@ -88,7 +88,7 @@ build = [ # purpose (see the pin below and the embedded ``-m playwright`` process # mode). Without it the driver becomes build-only and the artifact gate # correctly refuses the archive. - "openadapt-flow[browser,console]==1.34.0", + "openadapt-flow[browser,console]==1.35.1", # Desktop deliberately embeds the optional browser driver so selecting a # web workflow is one click. It does NOT bundle Chromium: that larger # runtime is fetched only after the operator chooses the browser surface. diff --git a/scripts/smoke_test_frozen_flow.py b/scripts/smoke_test_frozen_flow.py index be108f1..8ee8996 100644 --- a/scripts/smoke_test_frozen_flow.py +++ b/scripts/smoke_test_frozen_flow.py @@ -328,6 +328,11 @@ def _verify_bundled_capture(executable: Path, root: Path, env: dict[str, str]) - probe_env = dict(env) probe_env["OPENADAPT_DATA_DIR"] = str(root / "capture-contract-data") + # This probe verifies the frozen capture producer, not a user's hosted + # login. A local Keychain prompt must not block the unattended smoke test. + probe_env["PYTHON_KEYRING_BACKEND"] = "keyring.backends.null.Keyring" + probe_env["OPENADAPT_CONFIG_TOML"] = str(root / "doctor-config.toml") + probe_env.pop("OPENADAPT_INGEST_TOKEN", None) output, _ = _run([str(executable), "doctor"], env=probe_env, timeout=300) line = next( diff --git a/scripts/sync_control_overlay_contract.py b/scripts/sync_control_overlay_contract.py index f306293..e2ceed3 100644 --- a/scripts/sync_control_overlay_contract.py +++ b/scripts/sync_control_overlay_contract.py @@ -23,7 +23,7 @@ ROOT = Path(__file__).resolve().parents[1] OUTPUT = ROOT / "src" / "overlay" / "generated" / "contract.ts" SCHEMA_DIR = ROOT / "src" / "overlay" / "generated" / "schemas" -PINNED_TYPES_VERSION = "0.10.0" +PINNED_TYPES_VERSION = "0.17.0" SCHEMA_NAMES = ( "control-overlay-frame-v2.json", "control-overlay-timeline-v2.json", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 225628c..b84f313 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -523,6 +523,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -546,7 +556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ "bitflags 2.13.1", - "core-foundation", + "core-foundation 0.10.1", "core-graphics-types", "foreign-types", "libc", @@ -559,7 +569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ "bitflags 2.13.1", - "core-foundation", + "core-foundation 0.10.1", "libc", ] @@ -1612,9 +1622,11 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -3075,7 +3087,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "jni 0.22.4", "log", @@ -3195,7 +3207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.13.1", - "core-foundation", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -3660,6 +3672,27 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.13.1", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -3681,7 +3714,7 @@ checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ "bitflags 2.13.1", "block2", - "core-foundation", + "core-foundation 0.10.1", "core-graphics", "crossbeam-channel", "dbus", @@ -3872,9 +3905,9 @@ dependencies = [ [[package]] name = "tauri-plugin-deep-link" -version = "2.4.9" +version = "2.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ee75bc5627f77bfdf40c913255ebc258117b10ebe2b2239a1a1cf40b0b58aa" +checksum = "92d489b8ecceae1cd09f6e1f7606f2095ac721cc8d54cf2f0e6bb377cc52cff6" dependencies = [ "dunce", "plist", @@ -3893,9 +3926,9 @@ dependencies = [ [[package]] name = "tauri-plugin-notification" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc" +checksum = "ad2fd40946aef810c4be9fd33a2d1b9b397cb79042b2d21c81a0a8f204354fd1" dependencies = [ "log", "notify-rust", @@ -3912,9 +3945,9 @@ dependencies = [ [[package]] name = "tauri-plugin-shell" -version = "2.3.5" +version = "2.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8457dbf9e2bab1edd8df22bb2c20857a59a9868e79cb3eac5ed639eec4d0c73b" +checksum = "8548af174c5516e4f71f142acea4d02e00316296ea9aafa58798851481003e3c" dependencies = [ "encoding_rs", "log", @@ -3933,9 +3966,9 @@ dependencies = [ [[package]] name = "tauri-plugin-single-instance" -version = "2.4.3" +version = "2.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3214becf9ef5783c0ae99a3bb25adf5353a7a16ebf53e74b909e29205735c6c" +checksum = "5cd0cb5c412a5071b69bab6a6df1583cbb89460d4a83b6a24769b08d15b6b1e1" dependencies = [ "serde", "serde_json", @@ -3950,9 +3983,9 @@ dependencies = [ [[package]] name = "tauri-plugin-updater" -version = "2.10.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806d9dac662c2e4594ff03c647a552f2c9bd544e7d0f683ec58f872f952ce4af" +checksum = "b28d8cabdeb0564f03ae261963de4bc3d98321cd3d213e76a81b7d344e5df606" dependencies = [ "base64 0.22.1", "dirs", diff --git a/src-tauri/src/pairing.rs b/src-tauri/src/pairing.rs index c83557c..febbea2 100644 --- a/src-tauri/src/pairing.rs +++ b/src-tauri/src/pairing.rs @@ -357,7 +357,6 @@ mod tests { format!("https://connect?pairing={SECRET}&host=https://app.openadapt.ai"), format!("openadapt://connect/run?pairing={SECRET}&host=https://app.openadapt.ai"), format!("openadapt://connect?pairing={SECRET}&host=https://app.openadapt.ai#x"), - runner_uri(), format!("openadapt://connect?pack={PACK}&bind={BIND}&origin=https://openadapt.ai"), ] { assert!(action_for_url(&parse(&raw)).is_err(), "{raw}"); @@ -377,7 +376,6 @@ mod tests { "openadapt://connect/runner?pack={PACK}&bind={BIND}&origin=https://openadapt.ai" ), format!("{}#x", runner_uri()), - format!("openadapt://connect?pairing={SECRET}&host=https://app.openadapt.ai"), format!("openadapt://runner?pairing={SECRET}&host=https://app.openadapt.ai"), ] { assert!(action_for_url(&parse(&raw)).is_err(), "{raw}"); diff --git a/src/overlay/generated/contract.ts b/src/overlay/generated/contract.ts index 2b0949a..539c151 100644 --- a/src/overlay/generated/contract.ts +++ b/src/overlay/generated/contract.ts @@ -1,4 +1,4 @@ -// Generated from openadapt-types 0.10.0. Do not edit by hand. +// Generated from openadapt-types 0.17.0. Do not edit by hand. export const CONTROL_OVERLAY_FRAME_VERSION = "openadapt.control-overlay-frame/v2" as const; export const CONTROL_OVERLAY_TIMELINE_VERSION = "openadapt.control-overlay-timeline/v2" as const; diff --git a/tests/test_build_frozen_engine.py b/tests/test_build_frozen_engine.py index cc90617..e8ce331 100644 --- a/tests/test_build_frozen_engine.py +++ b/tests/test_build_frozen_engine.py @@ -447,15 +447,15 @@ def _pyproject(pin: str) -> Path: return root version, extras = frozen_notices.bundled_flow_pin(build.ROOT) - assert version == "1.34.0" + assert version == "1.35.1" assert set(frozen_notices.FLOW_REQUIRED_EXTRAS) <= set(extras) with pytest.raises(ValueError, match="console"): - frozen_notices.bundled_flow_pin(_pyproject("openadapt-flow==1.34.0")) + frozen_notices.bundled_flow_pin(_pyproject("openadapt-flow==1.35.1")) with pytest.raises(ValueError, match="browser"): - frozen_notices.bundled_flow_pin(_pyproject("openadapt-flow[console]==1.34.0")) + frozen_notices.bundled_flow_pin(_pyproject("openadapt-flow[console]==1.35.1")) with pytest.raises(ValueError, match="exact openadapt-flow build pin"): - frozen_notices.bundled_flow_pin(_pyproject("openadapt-flow[browser,console]>=1.34.0")) + frozen_notices.bundled_flow_pin(_pyproject("openadapt-flow[browser,console]>=1.35.1")) def test_frozen_runtime_roots_carry_the_pinned_flow_extras() -> None: diff --git a/tests/test_native_release.py b/tests/test_native_release.py index ebda44b..74f1f86 100644 --- a/tests/test_native_release.py +++ b/tests/test_native_release.py @@ -5,6 +5,7 @@ import os import re import subprocess +import tomllib from pathlib import Path import pytest @@ -2836,3 +2837,16 @@ def test_production_workflow_keeps_normal_publication_unadmitted() -> None: assert "write-channel" not in text assert "unadmitted release candidate" in normal_release_text assert "unadmitted release candidate" in native_release_text + + +def test_frontend_and_native_plugins_share_the_same_protocol_version() -> None: + """A JS plugin update must ship with its matching native IPC implementation.""" + root = Path(__file__).resolve().parents[1] + npm = json.loads((root / "package-lock.json").read_text(encoding="utf-8")) + cargo = tomllib.loads((root / "src-tauri/Cargo.lock").read_text(encoding="utf-8")) + native_versions = {package["name"]: package["version"] for package in cargo["package"]} + for name, package in npm["packages"].items(): + prefix = "node_modules/@tauri-apps/plugin-" + if name.startswith(prefix): + native_name = "tauri-plugin-" + name.removeprefix(prefix) + assert package["version"] == native_versions[native_name], native_name diff --git a/tests/test_public_metadata.py b/tests/test_public_metadata.py index 3e38596..2aa12ae 100644 --- a/tests/test_public_metadata.py +++ b/tests/test_public_metadata.py @@ -279,7 +279,7 @@ def test_candidate_release_notes_describe_the_bundled_flow_runtime() -> None: flow_dependencies = [ dependency for dependency in build_dependencies if dependency.startswith("openadapt-flow") ] - assert flow_dependencies == ["openadapt-flow[browser,console]==1.34.0"] + assert flow_dependencies == ["openadapt-flow[browser,console]==1.35.1"] # At or above the floor the bundled Flow declares for its ``capture`` # extra; ``tests/test_capture_runtime_contract.py`` compares the two # authoritatively. 1.2.1 specifically, because 1.2.0 and every release @@ -289,8 +289,8 @@ def test_candidate_release_notes_describe_the_bundled_flow_runtime() -> None: assert "openadapt-privacy>=1.0.0" in dependencies assert not any(item.startswith("Development Status ::") for item in classifiers) assert "Development Status :: 2 - Pre-Alpha" not in classifiers - assert bundled_flow_version() == "1.34.0" - assert bundled_flow_banner() == "openadapt-flow 1.34.0" + assert bundled_flow_version() == "1.35.1" + assert bundled_flow_banner() == "openadapt-flow 1.35.1" assert 'name = "playwright"\nversion = "1.61.0"' in lock assert flow_dependencies[0] in notes assert "playwright==1.61.0" in notes diff --git a/uv.lock b/uv.lock index 6398f10..6dfa5cf 100644 --- a/uv.lock +++ b/uv.lock @@ -1381,9 +1381,9 @@ requires-dist = [ { name = "onnxruntime", marker = "(platform_machine != 'x86_64' and extra == 'build') or (sys_platform != 'darwin' and extra == 'build')", specifier = "==1.27.0" }, { name = "openadapt-capture", specifier = ">=1.2.1" }, { name = "openadapt-desktop", extras = ["enterprise"], marker = "extra == 'full'" }, - { name = "openadapt-flow", extras = ["browser", "console"], marker = "extra == 'build'", specifier = "==1.34.0" }, + { name = "openadapt-flow", extras = ["browser", "console"], marker = "extra == 'build'", specifier = "==1.35.1" }, { name = "openadapt-privacy", specifier = ">=1.0.0" }, - { name = "openadapt-types", specifier = "==0.10.0" }, + { name = "openadapt-types", specifier = "==0.17.0" }, { name = "packaging", specifier = ">=24" }, { name = "playwright", marker = "extra == 'build'", specifier = ">=1.44" }, { name = "psutil" }, @@ -1402,22 +1402,23 @@ provides-extras = ["enterprise", "full", "build", "dev"] [[package]] name = "openadapt-flow" -version = "1.34.0" +version = "1.35.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography" }, { name = "httpx" }, { name = "idna" }, { name = "numpy" }, + { name = "openadapt-types" }, { name = "opencv-python" }, { name = "pillow" }, { name = "pydantic" }, { name = "pyyaml" }, { name = "rapidocr-onnxruntime" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/27/aa3986b135964f7a6f4992a08873922d36bbb64a83a126f272497668fec4/openadapt_flow-1.34.0.tar.gz", hash = "sha256:a941a70015fe91897e655bfc9bf83e6cf8fbcf8bd4e4c7206ffb133c505203f8", size = 20440838, upload-time = "2026-08-28T14:23:46.17Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/9b/54d64f124c0789c4e8f82a54a298e4e33681c4f02e056c49931939ae384f/openadapt_flow-1.35.1.tar.gz", hash = "sha256:c5c6c437472b23999223b0d2473dbf21de2ca05274c270ae3854adeda6b07dca", size = 21135866, upload-time = "2026-09-09T17:16:21.203Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/23/4b/22e115d8fde6f562c7debf896351d7a8a3bc14483ca246abc3ca180d9077/openadapt_flow-1.34.0-py3-none-any.whl", hash = "sha256:56d32818989cb3a92830080ead39e10b08718c55e00988117f22cbfeaac98854", size = 1928194, upload-time = "2026-08-28T14:23:44.184Z" }, + { url = "https://files.pythonhosted.org/packages/84/4d/2bfa44495c907e691fe9bcc256230b919b97430bd430d72c8291b9365fc1/openadapt_flow-1.35.1-py3-none-any.whl", hash = "sha256:cfbc89acc6a2e3bcb5502a4d1fb29e985a03149a7f14c32c259254676bb3f11d", size = 2129416, upload-time = "2026-09-09T17:16:19.067Z" }, ] [package.optional-dependencies] @@ -1446,14 +1447,14 @@ wheels = [ [[package]] name = "openadapt-types" -version = "0.10.0" +version = "0.17.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0c/54/4cc84122fe9405fa3dbcd1521d252f92ba5d5c9d1eb367187aef06d0d4a3/openadapt_types-0.10.0.tar.gz", hash = "sha256:ea4d784da2d6dae15508d44a1e207a63539448312b3490d8c38110b4013710e8", size = 151235, upload-time = "2026-08-08T19:07:11.487Z" } +sdist = { url = "https://files.pythonhosted.org/packages/17/d5/549afc2b6bdde8a0a80d4eec67644275df251ee1654f3189f0cc66235730/openadapt_types-0.17.0.tar.gz", hash = "sha256:43dc00d82d6d8feb2cfaa16960224a85933440d7dee3b5f3c60618873535287b", size = 212574, upload-time = "2026-09-01T23:50:50.837Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/6e/1efc97ed73c84205149b7e2a7474638afa0a1c29374b867c5a357bdff59e/openadapt_types-0.10.0-py3-none-any.whl", hash = "sha256:37317cc56968a88869cff8181179211365c3f772302e87ce76f95181565125b9", size = 105149, upload-time = "2026-08-08T19:07:10.104Z" }, + { url = "https://files.pythonhosted.org/packages/55/9a/bec1d51cba5749732ceeba6e4abf7abe6aeaa22c849a1edb26b97c7ab479/openadapt_types-0.17.0-py3-none-any.whl", hash = "sha256:79738ab529f71241963725c6a40603deae032ff60c61d66baf33d7a248b1afa9", size = 155033, upload-time = "2026-09-01T23:50:49.083Z" }, ] [[package]]