diff --git a/.github/workflows/release-pypi.yml b/.github/workflows/release-pypi.yml index 54c547e..808e17f 100644 --- a/.github/workflows/release-pypi.yml +++ b/.github/workflows/release-pypi.yml @@ -1,4 +1,4 @@ -# Publish sdist + wheel to PyPI when a SemVer tag is pushed (e.g. v1.0.4). +# Publish sdist + wheel to PyPI when a SemVer tag is pushed (e.g. v1.0.6). # Configure "trusted publishing" on PyPI for this workflow + repository + optional GitHub environment. # https://docs.pypi.org/trusted-publishers/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ff8524..442845e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,30 @@ This project follows [Semantic Versioning](https://semver.org/). From **v1.0.0** ## Unreleased +## 1.0.6 - 2026-05-02 + +### Added + +- **CLI `flightdeck doctor --backup PATH`:** SQLite online backup of the workspace database to **`PATH`** (parent directories created; file overwritten if present), then the usual doctor checks. +- **Examples:** **[examples/integration/emit_sample_events.node.mjs](examples/integration/emit_sample_events.node.mjs)** — **`POST /v1/events`** sample using built-in **`fetch`** (Node 18+); **[examples/integration/README.md](examples/integration/README.md)** adds **`curl`** + **`jq`** example. +- **Docs:** **[examples/deploy/README.md](examples/deploy/README.md)** — Compose **`/health`** healthcheck and **`doctor --backup`** / cron scheduling notes. +- **Roadmap:** **Phase 0** declared **closed**; **catalog-level** multi-provider pricing normalization called out under **Phase 1** build items. +- **Tests:** **`test_doctor_backup_writes_valid_sqlite`** in **`tests/test_cli.py`**. + +### Changed + +- **Examples / CI snippets:** **`flightdeck-ai>=1.0.6`** in Docker and PyPI gate samples. + +## 1.0.5 - 2026-05-02 + +### Added + +- **CLI `release diff --output json`:** prints the same JSON object as **`POST /v1/diff`** (sorted keys) for **`jq`** / CI parsers; works with **`--fail-on-policy`** (JSON to stdout, then exit **1** on policy failure). +- **`POST /v1/diff`:** **`pricing.warnings`** — string list when baseline or candidate **`spec.runtime.model`** has no row in that side's imported pricing table (diagnostic only; **`policy`** unchanged). CLI prints matching **`WARNING:`** lines in text mode. +- **Web UI:** **Run diff** shows pricing warnings above the pricing/model-change banner; **Overview** adds a **Ledger metrics** card (**`GET /v1/metrics`**). +- **Docs:** **[docs/cli.md](docs/cli.md)** and **[docs/http-api.md](docs/http-api.md)** document **`--output json`** and **`pricing.warnings`**. +- **Tests:** **`test_release_diff_output_json_shape`**, **`test_release_diff_pricing_warnings_when_model_not_in_table`** in **`tests/test_spine.py`**; **`test_release_diff_fail_on_policy_with_json_output`** in **`tests/test_cli_contract.py`**; **`test_http_v1_diff_pricing_warnings_when_model_missing`** and **`pricing.warnings`** assertion on the happy path in **`tests/test_server_actions.py`**. + ## 1.0.4 - 2026-05-03 ### Added diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index cce1e82..a265021 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -133,7 +133,7 @@ Merging to **`main` does not publish packages** — PyPI uploads are **tag-drive 1. **PyPI:** add a **trusted publisher** for **[github.com/flightdeckdev/flightdeck](https://github.com/flightdeckdev/flightdeck)** — workflow **`release-pypi.yml`**. If PyPI offers **Environment name: (Any)**, you can still use a GitHub **Environment** named **`pypi`** for approval gates; otherwise match whatever you register on PyPI ([trusted publishers](https://docs.pypi.org/trusted-publishers/)). 2. **GitHub:** Settings → **Environments** → create **`pypi`** (optional: required reviewers / wait timer before OIDC publish). 3. Bump **`version`** in **`pyproject.toml`** and **`src/flightdeck/__init__.py`**, update **`CHANGELOG.md`**, merge to **`main`**. -4. **`git tag vX.Y.Z`** (must match **`pyproject.toml`** exactly, e.g. **`v1.0.4`**) then **`git push origin vX.Y.Z`**. +4. **`git tag vX.Y.Z`** (must match **`pyproject.toml`** exactly, e.g. **`v1.0.6`**) then **`git push origin vX.Y.Z`**. The workflow runs **ruff**, **pytest**, schema drift, **`uv build`**, publishes **sdist + wheel** to **PyPI** via **OIDC** (no long-lived API token in repo secrets), enables **publish attestations**, and creates a **GitHub Release** with generated notes and **`dist/*`** assets. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c0bc3c1..835a237 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,6 +4,14 @@ High-level notes for **shipping FlightDeck**. Detailed history: **[CHANGELOG.md] Narrative docs (including the CLI reference) are maintained on **[github.com/flightdeckdev/flightdeck](https://github.com/flightdeckdev/flightdeck)** `main`; this file and **`schemas/`** ship in minimal clones. +## v1.0.6 — Phase 0 closure (backup, cross-language emitters, roadmap) + +Patch release (see **[CHANGELOG.md](CHANGELOG.md)**): **`flightdeck doctor --backup PATH`** performs a SQLite online backup of the workspace DB; **[examples/integration/](examples/integration/README.md)** gains **`curl`** and a **Node** **`emit_sample_events.node.mjs`** path for **`POST /v1/events`**; **[examples/deploy/README.md](examples/deploy/README.md)** documents the Compose **`/health`** healthcheck and backup scheduling. **ROADMAP:** **Phase 0** is **closed**; **catalog-level** multi-provider pricing normalization is an explicit **Phase 1** build item. **Stable contracts:** additive CLI flag and HTTP field **`pricing.warnings`** (from **v1.0.5**) remain backward-compatible. + +## v1.0.5 — Diff JSON output, pricing warnings, metrics in Overview + +Patch release (see **[CHANGELOG.md](CHANGELOG.md)**): **`flightdeck release diff --output json`** matches **`POST /v1/diff`** for machine consumers; **`pricing.warnings`** surfaces missing pricing-table rows for a release's resolved model (CLI **`WARNING:`** lines + web); **Overview** shows **`GET /v1/metrics`** counters. **Stable contracts:** additive only. + ## v1.0.4 — Phase 0 closing slice (pricing diagnostic, examples index, metrics) Patch release (see **[CHANGELOG.md](CHANGELOG.md)**): **`GET /v1/metrics`** exposes additive JSON counters for operators; **`POST /v1/diff`** and **`flightdeck release diff`** add **`pricing.prices`** / a **Per-1k token prices** line when pricing or model differs, so cost deltas are easier to interpret; **[examples/README.md](examples/README.md)** ties **integration**, **CI**, and **deploy** examples into one loop; web **Run diff** shows the same unit-price deltas when present. **Stable contracts:** additive HTTP and CLI output only; no **`v1`** payload or schema removals. diff --git a/ROADMAP.md b/ROADMAP.md index f53ed46..cb8b440 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -14,22 +14,14 @@ This roadmap is meant to be clear from **what is already shipped** to **near-ter - **Economic + operational governance:** immutable pricing imports, trusted `release diff`, policy-gated `promote` and `rollback`. - **Audit trail:** promotion/rollback history with stable sequencing (`audit_seq`) and integrity checks via `doctor`. - **Evidence ingestion:** `runs ingest` from JSONL/JSON arrays plus stable `POST /v1/events` contracts (`schemas/v1/`). -- **Local API + UI:** `flightdeck serve` routes and web UI (Overview, Diff, Promote) in `src/flightdeck/server/static/`. +- **Local API + UI:** `flightdeck serve` routes and web UI (Overview with ledger metrics, Diff, Promote) in `src/flightdeck/server/static/`. - **SDK and tooling:** Python sync/async clients with retries/batching and `flightdeck-quickstart-verify`. --- ## Next release -**v1.0.4 is shipped.** See **[CHANGELOG.md](CHANGELOG.md)** for the full list of additions. The -v1.0.4 slice delivered: `GET /v1/metrics` (JSON ledger counters), `pricing.prices` on -`POST /v1/diff`, CLI **Per-1k token prices** output, matching web diff banner detail, and the -**[examples/README.md](examples/README.md)** end-to-end walkthrough. - -**v1.0.5 / next patch:** candidates include documentation completeness improvements (time-window -semantics, error message catalog, checksum format, tenant/task filter scope in UI), and -continued Phase 0 hardening. No breaking changes expected to stable CLI, HTTP, or -**`api_version` `v1`** contracts. +**v1.0.6** (patch): Phase 0 closure — **`flightdeck release diff --output json`** (same shape as **`POST /v1/diff`**); **`pricing.warnings`** when a release model has no row in its pricing table (CLI **`WARNING:`** lines + web Diff); **Overview** ledger metrics card (**`GET /v1/metrics`**); **`curl`** + **Node** samples under **[examples/integration/](examples/integration/README.md)**; **`flightdeck doctor --backup PATH`** (SQLite online backup); **[examples/deploy/](examples/deploy/README.md)** documents Compose **`/health`** healthcheck and backup scheduling. **Phase 0** is declared **closed**; **catalog-level** multi-provider normalization moves to **Phase 1**. See **[CHANGELOG.md](CHANGELOG.md)** and **[RELEASE_NOTES.md](RELEASE_NOTES.md)**. No breaking changes to stable CLI, HTTP, or **`api_version` `v1`** contracts. --- @@ -57,11 +49,11 @@ Goal: prove the wedge with real teams using FlightDeck as release governance sou - Harden CLI/schema contracts and edge-case policy coverage (sample windows, sparse traffic, error paths). - Add concrete integration references: app runtime event emitters, CI pipeline examples, and deployment recipes for `flightdeck serve`. -- Improve pricing normalization for multiple provider inputs while keeping diff semantics stable. +- **Catalog-level cross-vendor pricing normalization** — deferred to **Phase 1** (see Phase 1 build list). **v1.0.4–v1.0.6** ship per-side **`pricing.prices`** and **`pricing.warnings`** diagnostics only. - Strengthen local security ergonomics: explicit token/env status in UI, mutation guardrails, optional read-only UX. - Continue UI productization for current scope (structured views over raw JSON where stable). -### Phase 0 progress (v1.0.3–v1.0.4) +### Phase 0 progress (v1.0.3–v1.0.6) Shipped on **`main`**: @@ -72,8 +64,14 @@ Shipped on **`main`**: - **Pricing diagnostics (v1.0.4):** **`pricing.prices`** on **`POST /v1/diff`** and matching CLI / web lines for per-1k input/output unit prices when pricing or model differs. - **Operating narrative (v1.0.4):** **[examples/README.md](examples/README.md)** index tying emit → ingest → verify → diff/gate → promote → serve. - **Observability foundation (v1.0.4):** **`GET /v1/metrics`** JSON counters over the local ledger (not Prometheus/OTel; longer arc stays mid term). +- **Diff ergonomics (v1.0.5):** **`flightdeck release diff --output json`**; **`pricing.warnings`** on **`POST /v1/diff`** / CLI / web when the release model is missing from the imported pricing table; **Overview** shows key **`GET /v1/metrics`** counters. +- **Operator + pipeline breadth (v1.0.6):** **`curl`** and **Node** **`emit_sample_events.node.mjs`** under **[examples/integration/](examples/integration/README.md)**; **`flightdeck doctor --backup`**; deploy README covers healthcheck + backup scheduling. + +### Phase 0 status + +**Phase 0 is closed** as of **v1.0.6** for the local-first wedge (immutable releases, evidence ingest, diff + policy gate, promote/rollback, audit, CI/deploy/integration references, metrics, diagnostics, and operator backup ergonomics). -**Still open in Phase 0** (see gaps table and Phase 1): **catalog-level** multi-provider normalization (single comparable unit across vendors), deeper **event pipeline** and **fleet** ergonomics, and **OTLP-oriented** telemetry remain beyond this patch. +**Carried forward to Phase 1** (see gaps table): **catalog-level** multi-provider pricing normalization (single comparable unit across vendors), deeper **fleet** ergonomics, and **OTLP-oriented** telemetry — not blocking further patch releases on the Phase 0 spine. ### Phase-0 success signals @@ -91,7 +89,8 @@ Goal: move from solid local tooling to repeatable production usage patterns. ### Build in this phase - Human-in-the-loop approval workflow on top of policy gates (without requiring a hosted control plane). -- Stronger multi-provider pricing normalization and clearer mismatch diagnostics. +- **Catalog-level multi-provider pricing normalization** — single comparable tariff unit across vendors; additive to today's per-provider **`pricing import`** tables and **`pricing.prices`** / **`pricing.warnings`** diagnostics. +- Stronger mismatch diagnostics beyond table row presence (for example version skew hints) as needed for the catalog work. - Incident forensics improvements (replay/trace-style analysis over ingested evidence) as governance support tooling. - Deployment hardening artifacts (for example Helm or equivalent) if a blessed server topology is chosen. - Multi-workspace operator ergonomics (naming, templates, reproducible setup patterns). diff --git a/docs/cli.md b/docs/cli.md index ed15fa6..42b2eff 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -71,10 +71,14 @@ in a shared repo. See [release-artifact.md § Workspace config](release-artifact Run read-only health checks on the local SQLite ledger. ```bash -flightdeck doctor +flightdeck doctor [--backup PATH] ``` -No flags. Calls `Storage.migrate()` at start (idempotent) and then checks: +Calls `Storage.migrate()` at start (idempotent). With **`--backup PATH`**, runs an SQLite +online backup of the workspace database to **`PATH`** (parent directories are created; +an existing file is overwritten), then runs the checks below. + +Without **`--backup`**, only the checks run. In both cases **`migrate()`** runs first. | Check | What it verifies | |-------|-----------------| @@ -216,11 +220,16 @@ flightdeck release diff BASELINE_ID CANDIDATE_ID --window WINDOW [OPTIONS] | `--tenant` | Filter events by `tenant_id` | | `--task` | Filter events by `task_id` | | `--fail-on-policy` | After printing the diff, exit **1** when the active policy does not pass (for CI gates). | +| `--output` | `text` (default) or `json`. **`json`**: same JSON object as **`POST /v1/diff`** (stable keys for `jq` / CI parsers). With **`--fail-on-policy`**, JSON is still printed to stdout before exit **1**. | Both releases must have the same `agent_id`. Cross-agent diffs are rejected with exit 1. **Exit codes:** invalid input, missing pricing, or other `OperationError` → non-zero. With **`--fail-on-policy`**, a computed diff whose policy result is **FAIL** also exits **1** (after the usual stdout). +When a release's resolved model has **no row** in its pricing table, the diff still completes +(if rollups do not need that rate for ingested events), and the CLI prints **`WARNING:`** lines +and JSON includes **`pricing.warnings`** — diagnostic only; policy is unchanged. + The diff is a **read-only computation** — it does not write to the audit ledger or update any promoted pointers. diff --git a/docs/http-api.md b/docs/http-api.md index 9517e20..6df3871 100644 --- a/docs/http-api.md +++ b/docs/http-api.md @@ -351,7 +351,8 @@ included. "candidate_input_usd_per_1k_tokens": 0.0045, "candidate_output_usd_per_1k_tokens": 0.0135, "candidate_cached_input_usd_per_1k_tokens": null - } + }, + "warnings": [] }, "samples": { "baseline_runs": 1200, @@ -379,6 +380,12 @@ included. } ``` +**`pricing.warnings`** — array of human-readable strings when the baseline or candidate +release's **`spec.runtime.model`** has no matching entry in that side's imported pricing +table. Per-side **`prices.*`** fields are **`null`** in that case. Warnings are **informational +only** and do not change **`policy`**. If ingested run events reference a model that cannot +be priced, the diff request still fails with HTTP 400 as before. + **Confidence levels** | Label | Meaning | diff --git a/docs/operations-and-policy.md b/docs/operations-and-policy.md index 7c3e26c..4c16fd2 100644 --- a/docs/operations-and-policy.md +++ b/docs/operations-and-policy.md @@ -190,6 +190,11 @@ following differ between baseline and candidate: These fields are populated by `pricing_entry_for(table, model)` in `flightdeck.ledger` after `diff_releases` returns and before the `DiffOutcome` is constructed. +`DiffOutcome.pricing_warnings` is a tuple of human-readable strings when the release artifact's +`spec.runtime.model` has **no** matching row in that side's imported pricing table. Warnings are +**diagnostic only** (they do not change `policy`). If ingested events reference a model that +cannot be priced, `compute_rollup` still raises and `compute_diff` surfaces that as before. + **CLI output** — when `pricing_or_model_changed` is `True`, the CLI prints: ``` @@ -200,8 +205,12 @@ Per-1k token prices: input 0.005000 -> 0.004500, output 0.015000 -> 0.013500 The **Per-1k token prices** line is only printed when both input and output rates are present for both sides. If any rate is `None`, that line is omitted. +When `pricing_warnings` is non-empty, the CLI also prints one **`WARNING:`** line per string +before the `NOTE:` / per-1k lines. + **HTTP API** — `/v1/diff` includes a `pricing.prices` object alongside the existing -`pricing_or_model_changed` flag: +`pricing_or_model_changed` flag and a `pricing.warnings` string array (empty when both models +resolve to a table row): ```json "pricing": { @@ -219,14 +228,16 @@ for both sides. If any rate is `None`, that line is omitted. "candidate_input_usd_per_1k_tokens": 0.0045, "candidate_output_usd_per_1k_tokens": 0.0135, "candidate_cached_input_usd_per_1k_tokens": null - } + }, + "warnings": [] } ``` `pricing.prices` is always present in the response (not gated on `pricing_or_model_changed`). Fields are `null` when the rate is not set in the pricing table. -**Web UI** — the `DiffPage` `fd-alert--warn` banner shows the per-1k input/output price deltas +**Web UI** — the `DiffPage` shows `pricing.warnings` as a warning list when non-empty, then the +`fd-alert--warn` banner for `pricing_or_model_changed` when applicable, and the per-1k input/output price deltas (baseline → candidate) when all four rates are present. See [web-ui.md § DiffPage](web-ui.md). This is an informational signal — the diff still computes and the policy still evaluates; cost diff --git a/docs/web-ui.md b/docs/web-ui.md index 1afb9b5..b1a3bc3 100644 --- a/docs/web-ui.md +++ b/docs/web-ui.md @@ -16,7 +16,7 @@ The app uses **HashRouter** (`react-router-dom`) so all navigation stays within | Hash path | Component | HTTP calls | Notes | |-----------|-----------|-----------|-------| -| `#/` | `OverviewPage` | `GET /v1/releases`, `GET /v1/promoted`, `GET /v1/actions` (parallel) | | +| `#/` | `OverviewPage` | `GET /v1/releases`, `GET /v1/promoted`, `GET /v1/actions`, `GET /v1/metrics` (parallel where applicable) | Ledger metrics card is read-only counters | | `#/diff` | `DiffPage` | `POST /v1/diff` | | | `#/actions` | `ActionsPage` | `POST /v1/promote` or `POST /v1/rollback` | Redirects to `#/` when `VITE_FLIGHTDECK_UI_READ_ONLY=true` | | `#/*` (any other) | — | Redirects to `#/` | | @@ -121,10 +121,11 @@ fail. This is a configuration hint only — the server enforces the actual gate. ## `OverviewPage` (`web/src/pages/OverviewPage.tsx`) -Read-only dashboard. Renders three tables from `loadTimeline()` output: +Read-only dashboard. Renders a **Ledger metrics** card from `fetchMetrics()` plus three tables from `loadTimeline()` output: -| Table | Source | Columns | +| Block | Source | Content | |-------|--------|---------| +| Ledger metrics | `GET /v1/metrics` | Releases, pricing tables, run events, promoted pointers, and actions totals (plus `actions_by_action` breakdown), `schema_version`, `generated_at` | | Releases | `GET /v1/releases` | Release ID, Agent, Version, Environment, Checksum, Created | | Promoted | `GET /v1/promoted` | Agent, Environment, Active release | | Recent actions | `GET /v1/actions` | When, Action, Policy (PASS/FAIL badge), Release, Environment, Reason | @@ -160,6 +161,8 @@ On submit, the raw diff response is parsed and rendered as: - **Summary card:** policy badge (PASS / FAIL), failure reasons list, sample counts and confidence label (including `confidence_reason` when present). +- **Pricing table warnings:** when `pricing.warnings` is a non-empty string array, a + `fd-alert--warn` list is shown above the pricing/model-change banner (diagnostic only). - **Pricing change warning:** when the diff response includes a `pricing` block with `pricing_or_model_changed: true`, a `fd-alert--warn` banner is shown in the summary card. It names the baseline and candidate provider/version/model so the user knows the diff --git a/examples/ci/README.md b/examples/ci/README.md index 745c0c4..c53cd18 100644 --- a/examples/ci/README.md +++ b/examples/ci/README.md @@ -37,7 +37,7 @@ uv run python examples/ci/ledger_gate.py Example (**PyPI** install): ```bash -pip install "flightdeck-ai>=1.0.4" +pip install "flightdeck-ai>=1.0.6" export WORKSPACE="$(mktemp -d)" export QUICKSTART_ROOT=/path/to/flightdeck/examples/quickstart python /path/to/flightdeck/examples/ci/ledger_gate.py diff --git a/examples/ci/github-actions/policy-gate-pypi.yml b/examples/ci/github-actions/policy-gate-pypi.yml index 2dcb2a1..5a43c1b 100644 --- a/examples/ci/github-actions/policy-gate-pypi.yml +++ b/examples/ci/github-actions/policy-gate-pypi.yml @@ -11,7 +11,7 @@ on: env: # Pin to a tag or SHA that matches your installed flightdeck-ai version when possible. FLIGHTDECK_REF: main - FLIGHTDECK_AI_SPEC: ">=1.0.4" + FLIGHTDECK_AI_SPEC: ">=1.0.6" jobs: ledger-gate: diff --git a/examples/deploy/Dockerfile b/examples/deploy/Dockerfile index e98f49a..e193bdd 100644 --- a/examples/deploy/Dockerfile +++ b/examples/deploy/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.14-slim RUN pip install --no-cache-dir --upgrade pip \ - && pip install --no-cache-dir "flightdeck-ai>=1.0.4" + && pip install --no-cache-dir "flightdeck-ai>=1.0.6" WORKDIR /workspace diff --git a/examples/deploy/README.md b/examples/deploy/README.md index 0878277..6544095 100644 --- a/examples/deploy/README.md +++ b/examples/deploy/README.md @@ -23,8 +23,19 @@ docker compose up --build - **UI + API:** `http://127.0.0.1:8765/` (static UI + `/v1/*`). - **Health:** `GET http://127.0.0.1:8765/health`. +- **Compose healthcheck:** `docker-compose.yml` probes **`/health`** so orchestrators can mark the service ready (see `healthcheck:` in that file). - **Data:** named Docker volume **`fd_workspace`** (SQLite under **`.flightdeck/`** inside the volume). Remove with `docker compose down -v` when you want a clean ledger. +### SQLite backups + +FlightDeck stores the ledger in **`.flightdeck/flightdeck.db`** under the workspace root. For a **hot copy** while the server is stopped or idle, run from the workspace directory: + +```bash +flightdeck doctor --backup ./backups/flightdeck-$(date -u +%Y%m%dT%H%M%SZ).db +``` + +Inside the Compose stack, **`exec`** into the running container with **`/workspace`** as cwd (same layout as local **`flightdeck init`**), or run a one-shot sidecar that mounts the same volume and invokes **`flightdeck doctor --backup /workspace/backups/snapshot.db`**. Schedule with **cron** or your platform scheduler; keep backups off the primary volume when possible. + ### Optional mutation token Set **`FLIGHTDECK_LOCAL_API_TOKEN`** in your environment before `docker compose up` (or in an `.env` file beside `docker-compose.yml`). Clients must send **`Authorization: Bearer …`** for **`POST /v1/promote`** and **`POST /v1/rollback`**. Ingest and diff are **not** behind this Bearer gate by default—treat network placement accordingly. @@ -42,7 +53,7 @@ Use an absolute path on Linux/macOS; on Windows Docker Desktop, use a path Docke ## Process supervision -Compose provides restart policies; for systemd/Kubernetes, reuse the same image and run **`/entrypoint.sh`** (or invoke **`flightdeck serve`** directly with a prepared workspace directory). +Compose sets a **`healthcheck`** on **`/health`** plus restart policies; for systemd/Kubernetes, reuse the same image and run **`/entrypoint.sh`** (or invoke **`flightdeck serve`** directly with a prepared workspace directory). ## Related diff --git a/examples/integration/README.md b/examples/integration/README.md index e96115a..fef3160 100644 --- a/examples/integration/README.md +++ b/examples/integration/README.md @@ -31,6 +31,47 @@ python examples/integration/emit_sample_events.py --release-id rel_abc123 --agen The HTTP body is `{"events": [, ...]}` with **`api_version`: `"v1"`**. Field reference: **[docs/http-api.md](../../docs/http-api.md)** and **`schemas/v1/run_event.schema.json`**. +### `curl` (no SDK) + +Replace **`REL_ID`**, **`AGENT`**, and optionally **`BASE`** (default `http://127.0.0.1:8765`): + +```bash +BASE=http://127.0.0.1:8765 +REL_ID=rel_yourregisteredid +AGENT=agent_support +RUN_ID=emit-curl-$(date +%s) +TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + +curl -sS -X POST "$BASE/v1/events" \ + -H 'Content-Type: application/json' \ + -d "$(jq -n \ + --arg rid "$REL_ID" \ + --arg aid "$AGENT" \ + --arg run "$RUN_ID" \ + --arg ts "$TS" \ + '{events:[{ + api_version:"v1", type:"run_end", timestamp:$ts, + workspace_id:"ws_local", agent_id:$aid, release_id:$rid, run_id:$run, + tenant_id:"tenant_example", task_id:"task_example", environment:"local", + metrics:{latency_ms:250, success:true, error_type:null}, + usage:{model:{provider:"openai", model:"gpt-4.1-mini", input_tokens:400, output_tokens:120, cached_input_tokens:0}, tools:[]}, + labels:{source:"curl-example"} + }]}')" +``` + +Without **`jq`**, paste a static JSON file or use the Node script below. + +### Node (`emit_sample_events.node.mjs`) + +Uses built-in **`fetch`** (Node **18+**). No npm dependencies: + +```bash +node examples/integration/emit_sample_events.node.mjs \ + --base-url http://127.0.0.1:8765 \ + --release-id rel_yourregisteredid \ + --agent-id agent_support +``` + ### Trust boundaries Anyone who can reach **`POST /v1/events`** can append ledger rows for a `release_id` they guess. Keep **`serve`** on loopback or a private network, or front it with your own controls. See **[SECURITY.md](../../SECURITY.md)**. diff --git a/examples/integration/emit_sample_events.node.mjs b/examples/integration/emit_sample_events.node.mjs new file mode 100644 index 0000000..3736fb6 --- /dev/null +++ b/examples/integration/emit_sample_events.node.mjs @@ -0,0 +1,70 @@ +/** + * Minimal POST /v1/events sample (Node 18+ with global fetch, or Node 20+). + * + * node examples/integration/emit_sample_events.node.mjs \ + * --base-url http://127.0.0.1:8765 \ + * --release-id rel_yourregisteredid \ + * --agent-id agent_support + * + * Same envelope as emit_sample_events.py: { "events": [ RunEvent, ... ] }. + */ +function arg(name, fallback = null) { + const i = process.argv.indexOf(name); + if (i === -1 || i + 1 >= process.argv.length) return fallback; + return process.argv[i + 1]; +} + +const baseUrl = (arg("--base-url", "http://127.0.0.1:8765") ?? "http://127.0.0.1:8765").replace(/\/$/, ""); +const releaseId = arg("--release-id"); +const agentId = arg("--agent-id"); +const environment = arg("--environment", "local") ?? "local"; + +if (!releaseId || !agentId) { + console.error("Usage: node emit_sample_events.node.mjs --release-id REL --agent-id AGENT [--base-url URL] [--environment ENV]"); + process.exit(2); +} + +const rid = Math.random().toString(16).slice(2, 12); +const ts = new Date().toISOString(); + +const event = { + api_version: "v1", + type: "run_end", + timestamp: ts, + workspace_id: "ws_local", + agent_id: agentId, + release_id: releaseId, + run_id: `emit-sample-node-${rid}`, + tenant_id: "tenant_example", + task_id: "task_example", + environment, + metrics: { latency_ms: 250, success: true, error_type: null }, + usage: { + model: { + provider: "openai", + model: "gpt-4.1-mini", + input_tokens: 400, + output_tokens: 120, + cached_input_tokens: 0, + }, + tools: [], + }, + labels: { source: "examples/integration/emit_sample_events.node.mjs" }, +}; + +const body = JSON.stringify({ events: [event] }); + +const url = `${baseUrl}/v1/events`; +const res = await fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body, +}); + +const text = await res.text(); +if (!res.ok) { + console.error(`HTTP ${res.status}: ${text}`); + process.exit(1); +} +console.log(`POST ${url} -> ${res.status}`); +console.log(text); diff --git a/pyproject.toml b/pyproject.toml index 1b07eee..e21eda7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "flightdeck-ai" -version = "1.0.4" +version = "1.0.6" description = "AI Release Governance for production agents." readme = "README.md" license = "Apache-2.0" diff --git a/src/flightdeck/__init__.py b/src/flightdeck/__init__.py index 5abc00e..f8979f4 100644 --- a/src/flightdeck/__init__.py +++ b/src/flightdeck/__init__.py @@ -1,3 +1,3 @@ """FlightDeck - AI Release Governance for production agents.""" -__version__ = "1.0.4" +__version__ = "1.0.6" diff --git a/src/flightdeck/cli/main.py b/src/flightdeck/cli/main.py index bad85a6..073b812 100644 --- a/src/flightdeck/cli/main.py +++ b/src/flightdeck/cli/main.py @@ -79,10 +79,20 @@ def init(path_: str) -> None: @cli.command("doctor") -def doctor_cmd() -> None: +@click.option( + "--backup", + "backup_path", + type=click.Path(path_type=Path, dir_okay=False), + default=None, + help="Copy the workspace SQLite database to PATH (online backup), then run checks.", +) +def doctor_cmd(backup_path: Path | None) -> None: """Run read-only health checks on the local ledger (migrations, promoted pointers).""" cfg = load_config() storage = Storage(cfg.db_path) + if backup_path is not None: + storage.backup_to(backup_path) + click.echo(f"Backed up database to {backup_path}") checks = run_doctor(storage) failed = False for c in checks: @@ -327,6 +337,14 @@ def runs_ingest(path: Path) -> None: default=False, help="Exit with code 1 when the active policy does not pass (after printing the diff).", ) +@click.option( + "--output", + "output_format", + type=click.Choice(["text", "json"]), + default="text", + show_default=True, + help="Output format. 'json' emits the same shape as POST /v1/diff for machine consumers.", +) def release_diff( baseline_release_id: str, candidate_release_id: str, @@ -335,6 +353,7 @@ def release_diff( task_id: str | None, environment: str | None, fail_on_policy: bool, + output_format: str, ) -> None: """Compare two releases over a time window and print a confidence-labeled safety diff.""" cfg = load_config() @@ -354,6 +373,59 @@ def release_diff( except OperationError as e: raise click.ClickException(str(e)) from e + if output_format == "json": + body = { + "window": result.window, + "since": result.since.isoformat(), + "until": result.until.isoformat(), + "filters": { + "environment": result.environment, + "tenant_id": result.tenant_id, + "task_id": result.task_id, + }, + "pricing": { + "baseline_provider": result.baseline_pricing_provider, + "baseline_version": result.baseline_pricing_version, + "baseline_model": result.baseline_model, + "candidate_provider": result.candidate_pricing_provider, + "candidate_version": result.candidate_pricing_version, + "candidate_model": result.candidate_model, + "pricing_or_model_changed": result.pricing_or_model_changed, + "prices": { + "baseline_input_usd_per_1k_tokens": result.baseline_input_usd_per_1k_tokens, + "baseline_output_usd_per_1k_tokens": result.baseline_output_usd_per_1k_tokens, + "baseline_cached_input_usd_per_1k_tokens": result.baseline_cached_input_usd_per_1k_tokens, + "candidate_input_usd_per_1k_tokens": result.candidate_input_usd_per_1k_tokens, + "candidate_output_usd_per_1k_tokens": result.candidate_output_usd_per_1k_tokens, + "candidate_cached_input_usd_per_1k_tokens": result.candidate_cached_input_usd_per_1k_tokens, + }, + "warnings": list(result.pricing_warnings), + }, + "samples": { + "baseline_runs": result.baseline_runs, + "candidate_runs": result.candidate_runs, + "confidence": result.confidence, + "confidence_reason": result.confidence_reason, + }, + "metrics": { + "baseline_cost_per_run_usd": result.baseline_cost_per_run_usd, + "candidate_cost_per_run_usd": result.candidate_cost_per_run_usd, + "delta_cost_per_run_usd": result.delta_cost_per_run_usd, + "delta_cost_per_run_pct": result.delta_cost_per_run_pct, + "baseline_latency_ms_avg": result.baseline_latency_ms_avg, + "candidate_latency_ms_avg": result.candidate_latency_ms_avg, + "delta_latency_ms_avg": result.delta_latency_ms_avg, + "baseline_error_rate": result.baseline_error_rate, + "candidate_error_rate": result.candidate_error_rate, + "delta_error_rate": result.delta_error_rate, + }, + "policy": result.policy.model_dump(mode="json"), + } + click.echo(json.dumps(body, indent=2, sort_keys=True)) + if fail_on_policy and not result.policy.passed: + raise click.ClickException("Policy gate: diff blocked by active policy (see policy.reasons in JSON output).") + return + click.echo(f"Window: {window} ({result.since.isoformat()} .. {result.until.isoformat()})") click.echo(f"Filters: env={result.environment} tenant={tenant_id or '*'} task={task_id or '*'}") click.echo( @@ -364,6 +436,8 @@ def release_diff( f"Candidate pricing: {result.candidate_pricing_provider}/{result.candidate_pricing_version} " f"(model={result.candidate_model})" ) + for w in result.pricing_warnings: + click.echo(f"WARNING: {w}") if result.pricing_or_model_changed: click.echo("NOTE: cost delta includes pricing/model assumption changes (pricing reference and/or model differ).") if ( diff --git a/src/flightdeck/operations.py b/src/flightdeck/operations.py index 274c5d7..0bc7efd 100644 --- a/src/flightdeck/operations.py +++ b/src/flightdeck/operations.py @@ -58,6 +58,7 @@ class DiffOutcome: candidate_error_rate: float delta_error_rate: float policy: PolicyResult + pricing_warnings: tuple[str, ...] @dataclass(frozen=True) @@ -193,6 +194,18 @@ def compute_diff( base_entry = pricing_entry_for(base_table, base_artifact.spec.runtime.model) cand_entry = pricing_entry_for(cand_table, cand_artifact.spec.runtime.model) + pricing_warnings: list[str] = [] + if base_entry is None: + pricing_warnings.append( + f"baseline pricing table {base_ref.provider}/{base_ref.pricing_version} " + f"has no entry for model {base_artifact.spec.runtime.model!r}" + ) + if cand_entry is None: + pricing_warnings.append( + f"candidate pricing table {cand_ref.provider}/{cand_ref.pricing_version} " + f"has no entry for model {cand_artifact.spec.runtime.model!r}" + ) + return DiffOutcome( window=window, since=since, @@ -236,6 +249,7 @@ def compute_diff( candidate_error_rate=diff.candidate.error_rate, delta_error_rate=diff.delta_error_rate, policy=diff.policy, + pricing_warnings=tuple(pricing_warnings), ) diff --git a/src/flightdeck/server/routes/actions.py b/src/flightdeck/server/routes/actions.py index 28020be..f2632ae 100644 --- a/src/flightdeck/server/routes/actions.py +++ b/src/flightdeck/server/routes/actions.py @@ -117,6 +117,11 @@ def post_diff(request: Request, req: DiffRequest) -> dict[str, object]: "candidate_output_usd_per_1k_tokens": result.candidate_output_usd_per_1k_tokens, "candidate_cached_input_usd_per_1k_tokens": result.candidate_cached_input_usd_per_1k_tokens, }, + # Diagnostic strings when a release's resolved model has no entry + # in its pricing table; the cost rollup still raises if such a + # model appears in events. These are informational only and do + # not flip policy. + "warnings": list(result.pricing_warnings), }, "samples": { "baseline_runs": result.baseline_runs, diff --git a/src/flightdeck/server/static/assets/index-92annNc3.js b/src/flightdeck/server/static/assets/index-92annNc3.js new file mode 100644 index 0000000..85ff6f3 --- /dev/null +++ b/src/flightdeck/server/static/assets/index-92annNc3.js @@ -0,0 +1,11 @@ +(function(){const s=document.createElement("link").relList;if(s&&s.supports&&s.supports("modulepreload"))return;for(const d of document.querySelectorAll('link[rel="modulepreload"]'))f(d);new MutationObserver(d=>{for(const h of d)if(h.type==="childList")for(const b of h.addedNodes)b.tagName==="LINK"&&b.rel==="modulepreload"&&f(b)}).observe(document,{childList:!0,subtree:!0});function o(d){const h={};return d.integrity&&(h.integrity=d.integrity),d.referrerPolicy&&(h.referrerPolicy=d.referrerPolicy),d.crossOrigin==="use-credentials"?h.credentials="include":d.crossOrigin==="anonymous"?h.credentials="omit":h.credentials="same-origin",h}function f(d){if(d.ep)return;d.ep=!0;const h=o(d);fetch(d.href,h)}})();var Cf={exports:{}},Mn={};var im;function yy(){if(im)return Mn;im=1;var i=Symbol.for("react.transitional.element"),s=Symbol.for("react.fragment");function o(f,d,h){var b=null;if(h!==void 0&&(b=""+h),d.key!==void 0&&(b=""+d.key),"key"in d){h={};for(var N in d)N!=="key"&&(h[N]=d[N])}else h=d;return d=h.ref,{$$typeof:i,type:f,key:b,ref:d!==void 0?d:null,props:h}}return Mn.Fragment=s,Mn.jsx=o,Mn.jsxs=o,Mn}var cm;function py(){return cm||(cm=1,Cf.exports=yy()),Cf.exports}var m=py(),Uf={exports:{}},P={};var fm;function gy(){if(fm)return P;fm=1;var i=Symbol.for("react.transitional.element"),s=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),f=Symbol.for("react.strict_mode"),d=Symbol.for("react.profiler"),h=Symbol.for("react.consumer"),b=Symbol.for("react.context"),N=Symbol.for("react.forward_ref"),S=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),j=Symbol.for("react.lazy"),A=Symbol.for("react.activity"),q=Symbol.iterator;function H(g){return g===null||typeof g!="object"?null:(g=q&&g[q]||g["@@iterator"],typeof g=="function"?g:null)}var Z={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},G=Object.assign,B={};function Q(g,U,Y){this.props=g,this.context=U,this.refs=B,this.updater=Y||Z}Q.prototype.isReactComponent={},Q.prototype.setState=function(g,U){if(typeof g!="object"&&typeof g!="function"&&g!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,g,U,"setState")},Q.prototype.forceUpdate=function(g){this.updater.enqueueForceUpdate(this,g,"forceUpdate")};function V(){}V.prototype=Q.prototype;function $(g,U,Y){this.props=g,this.context=U,this.refs=B,this.updater=Y||Z}var F=$.prototype=new V;F.constructor=$,G(F,Q.prototype),F.isPureReactComponent=!0;var le=Array.isArray;function be(){}var X={H:null,A:null,T:null,S:null},Ne=Object.prototype.hasOwnProperty;function Ke(g,U,Y){var K=Y.ref;return{$$typeof:i,type:g,key:U,ref:K!==void 0?K:null,props:Y}}function Ct(g,U){return Ke(g.type,U,g.props)}function vt(g){return typeof g=="object"&&g!==null&&g.$$typeof===i}function Je(g){var U={"=":"=0",":":"=2"};return"$"+g.replace(/[=:]/g,function(Y){return U[Y]})}var Ut=/\/+/g;function yt(g,U){return typeof g=="object"&&g!==null&&g.key!=null?Je(""+g.key):U.toString(36)}function Ce(g){switch(g.status){case"fulfilled":return g.value;case"rejected":throw g.reason;default:switch(typeof g.status=="string"?g.then(be,be):(g.status="pending",g.then(function(U){g.status==="pending"&&(g.status="fulfilled",g.value=U)},function(U){g.status==="pending"&&(g.status="rejected",g.reason=U)})),g.status){case"fulfilled":return g.value;case"rejected":throw g.reason}}throw g}function D(g,U,Y,K,ee){var ne=typeof g;(ne==="undefined"||ne==="boolean")&&(g=null);var me=!1;if(g===null)me=!0;else switch(ne){case"bigint":case"string":case"number":me=!0;break;case"object":switch(g.$$typeof){case i:case s:me=!0;break;case j:return me=g._init,D(me(g._payload),U,Y,K,ee)}}if(me)return ee=ee(g),me=K===""?"."+yt(g,0):K,le(ee)?(Y="",me!=null&&(Y=me.replace(Ut,"$&/")+"/"),D(ee,U,Y,"",function(La){return La})):ee!=null&&(vt(ee)&&(ee=Ct(ee,Y+(ee.key==null||g&&g.key===ee.key?"":(""+ee.key).replace(Ut,"$&/")+"/")+me)),U.push(ee)),1;me=0;var We=K===""?".":K+":";if(le(g))for(var je=0;je>>1,_e=D[ye];if(0>>1;yed(Y,I))K<_e&&0>d(ee,Y)?(D[ye]=ee,D[K]=I,ye=K):(D[ye]=Y,D[U]=I,ye=U);else if(K<_e&&0>d(ee,I))D[ye]=ee,D[K]=I,ye=K;else break e}}return L}function d(D,L){var I=D.sortIndex-L.sortIndex;return I!==0?I:D.id-L.id}if(i.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var h=performance;i.unstable_now=function(){return h.now()}}else{var b=Date,N=b.now();i.unstable_now=function(){return b.now()-N}}var S=[],y=[],j=1,A=null,q=3,H=!1,Z=!1,G=!1,B=!1,Q=typeof setTimeout=="function"?setTimeout:null,V=typeof clearTimeout=="function"?clearTimeout:null,$=typeof setImmediate<"u"?setImmediate:null;function F(D){for(var L=o(y);L!==null;){if(L.callback===null)f(y);else if(L.startTime<=D)f(y),L.sortIndex=L.expirationTime,s(S,L);else break;L=o(y)}}function le(D){if(G=!1,F(D),!Z)if(o(S)!==null)Z=!0,be||(be=!0,Je());else{var L=o(y);L!==null&&Ce(le,L.startTime-D)}}var be=!1,X=-1,Ne=5,Ke=-1;function Ct(){return B?!0:!(i.unstable_now()-KeD&&Ct());){var ye=A.callback;if(typeof ye=="function"){A.callback=null,q=A.priorityLevel;var _e=ye(A.expirationTime<=D);if(D=i.unstable_now(),typeof _e=="function"){A.callback=_e,F(D),L=!0;break t}A===o(S)&&f(S),F(D)}else f(S);A=o(S)}if(A!==null)L=!0;else{var g=o(y);g!==null&&Ce(le,g.startTime-D),L=!1}}break e}finally{A=null,q=I,H=!1}L=void 0}}finally{L?Je():be=!1}}}var Je;if(typeof $=="function")Je=function(){$(vt)};else if(typeof MessageChannel<"u"){var Ut=new MessageChannel,yt=Ut.port2;Ut.port1.onmessage=vt,Je=function(){yt.postMessage(null)}}else Je=function(){Q(vt,0)};function Ce(D,L){X=Q(function(){D(i.unstable_now())},L)}i.unstable_IdlePriority=5,i.unstable_ImmediatePriority=1,i.unstable_LowPriority=4,i.unstable_NormalPriority=3,i.unstable_Profiling=null,i.unstable_UserBlockingPriority=2,i.unstable_cancelCallback=function(D){D.callback=null},i.unstable_forceFrameRate=function(D){0>D||125ye?(D.sortIndex=I,s(y,D),o(S)===null&&D===o(y)&&(G?(V(X),X=-1):G=!0,Ce(le,I-ye))):(D.sortIndex=_e,s(S,D),Z||H||(Z=!0,be||(be=!0,Je()))),D},i.unstable_shouldYield=Ct,i.unstable_wrapCallback=function(D){var L=q;return function(){var I=q;q=L;try{return D.apply(this,arguments)}finally{q=I}}}})(qf)),qf}var om;function by(){return om||(om=1,Bf.exports=Sy()),Bf.exports}var Lf={exports:{}},$e={};var dm;function _y(){if(dm)return $e;dm=1;var i=$f();function s(S){var y="https://react.dev/errors/"+S;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(s){console.error(s)}}return i(),Lf.exports=_y(),Lf.exports}var hm;function Ty(){if(hm)return Cn;hm=1;var i=by(),s=$f(),o=Ey();function f(e){var t="https://react.dev/errors/"+e;if(1_e||(e.current=ye[_e],ye[_e]=null,_e--)}function Y(e,t){_e++,ye[_e]=e.current,e.current=t}var K=g(null),ee=g(null),ne=g(null),me=g(null);function We(e,t){switch(Y(ne,t),Y(ee,e),Y(K,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Od(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Od(t),e=jd(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}U(K),Y(K,e)}function je(){U(K),U(ee),U(ne)}function La(e){e.memoizedState!==null&&Y(me,e);var t=K.current,l=jd(t,e.type);t!==l&&(Y(ee,e),Y(K,l))}function Yn(e){ee.current===e&&(U(K),U(ee)),me.current===e&&(U(me),Rn._currentValue=I)}var hi,ns;function jl(e){if(hi===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);hi=t&&t[1]||"",ns=-1)":-1n||v[a]!==x[n]){var O=` +`+v[a].replace(" at new "," at ");return e.displayName&&O.includes("")&&(O=O.replace("",e.displayName)),O}while(1<=a&&0<=n);break}}}finally{vi=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?jl(l):""}function Jm(e,t){switch(e.tag){case 26:case 27:case 5:return jl(e.type);case 16:return jl("Lazy");case 13:return e.child!==t&&t!==null?jl("Suspense Fallback"):jl("Suspense");case 19:return jl("SuspenseList");case 0:case 15:return yi(e.type,!1);case 11:return yi(e.type.render,!1);case 1:return yi(e.type,!0);case 31:return jl("Activity");default:return""}}function us(e){try{var t="",l=null;do t+=Jm(e,l),l=e,e=e.return;while(e);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var pi=Object.prototype.hasOwnProperty,gi=i.unstable_scheduleCallback,Si=i.unstable_cancelCallback,$m=i.unstable_shouldYield,Wm=i.unstable_requestPaint,nt=i.unstable_now,km=i.unstable_getCurrentPriorityLevel,is=i.unstable_ImmediatePriority,cs=i.unstable_UserBlockingPriority,Gn=i.unstable_NormalPriority,Fm=i.unstable_LowPriority,fs=i.unstable_IdlePriority,Im=i.log,Pm=i.unstable_setDisableYieldValue,Ya=null,ut=null;function ul(e){if(typeof Im=="function"&&Pm(e),ut&&typeof ut.setStrictMode=="function")try{ut.setStrictMode(Ya,e)}catch{}}var it=Math.clz32?Math.clz32:lh,eh=Math.log,th=Math.LN2;function lh(e){return e>>>=0,e===0?32:31-(eh(e)/th|0)|0}var Xn=256,Qn=262144,Zn=4194304;function Dl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Vn(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var n=0,u=e.suspendedLanes,c=e.pingedLanes;e=e.warmLanes;var r=a&134217727;return r!==0?(a=r&~u,a!==0?n=Dl(a):(c&=r,c!==0?n=Dl(c):l||(l=r&~e,l!==0&&(n=Dl(l))))):(r=a&~u,r!==0?n=Dl(r):c!==0?n=Dl(c):l||(l=a&~e,l!==0&&(n=Dl(l)))),n===0?0:t!==0&&t!==n&&(t&u)===0&&(u=n&-n,l=t&-t,u>=l||u===32&&(l&4194048)!==0)?t:n}function Ga(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function ah(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ss(){var e=Zn;return Zn<<=1,(Zn&62914560)===0&&(Zn=4194304),e}function bi(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function Xa(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function nh(e,t,l,a,n,u){var c=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var r=e.entanglements,v=e.expirationTimes,x=e.hiddenUpdates;for(l=c&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var rh=/[\n"\\]/g;function gt(e){return e.replace(rh,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function zi(e,t,l,a,n,u,c,r){e.name="",c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?e.type=c:e.removeAttribute("type"),t!=null?c==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+pt(t)):e.value!==""+pt(t)&&(e.value=""+pt(t)):c!=="submit"&&c!=="reset"||e.removeAttribute("value"),t!=null?Ni(e,c,pt(t)):l!=null?Ni(e,c,pt(l)):a!=null&&e.removeAttribute("value"),n==null&&u!=null&&(e.defaultChecked=!!u),n!=null&&(e.checked=n&&typeof n!="function"&&typeof n!="symbol"),r!=null&&typeof r!="function"&&typeof r!="symbol"&&typeof r!="boolean"?e.name=""+pt(r):e.removeAttribute("name")}function Es(e,t,l,a,n,u,c,r){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.type=u),t!=null||l!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){Ai(e);return}l=l!=null?""+pt(l):"",t=t!=null?""+pt(t):l,r||t===e.value||(e.value=t),e.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=r?e.checked:!!a,e.defaultChecked=!!a,c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"&&(e.name=c),Ai(e)}function Ni(e,t,l){t==="number"&&Jn(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function la(e,t,l,a){if(e=e.options,t){t={};for(var n=0;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Mi=!1;if(Qt)try{var wa={};Object.defineProperty(wa,"passive",{get:function(){Mi=!0}}),window.addEventListener("test",wa,wa),window.removeEventListener("test",wa,wa)}catch{Mi=!1}var cl=null,Ci=null,Wn=null;function Os(){if(Wn)return Wn;var e,t=Ci,l=t.length,a,n="value"in cl?cl.value:cl.textContent,u=n.length;for(e=0;e=$a),Hs=" ",Bs=!1;function qs(e,t){switch(e){case"keyup":return Lh.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Ls(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var ia=!1;function Gh(e,t){switch(e){case"compositionend":return Ls(t);case"keypress":return t.which!==32?null:(Bs=!0,Hs);case"textInput":return e=t.data,e===Hs&&Bs?null:e;default:return null}}function Xh(e,t){if(ia)return e==="compositionend"||!Li&&qs(e,t)?(e=Os(),Wn=Ci=cl=null,ia=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Ks(l)}}function $s(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?$s(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ws(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Jn(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=Jn(e.document)}return t}function Xi(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var Wh=Qt&&"documentMode"in document&&11>=document.documentMode,ca=null,Qi=null,Ia=null,Zi=!1;function ks(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Zi||ca==null||ca!==Jn(a)||(a=ca,"selectionStart"in a&&Xi(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Ia&&Fa(Ia,a)||(Ia=a,a=Qu(Qi,"onSelect"),0>=c,n-=c,Ht=1<<32-it(t)+n|l<ae?(fe=J,J=null):fe=J.sibling;var oe=z(_,J,T[ae],M);if(oe===null){J===null&&(J=fe);break}e&&J&&oe.alternate===null&&t(_,J),p=u(oe,p,ae),re===null?W=oe:re.sibling=oe,re=oe,J=fe}if(ae===T.length)return l(_,J),se&&Vt(_,ae),W;if(J===null){for(;aeae?(fe=J,J=null):fe=J.sibling;var Ol=z(_,J,oe.value,M);if(Ol===null){J===null&&(J=fe);break}e&&J&&Ol.alternate===null&&t(_,J),p=u(Ol,p,ae),re===null?W=Ol:re.sibling=Ol,re=Ol,J=fe}if(oe.done)return l(_,J),se&&Vt(_,ae),W;if(J===null){for(;!oe.done;ae++,oe=T.next())oe=C(_,oe.value,M),oe!==null&&(p=u(oe,p,ae),re===null?W=oe:re.sibling=oe,re=oe);return se&&Vt(_,ae),W}for(J=a(J);!oe.done;ae++,oe=T.next())oe=R(J,_,ae,oe.value,M),oe!==null&&(e&&oe.alternate!==null&&J.delete(oe.key===null?ae:oe.key),p=u(oe,p,ae),re===null?W=oe:re.sibling=oe,re=oe);return e&&J.forEach(function(vy){return t(_,vy)}),se&&Vt(_,ae),W}function Se(_,p,T,M){if(typeof T=="object"&&T!==null&&T.type===G&&T.key===null&&(T=T.props.children),typeof T=="object"&&T!==null){switch(T.$$typeof){case H:e:{for(var W=T.key;p!==null;){if(p.key===W){if(W=T.type,W===G){if(p.tag===7){l(_,p.sibling),M=n(p,T.props.children),M.return=_,_=M;break e}}else if(p.elementType===W||typeof W=="object"&&W!==null&&W.$$typeof===Ne&&Ql(W)===p.type){l(_,p.sibling),M=n(p,T.props),nn(M,T),M.return=_,_=M;break e}l(_,p);break}else t(_,p);p=p.sibling}T.type===G?(M=ql(T.props.children,_.mode,M,T.key),M.return=_,_=M):(M=uu(T.type,T.key,T.props,null,_.mode,M),nn(M,T),M.return=_,_=M)}return c(_);case Z:e:{for(W=T.key;p!==null;){if(p.key===W)if(p.tag===4&&p.stateNode.containerInfo===T.containerInfo&&p.stateNode.implementation===T.implementation){l(_,p.sibling),M=n(p,T.children||[]),M.return=_,_=M;break e}else{l(_,p);break}else t(_,p);p=p.sibling}M=ki(T,_.mode,M),M.return=_,_=M}return c(_);case Ne:return T=Ql(T),Se(_,p,T,M)}if(Ce(T))return w(_,p,T,M);if(Je(T)){if(W=Je(T),typeof W!="function")throw Error(f(150));return T=W.call(T),k(_,p,T,M)}if(typeof T.then=="function")return Se(_,p,du(T),M);if(T.$$typeof===$)return Se(_,p,fu(_,T),M);mu(_,T)}return typeof T=="string"&&T!==""||typeof T=="number"||typeof T=="bigint"?(T=""+T,p!==null&&p.tag===6?(l(_,p.sibling),M=n(p,T),M.return=_,_=M):(l(_,p),M=Wi(T,_.mode,M),M.return=_,_=M),c(_)):l(_,p)}return function(_,p,T,M){try{an=0;var W=Se(_,p,T,M);return ga=null,W}catch(J){if(J===pa||J===ru)throw J;var re=ft(29,J,null,_.mode);return re.lanes=M,re.return=_,re}}}var Vl=Sr(!0),br=Sr(!1),dl=!1;function fc(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function sc(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function ml(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function hl(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(de&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=nu(e),ar(e,null,l),t}return au(e,a,t,l),nu(e)}function un(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,os(e,l)}}function rc(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var c={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=c:u=u.next=c,l=l.next}while(l!==null);u===null?n=u=t:u=u.next=t}else n=u=t;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var oc=!1;function cn(){if(oc){var e=ya;if(e!==null)throw e}}function fn(e,t,l,a){oc=!1;var n=e.updateQueue;dl=!1;var u=n.firstBaseUpdate,c=n.lastBaseUpdate,r=n.shared.pending;if(r!==null){n.shared.pending=null;var v=r,x=v.next;v.next=null,c===null?u=x:c.next=x,c=v;var O=e.alternate;O!==null&&(O=O.updateQueue,r=O.lastBaseUpdate,r!==c&&(r===null?O.firstBaseUpdate=x:r.next=x,O.lastBaseUpdate=v))}if(u!==null){var C=n.baseState;c=0,O=x=v=null,r=u;do{var z=r.lane&-536870913,R=z!==r.lane;if(R?(ce&z)===z:(a&z)===z){z!==0&&z===va&&(oc=!0),O!==null&&(O=O.next={lane:0,tag:r.tag,payload:r.payload,callback:null,next:null});e:{var w=e,k=r;z=t;var Se=l;switch(k.tag){case 1:if(w=k.payload,typeof w=="function"){C=w.call(Se,C,z);break e}C=w;break e;case 3:w.flags=w.flags&-65537|128;case 0:if(w=k.payload,z=typeof w=="function"?w.call(Se,C,z):w,z==null)break e;C=A({},C,z);break e;case 2:dl=!0}}z=r.callback,z!==null&&(e.flags|=64,R&&(e.flags|=8192),R=n.callbacks,R===null?n.callbacks=[z]:R.push(z))}else R={lane:z,tag:r.tag,payload:r.payload,callback:r.callback,next:null},O===null?(x=O=R,v=C):O=O.next=R,c|=z;if(r=r.next,r===null){if(r=n.shared.pending,r===null)break;R=r,r=R.next,R.next=null,n.lastBaseUpdate=R,n.shared.pending=null}}while(!0);O===null&&(v=C),n.baseState=v,n.firstBaseUpdate=x,n.lastBaseUpdate=O,u===null&&(n.shared.lanes=0),Sl|=c,e.lanes=c,e.memoizedState=C}}function _r(e,t){if(typeof e!="function")throw Error(f(191,e));e.call(t)}function Er(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;eu?u:8;var c=D.T,r={};D.T=r,jc(e,!1,t,l);try{var v=n(),x=D.S;if(x!==null&&x(r,v),v!==null&&typeof v=="object"&&typeof v.then=="function"){var O=nv(v,a);on(e,t,O,mt(e))}else on(e,t,a,mt(e))}catch(C){on(e,t,{then:function(){},status:"rejected",reason:C},mt())}finally{L.p=u,c!==null&&r.types!==null&&(c.types=r.types),D.T=c}}function rv(){}function Rc(e,t,l,a){if(e.tag!==5)throw Error(f(476));var n=eo(e).queue;Pr(e,n,t,I,l===null?rv:function(){return to(e),l(a)})}function eo(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:I,baseState:I,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:$t,lastRenderedState:I},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:$t,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function to(e){var t=eo(e);t.next===null&&(t=e.alternate.memoizedState),on(e,t.next.queue,{},mt())}function Oc(){return Ze(Rn)}function lo(){return Me().memoizedState}function ao(){return Me().memoizedState}function ov(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=mt();e=ml(l);var a=hl(t,e,l);a!==null&&(at(a,t,l),un(a,t,l)),t={cache:nc()},e.payload=t;return}t=t.return}}function dv(e,t,l){var a=mt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Tu(e)?uo(t,l):(l=Ji(e,t,l,a),l!==null&&(at(l,e,a),io(l,t,a)))}function no(e,t,l){var a=mt();on(e,t,l,a)}function on(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Tu(e))uo(t,n);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var c=t.lastRenderedState,r=u(c,l);if(n.hasEagerState=!0,n.eagerState=r,ct(r,c))return au(e,t,n,0),Ee===null&&lu(),!1}catch{}if(l=Ji(e,t,n,a),l!==null)return at(l,e,a),io(l,t,a),!0}return!1}function jc(e,t,l,a){if(a={lane:2,revertLane:sf(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Tu(e)){if(t)throw Error(f(479))}else t=Ji(e,l,a,2),t!==null&&at(t,e,2)}function Tu(e){var t=e.alternate;return e===te||t!==null&&t===te}function uo(e,t){ba=yu=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function io(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,os(e,l)}}var dn={readContext:Ze,use:Su,useCallback:Re,useContext:Re,useEffect:Re,useImperativeHandle:Re,useLayoutEffect:Re,useInsertionEffect:Re,useMemo:Re,useReducer:Re,useRef:Re,useState:Re,useDebugValue:Re,useDeferredValue:Re,useTransition:Re,useSyncExternalStore:Re,useId:Re,useHostTransitionStatus:Re,useFormState:Re,useActionState:Re,useOptimistic:Re,useMemoCache:Re,useCacheRefresh:Re};dn.useEffectEvent=Re;var co={readContext:Ze,use:Su,useCallback:function(e,t){return ke().memoizedState=[e,t===void 0?null:t],e},useContext:Ze,useEffect:Vr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,_u(4194308,4,$r.bind(null,t,e),l)},useLayoutEffect:function(e,t){return _u(4194308,4,e,t)},useInsertionEffect:function(e,t){_u(4,2,e,t)},useMemo:function(e,t){var l=ke();t=t===void 0?null:t;var a=e();if(wl){ul(!0);try{e()}finally{ul(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=ke();if(l!==void 0){var n=l(t);if(wl){ul(!0);try{l(t)}finally{ul(!1)}}}else n=t;return a.memoizedState=a.baseState=n,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},a.queue=e,e=e.dispatch=dv.bind(null,te,e),[a.memoizedState,e]},useRef:function(e){var t=ke();return e={current:e},t.memoizedState=e},useState:function(e){e=Tc(e);var t=e.queue,l=no.bind(null,te,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:zc,useDeferredValue:function(e,t){var l=ke();return Nc(l,e,t)},useTransition:function(){var e=Tc(!1);return e=Pr.bind(null,te,e.queue,!0,!1),ke().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=te,n=ke();if(se){if(l===void 0)throw Error(f(407));l=l()}else{if(l=t(),Ee===null)throw Error(f(349));(ce&127)!==0||Rr(a,t,l)}n.memoizedState=l;var u={value:l,getSnapshot:t};return n.queue=u,Vr(jr.bind(null,a,u,e),[e]),a.flags|=2048,Ea(9,{destroy:void 0},Or.bind(null,a,u,l,t),null),l},useId:function(){var e=ke(),t=Ee.identifierPrefix;if(se){var l=Bt,a=Ht;l=(a&~(1<<32-it(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=pu++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?c.createElement("select",{is:a.is}):c.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?c.createElement(n,{is:a.is}):c.createElement(n)}}u[Xe]=t,u[Fe]=a;e:for(c=t.child;c!==null;){if(c.tag===5||c.tag===6)u.appendChild(c.stateNode);else if(c.tag!==4&&c.tag!==27&&c.child!==null){c.child.return=c,c=c.child;continue}if(c===t)break e;for(;c.sibling===null;){if(c.return===null||c.return===t)break e;c=c.return}c.sibling.return=c.return,c=c.sibling}t.stateNode=u;e:switch(we(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&kt(t)}}return xe(t),Vc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&kt(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(f(166));if(e=ne.current,ma(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=Qe,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[Xe]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||Nd(e.nodeValue,l)),e||rl(t,!0)}else e=Zu(e).createTextNode(a),e[Xe]=t,t.stateNode=e}return xe(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=ma(t),l!==null){if(e===null){if(!a)throw Error(f(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(f(557));e[Xe]=t}else Ll(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;xe(t),e=!1}else l=ec(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(rt(t),t):(rt(t),null);if((t.flags&128)!==0)throw Error(f(558))}return xe(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(n=ma(t),a!==null&&a.dehydrated!==null){if(e===null){if(!n)throw Error(f(318));if(n=t.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(f(317));n[Xe]=t}else Ll(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;xe(t),n=!1}else n=ec(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(rt(t),t):(rt(t),null)}return rt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),Ru(t,t.updateQueue),xe(t),null);case 4:return je(),e===null&&mf(t.stateNode.containerInfo),xe(t),null;case 10:return Kt(t.type),xe(t),null;case 19:if(U(De),a=t.memoizedState,a===null)return xe(t),null;if(n=(t.flags&128)!==0,u=a.rendering,u===null)if(n)hn(a,!1);else{if(Oe!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=vu(e),u!==null){for(t.flags|=128,hn(a,!1),e=u.updateQueue,t.updateQueue=e,Ru(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)nr(l,e),l=l.sibling;return Y(De,De.current&1|2),se&&Vt(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&nt()>Cu&&(t.flags|=128,n=!0,hn(a,!1),t.lanes=4194304)}else{if(!n)if(e=vu(u),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,Ru(t,e),hn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!u.alternate&&!se)return xe(t),null}else 2*nt()-a.renderingStartTime>Cu&&l!==536870912&&(t.flags|=128,n=!0,hn(a,!1),t.lanes=4194304);a.isBackwards?(u.sibling=t.child,t.child=u):(e=a.last,e!==null?e.sibling=u:t.child=u,a.last=u)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=nt(),e.sibling=null,l=De.current,Y(De,n?l&1|2:l&1),se&&Vt(t,a.treeForkCount),e):(xe(t),null);case 22:case 23:return rt(t),mc(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(xe(t),t.subtreeFlags&6&&(t.flags|=8192)):xe(t),l=t.updateQueue,l!==null&&Ru(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&U(Xl),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),Kt(Ue),xe(t),null;case 25:return null;case 30:return null}throw Error(f(156,t.tag))}function pv(e,t){switch(Ii(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Kt(Ue),je(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Yn(t),null;case 31:if(t.memoizedState!==null){if(rt(t),t.alternate===null)throw Error(f(340));Ll()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(rt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(f(340));Ll()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return U(De),null;case 4:return je(),null;case 10:return Kt(t.type),null;case 22:case 23:return rt(t),mc(),e!==null&&U(Xl),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Kt(Ue),null;case 25:return null;default:return null}}function Mo(e,t){switch(Ii(t),t.tag){case 3:Kt(Ue),je();break;case 26:case 27:case 5:Yn(t);break;case 4:je();break;case 31:t.memoizedState!==null&&rt(t);break;case 13:rt(t);break;case 19:U(De);break;case 10:Kt(t.type);break;case 22:case 23:rt(t),mc(),e!==null&&U(Xl);break;case 24:Kt(Ue)}}function vn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&e)===e){a=void 0;var u=l.create,c=l.inst;a=u(),c.destroy=a}l=l.next}while(l!==n)}}catch(r){ve(t,t.return,r)}}function pl(e,t,l){try{var a=t.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&e)===e){var c=a.inst,r=c.destroy;if(r!==void 0){c.destroy=void 0,n=t;var v=l,x=r;try{x()}catch(O){ve(n,v,O)}}}a=a.next}while(a!==u)}}catch(O){ve(t,t.return,O)}}function Co(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{Er(t,l)}catch(a){ve(e,e.return,a)}}}function Uo(e,t,l){l.props=Kl(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){ve(e,t,a)}}function yn(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(n){ve(e,t,n)}}function qt(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){ve(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){ve(e,t,n)}else l.current=null}function Ho(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(n){ve(e,e.return,n)}}function wc(e,t,l){try{var a=e.stateNode;Yv(a,e.type,l,t),a[Fe]=t}catch(n){ve(e,e.return,n)}}function Bo(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&xl(e.type)||e.tag===4}function Kc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Bo(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&xl(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Jc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=Xt));else if(a!==4&&(a===27&&xl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(Jc(e,t,l),e=e.sibling;e!==null;)Jc(e,t,l),e=e.sibling}function Ou(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&xl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Ou(e,t,l),e=e.sibling;e!==null;)Ou(e,t,l),e=e.sibling}function qo(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);we(t,a,l),t[Xe]=e,t[Fe]=l}catch(u){ve(e,e.return,u)}}var Ft=!1,qe=!1,$c=!1,Lo=typeof WeakSet=="function"?WeakSet:Set,Ge=null;function gv(e,t){if(e=e.containerInfo,yf=ku,e=Ws(e),Xi(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var n=a.anchorOffset,u=a.focusNode;a=a.focusOffset;try{l.nodeType,u.nodeType}catch{l=null;break e}var c=0,r=-1,v=-1,x=0,O=0,C=e,z=null;t:for(;;){for(var R;C!==l||n!==0&&C.nodeType!==3||(r=c+n),C!==u||a!==0&&C.nodeType!==3||(v=c+a),C.nodeType===3&&(c+=C.nodeValue.length),(R=C.firstChild)!==null;)z=C,C=R;for(;;){if(C===e)break t;if(z===l&&++x===n&&(r=c),z===u&&++O===a&&(v=c),(R=C.nextSibling)!==null)break;C=z,z=C.parentNode}C=R}l=r===-1||v===-1?null:{start:r,end:v}}else l=null}l=l||{start:0,end:0}}else l=null;for(pf={focusedElem:e,selectionRange:l},ku=!1,Ge=t;Ge!==null;)if(t=Ge,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,Ge=e;else for(;Ge!==null;){switch(t=Ge,u=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),we(u,a,l),u[Xe]=e,Ye(u),a=u;break e;case"link":var c=Vd("link","href",n).get(a+(l.href||""));if(c){for(var r=0;rSe&&(c=Se,Se=k,k=c);var _=Js(r,k),p=Js(r,Se);if(_&&p&&(R.rangeCount!==1||R.anchorNode!==_.node||R.anchorOffset!==_.offset||R.focusNode!==p.node||R.focusOffset!==p.offset)){var T=C.createRange();T.setStart(_.node,_.offset),R.removeAllRanges(),k>Se?(R.addRange(T),R.extend(p.node,p.offset)):(T.setEnd(p.node,p.offset),R.addRange(T))}}}}for(C=[],R=r;R=R.parentNode;)R.nodeType===1&&C.push({element:R,left:R.scrollLeft,top:R.scrollTop});for(typeof r.focus=="function"&&r.focus(),r=0;rl?32:l,D.T=null,l=tf,tf=null;var u=_l,c=ll;if(Le=0,Na=_l=null,ll=0,(de&6)!==0)throw Error(f(331));var r=de;if(de|=4,Wo(u.current),Ko(u,u.current,c,l),de=r,En(0,!1),ut&&typeof ut.onPostCommitFiberRoot=="function")try{ut.onPostCommitFiberRoot(Ya,u)}catch{}return!0}finally{L.p=n,D.T=a,md(e,t)}}function vd(e,t,l){t=bt(l,t),t=Uc(e.stateNode,t,2),e=hl(e,t,2),e!==null&&(Xa(e,2),Lt(e))}function ve(e,t,l){if(e.tag===3)vd(e,e,l);else for(;t!==null;){if(t.tag===3){vd(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(bl===null||!bl.has(a))){e=bt(l,e),l=yo(2),a=hl(t,l,2),a!==null&&(po(l,a,t,e),Xa(a,2),Lt(a));break}}t=t.return}}function uf(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new _v;var n=new Set;a.set(t,n)}else n=a.get(t),n===void 0&&(n=new Set,a.set(t,n));n.has(l)||(Fc=!0,n.add(l),e=zv.bind(null,e,t,l),t.then(e,e))}function zv(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Ee===e&&(ce&l)===l&&(Oe===4||Oe===3&&(ce&62914560)===ce&&300>nt()-Mu?(de&2)===0&&Ra(e,0):Ic|=l,za===ce&&(za=0)),Lt(e)}function yd(e,t){t===0&&(t=ss()),e=Bl(e,t),e!==null&&(Xa(e,t),Lt(e))}function Nv(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),yd(e,l)}function Rv(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,n=e.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(f(314))}a!==null&&a.delete(t),yd(e,l)}function Ov(e,t){return gi(e,t)}var Yu=null,ja=null,cf=!1,Gu=!1,ff=!1,Tl=0;function Lt(e){e!==ja&&e.next===null&&(ja===null?Yu=ja=e:ja=ja.next=e),Gu=!0,cf||(cf=!0,Dv())}function En(e,t){if(!ff&&Gu){ff=!0;do for(var l=!1,a=Yu;a!==null;){if(e!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var c=a.suspendedLanes,r=a.pingedLanes;u=(1<<31-it(42|e)+1)-1,u&=n&~(c&~r),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,bd(a,u))}else u=ce,u=Vn(a,a===Ee?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||Ga(a,u)||(l=!0,bd(a,u));a=a.next}while(l);ff=!1}}function jv(){pd()}function pd(){Gu=cf=!1;var e=0;Tl!==0&&Xv()&&(e=Tl);for(var t=nt(),l=null,a=Yu;a!==null;){var n=a.next,u=gd(a,t);u===0?(a.next=null,l===null?Yu=n:l.next=n,n===null&&(ja=l)):(l=a,(e!==0||(u&3)!==0)&&(Gu=!0)),a=n}Le!==0&&Le!==5||En(e),Tl!==0&&(Tl=0)}function gd(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,n=e.expirationTimes,u=e.pendingLanes&-62914561;0r)break;var O=v.transferSize,C=v.initiatorType;O&&Rd(C)&&(v=v.responseEnd,c+=O*(v"u"?null:document;function Gd(e,t,l){var a=Da;if(a&&typeof t=="string"&&t){var n=gt(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),Yd.has(n)||(Yd.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),we(t,"link",e),Ye(t),a.head.appendChild(t)))}}function kv(e){al.D(e),Gd("dns-prefetch",e,null)}function Fv(e,t){al.C(e,t),Gd("preconnect",e,t)}function Iv(e,t,l){al.L(e,t,l);var a=Da;if(a&&e&&t){var n='link[rel="preload"][as="'+gt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+gt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+gt(l.imageSizes)+'"]')):n+='[href="'+gt(e)+'"]';var u=n;switch(t){case"style":u=Ma(e);break;case"script":u=Ca(e)}zt.has(u)||(e=A({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),zt.set(u,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(zn(u))||t==="script"&&a.querySelector(Nn(u))||(t=a.createElement("link"),we(t,"link",e),Ye(t),a.head.appendChild(t)))}}function Pv(e,t){al.m(e,t);var l=Da;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+gt(a)+'"][href="'+gt(e)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ca(e)}if(!zt.has(u)&&(e=A({rel:"modulepreload",href:e},t),zt.set(u,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(Nn(u)))return}a=l.createElement("link"),we(a,"link",e),Ye(a),l.head.appendChild(a)}}}function ey(e,t,l){al.S(e,t,l);var a=Da;if(a&&e){var n=ea(a).hoistableStyles,u=Ma(e);t=t||"default";var c=n.get(u);if(!c){var r={loading:0,preload:null};if(c=a.querySelector(zn(u)))r.loading=5;else{e=A({rel:"stylesheet",href:e,"data-precedence":t},l),(l=zt.get(u))&&xf(e,l);var v=c=a.createElement("link");Ye(v),we(v,"link",e),v._p=new Promise(function(x,O){v.onload=x,v.onerror=O}),v.addEventListener("load",function(){r.loading|=1}),v.addEventListener("error",function(){r.loading|=2}),r.loading|=4,wu(c,t,a)}c={type:"stylesheet",instance:c,count:1,state:r},n.set(u,c)}}}function ty(e,t){al.X(e,t);var l=Da;if(l&&e){var a=ea(l).hoistableScripts,n=Ca(e),u=a.get(n);u||(u=l.querySelector(Nn(n)),u||(e=A({src:e,async:!0},t),(t=zt.get(n))&&Af(e,t),u=l.createElement("script"),Ye(u),we(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function ly(e,t){al.M(e,t);var l=Da;if(l&&e){var a=ea(l).hoistableScripts,n=Ca(e),u=a.get(n);u||(u=l.querySelector(Nn(n)),u||(e=A({src:e,async:!0,type:"module"},t),(t=zt.get(n))&&Af(e,t),u=l.createElement("script"),Ye(u),we(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function Xd(e,t,l,a){var n=(n=ne.current)?Vu(n):null;if(!n)throw Error(f(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=Ma(l.href),l=ea(n).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=Ma(l.href);var u=ea(n).hoistableStyles,c=u.get(e);if(c||(n=n.ownerDocument||n,c={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(e,c),(u=n.querySelector(zn(e)))&&!u._p&&(c.instance=u,c.state.loading=5),zt.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},zt.set(e,l),u||ay(n,e,l,c.state))),t&&a===null)throw Error(f(528,""));return c}if(t&&a!==null)throw Error(f(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Ca(l),l=ea(n).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(f(444,e))}}function Ma(e){return'href="'+gt(e)+'"'}function zn(e){return'link[rel="stylesheet"]['+e+"]"}function Qd(e){return A({},e,{"data-precedence":e.precedence,precedence:null})}function ay(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),we(t,"link",l),Ye(t),e.head.appendChild(t))}function Ca(e){return'[src="'+gt(e)+'"]'}function Nn(e){return"script[async]"+e}function Zd(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+gt(l.href)+'"]');if(a)return t.instance=a,Ye(a),a;var n=A({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),Ye(a),we(a,"style",n),wu(a,l.precedence,e),t.instance=a;case"stylesheet":n=Ma(l.href);var u=e.querySelector(zn(n));if(u)return t.state.loading|=4,t.instance=u,Ye(u),u;a=Qd(l),(n=zt.get(n))&&xf(a,n),u=(e.ownerDocument||e).createElement("link"),Ye(u);var c=u;return c._p=new Promise(function(r,v){c.onload=r,c.onerror=v}),we(u,"link",a),t.state.loading|=4,wu(u,l.precedence,e),t.instance=u;case"script":return u=Ca(l.src),(n=e.querySelector(Nn(u)))?(t.instance=n,Ye(n),n):(a=l,(n=zt.get(u))&&(a=A({},l),Af(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),Ye(n),we(n,"link",a),e.head.appendChild(n),t.instance=n);case"void":return null;default:throw Error(f(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,wu(a,l.precedence,e));return t.instance}function wu(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,c=0;c title"):null)}function ny(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;return t.rel==="stylesheet"?(e=t.disabled,typeof t.precedence=="string"&&e==null):!0;case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Kd(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function uy(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=Ma(a.href),u=t.querySelector(zn(n));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=Ju.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=u,Ye(u);return}u=t.ownerDocument||t,a=Qd(a),(n=zt.get(n))&&xf(a,n),u=u.createElement("link"),Ye(u);var c=u;c._p=new Promise(function(r,v){c.onload=r,c.onerror=v}),we(u,"link",a),l.instance=u}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=Ju.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var zf=0;function iy(e,t){return e.stylesheets&&e.count===0&&Wu(e,e.stylesheets),0zf?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function Ju(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Wu(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var $u=null;function Wu(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,$u=new Map,t.forEach(cy,e),$u=null,Ju.call(e))}function cy(e,t){if(!(t.state.loading&4)){var l=$u.get(e);if(l)var a=l.get(null);else{l=new Map,$u.set(e,l);for(var n=e.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(s){console.error(s)}}return i(),Hf.exports=Ty(),Hf.exports}var Ay=xy();var ym="popstate";function pm(i){return typeof i=="object"&&i!=null&&"pathname"in i&&"search"in i&&"hash"in i&&"state"in i&&"key"in i}function zy(i={}){function s(d,h){let{pathname:b="/",search:N="",hash:S=""}=kl(d.location.hash.substring(1));return!b.startsWith("/")&&!b.startsWith(".")&&(b="/"+b),Kf("",{pathname:b,search:N,hash:S},h.state&&h.state.usr||null,h.state&&h.state.key||"default")}function o(d,h){let b=d.document.querySelector("base"),N="";if(b&&b.getAttribute("href")){let S=d.location.href,y=S.indexOf("#");N=y===-1?S:S.slice(0,y)}return N+"#"+(typeof h=="string"?h:Hn(h))}function f(d,h){Nt(d.pathname.charAt(0)==="/",`relative pathnames are not supported in hash history.push(${JSON.stringify(h)})`)}return Ry(s,o,f,i)}function ze(i,s){if(i===!1||i===null||typeof i>"u")throw new Error(s)}function Nt(i,s){if(!i){typeof console<"u"&&console.warn(s);try{throw new Error(s)}catch{}}}function Ny(){return Math.random().toString(36).substring(2,10)}function gm(i,s){return{usr:i.state,key:i.key,idx:s,masked:i.unstable_mask?{pathname:i.pathname,search:i.search,hash:i.hash}:void 0}}function Kf(i,s,o=null,f,d){return{pathname:typeof i=="string"?i:i.pathname,search:"",hash:"",...typeof s=="string"?kl(s):s,state:o,key:s&&s.key||f||Ny(),unstable_mask:d}}function Hn({pathname:i="/",search:s="",hash:o=""}){return s&&s!=="?"&&(i+=s.charAt(0)==="?"?s:"?"+s),o&&o!=="#"&&(i+=o.charAt(0)==="#"?o:"#"+o),i}function kl(i){let s={};if(i){let o=i.indexOf("#");o>=0&&(s.hash=i.substring(o),i=i.substring(0,o));let f=i.indexOf("?");f>=0&&(s.search=i.substring(f),i=i.substring(0,f)),i&&(s.pathname=i)}return s}function Ry(i,s,o,f={}){let{window:d=document.defaultView,v5Compat:h=!1}=f,b=d.history,N="POP",S=null,y=j();y==null&&(y=0,b.replaceState({...b.state,idx:y},""));function j(){return(b.state||{idx:null}).idx}function A(){N="POP";let B=j(),Q=B==null?null:B-y;y=B,S&&S({action:N,location:G.location,delta:Q})}function q(B,Q){N="PUSH";let V=pm(B)?B:Kf(G.location,B,Q);o&&o(V,B),y=j()+1;let $=gm(V,y),F=G.createHref(V.unstable_mask||V);try{b.pushState($,"",F)}catch(le){if(le instanceof DOMException&&le.name==="DataCloneError")throw le;d.location.assign(F)}h&&S&&S({action:N,location:G.location,delta:1})}function H(B,Q){N="REPLACE";let V=pm(B)?B:Kf(G.location,B,Q);o&&o(V,B),y=j();let $=gm(V,y),F=G.createHref(V.unstable_mask||V);b.replaceState($,"",F),h&&S&&S({action:N,location:G.location,delta:0})}function Z(B){return Oy(B)}let G={get action(){return N},get location(){return i(d,b)},listen(B){if(S)throw new Error("A history only accepts one active listener");return d.addEventListener(ym,A),S=B,()=>{d.removeEventListener(ym,A),S=null}},createHref(B){return s(d,B)},createURL:Z,encodeLocation(B){let Q=Z(B);return{pathname:Q.pathname,search:Q.search,hash:Q.hash}},push:q,replace:H,go(B){return b.go(B)}};return G}function Oy(i,s=!1){let o="http://localhost";typeof window<"u"&&(o=window.location.origin!=="null"?window.location.origin:window.location.href),ze(o,"No window.location.(origin|href) available to create URL");let f=typeof i=="string"?i:Hn(i);return f=f.replace(/ $/,"%20"),!s&&f.startsWith("//")&&(f=o+f),new URL(f,o)}function xm(i,s,o="/"){return jy(i,s,o,!1)}function jy(i,s,o,f){let d=typeof s=="string"?kl(s):s,h=nl(d.pathname||"/",o);if(h==null)return null;let b=Am(i);Dy(b);let N=null;for(let S=0;N==null&&S{let j={relativePath:y===void 0?b.path||"":y,caseSensitive:b.caseSensitive===!0,childrenIndex:N,route:b};if(j.relativePath.startsWith("/")){if(!j.relativePath.startsWith(f)&&S)return;ze(j.relativePath.startsWith(f),`Absolute route path "${j.relativePath}" nested under path "${f}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),j.relativePath=j.relativePath.slice(f.length)}let A=Dt([f,j.relativePath]),q=o.concat(j);b.children&&b.children.length>0&&(ze(b.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${A}".`),Am(b.children,s,q,A,S)),!(b.path==null&&!b.index)&&s.push({path:A,score:Ly(A,b.index),routesMeta:q})};return i.forEach((b,N)=>{if(b.path===""||!b.path?.includes("?"))h(b,N);else for(let S of zm(b.path))h(b,N,!0,S)}),s}function zm(i){let s=i.split("/");if(s.length===0)return[];let[o,...f]=s,d=o.endsWith("?"),h=o.replace(/\?$/,"");if(f.length===0)return d?[h,""]:[h];let b=zm(f.join("/")),N=[];return N.push(...b.map(S=>S===""?h:[h,S].join("/"))),d&&N.push(...b),N.map(S=>i.startsWith("/")&&S===""?"/":S)}function Dy(i){i.sort((s,o)=>s.score!==o.score?o.score-s.score:Yy(s.routesMeta.map(f=>f.childrenIndex),o.routesMeta.map(f=>f.childrenIndex)))}var My=/^:[\w-]+$/,Cy=3,Uy=2,Hy=1,By=10,qy=-2,Sm=i=>i==="*";function Ly(i,s){let o=i.split("/"),f=o.length;return o.some(Sm)&&(f+=qy),s&&(f+=Uy),o.filter(d=>!Sm(d)).reduce((d,h)=>d+(My.test(h)?Cy:h===""?Hy:By),f)}function Yy(i,s){return i.length===s.length&&i.slice(0,-1).every((f,d)=>f===s[d])?i[i.length-1]-s[s.length-1]:0}function Gy(i,s,o=!1){let{routesMeta:f}=i,d={},h="/",b=[];for(let N=0;N{if(j==="*"){let Z=N[q]||"";b=h.slice(0,h.length-Z.length).replace(/(.)\/+$/,"$1")}const H=N[q];return A&&!H?y[j]=void 0:y[j]=(H||"").replace(/%2F/g,"/"),y},{}),pathname:h,pathnameBase:b,pattern:i}}function Xy(i,s=!1,o=!0){Nt(i==="*"||!i.endsWith("*")||i.endsWith("/*"),`Route path "${i}" will be treated as if it were "${i.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${i.replace(/\*$/,"/*")}".`);let f=[],d="^"+i.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(b,N,S,y,j)=>{if(f.push({paramName:N,isOptional:S!=null}),S){let A=j.charAt(y+b.length);return A&&A!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return i.endsWith("*")?(f.push({paramName:"*"}),d+=i==="*"||i==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):o?d+="\\/*$":i!==""&&i!=="/"&&(d+="(?:(?=\\/|$))"),[new RegExp(d,s?void 0:"i"),f]}function Qy(i){try{return i.split("/").map(s=>decodeURIComponent(s).replace(/\//g,"%2F")).join("/")}catch(s){return Nt(!1,`The URL path "${i}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${s}).`),i}}function nl(i,s){if(s==="/")return i;if(!i.toLowerCase().startsWith(s.toLowerCase()))return null;let o=s.endsWith("/")?s.length-1:s.length,f=i.charAt(o);return f&&f!=="/"?null:i.slice(o)||"/"}var Zy=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function Vy(i,s="/"){let{pathname:o,search:f="",hash:d=""}=typeof i=="string"?kl(i):i,h;return o?(o=Nm(o),o.startsWith("/")?h=bm(o.substring(1),"/"):h=bm(o,s)):h=s,{pathname:h,search:Jy(f),hash:$y(d)}}function bm(i,s){let o=si(s).split("/");return i.split("/").forEach(d=>{d===".."?o.length>1&&o.pop():d!=="."&&o.push(d)}),o.length>1?o.join("/"):"/"}function Yf(i,s,o,f){return`Cannot include a '${i}' character in a manually specified \`to.${s}\` field [${JSON.stringify(f)}]. Please separate it out to the \`to.${o}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function wy(i){return i.filter((s,o)=>o===0||s.route.path&&s.route.path.length>0)}function Wf(i){let s=wy(i);return s.map((o,f)=>f===s.length-1?o.pathname:o.pathnameBase)}function oi(i,s,o,f=!1){let d;typeof i=="string"?d=kl(i):(d={...i},ze(!d.pathname||!d.pathname.includes("?"),Yf("?","pathname","search",d)),ze(!d.pathname||!d.pathname.includes("#"),Yf("#","pathname","hash",d)),ze(!d.search||!d.search.includes("#"),Yf("#","search","hash",d)));let h=i===""||d.pathname==="",b=h?"/":d.pathname,N;if(b==null)N=o;else{let A=s.length-1;if(!f&&b.startsWith("..")){let q=b.split("/");for(;q[0]==="..";)q.shift(),A-=1;d.pathname=q.join("/")}N=A>=0?s[A]:"/"}let S=Vy(d,N),y=b&&b!=="/"&&b.endsWith("/"),j=(h||b===".")&&o.endsWith("/");return!S.pathname.endsWith("/")&&(y||j)&&(S.pathname+="/"),S}var Nm=i=>i.replace(/\/\/+/g,"/"),Dt=i=>Nm(i.join("/")),si=i=>i.replace(/\/+$/,""),Ky=i=>si(i).replace(/^\/*/,"/"),Jy=i=>!i||i==="?"?"":i.startsWith("?")?i:"?"+i,$y=i=>!i||i==="#"?"":i.startsWith("#")?i:"#"+i,Wy=class{constructor(i,s,o,f=!1){this.status=i,this.statusText=s||"",this.internal=f,o instanceof Error?(this.data=o.toString(),this.error=o):this.data=o}};function ky(i){return i!=null&&typeof i.status=="number"&&typeof i.statusText=="string"&&typeof i.internal=="boolean"&&"data"in i}function Fy(i){let s=i.map(o=>o.route.path).filter(Boolean);return Dt(s)||"/"}var Rm=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function Om(i,s){let o=i;if(typeof o!="string"||!Zy.test(o))return{absoluteURL:void 0,isExternal:!1,to:o};let f=o,d=!1;if(Rm)try{let h=new URL(window.location.href),b=o.startsWith("//")?new URL(h.protocol+o):new URL(o),N=nl(b.pathname,s);b.origin===h.origin&&N!=null?o=N+b.search+b.hash:d=!0}catch{Nt(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:f,isExternal:d,to:o}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var jm=["POST","PUT","PATCH","DELETE"];new Set(jm);var Iy=["GET",...jm];new Set(Iy);var Ba=E.createContext(null);Ba.displayName="DataRouter";var di=E.createContext(null);di.displayName="DataRouterState";var Dm=E.createContext(!1);function Py(){return E.useContext(Dm)}var Mm=E.createContext({isTransitioning:!1});Mm.displayName="ViewTransition";var e0=E.createContext(new Map);e0.displayName="Fetchers";var t0=E.createContext(null);t0.displayName="Await";var ht=E.createContext(null);ht.displayName="Navigation";var qn=E.createContext(null);qn.displayName="Location";var Mt=E.createContext({outlet:null,matches:[],isDataRoute:!1});Mt.displayName="Route";var kf=E.createContext(null);kf.displayName="RouteError";var Cm="REACT_ROUTER_ERROR",l0="REDIRECT",a0="ROUTE_ERROR_RESPONSE";function n0(i){if(i.startsWith(`${Cm}:${l0}:{`))try{let s=JSON.parse(i.slice(28));if(typeof s=="object"&&s&&typeof s.status=="number"&&typeof s.statusText=="string"&&typeof s.location=="string"&&typeof s.reloadDocument=="boolean"&&typeof s.replace=="boolean")return s}catch{}}function u0(i){if(i.startsWith(`${Cm}:${a0}:{`))try{let s=JSON.parse(i.slice(40));if(typeof s=="object"&&s&&typeof s.status=="number"&&typeof s.statusText=="string")return new Wy(s.status,s.statusText,s.data)}catch{}}function i0(i,{relative:s}={}){ze(qa(),"useHref() may be used only in the context of a component.");let{basename:o,navigator:f}=E.useContext(ht),{hash:d,pathname:h,search:b}=Ln(i,{relative:s}),N=h;return o!=="/"&&(N=h==="/"?o:Dt([o,h])),f.createHref({pathname:N,search:b,hash:d})}function qa(){return E.useContext(qn)!=null}function Yt(){return ze(qa(),"useLocation() may be used only in the context of a component."),E.useContext(qn).location}var Um="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Hm(i){E.useContext(ht).static||E.useLayoutEffect(i)}function Bm(){let{isDataRoute:i}=E.useContext(Mt);return i?_0():c0()}function c0(){ze(qa(),"useNavigate() may be used only in the context of a component.");let i=E.useContext(Ba),{basename:s,navigator:o}=E.useContext(ht),{matches:f}=E.useContext(Mt),{pathname:d}=Yt(),h=JSON.stringify(Wf(f)),b=E.useRef(!1);return Hm(()=>{b.current=!0}),E.useCallback((S,y={})=>{if(Nt(b.current,Um),!b.current)return;if(typeof S=="number"){o.go(S);return}let j=oi(S,JSON.parse(h),d,y.relative==="path");i==null&&s!=="/"&&(j.pathname=j.pathname==="/"?s:Dt([s,j.pathname])),(y.replace?o.replace:o.push)(j,y.state,y)},[s,o,h,d,i])}var f0=E.createContext(null);function s0(i){let s=E.useContext(Mt).outlet;return E.useMemo(()=>s&&E.createElement(f0.Provider,{value:i},s),[s,i])}function Ln(i,{relative:s}={}){let{matches:o}=E.useContext(Mt),{pathname:f}=Yt(),d=JSON.stringify(Wf(o));return E.useMemo(()=>oi(i,JSON.parse(d),f,s==="path"),[i,d,f,s])}function r0(i,s){return qm(i,s)}function qm(i,s,o){ze(qa(),"useRoutes() may be used only in the context of a component.");let{navigator:f}=E.useContext(ht),{matches:d}=E.useContext(Mt),h=d[d.length-1],b=h?h.params:{},N=h?h.pathname:"/",S=h?h.pathnameBase:"/",y=h&&h.route;{let B=y&&y.path||"";Ym(N,!y||B.endsWith("*")||B.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${N}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .`)}let j=Yt(),A;if(s){let B=typeof s=="string"?kl(s):s;ze(S==="/"||B.pathname?.startsWith(S),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${S}" but pathname "${B.pathname}" was given in the \`location\` prop.`),A=B}else A=j;let q=A.pathname||"/",H=q;if(S!=="/"){let B=S.replace(/^\//,"").split("/");H="/"+q.replace(/^\//,"").split("/").slice(B.length).join("/")}let Z=xm(i,{pathname:H});Nt(y||Z!=null,`No routes matched location "${A.pathname}${A.search}${A.hash}" `),Nt(Z==null||Z[Z.length-1].route.element!==void 0||Z[Z.length-1].route.Component!==void 0||Z[Z.length-1].route.lazy!==void 0,`Matched leaf route at location "${A.pathname}${A.search}${A.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let G=v0(Z&&Z.map(B=>Object.assign({},B,{params:Object.assign({},b,B.params),pathname:Dt([S,f.encodeLocation?f.encodeLocation(B.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:B.pathname]),pathnameBase:B.pathnameBase==="/"?S:Dt([S,f.encodeLocation?f.encodeLocation(B.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:B.pathnameBase])})),d,o);return s&&G?E.createElement(qn.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",unstable_mask:void 0,...A},navigationType:"POP"}},G):G}function o0(){let i=b0(),s=ky(i)?`${i.status} ${i.statusText}`:i instanceof Error?i.message:JSON.stringify(i),o=i instanceof Error?i.stack:null,f="rgba(200,200,200, 0.5)",d={padding:"0.5rem",backgroundColor:f},h={padding:"2px 4px",backgroundColor:f},b=null;return console.error("Error handled by React Router default ErrorBoundary:",i),b=E.createElement(E.Fragment,null,E.createElement("p",null,"💿 Hey developer 👋"),E.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",E.createElement("code",{style:h},"ErrorBoundary")," or"," ",E.createElement("code",{style:h},"errorElement")," prop on your route.")),E.createElement(E.Fragment,null,E.createElement("h2",null,"Unexpected Application Error!"),E.createElement("h3",{style:{fontStyle:"italic"}},s),o?E.createElement("pre",{style:d},o):null,b)}var d0=E.createElement(o0,null),Lm=class extends E.Component{constructor(i){super(i),this.state={location:i.location,revalidation:i.revalidation,error:i.error}}static getDerivedStateFromError(i){return{error:i}}static getDerivedStateFromProps(i,s){return s.location!==i.location||s.revalidation!=="idle"&&i.revalidation==="idle"?{error:i.error,location:i.location,revalidation:i.revalidation}:{error:i.error!==void 0?i.error:s.error,location:s.location,revalidation:i.revalidation||s.revalidation}}componentDidCatch(i,s){this.props.onError?this.props.onError(i,s):console.error("React Router caught the following error during render",i)}render(){let i=this.state.error;if(this.context&&typeof i=="object"&&i&&"digest"in i&&typeof i.digest=="string"){const o=u0(i.digest);o&&(i=o)}let s=i!==void 0?E.createElement(Mt.Provider,{value:this.props.routeContext},E.createElement(kf.Provider,{value:i,children:this.props.component})):this.props.children;return this.context?E.createElement(m0,{error:i},s):s}};Lm.contextType=Dm;var Gf=new WeakMap;function m0({children:i,error:s}){let{basename:o}=E.useContext(ht);if(typeof s=="object"&&s&&"digest"in s&&typeof s.digest=="string"){let f=n0(s.digest);if(f){let d=Gf.get(s);if(d)throw d;let h=Om(f.location,o);if(Rm&&!Gf.get(s))if(h.isExternal||f.reloadDocument)window.location.href=h.absoluteURL||h.to;else{const b=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(h.to,{replace:f.replace}));throw Gf.set(s,b),b}return E.createElement("meta",{httpEquiv:"refresh",content:`0;url=${h.absoluteURL||h.to}`})}}return i}function h0({routeContext:i,match:s,children:o}){let f=E.useContext(Ba);return f&&f.static&&f.staticContext&&(s.route.errorElement||s.route.ErrorBoundary)&&(f.staticContext._deepestRenderedBoundaryId=s.route.id),E.createElement(Mt.Provider,{value:i},o)}function v0(i,s=[],o){let f=o?.state;if(i==null){if(!f)return null;if(f.errors)i=f.matches;else if(s.length===0&&!f.initialized&&f.matches.length>0)i=f.matches;else return null}let d=i,h=f?.errors;if(h!=null){let j=d.findIndex(A=>A.route.id&&h?.[A.route.id]!==void 0);ze(j>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(h).join(",")}`),d=d.slice(0,Math.min(d.length,j+1))}let b=!1,N=-1;if(o&&f){b=f.renderFallback;for(let j=0;j=0?d=d.slice(0,N+1):d=[d[0]];break}}}}let S=o?.onError,y=f&&S?(j,A)=>{S(j,{location:f.location,params:f.matches?.[0]?.params??{},unstable_pattern:Fy(f.matches),errorInfo:A})}:void 0;return d.reduceRight((j,A,q)=>{let H,Z=!1,G=null,B=null;f&&(H=h&&A.route.id?h[A.route.id]:void 0,G=A.route.errorElement||d0,b&&(N<0&&q===0?(Ym("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),Z=!0,B=null):N===q&&(Z=!0,B=A.route.hydrateFallbackElement||null)));let Q=s.concat(d.slice(0,q+1)),V=()=>{let $;return H?$=G:Z?$=B:A.route.Component?$=E.createElement(A.route.Component,null):A.route.element?$=A.route.element:$=j,E.createElement(h0,{match:A,routeContext:{outlet:j,matches:Q,isDataRoute:f!=null},children:$})};return f&&(A.route.ErrorBoundary||A.route.errorElement||q===0)?E.createElement(Lm,{location:f.location,revalidation:f.revalidation,component:G,error:H,children:V(),routeContext:{outlet:null,matches:Q,isDataRoute:!0},onError:y}):V()},null)}function Ff(i){return`${i} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function y0(i){let s=E.useContext(Ba);return ze(s,Ff(i)),s}function p0(i){let s=E.useContext(di);return ze(s,Ff(i)),s}function g0(i){let s=E.useContext(Mt);return ze(s,Ff(i)),s}function If(i){let s=g0(i),o=s.matches[s.matches.length-1];return ze(o.route.id,`${i} can only be used on routes that contain a unique "id"`),o.route.id}function S0(){return If("useRouteId")}function b0(){let i=E.useContext(kf),s=p0("useRouteError"),o=If("useRouteError");return i!==void 0?i:s.errors?.[o]}function _0(){let{router:i}=y0("useNavigate"),s=If("useNavigate"),o=E.useRef(!1);return Hm(()=>{o.current=!0}),E.useCallback(async(d,h={})=>{Nt(o.current,Um),o.current&&(typeof d=="number"?await i.navigate(d):await i.navigate(d,{fromRouteId:s,...h}))},[i,s])}var _m={};function Ym(i,s,o){!s&&!_m[i]&&(_m[i]=!0,Nt(!1,o))}E.memo(E0);function E0({routes:i,future:s,state:o,isStatic:f,onError:d}){return qm(i,void 0,{state:o,isStatic:f,onError:d})}function T0({to:i,replace:s,state:o,relative:f}){ze(qa()," may be used only in the context of a component.");let{static:d}=E.useContext(ht);Nt(!d," must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.");let{matches:h}=E.useContext(Mt),{pathname:b}=Yt(),N=Bm(),S=oi(i,Wf(h),b,f==="path"),y=JSON.stringify(S);return E.useEffect(()=>{N(JSON.parse(y),{replace:s,state:o,relative:f})},[N,y,f,s,o]),null}function x0(i){return s0(i.context)}function Ha(i){ze(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function A0({basename:i="/",children:s=null,location:o,navigationType:f="POP",navigator:d,static:h=!1,unstable_useTransitions:b}){ze(!qa(),"You cannot render a inside another . You should never have more than one in your app.");let N=i.replace(/^\/*/,"/"),S=E.useMemo(()=>({basename:N,navigator:d,static:h,unstable_useTransitions:b,future:{}}),[N,d,h,b]);typeof o=="string"&&(o=kl(o));let{pathname:y="/",search:j="",hash:A="",state:q=null,key:H="default",unstable_mask:Z}=o,G=E.useMemo(()=>{let B=nl(y,N);return B==null?null:{location:{pathname:B,search:j,hash:A,state:q,key:H,unstable_mask:Z},navigationType:f}},[N,y,j,A,q,H,f,Z]);return Nt(G!=null,` is not able to match the URL "${y}${j}${A}" because it does not start with the basename, so the won't render anything.`),G==null?null:E.createElement(ht.Provider,{value:S},E.createElement(qn.Provider,{children:s,value:G}))}function z0({children:i,location:s}){return r0(Jf(i),s)}function Jf(i,s=[]){let o=[];return E.Children.forEach(i,(f,d)=>{if(!E.isValidElement(f))return;let h=[...s,d];if(f.type===E.Fragment){o.push.apply(o,Jf(f.props.children,h));return}ze(f.type===Ha,`[${typeof f.type=="string"?f.type:f.type.name}] is not a component. All component children of must be a or `),ze(!f.props.index||!f.props.children,"An index route cannot have child routes.");let b={id:f.props.id||h.join("-"),caseSensitive:f.props.caseSensitive,element:f.props.element,Component:f.props.Component,index:f.props.index,path:f.props.path,middleware:f.props.middleware,loader:f.props.loader,action:f.props.action,hydrateFallbackElement:f.props.hydrateFallbackElement,HydrateFallback:f.props.HydrateFallback,errorElement:f.props.errorElement,ErrorBoundary:f.props.ErrorBoundary,hasErrorBoundary:f.props.hasErrorBoundary===!0||f.props.ErrorBoundary!=null||f.props.errorElement!=null,shouldRevalidate:f.props.shouldRevalidate,handle:f.props.handle,lazy:f.props.lazy};f.props.children&&(b.children=Jf(f.props.children,h)),o.push(b)}),o}var ui="get",ii="application/x-www-form-urlencoded";function mi(i){return typeof HTMLElement<"u"&&i instanceof HTMLElement}function N0(i){return mi(i)&&i.tagName.toLowerCase()==="button"}function R0(i){return mi(i)&&i.tagName.toLowerCase()==="form"}function O0(i){return mi(i)&&i.tagName.toLowerCase()==="input"}function j0(i){return!!(i.metaKey||i.altKey||i.ctrlKey||i.shiftKey)}function D0(i,s){return i.button===0&&(!s||s==="_self")&&!j0(i)}var ai=null;function M0(){if(ai===null)try{new FormData(document.createElement("form"),0),ai=!1}catch{ai=!0}return ai}var C0=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Xf(i){return i!=null&&!C0.has(i)?(Nt(!1,`"${i}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${ii}"`),null):i}function U0(i,s){let o,f,d,h,b;if(R0(i)){let N=i.getAttribute("action");f=N?nl(N,s):null,o=i.getAttribute("method")||ui,d=Xf(i.getAttribute("enctype"))||ii,h=new FormData(i)}else if(N0(i)||O0(i)&&(i.type==="submit"||i.type==="image")){let N=i.form;if(N==null)throw new Error('Cannot submit a