diff --git a/CHANGELOG.md b/CHANGELOG.md index 42a8ea996..abf7fbbef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,84 @@ All notable changes to GBrain will be documented in this file. +## [0.28.6] - 2026-05-06 + +**The brain finally captures what you BELIEVE, not just what's true.** +**Takes ship: typed, weighted, attributed claims that diff in git.** + +v0.28.6 adds the largest structural surface gbrain has ever shipped: a takes +layer that turns every page into a queryable belief surface. Four kinds +(`fact | take | bet | hunch`), explicit attribution (`world | garry | brain +| `), 0.0–1.0 weight, since/until dates, supersede chains, and bet +resolution. Markdown is the source of truth (a fenced table on the page); +Postgres is the derived index. Every weight change diffs in git. Every +superseded take stays visible with strikethrough so belief evolution is +preserved. `gbrain takes` CLI ships list, search, add, update, supersede, +and resolve. Plus unified model config, per-token MCP visibility for the +takes layer, three new MCP ops, and a re-chunk fix that closes a real +privacy hole at the index layer. + +### The numbers that matter + +Real surface area added vs the v0.24 baseline. Numbers from `git diff +master..HEAD --stat`: + +| Surface | Before | After | Δ | +|---|---|---|---| +| Engine methods on BrainEngine | 41 | 50 | +9 | +| MCP operations | 41 | 44 | +3 (takes_list, takes_search, think) | +| New SQL tables | — | 2 | takes + synthesis_evidence (HNSW partial index, FK CASCADE) | +| Schema migrations | v36 | v38 | +v37 (takes), +v38 (access_tokens.permissions JSONB) | +| New unit/integration tests | — | 75 | 36 takes + 10 page-lock + 11 model-config + 8 MCP allow-list + 5 extract + 5 fence parity | +| New CLI commands | — | 1 family | `gbrain takes ` + `gbrain auth permissions` | +| Privacy holes closed | 1 P0 | 0 | takes content stripped from page chunks before indexing (Codex P0 #3) | + +**What this means for you**: every page becomes a queryable belief +surface. `gbrain takes search "vertical AI"` returns ranked claims across +the entire brain. Add a hunch after office hours; supersede it three +months later when the data turns. The brain has been collecting facts for +years; v0.28.6 starts collecting your reads on those facts. + +### What's coming in v0.28.x as follow-ups + +- `gbrain think` synthesis pipeline (op surface registered now; gather + + RRF + cite + synthesize land in v0.28.x) +- `gbrain takes seed ` — LLM extracts claims from page prose +- Dream `auto_think` + `drift` phases (opt-in) + +The architecture is fully plumbed; the LLM-touching paths land +incrementally so the contracts are stable for SDK callers from day one. + +## To take advantage of v0.28.6 + +`gbrain upgrade` should do this automatically. If it didn't, or if `gbrain +doctor` warns about an incomplete migration: + +1. **Run the orchestrator manually:** + ```bash + gbrain apply-migrations --yes + ``` + This applies migrations v37 (takes + synthesis_evidence) and v38 + (access_tokens.permissions JSONB) and runs a one-time backfill to + populate the takes index from any pre-existing fenced takes tables + in your markdown. +2. **Your agent reads `skills/migrations/v0.28.0.md` the next time you + interact with it** — that skill explains the takes layer and how to + invoke `gbrain takes`. The migration orchestrator handles the + mechanical side; your agent picks up the new conventions on its + own. +3. **Verify the outcome:** + ```bash + gbrain takes --help + gbrain doctor + gbrain stats + ``` +4. **If any step fails or the numbers look wrong,** please file an issue + at https://github.com/garrytan/gbrain/issues with: + - output of `gbrain doctor` + - contents of `~/.gbrain/upgrade-errors.jsonl` if it exists + - which step broke + ## [0.28.5] - 2026-05-06 ## **`gbrain upgrade` is finally self-healing. Wedged brains, blocked binaries, and the `bun add -g` foot-gun all fixed in one wave.** @@ -108,6 +186,7 @@ issue with the doctor output and we will look. - output of `gbrain --version` - which step broke + ## [0.28.4] - 2026-05-06 ## **`gbrain eval cross-modal` — three frontier models score your skill output BEFORE tests cement it.** @@ -251,6 +330,185 @@ If you've been running an earlier copy of `restart-sweep.mjs` from the directory #### For contributors - Plan + reviews for this work live at `~/.claude/plans/figure-out-if-we-eager-coral.md`. Three review passes ran (CEO/HOLD, ENG/PLAN, codex outside-voice). Codex caught two silent-correctness bugs the eng review missed: idempotency key collapse (C1) and import-time env snapshot (C2). Both folded in before merge. The plan documents the recipe-vs-plugin-handler decision (held recipe path for v1; plugin handler is the v2 shape per `docs/guides/plugin-handlers.md`). +## [0.28.2] - 2026-05-06 + +**Register a remote git URL as a brain source over HTTP MCP.** +**Least-privilege OAuth: scoped tokens for sources management without admin keys.** + +If your brain runs on a server (Tailscale-reachable, Cloudflare-tunneled, +on-prem), you can now point any MCP client at the brain and add a federated +source by URL — no SSH into the brain host. `gbrain sources add --url +https://github.com/your-org/notes` clones, registers, and syncs in one +call. The clone lives at a predictable path; if it gets autopurged the +next sync re-clones it. The whole flow is also exposed as MCP ops, so +gstack and similar agents can wire up the source automatically. + +The OAuth scope hierarchy got two new tiers (`sources_admin`, +`users_admin`) so you can mint tokens that manage sources without granting +admin to your pages. Tokens stay least-privilege; refresh and discovery +work end to end. + +### What you can do that you couldn't before + +- **`gbrain sources add --url `** — clones a remote git repo + into `$GBRAIN_HOME/clones//`, registers it as a federated source, + and stores the URL so future syncs auto-recover from a missing clone. +- **`whoami` MCP op** — any authenticated client can introspect itself: + `{transport, client_id, scopes, expires_at}`. Lets agents detect what + capabilities they have without trial-and-error against every other op. +- **`sources_add`, `sources_list`, `sources_remove`, `sources_status` + MCP ops** — full source lifecycle over HTTP MCP. `sources_status` + returns a `clone_state` field (`healthy | missing | no-git | url-drift + | corrupted`) so a remote agent can diagnose a busted clone without + SSH. +- **Scoped tokens** — `gbrain auth register-client X --scopes "read + sources_admin"` mints a token that can manage federated sources without + page-write or admin access. The OAuth allowlist rejects bogus scope + strings at registration time. +- **Auto-recovery on sync** — if your `$GBRAIN_HOME/clones//` + directory gets deleted (operator cleanup, disk move, host migration), + the next `gbrain sync --source ` re-clones from the recorded URL + and continues. +- **`gbrain doctor` orphan-clones check** — surfaces stale temp dirs in + `$GBRAIN_HOME/clones/.tmp/` so a SIGKILL'd `add --url` doesn't quietly + fill your disk over months. + +### Numbers that matter + +| Metric | Before | After | Δ | +|---|---|---|---| +| MCP ops registered | 44 | 49 | +5 (whoami + sources_*) | +| OAuth scopes advertised | 3 | 5 | +2 (sources_admin, users_admin) | +| `/setup-gbrain` Path 4 manual SSH steps | 4 | 0 | -4 | +| Lines of new test coverage | 0 | ~1500 | (8 new test files) | + +The 4-to-0 SSH-step number is the gstack `/setup-gbrain` flow: previously +the operator had to ssh into the brain host, run `gbrain sources add +--path `, and re-register. Post-v0.28.2 that's a single +`sources_add` MCP call from any agent with `sources_admin` scope. + +### What this means for you + +If you run a personal brain on your laptop, this is invisible — `gbrain +upgrade` and you keep working. If you run a brain on a server that other +agents talk to over HTTP MCP (Tailscale node, Cloudflare tunnel, lab +host), this is the v0.28 release that lets you wire those agents up +without ever opening an SSH session. Mint a `sources_admin` token, hand +it to the agent, the agent does the rest. + +### To take advantage of v0.28.2 + +`gbrain upgrade` should do this automatically. If you're running a +gbrain HTTP server, also rebuild the admin SPA so the Register modal +shows the new scope checkboxes: + +```bash +gbrain upgrade +cd admin && bun install && bun run build +git add admin/dist/ && git commit -m "chore: rebuild admin SPA" +``` + +Then mint a scoped token and verify `/.well-known/oauth-authorization-server` +advertises all 5 scopes: + +```bash +gbrain auth register-client gstack-test \ + --grant-types client_credentials \ + --scopes "read sources_admin" +curl http://your-brain-host/.well-known/oauth-authorization-server | jq .scopes_supported +# expect: ["admin","read","sources_admin","users_admin","write"] +``` + +If anything looks wrong, please file an issue: +https://github.com/garrytan/gbrain/issues with: +- output of `gbrain doctor` +- which step broke + +### Itemized changes + +**New: `gbrain sources add --url`** — HTTPS-only remote source registration +with SSRF defenses and atomic clone (temp-dir + rename + rollback). Internal +URL classification reuses `isInternalUrl` from `src/core/url-safety.ts` +(extracted from `integrations.ts` so SSRF gates stay DRY across the +codebase). `git clone` runs with redirects disabled, submodule recursion +disabled, and no external protocol helpers — closes the bypass surfaces +that survive a naive private-IP filter. + +**New: `whoami` + `sources_*` MCP ops** — five new ops auto-flow through +the existing tool-defs surface. `whoami` returns a `transport` field +(`oauth | legacy | local`) and throws `unknown_transport` when the +context is ambiguous (preserves the v0.26.9 fail-closed posture). +`sources_*` ops use `sources_admin` scope so a token with that scope +can register and remove sources but cannot write pages. + +**New: scope hierarchy + allowlist (`src/core/scope.ts`)** — `hasScope` +helper replaces exact-string-match at four enforcement sites. `admin` +implies all; `write` implies `read`; `sources_admin` and `users_admin` +are siblings. `ALLOWED_SCOPES` is validated at registration time +(CLI + DCR /register + manual). Pre-allowlist clients keep working. + +**New: doctor `orphan_clones` check + `purge` phase substep** — surfaces +stale `.tmp/` clone dirs older than 24h; the autopilot purge phase nukes +them on the same TTL as page soft-deletes (72h). + +**Sync auto-recovery** — `performSync` now classifies the on-disk clone +state via `validateRepoState`. If the clone is missing/no-git/not-a-dir, +it re-clones from `config.remote_url`. If corrupted or url-drift, it +refuses with structured hints rather than syncing wrong state. + +**Symlink-safe clone cleanup** — `sources_remove` uses realpath+lstat +confinement (matching `validateUploadPath`) before `rm -rf`. String +prefix match would let a malicious symlink resolve out of the +$GBRAIN_HOME/clones/ confine. + +**OAuth metadata** — `/.well-known/oauth-authorization-server` advertises +all 5 scopes so MCP clients (Claude Desktop, ChatGPT, Perplexity) discover +the new tiers via standard OAuth discovery. + +**Admin SPA** — Register Client modal sources its scope checkbox set from +`admin/src/lib/scope-constants.ts`, a hand-maintained mirror of +`src/core/scope.ts`. `scripts/check-admin-scope-drift.sh` fails the build +if the two diverge — wired into `bun run verify`. + +### Codex hardening pass (pre-ship adversarial review) + +The pre-ship adversarial review caught five issues that landed alongside the +core feature: + +- `sources_admin` tokens over HTTP MCP can no longer override `path` or + `clone_dir`. Those flags were a privilege escalation primitive: a remote + caller with the new scope could plant repo content at any host path, + and the auto-recovery branch's `rm -rf` on degraded state turned that + into arbitrary delete. Local CLI keeps the override (operator trust); + remote callers get the safe default `$GBRAIN_HOME/clones//` and a + warn log when they tried. +- Steady-state `git pull --ff-only` now routes through the same SSRF-defensive + flag set as the initial clone. The legacy helper at `src/commands/sync.ts:192` + was spawning git without `-c http.followRedirects=false -c protocol.{file,ext}.allow=never --no-recurse-submodules`, + so every recurring sync was reopening the redirect/submodule/protocol + bypass that `cloneRepo` closed. +- `sources_list` honors `include_archived: false` (the default). Archived + sources' ids, local_paths, and remote_urls were leaking to read-scoped + callers regardless of the flag. +- `parseRemoteUrl` blocks IPv6 ULA `fc00::/7` and link-local `fe80::/10`. + Previously only `::1` / `::` and IPv4-mapped IPv6 were rejected. +- DNS rebinding defense filed as a v0.28.x follow-up TODO. The current + gate is lexical only; a deliberate attacker with DNS control can still + resolve a public hostname to an internal IP. Closing this needs async + DNS resolution + revalidation. + +### For contributors + +- `src/core/url-safety.ts` extracted from `integrations.ts` for cross-layer + reuse. `src/commands/integrations.ts` re-exports the same names so + existing test imports work unchanged. +- `src/core/sources-ops.ts` houses the pure-function source-management + surface that both the CLI and the new MCP ops call into. Atomicity + contract documented in the file header. +- `bun run check:admin-scope-drift` — new gate; fails the build if + `admin/src/lib/scope-constants.ts` falls behind `src/core/scope.ts`. + + ## [0.28.1] - 2026-05-06 ## **Long-running deployments stop drowning in zombie processes. /health stops racing the orchestrator. Pool slots free immediately on shutdown.** @@ -1165,6 +1423,32 @@ React admin dashboard baked into the binary. Seven screens designed through Stev ```bash gbrain apply-migrations --yes ``` +2. **Your agent reads `skills/migrations/v0.28.0.md` the next time you + interact with it.** The migration backfills takes from any pre-existing + fenced markdown tables; queues a re-chunk TODO so the chunker-strip + rule (Codex P0 fix — keeps takes content out of page chunks where the + per-token allow-list cannot reach) catches up on legacy pages. +3. **Verify the outcome:** + ```bash + gbrain doctor + gbrain stats + gbrain takes --help + ``` +4. **Migrate per-phase model keys** (optional, mechanical, deprecation + warning until v0.30): + ```bash + gbrain config set models.default sonnet + ``` +5. **Configure MCP token visibility** (security-relevant for tokens + bound to public/agent integrations): + ```bash + gbrain auth permissions set-takes-holders world,garry,brain + ``` + Default for tokens with no permissions row: `["world"]`. Hunches stay + private to local CLI callers unless you explicitly grant agent visibility. + +6. **If any step fails or the numbers look wrong,** please file an issue: + https://github.com/garrytan/gbrain/issues with: 2. **Verify OAuth tables exist:** ```bash gbrain doctor @@ -1185,6 +1469,69 @@ React admin dashboard baked into the binary. Seven screens designed through Stev ### Itemized changes +#### Schema (migrations v37 + v38) + +- **takes table** — `(page_id, row_num)` natural unique key + `id BIGSERIAL` + PK; full claim metadata; resolution metadata (`resolved_at`, + `resolved_outcome`, `resolved_value`, `resolved_unit`, `resolved_source`, + `resolved_by`); HNSW partial index on `embedding` for active rows. +- **synthesis_evidence table** — composite FK with `ON DELETE CASCADE`. +- **access_tokens.permissions JSONB** — default `{"takes_holders":["world"]}`. + Backfill UPDATE handles pre-existing rows so old tokens default-deny. + +#### Engine + types + +- BrainEngine gains 9 new methods. +- `Take`, `TakeBatchInput`, `TakeHit`, `StaleTakeRow`, `TakeKind`, + `TakesListOpts`, `TakeResolution`, `SynthesisEvidenceInput` types. +- `OperationContext.takesHoldersAllowList` threaded through dispatch. + +#### Markdown surface + +- `src/core/takes-fence.ts` — pure parser/renderer/upserter for the + fenced table. Append-only semantics; row_num monotonic forever. +- `src/core/page-lock.ts` — PID-liveness file lock per page. +- `src/core/cycle/extract-takes.ts` — dual-path (fs + db) phase. +- `src/core/chunkers/recursive.ts` — calls `stripTakesFence()` BEFORE + chunking (Codex P0 #3 privacy fix). + +#### Unified model config + +- `src/core/model-config.ts` — `resolveModel()` 6-tier resolver replaces + hardcoded model strings and per-phase config keys. +- Aliases: `opus`, `sonnet`, `haiku`, `gemini`, `gpt`. Cycle-safe. +- Migrated call sites: `synthesize.ts` (model + verdictModel), `patterns.ts` + (model). Deprecated keys still honored with stderr warning until v0.30. + +#### MCP + auth + +- New ops `takes_list`, `takes_search`, `think` (think op-surface only; + pipeline in v0.28.x). +- HTTP transport reads `access_tokens.permissions.takes_holders` and + threads through dispatch → engine SQL filter. +- Stdio defaults to `["world"]`. +- `gbrain auth create --takes-holders` flag + `auth permissions + set-takes-holders` subcommand. + +#### CLI + +- `gbrain takes ` / `search` / `add` / `update` / `supersede` / + `resolve` — full lifecycle. + +#### Tests added + +75 new cases. All pass. Coverage: `test/takes-engine.test.ts` (16), +`test/takes-fence.test.ts` (15), `test/extract-takes.test.ts` (5), +`test/page-lock.test.ts` (10), `test/model-config.test.ts` (11), +`test/takes-mcp-allowlist.test.ts` (8). + +#### Risks accepted + +- **Think pipeline ships incrementally**: op surface registered now, + pipeline lands in v0.28.x. SDK callers detect the surface and degrade + gracefully. +- **Auto-think + drift phases deferred**: opt-in dream-cycle phases for + autonomous belief evolution. Land in v0.28.x; no schema migration needed. **Security hardening (post-/cso pass):** - Auth code exchange + refresh token rotation now use atomic `DELETE...RETURNING` instead of SELECT-then-DELETE. The earlier non-atomic pattern let two concurrent token requests with the same auth code both succeed, issuing two valid token pairs from one code (RFC 6749 §10.5 violation). Same shape applied to refresh tokens (RFC 6749 §10.4 detection of stolen tokens depends on second-use failure). New regression tests fire 10 concurrent requests with the same code/refresh and assert exactly one succeeds. - `pgArray()` now escapes commas, braces, quotes, and backslashes inside array elements. The earlier no-escape join could be exploited (with `--enable-dcr` on) to smuggle a second redirect_uri into a registered client's array, enabling auth code redirection to an attacker-controlled domain. diff --git a/README.md b/README.md index 3267be538..423c2a6ef 100644 --- a/README.md +++ b/README.md @@ -749,6 +749,11 @@ ADMIN # programmatically via oauthProvider.registerClientManual() for host-repo wrappers. gbrain integrations Integration recipe dashboard gbrain sources list|add|remove|... Multi-source brain management (v0.18) + v0.28.2: --url registers a federated + remote git repo; clone is auto-managed under + $GBRAIN_HOME/clones// and re-cloned on sync if + it goes missing. Also exposed via MCP for remote + agent setup (whoami + sources_{add,list,remove,status}). gbrain dream [--dry-run] [--phase N] 8-phase maintenance cycle (lint→backlinks→sync→synthesize →extract→patterns→embed→orphans). v0.23 added synthesize + patterns: transcripts → reflections + cross-session themes. diff --git a/TODOS.md b/TODOS.md index aeda7fa9e..2e1035cc4 100644 --- a/TODOS.md +++ b/TODOS.md @@ -74,6 +74,90 @@ **Pros:** Liveness probe stays under 100ms even on saturated pools. Operators get a separate `/stats` for the count breakdown when they actually want it. **Cons:** Behavior change for orchestrator setups that scrape /health as both liveness AND count source. **Context:** PR #637 (v0.28.1) adversarial review. Pair with the AbortController follow-up above. +## Remote-source MCP follow-ups (v0.28.2) + +### Token rotation: `gbrain auth rotate ` + `rotate_token` MCP op +**Priority:** P2 + +**What:** Atomic rotate for legacy + OAuth tokens. Issue a new token in the same TX as the revocation of the old, no overlap window. Refresh-token rotation already exists for OAuth; this is the unified user-facing surface (CLI + MCP). + +**Why:** Today rotation is `revoke + create`, with a window where neither token works. For long-lived bearer keys handed to agents, that's a reload outage every time the key gets rotated. + +**Pros:** Single command does the right thing. Atomic cutover. Operators stop scripting around the gap. +**Cons:** Needs careful testing of the legacy `access_tokens` UPDATE path (returns single-use new token before the row mutates) plus an MCP op that grants a new token bound to the original client_id without requiring a new authorize round trip. +**Context:** Item 4 from the gstack /setup-gbrain v1.28.1.0 enhancement request. v0.28.x candidate. +**Depends on:** Nothing. + +### Migration introspection in `get_health` +**Priority:** P3 + +**What:** Extend `BrainEngine.getHealth()` return shape with `migrations: { pending: [...], wedged: [...] }`. `gbrain doctor` already shows this; expose it via the MCP op so remote agents can detect partial-migration state without invoking `doctor` separately. + +**Why:** Closes a remote-diagnostic gap. gstack /setup-gbrain Path 4 hit a wedged-migration brain mid-session; the only readback was SSH + `gbrain doctor`. With this, the same diagnostic flows through MCP. + +**Pros:** Pure additive change to the `get_health` op shape. No new op surface. Consumers ignore the new field if they don't care. +**Cons:** Wedged detection logic lives in `gbrain doctor`'s code today; need to extract or duplicate. Care needed not to leak migration internals to non-admin scopes (current op is admin-only — fine). +**Context:** Item 5 from the gstack /setup-gbrain v1.28.1.0 enhancement request. +**Depends on:** Nothing. + +### Accept-header friendliness on `/mcp` +**Priority:** P3 + +**What:** MCP SDK rejects requests missing `text/event-stream` in the Accept header with a generic 406 Not Acceptable. Pre-check the header at the express middleware layer and return a 400 with a descriptive hint pointing at the spec. + +**Why:** Other MCP clients (curl scripts, custom integrations) hit the SDK's 406 and get no diagnostic. gstack's verify-helper sets both headers correctly so the headline path works. + +**Pros:** Operator UX improvement. Faster debugging when clients fail discovery. +**Cons:** Tight coupling to the SDK behavior — if it later loosens, the pre-check becomes redundant. +**Context:** Item 6 from the gstack /setup-gbrain v1.28.1.0 enhancement request. +**Depends on:** Nothing. + +### `gbrain sources rebase-clone ` +**Priority:** P3 + +**What:** Recover from `url-drift` (config.remote_url updated but the on-disk clone still points at the old origin). Currently `sync` refuses with a structured error pointing at this command — but the command itself doesn't exist yet. Implement: prompt for confirmation (rm-rf the clone is destructive), then re-clone via the same temp-dir + rename atomicity contract as `sources add --url`. + +**Why:** Closes the loop on the URL-drift code path the v0.28.2 sync added. Without it, operators have to `sources remove --confirm-destructive` + `sources add --url` (loses page count, history). + +**Pros:** Cleaner UX for URL changes. Preserves the source row + history. +**Cons:** Destructive on-disk; needs `--confirm-destructive` gate. Edge case: what if sync is mid-run when rebase fires? The existing sync-lock guards this, but worth pinning in tests. +**Context:** v0.28.2 plan filed this explicitly as a follow-up. +**Depends on:** Nothing. + +### `--filter=blob:none` partial-clone option for federated sources +**Priority:** P3 + +**What:** v0.28.2 defaults `gbrain sources add --url` to `--depth=1` (no history). For users who want commit-aware features later (page-state-at-commit-X, blame, who-edited-what), expose `--filter=blob:none` as an opt-in: keeps full graph metadata, lazy-fetches blobs. + +**Why:** `--depth=1` is a one-way door — once cloned, you can't reconstruct history without re-cloning the whole repo. Partial clones preserve history while staying small. + +**Pros:** Forward-compat for commit-aware brain features. Negligible cost on first clone for typical brain repos. Better than the alternative (full clones for everyone). +**Cons:** First-clone latency is higher on long-history repos. Adds one more flag to the `add` surface. +**Context:** Eng review A5 — the boring choice for v0.28.2 was `--depth=1`. This is the unboring follow-up. +**Depends on:** Nothing. + +### DNS rebinding defense for `parseRemoteUrl` +**Priority:** P3 + +**What:** `isInternalUrl` (`src/core/url-safety.ts`) does lexical/string-based classification only — no DNS resolution. An attacker who controls a public hostname's A/AAAA records can resolve to internal IPs (`127.0.0.1`, `169.254.169.254`, RFC 1918) and bypass the SSRF gate. The gate catches direct IP literals + metadata hostnames; it doesn't catch `https://attacker-controlled.example/repo.git` where DNS points internal. + +**Why:** Defense in depth. The current gate is sufficient for naive abuse (typing `192.168.1.1` directly), but a deliberate attacker with DNS control can bypass it. Adding async DNS resolution + revalidation closes the hole. + +**Pros:** Closes the cleanest remaining SSRF bypass. Mirrors the redirect-revalidation pattern at `integrations.ts:289`. Pinned by a future test using a mock resolver. +**Cons:** Async DNS makes `parseRemoteUrl` `async`. Every caller (CLI, MCP op, test) needs to update. ~50-line change. +**Context:** Codex finding from v0.28.2 ship adversarial review. The IPv6 ULA + link-local portion of the same finding shipped in v0.28.2; DNS rebinding deferred. +**Depends on:** Nothing. + +### `sources.chunker_version` PGLite-schema parity +**Priority:** P3 + +**What:** `src/schema.sql:33` declares `sources.chunker_version` and `src/commands/sync.ts:253` reads/writes it, but `src/core/pglite-schema.ts:28` omits the column. PGLite users hit a schema-mismatch error on the sync write path. + +**Why:** Pre-existing bug surfaced during the v0.28.2 codex review. Not introduced by remote-source work, but adjacent to source-sync code. Worth fixing as a small parity PR before more source-local state lands. + +**Pros:** Closes a quiet schema drift between the two engine implementations. ~10 lines. +**Cons:** Needs a migration entry to add the column to existing PGLite brains. Migration version bump. +**Context:** Codex D5 from v0.28.2 plan review. **Depends on:** Nothing. ## OAuth/MCP hardening (v0.26.7 follow-up) diff --git a/VERSION b/VERSION index 42a133b21..2aa6ed79d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.28.5 \ No newline at end of file +0.28.6 diff --git a/admin/dist/assets/index-DWYc55rS.js b/admin/dist/assets/index-CDv6_ml5.js similarity index 83% rename from admin/dist/assets/index-DWYc55rS.js rename to admin/dist/assets/index-CDv6_ml5.js index 014ccc28d..3994ff46a 100644 --- a/admin/dist/assets/index-DWYc55rS.js +++ b/admin/dist/assets/index-CDv6_ml5.js @@ -1,4 +1,4 @@ -(function(){const H=document.createElement("link").relList;if(H&&H.supports&&H.supports("modulepreload"))return;for(const O of document.querySelectorAll('link[rel="modulepreload"]'))r(O);new MutationObserver(O=>{for(const G of O)if(G.type==="childList")for(const U of G.addedNodes)U.tagName==="LINK"&&U.rel==="modulepreload"&&r(U)}).observe(document,{childList:!0,subtree:!0});function D(O){const G={};return O.integrity&&(G.integrity=O.integrity),O.referrerPolicy&&(G.referrerPolicy=O.referrerPolicy),O.crossOrigin==="use-credentials"?G.credentials="include":O.crossOrigin==="anonymous"?G.credentials="omit":G.credentials="same-origin",G}function r(O){if(O.ep)return;O.ep=!0;const G=D(O);fetch(O.href,G)}})();function jr(m){return m&&m.__esModule&&Object.prototype.hasOwnProperty.call(m,"default")?m.default:m}var cf={exports:{}},Tu={};/** +(function(){const H=document.createElement("link").relList;if(H&&H.supports&&H.supports("modulepreload"))return;for(const O of document.querySelectorAll('link[rel="modulepreload"]'))r(O);new MutationObserver(O=>{for(const G of O)if(G.type==="childList")for(const U of G.addedNodes)U.tagName==="LINK"&&U.rel==="modulepreload"&&r(U)}).observe(document,{childList:!0,subtree:!0});function D(O){const G={};return O.integrity&&(G.integrity=O.integrity),O.referrerPolicy&&(G.referrerPolicy=O.referrerPolicy),O.crossOrigin==="use-credentials"?G.credentials="include":O.crossOrigin==="anonymous"?G.credentials="omit":G.credentials="same-origin",G}function r(O){if(O.ep)return;O.ep=!0;const G=D(O);fetch(O.href,G)}})();function Or(m){return m&&m.__esModule&&Object.prototype.hasOwnProperty.call(m,"default")?m.default:m}var cf={exports:{}},Tu={};/** * @license React * react-jsx-runtime.production.js * @@ -6,7 +6,7 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var vr;function Im(){if(vr)return Tu;vr=1;var m=Symbol.for("react.transitional.element"),H=Symbol.for("react.fragment");function D(r,O,G){var U=null;if(G!==void 0&&(U=""+G),O.key!==void 0&&(U=""+O.key),"key"in O){G={};for(var w in O)w!=="key"&&(G[w]=O[w])}else G=O;return O=G.ref,{$$typeof:m,type:r,key:U,ref:O!==void 0?O:null,props:G}}return Tu.Fragment=H,Tu.jsx=D,Tu.jsxs=D,Tu}var gr;function Pm(){return gr||(gr=1,cf.exports=Im()),cf.exports}var f=Pm(),ff={exports:{}},Z={};/** + */var vr;function Pm(){if(vr)return Tu;vr=1;var m=Symbol.for("react.transitional.element"),H=Symbol.for("react.fragment");function D(r,O,G){var U=null;if(G!==void 0&&(U=""+G),O.key!==void 0&&(U=""+O.key),"key"in O){G={};for(var w in O)w!=="key"&&(G[w]=O[w])}else G=O;return O=G.ref,{$$typeof:m,type:r,key:U,ref:O!==void 0?O:null,props:G}}return Tu.Fragment=H,Tu.jsx=D,Tu.jsxs=D,Tu}var gr;function ly(){return gr||(gr=1,cf.exports=Pm()),cf.exports}var f=ly(),ff={exports:{}},L={};/** * @license React * react.production.js * @@ -14,7 +14,7 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var Sr;function ly(){if(Sr)return Z;Sr=1;var m=Symbol.for("react.transitional.element"),H=Symbol.for("react.portal"),D=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),O=Symbol.for("react.profiler"),G=Symbol.for("react.consumer"),U=Symbol.for("react.context"),w=Symbol.for("react.forward_ref"),M=Symbol.for("react.suspense"),p=Symbol.for("react.memo"),R=Symbol.for("react.lazy"),_=Symbol.for("react.activity"),x=Symbol.iterator;function F(d){return d===null||typeof d!="object"?null:(d=x&&d[x]||d["@@iterator"],typeof d=="function"?d:null)}var K={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},al=Object.assign,ll={};function pl(d,E,N){this.props=d,this.context=E,this.refs=ll,this.updater=N||K}pl.prototype.isReactComponent={},pl.prototype.setState=function(d,E){if(typeof d!="object"&&typeof d!="function"&&d!=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,d,E,"setState")},pl.prototype.forceUpdate=function(d){this.updater.enqueueForceUpdate(this,d,"forceUpdate")};function Ml(){}Ml.prototype=pl.prototype;function Gl(d,E,N){this.props=d,this.context=E,this.refs=ll,this.updater=N||K}var st=Gl.prototype=new Ml;st.constructor=Gl,al(st,pl.prototype),st.isPureReactComponent=!0;var _t=Array.isArray;function Ll(){}var tl={H:null,A:null,T:null,S:null},Vl=Object.prototype.hasOwnProperty;function jt(d,E,N){var B=N.ref;return{$$typeof:m,type:d,key:E,ref:B!==void 0?B:null,props:N}}function Le(d,E){return jt(d.type,E,d.props)}function Ot(d){return typeof d=="object"&&d!==null&&d.$$typeof===m}function Kl(d){var E={"=":"=0",":":"=2"};return"$"+d.replace(/[=:]/g,function(N){return E[N]})}var Ae=/\/+/g;function Ut(d,E){return typeof d=="object"&&d!==null&&d.key!=null?Kl(""+d.key):E.toString(36)}function pt(d){switch(d.status){case"fulfilled":return d.value;case"rejected":throw d.reason;default:switch(typeof d.status=="string"?d.then(Ll,Ll):(d.status="pending",d.then(function(E){d.status==="pending"&&(d.status="fulfilled",d.value=E)},function(E){d.status==="pending"&&(d.status="rejected",d.reason=E)})),d.status){case"fulfilled":return d.value;case"rejected":throw d.reason}}throw d}function T(d,E,N,B,L){var k=typeof d;(k==="undefined"||k==="boolean")&&(d=null);var fl=!1;if(d===null)fl=!0;else switch(k){case"bigint":case"string":case"number":fl=!0;break;case"object":switch(d.$$typeof){case m:case H:fl=!0;break;case R:return fl=d._init,T(fl(d._payload),E,N,B,L)}}if(fl)return L=L(d),fl=B===""?"."+Ut(d,0):B,_t(L)?(N="",fl!=null&&(N=fl.replace(Ae,"$&/")+"/"),T(L,E,N,"",function(Oa){return Oa})):L!=null&&(Ot(L)&&(L=Le(L,N+(L.key==null||d&&d.key===L.key?"":(""+L.key).replace(Ae,"$&/")+"/")+fl)),E.push(L)),1;fl=0;var Ql=B===""?".":B+":";if(_t(d))for(var Al=0;Al>>1,yl=T[dl];if(0>>1;dlO(N,Q))BO(L,N)?(T[dl]=L,T[B]=Q,dl=B):(T[dl]=N,T[E]=Q,dl=E);else if(BO(L,Q))T[dl]=L,T[B]=Q,dl=B;else break l}}return j}function O(T,j){var Q=T.sortIndex-j.sortIndex;return Q!==0?Q:T.id-j.id}if(m.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var G=performance;m.unstable_now=function(){return G.now()}}else{var U=Date,w=U.now();m.unstable_now=function(){return U.now()-w}}var M=[],p=[],R=1,_=null,x=3,F=!1,K=!1,al=!1,ll=!1,pl=typeof setTimeout=="function"?setTimeout:null,Ml=typeof clearTimeout=="function"?clearTimeout:null,Gl=typeof setImmediate<"u"?setImmediate:null;function st(T){for(var j=D(p);j!==null;){if(j.callback===null)r(p);else if(j.startTime<=T)r(p),j.sortIndex=j.expirationTime,H(M,j);else break;j=D(p)}}function _t(T){if(al=!1,st(T),!K)if(D(M)!==null)K=!0,Ll||(Ll=!0,Kl());else{var j=D(p);j!==null&&pt(_t,j.startTime-T)}}var Ll=!1,tl=-1,Vl=5,jt=-1;function Le(){return ll?!0:!(m.unstable_now()-jtT&&Le());){var dl=_.callback;if(typeof dl=="function"){_.callback=null,x=_.priorityLevel;var yl=dl(_.expirationTime<=T);if(T=m.unstable_now(),typeof yl=="function"){_.callback=yl,st(T),j=!0;break t}_===D(M)&&r(M),st(T)}else r(M);_=D(M)}if(_!==null)j=!0;else{var d=D(p);d!==null&&pt(_t,d.startTime-T),j=!1}}break l}finally{_=null,x=Q,F=!1}j=void 0}}finally{j?Kl():Ll=!1}}}var Kl;if(typeof Gl=="function")Kl=function(){Gl(Ot)};else if(typeof MessageChannel<"u"){var Ae=new MessageChannel,Ut=Ae.port2;Ae.port1.onmessage=Ot,Kl=function(){Ut.postMessage(null)}}else Kl=function(){pl(Ot,0)};function pt(T,j){tl=pl(function(){T(m.unstable_now())},j)}m.unstable_IdlePriority=5,m.unstable_ImmediatePriority=1,m.unstable_LowPriority=4,m.unstable_NormalPriority=3,m.unstable_Profiling=null,m.unstable_UserBlockingPriority=2,m.unstable_cancelCallback=function(T){T.callback=null},m.unstable_forceFrameRate=function(T){0>T||125dl?(T.sortIndex=Q,H(p,T),D(M)===null&&T===D(p)&&(al?(Ml(tl),tl=-1):al=!0,pt(_t,Q-dl))):(T.sortIndex=yl,H(M,T),K||F||(K=!0,Ll||(Ll=!0,Kl()))),T},m.unstable_shouldYield=Le,m.unstable_wrapCallback=function(T){var j=x;return function(){var Q=x;x=j;try{return T.apply(this,arguments)}finally{x=Q}}}})(df)),df}var Tr;function ey(){return Tr||(Tr=1,of.exports=ty()),of.exports}var rf={exports:{}},Xl={};/** + */var pr;function ey(){return pr||(pr=1,(function(m){function H(T,j){var Q=T.length;T.push(j);l:for(;0>>1,yl=T[dl];if(0>>1;dlO(N,Q))BO(V,N)?(T[dl]=V,T[B]=Q,dl=B):(T[dl]=N,T[E]=Q,dl=E);else if(BO(V,Q))T[dl]=V,T[B]=Q,dl=B;else break l}}return j}function O(T,j){var Q=T.sortIndex-j.sortIndex;return Q!==0?Q:T.id-j.id}if(m.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var G=performance;m.unstable_now=function(){return G.now()}}else{var U=Date,w=U.now();m.unstable_now=function(){return U.now()-w}}var M=[],p=[],R=1,x=null,_=3,F=!1,Z=!1,al=!1,ll=!1,pl=typeof setTimeout=="function"?setTimeout:null,Ml=typeof clearTimeout=="function"?clearTimeout:null,Gl=typeof setImmediate<"u"?setImmediate:null;function st(T){for(var j=D(p);j!==null;){if(j.callback===null)r(p);else if(j.startTime<=T)r(p),j.sortIndex=j.expirationTime,H(M,j);else break;j=D(p)}}function xt(T){if(al=!1,st(T),!Z)if(D(M)!==null)Z=!0,Ll||(Ll=!0,Kl());else{var j=D(p);j!==null&&pt(xt,j.startTime-T)}}var Ll=!1,tl=-1,Vl=5,jt=-1;function Le(){return ll?!0:!(m.unstable_now()-jtT&&Le());){var dl=x.callback;if(typeof dl=="function"){x.callback=null,_=x.priorityLevel;var yl=dl(x.expirationTime<=T);if(T=m.unstable_now(),typeof yl=="function"){x.callback=yl,st(T),j=!0;break t}x===D(M)&&r(M),st(T)}else r(M);x=D(M)}if(x!==null)j=!0;else{var d=D(p);d!==null&&pt(xt,d.startTime-T),j=!1}}break l}finally{x=null,_=Q,F=!1}j=void 0}}finally{j?Kl():Ll=!1}}}var Kl;if(typeof Gl=="function")Kl=function(){Gl(Ot)};else if(typeof MessageChannel<"u"){var Ae=new MessageChannel,Ut=Ae.port2;Ae.port1.onmessage=Ot,Kl=function(){Ut.postMessage(null)}}else Kl=function(){pl(Ot,0)};function pt(T,j){tl=pl(function(){T(m.unstable_now())},j)}m.unstable_IdlePriority=5,m.unstable_ImmediatePriority=1,m.unstable_LowPriority=4,m.unstable_NormalPriority=3,m.unstable_Profiling=null,m.unstable_UserBlockingPriority=2,m.unstable_cancelCallback=function(T){T.callback=null},m.unstable_forceFrameRate=function(T){0>T||125dl?(T.sortIndex=Q,H(p,T),D(M)===null&&T===D(p)&&(al?(Ml(tl),tl=-1):al=!0,pt(xt,Q-dl))):(T.sortIndex=yl,H(M,T),Z||F||(Z=!0,Ll||(Ll=!0,Kl()))),T},m.unstable_shouldYield=Le,m.unstable_wrapCallback=function(T){var j=_;return function(){var Q=_;_=j;try{return T.apply(this,arguments)}finally{_=Q}}}})(df)),df}var Tr;function ay(){return Tr||(Tr=1,of.exports=ey()),of.exports}var rf={exports:{}},Xl={};/** * @license React * react-dom.production.js * @@ -30,7 +30,7 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var zr;function ay(){if(zr)return Xl;zr=1;var m=hf();function H(M){var p="https://react.dev/errors/"+M;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(m)}catch(H){console.error(H)}}return m(),rf.exports=ay(),rf.exports}/** + */var zr;function uy(){if(zr)return Xl;zr=1;var m=hf();function H(M){var p="https://react.dev/errors/"+M;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(m)}catch(H){console.error(H)}}return m(),rf.exports=uy(),rf.exports}/** * @license React * react-dom-client.production.js * @@ -38,19 +38,19 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var Er;function ny(){if(Er)return zu;Er=1;var m=ey(),H=hf(),D=uy();function r(l){var t="https://react.dev/errors/"+l;if(1yl||(l.current=dl[yl],dl[yl]=null,yl--)}function N(l,t){yl++,dl[yl]=l.current,l.current=t}var B=d(null),L=d(null),k=d(null),fl=d(null);function Ql(l,t){switch(N(k,t),N(L,l),N(B,null),t.nodeType){case 9:case 11:l=(l=t.documentElement)&&(l=l.namespaceURI)?Gd(l):0;break;default:if(l=t.tagName,t=t.namespaceURI)t=Gd(t),l=Xd(t,l);else switch(l){case"svg":l=1;break;case"math":l=2;break;default:l=0}}E(B),N(B,l)}function Al(){E(B),E(L),E(k)}function Oa(l){l.memoizedState!==null&&N(fl,l);var t=B.current,e=Xd(t,l.type);t!==e&&(N(L,l),N(B,e))}function Au(l){L.current===l&&(E(B),E(L)),fl.current===l&&(E(fl),gu._currentValue=Q)}var Zn,mf;function Ee(l){if(Zn===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Zn=t&&t[1]||"",mf=-1yl||(l.current=dl[yl],dl[yl]=null,yl--)}function N(l,t){yl++,dl[yl]=l.current,l.current=t}var B=d(null),V=d(null),k=d(null),fl=d(null);function Ql(l,t){switch(N(k,t),N(V,l),N(B,null),t.nodeType){case 9:case 11:l=(l=t.documentElement)&&(l=l.namespaceURI)?Gd(l):0;break;default:if(l=t.tagName,t=t.namespaceURI)t=Gd(t),l=Xd(t,l);else switch(l){case"svg":l=1;break;case"math":l=2;break;default:l=0}}E(B),N(B,l)}function Al(){E(B),E(V),E(k)}function Oa(l){l.memoizedState!==null&&N(fl,l);var t=B.current,e=Xd(t,l.type);t!==e&&(N(V,l),N(B,e))}function Au(l){V.current===l&&(E(B),E(V)),fl.current===l&&(E(fl),gu._currentValue=Q)}var Zn,mf;function Ee(l){if(Zn===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Zn=t&&t[1]||"",mf=-1)":-1u||s[a]!==v[u]){var b=` -`+s[a].replace(" at new "," at ");return l.displayName&&b.includes("")&&(b=b.replace("",l.displayName)),b}while(1<=a&&0<=u);break}}}finally{Ln=!1,Error.prepareStackTrace=e}return(e=l?l.displayName||l.name:"")?Ee(e):""}function Nr(l,t){switch(l.tag){case 26:case 27:case 5:return Ee(l.type);case 16:return Ee("Lazy");case 13:return l.child!==t&&t!==null?Ee("Suspense Fallback"):Ee("Suspense");case 19:return Ee("SuspenseList");case 0:case 15:return Vn(l.type,!1);case 11:return Vn(l.type.render,!1);case 1:return Vn(l.type,!0);case 31:return Ee("Activity");default:return""}}function yf(l){try{var t="",e=null;do t+=Nr(l,e),e=l,l=l.return;while(l);return t}catch(a){return` +`+s[a].replace(" at new "," at ");return l.displayName&&b.includes("")&&(b=b.replace("",l.displayName)),b}while(1<=a&&0<=u);break}}}finally{Ln=!1,Error.prepareStackTrace=e}return(e=l?l.displayName||l.name:"")?Ee(e):""}function Mr(l,t){switch(l.tag){case 26:case 27:case 5:return Ee(l.type);case 16:return Ee("Lazy");case 13:return l.child!==t&&t!==null?Ee("Suspense Fallback"):Ee("Suspense");case 19:return Ee("SuspenseList");case 0:case 15:return Vn(l.type,!1);case 11:return Vn(l.type.render,!1);case 1:return Vn(l.type,!0);case 31:return Ee("Activity");default:return""}}function yf(l){try{var t="",e=null;do t+=Mr(l,e),e=l,l=l.return;while(l);return t}catch(a){return` Error generating stack: `+a.message+` -`+a.stack}}var Kn=Object.prototype.hasOwnProperty,Jn=m.unstable_scheduleCallback,wn=m.unstable_cancelCallback,Mr=m.unstable_shouldYield,Dr=m.unstable_requestPaint,Pl=m.unstable_now,Cr=m.unstable_getCurrentPriorityLevel,vf=m.unstable_ImmediatePriority,gf=m.unstable_UserBlockingPriority,Eu=m.unstable_NormalPriority,Ur=m.unstable_LowPriority,Sf=m.unstable_IdlePriority,Rr=m.log,Hr=m.unstable_setDisableYieldValue,Na=null,lt=null;function It(l){if(typeof Rr=="function"&&Hr(l),lt&&typeof lt.setStrictMode=="function")try{lt.setStrictMode(Na,l)}catch{}}var tt=Math.clz32?Math.clz32:Yr,Br=Math.log,qr=Math.LN2;function Yr(l){return l>>>=0,l===0?32:31-(Br(l)/qr|0)|0}var xu=256,_u=262144,ju=4194304;function xe(l){var t=l&42;if(t!==0)return t;switch(l&-l){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 l&261888;case 262144:case 524288:case 1048576:case 2097152:return l&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return l&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return l}}function Ou(l,t,e){var a=l.pendingLanes;if(a===0)return 0;var u=0,n=l.suspendedLanes,i=l.pingedLanes;l=l.warmLanes;var c=a&134217727;return c!==0?(a=c&~n,a!==0?u=xe(a):(i&=c,i!==0?u=xe(i):e||(e=c&~l,e!==0&&(u=xe(e))))):(c=a&~n,c!==0?u=xe(c):i!==0?u=xe(i):e||(e=a&~l,e!==0&&(u=xe(e)))),u===0?0:t!==0&&t!==u&&(t&n)===0&&(n=u&-u,e=t&-t,n>=e||n===32&&(e&4194048)!==0)?t:u}function Ma(l,t){return(l.pendingLanes&~(l.suspendedLanes&~l.pingedLanes)&t)===0}function Gr(l,t){switch(l){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 bf(){var l=ju;return ju<<=1,(ju&62914560)===0&&(ju=4194304),l}function kn(l){for(var t=[],e=0;31>e;e++)t.push(l);return t}function Da(l,t){l.pendingLanes|=t,t!==268435456&&(l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0)}function Xr(l,t,e,a,u,n){var i=l.pendingLanes;l.pendingLanes=e,l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0,l.expiredLanes&=e,l.entangledLanes&=e,l.errorRecoveryDisabledLanes&=e,l.shellSuspendCounter=0;var c=l.entanglements,s=l.expirationTimes,v=l.hiddenUpdates;for(e=i&~e;0"u")return null;try{return l.activeElement||l.body}catch{return l.body}}var Jr=/[\n"\\]/g;function dt(l){return l.replace(Jr,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function li(l,t,e,a,u,n,i,c){l.name="",i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"?l.type=i:l.removeAttribute("type"),t!=null?i==="number"?(t===0&&l.value===""||l.value!=t)&&(l.value=""+ot(t)):l.value!==""+ot(t)&&(l.value=""+ot(t)):i!=="submit"&&i!=="reset"||l.removeAttribute("value"),t!=null?ti(l,i,ot(t)):e!=null?ti(l,i,ot(e)):a!=null&&l.removeAttribute("value"),u==null&&n!=null&&(l.defaultChecked=!!n),u!=null&&(l.checked=u&&typeof u!="function"&&typeof u!="symbol"),c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?l.name=""+ot(c):l.removeAttribute("name")}function Cf(l,t,e,a,u,n,i,c){if(n!=null&&typeof n!="function"&&typeof n!="symbol"&&typeof n!="boolean"&&(l.type=n),t!=null||e!=null){if(!(n!=="submit"&&n!=="reset"||t!=null)){Pn(l);return}e=e!=null?""+ot(e):"",t=t!=null?""+ot(t):e,c||t===l.value||(l.value=t),l.defaultValue=t}a=a??u,a=typeof a!="function"&&typeof a!="symbol"&&!!a,l.checked=c?l.checked:!!a,l.defaultChecked=!!a,i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(l.name=i),Pn(l)}function ti(l,t,e){t==="number"&&Du(l.ownerDocument)===l||l.defaultValue===""+e||(l.defaultValue=""+e)}function $e(l,t,e,a){if(l=l.options,t){t={};for(var u=0;u"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),ii=!1;if(Bt)try{var Ha={};Object.defineProperty(Ha,"passive",{get:function(){ii=!0}}),window.addEventListener("test",Ha,Ha),window.removeEventListener("test",Ha,Ha)}catch{ii=!1}var le=null,ci=null,Uu=null;function Gf(){if(Uu)return Uu;var l,t=ci,e=t.length,a,u="value"in le?le.value:le.textContent,n=u.length;for(l=0;l=Ya),Kf=" ",Jf=!1;function wf(l,t){switch(l){case"keyup":return ph.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function kf(l){return l=l.detail,typeof l=="object"&&"data"in l?l.data:null}var Pe=!1;function zh(l,t){switch(l){case"compositionend":return kf(t);case"keypress":return t.which!==32?null:(Jf=!0,Kf);case"textInput":return l=t.data,l===Kf&&Jf?null:l;default:return null}}function Ah(l,t){if(Pe)return l==="compositionend"||!ri&&wf(l,t)?(l=Gf(),Uu=ci=le=null,Pe=!1,l):null;switch(l){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:e,offset:t-l};l=a}l:{for(;e;){if(e.nextSibling){e=e.nextSibling;break l}e=e.parentNode}e=void 0}e=es(e)}}function us(l,t){return l&&t?l===t?!0:l&&l.nodeType===3?!1:t&&t.nodeType===3?us(l,t.parentNode):"contains"in l?l.contains(t):l.compareDocumentPosition?!!(l.compareDocumentPosition(t)&16):!1:!1}function ns(l){l=l!=null&&l.ownerDocument!=null&&l.ownerDocument.defaultView!=null?l.ownerDocument.defaultView:window;for(var t=Du(l.document);t instanceof l.HTMLIFrameElement;){try{var e=typeof t.contentWindow.location.href=="string"}catch{e=!1}if(e)l=t.contentWindow;else break;t=Du(l.document)}return t}function yi(l){var t=l&&l.nodeName&&l.nodeName.toLowerCase();return t&&(t==="input"&&(l.type==="text"||l.type==="search"||l.type==="tel"||l.type==="url"||l.type==="password")||t==="textarea"||l.contentEditable==="true")}var Dh=Bt&&"documentMode"in document&&11>=document.documentMode,la=null,vi=null,Za=null,gi=!1;function is(l,t,e){var a=e.window===e?e.document:e.nodeType===9?e:e.ownerDocument;gi||la==null||la!==Du(a)||(a=la,"selectionStart"in a&&yi(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}),Za&&Qa(Za,a)||(Za=a,a=jn(vi,"onSelect"),0>=i,u-=i,Nt=1<<32-tt(t)+u|e<J?(P=q,q=null):P=q.sibling;var il=g(h,q,y[J],z);if(il===null){q===null&&(q=P);break}l&&q&&il.alternate===null&&t(h,q),o=n(il,o,J),nl===null?Y=il:nl.sibling=il,nl=il,q=P}if(J===y.length)return e(h,q),el&&Yt(h,J),Y;if(q===null){for(;JJ?(P=q,q=null):P=q.sibling;var ze=g(h,q,il.value,z);if(ze===null){q===null&&(q=P);break}l&&q&&ze.alternate===null&&t(h,q),o=n(ze,o,J),nl===null?Y=ze:nl.sibling=ze,nl=ze,q=P}if(il.done)return e(h,q),el&&Yt(h,J),Y;if(q===null){for(;!il.done;J++,il=y.next())il=A(h,il.value,z),il!==null&&(o=n(il,o,J),nl===null?Y=il:nl.sibling=il,nl=il);return el&&Yt(h,J),Y}for(q=a(q);!il.done;J++,il=y.next())il=S(q,h,J,il.value,z),il!==null&&(l&&il.alternate!==null&&q.delete(il.key===null?J:il.key),o=n(il,o,J),nl===null?Y=il:nl.sibling=il,nl=il);return l&&q.forEach(function(Fm){return t(h,Fm)}),el&&Yt(h,J),Y}function ml(h,o,y,z){if(typeof y=="object"&&y!==null&&y.type===al&&y.key===null&&(y=y.props.children),typeof y=="object"&&y!==null){switch(y.$$typeof){case F:l:{for(var Y=y.key;o!==null;){if(o.key===Y){if(Y=y.type,Y===al){if(o.tag===7){e(h,o.sibling),z=u(o,y.props.children),z.return=h,h=z;break l}}else if(o.elementType===Y||typeof Y=="object"&&Y!==null&&Y.$$typeof===Vl&&Be(Y)===o.type){e(h,o.sibling),z=u(o,y.props),ka(z,y),z.return=h,h=z;break l}e(h,o);break}else t(h,o);o=o.sibling}y.type===al?(z=De(y.props.children,h.mode,z,y.key),z.return=h,h=z):(z=Lu(y.type,y.key,y.props,null,h.mode,z),ka(z,y),z.return=h,h=z)}return i(h);case K:l:{for(Y=y.key;o!==null;){if(o.key===Y)if(o.tag===4&&o.stateNode.containerInfo===y.containerInfo&&o.stateNode.implementation===y.implementation){e(h,o.sibling),z=u(o,y.children||[]),z.return=h,h=z;break l}else{e(h,o);break}else t(h,o);o=o.sibling}z=Ei(y,h.mode,z),z.return=h,h=z}return i(h);case Vl:return y=Be(y),ml(h,o,y,z)}if(pt(y))return C(h,o,y,z);if(Kl(y)){if(Y=Kl(y),typeof Y!="function")throw Error(r(150));return y=Y.call(y),X(h,o,y,z)}if(typeof y.then=="function")return ml(h,o,Wu(y),z);if(y.$$typeof===Gl)return ml(h,o,Ju(h,y),z);Fu(h,y)}return typeof y=="string"&&y!==""||typeof y=="number"||typeof y=="bigint"?(y=""+y,o!==null&&o.tag===6?(e(h,o.sibling),z=u(o,y),z.return=h,h=z):(e(h,o),z=Ai(y,h.mode,z),z.return=h,h=z),i(h)):e(h,o)}return function(h,o,y,z){try{wa=0;var Y=ml(h,o,y,z);return da=null,Y}catch(q){if(q===oa||q===ku)throw q;var nl=at(29,q,null,h.mode);return nl.lanes=z,nl.return=h,nl}finally{}}}var Ye=Ns(!0),Ms=Ns(!1),ne=!1;function Bi(l){l.updateQueue={baseState:l.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function qi(l,t){l=l.updateQueue,t.updateQueue===l&&(t.updateQueue={baseState:l.baseState,firstBaseUpdate:l.firstBaseUpdate,lastBaseUpdate:l.lastBaseUpdate,shared:l.shared,callbacks:null})}function ie(l){return{lane:l,tag:0,payload:null,callback:null,next:null}}function ce(l,t,e){var a=l.updateQueue;if(a===null)return null;if(a=a.shared,(cl&2)!==0){var u=a.pending;return u===null?t.next=t:(t.next=u.next,u.next=t),a.pending=t,t=Zu(l),hs(l,null,e),t}return Qu(l,a,t,e),Zu(l)}function $a(l,t,e){if(t=t.updateQueue,t!==null&&(t=t.shared,(e&4194048)!==0)){var a=t.lanes;a&=l.pendingLanes,e|=a,t.lanes=e,Tf(l,e)}}function Yi(l,t){var e=l.updateQueue,a=l.alternate;if(a!==null&&(a=a.updateQueue,e===a)){var u=null,n=null;if(e=e.firstBaseUpdate,e!==null){do{var i={lane:e.lane,tag:e.tag,payload:e.payload,callback:null,next:null};n===null?u=n=i:n=n.next=i,e=e.next}while(e!==null);n===null?u=n=t:n=n.next=t}else u=n=t;e={baseState:a.baseState,firstBaseUpdate:u,lastBaseUpdate:n,shared:a.shared,callbacks:a.callbacks},l.updateQueue=e;return}l=e.lastBaseUpdate,l===null?e.firstBaseUpdate=t:l.next=t,e.lastBaseUpdate=t}var Gi=!1;function Wa(){if(Gi){var l=sa;if(l!==null)throw l}}function Fa(l,t,e,a){Gi=!1;var u=l.updateQueue;ne=!1;var n=u.firstBaseUpdate,i=u.lastBaseUpdate,c=u.shared.pending;if(c!==null){u.shared.pending=null;var s=c,v=s.next;s.next=null,i===null?n=v:i.next=v,i=s;var b=l.alternate;b!==null&&(b=b.updateQueue,c=b.lastBaseUpdate,c!==i&&(c===null?b.firstBaseUpdate=v:c.next=v,b.lastBaseUpdate=s))}if(n!==null){var A=u.baseState;i=0,b=v=s=null,c=n;do{var g=c.lane&-536870913,S=g!==c.lane;if(S?(I&g)===g:(a&g)===g){g!==0&&g===fa&&(Gi=!0),b!==null&&(b=b.next={lane:0,tag:c.tag,payload:c.payload,callback:null,next:null});l:{var C=l,X=c;g=t;var ml=e;switch(X.tag){case 1:if(C=X.payload,typeof C=="function"){A=C.call(ml,A,g);break l}A=C;break l;case 3:C.flags=C.flags&-65537|128;case 0:if(C=X.payload,g=typeof C=="function"?C.call(ml,A,g):C,g==null)break l;A=_({},A,g);break l;case 2:ne=!0}}g=c.callback,g!==null&&(l.flags|=64,S&&(l.flags|=8192),S=u.callbacks,S===null?u.callbacks=[g]:S.push(g))}else S={lane:g,tag:c.tag,payload:c.payload,callback:c.callback,next:null},b===null?(v=b=S,s=A):b=b.next=S,i|=g;if(c=c.next,c===null){if(c=u.shared.pending,c===null)break;S=c,c=S.next,S.next=null,u.lastBaseUpdate=S,u.shared.pending=null}}while(!0);b===null&&(s=A),u.baseState=s,u.firstBaseUpdate=v,u.lastBaseUpdate=b,n===null&&(u.shared.lanes=0),re|=i,l.lanes=i,l.memoizedState=A}}function Ds(l,t){if(typeof l!="function")throw Error(r(191,l));l.call(t)}function Cs(l,t){var e=l.callbacks;if(e!==null)for(l.callbacks=null,l=0;ln?n:8;var i=T.T,c={};T.T=c,uc(l,!1,t,e);try{var s=u(),v=T.S;if(v!==null&&v(c,s),s!==null&&typeof s=="object"&&typeof s.then=="function"){var b=Xh(s,a);lu(l,t,b,ft(l))}else lu(l,t,a,ft(l))}catch(A){lu(l,t,{then:function(){},status:"rejected",reason:A},ft())}finally{j.p=n,i!==null&&c.types!==null&&(i.types=c.types),T.T=i}}function Jh(){}function ec(l,t,e,a){if(l.tag!==5)throw Error(r(476));var u=oo(l).queue;so(l,u,t,Q,e===null?Jh:function(){return ro(l),e(a)})}function oo(l){var t=l.memoizedState;if(t!==null)return t;t={memoizedState:Q,baseState:Q,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Zt,lastRenderedState:Q},next:null};var e={};return t.next={memoizedState:e,baseState:e,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Zt,lastRenderedState:e},next:null},l.memoizedState=t,l=l.alternate,l!==null&&(l.memoizedState=t),t}function ro(l){var t=oo(l);t.next===null&&(t=l.alternate.memoizedState),lu(l,t.next.queue,{},ft())}function ac(){return Bl(gu)}function ho(){return xl().memoizedState}function mo(){return xl().memoizedState}function wh(l){for(var t=l.return;t!==null;){switch(t.tag){case 24:case 3:var e=ft();l=ie(e);var a=ce(t,l,e);a!==null&&(Il(a,t,e),$a(a,t,e)),t={cache:Ci()},l.payload=t;return}t=t.return}}function kh(l,t,e){var a=ft();e={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null},fn(l)?vo(t,e):(e=Ti(l,t,e,a),e!==null&&(Il(e,l,a),go(e,t,a)))}function yo(l,t,e){var a=ft();lu(l,t,e,a)}function lu(l,t,e,a){var u={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null};if(fn(l))vo(t,u);else{var n=l.alternate;if(l.lanes===0&&(n===null||n.lanes===0)&&(n=t.lastRenderedReducer,n!==null))try{var i=t.lastRenderedState,c=n(i,e);if(u.hasEagerState=!0,u.eagerState=c,et(c,i))return Qu(l,t,u,0),vl===null&&Xu(),!1}catch{}finally{}if(e=Ti(l,t,u,a),e!==null)return Il(e,l,a),go(e,t,a),!0}return!1}function uc(l,t,e,a){if(a={lane:2,revertLane:Bc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},fn(l)){if(t)throw Error(r(479))}else t=Ti(l,e,a,2),t!==null&&Il(t,l,2)}function fn(l){var t=l.alternate;return l===V||t!==null&&t===V}function vo(l,t){ha=ln=!0;var e=l.pending;e===null?t.next=t:(t.next=e.next,e.next=t),l.pending=t}function go(l,t,e){if((e&4194048)!==0){var a=t.lanes;a&=l.pendingLanes,e|=a,t.lanes=e,Tf(l,e)}}var tu={readContext:Bl,use:an,useCallback:Tl,useContext:Tl,useEffect:Tl,useImperativeHandle:Tl,useLayoutEffect:Tl,useInsertionEffect:Tl,useMemo:Tl,useReducer:Tl,useRef:Tl,useState:Tl,useDebugValue:Tl,useDeferredValue:Tl,useTransition:Tl,useSyncExternalStore:Tl,useId:Tl,useHostTransitionStatus:Tl,useFormState:Tl,useActionState:Tl,useOptimistic:Tl,useMemoCache:Tl,useCacheRefresh:Tl};tu.useEffectEvent=Tl;var So={readContext:Bl,use:an,useCallback:function(l,t){return Zl().memoizedState=[l,t===void 0?null:t],l},useContext:Bl,useEffect:lo,useImperativeHandle:function(l,t,e){e=e!=null?e.concat([l]):null,nn(4194308,4,uo.bind(null,t,l),e)},useLayoutEffect:function(l,t){return nn(4194308,4,l,t)},useInsertionEffect:function(l,t){nn(4,2,l,t)},useMemo:function(l,t){var e=Zl();t=t===void 0?null:t;var a=l();if(Ge){It(!0);try{l()}finally{It(!1)}}return e.memoizedState=[a,t],a},useReducer:function(l,t,e){var a=Zl();if(e!==void 0){var u=e(t);if(Ge){It(!0);try{e(t)}finally{It(!1)}}}else u=t;return a.memoizedState=a.baseState=u,l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:l,lastRenderedState:u},a.queue=l,l=l.dispatch=kh.bind(null,V,l),[a.memoizedState,l]},useRef:function(l){var t=Zl();return l={current:l},t.memoizedState=l},useState:function(l){l=Fi(l);var t=l.queue,e=yo.bind(null,V,t);return t.dispatch=e,[l.memoizedState,e]},useDebugValue:lc,useDeferredValue:function(l,t){var e=Zl();return tc(e,l,t)},useTransition:function(){var l=Fi(!1);return l=so.bind(null,V,l.queue,!0,!1),Zl().memoizedState=l,[!1,l]},useSyncExternalStore:function(l,t,e){var a=V,u=Zl();if(el){if(e===void 0)throw Error(r(407));e=e()}else{if(e=t(),vl===null)throw Error(r(349));(I&127)!==0||Ys(a,t,e)}u.memoizedState=e;var n={value:e,getSnapshot:t};return u.queue=n,lo(Xs.bind(null,a,n,l),[l]),a.flags|=2048,ya(9,{destroy:void 0},Gs.bind(null,a,n,e,t),null),e},useId:function(){var l=Zl(),t=vl.identifierPrefix;if(el){var e=Mt,a=Nt;e=(a&~(1<<32-tt(a)-1)).toString(32)+e,t="_"+t+"R_"+e,e=tn++,0<\/script>",n=n.removeChild(n.firstChild);break;case"select":n=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?n.multiple=!0:a.size&&(n.size=a.size);break;default:n=typeof a.is=="string"?i.createElement(u,{is:a.is}):i.createElement(u)}}n[Rl]=t,n[Jl]=a;l:for(i=t.child;i!==null;){if(i.tag===5||i.tag===6)n.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===t)break l;for(;i.sibling===null;){if(i.return===null||i.return===t)break l;i=i.return}i.sibling.return=i.return,i=i.sibling}t.stateNode=n;l:switch(Yl(n,u,a),u){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break l;case"img":a=!0;break l;default:a=!1}a&&Vt(t)}}return Sl(t),Sc(t,t.type,l===null?null:l.memoizedProps,t.pendingProps,e),null;case 6:if(l&&t.stateNode!=null)l.memoizedProps!==a&&Vt(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(l=k.current,ia(t)){if(l=t.stateNode,e=t.memoizedProps,a=null,u=Hl,u!==null)switch(u.tag){case 27:case 5:a=u.memoizedProps}l[Rl]=t,l=!!(l.nodeValue===e||a!==null&&a.suppressHydrationWarning===!0||qd(l.nodeValue,e)),l||ae(t,!0)}else l=On(l).createTextNode(a),l[Rl]=t,t.stateNode=l}return Sl(t),null;case 31:if(e=t.memoizedState,l===null||l.memoizedState!==null){if(a=ia(t),e!==null){if(l===null){if(!a)throw Error(r(318));if(l=t.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(r(557));l[Rl]=t}else Ce(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Sl(t),l=!1}else e=Oi(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=e),l=!0;if(!l)return t.flags&256?(nt(t),t):(nt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Sl(t),null;case 13:if(a=t.memoizedState,l===null||l.memoizedState!==null&&l.memoizedState.dehydrated!==null){if(u=ia(t),a!==null&&a.dehydrated!==null){if(l===null){if(!u)throw Error(r(318));if(u=t.memoizedState,u=u!==null?u.dehydrated:null,!u)throw Error(r(317));u[Rl]=t}else Ce(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Sl(t),u=!1}else u=Oi(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=u),u=!0;if(!u)return t.flags&256?(nt(t),t):(nt(t),null)}return nt(t),(t.flags&128)!==0?(t.lanes=e,t):(e=a!==null,l=l!==null&&l.memoizedState!==null,e&&(a=t.child,u=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(u=a.alternate.memoizedState.cachePool.pool),n=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(n=a.memoizedState.cachePool.pool),n!==u&&(a.flags|=2048)),e!==l&&e&&(t.child.flags|=8192),hn(t,t.updateQueue),Sl(t),null);case 4:return Al(),l===null&&Xc(t.stateNode.containerInfo),Sl(t),null;case 10:return Xt(t.type),Sl(t),null;case 19:if(E(El),a=t.memoizedState,a===null)return Sl(t),null;if(u=(t.flags&128)!==0,n=a.rendering,n===null)if(u)au(a,!1);else{if(zl!==0||l!==null&&(l.flags&128)!==0)for(l=t.child;l!==null;){if(n=Pu(l),n!==null){for(t.flags|=128,au(a,!1),l=n.updateQueue,t.updateQueue=l,hn(t,l),t.subtreeFlags=0,l=e,e=t.child;e!==null;)ms(e,l),e=e.sibling;return N(El,El.current&1|2),el&&Yt(t,a.treeForkCount),t.child}l=l.sibling}a.tail!==null&&Pl()>Sn&&(t.flags|=128,u=!0,au(a,!1),t.lanes=4194304)}else{if(!u)if(l=Pu(n),l!==null){if(t.flags|=128,u=!0,l=l.updateQueue,t.updateQueue=l,hn(t,l),au(a,!0),a.tail===null&&a.tailMode==="hidden"&&!n.alternate&&!el)return Sl(t),null}else 2*Pl()-a.renderingStartTime>Sn&&e!==536870912&&(t.flags|=128,u=!0,au(a,!1),t.lanes=4194304);a.isBackwards?(n.sibling=t.child,t.child=n):(l=a.last,l!==null?l.sibling=n:t.child=n,a.last=n)}return a.tail!==null?(l=a.tail,a.rendering=l,a.tail=l.sibling,a.renderingStartTime=Pl(),l.sibling=null,e=El.current,N(El,u?e&1|2:e&1),el&&Yt(t,a.treeForkCount),l):(Sl(t),null);case 22:case 23:return nt(t),Qi(),a=t.memoizedState!==null,l!==null?l.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(e&536870912)!==0&&(t.flags&128)===0&&(Sl(t),t.subtreeFlags&6&&(t.flags|=8192)):Sl(t),e=t.updateQueue,e!==null&&hn(t,e.retryQueue),e=null,l!==null&&l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(e=l.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==e&&(t.flags|=2048),l!==null&&E(He),null;case 24:return e=null,l!==null&&(e=l.memoizedState.cache),t.memoizedState.cache!==e&&(t.flags|=2048),Xt(_l),Sl(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function Ph(l,t){switch(_i(t),t.tag){case 1:return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 3:return Xt(_l),Al(),l=t.flags,(l&65536)!==0&&(l&128)===0?(t.flags=l&-65537|128,t):null;case 26:case 27:case 5:return Au(t),null;case 31:if(t.memoizedState!==null){if(nt(t),t.alternate===null)throw Error(r(340));Ce()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 13:if(nt(t),l=t.memoizedState,l!==null&&l.dehydrated!==null){if(t.alternate===null)throw Error(r(340));Ce()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 19:return E(El),null;case 4:return Al(),null;case 10:return Xt(t.type),null;case 22:case 23:return nt(t),Qi(),l!==null&&E(He),l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 24:return Xt(_l),null;case 25:return null;default:return null}}function Zo(l,t){switch(_i(t),t.tag){case 3:Xt(_l),Al();break;case 26:case 27:case 5:Au(t);break;case 4:Al();break;case 31:t.memoizedState!==null&&nt(t);break;case 13:nt(t);break;case 19:E(El);break;case 10:Xt(t.type);break;case 22:case 23:nt(t),Qi(),l!==null&&E(He);break;case 24:Xt(_l)}}function uu(l,t){try{var e=t.updateQueue,a=e!==null?e.lastEffect:null;if(a!==null){var u=a.next;e=u;do{if((e.tag&l)===l){a=void 0;var n=e.create,i=e.inst;a=n(),i.destroy=a}e=e.next}while(e!==u)}}catch(c){ol(t,t.return,c)}}function oe(l,t,e){try{var a=t.updateQueue,u=a!==null?a.lastEffect:null;if(u!==null){var n=u.next;a=n;do{if((a.tag&l)===l){var i=a.inst,c=i.destroy;if(c!==void 0){i.destroy=void 0,u=t;var s=e,v=c;try{v()}catch(b){ol(u,s,b)}}}a=a.next}while(a!==n)}}catch(b){ol(t,t.return,b)}}function Lo(l){var t=l.updateQueue;if(t!==null){var e=l.stateNode;try{Cs(t,e)}catch(a){ol(l,l.return,a)}}}function Vo(l,t,e){e.props=Xe(l.type,l.memoizedProps),e.state=l.memoizedState;try{e.componentWillUnmount()}catch(a){ol(l,t,a)}}function nu(l,t){try{var e=l.ref;if(e!==null){switch(l.tag){case 26:case 27:case 5:var a=l.stateNode;break;case 30:a=l.stateNode;break;default:a=l.stateNode}typeof e=="function"?l.refCleanup=e(a):e.current=a}}catch(u){ol(l,t,u)}}function Dt(l,t){var e=l.ref,a=l.refCleanup;if(e!==null)if(typeof a=="function")try{a()}catch(u){ol(l,t,u)}finally{l.refCleanup=null,l=l.alternate,l!=null&&(l.refCleanup=null)}else if(typeof e=="function")try{e(null)}catch(u){ol(l,t,u)}else e.current=null}function Ko(l){var t=l.type,e=l.memoizedProps,a=l.stateNode;try{l:switch(t){case"button":case"input":case"select":case"textarea":e.autoFocus&&a.focus();break l;case"img":e.src?a.src=e.src:e.srcSet&&(a.srcset=e.srcSet)}}catch(u){ol(l,l.return,u)}}function bc(l,t,e){try{var a=l.stateNode;Tm(a,l.type,e,t),a[Jl]=t}catch(u){ol(l,l.return,u)}}function Jo(l){return l.tag===5||l.tag===3||l.tag===26||l.tag===27&&ge(l.type)||l.tag===4}function pc(l){l:for(;;){for(;l.sibling===null;){if(l.return===null||Jo(l.return))return null;l=l.return}for(l.sibling.return=l.return,l=l.sibling;l.tag!==5&&l.tag!==6&&l.tag!==18;){if(l.tag===27&&ge(l.type)||l.flags&2||l.child===null||l.tag===4)continue l;l.child.return=l,l=l.child}if(!(l.flags&2))return l.stateNode}}function Tc(l,t,e){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?(e.nodeType===9?e.body:e.nodeName==="HTML"?e.ownerDocument.body:e).insertBefore(l,t):(t=e.nodeType===9?e.body:e.nodeName==="HTML"?e.ownerDocument.body:e,t.appendChild(l),e=e._reactRootContainer,e!=null||t.onclick!==null||(t.onclick=Ht));else if(a!==4&&(a===27&&ge(l.type)&&(e=l.stateNode,t=null),l=l.child,l!==null))for(Tc(l,t,e),l=l.sibling;l!==null;)Tc(l,t,e),l=l.sibling}function mn(l,t,e){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?e.insertBefore(l,t):e.appendChild(l);else if(a!==4&&(a===27&&ge(l.type)&&(e=l.stateNode),l=l.child,l!==null))for(mn(l,t,e),l=l.sibling;l!==null;)mn(l,t,e),l=l.sibling}function wo(l){var t=l.stateNode,e=l.memoizedProps;try{for(var a=l.type,u=t.attributes;u.length;)t.removeAttributeNode(u[0]);Yl(t,a,e),t[Rl]=l,t[Jl]=e}catch(n){ol(l,l.return,n)}}var Kt=!1,Nl=!1,zc=!1,ko=typeof WeakSet=="function"?WeakSet:Set,Ul=null;function lm(l,t){if(l=l.containerInfo,Lc=Hn,l=ns(l),yi(l)){if("selectionStart"in l)var e={start:l.selectionStart,end:l.selectionEnd};else l:{e=(e=l.ownerDocument)&&e.defaultView||window;var a=e.getSelection&&e.getSelection();if(a&&a.rangeCount!==0){e=a.anchorNode;var u=a.anchorOffset,n=a.focusNode;a=a.focusOffset;try{e.nodeType,n.nodeType}catch{e=null;break l}var i=0,c=-1,s=-1,v=0,b=0,A=l,g=null;t:for(;;){for(var S;A!==e||u!==0&&A.nodeType!==3||(c=i+u),A!==n||a!==0&&A.nodeType!==3||(s=i+a),A.nodeType===3&&(i+=A.nodeValue.length),(S=A.firstChild)!==null;)g=A,A=S;for(;;){if(A===l)break t;if(g===e&&++v===u&&(c=i),g===n&&++b===a&&(s=i),(S=A.nextSibling)!==null)break;A=g,g=A.parentNode}A=S}e=c===-1||s===-1?null:{start:c,end:s}}else e=null}e=e||{start:0,end:0}}else e=null;for(Vc={focusedElem:l,selectionRange:e},Hn=!1,Ul=t;Ul!==null;)if(t=Ul,l=t.child,(t.subtreeFlags&1028)!==0&&l!==null)l.return=t,Ul=l;else for(;Ul!==null;){switch(t=Ul,n=t.alternate,l=t.flags,t.tag){case 0:if((l&4)!==0&&(l=t.updateQueue,l=l!==null?l.events:null,l!==null))for(e=0;e title"))),Yl(n,a,e),n[Rl]=l,Cl(n),a=n;break l;case"link":var i=lr("link","href",u).get(a+(e.href||""));if(i){for(var c=0;cml&&(i=ml,ml=X,X=i);var h=as(c,X),o=as(c,ml);if(h&&o&&(S.rangeCount!==1||S.anchorNode!==h.node||S.anchorOffset!==h.offset||S.focusNode!==o.node||S.focusOffset!==o.offset)){var y=A.createRange();y.setStart(h.node,h.offset),S.removeAllRanges(),X>ml?(S.addRange(y),S.extend(o.node,o.offset)):(y.setEnd(o.node,o.offset),S.addRange(y))}}}}for(A=[],S=c;S=S.parentNode;)S.nodeType===1&&A.push({element:S,left:S.scrollLeft,top:S.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;ce?32:e,T.T=null,e=Nc,Nc=null;var n=me,i=Wt;if(Dl=0,pa=me=null,Wt=0,(cl&6)!==0)throw Error(r(331));var c=cl;if(cl|=4,nd(n.current),ed(n,n.current,i,e),cl=c,du(0,!1),lt&&typeof lt.onPostCommitFiberRoot=="function")try{lt.onPostCommitFiberRoot(Na,n)}catch{}return!0}finally{j.p=u,T.T=a,Ad(l,t)}}function xd(l,t,e){t=ht(e,t),t=fc(l.stateNode,t,2),l=ce(l,t,2),l!==null&&(Da(l,2),Ct(l))}function ol(l,t,e){if(l.tag===3)xd(l,l,e);else for(;t!==null;){if(t.tag===3){xd(t,l,e);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(he===null||!he.has(a))){l=ht(e,l),e=_o(2),a=ce(t,e,2),a!==null&&(jo(e,a,t,l),Da(a,2),Ct(a));break}}t=t.return}}function Uc(l,t,e){var a=l.pingCache;if(a===null){a=l.pingCache=new am;var u=new Set;a.set(t,u)}else u=a.get(t),u===void 0&&(u=new Set,a.set(t,u));u.has(e)||(xc=!0,u.add(e),l=fm.bind(null,l,t,e),t.then(l,l))}function fm(l,t,e){var a=l.pingCache;a!==null&&a.delete(t),l.pingedLanes|=l.suspendedLanes&e,l.warmLanes&=~e,vl===l&&(I&e)===e&&(zl===4||zl===3&&(I&62914560)===I&&300>Pl()-gn?(cl&2)===0&&Ta(l,0):_c|=e,ba===I&&(ba=0)),Ct(l)}function _d(l,t){t===0&&(t=bf()),l=Me(l,t),l!==null&&(Da(l,t),Ct(l))}function sm(l){var t=l.memoizedState,e=0;t!==null&&(e=t.retryLane),_d(l,e)}function om(l,t){var e=0;switch(l.tag){case 31:case 13:var a=l.stateNode,u=l.memoizedState;u!==null&&(e=u.retryLane);break;case 19:a=l.stateNode;break;case 22:a=l.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),_d(l,e)}function dm(l,t){return Jn(l,t)}var En=null,Aa=null,Rc=!1,xn=!1,Hc=!1,ve=0;function Ct(l){l!==Aa&&l.next===null&&(Aa===null?En=Aa=l:Aa=Aa.next=l),xn=!0,Rc||(Rc=!0,hm())}function du(l,t){if(!Hc&&xn){Hc=!0;do for(var e=!1,a=En;a!==null;){if(l!==0){var u=a.pendingLanes;if(u===0)var n=0;else{var i=a.suspendedLanes,c=a.pingedLanes;n=(1<<31-tt(42|l)+1)-1,n&=u&~(i&~c),n=n&201326741?n&201326741|1:n?n|2:0}n!==0&&(e=!0,Md(a,n))}else n=I,n=Ou(a,a===vl?n:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(n&3)===0||Ma(a,n)||(e=!0,Md(a,n));a=a.next}while(e);Hc=!1}}function rm(){jd()}function jd(){xn=Rc=!1;var l=0;ve!==0&&Am()&&(l=ve);for(var t=Pl(),e=null,a=En;a!==null;){var u=a.next,n=Od(a,t);n===0?(a.next=null,e===null?En=u:e.next=u,u===null&&(Aa=e)):(e=a,(l!==0||(n&3)!==0)&&(xn=!0)),a=u}Dl!==0&&Dl!==5||du(l),ve!==0&&(ve=0)}function Od(l,t){for(var e=l.suspendedLanes,a=l.pingedLanes,u=l.expirationTimes,n=l.pendingLanes&-62914561;0c)break;var b=s.transferSize,A=s.initiatorType;b&&Yd(A)&&(s=s.responseEnd,i+=b*(s"u"?null:document;function Wd(l,t,e){var a=Ea;if(a&&typeof t=="string"&&t){var u=dt(t);u='link[rel="'+l+'"][href="'+u+'"]',typeof e=="string"&&(u+='[crossorigin="'+e+'"]'),$d.has(u)||($d.add(u),l={rel:l,crossOrigin:e,href:t},a.querySelector(u)===null&&(t=a.createElement("link"),Yl(t,"link",l),Cl(t),a.head.appendChild(t)))}}function Cm(l){Ft.D(l),Wd("dns-prefetch",l,null)}function Um(l,t){Ft.C(l,t),Wd("preconnect",l,t)}function Rm(l,t,e){Ft.L(l,t,e);var a=Ea;if(a&&l&&t){var u='link[rel="preload"][as="'+dt(t)+'"]';t==="image"&&e&&e.imageSrcSet?(u+='[imagesrcset="'+dt(e.imageSrcSet)+'"]',typeof e.imageSizes=="string"&&(u+='[imagesizes="'+dt(e.imageSizes)+'"]')):u+='[href="'+dt(l)+'"]';var n=u;switch(t){case"style":n=xa(l);break;case"script":n=_a(l)}bt.has(n)||(l=_({rel:"preload",href:t==="image"&&e&&e.imageSrcSet?void 0:l,as:t},e),bt.set(n,l),a.querySelector(u)!==null||t==="style"&&a.querySelector(yu(n))||t==="script"&&a.querySelector(vu(n))||(t=a.createElement("link"),Yl(t,"link",l),Cl(t),a.head.appendChild(t)))}}function Hm(l,t){Ft.m(l,t);var e=Ea;if(e&&l){var a=t&&typeof t.as=="string"?t.as:"script",u='link[rel="modulepreload"][as="'+dt(a)+'"][href="'+dt(l)+'"]',n=u;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":n=_a(l)}if(!bt.has(n)&&(l=_({rel:"modulepreload",href:l},t),bt.set(n,l),e.querySelector(u)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(e.querySelector(vu(n)))return}a=e.createElement("link"),Yl(a,"link",l),Cl(a),e.head.appendChild(a)}}}function Bm(l,t,e){Ft.S(l,t,e);var a=Ea;if(a&&l){var u=we(a).hoistableStyles,n=xa(l);t=t||"default";var i=u.get(n);if(!i){var c={loading:0,preload:null};if(i=a.querySelector(yu(n)))c.loading=5;else{l=_({rel:"stylesheet",href:l,"data-precedence":t},e),(e=bt.get(n))&&Fc(l,e);var s=i=a.createElement("link");Cl(s),Yl(s,"link",l),s._p=new Promise(function(v,b){s.onload=v,s.onerror=b}),s.addEventListener("load",function(){c.loading|=1}),s.addEventListener("error",function(){c.loading|=2}),c.loading|=4,Mn(i,t,a)}i={type:"stylesheet",instance:i,count:1,state:c},u.set(n,i)}}}function qm(l,t){Ft.X(l,t);var e=Ea;if(e&&l){var a=we(e).hoistableScripts,u=_a(l),n=a.get(u);n||(n=e.querySelector(vu(u)),n||(l=_({src:l,async:!0},t),(t=bt.get(u))&&Ic(l,t),n=e.createElement("script"),Cl(n),Yl(n,"link",l),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Ym(l,t){Ft.M(l,t);var e=Ea;if(e&&l){var a=we(e).hoistableScripts,u=_a(l),n=a.get(u);n||(n=e.querySelector(vu(u)),n||(l=_({src:l,async:!0,type:"module"},t),(t=bt.get(u))&&Ic(l,t),n=e.createElement("script"),Cl(n),Yl(n,"link",l),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Fd(l,t,e,a){var u=(u=k.current)?Nn(u):null;if(!u)throw Error(r(446));switch(l){case"meta":case"title":return null;case"style":return typeof e.precedence=="string"&&typeof e.href=="string"?(t=xa(e.href),e=we(u).hoistableStyles,a=e.get(t),a||(a={type:"style",instance:null,count:0,state:null},e.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(e.rel==="stylesheet"&&typeof e.href=="string"&&typeof e.precedence=="string"){l=xa(e.href);var n=we(u).hoistableStyles,i=n.get(l);if(i||(u=u.ownerDocument||u,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},n.set(l,i),(n=u.querySelector(yu(l)))&&!n._p&&(i.instance=n,i.state.loading=5),bt.has(l)||(e={rel:"preload",as:"style",href:e.href,crossOrigin:e.crossOrigin,integrity:e.integrity,media:e.media,hrefLang:e.hrefLang,referrerPolicy:e.referrerPolicy},bt.set(l,e),n||Gm(u,l,e,i.state))),t&&a===null)throw Error(r(528,""));return i}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=e.async,e=e.src,typeof e=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=_a(e),e=we(u).hoistableScripts,a=e.get(t),a||(a={type:"script",instance:null,count:0,state:null},e.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,l))}}function xa(l){return'href="'+dt(l)+'"'}function yu(l){return'link[rel="stylesheet"]['+l+"]"}function Id(l){return _({},l,{"data-precedence":l.precedence,precedence:null})}function Gm(l,t,e,a){l.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=l.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),Yl(t,"link",e),Cl(t),l.head.appendChild(t))}function _a(l){return'[src="'+dt(l)+'"]'}function vu(l){return"script[async]"+l}function Pd(l,t,e){if(t.count++,t.instance===null)switch(t.type){case"style":var a=l.querySelector('style[data-href~="'+dt(e.href)+'"]');if(a)return t.instance=a,Cl(a),a;var u=_({},e,{"data-href":e.href,"data-precedence":e.precedence,href:null,precedence:null});return a=(l.ownerDocument||l).createElement("style"),Cl(a),Yl(a,"style",u),Mn(a,e.precedence,l),t.instance=a;case"stylesheet":u=xa(e.href);var n=l.querySelector(yu(u));if(n)return t.state.loading|=4,t.instance=n,Cl(n),n;a=Id(e),(u=bt.get(u))&&Fc(a,u),n=(l.ownerDocument||l).createElement("link"),Cl(n);var i=n;return i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),Yl(n,"link",a),t.state.loading|=4,Mn(n,e.precedence,l),t.instance=n;case"script":return n=_a(e.src),(u=l.querySelector(vu(n)))?(t.instance=u,Cl(u),u):(a=e,(u=bt.get(n))&&(a=_({},e),Ic(a,u)),l=l.ownerDocument||l,u=l.createElement("script"),Cl(u),Yl(u,"link",a),l.head.appendChild(u),t.instance=u);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,Mn(a,e.precedence,l));return t.instance}function Mn(l,t,e){for(var a=e.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),u=a.length?a[a.length-1]:null,n=u,i=0;i title"):null)}function Xm(l,t,e){if(e===1||t.itemProp!=null)return!1;switch(l){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;switch(t.rel){case"stylesheet":return l=t.disabled,typeof t.precedence=="string"&&l==null;default:return!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 er(l){return!(l.type==="stylesheet"&&(l.state.loading&3)===0)}function Qm(l,t,e,a){if(e.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(e.state.loading&4)===0){if(e.instance===null){var u=xa(a.href),n=t.querySelector(yu(u));if(n){t=n._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(l.count++,l=Cn.bind(l),t.then(l,l)),e.state.loading|=4,e.instance=n,Cl(n);return}n=t.ownerDocument||t,a=Id(a),(u=bt.get(u))&&Fc(a,u),n=n.createElement("link"),Cl(n);var i=n;i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),Yl(n,"link",a),e.instance=n}l.stylesheets===null&&(l.stylesheets=new Map),l.stylesheets.set(e,t),(t=e.state.preload)&&(e.state.loading&3)===0&&(l.count++,e=Cn.bind(l),t.addEventListener("load",e),t.addEventListener("error",e))}}var Pc=0;function Zm(l,t){return l.stylesheets&&l.count===0&&Rn(l,l.stylesheets),0Pc?50:800)+t);return l.unsuspend=e,function(){l.unsuspend=null,clearTimeout(a),clearTimeout(u)}}:null}function Cn(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Rn(this,this.stylesheets);else if(this.unsuspend){var l=this.unsuspend;this.unsuspend=null,l()}}}var Un=null;function Rn(l,t){l.stylesheets=null,l.unsuspend!==null&&(l.count++,Un=new Map,t.forEach(Lm,l),Un=null,Cn.call(l))}function Lm(l,t){if(!(t.state.loading&4)){var e=Un.get(l);if(e)var a=e.get(null);else{e=new Map,Un.set(l,e);for(var u=l.querySelectorAll("link[data-precedence],style[data-precedence]"),n=0;n"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(m)}catch(H){console.error(H)}}return m(),sf.exports=ny(),sf.exports}var cy=iy();const fy=jr(cy),sy="";async function Et(m,H){const D=await fetch(`${sy}${m}`,{...H,credentials:"same-origin",headers:{"Content-Type":"application/json",...H==null?void 0:H.headers}});if(D.status===401)throw window.location.hash="#login",new Error("Unauthorized");if(!D.ok){const r=await D.json().catch(()=>({}));throw new Error(r.error||`HTTP ${D.status}`)}return D.json()}const xt={login:m=>Et("/admin/login",{method:"POST",body:JSON.stringify({token:m})}),signOutEverywhere:()=>Et("/admin/api/sign-out-everywhere",{method:"POST"}),stats:()=>Et("/admin/api/stats"),health:()=>Et("/admin/api/health-indicators"),agents:()=>Et("/admin/api/agents"),requests:(m=1,H="")=>Et(`/admin/api/requests?page=${m}${H}`),apiKeys:()=>Et("/admin/api/api-keys"),createApiKey:m=>Et("/admin/api/api-keys",{method:"POST",body:JSON.stringify({name:m})}),revokeApiKey:m=>Et("/admin/api/api-keys/revoke",{method:"POST",body:JSON.stringify({name:m})}),updateClientTtl:(m,H)=>Et("/admin/api/update-client-ttl",{method:"POST",body:JSON.stringify({clientId:m,tokenTtl:H})}),revokeClient:m=>Et("/admin/api/revoke-client",{method:"POST",body:JSON.stringify({clientId:m})})};function oy({onLogin:m}){const[H,D]=ul.useState(""),[r,O]=ul.useState(""),[G,U]=ul.useState(!1),w=async M=>{M.preventDefault(),O(""),U(!0);try{await xt.login(H),D(""),m()}catch{O("Invalid token.")}finally{U(!1)}};return f.jsx("div",{className:"login-page",children:f.jsxs("div",{className:"login-box",children:[f.jsx("div",{className:"login-logo",children:"GBrain"}),f.jsxs("div",{style:{background:"rgba(136, 170, 255, 0.08)",border:"1px solid rgba(136, 170, 255, 0.2)",borderRadius:8,padding:"14px 16px",marginBottom:20,fontSize:13,lineHeight:1.5,color:"var(--text-secondary)"},children:[f.jsx("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:6},children:"🔒 This is a protected dashboard"}),"Ask your AI agent for the admin login link:",f.jsx("div",{style:{background:"rgba(0,0,0,0.3)",borderRadius:6,padding:"8px 12px",marginTop:8,fontFamily:"var(--font-mono)",fontSize:12,color:"#88aaff",wordBreak:"break-all"},children:'"Give me the GBrain admin login link"'}),f.jsx("div",{style:{marginTop:8,fontSize:12,color:"var(--text-muted)"},children:"Each link is single-use. Your agent generates a fresh one each time."})]}),f.jsxs("details",{style:{marginBottom:16},children:[f.jsx("summary",{style:{cursor:"pointer",fontSize:13,color:"var(--text-muted)"},children:"Or paste bootstrap token manually"}),f.jsxs("form",{onSubmit:w,style:{marginTop:12},children:[f.jsx("div",{style:{marginBottom:12},children:f.jsx("input",{type:"password",placeholder:"Admin Token",value:H,onChange:M=>D(M.target.value)})}),f.jsx("button",{className:"btn btn-primary",style:{width:"100%"},disabled:G,children:G?"Authenticating...":"Submit"}),r&&f.jsx("div",{className:"login-error",children:r})]})]})]})})}function dy(){const[m,H]=ul.useState({connected_agents:0,requests_today:0,active_tokens:0}),[D,r]=ul.useState({expiring_soon:0,error_rate:"0%"}),[O,G]=ul.useState([]),[U,w]=ul.useState("connecting"),M=ul.useRef(null);ul.useEffect(()=>{xt.stats().then(H).catch(()=>{}),xt.health().then(r).catch(()=>{});const R=new EventSource("/admin/events");M.current=R,R.onopen=()=>w("connected"),R.onmessage=x=>{try{const F=JSON.parse(x.data);G(K=>[F,...K].slice(0,50))}catch{}},R.onerror=()=>{w("disconnected"),setTimeout(()=>{w("connecting"),R.close()},3e3)};const _=setInterval(()=>{xt.stats().then(H).catch(()=>{}),xt.health().then(r).catch(()=>{})},3e4);return()=>{R.close(),clearInterval(_)}},[]);const p=R=>{const _=Date.now()-new Date(R).getTime();return _<6e4?`${Math.floor(_/1e3)}s ago`:_<36e5?`${Math.floor(_/6e4)} min ago`:`${Math.floor(_/36e5)}h ago`};return f.jsxs(f.Fragment,{children:[f.jsx("h1",{className:"page-title",children:"Dashboard"}),f.jsxs("div",{style:{display:"flex",gap:24},children:[f.jsxs("div",{style:{flex:1},children:[f.jsxs("div",{className:"metrics",children:[f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:m.connected_agents}),f.jsx("div",{className:"metric-label",children:"Connected Agents"})]}),f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:m.requests_today}),f.jsx("div",{className:"metric-label",children:"Requests Today"})]}),f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:m.active_tokens}),f.jsx("div",{className:"metric-label",children:"Active Tokens"})]})]}),f.jsxs("h2",{className:"section-title",children:["Live Activity",f.jsx("span",{style:{marginLeft:8,fontSize:10,color:U==="connected"?"var(--success)":U==="connecting"?"var(--warning)":"var(--error)"},children:U==="connected"?"● connected":U==="connecting"?"● connecting...":"● disconnected"})]}),f.jsx("div",{className:"feed",children:O.length===0?f.jsx("div",{className:"feed-empty",children:U==="connected"?"No requests yet. Agents will appear when they connect.":"Connecting..."}):f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Agent"}),f.jsx("th",{children:"Operation"}),f.jsx("th",{children:"Scopes"}),f.jsx("th",{children:"Latency"}),f.jsx("th",{children:"Status"}),f.jsx("th",{children:"Time"})]})}),f.jsx("tbody",{children:O.map((R,_)=>f.jsxs("tr",{children:[f.jsx("td",{className:"mono",children:R.agent}),f.jsx("td",{className:"mono",children:R.operation}),f.jsx("td",{children:R.scopes.split(",").map(x=>f.jsx("span",{className:`badge badge-${x.trim()}`,style:{marginRight:4},children:x.trim()},x))}),f.jsxs("td",{className:"mono",children:[R.latency_ms," ms"]}),f.jsx("td",{children:f.jsx("span",{className:`badge badge-${R.status}`,children:R.status})}),f.jsx("td",{style:{color:"var(--text-secondary)"},children:p(R.timestamp)})]},_))})]})})]}),f.jsxs("div",{style:{width:220},children:[f.jsx("h2",{className:"section-title",children:"Token Health"}),f.jsxs("div",{className:"health-panel",children:[f.jsxs("div",{className:"health-row",children:[f.jsx("span",{style:{color:"var(--warning)"},children:"Expiring Soon"}),f.jsx("span",{className:"mono",children:D.expiring_soon})]}),f.jsxs("div",{className:"health-row",children:[f.jsx("span",{style:{color:"var(--error)"},children:"Error Rate"}),f.jsx("span",{className:"mono",children:D.error_rate})]})]})]})]})]})}function ry(m){const H=Math.floor((Date.now()-m.getTime())/1e3);return H<60?"just now":H<3600?`${Math.floor(H/60)}m ago`:H<86400?`${Math.floor(H/3600)}h ago`:`${Math.floor(H/86400)}d ago`}function hy(){const[m,H]=ul.useState([]),[D,r]=ul.useState(!0),[O,G]=ul.useState(!1),[U,w]=ul.useState(null),[M,p]=ul.useState(!1),[R,_]=ul.useState(null),[x,F]=ul.useState(null);ul.useEffect(()=>{K()},[]);const K=()=>{xt.agents().then(H).catch(()=>{})};return f.jsxs(f.Fragment,{children:[f.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:24},children:[f.jsx("h1",{className:"page-title",style:{marginBottom:0},children:"Agents"}),f.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[f.jsxs("label",{style:{fontSize:13,color:"var(--text-secondary)",display:"flex",alignItems:"center",gap:6,cursor:"pointer"},children:[f.jsx("input",{type:"checkbox",checked:D,onChange:al=>r(al.target.checked)})," Hide revoked"]}),f.jsx("button",{className:"btn btn-secondary",onClick:()=>p(!0),children:"+ API Key"}),f.jsx("button",{className:"btn btn-primary",onClick:()=>G(!0),children:"+ OAuth Client"})]})]}),(()=>{const al=m.filter(ll=>!D||ll.status!=="revoked");return m.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:"No agents registered. Register your first agent to get started."}):al.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:'All agents are revoked. Uncheck "Hide revoked" to view them.'}):f.jsxs(f.Fragment,{children:[f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Name"}),f.jsx("th",{children:"Type"}),f.jsx("th",{children:"Scopes"}),f.jsx("th",{children:"Status"}),f.jsx("th",{children:"Requests"}),f.jsx("th",{children:"Last Used"})]})}),f.jsx("tbody",{children:al.map(ll=>f.jsxs("tr",{onClick:()=>F(ll),style:{cursor:"pointer"},children:[f.jsx("td",{style:{fontWeight:500},children:ll.name||ll.client_name}),f.jsx("td",{children:f.jsx("span",{className:`badge ${ll.auth_type==="oauth"?"badge-read":"badge-write"}`,style:{fontSize:11},children:ll.auth_type==="oauth"?"OAuth":"API Key"})}),f.jsx("td",{children:(ll.scope||"").split(" ").filter(Boolean).map(pl=>f.jsx("span",{className:`badge badge-${pl}`,style:{marginRight:4},children:pl},pl))}),f.jsx("td",{children:f.jsx("span",{className:`badge ${ll.status==="active"?"badge-success":"badge-danger"}`,children:ll.status})}),f.jsxs("td",{children:[f.jsx("span",{style:{fontWeight:500},children:ll.requests_today||0}),f.jsxs("span",{style:{color:"var(--text-muted)",fontSize:12},children:[" / ",ll.total_requests||0]})]}),f.jsx("td",{style:{color:"var(--text-secondary)"},children:ll.last_used_at?ry(new Date(ll.last_used_at)):"Never"})]},ll.id))})]}),f.jsxs("div",{style:{color:"var(--text-muted)",fontSize:13,marginTop:12},children:[m.filter(ll=>ll.status==="active").length," active / ",m.length," total"]})]})})(),O&&f.jsx(vy,{onClose:()=>G(!1),onRegistered:al=>{G(!1),w(al),K()}}),U&&f.jsx(gy,{credentials:U,onClose:()=>w(null)}),x&&f.jsx(Sy,{agent:x,onClose:()=>F(null),onRevoked:K}),M&&f.jsx(my,{onClose:()=>p(!1),onCreated:al=>{p(!1),_(al),K()}}),R&&f.jsx(yy,{token:R,onClose:()=>_(null)})]})}function my({onClose:m,onCreated:H}){const[D,r]=ul.useState(""),[O,G]=ul.useState(!1),[U,w]=ul.useState(""),M=async p=>{if(p.preventDefault(),!D.trim()){w("Name required");return}G(!0);try{const R=await xt.createApiKey(D.trim());H({name:R.name,token:R.token})}catch(R){w(R instanceof Error?R.message:"Failed")}finally{G(!1)}};return f.jsx("div",{className:"modal-overlay",onClick:m,children:f.jsxs("form",{className:"modal",onClick:p=>p.stopPropagation(),onSubmit:M,children:[f.jsx("div",{className:"modal-title",children:"Create API Key"}),f.jsx("p",{style:{color:"var(--text-secondary)",fontSize:13,marginBottom:16},children:"API keys use simple bearer token auth. They grant full read+write+admin access. For scoped access, use OAuth clients instead."}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Key Name"}),f.jsx("input",{placeholder:"e.g. claude-code-local",value:D,onChange:p=>r(p.target.value),autoFocus:!0})]}),U&&f.jsx("div",{style:{color:"var(--error)",fontSize:13,marginBottom:12},children:U}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end"},children:[f.jsx("button",{type:"button",className:"btn btn-secondary",onClick:m,children:"Cancel"}),f.jsx("button",{type:"submit",className:"btn btn-primary",disabled:O,children:O?"Creating...":"Create Key"})]})]})})}function yy({token:m,onClose:H}){const D=r=>navigator.clipboard.writeText(r);return f.jsx("div",{className:"modal-overlay",children:f.jsxs("div",{className:"modal",style:{maxWidth:560},children:[f.jsxs("div",{style:{textAlign:"center",marginBottom:16},children:[f.jsx("div",{style:{fontSize:36,color:"var(--success)",marginBottom:8},children:"✓"}),f.jsx("div",{style:{fontSize:20,fontWeight:600},children:"API Key Created"})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Name"}),f.jsx("div",{className:"code-block",children:f.jsx("span",{children:m.name})})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Bearer Token"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:m.token}),f.jsx("button",{className:"copy-btn",onClick:()=>D(m.token),children:"Copy"})]})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Usage"}),f.jsxs("div",{className:"code-block",children:[f.jsx("pre",{style:{whiteSpace:"pre-wrap",margin:0,fontSize:12},children:`Authorization: Bearer ${m.token}`}),f.jsx("button",{className:"copy-btn",onClick:()=>D(`Authorization: Bearer ${m.token}`),children:"Copy"})]})]}),f.jsx("div",{className:"warning-bar",children:"Save this token now. It will not be shown again."}),f.jsx("div",{style:{display:"flex",gap:12,justifyContent:"flex-end",marginTop:20},children:f.jsx("button",{className:"btn btn-primary",onClick:H,children:"Done"})})]})})}function vy({onClose:m,onRegistered:H}){const[D,r]=ul.useState(""),[O,G]=ul.useState({read:!0,write:!1,admin:!1}),[U,w]=ul.useState("86400"),[M,p]=ul.useState(!1),[R,_]=ul.useState(""),x=[{label:"1 hour",value:"3600"},{label:"24 hours",value:"86400"},{label:"7 days",value:"604800"},{label:"30 days",value:"2592000"},{label:"1 year",value:"31536000"},{label:"No expiry",value:"0"}],F=async K=>{if(K.preventDefault(),!D.trim()){_("Name required");return}p(!0),_("");try{const al=Object.entries(O).filter(([,Ml])=>Ml).map(([Ml])=>Ml).join(" "),ll=await fetch("/admin/api/register-client",{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D.trim(),scopes:al,tokenTtl:U==="0"?31536e4:Number(U)})});if(!ll.ok)throw new Error("Registration failed");const pl=await ll.json();H({clientId:pl.clientId,clientSecret:pl.clientSecret,name:D.trim()})}catch(al){_(al instanceof Error?al.message:"Registration failed")}finally{p(!1)}};return f.jsx("div",{className:"modal-overlay",onClick:m,children:f.jsxs("form",{className:"modal",onClick:K=>K.stopPropagation(),onSubmit:F,children:[f.jsx("div",{className:"modal-title",children:"Register Agent"}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Agent Name"}),f.jsx("input",{placeholder:"e.g. perplexity-production",value:D,onChange:K=>r(K.target.value),autoFocus:!0})]}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Scopes"}),f.jsx("div",{className:"checkbox-group",children:["read","write","admin"].map(K=>f.jsxs("label",{className:"checkbox-label",children:[f.jsx("input",{type:"checkbox",checked:O[K],onChange:al=>G(ll=>({...ll,[K]:al.target.checked}))}),K]},K))})]}),f.jsxs("div",{style:{marginBottom:20},children:[f.jsx("label",{children:"Token Lifetime"}),f.jsx("select",{value:U,onChange:K=>w(K.target.value),style:{width:"100%",background:"var(--bg-secondary)",color:"var(--text-primary)",border:"1px solid var(--border)",borderRadius:6,padding:"6px 10px",fontSize:14},children:x.map(K=>f.jsx("option",{value:K.value,children:K.label},K.value))})]}),R&&f.jsx("div",{style:{color:"var(--error)",fontSize:13,marginBottom:12},children:R}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end"},children:[f.jsx("button",{type:"button",className:"btn btn-secondary",onClick:m,children:"Cancel"}),f.jsx("button",{type:"submit",className:"btn btn-primary",disabled:M,children:M?"Registering...":"Register"})]})]})})}function gy({credentials:m,onClose:H}){const D=O=>navigator.clipboard.writeText(O),r=()=>{const O=new Blob([JSON.stringify(m,null,2)],{type:"application/json"}),G=URL.createObjectURL(O),U=document.createElement("a");U.href=G,U.download=`${m.name}-credentials.json`,U.click(),URL.revokeObjectURL(G)};return f.jsx("div",{className:"modal-overlay",children:f.jsxs("div",{className:"modal",style:{maxWidth:560},children:[f.jsxs("div",{style:{textAlign:"center",marginBottom:16},children:[f.jsx("div",{style:{fontSize:36,color:"var(--success)",marginBottom:8},children:"✓"}),f.jsx("div",{style:{fontSize:20,fontWeight:600},children:"Agent Registered"})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Client ID"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:m.clientId}),f.jsx("button",{className:"copy-btn",onClick:()=>D(m.clientId),children:"Copy"})]})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Client Secret"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:m.clientSecret}),f.jsx("button",{className:"copy-btn",onClick:()=>D(m.clientSecret),children:"Copy"})]})]}),f.jsx("div",{className:"warning-bar",children:"Save this secret now. It will not be shown again."}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end",marginTop:20},children:[f.jsx("button",{className:"btn btn-secondary",onClick:r,children:"Download as JSON"}),f.jsx("button",{className:"btn btn-primary",onClick:H,children:"Done"})]})]})})}function Sy({agent:m,onClose:H,onRevoked:D}){const[r,O]=ul.useState("claude-code"),G=_=>navigator.clipboard.writeText(_),U=window.location.origin,w=m.id||m.client_id||"",M=m.auth_type==="oauth",p=m.name||m.client_name||"unknown",R={"claude-code":M?["The user wants to connect GBrain MCP to your context. Here's how.","","# Step 1 — read the client secret from the operator without putting it in shell history.","# read -s suppresses the echo; export keeps it scoped to this shell session.",'read -rs -p "Client Secret: " GBRAIN_CS && echo',"","# Step 2 — mint a token and register GBrain in one go.",`claude mcp add --transport http gbrain ${U}/mcp \\`,` --header "Authorization: Bearer $(curl -s -X POST ${U}/token \\`," -d 'grant_type=client_credentials' \\",` -d 'client_id=${w}' \\`,' --data-urlencode "client_secret=$GBRAIN_CS" \\',` -d 'scope=${m.scope||"read write"}' | jq -r .access_token)"`,"","# Step 3 — clear the secret from this shell.","unset GBRAIN_CS","",`The token will last ${m.token_ttl?m.token_ttl>=86400?Math.floor(m.token_ttl/86400)+" days":Math.floor(m.token_ttl/3600)+" hours":"1 hour (default)"}.`,"","─── Fallback: 2-step curl + paste ───","","If your shell doesn't support read -s, mint the token first, then paste:","",`curl -s -X POST ${U}/token \\`," -d 'grant_type=client_credentials' \\",` -d 'client_id=${w}' \\`," -d 'client_secret=PASTE_YOUR_CLIENT_SECRET_HERE' \\",` -d 'scope=${m.scope||"read write"}' | jq -r .access_token`,"",`claude mcp add --transport http gbrain ${U}/mcp \\`,' --header "Authorization: Bearer PASTE_TOKEN_FROM_ABOVE"',"","# Then run: history -d $((HISTCMD-1)) # zsh: print -s -- '' && fc -p"].join(` +`+a.stack}}var Kn=Object.prototype.hasOwnProperty,Jn=m.unstable_scheduleCallback,wn=m.unstable_cancelCallback,Dr=m.unstable_shouldYield,Cr=m.unstable_requestPaint,Pl=m.unstable_now,Ur=m.unstable_getCurrentPriorityLevel,vf=m.unstable_ImmediatePriority,gf=m.unstable_UserBlockingPriority,Eu=m.unstable_NormalPriority,Rr=m.unstable_LowPriority,Sf=m.unstable_IdlePriority,Hr=m.log,Br=m.unstable_setDisableYieldValue,Na=null,lt=null;function It(l){if(typeof Hr=="function"&&Br(l),lt&&typeof lt.setStrictMode=="function")try{lt.setStrictMode(Na,l)}catch{}}var tt=Math.clz32?Math.clz32:Gr,qr=Math.log,Yr=Math.LN2;function Gr(l){return l>>>=0,l===0?32:31-(qr(l)/Yr|0)|0}var _u=256,xu=262144,ju=4194304;function _e(l){var t=l&42;if(t!==0)return t;switch(l&-l){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 l&261888;case 262144:case 524288:case 1048576:case 2097152:return l&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return l&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return l}}function Ou(l,t,e){var a=l.pendingLanes;if(a===0)return 0;var u=0,n=l.suspendedLanes,i=l.pingedLanes;l=l.warmLanes;var c=a&134217727;return c!==0?(a=c&~n,a!==0?u=_e(a):(i&=c,i!==0?u=_e(i):e||(e=c&~l,e!==0&&(u=_e(e))))):(c=a&~n,c!==0?u=_e(c):i!==0?u=_e(i):e||(e=a&~l,e!==0&&(u=_e(e)))),u===0?0:t!==0&&t!==u&&(t&n)===0&&(n=u&-u,e=t&-t,n>=e||n===32&&(e&4194048)!==0)?t:u}function Ma(l,t){return(l.pendingLanes&~(l.suspendedLanes&~l.pingedLanes)&t)===0}function Xr(l,t){switch(l){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 bf(){var l=ju;return ju<<=1,(ju&62914560)===0&&(ju=4194304),l}function kn(l){for(var t=[],e=0;31>e;e++)t.push(l);return t}function Da(l,t){l.pendingLanes|=t,t!==268435456&&(l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0)}function Qr(l,t,e,a,u,n){var i=l.pendingLanes;l.pendingLanes=e,l.suspendedLanes=0,l.pingedLanes=0,l.warmLanes=0,l.expiredLanes&=e,l.entangledLanes&=e,l.errorRecoveryDisabledLanes&=e,l.shellSuspendCounter=0;var c=l.entanglements,s=l.expirationTimes,v=l.hiddenUpdates;for(e=i&~e;0"u")return null;try{return l.activeElement||l.body}catch{return l.body}}var wr=/[\n"\\]/g;function dt(l){return l.replace(wr,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function li(l,t,e,a,u,n,i,c){l.name="",i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"?l.type=i:l.removeAttribute("type"),t!=null?i==="number"?(t===0&&l.value===""||l.value!=t)&&(l.value=""+ot(t)):l.value!==""+ot(t)&&(l.value=""+ot(t)):i!=="submit"&&i!=="reset"||l.removeAttribute("value"),t!=null?ti(l,i,ot(t)):e!=null?ti(l,i,ot(e)):a!=null&&l.removeAttribute("value"),u==null&&n!=null&&(l.defaultChecked=!!n),u!=null&&(l.checked=u&&typeof u!="function"&&typeof u!="symbol"),c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?l.name=""+ot(c):l.removeAttribute("name")}function Cf(l,t,e,a,u,n,i,c){if(n!=null&&typeof n!="function"&&typeof n!="symbol"&&typeof n!="boolean"&&(l.type=n),t!=null||e!=null){if(!(n!=="submit"&&n!=="reset"||t!=null)){Pn(l);return}e=e!=null?""+ot(e):"",t=t!=null?""+ot(t):e,c||t===l.value||(l.value=t),l.defaultValue=t}a=a??u,a=typeof a!="function"&&typeof a!="symbol"&&!!a,l.checked=c?l.checked:!!a,l.defaultChecked=!!a,i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(l.name=i),Pn(l)}function ti(l,t,e){t==="number"&&Du(l.ownerDocument)===l||l.defaultValue===""+e||(l.defaultValue=""+e)}function $e(l,t,e,a){if(l=l.options,t){t={};for(var u=0;u"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),ii=!1;if(Bt)try{var Ha={};Object.defineProperty(Ha,"passive",{get:function(){ii=!0}}),window.addEventListener("test",Ha,Ha),window.removeEventListener("test",Ha,Ha)}catch{ii=!1}var le=null,ci=null,Uu=null;function Gf(){if(Uu)return Uu;var l,t=ci,e=t.length,a,u="value"in le?le.value:le.textContent,n=u.length;for(l=0;l=Ya),Kf=" ",Jf=!1;function wf(l,t){switch(l){case"keyup":return Th.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function kf(l){return l=l.detail,typeof l=="object"&&"data"in l?l.data:null}var Pe=!1;function Ah(l,t){switch(l){case"compositionend":return kf(t);case"keypress":return t.which!==32?null:(Jf=!0,Kf);case"textInput":return l=t.data,l===Kf&&Jf?null:l;default:return null}}function Eh(l,t){if(Pe)return l==="compositionend"||!ri&&wf(l,t)?(l=Gf(),Uu=ci=le=null,Pe=!1,l):null;switch(l){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:e,offset:t-l};l=a}l:{for(;e;){if(e.nextSibling){e=e.nextSibling;break l}e=e.parentNode}e=void 0}e=es(e)}}function us(l,t){return l&&t?l===t?!0:l&&l.nodeType===3?!1:t&&t.nodeType===3?us(l,t.parentNode):"contains"in l?l.contains(t):l.compareDocumentPosition?!!(l.compareDocumentPosition(t)&16):!1:!1}function ns(l){l=l!=null&&l.ownerDocument!=null&&l.ownerDocument.defaultView!=null?l.ownerDocument.defaultView:window;for(var t=Du(l.document);t instanceof l.HTMLIFrameElement;){try{var e=typeof t.contentWindow.location.href=="string"}catch{e=!1}if(e)l=t.contentWindow;else break;t=Du(l.document)}return t}function yi(l){var t=l&&l.nodeName&&l.nodeName.toLowerCase();return t&&(t==="input"&&(l.type==="text"||l.type==="search"||l.type==="tel"||l.type==="url"||l.type==="password")||t==="textarea"||l.contentEditable==="true")}var Ch=Bt&&"documentMode"in document&&11>=document.documentMode,la=null,vi=null,Za=null,gi=!1;function is(l,t,e){var a=e.window===e?e.document:e.nodeType===9?e:e.ownerDocument;gi||la==null||la!==Du(a)||(a=la,"selectionStart"in a&&yi(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}),Za&&Qa(Za,a)||(Za=a,a=jn(vi,"onSelect"),0>=i,u-=i,Nt=1<<32-tt(t)+u|e<J?(P=q,q=null):P=q.sibling;var il=g(h,q,y[J],z);if(il===null){q===null&&(q=P);break}l&&q&&il.alternate===null&&t(h,q),o=n(il,o,J),nl===null?Y=il:nl.sibling=il,nl=il,q=P}if(J===y.length)return e(h,q),el&&Yt(h,J),Y;if(q===null){for(;JJ?(P=q,q=null):P=q.sibling;var ze=g(h,q,il.value,z);if(ze===null){q===null&&(q=P);break}l&&q&&ze.alternate===null&&t(h,q),o=n(ze,o,J),nl===null?Y=ze:nl.sibling=ze,nl=ze,q=P}if(il.done)return e(h,q),el&&Yt(h,J),Y;if(q===null){for(;!il.done;J++,il=y.next())il=A(h,il.value,z),il!==null&&(o=n(il,o,J),nl===null?Y=il:nl.sibling=il,nl=il);return el&&Yt(h,J),Y}for(q=a(q);!il.done;J++,il=y.next())il=S(q,h,J,il.value,z),il!==null&&(l&&il.alternate!==null&&q.delete(il.key===null?J:il.key),o=n(il,o,J),nl===null?Y=il:nl.sibling=il,nl=il);return l&&q.forEach(function(Im){return t(h,Im)}),el&&Yt(h,J),Y}function ml(h,o,y,z){if(typeof y=="object"&&y!==null&&y.type===al&&y.key===null&&(y=y.props.children),typeof y=="object"&&y!==null){switch(y.$$typeof){case F:l:{for(var Y=y.key;o!==null;){if(o.key===Y){if(Y=y.type,Y===al){if(o.tag===7){e(h,o.sibling),z=u(o,y.props.children),z.return=h,h=z;break l}}else if(o.elementType===Y||typeof Y=="object"&&Y!==null&&Y.$$typeof===Vl&&Be(Y)===o.type){e(h,o.sibling),z=u(o,y.props),ka(z,y),z.return=h,h=z;break l}e(h,o);break}else t(h,o);o=o.sibling}y.type===al?(z=De(y.props.children,h.mode,z,y.key),z.return=h,h=z):(z=Lu(y.type,y.key,y.props,null,h.mode,z),ka(z,y),z.return=h,h=z)}return i(h);case Z:l:{for(Y=y.key;o!==null;){if(o.key===Y)if(o.tag===4&&o.stateNode.containerInfo===y.containerInfo&&o.stateNode.implementation===y.implementation){e(h,o.sibling),z=u(o,y.children||[]),z.return=h,h=z;break l}else{e(h,o);break}else t(h,o);o=o.sibling}z=Ei(y,h.mode,z),z.return=h,h=z}return i(h);case Vl:return y=Be(y),ml(h,o,y,z)}if(pt(y))return C(h,o,y,z);if(Kl(y)){if(Y=Kl(y),typeof Y!="function")throw Error(r(150));return y=Y.call(y),X(h,o,y,z)}if(typeof y.then=="function")return ml(h,o,Wu(y),z);if(y.$$typeof===Gl)return ml(h,o,Ju(h,y),z);Fu(h,y)}return typeof y=="string"&&y!==""||typeof y=="number"||typeof y=="bigint"?(y=""+y,o!==null&&o.tag===6?(e(h,o.sibling),z=u(o,y),z.return=h,h=z):(e(h,o),z=Ai(y,h.mode,z),z.return=h,h=z),i(h)):e(h,o)}return function(h,o,y,z){try{wa=0;var Y=ml(h,o,y,z);return da=null,Y}catch(q){if(q===oa||q===ku)throw q;var nl=at(29,q,null,h.mode);return nl.lanes=z,nl.return=h,nl}finally{}}}var Ye=Ns(!0),Ms=Ns(!1),ne=!1;function Bi(l){l.updateQueue={baseState:l.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function qi(l,t){l=l.updateQueue,t.updateQueue===l&&(t.updateQueue={baseState:l.baseState,firstBaseUpdate:l.firstBaseUpdate,lastBaseUpdate:l.lastBaseUpdate,shared:l.shared,callbacks:null})}function ie(l){return{lane:l,tag:0,payload:null,callback:null,next:null}}function ce(l,t,e){var a=l.updateQueue;if(a===null)return null;if(a=a.shared,(cl&2)!==0){var u=a.pending;return u===null?t.next=t:(t.next=u.next,u.next=t),a.pending=t,t=Zu(l),hs(l,null,e),t}return Qu(l,a,t,e),Zu(l)}function $a(l,t,e){if(t=t.updateQueue,t!==null&&(t=t.shared,(e&4194048)!==0)){var a=t.lanes;a&=l.pendingLanes,e|=a,t.lanes=e,Tf(l,e)}}function Yi(l,t){var e=l.updateQueue,a=l.alternate;if(a!==null&&(a=a.updateQueue,e===a)){var u=null,n=null;if(e=e.firstBaseUpdate,e!==null){do{var i={lane:e.lane,tag:e.tag,payload:e.payload,callback:null,next:null};n===null?u=n=i:n=n.next=i,e=e.next}while(e!==null);n===null?u=n=t:n=n.next=t}else u=n=t;e={baseState:a.baseState,firstBaseUpdate:u,lastBaseUpdate:n,shared:a.shared,callbacks:a.callbacks},l.updateQueue=e;return}l=e.lastBaseUpdate,l===null?e.firstBaseUpdate=t:l.next=t,e.lastBaseUpdate=t}var Gi=!1;function Wa(){if(Gi){var l=sa;if(l!==null)throw l}}function Fa(l,t,e,a){Gi=!1;var u=l.updateQueue;ne=!1;var n=u.firstBaseUpdate,i=u.lastBaseUpdate,c=u.shared.pending;if(c!==null){u.shared.pending=null;var s=c,v=s.next;s.next=null,i===null?n=v:i.next=v,i=s;var b=l.alternate;b!==null&&(b=b.updateQueue,c=b.lastBaseUpdate,c!==i&&(c===null?b.firstBaseUpdate=v:c.next=v,b.lastBaseUpdate=s))}if(n!==null){var A=u.baseState;i=0,b=v=s=null,c=n;do{var g=c.lane&-536870913,S=g!==c.lane;if(S?(I&g)===g:(a&g)===g){g!==0&&g===fa&&(Gi=!0),b!==null&&(b=b.next={lane:0,tag:c.tag,payload:c.payload,callback:null,next:null});l:{var C=l,X=c;g=t;var ml=e;switch(X.tag){case 1:if(C=X.payload,typeof C=="function"){A=C.call(ml,A,g);break l}A=C;break l;case 3:C.flags=C.flags&-65537|128;case 0:if(C=X.payload,g=typeof C=="function"?C.call(ml,A,g):C,g==null)break l;A=x({},A,g);break l;case 2:ne=!0}}g=c.callback,g!==null&&(l.flags|=64,S&&(l.flags|=8192),S=u.callbacks,S===null?u.callbacks=[g]:S.push(g))}else S={lane:g,tag:c.tag,payload:c.payload,callback:c.callback,next:null},b===null?(v=b=S,s=A):b=b.next=S,i|=g;if(c=c.next,c===null){if(c=u.shared.pending,c===null)break;S=c,c=S.next,S.next=null,u.lastBaseUpdate=S,u.shared.pending=null}}while(!0);b===null&&(s=A),u.baseState=s,u.firstBaseUpdate=v,u.lastBaseUpdate=b,n===null&&(u.shared.lanes=0),re|=i,l.lanes=i,l.memoizedState=A}}function Ds(l,t){if(typeof l!="function")throw Error(r(191,l));l.call(t)}function Cs(l,t){var e=l.callbacks;if(e!==null)for(l.callbacks=null,l=0;ln?n:8;var i=T.T,c={};T.T=c,uc(l,!1,t,e);try{var s=u(),v=T.S;if(v!==null&&v(c,s),s!==null&&typeof s=="object"&&typeof s.then=="function"){var b=Qh(s,a);lu(l,t,b,ft(l))}else lu(l,t,a,ft(l))}catch(A){lu(l,t,{then:function(){},status:"rejected",reason:A},ft())}finally{j.p=n,i!==null&&c.types!==null&&(i.types=c.types),T.T=i}}function wh(){}function ec(l,t,e,a){if(l.tag!==5)throw Error(r(476));var u=oo(l).queue;so(l,u,t,Q,e===null?wh:function(){return ro(l),e(a)})}function oo(l){var t=l.memoizedState;if(t!==null)return t;t={memoizedState:Q,baseState:Q,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Zt,lastRenderedState:Q},next:null};var e={};return t.next={memoizedState:e,baseState:e,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Zt,lastRenderedState:e},next:null},l.memoizedState=t,l=l.alternate,l!==null&&(l.memoizedState=t),t}function ro(l){var t=oo(l);t.next===null&&(t=l.alternate.memoizedState),lu(l,t.next.queue,{},ft())}function ac(){return Bl(gu)}function ho(){return _l().memoizedState}function mo(){return _l().memoizedState}function kh(l){for(var t=l.return;t!==null;){switch(t.tag){case 24:case 3:var e=ft();l=ie(e);var a=ce(t,l,e);a!==null&&(Il(a,t,e),$a(a,t,e)),t={cache:Ci()},l.payload=t;return}t=t.return}}function $h(l,t,e){var a=ft();e={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null},fn(l)?vo(t,e):(e=Ti(l,t,e,a),e!==null&&(Il(e,l,a),go(e,t,a)))}function yo(l,t,e){var a=ft();lu(l,t,e,a)}function lu(l,t,e,a){var u={lane:a,revertLane:0,gesture:null,action:e,hasEagerState:!1,eagerState:null,next:null};if(fn(l))vo(t,u);else{var n=l.alternate;if(l.lanes===0&&(n===null||n.lanes===0)&&(n=t.lastRenderedReducer,n!==null))try{var i=t.lastRenderedState,c=n(i,e);if(u.hasEagerState=!0,u.eagerState=c,et(c,i))return Qu(l,t,u,0),vl===null&&Xu(),!1}catch{}finally{}if(e=Ti(l,t,u,a),e!==null)return Il(e,l,a),go(e,t,a),!0}return!1}function uc(l,t,e,a){if(a={lane:2,revertLane:Bc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},fn(l)){if(t)throw Error(r(479))}else t=Ti(l,e,a,2),t!==null&&Il(t,l,2)}function fn(l){var t=l.alternate;return l===K||t!==null&&t===K}function vo(l,t){ha=ln=!0;var e=l.pending;e===null?t.next=t:(t.next=e.next,e.next=t),l.pending=t}function go(l,t,e){if((e&4194048)!==0){var a=t.lanes;a&=l.pendingLanes,e|=a,t.lanes=e,Tf(l,e)}}var tu={readContext:Bl,use:an,useCallback:Tl,useContext:Tl,useEffect:Tl,useImperativeHandle:Tl,useLayoutEffect:Tl,useInsertionEffect:Tl,useMemo:Tl,useReducer:Tl,useRef:Tl,useState:Tl,useDebugValue:Tl,useDeferredValue:Tl,useTransition:Tl,useSyncExternalStore:Tl,useId:Tl,useHostTransitionStatus:Tl,useFormState:Tl,useActionState:Tl,useOptimistic:Tl,useMemoCache:Tl,useCacheRefresh:Tl};tu.useEffectEvent=Tl;var So={readContext:Bl,use:an,useCallback:function(l,t){return Zl().memoizedState=[l,t===void 0?null:t],l},useContext:Bl,useEffect:lo,useImperativeHandle:function(l,t,e){e=e!=null?e.concat([l]):null,nn(4194308,4,uo.bind(null,t,l),e)},useLayoutEffect:function(l,t){return nn(4194308,4,l,t)},useInsertionEffect:function(l,t){nn(4,2,l,t)},useMemo:function(l,t){var e=Zl();t=t===void 0?null:t;var a=l();if(Ge){It(!0);try{l()}finally{It(!1)}}return e.memoizedState=[a,t],a},useReducer:function(l,t,e){var a=Zl();if(e!==void 0){var u=e(t);if(Ge){It(!0);try{e(t)}finally{It(!1)}}}else u=t;return a.memoizedState=a.baseState=u,l={pending:null,lanes:0,dispatch:null,lastRenderedReducer:l,lastRenderedState:u},a.queue=l,l=l.dispatch=$h.bind(null,K,l),[a.memoizedState,l]},useRef:function(l){var t=Zl();return l={current:l},t.memoizedState=l},useState:function(l){l=Fi(l);var t=l.queue,e=yo.bind(null,K,t);return t.dispatch=e,[l.memoizedState,e]},useDebugValue:lc,useDeferredValue:function(l,t){var e=Zl();return tc(e,l,t)},useTransition:function(){var l=Fi(!1);return l=so.bind(null,K,l.queue,!0,!1),Zl().memoizedState=l,[!1,l]},useSyncExternalStore:function(l,t,e){var a=K,u=Zl();if(el){if(e===void 0)throw Error(r(407));e=e()}else{if(e=t(),vl===null)throw Error(r(349));(I&127)!==0||Ys(a,t,e)}u.memoizedState=e;var n={value:e,getSnapshot:t};return u.queue=n,lo(Xs.bind(null,a,n,l),[l]),a.flags|=2048,ya(9,{destroy:void 0},Gs.bind(null,a,n,e,t),null),e},useId:function(){var l=Zl(),t=vl.identifierPrefix;if(el){var e=Mt,a=Nt;e=(a&~(1<<32-tt(a)-1)).toString(32)+e,t="_"+t+"R_"+e,e=tn++,0<\/script>",n=n.removeChild(n.firstChild);break;case"select":n=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?n.multiple=!0:a.size&&(n.size=a.size);break;default:n=typeof a.is=="string"?i.createElement(u,{is:a.is}):i.createElement(u)}}n[Rl]=t,n[Jl]=a;l:for(i=t.child;i!==null;){if(i.tag===5||i.tag===6)n.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===t)break l;for(;i.sibling===null;){if(i.return===null||i.return===t)break l;i=i.return}i.sibling.return=i.return,i=i.sibling}t.stateNode=n;l:switch(Yl(n,u,a),u){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break l;case"img":a=!0;break l;default:a=!1}a&&Vt(t)}}return Sl(t),Sc(t,t.type,l===null?null:l.memoizedProps,t.pendingProps,e),null;case 6:if(l&&t.stateNode!=null)l.memoizedProps!==a&&Vt(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(l=k.current,ia(t)){if(l=t.stateNode,e=t.memoizedProps,a=null,u=Hl,u!==null)switch(u.tag){case 27:case 5:a=u.memoizedProps}l[Rl]=t,l=!!(l.nodeValue===e||a!==null&&a.suppressHydrationWarning===!0||qd(l.nodeValue,e)),l||ae(t,!0)}else l=On(l).createTextNode(a),l[Rl]=t,t.stateNode=l}return Sl(t),null;case 31:if(e=t.memoizedState,l===null||l.memoizedState!==null){if(a=ia(t),e!==null){if(l===null){if(!a)throw Error(r(318));if(l=t.memoizedState,l=l!==null?l.dehydrated:null,!l)throw Error(r(557));l[Rl]=t}else Ce(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Sl(t),l=!1}else e=Oi(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=e),l=!0;if(!l)return t.flags&256?(nt(t),t):(nt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Sl(t),null;case 13:if(a=t.memoizedState,l===null||l.memoizedState!==null&&l.memoizedState.dehydrated!==null){if(u=ia(t),a!==null&&a.dehydrated!==null){if(l===null){if(!u)throw Error(r(318));if(u=t.memoizedState,u=u!==null?u.dehydrated:null,!u)throw Error(r(317));u[Rl]=t}else Ce(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Sl(t),u=!1}else u=Oi(),l!==null&&l.memoizedState!==null&&(l.memoizedState.hydrationErrors=u),u=!0;if(!u)return t.flags&256?(nt(t),t):(nt(t),null)}return nt(t),(t.flags&128)!==0?(t.lanes=e,t):(e=a!==null,l=l!==null&&l.memoizedState!==null,e&&(a=t.child,u=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(u=a.alternate.memoizedState.cachePool.pool),n=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(n=a.memoizedState.cachePool.pool),n!==u&&(a.flags|=2048)),e!==l&&e&&(t.child.flags|=8192),hn(t,t.updateQueue),Sl(t),null);case 4:return Al(),l===null&&Xc(t.stateNode.containerInfo),Sl(t),null;case 10:return Xt(t.type),Sl(t),null;case 19:if(E(El),a=t.memoizedState,a===null)return Sl(t),null;if(u=(t.flags&128)!==0,n=a.rendering,n===null)if(u)au(a,!1);else{if(zl!==0||l!==null&&(l.flags&128)!==0)for(l=t.child;l!==null;){if(n=Pu(l),n!==null){for(t.flags|=128,au(a,!1),l=n.updateQueue,t.updateQueue=l,hn(t,l),t.subtreeFlags=0,l=e,e=t.child;e!==null;)ms(e,l),e=e.sibling;return N(El,El.current&1|2),el&&Yt(t,a.treeForkCount),t.child}l=l.sibling}a.tail!==null&&Pl()>Sn&&(t.flags|=128,u=!0,au(a,!1),t.lanes=4194304)}else{if(!u)if(l=Pu(n),l!==null){if(t.flags|=128,u=!0,l=l.updateQueue,t.updateQueue=l,hn(t,l),au(a,!0),a.tail===null&&a.tailMode==="hidden"&&!n.alternate&&!el)return Sl(t),null}else 2*Pl()-a.renderingStartTime>Sn&&e!==536870912&&(t.flags|=128,u=!0,au(a,!1),t.lanes=4194304);a.isBackwards?(n.sibling=t.child,t.child=n):(l=a.last,l!==null?l.sibling=n:t.child=n,a.last=n)}return a.tail!==null?(l=a.tail,a.rendering=l,a.tail=l.sibling,a.renderingStartTime=Pl(),l.sibling=null,e=El.current,N(El,u?e&1|2:e&1),el&&Yt(t,a.treeForkCount),l):(Sl(t),null);case 22:case 23:return nt(t),Qi(),a=t.memoizedState!==null,l!==null?l.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(e&536870912)!==0&&(t.flags&128)===0&&(Sl(t),t.subtreeFlags&6&&(t.flags|=8192)):Sl(t),e=t.updateQueue,e!==null&&hn(t,e.retryQueue),e=null,l!==null&&l.memoizedState!==null&&l.memoizedState.cachePool!==null&&(e=l.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==e&&(t.flags|=2048),l!==null&&E(He),null;case 24:return e=null,l!==null&&(e=l.memoizedState.cache),t.memoizedState.cache!==e&&(t.flags|=2048),Xt(xl),Sl(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function lm(l,t){switch(xi(t),t.tag){case 1:return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 3:return Xt(xl),Al(),l=t.flags,(l&65536)!==0&&(l&128)===0?(t.flags=l&-65537|128,t):null;case 26:case 27:case 5:return Au(t),null;case 31:if(t.memoizedState!==null){if(nt(t),t.alternate===null)throw Error(r(340));Ce()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 13:if(nt(t),l=t.memoizedState,l!==null&&l.dehydrated!==null){if(t.alternate===null)throw Error(r(340));Ce()}return l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 19:return E(El),null;case 4:return Al(),null;case 10:return Xt(t.type),null;case 22:case 23:return nt(t),Qi(),l!==null&&E(He),l=t.flags,l&65536?(t.flags=l&-65537|128,t):null;case 24:return Xt(xl),null;case 25:return null;default:return null}}function Zo(l,t){switch(xi(t),t.tag){case 3:Xt(xl),Al();break;case 26:case 27:case 5:Au(t);break;case 4:Al();break;case 31:t.memoizedState!==null&&nt(t);break;case 13:nt(t);break;case 19:E(El);break;case 10:Xt(t.type);break;case 22:case 23:nt(t),Qi(),l!==null&&E(He);break;case 24:Xt(xl)}}function uu(l,t){try{var e=t.updateQueue,a=e!==null?e.lastEffect:null;if(a!==null){var u=a.next;e=u;do{if((e.tag&l)===l){a=void 0;var n=e.create,i=e.inst;a=n(),i.destroy=a}e=e.next}while(e!==u)}}catch(c){ol(t,t.return,c)}}function oe(l,t,e){try{var a=t.updateQueue,u=a!==null?a.lastEffect:null;if(u!==null){var n=u.next;a=n;do{if((a.tag&l)===l){var i=a.inst,c=i.destroy;if(c!==void 0){i.destroy=void 0,u=t;var s=e,v=c;try{v()}catch(b){ol(u,s,b)}}}a=a.next}while(a!==n)}}catch(b){ol(t,t.return,b)}}function Lo(l){var t=l.updateQueue;if(t!==null){var e=l.stateNode;try{Cs(t,e)}catch(a){ol(l,l.return,a)}}}function Vo(l,t,e){e.props=Xe(l.type,l.memoizedProps),e.state=l.memoizedState;try{e.componentWillUnmount()}catch(a){ol(l,t,a)}}function nu(l,t){try{var e=l.ref;if(e!==null){switch(l.tag){case 26:case 27:case 5:var a=l.stateNode;break;case 30:a=l.stateNode;break;default:a=l.stateNode}typeof e=="function"?l.refCleanup=e(a):e.current=a}}catch(u){ol(l,t,u)}}function Dt(l,t){var e=l.ref,a=l.refCleanup;if(e!==null)if(typeof a=="function")try{a()}catch(u){ol(l,t,u)}finally{l.refCleanup=null,l=l.alternate,l!=null&&(l.refCleanup=null)}else if(typeof e=="function")try{e(null)}catch(u){ol(l,t,u)}else e.current=null}function Ko(l){var t=l.type,e=l.memoizedProps,a=l.stateNode;try{l:switch(t){case"button":case"input":case"select":case"textarea":e.autoFocus&&a.focus();break l;case"img":e.src?a.src=e.src:e.srcSet&&(a.srcset=e.srcSet)}}catch(u){ol(l,l.return,u)}}function bc(l,t,e){try{var a=l.stateNode;zm(a,l.type,e,t),a[Jl]=t}catch(u){ol(l,l.return,u)}}function Jo(l){return l.tag===5||l.tag===3||l.tag===26||l.tag===27&&ge(l.type)||l.tag===4}function pc(l){l:for(;;){for(;l.sibling===null;){if(l.return===null||Jo(l.return))return null;l=l.return}for(l.sibling.return=l.return,l=l.sibling;l.tag!==5&&l.tag!==6&&l.tag!==18;){if(l.tag===27&&ge(l.type)||l.flags&2||l.child===null||l.tag===4)continue l;l.child.return=l,l=l.child}if(!(l.flags&2))return l.stateNode}}function Tc(l,t,e){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?(e.nodeType===9?e.body:e.nodeName==="HTML"?e.ownerDocument.body:e).insertBefore(l,t):(t=e.nodeType===9?e.body:e.nodeName==="HTML"?e.ownerDocument.body:e,t.appendChild(l),e=e._reactRootContainer,e!=null||t.onclick!==null||(t.onclick=Ht));else if(a!==4&&(a===27&&ge(l.type)&&(e=l.stateNode,t=null),l=l.child,l!==null))for(Tc(l,t,e),l=l.sibling;l!==null;)Tc(l,t,e),l=l.sibling}function mn(l,t,e){var a=l.tag;if(a===5||a===6)l=l.stateNode,t?e.insertBefore(l,t):e.appendChild(l);else if(a!==4&&(a===27&&ge(l.type)&&(e=l.stateNode),l=l.child,l!==null))for(mn(l,t,e),l=l.sibling;l!==null;)mn(l,t,e),l=l.sibling}function wo(l){var t=l.stateNode,e=l.memoizedProps;try{for(var a=l.type,u=t.attributes;u.length;)t.removeAttributeNode(u[0]);Yl(t,a,e),t[Rl]=l,t[Jl]=e}catch(n){ol(l,l.return,n)}}var Kt=!1,Nl=!1,zc=!1,ko=typeof WeakSet=="function"?WeakSet:Set,Ul=null;function tm(l,t){if(l=l.containerInfo,Lc=Hn,l=ns(l),yi(l)){if("selectionStart"in l)var e={start:l.selectionStart,end:l.selectionEnd};else l:{e=(e=l.ownerDocument)&&e.defaultView||window;var a=e.getSelection&&e.getSelection();if(a&&a.rangeCount!==0){e=a.anchorNode;var u=a.anchorOffset,n=a.focusNode;a=a.focusOffset;try{e.nodeType,n.nodeType}catch{e=null;break l}var i=0,c=-1,s=-1,v=0,b=0,A=l,g=null;t:for(;;){for(var S;A!==e||u!==0&&A.nodeType!==3||(c=i+u),A!==n||a!==0&&A.nodeType!==3||(s=i+a),A.nodeType===3&&(i+=A.nodeValue.length),(S=A.firstChild)!==null;)g=A,A=S;for(;;){if(A===l)break t;if(g===e&&++v===u&&(c=i),g===n&&++b===a&&(s=i),(S=A.nextSibling)!==null)break;A=g,g=A.parentNode}A=S}e=c===-1||s===-1?null:{start:c,end:s}}else e=null}e=e||{start:0,end:0}}else e=null;for(Vc={focusedElem:l,selectionRange:e},Hn=!1,Ul=t;Ul!==null;)if(t=Ul,l=t.child,(t.subtreeFlags&1028)!==0&&l!==null)l.return=t,Ul=l;else for(;Ul!==null;){switch(t=Ul,n=t.alternate,l=t.flags,t.tag){case 0:if((l&4)!==0&&(l=t.updateQueue,l=l!==null?l.events:null,l!==null))for(e=0;e title"))),Yl(n,a,e),n[Rl]=l,Cl(n),a=n;break l;case"link":var i=lr("link","href",u).get(a+(e.href||""));if(i){for(var c=0;cml&&(i=ml,ml=X,X=i);var h=as(c,X),o=as(c,ml);if(h&&o&&(S.rangeCount!==1||S.anchorNode!==h.node||S.anchorOffset!==h.offset||S.focusNode!==o.node||S.focusOffset!==o.offset)){var y=A.createRange();y.setStart(h.node,h.offset),S.removeAllRanges(),X>ml?(S.addRange(y),S.extend(o.node,o.offset)):(y.setEnd(o.node,o.offset),S.addRange(y))}}}}for(A=[],S=c;S=S.parentNode;)S.nodeType===1&&A.push({element:S,left:S.scrollLeft,top:S.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;ce?32:e,T.T=null,e=Nc,Nc=null;var n=me,i=Wt;if(Dl=0,pa=me=null,Wt=0,(cl&6)!==0)throw Error(r(331));var c=cl;if(cl|=4,nd(n.current),ed(n,n.current,i,e),cl=c,du(0,!1),lt&&typeof lt.onPostCommitFiberRoot=="function")try{lt.onPostCommitFiberRoot(Na,n)}catch{}return!0}finally{j.p=u,T.T=a,Ad(l,t)}}function _d(l,t,e){t=ht(e,t),t=fc(l.stateNode,t,2),l=ce(l,t,2),l!==null&&(Da(l,2),Ct(l))}function ol(l,t,e){if(l.tag===3)_d(l,l,e);else for(;t!==null;){if(t.tag===3){_d(t,l,e);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(he===null||!he.has(a))){l=ht(e,l),e=xo(2),a=ce(t,e,2),a!==null&&(jo(e,a,t,l),Da(a,2),Ct(a));break}}t=t.return}}function Uc(l,t,e){var a=l.pingCache;if(a===null){a=l.pingCache=new um;var u=new Set;a.set(t,u)}else u=a.get(t),u===void 0&&(u=new Set,a.set(t,u));u.has(e)||(_c=!0,u.add(e),l=sm.bind(null,l,t,e),t.then(l,l))}function sm(l,t,e){var a=l.pingCache;a!==null&&a.delete(t),l.pingedLanes|=l.suspendedLanes&e,l.warmLanes&=~e,vl===l&&(I&e)===e&&(zl===4||zl===3&&(I&62914560)===I&&300>Pl()-gn?(cl&2)===0&&Ta(l,0):xc|=e,ba===I&&(ba=0)),Ct(l)}function xd(l,t){t===0&&(t=bf()),l=Me(l,t),l!==null&&(Da(l,t),Ct(l))}function om(l){var t=l.memoizedState,e=0;t!==null&&(e=t.retryLane),xd(l,e)}function dm(l,t){var e=0;switch(l.tag){case 31:case 13:var a=l.stateNode,u=l.memoizedState;u!==null&&(e=u.retryLane);break;case 19:a=l.stateNode;break;case 22:a=l.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),xd(l,e)}function rm(l,t){return Jn(l,t)}var En=null,Aa=null,Rc=!1,_n=!1,Hc=!1,ve=0;function Ct(l){l!==Aa&&l.next===null&&(Aa===null?En=Aa=l:Aa=Aa.next=l),_n=!0,Rc||(Rc=!0,mm())}function du(l,t){if(!Hc&&_n){Hc=!0;do for(var e=!1,a=En;a!==null;){if(l!==0){var u=a.pendingLanes;if(u===0)var n=0;else{var i=a.suspendedLanes,c=a.pingedLanes;n=(1<<31-tt(42|l)+1)-1,n&=u&~(i&~c),n=n&201326741?n&201326741|1:n?n|2:0}n!==0&&(e=!0,Md(a,n))}else n=I,n=Ou(a,a===vl?n:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(n&3)===0||Ma(a,n)||(e=!0,Md(a,n));a=a.next}while(e);Hc=!1}}function hm(){jd()}function jd(){_n=Rc=!1;var l=0;ve!==0&&Em()&&(l=ve);for(var t=Pl(),e=null,a=En;a!==null;){var u=a.next,n=Od(a,t);n===0?(a.next=null,e===null?En=u:e.next=u,u===null&&(Aa=e)):(e=a,(l!==0||(n&3)!==0)&&(_n=!0)),a=u}Dl!==0&&Dl!==5||du(l),ve!==0&&(ve=0)}function Od(l,t){for(var e=l.suspendedLanes,a=l.pingedLanes,u=l.expirationTimes,n=l.pendingLanes&-62914561;0c)break;var b=s.transferSize,A=s.initiatorType;b&&Yd(A)&&(s=s.responseEnd,i+=b*(s"u"?null:document;function Wd(l,t,e){var a=Ea;if(a&&typeof t=="string"&&t){var u=dt(t);u='link[rel="'+l+'"][href="'+u+'"]',typeof e=="string"&&(u+='[crossorigin="'+e+'"]'),$d.has(u)||($d.add(u),l={rel:l,crossOrigin:e,href:t},a.querySelector(u)===null&&(t=a.createElement("link"),Yl(t,"link",l),Cl(t),a.head.appendChild(t)))}}function Um(l){Ft.D(l),Wd("dns-prefetch",l,null)}function Rm(l,t){Ft.C(l,t),Wd("preconnect",l,t)}function Hm(l,t,e){Ft.L(l,t,e);var a=Ea;if(a&&l&&t){var u='link[rel="preload"][as="'+dt(t)+'"]';t==="image"&&e&&e.imageSrcSet?(u+='[imagesrcset="'+dt(e.imageSrcSet)+'"]',typeof e.imageSizes=="string"&&(u+='[imagesizes="'+dt(e.imageSizes)+'"]')):u+='[href="'+dt(l)+'"]';var n=u;switch(t){case"style":n=_a(l);break;case"script":n=xa(l)}bt.has(n)||(l=x({rel:"preload",href:t==="image"&&e&&e.imageSrcSet?void 0:l,as:t},e),bt.set(n,l),a.querySelector(u)!==null||t==="style"&&a.querySelector(yu(n))||t==="script"&&a.querySelector(vu(n))||(t=a.createElement("link"),Yl(t,"link",l),Cl(t),a.head.appendChild(t)))}}function Bm(l,t){Ft.m(l,t);var e=Ea;if(e&&l){var a=t&&typeof t.as=="string"?t.as:"script",u='link[rel="modulepreload"][as="'+dt(a)+'"][href="'+dt(l)+'"]',n=u;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":n=xa(l)}if(!bt.has(n)&&(l=x({rel:"modulepreload",href:l},t),bt.set(n,l),e.querySelector(u)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(e.querySelector(vu(n)))return}a=e.createElement("link"),Yl(a,"link",l),Cl(a),e.head.appendChild(a)}}}function qm(l,t,e){Ft.S(l,t,e);var a=Ea;if(a&&l){var u=we(a).hoistableStyles,n=_a(l);t=t||"default";var i=u.get(n);if(!i){var c={loading:0,preload:null};if(i=a.querySelector(yu(n)))c.loading=5;else{l=x({rel:"stylesheet",href:l,"data-precedence":t},e),(e=bt.get(n))&&Fc(l,e);var s=i=a.createElement("link");Cl(s),Yl(s,"link",l),s._p=new Promise(function(v,b){s.onload=v,s.onerror=b}),s.addEventListener("load",function(){c.loading|=1}),s.addEventListener("error",function(){c.loading|=2}),c.loading|=4,Mn(i,t,a)}i={type:"stylesheet",instance:i,count:1,state:c},u.set(n,i)}}}function Ym(l,t){Ft.X(l,t);var e=Ea;if(e&&l){var a=we(e).hoistableScripts,u=xa(l),n=a.get(u);n||(n=e.querySelector(vu(u)),n||(l=x({src:l,async:!0},t),(t=bt.get(u))&&Ic(l,t),n=e.createElement("script"),Cl(n),Yl(n,"link",l),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Gm(l,t){Ft.M(l,t);var e=Ea;if(e&&l){var a=we(e).hoistableScripts,u=xa(l),n=a.get(u);n||(n=e.querySelector(vu(u)),n||(l=x({src:l,async:!0,type:"module"},t),(t=bt.get(u))&&Ic(l,t),n=e.createElement("script"),Cl(n),Yl(n,"link",l),e.head.appendChild(n)),n={type:"script",instance:n,count:1,state:null},a.set(u,n))}}function Fd(l,t,e,a){var u=(u=k.current)?Nn(u):null;if(!u)throw Error(r(446));switch(l){case"meta":case"title":return null;case"style":return typeof e.precedence=="string"&&typeof e.href=="string"?(t=_a(e.href),e=we(u).hoistableStyles,a=e.get(t),a||(a={type:"style",instance:null,count:0,state:null},e.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(e.rel==="stylesheet"&&typeof e.href=="string"&&typeof e.precedence=="string"){l=_a(e.href);var n=we(u).hoistableStyles,i=n.get(l);if(i||(u=u.ownerDocument||u,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},n.set(l,i),(n=u.querySelector(yu(l)))&&!n._p&&(i.instance=n,i.state.loading=5),bt.has(l)||(e={rel:"preload",as:"style",href:e.href,crossOrigin:e.crossOrigin,integrity:e.integrity,media:e.media,hrefLang:e.hrefLang,referrerPolicy:e.referrerPolicy},bt.set(l,e),n||Xm(u,l,e,i.state))),t&&a===null)throw Error(r(528,""));return i}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=e.async,e=e.src,typeof e=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=xa(e),e=we(u).hoistableScripts,a=e.get(t),a||(a={type:"script",instance:null,count:0,state:null},e.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,l))}}function _a(l){return'href="'+dt(l)+'"'}function yu(l){return'link[rel="stylesheet"]['+l+"]"}function Id(l){return x({},l,{"data-precedence":l.precedence,precedence:null})}function Xm(l,t,e,a){l.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=l.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),Yl(t,"link",e),Cl(t),l.head.appendChild(t))}function xa(l){return'[src="'+dt(l)+'"]'}function vu(l){return"script[async]"+l}function Pd(l,t,e){if(t.count++,t.instance===null)switch(t.type){case"style":var a=l.querySelector('style[data-href~="'+dt(e.href)+'"]');if(a)return t.instance=a,Cl(a),a;var u=x({},e,{"data-href":e.href,"data-precedence":e.precedence,href:null,precedence:null});return a=(l.ownerDocument||l).createElement("style"),Cl(a),Yl(a,"style",u),Mn(a,e.precedence,l),t.instance=a;case"stylesheet":u=_a(e.href);var n=l.querySelector(yu(u));if(n)return t.state.loading|=4,t.instance=n,Cl(n),n;a=Id(e),(u=bt.get(u))&&Fc(a,u),n=(l.ownerDocument||l).createElement("link"),Cl(n);var i=n;return i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),Yl(n,"link",a),t.state.loading|=4,Mn(n,e.precedence,l),t.instance=n;case"script":return n=xa(e.src),(u=l.querySelector(vu(n)))?(t.instance=u,Cl(u),u):(a=e,(u=bt.get(n))&&(a=x({},e),Ic(a,u)),l=l.ownerDocument||l,u=l.createElement("script"),Cl(u),Yl(u,"link",a),l.head.appendChild(u),t.instance=u);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,Mn(a,e.precedence,l));return t.instance}function Mn(l,t,e){for(var a=e.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),u=a.length?a[a.length-1]:null,n=u,i=0;i title"):null)}function Qm(l,t,e){if(e===1||t.itemProp!=null)return!1;switch(l){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;switch(t.rel){case"stylesheet":return l=t.disabled,typeof t.precedence=="string"&&l==null;default:return!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 er(l){return!(l.type==="stylesheet"&&(l.state.loading&3)===0)}function Zm(l,t,e,a){if(e.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(e.state.loading&4)===0){if(e.instance===null){var u=_a(a.href),n=t.querySelector(yu(u));if(n){t=n._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(l.count++,l=Cn.bind(l),t.then(l,l)),e.state.loading|=4,e.instance=n,Cl(n);return}n=t.ownerDocument||t,a=Id(a),(u=bt.get(u))&&Fc(a,u),n=n.createElement("link"),Cl(n);var i=n;i._p=new Promise(function(c,s){i.onload=c,i.onerror=s}),Yl(n,"link",a),e.instance=n}l.stylesheets===null&&(l.stylesheets=new Map),l.stylesheets.set(e,t),(t=e.state.preload)&&(e.state.loading&3)===0&&(l.count++,e=Cn.bind(l),t.addEventListener("load",e),t.addEventListener("error",e))}}var Pc=0;function Lm(l,t){return l.stylesheets&&l.count===0&&Rn(l,l.stylesheets),0Pc?50:800)+t);return l.unsuspend=e,function(){l.unsuspend=null,clearTimeout(a),clearTimeout(u)}}:null}function Cn(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Rn(this,this.stylesheets);else if(this.unsuspend){var l=this.unsuspend;this.unsuspend=null,l()}}}var Un=null;function Rn(l,t){l.stylesheets=null,l.unsuspend!==null&&(l.count++,Un=new Map,t.forEach(Vm,l),Un=null,Cn.call(l))}function Vm(l,t){if(!(t.state.loading&4)){var e=Un.get(l);if(e)var a=e.get(null);else{e=new Map,Un.set(l,e);for(var u=l.querySelectorAll("link[data-precedence],style[data-precedence]"),n=0;n"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(m)}catch(H){console.error(H)}}return m(),sf.exports=iy(),sf.exports}var fy=cy();const sy=Or(fy),oy="";async function Et(m,H){const D=await fetch(`${oy}${m}`,{...H,credentials:"same-origin",headers:{"Content-Type":"application/json",...H==null?void 0:H.headers}});if(D.status===401)throw window.location.hash="#login",new Error("Unauthorized");if(!D.ok){const r=await D.json().catch(()=>({}));throw new Error(r.error||`HTTP ${D.status}`)}return D.json()}const _t={login:m=>Et("/admin/login",{method:"POST",body:JSON.stringify({token:m})}),signOutEverywhere:()=>Et("/admin/api/sign-out-everywhere",{method:"POST"}),stats:()=>Et("/admin/api/stats"),health:()=>Et("/admin/api/health-indicators"),agents:()=>Et("/admin/api/agents"),requests:(m=1,H="")=>Et(`/admin/api/requests?page=${m}${H}`),apiKeys:()=>Et("/admin/api/api-keys"),createApiKey:m=>Et("/admin/api/api-keys",{method:"POST",body:JSON.stringify({name:m})}),revokeApiKey:m=>Et("/admin/api/api-keys/revoke",{method:"POST",body:JSON.stringify({name:m})}),updateClientTtl:(m,H)=>Et("/admin/api/update-client-ttl",{method:"POST",body:JSON.stringify({clientId:m,tokenTtl:H})}),revokeClient:m=>Et("/admin/api/revoke-client",{method:"POST",body:JSON.stringify({clientId:m})})};function dy({onLogin:m}){const[H,D]=ul.useState(""),[r,O]=ul.useState(""),[G,U]=ul.useState(!1),w=async M=>{M.preventDefault(),O(""),U(!0);try{await _t.login(H),D(""),m()}catch{O("Invalid token.")}finally{U(!1)}};return f.jsx("div",{className:"login-page",children:f.jsxs("div",{className:"login-box",children:[f.jsx("div",{className:"login-logo",children:"GBrain"}),f.jsxs("div",{style:{background:"rgba(136, 170, 255, 0.08)",border:"1px solid rgba(136, 170, 255, 0.2)",borderRadius:8,padding:"14px 16px",marginBottom:20,fontSize:13,lineHeight:1.5,color:"var(--text-secondary)"},children:[f.jsx("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:6},children:"🔒 This is a protected dashboard"}),"Ask your AI agent for the admin login link:",f.jsx("div",{style:{background:"rgba(0,0,0,0.3)",borderRadius:6,padding:"8px 12px",marginTop:8,fontFamily:"var(--font-mono)",fontSize:12,color:"#88aaff",wordBreak:"break-all"},children:'"Give me the GBrain admin login link"'}),f.jsx("div",{style:{marginTop:8,fontSize:12,color:"var(--text-muted)"},children:"Each link is single-use. Your agent generates a fresh one each time."})]}),f.jsxs("details",{style:{marginBottom:16},children:[f.jsx("summary",{style:{cursor:"pointer",fontSize:13,color:"var(--text-muted)"},children:"Or paste bootstrap token manually"}),f.jsxs("form",{onSubmit:w,style:{marginTop:12},children:[f.jsx("div",{style:{marginBottom:12},children:f.jsx("input",{type:"password",placeholder:"Admin Token",value:H,onChange:M=>D(M.target.value)})}),f.jsx("button",{className:"btn btn-primary",style:{width:"100%"},disabled:G,children:G?"Authenticating...":"Submit"}),r&&f.jsx("div",{className:"login-error",children:r})]})]})]})})}function ry(){const[m,H]=ul.useState({connected_agents:0,requests_today:0,active_tokens:0}),[D,r]=ul.useState({expiring_soon:0,error_rate:"0%"}),[O,G]=ul.useState([]),[U,w]=ul.useState("connecting"),M=ul.useRef(null);ul.useEffect(()=>{_t.stats().then(H).catch(()=>{}),_t.health().then(r).catch(()=>{});const R=new EventSource("/admin/events");M.current=R,R.onopen=()=>w("connected"),R.onmessage=_=>{try{const F=JSON.parse(_.data);G(Z=>[F,...Z].slice(0,50))}catch{}},R.onerror=()=>{w("disconnected"),setTimeout(()=>{w("connecting"),R.close()},3e3)};const x=setInterval(()=>{_t.stats().then(H).catch(()=>{}),_t.health().then(r).catch(()=>{})},3e4);return()=>{R.close(),clearInterval(x)}},[]);const p=R=>{const x=Date.now()-new Date(R).getTime();return x<6e4?`${Math.floor(x/1e3)}s ago`:x<36e5?`${Math.floor(x/6e4)} min ago`:`${Math.floor(x/36e5)}h ago`};return f.jsxs(f.Fragment,{children:[f.jsx("h1",{className:"page-title",children:"Dashboard"}),f.jsxs("div",{style:{display:"flex",gap:24},children:[f.jsxs("div",{style:{flex:1},children:[f.jsxs("div",{className:"metrics",children:[f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:m.connected_agents}),f.jsx("div",{className:"metric-label",children:"Connected Agents"})]}),f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:m.requests_today}),f.jsx("div",{className:"metric-label",children:"Requests Today"})]}),f.jsxs("div",{className:"metric",children:[f.jsx("div",{className:"metric-value",children:m.active_tokens}),f.jsx("div",{className:"metric-label",children:"Active Tokens"})]})]}),f.jsxs("h2",{className:"section-title",children:["Live Activity",f.jsx("span",{style:{marginLeft:8,fontSize:10,color:U==="connected"?"var(--success)":U==="connecting"?"var(--warning)":"var(--error)"},children:U==="connected"?"● connected":U==="connecting"?"● connecting...":"● disconnected"})]}),f.jsx("div",{className:"feed",children:O.length===0?f.jsx("div",{className:"feed-empty",children:U==="connected"?"No requests yet. Agents will appear when they connect.":"Connecting..."}):f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Agent"}),f.jsx("th",{children:"Operation"}),f.jsx("th",{children:"Scopes"}),f.jsx("th",{children:"Latency"}),f.jsx("th",{children:"Status"}),f.jsx("th",{children:"Time"})]})}),f.jsx("tbody",{children:O.map((R,x)=>f.jsxs("tr",{children:[f.jsx("td",{className:"mono",children:R.agent}),f.jsx("td",{className:"mono",children:R.operation}),f.jsx("td",{children:R.scopes.split(",").map(_=>f.jsx("span",{className:`badge badge-${_.trim()}`,style:{marginRight:4},children:_.trim()},_))}),f.jsxs("td",{className:"mono",children:[R.latency_ms," ms"]}),f.jsx("td",{children:f.jsx("span",{className:`badge badge-${R.status}`,children:R.status})}),f.jsx("td",{style:{color:"var(--text-secondary)"},children:p(R.timestamp)})]},x))})]})})]}),f.jsxs("div",{style:{width:220},children:[f.jsx("h2",{className:"section-title",children:"Token Health"}),f.jsxs("div",{className:"health-panel",children:[f.jsxs("div",{className:"health-row",children:[f.jsx("span",{style:{color:"var(--warning)"},children:"Expiring Soon"}),f.jsx("span",{className:"mono",children:D.expiring_soon})]}),f.jsxs("div",{className:"health-row",children:[f.jsx("span",{style:{color:"var(--error)"},children:"Error Rate"}),f.jsx("span",{className:"mono",children:D.error_rate})]})]})]})]})]})}const xr=["admin","read","sources_admin","users_admin","write"];function hy(m){const H=Math.floor((Date.now()-m.getTime())/1e3);return H<60?"just now":H<3600?`${Math.floor(H/60)}m ago`:H<86400?`${Math.floor(H/3600)}h ago`:`${Math.floor(H/86400)}d ago`}function my(){const[m,H]=ul.useState([]),[D,r]=ul.useState(!0),[O,G]=ul.useState(!1),[U,w]=ul.useState(null),[M,p]=ul.useState(!1),[R,x]=ul.useState(null),[_,F]=ul.useState(null);ul.useEffect(()=>{Z()},[]);const Z=()=>{_t.agents().then(H).catch(()=>{})};return f.jsxs(f.Fragment,{children:[f.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:24},children:[f.jsx("h1",{className:"page-title",style:{marginBottom:0},children:"Agents"}),f.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[f.jsxs("label",{style:{fontSize:13,color:"var(--text-secondary)",display:"flex",alignItems:"center",gap:6,cursor:"pointer"},children:[f.jsx("input",{type:"checkbox",checked:D,onChange:al=>r(al.target.checked)})," Hide revoked"]}),f.jsx("button",{className:"btn btn-secondary",onClick:()=>p(!0),children:"+ API Key"}),f.jsx("button",{className:"btn btn-primary",onClick:()=>G(!0),children:"+ OAuth Client"})]})]}),(()=>{const al=m.filter(ll=>!D||ll.status!=="revoked");return m.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:"No agents registered. Register your first agent to get started."}):al.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:'All agents are revoked. Uncheck "Hide revoked" to view them.'}):f.jsxs(f.Fragment,{children:[f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Name"}),f.jsx("th",{children:"Type"}),f.jsx("th",{children:"Scopes"}),f.jsx("th",{children:"Status"}),f.jsx("th",{children:"Requests"}),f.jsx("th",{children:"Last Used"})]})}),f.jsx("tbody",{children:al.map(ll=>f.jsxs("tr",{onClick:()=>F(ll),style:{cursor:"pointer"},children:[f.jsx("td",{style:{fontWeight:500},children:ll.name||ll.client_name}),f.jsx("td",{children:f.jsx("span",{className:`badge ${ll.auth_type==="oauth"?"badge-read":"badge-write"}`,style:{fontSize:11},children:ll.auth_type==="oauth"?"OAuth":"API Key"})}),f.jsx("td",{children:(ll.scope||"").split(" ").filter(Boolean).map(pl=>f.jsx("span",{className:`badge badge-${pl}`,style:{marginRight:4},children:pl},pl))}),f.jsx("td",{children:f.jsx("span",{className:`badge ${ll.status==="active"?"badge-success":"badge-danger"}`,children:ll.status})}),f.jsxs("td",{children:[f.jsx("span",{style:{fontWeight:500},children:ll.requests_today||0}),f.jsxs("span",{style:{color:"var(--text-muted)",fontSize:12},children:[" / ",ll.total_requests||0]})]}),f.jsx("td",{style:{color:"var(--text-secondary)"},children:ll.last_used_at?hy(new Date(ll.last_used_at)):"Never"})]},ll.id))})]}),f.jsxs("div",{style:{color:"var(--text-muted)",fontSize:13,marginTop:12},children:[m.filter(ll=>ll.status==="active").length," active / ",m.length," total"]})]})})(),O&&f.jsx(gy,{onClose:()=>G(!1),onRegistered:al=>{G(!1),w(al),Z()}}),U&&f.jsx(Sy,{credentials:U,onClose:()=>w(null)}),_&&f.jsx(by,{agent:_,onClose:()=>F(null),onRevoked:Z}),M&&f.jsx(yy,{onClose:()=>p(!1),onCreated:al=>{p(!1),x(al),Z()}}),R&&f.jsx(vy,{token:R,onClose:()=>x(null)})]})}function yy({onClose:m,onCreated:H}){const[D,r]=ul.useState(""),[O,G]=ul.useState(!1),[U,w]=ul.useState(""),M=async p=>{if(p.preventDefault(),!D.trim()){w("Name required");return}G(!0);try{const R=await _t.createApiKey(D.trim());H({name:R.name,token:R.token})}catch(R){w(R instanceof Error?R.message:"Failed")}finally{G(!1)}};return f.jsx("div",{className:"modal-overlay",onClick:m,children:f.jsxs("form",{className:"modal",onClick:p=>p.stopPropagation(),onSubmit:M,children:[f.jsx("div",{className:"modal-title",children:"Create API Key"}),f.jsx("p",{style:{color:"var(--text-secondary)",fontSize:13,marginBottom:16},children:"API keys use simple bearer token auth. They grant full read+write+admin access. For scoped access, use OAuth clients instead."}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Key Name"}),f.jsx("input",{placeholder:"e.g. claude-code-local",value:D,onChange:p=>r(p.target.value),autoFocus:!0})]}),U&&f.jsx("div",{style:{color:"var(--error)",fontSize:13,marginBottom:12},children:U}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end"},children:[f.jsx("button",{type:"button",className:"btn btn-secondary",onClick:m,children:"Cancel"}),f.jsx("button",{type:"submit",className:"btn btn-primary",disabled:O,children:O?"Creating...":"Create Key"})]})]})})}function vy({token:m,onClose:H}){const D=r=>navigator.clipboard.writeText(r);return f.jsx("div",{className:"modal-overlay",children:f.jsxs("div",{className:"modal",style:{maxWidth:560},children:[f.jsxs("div",{style:{textAlign:"center",marginBottom:16},children:[f.jsx("div",{style:{fontSize:36,color:"var(--success)",marginBottom:8},children:"✓"}),f.jsx("div",{style:{fontSize:20,fontWeight:600},children:"API Key Created"})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Name"}),f.jsx("div",{className:"code-block",children:f.jsx("span",{children:m.name})})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Bearer Token"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:m.token}),f.jsx("button",{className:"copy-btn",onClick:()=>D(m.token),children:"Copy"})]})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Usage"}),f.jsxs("div",{className:"code-block",children:[f.jsx("pre",{style:{whiteSpace:"pre-wrap",margin:0,fontSize:12},children:`Authorization: Bearer ${m.token}`}),f.jsx("button",{className:"copy-btn",onClick:()=>D(`Authorization: Bearer ${m.token}`),children:"Copy"})]})]}),f.jsx("div",{className:"warning-bar",children:"Save this token now. It will not be shown again."}),f.jsx("div",{style:{display:"flex",gap:12,justifyContent:"flex-end",marginTop:20},children:f.jsx("button",{className:"btn btn-primary",onClick:H,children:"Done"})})]})})}function gy({onClose:m,onRegistered:H}){const[D,r]=ul.useState(""),[O,G]=ul.useState(()=>Object.fromEntries(xr.map(Z=>[Z,Z==="read"]))),[U,w]=ul.useState("86400"),[M,p]=ul.useState(!1),[R,x]=ul.useState(""),_=[{label:"1 hour",value:"3600"},{label:"24 hours",value:"86400"},{label:"7 days",value:"604800"},{label:"30 days",value:"2592000"},{label:"1 year",value:"31536000"},{label:"No expiry",value:"0"}],F=async Z=>{if(Z.preventDefault(),!D.trim()){x("Name required");return}p(!0),x("");try{const al=Object.entries(O).filter(([,Ml])=>Ml).map(([Ml])=>Ml).join(" "),ll=await fetch("/admin/api/register-client",{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:D.trim(),scopes:al,tokenTtl:U==="0"?31536e4:Number(U)})});if(!ll.ok)throw new Error("Registration failed");const pl=await ll.json();H({clientId:pl.clientId,clientSecret:pl.clientSecret,name:D.trim()})}catch(al){x(al instanceof Error?al.message:"Registration failed")}finally{p(!1)}};return f.jsx("div",{className:"modal-overlay",onClick:m,children:f.jsxs("form",{className:"modal",onClick:Z=>Z.stopPropagation(),onSubmit:F,children:[f.jsx("div",{className:"modal-title",children:"Register Agent"}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Agent Name"}),f.jsx("input",{placeholder:"e.g. perplexity-production",value:D,onChange:Z=>r(Z.target.value),autoFocus:!0})]}),f.jsxs("div",{style:{marginBottom:16},children:[f.jsx("label",{children:"Scopes"}),f.jsx("div",{className:"checkbox-group",children:xr.map(Z=>f.jsxs("label",{className:"checkbox-label",children:[f.jsx("input",{type:"checkbox",checked:O[Z],onChange:al=>G(ll=>({...ll,[Z]:al.target.checked}))}),Z]},Z))})]}),f.jsxs("div",{style:{marginBottom:20},children:[f.jsx("label",{children:"Token Lifetime"}),f.jsx("select",{value:U,onChange:Z=>w(Z.target.value),style:{width:"100%",background:"var(--bg-secondary)",color:"var(--text-primary)",border:"1px solid var(--border)",borderRadius:6,padding:"6px 10px",fontSize:14},children:_.map(Z=>f.jsx("option",{value:Z.value,children:Z.label},Z.value))})]}),R&&f.jsx("div",{style:{color:"var(--error)",fontSize:13,marginBottom:12},children:R}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end"},children:[f.jsx("button",{type:"button",className:"btn btn-secondary",onClick:m,children:"Cancel"}),f.jsx("button",{type:"submit",className:"btn btn-primary",disabled:M,children:M?"Registering...":"Register"})]})]})})}function Sy({credentials:m,onClose:H}){const D=O=>navigator.clipboard.writeText(O),r=()=>{const O=new Blob([JSON.stringify(m,null,2)],{type:"application/json"}),G=URL.createObjectURL(O),U=document.createElement("a");U.href=G,U.download=`${m.name}-credentials.json`,U.click(),URL.revokeObjectURL(G)};return f.jsx("div",{className:"modal-overlay",children:f.jsxs("div",{className:"modal",style:{maxWidth:560},children:[f.jsxs("div",{style:{textAlign:"center",marginBottom:16},children:[f.jsx("div",{style:{fontSize:36,color:"var(--success)",marginBottom:8},children:"✓"}),f.jsx("div",{style:{fontSize:20,fontWeight:600},children:"Agent Registered"})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Client ID"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:m.clientId}),f.jsx("button",{className:"copy-btn",onClick:()=>D(m.clientId),children:"Copy"})]})]}),f.jsxs("div",{style:{marginBottom:12},children:[f.jsx("label",{style:{fontSize:12},children:"Client Secret"}),f.jsxs("div",{className:"code-block",children:[f.jsx("span",{children:m.clientSecret}),f.jsx("button",{className:"copy-btn",onClick:()=>D(m.clientSecret),children:"Copy"})]})]}),f.jsx("div",{className:"warning-bar",children:"Save this secret now. It will not be shown again."}),f.jsxs("div",{style:{display:"flex",gap:12,justifyContent:"flex-end",marginTop:20},children:[f.jsx("button",{className:"btn btn-secondary",onClick:r,children:"Download as JSON"}),f.jsx("button",{className:"btn btn-primary",onClick:H,children:"Done"})]})]})})}function by({agent:m,onClose:H,onRevoked:D}){const[r,O]=ul.useState("claude-code"),G=x=>navigator.clipboard.writeText(x),U=window.location.origin,w=m.id||m.client_id||"",M=m.auth_type==="oauth",p=m.name||m.client_name||"unknown",R={"claude-code":M?["The user wants to connect GBrain MCP to your context. Here's how.","","# Step 1 — read the client secret from the operator without putting it in shell history.","# read -s suppresses the echo; export keeps it scoped to this shell session.",'read -rs -p "Client Secret: " GBRAIN_CS && echo',"","# Step 2 — mint a token and register GBrain in one go.",`claude mcp add --transport http gbrain ${U}/mcp \\`,` --header "Authorization: Bearer $(curl -s -X POST ${U}/token \\`," -d 'grant_type=client_credentials' \\",` -d 'client_id=${w}' \\`,' --data-urlencode "client_secret=$GBRAIN_CS" \\',` -d 'scope=${m.scope||"read write"}' | jq -r .access_token)"`,"","# Step 3 — clear the secret from this shell.","unset GBRAIN_CS","",`The token will last ${m.token_ttl?m.token_ttl>=86400?Math.floor(m.token_ttl/86400)+" days":Math.floor(m.token_ttl/3600)+" hours":"1 hour (default)"}.`,"","─── Fallback: 2-step curl + paste ───","","If your shell doesn't support read -s, mint the token first, then paste:","",`curl -s -X POST ${U}/token \\`," -d 'grant_type=client_credentials' \\",` -d 'client_id=${w}' \\`," -d 'client_secret=PASTE_YOUR_CLIENT_SECRET_HERE' \\",` -d 'scope=${m.scope||"read write"}' | jq -r .access_token`,"",`claude mcp add --transport http gbrain ${U}/mcp \\`,' --header "Authorization: Bearer PASTE_TOKEN_FROM_ABOVE"',"","# Then run: history -d $((HISTCMD-1)) # zsh: print -s -- '' && fc -p"].join(` `):["The user wants to connect GBrain MCP to your context. Here's how.","","Run this command in terminal to register GBrain:","",`claude mcp add --transport http gbrain ${U}/mcp \\`,' --header "Authorization: Bearer PASTE_YOUR_API_KEY_HERE"',"",`Replace PASTE_YOUR_API_KEY_HERE with the API key shown when "${p}" was created.`,"API keys never expire."].join(` `),chatgpt:["The user wants to connect GBrain MCP to ChatGPT.","","1. Open ChatGPT > Settings > Tools & Integrations > Add MCP Server","2. Enter this URL — ChatGPT will auto-discover the OAuth configuration:","",` ${U}/.well-known/oauth-authorization-server`,"","3. When prompted for credentials:",` Client ID: ${w}`," Client Secret: (the secret from agent registration)"," Grant Type: client_credentials",` Scope: ${m.scope||"read write"}`].join(` `),"claude-cowork":["The user wants to connect GBrain MCP to Claude.ai.","","1. Open claude.ai > Settings > Connected Apps > Add MCP Server",`2. Server URL: ${U}/mcp`,"3. When prompted for auth:",` Token endpoint: ${U}/token`,` Client ID: ${w}`," Client Secret: (the secret from agent registration)",` Scope: ${m.scope||"read write"}`,"",`Discovery URL: ${U}/.well-known/oauth-authorization-server`].join(` `),cursor:M?["The user wants to connect GBrain MCP to Cursor.","","Cursor supports OAuth for remote MCP. Add to .cursor/mcp.json:","","{",' "mcpServers": {',' "gbrain": {',` "url": "${U}/mcp",`,' "transport": "sse"'," }"," }","}","","Cursor will auto-discover OAuth via:",`${U}/.well-known/oauth-authorization-server`,"",`When prompted: Client ID ${w}, use the secret from registration.`].join(` `):["The user wants to connect GBrain MCP to Cursor.","","Add to .cursor/mcp.json:","","{",' "mcpServers": {',' "gbrain": {',` "url": "${U}/mcp",`,' "transport": "sse",',' "headers": {',' "Authorization": "Bearer PASTE_YOUR_API_KEY_HERE"'," }"," }"," }","}","",`Replace PASTE_YOUR_API_KEY_HERE with the API key shown when "${p}" was created.`].join(` `),perplexity:["The user wants to connect GBrain MCP to Perplexity.","","1. Go to Settings > Connectors > Add MCP",`2. Server URL: ${U}/mcp`,`3. Client ID: ${w}`,"4. Client Secret: (the secret from agent registration)"].join(` -`),json:JSON.stringify({server_url:U+"/mcp",token_url:U+"/token",discovery_url:U+"/.well-known/oauth-authorization-server",client_id:w,client_name:p,auth_type:m.auth_type,scope:m.scope},null,2)};return f.jsxs(f.Fragment,{children:[f.jsx("div",{className:"drawer-overlay",onClick:H}),f.jsxs("div",{className:"drawer",children:[f.jsx("button",{className:"drawer-close",onClick:H,children:"✕"}),f.jsx("div",{style:{fontSize:18,fontWeight:600,marginBottom:4},children:m.name||m.client_name}),f.jsx("span",{className:`badge ${m.status==="active"?"badge-success":"badge-danger"}`,children:m.status}),f.jsx("div",{className:"section-title",children:"Details"}),f.jsxs("div",{style:{display:"grid",gridTemplateColumns:"100px 1fr",gap:"6px 12px",fontSize:13},children:[f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Client ID"}),f.jsxs("span",{className:"mono",children:[(m.id||m.id||m.client_id||"").substring(0,24),"..."]}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Scopes"}),f.jsx("span",{children:(m.scope||"").split(" ").filter(Boolean).map(_=>f.jsx("span",{className:`badge badge-${_}`,style:{marginRight:4},children:_},_))}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Registered"}),f.jsx("span",{children:new Date(m.created_at).toLocaleDateString()}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Token TTL"}),f.jsx("span",{children:m.token_ttl?m.token_ttl>=31536e3?"No expiry":m.token_ttl>=86400?`${Math.floor(m.token_ttl/86400)}d`:m.token_ttl>=3600?`${Math.floor(m.token_ttl/3600)}h`:`${m.token_ttl}s`:"1h (default)"})]}),f.jsx("div",{className:"section-title",children:"Config Export"}),f.jsxs("div",{className:"tabs",style:{flexWrap:"wrap"},children:[f.jsx("div",{className:`tab ${r==="claude-code"?"active":""}`,onClick:()=>O("claude-code"),children:"Claude Code"}),f.jsx("div",{className:`tab ${r==="chatgpt"?"active":""}`,onClick:()=>O("chatgpt"),children:"ChatGPT"}),f.jsx("div",{className:`tab ${r==="claude-cowork"?"active":""}`,onClick:()=>O("claude-cowork"),children:"Claude.ai"}),f.jsx("div",{className:`tab ${r==="cursor"?"active":""}`,onClick:()=>O("cursor"),children:"Cursor"}),f.jsx("div",{className:`tab ${r==="perplexity"?"active":""}`,onClick:()=>O("perplexity"),children:"Perplexity"}),f.jsx("div",{className:`tab ${r==="json"?"active":""}`,onClick:()=>O("json"),children:"JSON"})]}),(()=>{if(!M&&new Set(["chatgpt","claude-cowork","perplexity"]).has(r)){const x={chatgpt:"ChatGPT","claude-cowork":"Claude.ai",perplexity:"Perplexity"}[r]||r;return f.jsxs("div",{style:{background:"rgba(255, 200, 100, 0.08)",border:"1px solid rgba(255, 200, 100, 0.2)",borderRadius:8,padding:"14px 16px",marginTop:12,fontSize:13,lineHeight:1.6,color:"var(--text-secondary)"},children:[f.jsxs("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:6},children:[x," requires an OAuth client"]}),x," only supports OAuth 2.0 (client_credentials). API keys use raw bearer tokens, which ",x," does not accept. Register a separate OAuth client and use that to connect this AI."]})}return f.jsxs("div",{className:"code-block",children:[f.jsx("pre",{style:{whiteSpace:"pre-wrap",margin:0},children:R[r]}),f.jsx("button",{className:"copy-btn",onClick:()=>G(R[r]),children:"Copy"})]})})(),f.jsxs("div",{style:{marginTop:32},children:[m.status==="active"&&f.jsx("button",{className:"btn btn-danger",onClick:async()=>{if(confirm(`Revoke ${m.name||m.client_name}? All active tokens will be invalidated.`))try{m.auth_type==="oauth"?await xt.revokeClient(m.id||m.client_id||""):await xt.revokeApiKey(m.name||""),D(),H()}catch(_){alert("Revoke failed: "+(_ instanceof Error?_.message:"unknown error"))}},children:"Revoke Agent"}),m.status==="revoked"&&f.jsx("span",{style:{color:"var(--text-muted)",fontSize:13},children:"This agent has been revoked."})]})]})]})}function by(){const[m,H]=ul.useState({rows:[],total:0,page:1,pages:1}),[D,r]=ul.useState(1),[O,G]=ul.useState("all"),[U,w]=ul.useState(null);ul.useEffect(()=>{M(D)},[D,O]);const M=x=>{const F=O!=="all"?`&agent=${encodeURIComponent(O)}`:"";xt.requests(x,F).then(H).catch(()=>{})},p=x=>{const F=Date.now()-new Date(x).getTime();return F<6e4?`${Math.floor(F/1e3)}s ago`:F<36e5?`${Math.floor(F/6e4)} min ago`:F<864e5?`${Math.floor(F/36e5)}h ago`:new Date(x).toLocaleDateString()},R=x=>{if(!x)return null;const{query:F,slug:K,partial:al,limit:ll,...pl}=x,Ml=[];return F&&Ml.push(`"${F}"`),K&&Ml.push(K),al&&Ml.push(`~${al}`),ll&&Ml.push(`limit=${ll}`),Object.keys(pl).length>0&&Ml.push(`+${Object.keys(pl).length} params`),Ml.join(" ")},_=new Map;return m.rows.forEach(x=>{x.token_name&&_.set(x.token_name,x.agent_name||x.token_name)}),f.jsxs(f.Fragment,{children:[f.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:24},children:[f.jsx("h1",{className:"page-title",style:{marginBottom:0},children:"Request Log"}),f.jsxs("select",{value:O,onChange:x=>{G(x.target.value),r(1)},style:{background:"var(--bg-secondary)",color:"var(--text-primary)",border:"1px solid var(--border)",borderRadius:6,padding:"4px 8px",fontSize:13},children:[f.jsx("option",{value:"all",children:"All agents"}),[..._.entries()].map(([x,F])=>f.jsx("option",{value:x,children:F},x))]})]}),m.rows.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:"No requests yet."}):f.jsxs(f.Fragment,{children:[f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Time"}),f.jsx("th",{children:"Agent"}),f.jsx("th",{children:"Operation"}),f.jsx("th",{children:"Params"}),f.jsx("th",{children:"Latency"}),f.jsx("th",{children:"Status"})]})}),f.jsx("tbody",{children:m.rows.map(x=>f.jsxs(Or.Fragment,{children:[f.jsxs("tr",{onClick:()=>w(U===x.id?null:x.id),style:{cursor:"pointer"},children:[f.jsx("td",{style:{color:"var(--text-secondary)",whiteSpace:"nowrap"},children:p(x.created_at)}),f.jsx("td",{children:f.jsx("a",{style:{color:"var(--text-link, #88aaff)",cursor:"pointer",textDecoration:"none",fontWeight:500},onClick:F=>{F.stopPropagation(),G(x.token_name),r(1)},children:x.agent_name||x.token_name})}),f.jsx("td",{className:"mono",children:x.operation}),f.jsx("td",{style:{color:"var(--text-secondary)",fontSize:12,maxWidth:200,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:R(x.params)}),f.jsxs("td",{className:"mono",children:[x.latency_ms,"ms"]}),f.jsx("td",{children:f.jsx("span",{className:`badge badge-${x.status}`,children:x.status})})]}),U===x.id&&f.jsx("tr",{children:f.jsx("td",{colSpan:6,style:{background:"var(--bg-secondary, #0f0f1a)",padding:16},children:f.jsxs("div",{style:{display:"grid",gridTemplateColumns:"100px 1fr",gap:"6px 12px",fontSize:13},children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"Time"}),f.jsx("span",{children:new Date(x.created_at).toLocaleString()}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Agent"}),f.jsx("span",{className:"mono",children:x.token_name}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Operation"}),f.jsx("span",{className:"mono",children:x.operation}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Latency"}),f.jsxs("span",{children:[x.latency_ms,"ms"]}),x.params&&f.jsxs(f.Fragment,{children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"Params"}),f.jsx("pre",{className:"mono",style:{margin:0,whiteSpace:"pre-wrap",fontSize:12},children:JSON.stringify(x.params,null,2)})]}),x.error_message&&f.jsxs(f.Fragment,{children:[f.jsx("span",{style:{color:"var(--error, #ff6b6b)"},children:"Error"}),f.jsx("span",{style:{color:"var(--error, #ff6b6b)"},children:x.error_message})]})]})})})]},x.id))})]}),f.jsxs("div",{className:"pagination",children:[f.jsxs("span",{children:["Page ",m.page," of ",m.pages," (",m.total," total)"]}),f.jsxs("div",{style:{display:"flex",gap:8},children:[f.jsx("button",{disabled:m.page<=1,onClick:()=>r(x=>x-1),children:"Previous"}),f.jsx("button",{disabled:m.page>=m.pages,onClick:()=>r(x=>x+1),children:"Next"})]})]})]})]})}function _r(){const m=window.location.hash.replace("#","")||"dashboard";return["login","dashboard","agents","log"].includes(m)?m:"dashboard"}function py(){const[m,H]=ul.useState(_r);ul.useEffect(()=>{const O=()=>H(_r());return window.addEventListener("hashchange",O),()=>window.removeEventListener("hashchange",O)},[]);const D=O=>{window.location.hash=O,H(O)};if(m==="login")return f.jsx(oy,{onLogin:()=>D("dashboard")});const r=async()=>{if(confirm("Sign out every active admin session, including other browsers and tabs? Each one will need to re-authenticate via a fresh magic link.")){try{await xt.signOutEverywhere()}catch{}D("login")}};return f.jsxs("div",{className:"app",children:[f.jsxs("nav",{className:"sidebar",children:[f.jsx("div",{className:"sidebar-logo",children:"GBrain"}),f.jsxs("div",{className:"sidebar-nav",children:[f.jsx("a",{className:`nav-item ${m==="dashboard"?"active":""}`,onClick:()=>D("dashboard"),children:"Dashboard"}),f.jsx("a",{className:`nav-item ${m==="agents"?"active":""}`,onClick:()=>D("agents"),children:"Agents"}),f.jsx("a",{className:`nav-item ${m==="log"?"active":""}`,onClick:()=>D("log"),children:"Request Log"})]}),f.jsx("div",{style:{marginTop:"auto",padding:"16px 12px",borderTop:"1px solid var(--border)"},children:f.jsx("button",{onClick:r,style:{background:"transparent",border:"1px solid var(--border)",color:"var(--text-secondary)",padding:"6px 10px",borderRadius:6,fontSize:12,cursor:"pointer",width:"100%"},title:"Revoke every active admin session — every browser, every tab",children:"Sign out everywhere"})})]}),f.jsxs("main",{className:"main",children:[m==="dashboard"&&f.jsx(dy,{}),m==="agents"&&f.jsx(hy,{}),m==="log"&&f.jsx(by,{})]})]})}fy.createRoot(document.getElementById("root")).render(f.jsx(Or.StrictMode,{children:f.jsx(py,{})})); +`),json:JSON.stringify({server_url:U+"/mcp",token_url:U+"/token",discovery_url:U+"/.well-known/oauth-authorization-server",client_id:w,client_name:p,auth_type:m.auth_type,scope:m.scope},null,2)};return f.jsxs(f.Fragment,{children:[f.jsx("div",{className:"drawer-overlay",onClick:H}),f.jsxs("div",{className:"drawer",children:[f.jsx("button",{className:"drawer-close",onClick:H,children:"✕"}),f.jsx("div",{style:{fontSize:18,fontWeight:600,marginBottom:4},children:m.name||m.client_name}),f.jsx("span",{className:`badge ${m.status==="active"?"badge-success":"badge-danger"}`,children:m.status}),f.jsx("div",{className:"section-title",children:"Details"}),f.jsxs("div",{style:{display:"grid",gridTemplateColumns:"100px 1fr",gap:"6px 12px",fontSize:13},children:[f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Client ID"}),f.jsxs("span",{className:"mono",children:[(m.id||m.id||m.client_id||"").substring(0,24),"..."]}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Scopes"}),f.jsx("span",{children:(m.scope||"").split(" ").filter(Boolean).map(x=>f.jsx("span",{className:`badge badge-${x}`,style:{marginRight:4},children:x},x))}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Registered"}),f.jsx("span",{children:new Date(m.created_at).toLocaleDateString()}),f.jsx("span",{style:{color:"var(--text-secondary)"},children:"Token TTL"}),f.jsx("span",{children:m.token_ttl?m.token_ttl>=31536e3?"No expiry":m.token_ttl>=86400?`${Math.floor(m.token_ttl/86400)}d`:m.token_ttl>=3600?`${Math.floor(m.token_ttl/3600)}h`:`${m.token_ttl}s`:"1h (default)"})]}),f.jsx("div",{className:"section-title",children:"Config Export"}),f.jsxs("div",{className:"tabs",style:{flexWrap:"wrap"},children:[f.jsx("div",{className:`tab ${r==="claude-code"?"active":""}`,onClick:()=>O("claude-code"),children:"Claude Code"}),f.jsx("div",{className:`tab ${r==="chatgpt"?"active":""}`,onClick:()=>O("chatgpt"),children:"ChatGPT"}),f.jsx("div",{className:`tab ${r==="claude-cowork"?"active":""}`,onClick:()=>O("claude-cowork"),children:"Claude.ai"}),f.jsx("div",{className:`tab ${r==="cursor"?"active":""}`,onClick:()=>O("cursor"),children:"Cursor"}),f.jsx("div",{className:`tab ${r==="perplexity"?"active":""}`,onClick:()=>O("perplexity"),children:"Perplexity"}),f.jsx("div",{className:`tab ${r==="json"?"active":""}`,onClick:()=>O("json"),children:"JSON"})]}),(()=>{if(!M&&new Set(["chatgpt","claude-cowork","perplexity"]).has(r)){const _={chatgpt:"ChatGPT","claude-cowork":"Claude.ai",perplexity:"Perplexity"}[r]||r;return f.jsxs("div",{style:{background:"rgba(255, 200, 100, 0.08)",border:"1px solid rgba(255, 200, 100, 0.2)",borderRadius:8,padding:"14px 16px",marginTop:12,fontSize:13,lineHeight:1.6,color:"var(--text-secondary)"},children:[f.jsxs("div",{style:{fontWeight:600,color:"var(--text-primary)",marginBottom:6},children:[_," requires an OAuth client"]}),_," only supports OAuth 2.0 (client_credentials). API keys use raw bearer tokens, which ",_," does not accept. Register a separate OAuth client and use that to connect this AI."]})}return f.jsxs("div",{className:"code-block",children:[f.jsx("pre",{style:{whiteSpace:"pre-wrap",margin:0},children:R[r]}),f.jsx("button",{className:"copy-btn",onClick:()=>G(R[r]),children:"Copy"})]})})(),f.jsxs("div",{style:{marginTop:32},children:[m.status==="active"&&f.jsx("button",{className:"btn btn-danger",onClick:async()=>{if(confirm(`Revoke ${m.name||m.client_name}? All active tokens will be invalidated.`))try{m.auth_type==="oauth"?await _t.revokeClient(m.id||m.client_id||""):await _t.revokeApiKey(m.name||""),D(),H()}catch(x){alert("Revoke failed: "+(x instanceof Error?x.message:"unknown error"))}},children:"Revoke Agent"}),m.status==="revoked"&&f.jsx("span",{style:{color:"var(--text-muted)",fontSize:13},children:"This agent has been revoked."})]})]})]})}function py(){const[m,H]=ul.useState({rows:[],total:0,page:1,pages:1}),[D,r]=ul.useState(1),[O,G]=ul.useState("all"),[U,w]=ul.useState(null);ul.useEffect(()=>{M(D)},[D,O]);const M=_=>{const F=O!=="all"?`&agent=${encodeURIComponent(O)}`:"";_t.requests(_,F).then(H).catch(()=>{})},p=_=>{const F=Date.now()-new Date(_).getTime();return F<6e4?`${Math.floor(F/1e3)}s ago`:F<36e5?`${Math.floor(F/6e4)} min ago`:F<864e5?`${Math.floor(F/36e5)}h ago`:new Date(_).toLocaleDateString()},R=_=>{if(!_)return null;const{query:F,slug:Z,partial:al,limit:ll,...pl}=_,Ml=[];return F&&Ml.push(`"${F}"`),Z&&Ml.push(Z),al&&Ml.push(`~${al}`),ll&&Ml.push(`limit=${ll}`),Object.keys(pl).length>0&&Ml.push(`+${Object.keys(pl).length} params`),Ml.join(" ")},x=new Map;return m.rows.forEach(_=>{_.token_name&&x.set(_.token_name,_.agent_name||_.token_name)}),f.jsxs(f.Fragment,{children:[f.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:24},children:[f.jsx("h1",{className:"page-title",style:{marginBottom:0},children:"Request Log"}),f.jsxs("select",{value:O,onChange:_=>{G(_.target.value),r(1)},style:{background:"var(--bg-secondary)",color:"var(--text-primary)",border:"1px solid var(--border)",borderRadius:6,padding:"4px 8px",fontSize:13},children:[f.jsx("option",{value:"all",children:"All agents"}),[...x.entries()].map(([_,F])=>f.jsx("option",{value:_,children:F},_))]})]}),m.rows.length===0?f.jsx("div",{style:{textAlign:"center",padding:48,color:"var(--text-muted)"},children:"No requests yet."}):f.jsxs(f.Fragment,{children:[f.jsxs("table",{children:[f.jsx("thead",{children:f.jsxs("tr",{children:[f.jsx("th",{children:"Time"}),f.jsx("th",{children:"Agent"}),f.jsx("th",{children:"Operation"}),f.jsx("th",{children:"Params"}),f.jsx("th",{children:"Latency"}),f.jsx("th",{children:"Status"})]})}),f.jsx("tbody",{children:m.rows.map(_=>f.jsxs(Nr.Fragment,{children:[f.jsxs("tr",{onClick:()=>w(U===_.id?null:_.id),style:{cursor:"pointer"},children:[f.jsx("td",{style:{color:"var(--text-secondary)",whiteSpace:"nowrap"},children:p(_.created_at)}),f.jsx("td",{children:f.jsx("a",{style:{color:"var(--text-link, #88aaff)",cursor:"pointer",textDecoration:"none",fontWeight:500},onClick:F=>{F.stopPropagation(),G(_.token_name),r(1)},children:_.agent_name||_.token_name})}),f.jsx("td",{className:"mono",children:_.operation}),f.jsx("td",{style:{color:"var(--text-secondary)",fontSize:12,maxWidth:200,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:R(_.params)}),f.jsxs("td",{className:"mono",children:[_.latency_ms,"ms"]}),f.jsx("td",{children:f.jsx("span",{className:`badge badge-${_.status}`,children:_.status})})]}),U===_.id&&f.jsx("tr",{children:f.jsx("td",{colSpan:6,style:{background:"var(--bg-secondary, #0f0f1a)",padding:16},children:f.jsxs("div",{style:{display:"grid",gridTemplateColumns:"100px 1fr",gap:"6px 12px",fontSize:13},children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"Time"}),f.jsx("span",{children:new Date(_.created_at).toLocaleString()}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Agent"}),f.jsx("span",{className:"mono",children:_.token_name}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Operation"}),f.jsx("span",{className:"mono",children:_.operation}),f.jsx("span",{style:{color:"var(--text-muted)"},children:"Latency"}),f.jsxs("span",{children:[_.latency_ms,"ms"]}),_.params&&f.jsxs(f.Fragment,{children:[f.jsx("span",{style:{color:"var(--text-muted)"},children:"Params"}),f.jsx("pre",{className:"mono",style:{margin:0,whiteSpace:"pre-wrap",fontSize:12},children:JSON.stringify(_.params,null,2)})]}),_.error_message&&f.jsxs(f.Fragment,{children:[f.jsx("span",{style:{color:"var(--error, #ff6b6b)"},children:"Error"}),f.jsx("span",{style:{color:"var(--error, #ff6b6b)"},children:_.error_message})]})]})})})]},_.id))})]}),f.jsxs("div",{className:"pagination",children:[f.jsxs("span",{children:["Page ",m.page," of ",m.pages," (",m.total," total)"]}),f.jsxs("div",{style:{display:"flex",gap:8},children:[f.jsx("button",{disabled:m.page<=1,onClick:()=>r(_=>_-1),children:"Previous"}),f.jsx("button",{disabled:m.page>=m.pages,onClick:()=>r(_=>_+1),children:"Next"})]})]})]})]})}function jr(){const m=window.location.hash.replace("#","")||"dashboard";return["login","dashboard","agents","log"].includes(m)?m:"dashboard"}function Ty(){const[m,H]=ul.useState(jr);ul.useEffect(()=>{const O=()=>H(jr());return window.addEventListener("hashchange",O),()=>window.removeEventListener("hashchange",O)},[]);const D=O=>{window.location.hash=O,H(O)};if(m==="login")return f.jsx(dy,{onLogin:()=>D("dashboard")});const r=async()=>{if(confirm("Sign out every active admin session, including other browsers and tabs? Each one will need to re-authenticate via a fresh magic link.")){try{await _t.signOutEverywhere()}catch{}D("login")}};return f.jsxs("div",{className:"app",children:[f.jsxs("nav",{className:"sidebar",children:[f.jsx("div",{className:"sidebar-logo",children:"GBrain"}),f.jsxs("div",{className:"sidebar-nav",children:[f.jsx("a",{className:`nav-item ${m==="dashboard"?"active":""}`,onClick:()=>D("dashboard"),children:"Dashboard"}),f.jsx("a",{className:`nav-item ${m==="agents"?"active":""}`,onClick:()=>D("agents"),children:"Agents"}),f.jsx("a",{className:`nav-item ${m==="log"?"active":""}`,onClick:()=>D("log"),children:"Request Log"})]}),f.jsx("div",{style:{marginTop:"auto",padding:"16px 12px",borderTop:"1px solid var(--border)"},children:f.jsx("button",{onClick:r,style:{background:"transparent",border:"1px solid var(--border)",color:"var(--text-secondary)",padding:"6px 10px",borderRadius:6,fontSize:12,cursor:"pointer",width:"100%"},title:"Revoke every active admin session — every browser, every tab",children:"Sign out everywhere"})})]}),f.jsxs("main",{className:"main",children:[m==="dashboard"&&f.jsx(ry,{}),m==="agents"&&f.jsx(my,{}),m==="log"&&f.jsx(py,{})]})]})}sy.createRoot(document.getElementById("root")).render(f.jsx(Nr.StrictMode,{children:f.jsx(Ty,{})})); diff --git a/admin/dist/index.html b/admin/dist/index.html index d2b3403c7..2dd8be830 100644 --- a/admin/dist/index.html +++ b/admin/dist/index.html @@ -7,7 +7,7 @@ - + diff --git a/admin/src/lib/scope-constants.ts b/admin/src/lib/scope-constants.ts new file mode 100644 index 000000000..3399bfb56 --- /dev/null +++ b/admin/src/lib/scope-constants.ts @@ -0,0 +1,22 @@ +/** + * Admin SPA scope constants — HAND-MAINTAINED MIRROR of src/core/scope.ts. + * + * The admin tsconfig.json scopes `include: ['src']` to admin/src/, so we + * cannot directly import from ../../src/core/scope.ts without breaking the + * SPA's compile boundary. Instead, this file is a hand-maintained duplicate; + * scripts/check-admin-scope-drift.sh fails the build if the two lists drift. + * + * If you change ALLOWED_SCOPES in src/core/scope.ts, update this file too, + * or `bun run verify` will reject the change. + */ + +export type Scope = 'read' | 'write' | 'admin' | 'sources_admin' | 'users_admin'; + +// MIRROR OF src/core/scope.ts ALLOWED_SCOPES_LIST — keep alphabetically sorted. +export const ALLOWED_SCOPES_LIST: ReadonlyArray = [ + 'admin', + 'read', + 'sources_admin', + 'users_admin', + 'write', +]; diff --git a/admin/src/pages/Agents.tsx b/admin/src/pages/Agents.tsx index ca0edf12c..c0680006c 100644 --- a/admin/src/pages/Agents.tsx +++ b/admin/src/pages/Agents.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import { api } from '../api'; +import { ALLOWED_SCOPES_LIST, type Scope } from '../lib/scope-constants'; function timeAgo(date: Date): string { const s = Math.floor((Date.now() - date.getTime()) / 1000); @@ -249,7 +250,12 @@ function RegisterModal({ onClose, onRegistered }: { onRegistered: (creds: { clientId: string; clientSecret: string; name: string }) => void; }) { const [name, setName] = useState(''); - const [scopes, setScopes] = useState({ read: true, write: false, admin: false }); + // v0.28: scope set sourced from admin/src/lib/scope-constants.ts (mirror + // of src/core/scope.ts). CI drift check at scripts/check-admin-scope-drift.sh + // fails the build if these diverge. + const [scopes, setScopes] = useState>(() => + Object.fromEntries(ALLOWED_SCOPES_LIST.map(s => [s, s === 'read'])) as Record, + ); const [ttl, setTtl] = useState('86400'); // 24h default const [loading, setLoading] = useState(false); const [error, setError] = useState(''); @@ -298,7 +304,7 @@ function RegisterModal({ onClose, onRegistered }: {
- {(['read', 'write', 'admin'] as const).map(s => ( + {ALLOWED_SCOPES_LIST.map(s => (