diff --git a/CHANGELOG.md b/CHANGELOG.md index d858f32..09e80e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to FlightDeck will be documented in this file. This project follows [Semantic Versioning](https://semver.org/). From **v1.0.0**, documented CLI behavior (**[README.md](https://github.com/flightdeckdev/flightdeck/blob/main/README.md)** on the canonical **`main`** branch), committed **`schemas/v1/`**, and **`POST /v1/events`** payloads with **`api_version` `v1`** are treated as stable public contracts unless a release notes a semver-major bump. +## Unreleased + +### Added + +- **`GET /v1/runs/export`** — NDJSON stream of the same filtered slice as **`GET /v1/runs`** (optional response headers when truncated). +- **`session_id`** / **`span_id`** query filters on **`GET /v1/runs`**, matching CLI/SDK, and **`offset`** pagination on run listings (with **`runs list`** / **`runs export`**). +- **Web Runs** page — query **`GET /v1/runs`** from the bundled UI. + ## 1.1.2 - 2026-05-03 ### Added @@ -21,7 +29,7 @@ This project follows [Semantic Versioning](https://semver.org/). From **v1.0.0** - **`GET /v1/workspace`:** read-only JSON for operators and the web UI — **`promotion_requires_approval`**, **`pricing_catalog_configured`**, **`server_version`** (normative schema + Python SDK helper). - **Web Actions:** Promote flow uses workspace flags — direct **`POST /v1/promote`** when approval is off; **request → list pending → confirm** when **`promotion_requires_approval`** is on, with clearer errors. -- **Docs:** README / **release-artifact** / **examples** / **web-ui** / **http-api** / **sdk** updates for Phase 1 remainder; optional **`docs/pricing-catalog.md`**; **`examples/ci/promote_with_approval.sh`** and CI README **GitHub Actions** pattern for approval-gated promote. +- **Docs:** README / **release-artifact** / **examples** / **web-ui** / **http-api** / **sdk** updates for the **v1.1.x** remainder; optional **`docs/pricing-catalog.md`**; **`examples/ci/promote_with_approval.sh`** and CI README **GitHub Actions** pattern for approval-gated promote. ### Changed @@ -50,7 +58,7 @@ This project follows [Semantic Versioning](https://semver.org/). From **v1.0.0** - **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. +- **Roadmap:** **Phase 0** declared **closed**; **catalog-level** multi-provider pricing normalization called out under **mid-term productization** build items. - **Tests:** **`test_doctor_backup_writes_valid_sqlite`** in **`tests/test_cli.py`**. ### Changed diff --git a/README.md b/README.md index a01c8dc..74c0a69 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Small prompt or model changes can silently move **cost**, **latency**, and **err FlightDeck is **local-first** and ships as a Python CLI backed by SQLite. **v1.0.0** froze **SemVer-stable public contracts** for the documented CLI, committed **`schemas/v1/`**, -and **`POST /v1/events`** with **`api_version` `v1`**. **v1.1.x** adds Phase 1 slices (optional pricing catalog on diffs, +and **`POST /v1/events`** with **`api_version` `v1`**. **v1.1.x** adds catalog-aware diffs, approval flows, and forensics slices (optional pricing catalog on diffs, promotion request/confirm, read-only runs listing, **`GET /v1/workspace`** for UI and automation, Helm/fleet examples) without breaking those v1.0 shapes. See **[RELEASE_NOTES.md](RELEASE_NOTES.md)** and **[CHANGELOG.md](CHANGELOG.md)**. The product scope is still intentionally narrow (release governance, not a hosted agent platform). diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 79da562..65e08d4 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,7 +4,7 @@ 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.1.2 — Forensics filters, JSONL export, Phase 1 closure slice +## v1.1.2 — Forensics filters, JSONL export, productization closure slice Patch release (see **[CHANGELOG.md](CHANGELOG.md)**): optional **`trace_id`** filter on **`GET /v1/runs`**, **`flightdeck runs list --trace-id`**, and SDK **`list_runs(trace_id=…)`** (exact match on **`RunEvent.request.trace_id`**); **`flightdeck runs export`** writes the same filtered slice as JSONL (stdout or **`-o`**, **`--limit`** up to **500**, stderr warning when truncated). **Stable contracts:** additive HTTP query param and CLI command only. @@ -12,13 +12,13 @@ Patch release (see **[CHANGELOG.md](CHANGELOG.md)**): optional **`trace_id`** fi Patch release (see **[CHANGELOG.md](CHANGELOG.md)**): **`GET /v1/workspace`** exposes non-secret workspace flags (**`promotion_requires_approval`**, **`pricing_catalog_configured`**, **`server_version`**) for scripting and the **Actions** page; web **Promote** follows the two-step request/confirm path when approval is required; expanded operator docs and **`examples/ci/promote_with_approval.sh`** + README workflow snippet. **Stable contracts:** additive HTTP and JSON Schema only. -## v1.1.0 — Phase 1 first slice (catalog, approval, runs, Helm, fleet) +## v1.1.0 — Catalog, approval, runs, Helm, fleet (first v1.1 slice) Minor release (see **[CHANGELOG.md](CHANGELOG.md)**): optional **`pricing_catalog_path`** + **`PricingCatalog`** YAML for cross-vendor comparable **`pricing.catalog`** lines on diffs; **`pricing.hints`** for multi-version and model-name diagnostics; **`promotion_requires_approval`** with **`POST /v1/promote/request`** / **`POST /v1/promote/confirm`** / **`GET /v1/promotion-requests`** and matching CLI; **`GET /v1/runs`** and **`flightdeck runs list`**; SQLite migration **v4** (`promotion_requests`); reference **Helm** chart and **fleet** docs under **`examples/`**. **Stable contracts:** additive HTTP and CLI surfaces; existing **`v1`** event and release payloads unchanged. ## 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. +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 **mid-term** 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 diff --git a/ROADMAP.md b/ROADMAP.md index ac37800..2f98be7 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -14,7 +14,7 @@ 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/`); **`GET /v1/runs`**, **`runs list`**, optional **`trace_id`** filter, and **`runs export`** (JSONL) for operator forensics. -- **Local API + UI:** `flightdeck serve` routes and web UI (Overview with ledger metrics, Diff, Promote) in `src/flightdeck/server/static/`. +- **Local API + UI:** `flightdeck serve` routes and web UI (Overview with ledger metrics, Diff, Runs, Promote) in `src/flightdeck/server/static/`. - **SDK and tooling:** Python sync/async clients with retries/batching and `flightdeck-quickstart-verify`. --- @@ -23,13 +23,13 @@ This roadmap is meant to be clear from **what is already shipped** to **near-ter Further work after **v1.1.2** — **OTLP-oriented** telemetry, **replay-style web** forensics, deeper **catalog lifecycle** governance, and **cross-workspace / fleet** product surfaces stay on **Phase 2 / mid-term** (see gaps table below). Track **[CHANGELOG.md](CHANGELOG.md)**. -**v1.1.2** (patch, shipped): **`trace_id`** filter on **`GET /v1/runs`**, **`flightdeck runs list --trace-id`**, and SDK **`list_runs`**, plus **`flightdeck runs export`** (JSONL, stderr warning when truncated); **[examples/README.md](examples/README.md)** adds a **Phase 1 readiness checklist**; **Phase 1 status** (this document) records closure of the scoped productization tranche. See **[CHANGELOG.md](CHANGELOG.md)** and **[RELEASE_NOTES.md](RELEASE_NOTES.md)**. +**v1.1.2** (patch, shipped): **`trace_id`** filter on **`GET /v1/runs`**, **`flightdeck runs list --trace-id`**, and SDK **`list_runs`**, plus **`flightdeck runs export`** (JSONL, stderr warning when truncated); **[examples/README.md](examples/README.md)** adds a **readiness checklist**; **productization tranche status** (this document) records closure of the scoped local-first slice. See **[CHANGELOG.md](CHANGELOG.md)** and **[RELEASE_NOTES.md](RELEASE_NOTES.md)**. **v1.1.1** (patch, shipped): **`GET /v1/workspace`** (read-only flags + **`server_version`**); web **Actions** page uses it for **direct promote** vs **request / pending list / confirm**; operator docs refresh (**README**, **release-artifact**, **examples**, **web-ui**, **http-api**, **sdk**, **`docs/pricing-catalog.md`**, **SECURITY**); **`examples/ci/promote_with_approval.sh`** and **`github-actions/promote-approval-twostep.yml`**; CI runs a second Playwright pass with **`FD_E2E_FORCE_APPROVAL`**. See **[CHANGELOG.md](CHANGELOG.md)** and **[RELEASE_NOTES.md](RELEASE_NOTES.md)**. -**v1.1.0** (minor, shipped): Phase 1 first slice — **`pricing_catalog_path`** + **`pricing.catalog`** / **`pricing.hints`** on diffs; **`promotion_requires_approval`** + promote **request/confirm** (HTTP + CLI) + **`GET /v1/promotion-requests`**; **`GET /v1/runs`** / **`runs list`**; **Helm** reference chart; **`examples/fleet/`**; SQLite migration **v4**. See **[CHANGELOG.md](CHANGELOG.md)** and **[RELEASE_NOTES.md](RELEASE_NOTES.md)**. +**v1.1.0** (minor, shipped): **`pricing_catalog_path`** + **`pricing.catalog`** / **`pricing.hints`** on diffs; **`promotion_requires_approval`** + promote **request/confirm** (HTTP + CLI) + **`GET /v1/promotion-requests`**; **`GET /v1/runs`** / **`runs list`**; **Helm** reference chart; **`examples/fleet/`**; SQLite migration **v4**. See **[CHANGELOG.md](CHANGELOG.md)** and **[RELEASE_NOTES.md](RELEASE_NOTES.md)**. -**v1.0.6** (patch, shipped): 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. +**v1.0.6** (patch, shipped): 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 **mid-term productization** (the **v1.1.x** track). See **[CHANGELOG.md](CHANGELOG.md)** and **[RELEASE_NOTES.md](RELEASE_NOTES.md)**. No breaking changes to stable CLI, HTTP, or **`api_version` `v1`** contracts. --- @@ -79,7 +79,7 @@ Shipped on **`main`**: **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). -**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. +**Carried forward** (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 @@ -90,19 +90,19 @@ Shipped on **`main`**: --- -## Phase 1: Productization (mid term, roughly quarters) +## Mid term: Productization (v1.1.x tranche, roughly quarters) Goal: move from solid local tooling to repeatable production usage patterns. -**v1.1.0** ships the first tranche: catalog + hints on diffs, approval-gated promote (HTTP + CLI), read-only runs listing, Helm + fleet reference docs, and migration **v4**. **v1.1.1** closes the **web + discovery** gap for approval (**`GET /v1/workspace`**, Actions UX) and refreshes team docs / CI examples. **v1.1.2** adds **CLI/HTTP forensics** filters and **JSONL export**; see **Phase 1 status** below. +**v1.1.0** ships the first tranche: catalog + hints on diffs, approval-gated promote (HTTP + CLI), read-only runs listing, Helm + fleet reference docs, and migration **v4**. **v1.1.1** closes the **web + discovery** gap for approval (**`GET /v1/workspace`**, Actions UX) and refreshes team docs / CI examples. **v1.1.2** adds **CLI/HTTP forensics** filters and **JSONL export**; see **tranche status** below. -### Phase 1 progress (post–v1.1.0 / v1.1.1) +### Productization progress (post–v1.1.0 / v1.1.1) - **Approval workflow:** **v1.1.0** added HTTP + CLI + **`GET /v1/promotion-requests`**. **v1.1.1** adds **`GET /v1/workspace`** and a first-class **web** path (request → pending table → confirm) keyed off `promotion_requires_approval`, plus **`examples/ci/promote_with_approval.sh`** and a **`workflow_dispatch`** sample workflow. - **Operator narrative:** README / **examples** index / **web-ui** / **release-artifact** / **http-api** / **sdk** / optional **`docs/pricing-catalog.md`** describe catalog fields, runs listing, and the two promote modes. - **Forensics (v1.1.2):** **`trace_id`** filter and **`runs export`** (JSONL). **Still open** for replay-style **web** views and richer export semantics if needed; **OTLP** and **catalog lifecycle** depth remain mid-term (gaps table). -### Build in this phase +### Build targets - Human-in-the-loop approval workflow on top of policy gates (without requiring a hosted control plane). - **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. @@ -111,15 +111,15 @@ Goal: move from solid local tooling to repeatable production usage patterns. - Deployment hardening artifacts (for example Helm or equivalent) if a blessed server topology is chosen. - Multi-workspace operator ergonomics (naming, templates, reproducible setup patterns). -### Phase-1 readiness signals +### Readiness signals - Approval-gated promotion is used in at least one end-to-end production pipeline. - At least two provider pricing sources compare cleanly in one diff workflow. - Teams can stand up and operate `flightdeck serve` with documented deployment guidance. -### Phase 1 status +### Productization tranche status -**Phase 1 is closed** as of **v1.1.2** for the **scoped local-first productization tranche** shipped across **v1.1.0–v1.1.2**: catalog-aware diffs + hints, approval-gated promote (HTTP + CLI + web), read-only runs forensics (**`GET /v1/runs`**, **`runs list`**, **`trace_id`**, **`runs export`**), reference **Helm** / **Compose** / **fleet** examples, SQLite migration **v4**, **`GET /v1/workspace`**, and a discoverability **checklist** for the Phase-1 **readiness signals** in **[examples/README.md](examples/README.md)**. +**The scoped v1.1.0–v1.1.2 tranche is closed** as of **v1.1.2**: catalog-aware diffs + hints, approval-gated promote (HTTP + CLI + web), read-only runs forensics (**`GET /v1/runs`**, **`runs list`**, **`trace_id`**, **`runs export`**), reference **Helm** / **Compose** / **fleet** examples, SQLite migration **v4**, **`GET /v1/workspace`**, and a discoverability **checklist** for the **readiness signals** in **[examples/README.md](examples/README.md)**. **Carried forward to Phase 2 / mid-term** (explicitly not claimed by this closure): **OTLP-oriented** correlated telemetry; **cross-workspace / fleet** governance products; **replay-style** forensics UI beyond CLI/HTTP listing; **enterprise-grade** identity beyond documented bearer + loopback patterns; deeper **catalog lifecycle** governance (for example version skew hints). diff --git a/docs/cli.md b/docs/cli.md index 6baaa89..6365039 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -453,17 +453,17 @@ Subgroup for ingesting, listing, and exporting run events. Print ingested events for a release (newest first), truncated to `--limit`. ```bash -flightdeck runs list RELEASE_ID --window WINDOW [--env ENV] [--tenant …] [--task …] [--trace-id ID] [--limit N] [--output json] +flightdeck runs list RELEASE_ID --window WINDOW [--env ENV] [--tenant …] [--task …] [--trace-id ID] [--session-id ID] [--span-id ID] [--offset N] [--limit N] [--output json] ``` -`--trace-id` filters to events whose ingested `request.trace_id` equals the given string (exact match), same as the `trace_id` query parameter on `GET /v1/runs`. +`--trace-id`, `--session-id`, and `--span-id` filter to exact matches on ingested `request.*` fields (same query names as `GET /v1/runs`). **`--offset`** skips that many newest-matching events before applying **`--limit`**. ### `flightdeck runs export` Write the same filtered slice as `runs list` (newest first) as **JSONL** — one `RunEvent` JSON object per line. Default **`--limit`** is **500** (maximum **500**). If more events match the window and filters, only the first **`--limit`** lines are written and a **`WARNING:`** line is printed to **stderr** with `exported` / `matching` counts. ```bash -flightdeck runs export RELEASE_ID --window WINDOW [-o export.jsonl] [--env ENV] [--tenant …] [--task …] [--trace-id ID] [--limit N] +flightdeck runs export RELEASE_ID --window WINDOW [-o export.jsonl] [--env ENV] [--tenant …] [--task …] [--trace-id ID] [--session-id ID] [--span-id ID] [--offset N] [--limit N] ``` With **`-o` / `--output`**, writes UTF-8 JSONL to that path; without it, writes to **stdout** (suitable for pipes). diff --git a/docs/http-api.md b/docs/http-api.md index 8754fb6..12a06e4 100644 --- a/docs/http-api.md +++ b/docs/http-api.md @@ -22,7 +22,7 @@ Two access tiers: | Route | No token configured | `FLIGHTDECK_LOCAL_API_TOKEN` set | |-------|--------------------|---------------------------------| | `GET /health` | open | open | -| `GET /v1/*` (reads, including `GET /v1/workspace`, `GET /v1/metrics`, `GET /v1/runs`, `GET /v1/promotion-requests`) | open | open | +| `GET /v1/*` (reads, including `GET /v1/workspace`, `GET /v1/metrics`, `GET /v1/runs`, `GET /v1/runs/export`, `GET /v1/promotion-requests`) | open | open | | `POST /v1/events` | open† | open (no Bearer required) | | `POST /v1/diff` | open | open | | `POST /v1/promote` | loopback only | `Authorization: Bearer ` required | @@ -201,7 +201,7 @@ doctor` checks that the sequence has no gaps. ## `GET /v1/promotion-requests` -List promotion approval requests (Phase 1). Newest first. +List promotion approval requests. Newest first. **Query parameters** @@ -250,6 +250,9 @@ Read-only forensics: return a slice of ingested run events for one release (newe | `tenant_id` | string | — | Optional filter | | `task_id` | string | — | Optional filter | | `trace_id` | string | — | Optional filter: exact match on `RunEvent.request.trace_id` (ingested JSON path `request.trace_id`) | +| `session_id` | string | — | Optional filter: exact match on `request.session_id` | +| `span_id` | string | — | Optional filter: exact match on `request.span_id` | +| `offset` | integer | 0 | Skip this many newest-matching events before returning the page (0–500000) | | `limit` | integer | 100 | Max events returned (1–500) | **Response** @@ -259,7 +262,9 @@ Read-only forensics: return a slice of ingested run events for one release (newe "release_id": "rel_abc", "since": "2026-04-25T12:00:00+00:00", "until": "2026-05-02T12:00:00+00:00", - "filters": { "environment": "local", "tenant_id": null, "task_id": null, "trace_id": null }, + "filters": { "environment": "local", "tenant_id": null, "task_id": null, "trace_id": null, "session_id": null, "span_id": null }, + "offset": 0, + "limit": 10, "matched_total": 42, "returned": 10, "truncated": true, @@ -271,6 +276,21 @@ Each element of `events` is a `RunEvent` object (`schemas/v1/run_event.schema.js --- +## `GET /v1/runs/export` + +Same **query parameters** and filter semantics as **`GET /v1/runs`** (defaults: **`offset`** `0`, **`limit`** `500`). Response body is **NDJSON**: one JSON object per line, each a `RunEvent` (`schemas/v1/run_event.schema.json`). **`Content-Type`:** `application/x-ndjson`. + +Response headers (non-secret hints for clients): + +| Header | Meaning | +|--------|---------| +| `X-Flightdeck-Matched-Total` | Count of events matching filters in the window | +| `X-Flightdeck-Returned` | Lines in this response body | +| `X-Flightdeck-Offset` | `offset` query value used | +| `X-Flightdeck-Truncated` | `true` if more matching events exist after this page | + +--- + ## `POST /v1/events` Ingest `RunEvent` records (runtime evidence for diff and policy evaluation). diff --git a/docs/sdk.md b/docs/sdk.md index 3005526..ff301f1 100644 --- a/docs/sdk.md +++ b/docs/sdk.md @@ -177,9 +177,13 @@ as `post_promote`. `GET /v1/promotion-requests`. -### `list_runs(*, release_id, window, environment=None, tenant_id=None, task_id=None, trace_id=None, limit=100) -> dict` +### `list_runs(*, release_id, window, environment=None, tenant_id=None, task_id=None, trace_id=None, session_id=None, span_id=None, offset=0, limit=100) -> dict` -`GET /v1/runs` — read-only event slice for forensics. When `trace_id` is set, only events whose `request.trace_id` matches are returned. +`GET /v1/runs` — read-only event slice for forensics. Optional `trace_id`, `session_id`, and `span_id` filter on `request.*` (exact match). `offset` skips the newest matching events before returning up to `limit` rows. + +### `fetch_runs_export_ndjson(*, release_id, window, …) -> tuple[bytes, dict[str, str]]` + +`GET /v1/runs/export` — same filters as `list_runs`; returns the raw **NDJSON** body and selected `X-Flightdeck-*` response headers. ## Async usage diff --git a/docs/web-ui.md b/docs/web-ui.md index a5431f3..3de3f2a 100644 --- a/docs/web-ui.md +++ b/docs/web-ui.md @@ -18,6 +18,7 @@ The app uses **HashRouter** (`react-router-dom`) so all navigation stays within |-----------|-----------|-----------|-------| | `#/` | `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` | Renders `pricing.warnings`, optional **`pricing.catalog`** / **`pricing.hints`**, per-1k prices when present | +| `#/runs` | `RunsPage` | `GET /v1/releases` (for datalist), `GET /v1/runs`, `GET /v1/runs/export` | Forensics: filters, table, NDJSON download | | `#/actions` | `ActionsPage` | `GET /v1/workspace`, `GET /v1/promotion-requests` (when `promotion_requires_approval`), `POST /v1/promote` **or** `POST /v1/promote/request` + `POST /v1/promote/confirm`, `POST /v1/rollback` | Workspace strip shows server version + mode; see **ActionsPage** below | | `#/*` (any other) | — | Redirects to `#/` | | @@ -39,6 +40,7 @@ App (HashRouter) ├── SecurityStatusBar (below header, above main content) ├── OverviewPage (route: #/) ├── DiffPage (route: #/diff) + ├── RunsPage (route: #/runs) └── ActionsPage (route: #/actions; redirects → #/ when UI_READ_ONLY) ``` diff --git a/examples/README.md b/examples/README.md index 4f76ac1..30c89dc 100644 --- a/examples/README.md +++ b/examples/README.md @@ -12,9 +12,9 @@ This folder holds **copy-pasteable** references for wiring FlightDeck into a rea 6. **Run the server** in a container or compose stack — see [deploy/](deploy/README.md). The bundled UI calls **`GET /v1/workspace`** to choose direct promote vs request/confirm. 7. **Triage runs** with **`flightdeck runs list`** / **`runs export`** or **`GET /v1/runs`**, and **observe** aggregate ledger size with **`GET /v1/metrics`** (JSON counters; read-only, same access tier as other `GET /v1/*` routes). -## Phase 1 readiness (quick checklist) +## Readiness checklist (quick pass) -Use this as a **discoverability** pass for the **[ROADMAP.md](../ROADMAP.md)** Phase-1 readiness signals (not a product guarantee): +Use this as a **discoverability** pass for the **[ROADMAP.md](../ROADMAP.md)** readiness signals (not a product guarantee): | Signal | Where to start | |--------|----------------| diff --git a/examples/fleet/README.md b/examples/fleet/README.md index 5ba3a37..b8f57fc 100644 --- a/examples/fleet/README.md +++ b/examples/fleet/README.md @@ -1,4 +1,4 @@ -# Multi-workspace operator patterns (Phase 1) +# Multi-workspace operator patterns FlightDeck is **local-first**: one `flightdeck.yaml` + SQLite database per working directory. “Fleet” ergonomics here means **repeatable layouts** and naming—not a hosted control plane. @@ -19,3 +19,11 @@ Set `promotion_requires_approval: true` in `flightdeck.yaml` to require `release ## Template See `workspace-staging.example.yaml` for a copy-paste starting point; copy to your repo root as `flightdeck.yaml` and edit paths. + +## Multi-workspace aggregation (read-model) + +Prefer **per-workspace** ledgers and **pull**-based joins in your own tooling: + +- **`flightdeck runs export`** / **`GET /v1/runs`** (and **`GET /v1/runs/export`** when using `flightdeck serve`) — JSONL or JSON per workspace. +- **`GET /v1/metrics`** — coarse counters per workspace. +- **CI** — one job per workspace directory (see [examples/ci/README.md](../ci/README.md)). diff --git a/examples/fleet/workspace-staging.example.yaml b/examples/fleet/workspace-staging.example.yaml index ceee19b..fb63e8f 100644 --- a/examples/fleet/workspace-staging.example.yaml +++ b/examples/fleet/workspace-staging.example.yaml @@ -6,6 +6,6 @@ diff: min_candidate_runs: 500 min_baseline_runs: 500 min_low_runs: 50 -# Optional Phase 1 fields (uncomment and adjust paths): +# Optional catalog / pricing fields (uncomment and adjust paths): # pricing_catalog_path: examples/pricing/catalog.sample.yaml # promotion_requires_approval: true diff --git a/src/flightdeck/cli/main.py b/src/flightdeck/cli/main.py index 5f8924e..9a3a3de 100644 --- a/src/flightdeck/cli/main.py +++ b/src/flightdeck/cli/main.py @@ -323,7 +323,10 @@ def runs() -> None: @click.option("--tenant", "tenant_id", default=None) @click.option("--task", "task_id", default=None) @click.option("--trace-id", "trace_id", default=None, help="Filter to events whose request.trace_id matches (exact).") -@click.option("--limit", default=100, show_default=True, type=int) +@click.option("--session-id", "session_id", default=None, help="Filter to request.session_id (exact).") +@click.option("--span-id", "span_id", default=None, help="Filter to request.span_id (exact).") +@click.option("--offset", default=0, show_default=True, type=click.IntRange(0, 500_000)) +@click.option("--limit", default=100, show_default=True, type=click.IntRange(1, 500)) @click.option( "--output", "output_format", @@ -338,6 +341,9 @@ def runs_list( tenant_id: str | None, task_id: str | None, trace_id: str | None, + session_id: str | None, + span_id: str | None, + offset: int, limit: int, output_format: str, ) -> None: @@ -355,6 +361,9 @@ def runs_list( tenant_id=tenant_id, task_id=task_id, trace_id=trace_id, + session_id=session_id, + span_id=span_id, + offset=offset, limit=limit, ) except OperationError as e: @@ -377,6 +386,9 @@ def runs_list( @click.option("--tenant", "tenant_id", default=None) @click.option("--task", "task_id", default=None) @click.option("--trace-id", "trace_id", default=None, help="Filter to events whose request.trace_id matches (exact).") +@click.option("--session-id", "session_id", default=None, help="Filter to request.session_id (exact).") +@click.option("--span-id", "span_id", default=None, help="Filter to request.span_id (exact).") +@click.option("--offset", default=0, show_default=True, type=click.IntRange(0, 500_000)) @click.option("--limit", default=500, show_default=True, type=click.IntRange(1, 500)) @click.option( "-o", @@ -393,6 +405,9 @@ def runs_export( tenant_id: str | None, task_id: str | None, trace_id: str | None, + session_id: str | None, + span_id: str | None, + offset: int, limit: int, output_path: Path | None, ) -> None: @@ -410,6 +425,9 @@ def runs_export( tenant_id=tenant_id, task_id=task_id, trace_id=trace_id, + session_id=session_id, + span_id=span_id, + offset=offset, limit=limit, ) except OperationError as e: @@ -425,7 +443,7 @@ def runs_export( if payload["truncated"]: click.echo( f"WARNING: exported {payload['returned']} of {payload['matched_total']} matching events " - f"(cap --limit {limit}).", + f"(offset={payload['offset']}, --limit {limit}).", err=True, ) diff --git a/src/flightdeck/models.py b/src/flightdeck/models.py index 385420c..ef27555 100644 --- a/src/flightdeck/models.py +++ b/src/flightdeck/models.py @@ -262,7 +262,7 @@ class PromotionRecord(BaseModel): class PromotionRequestRecord(BaseModel): - """Pending human approval before ``commit_promotion`` (Phase 1).""" + """Pending human approval before ``commit_promotion``.""" request_id: str status: Literal["pending", "completed", "cancelled"] = "pending" diff --git a/src/flightdeck/operations.py b/src/flightdeck/operations.py index d8edd08..f1986d7 100644 --- a/src/flightdeck/operations.py +++ b/src/flightdeck/operations.py @@ -721,6 +721,9 @@ def query_run_events_page( tenant_id: str | None, task_id: str | None, trace_id: str | None = None, + session_id: str | None = None, + span_id: str | None = None, + offset: int = 0, limit: int, ) -> dict[str, object]: """Read-only slice of run events for forensics (newest-first truncation).""" @@ -728,6 +731,9 @@ def query_run_events_page( raise OperationError(f"Unknown release: {release_id}") env = environment or cfg.default_environment tid = (trace_id or "").strip() or None + sid = (session_id or "").strip() or None + spid = (span_id or "").strip() or None + off = max(0, int(offset)) try: delta = parse_window(window) except ValueError as e: @@ -742,10 +748,12 @@ def query_run_events_page( task_id=task_id, environment=env, trace_id=tid, + session_id=sid, + span_id=spid, ) events_sorted = sorted(events, key=lambda e: e.timestamp, reverse=True) lim = max(1, min(500, limit)) - page = events_sorted[:lim] + page = events_sorted[off : off + lim] return { "release_id": release_id, "since": since.isoformat(), @@ -755,10 +763,14 @@ def query_run_events_page( "tenant_id": tenant_id, "task_id": task_id, "trace_id": tid, + "session_id": sid, + "span_id": spid, }, + "offset": off, + "limit": lim, "matched_total": len(events), "returned": len(page), - "truncated": len(events) > len(page), + "truncated": off + len(page) < len(events), "events": [e.model_dump(mode="json") for e in page], } diff --git a/src/flightdeck/sdk/client.py b/src/flightdeck/sdk/client.py index d45a4ac..d883ac1 100644 --- a/src/flightdeck/sdk/client.py +++ b/src/flightdeck/sdk/client.py @@ -185,12 +185,16 @@ def list_runs( tenant_id: str | None = None, task_id: str | None = None, trace_id: str | None = None, + session_id: str | None = None, + span_id: str | None = None, + offset: int = 0, limit: int = 100, ) -> dict[str, Any]: params: dict[str, str | int] = { "release_id": release_id, "window": window, "limit": limit, + "offset": offset, } if environment is not None: params["environment"] = environment @@ -200,6 +204,10 @@ def list_runs( params["task_id"] = task_id if trace_id is not None: params["trace_id"] = trace_id + if session_id is not None: + params["session_id"] = session_id + if span_id is not None: + params["span_id"] = span_id resp = self._request_with_retry( "GET", "/v1/runs", @@ -209,6 +217,58 @@ def list_runs( resp.raise_for_status() return resp.json() + def fetch_runs_export_ndjson( + self, + *, + release_id: str, + window: str, + environment: str | None = None, + tenant_id: str | None = None, + task_id: str | None = None, + trace_id: str | None = None, + session_id: str | None = None, + span_id: str | None = None, + offset: int = 0, + limit: int = 500, + ) -> tuple[bytes, dict[str, str]]: + """GET /v1/runs/export — returns raw NDJSON body and selected response headers.""" + params: dict[str, str | int] = { + "release_id": release_id, + "window": window, + "limit": limit, + "offset": offset, + } + if environment is not None: + params["environment"] = environment + if tenant_id is not None: + params["tenant_id"] = tenant_id + if task_id is not None: + params["task_id"] = task_id + if trace_id is not None: + params["trace_id"] = trace_id + if session_id is not None: + params["session_id"] = session_id + if span_id is not None: + params["span_id"] = span_id + resp = self._request_with_retry( + "GET", + "/v1/runs/export", + params=params, + headers=self._auth_headers() or None, + ) + resp.raise_for_status() + hdrs = { + k: resp.headers[k] + for k in ( + "X-Flightdeck-Matched-Total", + "X-Flightdeck-Returned", + "X-Flightdeck-Offset", + "X-Flightdeck-Truncated", + ) + if k in resp.headers + } + return (resp.content, hdrs) + def post_rollback( self, *, @@ -442,12 +502,16 @@ async def list_runs( tenant_id: str | None = None, task_id: str | None = None, trace_id: str | None = None, + session_id: str | None = None, + span_id: str | None = None, + offset: int = 0, limit: int = 100, ) -> dict[str, Any]: params: dict[str, str | int] = { "release_id": release_id, "window": window, "limit": limit, + "offset": offset, } if environment is not None: params["environment"] = environment @@ -457,6 +521,10 @@ async def list_runs( params["task_id"] = task_id if trace_id is not None: params["trace_id"] = trace_id + if session_id is not None: + params["session_id"] = session_id + if span_id is not None: + params["span_id"] = span_id resp = await self._request_with_retry( "GET", "/v1/runs", @@ -466,6 +534,57 @@ async def list_runs( resp.raise_for_status() return resp.json() + async def fetch_runs_export_ndjson( + self, + *, + release_id: str, + window: str, + environment: str | None = None, + tenant_id: str | None = None, + task_id: str | None = None, + trace_id: str | None = None, + session_id: str | None = None, + span_id: str | None = None, + offset: int = 0, + limit: int = 500, + ) -> tuple[bytes, dict[str, str]]: + params: dict[str, str | int] = { + "release_id": release_id, + "window": window, + "limit": limit, + "offset": offset, + } + if environment is not None: + params["environment"] = environment + if tenant_id is not None: + params["tenant_id"] = tenant_id + if task_id is not None: + params["task_id"] = task_id + if trace_id is not None: + params["trace_id"] = trace_id + if session_id is not None: + params["session_id"] = session_id + if span_id is not None: + params["span_id"] = span_id + resp = await self._request_with_retry( + "GET", + "/v1/runs/export", + params=params, + headers=self._auth_headers() or None, + ) + resp.raise_for_status() + hdrs = { + k: resp.headers[k] + for k in ( + "X-Flightdeck-Matched-Total", + "X-Flightdeck-Returned", + "X-Flightdeck-Offset", + "X-Flightdeck-Truncated", + ) + if k in resp.headers + } + return (resp.content, hdrs) + async def post_rollback( self, *, diff --git a/src/flightdeck/server/routes/read.py b/src/flightdeck/server/routes/read.py index 10aed63..8913fcd 100644 --- a/src/flightdeck/server/routes/read.py +++ b/src/flightdeck/server/routes/read.py @@ -1,6 +1,9 @@ from __future__ import annotations +import json + from fastapi import APIRouter, HTTPException, Query, Request +from fastapi.responses import StreamingResponse from flightdeck import __version__ as flightdeck_version from flightdeck.models import PromotionRequestRecord, WorkspacePublic @@ -81,6 +84,9 @@ def get_runs( tenant_id: str | None = Query(default=None), task_id: str | None = Query(default=None), trace_id: str | None = Query(default=None), + session_id: str | None = Query(default=None), + span_id: str | None = Query(default=None), + offset: int = Query(default=0, ge=0, le=500_000), limit: int = Query(default=100, ge=1, le=500), ) -> dict[str, object]: cfg, storage = ensure_app_state(request) @@ -94,7 +100,61 @@ def get_runs( tenant_id=tenant_id, task_id=task_id, trace_id=trace_id, + session_id=session_id, + span_id=span_id, + offset=offset, limit=limit, ) except OperationError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc + + +@router.get("/v1/runs/export") +def get_runs_export( + request: Request, + release_id: str = Query(..., min_length=1), + window: str = Query(..., min_length=1), + environment: str | None = Query(default=None), + tenant_id: str | None = Query(default=None), + task_id: str | None = Query(default=None), + trace_id: str | None = Query(default=None), + session_id: str | None = Query(default=None), + span_id: str | None = Query(default=None), + offset: int = Query(default=0, ge=0, le=500_000), + limit: int = Query(default=500, ge=1, le=500), +) -> StreamingResponse: + """NDJSON stream of the same filtered slice as ``GET /v1/runs`` (read tier).""" + cfg, storage = ensure_app_state(request) + try: + payload = query_run_events_page( + cfg=cfg, + storage=storage, + release_id=release_id, + window=window, + environment=environment, + tenant_id=tenant_id, + task_id=task_id, + trace_id=trace_id, + session_id=session_id, + span_id=span_id, + offset=offset, + limit=limit, + ) + except OperationError as exc: + raise HTTPException(status_code=400, detail=str(exc)) from exc + + def body_iter(): + for ev in payload["events"]: + yield json.dumps(ev, sort_keys=True) + "\n" + + headers: dict[str, str] = { + "X-Flightdeck-Matched-Total": str(payload["matched_total"]), + "X-Flightdeck-Returned": str(payload["returned"]), + "X-Flightdeck-Offset": str(payload["offset"]), + "X-Flightdeck-Truncated": "true" if payload["truncated"] else "false", + } + return StreamingResponse( + body_iter(), + media_type="application/x-ndjson", + headers=headers, + ) diff --git a/src/flightdeck/server/static/assets/index-7m5ayZhE.js b/src/flightdeck/server/static/assets/index-7m5ayZhE.js new file mode 100644 index 0000000..7e0b7eb --- /dev/null +++ b/src/flightdeck/server/static/assets/index-7m5ayZhE.js @@ -0,0 +1,11 @@ +(function(){const s=document.createElement("link").relList;if(s&&s.supports&&s.supports("modulepreload"))return;for(const m of document.querySelectorAll('link[rel="modulepreload"]'))f(m);new MutationObserver(m=>{for(const h of m)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 d(m){const h={};return m.integrity&&(h.integrity=m.integrity),m.referrerPolicy&&(h.referrerPolicy=m.referrerPolicy),m.crossOrigin==="use-credentials"?h.credentials="include":m.crossOrigin==="anonymous"?h.credentials="omit":h.credentials="same-origin",h}function f(m){if(m.ep)return;m.ep=!0;const h=d(m);fetch(m.href,h)}})();var qf={exports:{}},Un={};var cm;function gy(){if(cm)return Un;cm=1;var i=Symbol.for("react.transitional.element"),s=Symbol.for("react.fragment");function d(f,m,h){var b=null;if(h!==void 0&&(b=""+h),m.key!==void 0&&(b=""+m.key),"key"in m){h={};for(var z in m)z!=="key"&&(h[z]=m[z])}else h=m;return m=h.ref,{$$typeof:i,type:f,key:b,ref:m!==void 0?m:null,props:h}}return Un.Fragment=s,Un.jsx=d,Un.jsxs=d,Un}var fm;function Sy(){return fm||(fm=1,qf.exports=gy()),qf.exports}var r=Sy(),Bf={exports:{}},ee={};var sm;function by(){if(sm)return ee;sm=1;var i=Symbol.for("react.transitional.element"),s=Symbol.for("react.portal"),d=Symbol.for("react.fragment"),f=Symbol.for("react.strict_mode"),m=Symbol.for("react.profiler"),h=Symbol.for("react.consumer"),b=Symbol.for("react.context"),z=Symbol.for("react.forward_ref"),S=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),C=Symbol.for("react.lazy"),T=Symbol.for("react.activity"),Y=Symbol.iterator;function H(p){return p===null||typeof p!="object"?null:(p=Y&&p[Y]||p["@@iterator"],typeof p=="function"?p:null)}var Q={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Z=Object.assign,q={};function V(p,A,B){this.props=p,this.context=A,this.refs=q,this.updater=B||Q}V.prototype.isReactComponent={},V.prototype.setState=function(p,A){if(typeof p!="object"&&typeof p!="function"&&p!=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,p,A,"setState")},V.prototype.forceUpdate=function(p){this.updater.enqueueForceUpdate(this,p,"forceUpdate")};function W(){}W.prototype=V.prototype;function X(p,A,B){this.props=p,this.context=A,this.refs=q,this.updater=B||Q}var w=X.prototype=new W;w.constructor=X,Z(w,V.prototype),w.isPureReactComponent=!0;var ae=Array.isArray;function te(){}var G={H:null,A:null,T:null,S:null},ie=Object.prototype.hasOwnProperty;function de(p,A,B){var K=B.ref;return{$$typeof:i,type:p,key:A,ref:K!==void 0?K:null,props:B}}function qe(p,A){return de(p.type,A,p.props)}function Xe(p){return typeof p=="object"&&p!==null&&p.$$typeof===i}function Oe(p){var A={"=":"=0",":":"=2"};return"$"+p.replace(/[=:]/g,function(B){return A[B]})}var We=/\/+/g;function Fe(p,A){return typeof p=="object"&&p!==null&&p.key!=null?Oe(""+p.key):A.toString(36)}function je(p){switch(p.status){case"fulfilled":return p.value;case"rejected":throw p.reason;default:switch(typeof p.status=="string"?p.then(te,te):(p.status="pending",p.then(function(A){p.status==="pending"&&(p.status="fulfilled",p.value=A)},function(A){p.status==="pending"&&(p.status="rejected",p.reason=A)})),p.status){case"fulfilled":return p.value;case"rejected":throw p.reason}}throw p}function x(p,A,B,K,P){var ce=typeof p;(ce==="undefined"||ce==="boolean")&&(p=null);var ge=!1;if(p===null)ge=!0;else switch(ce){case"bigint":case"string":case"number":ge=!0;break;case"object":switch(p.$$typeof){case i:case s:ge=!0;break;case C:return ge=p._init,x(ge(p._payload),A,B,K,P)}}if(ge)return P=P(p),ge=K===""?"."+Fe(p,0):K,ae(P)?(B="",ge!=null&&(B=ge.replace(We,"$&/")+"/"),x(P,A,B,"",function(Ga){return Ga})):P!=null&&(Xe(P)&&(P=qe(P,B+(P.key==null||p&&p.key===P.key?"":(""+P.key).replace(We,"$&/")+"/")+ge)),A.push(P)),1;ge=0;var Pe=K===""?".":K+":";if(ae(p))for(var Me=0;Me>>1,he=x[ue];if(0>>1;uem(B,$))Km(P,B)?(x[ue]=P,x[K]=$,ue=K):(x[ue]=B,x[A]=$,ue=A);else if(Km(P,$))x[ue]=P,x[K]=$,ue=K;else break e}}return L}function m(x,L){var $=x.sortIndex-L.sortIndex;return $!==0?$:x.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,z=b.now();i.unstable_now=function(){return b.now()-z}}var S=[],y=[],C=1,T=null,Y=3,H=!1,Q=!1,Z=!1,q=!1,V=typeof setTimeout=="function"?setTimeout:null,W=typeof clearTimeout=="function"?clearTimeout:null,X=typeof setImmediate<"u"?setImmediate:null;function w(x){for(var L=d(y);L!==null;){if(L.callback===null)f(y);else if(L.startTime<=x)f(y),L.sortIndex=L.expirationTime,s(S,L);else break;L=d(y)}}function ae(x){if(Z=!1,w(x),!Q)if(d(S)!==null)Q=!0,te||(te=!0,Oe());else{var L=d(y);L!==null&&je(ae,L.startTime-x)}}var te=!1,G=-1,ie=5,de=-1;function qe(){return q?!0:!(i.unstable_now()-dex&&qe());){var ue=T.callback;if(typeof ue=="function"){T.callback=null,Y=T.priorityLevel;var he=ue(T.expirationTime<=x);if(x=i.unstable_now(),typeof he=="function"){T.callback=he,w(x),L=!0;break t}T===d(S)&&f(S),w(x)}else f(S);T=d(S)}if(T!==null)L=!0;else{var p=d(y);p!==null&&je(ae,p.startTime-x),L=!1}}break e}finally{T=null,Y=$,H=!1}L=void 0}}finally{L?Oe():te=!1}}}var Oe;if(typeof X=="function")Oe=function(){X(Xe)};else if(typeof MessageChannel<"u"){var We=new MessageChannel,Fe=We.port2;We.port1.onmessage=Xe,Oe=function(){Fe.postMessage(null)}}else Oe=function(){V(Xe,0)};function je(x,L){G=V(function(){x(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(x){x.callback=null},i.unstable_forceFrameRate=function(x){0>x||125ue?(x.sortIndex=$,s(y,x),d(S)===null&&x===d(y)&&(Z?(W(G),G=-1):Z=!0,je(ae,$-ue))):(x.sortIndex=he,s(S,x),Q||H||(Q=!0,te||(te=!0,Oe()))),x},i.unstable_shouldYield=qe,i.unstable_wrapCallback=function(x){var L=Y;return function(){var $=Y;Y=L;try{return x.apply(this,arguments)}finally{Y=$}}}})(Gf)),Gf}var dm;function Ey(){return dm||(dm=1,Yf.exports=_y()),Yf.exports}var wf={exports:{}},Ie={};var mm;function xy(){if(mm)return Ie;mm=1;var i=Wf();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(),wf.exports=xy(),wf.exports}var vm;function jy(){if(vm)return Hn;vm=1;var i=Ey(),s=Wf(),d=Ny();function f(e){var t="https://react.dev/errors/"+e;if(1he||(e.current=ue[he],ue[he]=null,he--)}function B(e,t){he++,ue[he]=e.current,e.current=t}var K=p(null),P=p(null),ce=p(null),ge=p(null);function Pe(e,t){switch(B(ce,t),B(P,e),B(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=Cd(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}A(K),B(K,e)}function Me(){A(K),A(P),A(ce)}function Ga(e){e.memoizedState!==null&&B(ge,e);var t=K.current,l=Cd(t,e.type);t!==l&&(B(P,e),B(K,l))}function Qn(e){P.current===e&&(A(K),A(P)),ge.current===e&&(A(ge),On._currentValue=$)}var pi,us;function Cl(e){if(pi===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);pi=t&&t[1]||"",us=-1)":-1n||v[a]!==j[n]){var D=` +`+v[a].replace(" at new "," at ");return e.displayName&&D.includes("")&&(D=D.replace("",e.displayName)),D}while(1<=a&&0<=n);break}}}finally{gi=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Cl(l):""}function km(e,t){switch(e.tag){case 26:case 27:case 5:return Cl(e.type);case 16:return Cl("Lazy");case 13:return e.child!==t&&t!==null?Cl("Suspense Fallback"):Cl("Suspense");case 19:return Cl("SuspenseList");case 0:case 15:return Si(e.type,!1);case 11:return Si(e.type.render,!1);case 1:return Si(e.type,!0);case 31:return Cl("Activity");default:return""}}function is(e){try{var t="",l=null;do t+=km(e,l),l=e,e=e.return;while(e);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var bi=Object.prototype.hasOwnProperty,_i=i.unstable_scheduleCallback,Ei=i.unstable_cancelCallback,Wm=i.unstable_shouldYield,Fm=i.unstable_requestPaint,ft=i.unstable_now,Im=i.unstable_getCurrentPriorityLevel,cs=i.unstable_ImmediatePriority,fs=i.unstable_UserBlockingPriority,Zn=i.unstable_NormalPriority,Pm=i.unstable_LowPriority,ss=i.unstable_IdlePriority,eh=i.log,th=i.unstable_setDisableYieldValue,wa=null,st=null;function il(e){if(typeof eh=="function"&&th(e),st&&typeof st.setStrictMode=="function")try{st.setStrictMode(wa,e)}catch{}}var rt=Math.clz32?Math.clz32:nh,lh=Math.log,ah=Math.LN2;function nh(e){return e>>>=0,e===0?32:31-(lh(e)/ah|0)|0}var Vn=256,Kn=262144,Jn=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 $n(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 o=a&134217727;return o!==0?(a=o&~u,a!==0?n=Dl(a):(c&=o,c!==0?n=Dl(c):l||(l=o&~e,l!==0&&(n=Dl(l))))):(o=a&~u,o!==0?n=Dl(o):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 Xa(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function uh(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 rs(){var e=Jn;return Jn<<=1,(Jn&62914560)===0&&(Jn=4194304),e}function xi(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function Qa(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function ih(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 o=e.entanglements,v=e.expirationTimes,j=e.hiddenUpdates;for(l=c&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var dh=/[\n"\\]/g;function bt(e){return e.replace(dh,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function zi(e,t,l,a,n,u,c,o){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=""+St(t)):e.value!==""+St(t)&&(e.value=""+St(t)):c!=="submit"&&c!=="reset"||e.removeAttribute("value"),t!=null?Oi(e,c,St(t)):l!=null?Oi(e,c,St(l)):a!=null&&e.removeAttribute("value"),n==null&&u!=null&&(e.defaultChecked=!!u),n!=null&&(e.checked=n&&typeof n!="function"&&typeof n!="symbol"),o!=null&&typeof o!="function"&&typeof o!="symbol"&&typeof o!="boolean"?e.name=""+St(o):e.removeAttribute("name")}function xs(e,t,l,a,n,u,c,o){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?""+St(l):"",t=t!=null?""+St(t):l,o||t===e.value||(e.value=t),e.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=o?e.checked:!!a,e.defaultChecked=!!a,c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"&&(e.name=c),Ai(e)}function Oi(e,t,l){t==="number"&&Fn(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function aa(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"),Hi=!1;if(Qt)try{var Ja={};Object.defineProperty(Ja,"passive",{get:function(){Hi=!0}}),window.addEventListener("test",Ja,Ja),window.removeEventListener("test",Ja,Ja)}catch{Hi=!1}var fl=null,qi=null,Pn=null;function Os(){if(Pn)return Pn;var e,t=qi,l=t.length,a,n="value"in fl?fl.value:fl.textContent,u=n.length;for(e=0;e=Wa),qs=" ",Bs=!1;function Ls(e,t){switch(e){case"keyup":return Gh.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Ys(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var ca=!1;function Xh(e,t){switch(e){case"compositionend":return Ys(t);case"keypress":return t.which!==32?null:(Bs=!0,qs);case"textInput":return e=t.data,e===qs&&Bs?null:e;default:return null}}function Qh(e,t){if(ca)return e==="compositionend"||!wi&&Ls(e,t)?(e=Os(),Pn=qi=fl=null,ca=!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=Js(l)}}function ks(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?ks(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=Fn(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=Fn(e.document)}return t}function Zi(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 Fh=Qt&&"documentMode"in document&&11>=document.documentMode,fa=null,Vi=null,en=null,Ki=!1;function Fs(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Ki||fa==null||fa!==Fn(a)||(a=fa,"selectionStart"in a&&Zi(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}),en&&Pa(en,a)||(en=a,a=Ku(Vi,"onSelect"),0>=c,n-=c,qt=1<<32-rt(t)+n|l<ne?(oe=k,k=null):oe=k.sibling;var ye=R(E,k,N[ne],M);if(ye===null){k===null&&(k=oe);break}e&&k&&ye.alternate===null&&t(E,k),g=u(ye,g,ne),ve===null?F=ye:ve.sibling=ye,ve=ye,k=oe}if(ne===N.length)return l(E,k),me&&Vt(E,ne),F;if(k===null){for(;nene?(oe=k,k=null):oe=k.sibling;var Ol=R(E,k,ye.value,M);if(Ol===null){k===null&&(k=oe);break}e&&k&&Ol.alternate===null&&t(E,k),g=u(Ol,g,ne),ve===null?F=Ol:ve.sibling=Ol,ve=Ol,k=oe}if(ye.done)return l(E,k),me&&Vt(E,ne),F;if(k===null){for(;!ye.done;ne++,ye=N.next())ye=U(E,ye.value,M),ye!==null&&(g=u(ye,g,ne),ve===null?F=ye:ve.sibling=ye,ve=ye);return me&&Vt(E,ne),F}for(k=a(k);!ye.done;ne++,ye=N.next())ye=O(k,E,ne,ye.value,M),ye!==null&&(e&&ye.alternate!==null&&k.delete(ye.key===null?ne:ye.key),g=u(ye,g,ne),ve===null?F=ye:ve.sibling=ye,ve=ye);return e&&k.forEach(function(py){return t(E,py)}),me&&Vt(E,ne),F}function xe(E,g,N,M){if(typeof N=="object"&&N!==null&&N.type===Z&&N.key===null&&(N=N.props.children),typeof N=="object"&&N!==null){switch(N.$$typeof){case H:e:{for(var F=N.key;g!==null;){if(g.key===F){if(F=N.type,F===Z){if(g.tag===7){l(E,g.sibling),M=n(g,N.props.children),M.return=E,E=M;break e}}else if(g.elementType===F||typeof F=="object"&&F!==null&&F.$$typeof===ie&&Ql(F)===g.type){l(E,g.sibling),M=n(g,N.props),cn(M,N),M.return=E,E=M;break e}l(E,g);break}else t(E,g);g=g.sibling}N.type===Z?(M=Ll(N.props.children,E.mode,M,N.key),M.return=E,E=M):(M=su(N.type,N.key,N.props,null,E.mode,M),cn(M,N),M.return=E,E=M)}return c(E);case Q:e:{for(F=N.key;g!==null;){if(g.key===F)if(g.tag===4&&g.stateNode.containerInfo===N.containerInfo&&g.stateNode.implementation===N.implementation){l(E,g.sibling),M=n(g,N.children||[]),M.return=E,E=M;break e}else{l(E,g);break}else t(E,g);g=g.sibling}M=Pi(N,E.mode,M),M.return=E,E=M}return c(E);case ie:return N=Ql(N),xe(E,g,N,M)}if(je(N))return J(E,g,N,M);if(Oe(N)){if(F=Oe(N),typeof F!="function")throw Error(f(150));return N=F.call(N),I(E,g,N,M)}if(typeof N.then=="function")return xe(E,g,yu(N),M);if(N.$$typeof===X)return xe(E,g,du(E,N),M);pu(E,N)}return typeof N=="string"&&N!==""||typeof N=="number"||typeof N=="bigint"?(N=""+N,g!==null&&g.tag===6?(l(E,g.sibling),M=n(g,N),M.return=E,E=M):(l(E,g),M=Ii(N,E.mode,M),M.return=E,E=M),c(E)):l(E,g)}return function(E,g,N,M){try{un=0;var F=xe(E,g,N,M);return Sa=null,F}catch(k){if(k===ga||k===hu)throw k;var ve=dt(29,k,null,E.mode);return ve.lanes=M,ve.return=E,ve}}}var Vl=br(!0),_r=br(!1),ml=!1;function oc(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function dc(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 hl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function vl(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(pe&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=fu(e),nr(e,null,l),t}return cu(e,a,t,l),fu(e)}function fn(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,ds(e,l)}}function mc(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 hc=!1;function sn(){if(hc){var e=pa;if(e!==null)throw e}}function rn(e,t,l,a){hc=!1;var n=e.updateQueue;ml=!1;var u=n.firstBaseUpdate,c=n.lastBaseUpdate,o=n.shared.pending;if(o!==null){n.shared.pending=null;var v=o,j=v.next;v.next=null,c===null?u=j:c.next=j,c=v;var D=e.alternate;D!==null&&(D=D.updateQueue,o=D.lastBaseUpdate,o!==c&&(o===null?D.firstBaseUpdate=j:o.next=j,D.lastBaseUpdate=v))}if(u!==null){var U=n.baseState;c=0,D=j=v=null,o=u;do{var R=o.lane&-536870913,O=R!==o.lane;if(O?(re&R)===R:(a&R)===R){R!==0&&R===ya&&(hc=!0),D!==null&&(D=D.next={lane:0,tag:o.tag,payload:o.payload,callback:null,next:null});e:{var J=e,I=o;R=t;var xe=l;switch(I.tag){case 1:if(J=I.payload,typeof J=="function"){U=J.call(xe,U,R);break e}U=J;break e;case 3:J.flags=J.flags&-65537|128;case 0:if(J=I.payload,R=typeof J=="function"?J.call(xe,U,R):J,R==null)break e;U=T({},U,R);break e;case 2:ml=!0}}R=o.callback,R!==null&&(e.flags|=64,O&&(e.flags|=8192),O=n.callbacks,O===null?n.callbacks=[R]:O.push(R))}else O={lane:R,tag:o.tag,payload:o.payload,callback:o.callback,next:null},D===null?(j=D=O,v=U):D=D.next=O,c|=R;if(o=o.next,o===null){if(o=n.shared.pending,o===null)break;O=o,o=O.next,O.next=null,n.lastBaseUpdate=O,n.shared.pending=null}}while(!0);D===null&&(v=U),n.baseState=v,n.firstBaseUpdate=j,n.lastBaseUpdate=D,u===null&&(n.shared.lanes=0),bl|=c,e.lanes=c,e.memoizedState=U}}function Er(e,t){if(typeof e!="function")throw Error(f(191,e));e.call(t)}function xr(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;eu?u:8;var c=x.T,o={};x.T=o,Mc(e,!1,t,l);try{var v=n(),j=x.S;if(j!==null&&j(o,v),v!==null&&typeof v=="object"&&typeof v.then=="function"){var D=iv(v,a);mn(e,t,D,pt(e))}else mn(e,t,a,pt(e))}catch(U){mn(e,t,{then:function(){},status:"rejected",reason:U},pt())}finally{L.p=u,c!==null&&o.types!==null&&(c.types=o.types),x.T=c}}function dv(){}function Cc(e,t,l,a){if(e.tag!==5)throw Error(f(476));var n=to(e).queue;eo(e,n,t,$,l===null?dv:function(){return lo(e),l(a)})}function to(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:$,baseState:$,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:kt,lastRenderedState:$},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:kt,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function lo(e){var t=to(e);t.next===null&&(t=e.alternate.memoizedState),mn(e,t.next.queue,{},pt())}function Dc(){return Je(On)}function ao(){return He().memoizedState}function no(){return He().memoizedState}function mv(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=pt();e=hl(l);var a=vl(t,e,l);a!==null&&(ct(a,t,l),fn(a,t,l)),t={cache:cc()},e.payload=t;return}t=t.return}}function hv(e,t,l){var a=pt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},Ru(e)?io(t,l):(l=Wi(e,t,l,a),l!==null&&(ct(l,e,a),co(l,t,a)))}function uo(e,t,l){var a=pt();mn(e,t,l,a)}function mn(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(Ru(e))io(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,o=u(c,l);if(n.hasEagerState=!0,n.eagerState=o,ot(o,c))return cu(e,t,n,0),Ne===null&&iu(),!1}catch{}if(l=Wi(e,t,n,a),l!==null)return ct(l,e,a),co(l,t,a),!0}return!1}function Mc(e,t,l,a){if(a={lane:2,revertLane:df(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},Ru(e)){if(t)throw Error(f(479))}else t=Wi(e,l,a,2),t!==null&&ct(t,e,2)}function Ru(e){var t=e.alternate;return e===le||t!==null&&t===le}function io(e,t){_a=bu=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function co(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,ds(e,l)}}var hn={readContext:Je,use:xu,useCallback:Ce,useContext:Ce,useEffect:Ce,useImperativeHandle:Ce,useLayoutEffect:Ce,useInsertionEffect:Ce,useMemo:Ce,useReducer:Ce,useRef:Ce,useState:Ce,useDebugValue:Ce,useDeferredValue:Ce,useTransition:Ce,useSyncExternalStore:Ce,useId:Ce,useHostTransitionStatus:Ce,useFormState:Ce,useActionState:Ce,useOptimistic:Ce,useMemoCache:Ce,useCacheRefresh:Ce};hn.useEffectEvent=Ce;var fo={readContext:Je,use:xu,useCallback:function(e,t){return et().memoizedState=[e,t===void 0?null:t],e},useContext:Je,useEffect:Vr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,ju(4194308,4,kr.bind(null,t,e),l)},useLayoutEffect:function(e,t){return ju(4194308,4,e,t)},useInsertionEffect:function(e,t){ju(4,2,e,t)},useMemo:function(e,t){var l=et();t=t===void 0?null:t;var a=e();if(Kl){il(!0);try{e()}finally{il(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=et();if(l!==void 0){var n=l(t);if(Kl){il(!0);try{l(t)}finally{il(!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=hv.bind(null,le,e),[a.memoizedState,e]},useRef:function(e){var t=et();return e={current:e},t.memoizedState=e},useState:function(e){e=Tc(e);var t=e.queue,l=uo.bind(null,le,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:zc,useDeferredValue:function(e,t){var l=et();return Oc(l,e,t)},useTransition:function(){var e=Tc(!1);return e=eo.bind(null,le,e.queue,!0,!1),et().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=le,n=et();if(me){if(l===void 0)throw Error(f(407));l=l()}else{if(l=t(),Ne===null)throw Error(f(349));(re&127)!==0||zr(a,t,l)}n.memoizedState=l;var u={value:l,getSnapshot:t};return n.queue=u,Vr(Cr.bind(null,a,u,e),[e]),a.flags|=2048,xa(9,{destroy:void 0},Or.bind(null,a,u,l,t),null),l},useId:function(){var e=et(),t=Ne.identifierPrefix;if(me){var l=Bt,a=qt;l=(a&~(1<<32-rt(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=_u++,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[Ve]=t,u[tt]=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(ke(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&&Ft(t)}}return Re(t),Jc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&Ft(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(f(166));if(e=ce.current,ha(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=Ke,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[Ve]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||Ad(e.nodeValue,l)),e||ol(t,!0)}else e=Ju(e).createTextNode(a),e[Ve]=t,t.stateNode=e}return Re(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=ha(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[Ve]=t}else Yl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Re(t),e=!1}else l=ac(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(ht(t),t):(ht(t),null);if((t.flags&128)!==0)throw Error(f(558))}return Re(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(n=ha(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[Ve]=t}else Yl(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Re(t),n=!1}else n=ac(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(ht(t),t):(ht(t),null)}return ht(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),Du(t,t.updateQueue),Re(t),null);case 4:return Me(),e===null&&yf(t.stateNode.containerInfo),Re(t),null;case 10:return Jt(t.type),Re(t),null;case 19:if(A(Ue),a=t.memoizedState,a===null)return Re(t),null;if(n=(t.flags&128)!==0,u=a.rendering,u===null)if(n)yn(a,!1);else{if(De!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=Su(e),u!==null){for(t.flags|=128,yn(a,!1),e=u.updateQueue,t.updateQueue=e,Du(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)ur(l,e),l=l.sibling;return B(Ue,Ue.current&1|2),me&&Vt(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&ft()>Bu&&(t.flags|=128,n=!0,yn(a,!1),t.lanes=4194304)}else{if(!n)if(e=Su(u),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,Du(t,e),yn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!u.alternate&&!me)return Re(t),null}else 2*ft()-a.renderingStartTime>Bu&&l!==536870912&&(t.flags|=128,n=!0,yn(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=ft(),e.sibling=null,l=Ue.current,B(Ue,n?l&1|2:l&1),me&&Vt(t,a.treeForkCount),e):(Re(t),null);case 22:case 23:return ht(t),yc(),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&&(Re(t),t.subtreeFlags&6&&(t.flags|=8192)):Re(t),l=t.updateQueue,l!==null&&Du(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&&A(Xl),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),Jt(Be),Re(t),null;case 25:return null;case 30:return null}throw Error(f(156,t.tag))}function Sv(e,t){switch(tc(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Jt(Be),Me(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Qn(t),null;case 31:if(t.memoizedState!==null){if(ht(t),t.alternate===null)throw Error(f(340));Yl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(ht(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(f(340));Yl()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return A(Ue),null;case 4:return Me(),null;case 10:return Jt(t.type),null;case 22:case 23:return ht(t),yc(),e!==null&&A(Xl),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Jt(Be),null;case 25:return null;default:return null}}function Mo(e,t){switch(tc(t),t.tag){case 3:Jt(Be),Me();break;case 26:case 27:case 5:Qn(t);break;case 4:Me();break;case 31:t.memoizedState!==null&&ht(t);break;case 13:ht(t);break;case 19:A(Ue);break;case 10:Jt(t.type);break;case 22:case 23:ht(t),yc(),e!==null&&A(Xl);break;case 24:Jt(Be)}}function pn(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(o){be(t,t.return,o)}}function gl(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,o=c.destroy;if(o!==void 0){c.destroy=void 0,n=t;var v=l,j=o;try{j()}catch(D){be(n,v,D)}}}a=a.next}while(a!==u)}}catch(D){be(t,t.return,D)}}function Uo(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{xr(t,l)}catch(a){be(e,e.return,a)}}}function Ho(e,t,l){l.props=Jl(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){be(e,t,a)}}function gn(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){be(e,t,n)}}function Lt(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){be(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){be(e,t,n)}else l.current=null}function qo(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){be(e,e.return,n)}}function $c(e,t,l){try{var a=e.stateNode;wv(a,e.type,l,t),a[tt]=t}catch(n){be(e,e.return,n)}}function Bo(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&jl(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&&jl(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 Wc(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&&jl(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(Wc(e,t,l),e=e.sibling;e!==null;)Wc(e,t,l),e=e.sibling}function Mu(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&&jl(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Mu(e,t,l),e=e.sibling;e!==null;)Mu(e,t,l),e=e.sibling}function Lo(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);ke(t,a,l),t[Ve]=e,t[tt]=l}catch(u){be(e,e.return,u)}}var It=!1,Ge=!1,Fc=!1,Yo=typeof WeakSet=="function"?WeakSet:Set,Ze=null;function bv(e,t){if(e=e.containerInfo,Sf=ei,e=Ws(e),Zi(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,o=-1,v=-1,j=0,D=0,U=e,R=null;t:for(;;){for(var O;U!==l||n!==0&&U.nodeType!==3||(o=c+n),U!==u||a!==0&&U.nodeType!==3||(v=c+a),U.nodeType===3&&(c+=U.nodeValue.length),(O=U.firstChild)!==null;)R=U,U=O;for(;;){if(U===e)break t;if(R===l&&++j===n&&(o=c),R===u&&++D===a&&(v=c),(O=U.nextSibling)!==null)break;U=R,R=U.parentNode}U=O}l=o===-1||v===-1?null:{start:o,end:v}}else l=null}l=l||{start:0,end:0}}else l=null;for(bf={focusedElem:e,selectionRange:l},ei=!1,Ze=t;Ze!==null;)if(t=Ze,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,Ze=e;else for(;Ze!==null;){switch(t=Ze,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"))),ke(u,a,l),u[Ve]=e,Qe(u),a=u;break e;case"link":var c=Vd("link","href",n).get(a+(l.href||""));if(c){for(var o=0;oxe&&(c=xe,xe=I,I=c);var E=$s(o,I),g=$s(o,xe);if(E&&g&&(O.rangeCount!==1||O.anchorNode!==E.node||O.anchorOffset!==E.offset||O.focusNode!==g.node||O.focusOffset!==g.offset)){var N=U.createRange();N.setStart(E.node,E.offset),O.removeAllRanges(),I>xe?(O.addRange(N),O.extend(g.node,g.offset)):(N.setEnd(g.node,g.offset),O.addRange(N))}}}}for(U=[],O=o;O=O.parentNode;)O.nodeType===1&&U.push({element:O,left:O.scrollLeft,top:O.scrollTop});for(typeof o.focus=="function"&&o.focus(),o=0;ol?32:l,x.T=null,l=nf,nf=null;var u=El,c=al;if(we=0,Aa=El=null,al=0,(pe&6)!==0)throw Error(f(331));var o=pe;if(pe|=4,Wo(u.current),Jo(u,u.current,c,l),pe=o,Nn(0,!1),st&&typeof st.onPostCommitFiberRoot=="function")try{st.onPostCommitFiberRoot(wa,u)}catch{}return!0}finally{L.p=n,x.T=a,hd(e,t)}}function yd(e,t,l){t=Et(l,t),t=Bc(e.stateNode,t,2),e=vl(e,t,2),e!==null&&(Qa(e,2),Yt(e))}function be(e,t,l){if(e.tag===3)yd(e,e,l);else for(;t!==null;){if(t.tag===3){yd(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(_l===null||!_l.has(a))){e=Et(l,e),l=po(2),a=vl(t,l,2),a!==null&&(go(l,a,t,e),Qa(a,2),Yt(a));break}}t=t.return}}function sf(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new xv;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)||(ef=!0,n.add(l),e=Av.bind(null,e,t,l),t.then(e,e))}function Av(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Ne===e&&(re&l)===l&&(De===4||De===3&&(re&62914560)===re&&300>ft()-qu?(pe&2)===0&&za(e,0):tf|=l,Ra===re&&(Ra=0)),Yt(e)}function pd(e,t){t===0&&(t=rs()),e=Bl(e,t),e!==null&&(Qa(e,t),Yt(e))}function zv(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),pd(e,l)}function Ov(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),pd(e,l)}function Cv(e,t){return _i(e,t)}var Qu=null,Ca=null,rf=!1,Zu=!1,of=!1,Nl=0;function Yt(e){e!==Ca&&e.next===null&&(Ca===null?Qu=Ca=e:Ca=Ca.next=e),Zu=!0,rf||(rf=!0,Mv())}function Nn(e,t){if(!of&&Zu){of=!0;do for(var l=!1,a=Qu;a!==null;){if(e!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var c=a.suspendedLanes,o=a.pingedLanes;u=(1<<31-rt(42|e)+1)-1,u&=n&~(c&~o),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,_d(a,u))}else u=re,u=$n(a,a===Ne?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||Xa(a,u)||(l=!0,_d(a,u));a=a.next}while(l);of=!1}}function Dv(){gd()}function gd(){Zu=rf=!1;var e=0;Nl!==0&&Qv()&&(e=Nl);for(var t=ft(),l=null,a=Qu;a!==null;){var n=a.next,u=Sd(a,t);u===0?(a.next=null,l===null?Qu=n:l.next=n,n===null&&(Ca=l)):(l=a,(e!==0||(u&3)!==0)&&(Zu=!0)),a=n}we!==0&&we!==5||Nn(e),Nl!==0&&(Nl=0)}function Sd(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,n=e.expirationTimes,u=e.pendingLanes&-62914561;0o)break;var D=v.transferSize,U=v.initiatorType;D&&zd(U)&&(v=v.responseEnd,c+=D*(v"u"?null:document;function wd(e,t,l){var a=Da;if(a&&typeof t=="string"&&t){var n=bt(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),Gd.has(n)||(Gd.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),ke(t,"link",e),Qe(t),a.head.appendChild(t)))}}function Iv(e){nl.D(e),wd("dns-prefetch",e,null)}function Pv(e,t){nl.C(e,t),wd("preconnect",e,t)}function ey(e,t,l){nl.L(e,t,l);var a=Da;if(a&&e&&t){var n='link[rel="preload"][as="'+bt(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+bt(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+bt(l.imageSizes)+'"]')):n+='[href="'+bt(e)+'"]';var u=n;switch(t){case"style":u=Ma(e);break;case"script":u=Ua(e)}At.has(u)||(e=T({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),At.set(u,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(An(u))||t==="script"&&a.querySelector(zn(u))||(t=a.createElement("link"),ke(t,"link",e),Qe(t),a.head.appendChild(t)))}}function ty(e,t){nl.m(e,t);var l=Da;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+bt(a)+'"][href="'+bt(e)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ua(e)}if(!At.has(u)&&(e=T({rel:"modulepreload",href:e},t),At.set(u,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(zn(u)))return}a=l.createElement("link"),ke(a,"link",e),Qe(a),l.head.appendChild(a)}}}function ly(e,t,l){nl.S(e,t,l);var a=Da;if(a&&e){var n=ta(a).hoistableStyles,u=Ma(e);t=t||"default";var c=n.get(u);if(!c){var o={loading:0,preload:null};if(c=a.querySelector(An(u)))o.loading=5;else{e=T({rel:"stylesheet",href:e,"data-precedence":t},l),(l=At.get(u))&&Rf(e,l);var v=c=a.createElement("link");Qe(v),ke(v,"link",e),v._p=new Promise(function(j,D){v.onload=j,v.onerror=D}),v.addEventListener("load",function(){o.loading|=1}),v.addEventListener("error",function(){o.loading|=2}),o.loading|=4,ku(c,t,a)}c={type:"stylesheet",instance:c,count:1,state:o},n.set(u,c)}}}function ay(e,t){nl.X(e,t);var l=Da;if(l&&e){var a=ta(l).hoistableScripts,n=Ua(e),u=a.get(n);u||(u=l.querySelector(zn(n)),u||(e=T({src:e,async:!0},t),(t=At.get(n))&&Af(e,t),u=l.createElement("script"),Qe(u),ke(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function ny(e,t){nl.M(e,t);var l=Da;if(l&&e){var a=ta(l).hoistableScripts,n=Ua(e),u=a.get(n);u||(u=l.querySelector(zn(n)),u||(e=T({src:e,async:!0,type:"module"},t),(t=At.get(n))&&Af(e,t),u=l.createElement("script"),Qe(u),ke(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=ce.current)?$u(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=ta(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=ta(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(An(e)))&&!u._p&&(c.instance=u,c.state.loading=5),At.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},At.set(e,l),u||uy(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=Ua(l),l=ta(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="'+bt(e)+'"'}function An(e){return'link[rel="stylesheet"]['+e+"]"}function Qd(e){return T({},e,{"data-precedence":e.precedence,precedence:null})}function uy(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}),ke(t,"link",l),Qe(t),e.head.appendChild(t))}function Ua(e){return'[src="'+bt(e)+'"]'}function zn(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~="'+bt(l.href)+'"]');if(a)return t.instance=a,Qe(a),a;var n=T({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),Qe(a),ke(a,"style",n),ku(a,l.precedence,e),t.instance=a;case"stylesheet":n=Ma(l.href);var u=e.querySelector(An(n));if(u)return t.state.loading|=4,t.instance=u,Qe(u),u;a=Qd(l),(n=At.get(n))&&Rf(a,n),u=(e.ownerDocument||e).createElement("link"),Qe(u);var c=u;return c._p=new Promise(function(o,v){c.onload=o,c.onerror=v}),ke(u,"link",a),t.state.loading|=4,ku(u,l.precedence,e),t.instance=u;case"script":return u=Ua(l.src),(n=e.querySelector(zn(u)))?(t.instance=n,Qe(n),n):(a=l,(n=At.get(u))&&(a=T({},l),Af(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),Qe(n),ke(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,ku(a,l.precedence,e));return t.instance}function ku(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 iy(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 Jd(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function cy(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(An(n));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=Fu.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=u,Qe(u);return}u=t.ownerDocument||t,a=Qd(a),(n=At.get(n))&&Rf(a,n),u=u.createElement("link"),Qe(u);var c=u;c._p=new Promise(function(o,v){c.onload=o,c.onerror=v}),ke(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=Fu.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var zf=0;function fy(e,t){return e.stylesheets&&e.count===0&&Pu(e,e.stylesheets),0zf?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function Fu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Pu(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Iu=null;function Pu(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Iu=new Map,t.forEach(sy,e),Iu=null,Fu.call(e))}function sy(e,t){if(!(t.state.loading&4)){var l=Iu.get(e);if(l)var a=l.get(null);else{l=new Map,Iu.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(),Lf.exports=jy(),Lf.exports}var Ry=Ty();var pm="popstate";function gm(i){return typeof i=="object"&&i!=null&&"pathname"in i&&"search"in i&&"hash"in i&&"state"in i&&"key"in i}function Ay(i={}){function s(m,h){let{pathname:b="/",search:z="",hash:S=""}=Fl(m.location.hash.substring(1));return!b.startsWith("/")&&!b.startsWith(".")&&(b="/"+b),Jf("",{pathname:b,search:z,hash:S},h.state&&h.state.usr||null,h.state&&h.state.key||"default")}function d(m,h){let b=m.document.querySelector("base"),z="";if(b&&b.getAttribute("href")){let S=m.location.href,y=S.indexOf("#");z=y===-1?S:S.slice(0,y)}return z+"#"+(typeof h=="string"?h:Yn(h))}function f(m,h){Ot(m.pathname.charAt(0)==="/",`relative pathnames are not supported in hash history.push(${JSON.stringify(h)})`)}return Oy(s,d,f,i)}function ze(i,s){if(i===!1||i===null||typeof i>"u")throw new Error(s)}function Ot(i,s){if(!i){typeof console<"u"&&console.warn(s);try{throw new Error(s)}catch{}}}function zy(){return Math.random().toString(36).substring(2,10)}function Sm(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 Jf(i,s,d=null,f,m){return{pathname:typeof i=="string"?i:i.pathname,search:"",hash:"",...typeof s=="string"?Fl(s):s,state:d,key:s&&s.key||f||zy(),unstable_mask:m}}function Yn({pathname:i="/",search:s="",hash:d=""}){return s&&s!=="?"&&(i+=s.charAt(0)==="?"?s:"?"+s),d&&d!=="#"&&(i+=d.charAt(0)==="#"?d:"#"+d),i}function Fl(i){let s={};if(i){let d=i.indexOf("#");d>=0&&(s.hash=i.substring(d),i=i.substring(0,d));let f=i.indexOf("?");f>=0&&(s.search=i.substring(f),i=i.substring(0,f)),i&&(s.pathname=i)}return s}function Oy(i,s,d,f={}){let{window:m=document.defaultView,v5Compat:h=!1}=f,b=m.history,z="POP",S=null,y=C();y==null&&(y=0,b.replaceState({...b.state,idx:y},""));function C(){return(b.state||{idx:null}).idx}function T(){z="POP";let q=C(),V=q==null?null:q-y;y=q,S&&S({action:z,location:Z.location,delta:V})}function Y(q,V){z="PUSH";let W=gm(q)?q:Jf(Z.location,q,V);d&&d(W,q),y=C()+1;let X=Sm(W,y),w=Z.createHref(W.unstable_mask||W);try{b.pushState(X,"",w)}catch(ae){if(ae instanceof DOMException&&ae.name==="DataCloneError")throw ae;m.location.assign(w)}h&&S&&S({action:z,location:Z.location,delta:1})}function H(q,V){z="REPLACE";let W=gm(q)?q:Jf(Z.location,q,V);d&&d(W,q),y=C();let X=Sm(W,y),w=Z.createHref(W.unstable_mask||W);b.replaceState(X,"",w),h&&S&&S({action:z,location:Z.location,delta:0})}function Q(q){return Cy(q)}let Z={get action(){return z},get location(){return i(m,b)},listen(q){if(S)throw new Error("A history only accepts one active listener");return m.addEventListener(pm,T),S=q,()=>{m.removeEventListener(pm,T),S=null}},createHref(q){return s(m,q)},createURL:Q,encodeLocation(q){let V=Q(q);return{pathname:V.pathname,search:V.search,hash:V.hash}},push:Y,replace:H,go(q){return b.go(q)}};return Z}function Cy(i,s=!1){let d="http://localhost";typeof window<"u"&&(d=window.location.origin!=="null"?window.location.origin:window.location.href),ze(d,"No window.location.(origin|href) available to create URL");let f=typeof i=="string"?i:Yn(i);return f=f.replace(/ $/,"%20"),!s&&f.startsWith("//")&&(f=d+f),new URL(f,d)}function jm(i,s,d="/"){return Dy(i,s,d,!1)}function Dy(i,s,d,f){let m=typeof s=="string"?Fl(s):s,h=ul(m.pathname||"/",d);if(h==null)return null;let b=Tm(i);My(b);let z=null;for(let S=0;z==null&&S{let C={relativePath:y===void 0?b.path||"":y,caseSensitive:b.caseSensitive===!0,childrenIndex:z,route:b};if(C.relativePath.startsWith("/")){if(!C.relativePath.startsWith(f)&&S)return;ze(C.relativePath.startsWith(f),`Absolute route path "${C.relativePath}" nested under path "${f}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),C.relativePath=C.relativePath.slice(f.length)}let T=Ut([f,C.relativePath]),Y=d.concat(C);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 "${T}".`),Tm(b.children,s,Y,T,S)),!(b.path==null&&!b.index)&&s.push({path:T,score:Gy(T,b.index),routesMeta:Y})};return i.forEach((b,z)=>{if(b.path===""||!b.path?.includes("?"))h(b,z);else for(let S of Rm(b.path))h(b,z,!0,S)}),s}function Rm(i){let s=i.split("/");if(s.length===0)return[];let[d,...f]=s,m=d.endsWith("?"),h=d.replace(/\?$/,"");if(f.length===0)return m?[h,""]:[h];let b=Rm(f.join("/")),z=[];return z.push(...b.map(S=>S===""?h:[h,S].join("/"))),m&&z.push(...b),z.map(S=>i.startsWith("/")&&S===""?"/":S)}function My(i){i.sort((s,d)=>s.score!==d.score?d.score-s.score:wy(s.routesMeta.map(f=>f.childrenIndex),d.routesMeta.map(f=>f.childrenIndex)))}var Uy=/^:[\w-]+$/,Hy=3,qy=2,By=1,Ly=10,Yy=-2,bm=i=>i==="*";function Gy(i,s){let d=i.split("/"),f=d.length;return d.some(bm)&&(f+=Yy),s&&(f+=qy),d.filter(m=>!bm(m)).reduce((m,h)=>m+(Uy.test(h)?Hy:h===""?By:Ly),f)}function wy(i,s){return i.length===s.length&&i.slice(0,-1).every((f,m)=>f===s[m])?i[i.length-1]-s[s.length-1]:0}function Xy(i,s,d=!1){let{routesMeta:f}=i,m={},h="/",b=[];for(let z=0;z{if(C==="*"){let Q=z[Y]||"";b=h.slice(0,h.length-Q.length).replace(/(.)\/+$/,"$1")}const H=z[Y];return T&&!H?y[C]=void 0:y[C]=(H||"").replace(/%2F/g,"/"),y},{}),pathname:h,pathnameBase:b,pattern:i}}function Qy(i,s=!1,d=!0){Ot(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=[],m="^"+i.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(b,z,S,y,C)=>{if(f.push({paramName:z,isOptional:S!=null}),S){let T=C.charAt(y+b.length);return T&&T!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return i.endsWith("*")?(f.push({paramName:"*"}),m+=i==="*"||i==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):d?m+="\\/*$":i!==""&&i!=="/"&&(m+="(?:(?=\\/|$))"),[new RegExp(m,s?void 0:"i"),f]}function Zy(i){try{return i.split("/").map(s=>decodeURIComponent(s).replace(/\//g,"%2F")).join("/")}catch(s){return Ot(!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 ul(i,s){if(s==="/")return i;if(!i.toLowerCase().startsWith(s.toLowerCase()))return null;let d=s.endsWith("/")?s.length-1:s.length,f=i.charAt(d);return f&&f!=="/"?null:i.slice(d)||"/"}var Vy=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function Ky(i,s="/"){let{pathname:d,search:f="",hash:m=""}=typeof i=="string"?Fl(i):i,h;return d?(d=Am(d),d.startsWith("/")?h=_m(d.substring(1),"/"):h=_m(d,s)):h=s,{pathname:h,search:ky(f),hash:Wy(m)}}function _m(i,s){let d=mi(s).split("/");return i.split("/").forEach(m=>{m===".."?d.length>1&&d.pop():m!=="."&&d.push(m)}),d.length>1?d.join("/"):"/"}function Xf(i,s,d,f){return`Cannot include a '${i}' character in a manually specified \`to.${s}\` field [${JSON.stringify(f)}]. Please separate it out to the \`to.${d}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function Jy(i){return i.filter((s,d)=>d===0||s.route.path&&s.route.path.length>0)}function Ff(i){let s=Jy(i);return s.map((d,f)=>f===s.length-1?d.pathname:d.pathnameBase)}function hi(i,s,d,f=!1){let m;typeof i=="string"?m=Fl(i):(m={...i},ze(!m.pathname||!m.pathname.includes("?"),Xf("?","pathname","search",m)),ze(!m.pathname||!m.pathname.includes("#"),Xf("#","pathname","hash",m)),ze(!m.search||!m.search.includes("#"),Xf("#","search","hash",m)));let h=i===""||m.pathname==="",b=h?"/":m.pathname,z;if(b==null)z=d;else{let T=s.length-1;if(!f&&b.startsWith("..")){let Y=b.split("/");for(;Y[0]==="..";)Y.shift(),T-=1;m.pathname=Y.join("/")}z=T>=0?s[T]:"/"}let S=Ky(m,z),y=b&&b!=="/"&&b.endsWith("/"),C=(h||b===".")&&d.endsWith("/");return!S.pathname.endsWith("/")&&(y||C)&&(S.pathname+="/"),S}var Am=i=>i.replace(/\/\/+/g,"/"),Ut=i=>Am(i.join("/")),mi=i=>i.replace(/\/+$/,""),$y=i=>mi(i).replace(/^\/*/,"/"),ky=i=>!i||i==="?"?"":i.startsWith("?")?i:"?"+i,Wy=i=>!i||i==="#"?"":i.startsWith("#")?i:"#"+i,Fy=class{constructor(i,s,d,f=!1){this.status=i,this.statusText=s||"",this.internal=f,d instanceof Error?(this.data=d.toString(),this.error=d):this.data=d}};function Iy(i){return i!=null&&typeof i.status=="number"&&typeof i.statusText=="string"&&typeof i.internal=="boolean"&&"data"in i}function Py(i){let s=i.map(d=>d.route.path).filter(Boolean);return Ut(s)||"/"}var zm=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function Om(i,s){let d=i;if(typeof d!="string"||!Vy.test(d))return{absoluteURL:void 0,isExternal:!1,to:d};let f=d,m=!1;if(zm)try{let h=new URL(window.location.href),b=d.startsWith("//")?new URL(h.protocol+d):new URL(d),z=ul(b.pathname,s);b.origin===h.origin&&z!=null?d=z+b.search+b.hash:m=!0}catch{Ot(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:f,isExternal:m,to:d}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Cm=["POST","PUT","PATCH","DELETE"];new Set(Cm);var e0=["GET",...Cm];new Set(e0);var La=_.createContext(null);La.displayName="DataRouter";var vi=_.createContext(null);vi.displayName="DataRouterState";var Dm=_.createContext(!1);function t0(){return _.useContext(Dm)}var Mm=_.createContext({isTransitioning:!1});Mm.displayName="ViewTransition";var l0=_.createContext(new Map);l0.displayName="Fetchers";var a0=_.createContext(null);a0.displayName="Await";var gt=_.createContext(null);gt.displayName="Navigation";var wn=_.createContext(null);wn.displayName="Location";var Ht=_.createContext({outlet:null,matches:[],isDataRoute:!1});Ht.displayName="Route";var If=_.createContext(null);If.displayName="RouteError";var Um="REACT_ROUTER_ERROR",n0="REDIRECT",u0="ROUTE_ERROR_RESPONSE";function i0(i){if(i.startsWith(`${Um}:${n0}:{`))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 c0(i){if(i.startsWith(`${Um}:${u0}:{`))try{let s=JSON.parse(i.slice(40));if(typeof s=="object"&&s&&typeof s.status=="number"&&typeof s.statusText=="string")return new Fy(s.status,s.statusText,s.data)}catch{}}function f0(i,{relative:s}={}){ze(Ya(),"useHref() may be used only in the context of a component.");let{basename:d,navigator:f}=_.useContext(gt),{hash:m,pathname:h,search:b}=Xn(i,{relative:s}),z=h;return d!=="/"&&(z=h==="/"?d:Ut([d,h])),f.createHref({pathname:z,search:b,hash:m})}function Ya(){return _.useContext(wn)!=null}function Gt(){return ze(Ya(),"useLocation() may be used only in the context of a component."),_.useContext(wn).location}var Hm="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function qm(i){_.useContext(gt).static||_.useLayoutEffect(i)}function Bm(){let{isDataRoute:i}=_.useContext(Ht);return i?x0():s0()}function s0(){ze(Ya(),"useNavigate() may be used only in the context of a component.");let i=_.useContext(La),{basename:s,navigator:d}=_.useContext(gt),{matches:f}=_.useContext(Ht),{pathname:m}=Gt(),h=JSON.stringify(Ff(f)),b=_.useRef(!1);return qm(()=>{b.current=!0}),_.useCallback((S,y={})=>{if(Ot(b.current,Hm),!b.current)return;if(typeof S=="number"){d.go(S);return}let C=hi(S,JSON.parse(h),m,y.relative==="path");i==null&&s!=="/"&&(C.pathname=C.pathname==="/"?s:Ut([s,C.pathname])),(y.replace?d.replace:d.push)(C,y.state,y)},[s,d,h,m,i])}var r0=_.createContext(null);function o0(i){let s=_.useContext(Ht).outlet;return _.useMemo(()=>s&&_.createElement(r0.Provider,{value:i},s),[s,i])}function Xn(i,{relative:s}={}){let{matches:d}=_.useContext(Ht),{pathname:f}=Gt(),m=JSON.stringify(Ff(d));return _.useMemo(()=>hi(i,JSON.parse(m),f,s==="path"),[i,m,f,s])}function d0(i,s){return Lm(i,s)}function Lm(i,s,d){ze(Ya(),"useRoutes() may be used only in the context of a component.");let{navigator:f}=_.useContext(gt),{matches:m}=_.useContext(Ht),h=m[m.length-1],b=h?h.params:{},z=h?h.pathname:"/",S=h?h.pathnameBase:"/",y=h&&h.route;{let q=y&&y.path||"";Gm(z,!y||q.endsWith("*")||q.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${z}" (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 C=Gt(),T;if(s){let q=typeof s=="string"?Fl(s):s;ze(S==="/"||q.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 "${q.pathname}" was given in the \`location\` prop.`),T=q}else T=C;let Y=T.pathname||"/",H=Y;if(S!=="/"){let q=S.replace(/^\//,"").split("/");H="/"+Y.replace(/^\//,"").split("/").slice(q.length).join("/")}let Q=jm(i,{pathname:H});Ot(y||Q!=null,`No routes matched location "${T.pathname}${T.search}${T.hash}" `),Ot(Q==null||Q[Q.length-1].route.element!==void 0||Q[Q.length-1].route.Component!==void 0||Q[Q.length-1].route.lazy!==void 0,`Matched leaf route at location "${T.pathname}${T.search}${T.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 Z=p0(Q&&Q.map(q=>Object.assign({},q,{params:Object.assign({},b,q.params),pathname:Ut([S,f.encodeLocation?f.encodeLocation(q.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:q.pathname]),pathnameBase:q.pathnameBase==="/"?S:Ut([S,f.encodeLocation?f.encodeLocation(q.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:q.pathnameBase])})),m,d);return s&&Z?_.createElement(wn.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",unstable_mask:void 0,...T},navigationType:"POP"}},Z):Z}function m0(){let i=E0(),s=Iy(i)?`${i.status} ${i.statusText}`:i instanceof Error?i.message:JSON.stringify(i),d=i instanceof Error?i.stack:null,f="rgba(200,200,200, 0.5)",m={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=_.createElement(_.Fragment,null,_.createElement("p",null,"💿 Hey developer 👋"),_.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",_.createElement("code",{style:h},"ErrorBoundary")," or"," ",_.createElement("code",{style:h},"errorElement")," prop on your route.")),_.createElement(_.Fragment,null,_.createElement("h2",null,"Unexpected Application Error!"),_.createElement("h3",{style:{fontStyle:"italic"}},s),d?_.createElement("pre",{style:m},d):null,b)}var h0=_.createElement(m0,null),Ym=class extends _.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 d=c0(i.digest);d&&(i=d)}let s=i!==void 0?_.createElement(Ht.Provider,{value:this.props.routeContext},_.createElement(If.Provider,{value:i,children:this.props.component})):this.props.children;return this.context?_.createElement(v0,{error:i},s):s}};Ym.contextType=Dm;var Qf=new WeakMap;function v0({children:i,error:s}){let{basename:d}=_.useContext(gt);if(typeof s=="object"&&s&&"digest"in s&&typeof s.digest=="string"){let f=i0(s.digest);if(f){let m=Qf.get(s);if(m)throw m;let h=Om(f.location,d);if(zm&&!Qf.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 Qf.set(s,b),b}return _.createElement("meta",{httpEquiv:"refresh",content:`0;url=${h.absoluteURL||h.to}`})}}return i}function y0({routeContext:i,match:s,children:d}){let f=_.useContext(La);return f&&f.static&&f.staticContext&&(s.route.errorElement||s.route.ErrorBoundary)&&(f.staticContext._deepestRenderedBoundaryId=s.route.id),_.createElement(Ht.Provider,{value:i},d)}function p0(i,s=[],d){let f=d?.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 m=i,h=f?.errors;if(h!=null){let C=m.findIndex(T=>T.route.id&&h?.[T.route.id]!==void 0);ze(C>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(h).join(",")}`),m=m.slice(0,Math.min(m.length,C+1))}let b=!1,z=-1;if(d&&f){b=f.renderFallback;for(let C=0;C=0?m=m.slice(0,z+1):m=[m[0]];break}}}}let S=d?.onError,y=f&&S?(C,T)=>{S(C,{location:f.location,params:f.matches?.[0]?.params??{},unstable_pattern:Py(f.matches),errorInfo:T})}:void 0;return m.reduceRight((C,T,Y)=>{let H,Q=!1,Z=null,q=null;f&&(H=h&&T.route.id?h[T.route.id]:void 0,Z=T.route.errorElement||h0,b&&(z<0&&Y===0?(Gm("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),Q=!0,q=null):z===Y&&(Q=!0,q=T.route.hydrateFallbackElement||null)));let V=s.concat(m.slice(0,Y+1)),W=()=>{let X;return H?X=Z:Q?X=q:T.route.Component?X=_.createElement(T.route.Component,null):T.route.element?X=T.route.element:X=C,_.createElement(y0,{match:T,routeContext:{outlet:C,matches:V,isDataRoute:f!=null},children:X})};return f&&(T.route.ErrorBoundary||T.route.errorElement||Y===0)?_.createElement(Ym,{location:f.location,revalidation:f.revalidation,component:Z,error:H,children:W(),routeContext:{outlet:null,matches:V,isDataRoute:!0},onError:y}):W()},null)}function Pf(i){return`${i} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function g0(i){let s=_.useContext(La);return ze(s,Pf(i)),s}function S0(i){let s=_.useContext(vi);return ze(s,Pf(i)),s}function b0(i){let s=_.useContext(Ht);return ze(s,Pf(i)),s}function es(i){let s=b0(i),d=s.matches[s.matches.length-1];return ze(d.route.id,`${i} can only be used on routes that contain a unique "id"`),d.route.id}function _0(){return es("useRouteId")}function E0(){let i=_.useContext(If),s=S0("useRouteError"),d=es("useRouteError");return i!==void 0?i:s.errors?.[d]}function x0(){let{router:i}=g0("useNavigate"),s=es("useNavigate"),d=_.useRef(!1);return qm(()=>{d.current=!0}),_.useCallback(async(m,h={})=>{Ot(d.current,Hm),d.current&&(typeof m=="number"?await i.navigate(m):await i.navigate(m,{fromRouteId:s,...h}))},[i,s])}var Em={};function Gm(i,s,d){!s&&!Em[i]&&(Em[i]=!0,Ot(!1,d))}_.memo(N0);function N0({routes:i,future:s,state:d,isStatic:f,onError:m}){return Lm(i,void 0,{state:d,isStatic:f,onError:m})}function j0({to:i,replace:s,state:d,relative:f}){ze(Ya()," may be used only in the context of a component.");let{static:m}=_.useContext(gt);Ot(!m," 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}=_.useContext(Ht),{pathname:b}=Gt(),z=Bm(),S=hi(i,Ff(h),b,f==="path"),y=JSON.stringify(S);return _.useEffect(()=>{z(JSON.parse(y),{replace:s,state:d,relative:f})},[z,y,f,s,d]),null}function T0(i){return o0(i.context)}function Wl(i){ze(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function R0({basename:i="/",children:s=null,location:d,navigationType:f="POP",navigator:m,static:h=!1,unstable_useTransitions:b}){ze(!Ya(),"You cannot render a inside another . You should never have more than one in your app.");let z=i.replace(/^\/*/,"/"),S=_.useMemo(()=>({basename:z,navigator:m,static:h,unstable_useTransitions:b,future:{}}),[z,m,h,b]);typeof d=="string"&&(d=Fl(d));let{pathname:y="/",search:C="",hash:T="",state:Y=null,key:H="default",unstable_mask:Q}=d,Z=_.useMemo(()=>{let q=ul(y,z);return q==null?null:{location:{pathname:q,search:C,hash:T,state:Y,key:H,unstable_mask:Q},navigationType:f}},[z,y,C,T,Y,H,f,Q]);return Ot(Z!=null,` is not able to match the URL "${y}${C}${T}" because it does not start with the basename, so the won't render anything.`),Z==null?null:_.createElement(gt.Provider,{value:S},_.createElement(wn.Provider,{children:s,value:Z}))}function A0({children:i,location:s}){return d0($f(i),s)}function $f(i,s=[]){let d=[];return _.Children.forEach(i,(f,m)=>{if(!_.isValidElement(f))return;let h=[...s,m];if(f.type===_.Fragment){d.push.apply(d,$f(f.props.children,h));return}ze(f.type===Wl,`[${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=$f(f.props.children,h)),d.push(b)}),d}var ri="get",oi="application/x-www-form-urlencoded";function yi(i){return typeof HTMLElement<"u"&&i instanceof HTMLElement}function z0(i){return yi(i)&&i.tagName.toLowerCase()==="button"}function O0(i){return yi(i)&&i.tagName.toLowerCase()==="form"}function C0(i){return yi(i)&&i.tagName.toLowerCase()==="input"}function D0(i){return!!(i.metaKey||i.altKey||i.ctrlKey||i.shiftKey)}function M0(i,s){return i.button===0&&(!s||s==="_self")&&!D0(i)}var ci=null;function U0(){if(ci===null)try{new FormData(document.createElement("form"),0),ci=!1}catch{ci=!0}return ci}var H0=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function Zf(i){return i!=null&&!H0.has(i)?(Ot(!1,`"${i}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${oi}"`),null):i}function q0(i,s){let d,f,m,h,b;if(O0(i)){let z=i.getAttribute("action");f=z?ul(z,s):null,d=i.getAttribute("method")||ri,m=Zf(i.getAttribute("enctype"))||oi,h=new FormData(i)}else if(z0(i)||C0(i)&&(i.type==="submit"||i.type==="image")){let z=i.form;if(z==null)throw new Error('Cannot submit a + + + {rawErr ?

{rawErr}

: null} + + + {result ? ( +
+
+

Results

+

+ matched_total={result.matched_total} returned={result.returned} truncated= + {String(result.truncated)} offset={result.offset} +

+
+
+ + + + + + + + + + {result.events.length === 0 ? ( + + + + ) : ( + result.events.map((ev, idx) => { + const runId = typeof ev.run_id === "string" ? ev.run_id : ""; + const ts = typeof ev.timestamp === "string" ? ev.timestamp : ""; + const agent = typeof ev.agent_id === "string" ? ev.agent_id : ""; + return ( + + + + + + ); + }) + )} + +
Run IDTimestampAgent
+ No events in this page. +
{shortId(runId)}{ts}{agent}
+
+ +
+ ) : null} + + ); +}